mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-21 23:35:22 +03:00
Fixed dimension reporting.
This commit is contained in:
parent
8d5d81f9cf
commit
a72c436e8e
12 changed files with 251 additions and 151 deletions
|
@ -1,9 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
var Analytics = function (serviceName, trackingId, operatingSystem) {
|
||||
this.eventBuilder = analytics.EventBuilder;
|
||||
this.service = analytics.getService(serviceName);
|
||||
this.tracker = this.service.getTracker(trackingId);
|
||||
var Analytics = function (trackingId, userId, appName, appVersion, buildType, optOut, debugMode) {
|
||||
this._trackingId = trackingId;
|
||||
|
||||
this.setOptOut(optOut);
|
||||
|
||||
this._analytics = analytics;
|
||||
|
||||
this._analytics.initialize(this._trackingId, {
|
||||
storage: 'none',
|
||||
clientId: userId,
|
||||
debug: !!debugMode
|
||||
});
|
||||
|
||||
// Make it work for the Chrome App:
|
||||
this._analytics.set('forceSSL', true);
|
||||
this._analytics.set('transport', 'xhr');
|
||||
|
||||
// Make it work for NW.js:
|
||||
this._analytics.set('checkProtocolTask', null);
|
||||
|
||||
this._analytics.set('appName', appName);
|
||||
this._analytics.set('appVersion', debugMode ? appVersion + '-debug' : appVersion);
|
||||
|
||||
this.EVENT_CATEGORIES = {
|
||||
APPLICATION: 'Application',
|
||||
FLIGHT_CONTROLLER: 'FlightController',
|
||||
};
|
||||
|
||||
this.DATA = {
|
||||
BOARD_TYPE: 'boardType',
|
||||
|
@ -14,51 +37,71 @@ var Analytics = function (serviceName, trackingId, operatingSystem) {
|
|||
};
|
||||
|
||||
this.DIMENSIONS = {
|
||||
OS: 1,
|
||||
BUILD_TYPE: 1,
|
||||
BOARD_TYPE: 2,
|
||||
FIRMWARE_TYPE: 3,
|
||||
FIRMWARE_VERSION: 4,
|
||||
API_VERSION: 5,
|
||||
};
|
||||
|
||||
this.APPLICATION_EVENT = this.eventBuilder.builder()
|
||||
.category('Application')
|
||||
.dimension(this.DIMENSIONS.OS, operatingSystem);
|
||||
this.setDimension(this.DIMENSIONS.BUILD_TYPE, buildType);
|
||||
|
||||
this.resetFlightControllerData();
|
||||
};
|
||||
|
||||
Analytics.prototype.setTrackingPermitted = function (permitted) {
|
||||
this.service.getConfig().addCallback(function(config) {
|
||||
config.setTrackingPermitted(permitted);
|
||||
});
|
||||
Analytics.prototype.setDimension = function (dimension, value) {
|
||||
var dimensionName = 'dimension' + dimension;
|
||||
this._analytics.custom(dimensionName, value);
|
||||
}
|
||||
|
||||
Analytics.prototype.send = function (event) {
|
||||
this.tracker.send(event);
|
||||
Analytics.prototype.sendEvent = function (category, action, options) {
|
||||
options = options || {};
|
||||
options.eventLabel = options.eventLabel || this.flightControllerData[this.DATA.MCU_ID];
|
||||
this._analytics.event(category, action, options);
|
||||
}
|
||||
|
||||
Analytics.prototype.sendChangeEvents = function (category, changeList) {
|
||||
for (var actionName in changeList) {
|
||||
if (changeList.hasOwnProperty(actionName)) {
|
||||
var actionValue = changeList[actionName];
|
||||
if (actionValue !== undefined) {
|
||||
this.sendEvent(category, actionName, { eventLabel: actionValue });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Analytics.prototype.sendAppView = function (viewName) {
|
||||
this.tracker.sendAppView(viewName);
|
||||
this._analytics.screenview(viewName);
|
||||
}
|
||||
|
||||
Analytics.prototype.rebuildFlightControllerEvent = function () {
|
||||
this.FLIGHT_CONTROLLER_EVENT = this.eventBuilder.builder()
|
||||
.category('FlightController')
|
||||
.dimension(this.DIMENSIONS.BOARD_TYPE, this.flightControllerData[this.DATA.BOARD_TYPE])
|
||||
.dimension(this.DIMENSIONS.FIRMWARE_TYPE, this.flightControllerData[this.DATA.FIRMWARE_TYPE])
|
||||
.dimension(this.DIMENSIONS.FIRMWARE_VERSION, this.flightControllerData[this.DATA.FIRMWARE_VERSION])
|
||||
.dimension(this.DIMENSIONS.API_VERSION, this.flightControllerData[this.DATA.API_VERSION]);
|
||||
Analytics.prototype.sendTiming = function (category, timing, value) {
|
||||
this._analytics.timing(category, timing, value);
|
||||
}
|
||||
|
||||
Analytics.prototype.sendException = function (message) {
|
||||
this._analytics.exception(message);
|
||||
}
|
||||
|
||||
Analytics.prototype.setOptOut = function (optOut) {
|
||||
window['ga-disable-' + this._trackingId] = !!optOut;
|
||||
}
|
||||
|
||||
Analytics.prototype._rebuildFlightControllerEvent = function () {
|
||||
this.setDimension(this.DIMENSIONS.BOARD_TYPE, this.flightControllerData[this.DATA.BOARD_TYPE]);
|
||||
this.setDimension(this.DIMENSIONS.FIRMWARE_TYPE, this.flightControllerData[this.DATA.FIRMWARE_TYPE]);
|
||||
this.setDimension(this.DIMENSIONS.FIRMWARE_VERSION, this.flightControllerData[this.DATA.FIRMWARE_VERSION]);
|
||||
this.setDimension(this.DIMENSIONS.API_VERSION, this.flightControllerData[this.DATA.API_VERSION]);
|
||||
}
|
||||
|
||||
Analytics.prototype.setFlightControllerData = function (property, value) {
|
||||
this.flightControllerData[property] = value;
|
||||
|
||||
this.rebuildFlightControllerEvent();
|
||||
this._rebuildFlightControllerEvent();
|
||||
}
|
||||
|
||||
Analytics.prototype.resetFlightControllerData = function () {
|
||||
this.flightControllerData = {};
|
||||
|
||||
this.rebuildFlightControllerEvent();
|
||||
this._rebuildFlightControllerEvent();
|
||||
}
|
||||
|
|
|
@ -99,11 +99,16 @@ var Features = function (config) {
|
|||
|
||||
self._features = features;
|
||||
self._featureMask = 0;
|
||||
|
||||
self._analyticsChanges = {};
|
||||
};
|
||||
|
||||
Features.prototype.getMask = function () {
|
||||
var self = this;
|
||||
|
||||
analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self._analyticsChanges);
|
||||
self._analyticsChanges = {};
|
||||
|
||||
return self._featureMask;
|
||||
};
|
||||
|
||||
|
@ -127,6 +132,8 @@ Features.prototype.isEnabled = function (featureName) {
|
|||
Features.prototype.generateElements = function (featuresElements) {
|
||||
var self = this;
|
||||
|
||||
self._featureChanges = {};
|
||||
|
||||
var listElements = [];
|
||||
|
||||
for (var i = 0; i < self._features.length; i++) {
|
||||
|
@ -191,29 +198,48 @@ Features.prototype.generateElements = function (featuresElements) {
|
|||
}
|
||||
};
|
||||
|
||||
Features.prototype.findFeatureByBit = function (bit) {
|
||||
var self = this;
|
||||
|
||||
for (var i = 0; i < self._features.length; i++) {
|
||||
if (self._features[i].bit == bit) {
|
||||
return self._features[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Features.prototype.updateData = function (featureElement) {
|
||||
var self = this;
|
||||
|
||||
if (featureElement.attr('type') === 'checkbox') {
|
||||
var bit = featureElement.data('bit');
|
||||
|
||||
var featureValue;
|
||||
if (featureElement.is(':checked')) {
|
||||
self._featureMask = bit_set(self._featureMask, bit);
|
||||
featureValue = 'On';
|
||||
} else {
|
||||
self._featureMask = bit_clear(self._featureMask, bit);
|
||||
featureValue = 'Off';
|
||||
}
|
||||
self._analyticsChanges['Feature' + self.findFeatureByBit(bit).name] = featureValue;
|
||||
} else if (featureElement.prop('localName') === 'select') {
|
||||
var controlElements = featureElement.children();
|
||||
var selectedBit = featureElement.val();
|
||||
if (selectedBit !== -1) {
|
||||
var featureName;
|
||||
for (var i = 0; i < controlElements.length; i++) {
|
||||
var bit = controlElements[i].value;
|
||||
if (selectedBit === bit) {
|
||||
self._featureMask = bit_set(self._featureMask, bit);
|
||||
featureName = self.findFeatureByBit(bit).name;
|
||||
} else {
|
||||
self._featureMask = bit_clear(self._featureMask, bit);
|
||||
}
|
||||
}
|
||||
if (featureName) {
|
||||
self._analyticsChanges['Feature' + featureName] = 'On';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,8 +4,8 @@ var analytics;
|
|||
|
||||
openNewWindowsInExternalBrowser();
|
||||
|
||||
//Asynchronous configuration to be done.
|
||||
//When finish the startProcess() function must be called
|
||||
// Asynchronous configuration to be done.
|
||||
// When finish the startProcess() function must be called
|
||||
$(document).ready(function () {
|
||||
i18n.init(function() {
|
||||
setupAnalytics();
|
||||
|
@ -14,8 +14,7 @@ $(document).ready(function () {
|
|||
});
|
||||
|
||||
function setupAnalytics() {
|
||||
analytics = new Analytics('com.betaflight.configurator', 'UA-123002063-1', GUI.operating_system);
|
||||
chrome.storage.local.get('userId', function (result) {
|
||||
chrome.storage.local.get(['userId', 'analyticsOptOut'], function (result) {
|
||||
var userId;
|
||||
if (result.userId) {
|
||||
userId = result.userId;
|
||||
|
@ -23,17 +22,25 @@ function setupAnalytics() {
|
|||
var uid = new ShortUniqueId();
|
||||
userId = uid.randomUUID(13);
|
||||
|
||||
chrome.storage.local.set({'userId': userId});
|
||||
chrome.storage.local.set({ 'userId': userId });
|
||||
}
|
||||
|
||||
analytics.tracker.set('userId', userId);
|
||||
var optOut = !!result.analyticsOptOut
|
||||
|
||||
analytics.tracker.set('sessionControl', 'start');
|
||||
analytics.send(analytics.APPLICATION_EVENT.action('AppStart'))
|
||||
var debugMode = process.versions['nw-flavor'] === 'sdk';
|
||||
|
||||
analytics = new Analytics('UA-123002063-1', userId, 'Betaflight Configurator', getManifestVersion(), GUI.operating_system, optOut, debugMode);
|
||||
|
||||
function logException(exception) {
|
||||
analytics.sendException(exception.stack);
|
||||
}
|
||||
|
||||
process.on('uncaughtException', logException);
|
||||
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppStart', { sessionControl: 'start' });
|
||||
|
||||
function sendCloseEvent() {
|
||||
analytics.send(analytics.APPLICATION_EVENT.action('AppClose'))
|
||||
analytics.tracker.set('sessionControl', 'end');
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' })
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -303,13 +310,13 @@ function startProcess() {
|
|||
chrome.storage.local.set({'analyticsOptOut': checked});
|
||||
|
||||
if (checked) {
|
||||
analytics.send(analytics.APPLICATION_EVENT.action('OptOut'));
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'OptOut');
|
||||
}
|
||||
|
||||
analytics.setTrackingPermitted(!checked);
|
||||
analytics.setOptOut(checked);
|
||||
|
||||
if (!checked) {
|
||||
analytics.send(analytics.APPLICATION_EVENT.action('OptIn'));
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'OptIn');
|
||||
}
|
||||
}).change();
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
var mspHelper;
|
||||
|
||||
var analyticsTimer;
|
||||
var connectionTimestamp;
|
||||
|
||||
function initializeSerialBackend() {
|
||||
|
||||
|
@ -126,11 +126,12 @@ function initializeSerialBackend() {
|
|||
function finishClose(finishedCallback) {
|
||||
var wasConnected = CONFIGURATOR.connectionValid;
|
||||
|
||||
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('Disconnected'));
|
||||
if (analyticsTimer) {
|
||||
analyticsTimer.send();
|
||||
|
||||
analyticsTimer = undefined;
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Disconnected');
|
||||
if (connectionTimestamp) {
|
||||
var connectedTime = Date.now() - connectionTimestamp;
|
||||
analytics.sendTiming(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Connected', connectedTime);
|
||||
|
||||
connectedTime = undefined;
|
||||
}
|
||||
analytics.resetFlightControllerData();
|
||||
|
||||
|
@ -241,8 +242,8 @@ function onOpen(openInfo) {
|
|||
var uniqueDeviceIdentifier = CONFIG.uid[0].toString(16) + CONFIG.uid[1].toString(16) + CONFIG.uid[2].toString(16);
|
||||
|
||||
analytics.setFlightControllerData(analytics.DATA.MCU_ID, objectHash.sha1(uniqueDeviceIdentifier));
|
||||
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('Connected'));
|
||||
analyticsTimer = analytics.tracker.startTiming('FlightController', 'Connected');
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Connected');
|
||||
connectionTimestamp = Date.now();
|
||||
GUI.log(i18n.getMessage('uniqueDeviceIdReceived', [uniqueDeviceIdentifier]));
|
||||
|
||||
if (semver.gte(CONFIG.apiVersion, "1.20.0")) {
|
||||
|
@ -260,7 +261,7 @@ function onOpen(openInfo) {
|
|||
});
|
||||
});
|
||||
} else {
|
||||
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('ConnectionRefused'));
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'ConnectionRefused');
|
||||
|
||||
var dialog = $('.dialogConnectWarning')[0];
|
||||
|
||||
|
@ -276,7 +277,7 @@ function onOpen(openInfo) {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('ConnectionRefused'));
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'ConnectionRefused');
|
||||
|
||||
var dialog = $('.dialogConnectWarning')[0];
|
||||
|
||||
|
@ -292,7 +293,7 @@ function onOpen(openInfo) {
|
|||
}
|
||||
});
|
||||
} else {
|
||||
analytics.send(analytics.APPLICATION_EVENT.action('SerialPortFailed'));
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'SerialPortFailed');
|
||||
|
||||
console.log('Failed to open serial port');
|
||||
GUI.log(i18n.getMessage('serialPortOpenFail'));
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
TABS.configuration = {
|
||||
DSHOT_PROTOCOL_MIN_VALUE: 5,
|
||||
SHOW_OLD_BATTERY_CONFIG: false
|
||||
SHOW_OLD_BATTERY_CONFIG: false,
|
||||
analyticsChanges: {},
|
||||
};
|
||||
|
||||
TABS.configuration.initialize = function (callback, scrollPosition) {
|
||||
|
@ -195,6 +196,10 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
load_config();
|
||||
|
||||
function process_html() {
|
||||
var self = this;
|
||||
|
||||
self.analyticsChanges = {};
|
||||
|
||||
var mixer_list_e = $('select.mixerList');
|
||||
for (var selectIndex = 0; selectIndex < mixerList.length; selectIndex++) {
|
||||
mixerList.forEach(function (mixerEntry, mixerIndex) {
|
||||
|
@ -225,7 +230,15 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
reverseMotorSwitch_e.prop('checked', MIXER_CONFIG.reverseMotorDir != 0).change();
|
||||
|
||||
mixer_list_e.change(function () {
|
||||
MIXER_CONFIG.mixer = parseInt($(this).val());
|
||||
var mixerValue = parseInt($(this).val());
|
||||
|
||||
var newValue;
|
||||
if (mixerValue !== MIXER_CONFIG.mixer) {
|
||||
newValue = $(this).find('option:selected').text();
|
||||
}
|
||||
self.analyticsChanges['Mixer'] = newValue;
|
||||
|
||||
MIXER_CONFIG.mixer = mixerValue;
|
||||
refreshMixerPreview();
|
||||
});
|
||||
|
||||
|
@ -371,8 +384,16 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
|
||||
esc_protocol_e.val(PID_ADVANCED_CONFIG.fast_pwm_protocol + 1);
|
||||
esc_protocol_e.change(function () {
|
||||
var escProtocolValue = parseInt($(this).val()) - 1;
|
||||
|
||||
var newValue;
|
||||
if (escProtocolValue !== PID_ADVANCED_CONFIG.fast_pwm_protocol) {
|
||||
newValue = $(this).find('option:selected').text();
|
||||
}
|
||||
self.analyticsChanges['EscProtocol'] = newValue;
|
||||
|
||||
//hide not used setting for DSHOT protocol
|
||||
if ($(this).val() - 1 >= self.DSHOT_PROTOCOL_MIN_VALUE) {
|
||||
if (escProtocolValue >= self.DSHOT_PROTOCOL_MIN_VALUE) {
|
||||
$('div.minthrottle').hide();
|
||||
$('div.maxthrottle').hide();
|
||||
$('div.mincommand').hide();
|
||||
|
@ -621,7 +642,15 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
serialRX_e.change(function () {
|
||||
RX_CONFIG.serialrx_provider = parseInt($(this).val());
|
||||
var serialRxValue = parseInt($(this).val());
|
||||
|
||||
var newValue;
|
||||
if (serialRxValue !== RX_CONFIG.serialrx_provider) {
|
||||
newValue = $(this).find('option:selected').text();
|
||||
}
|
||||
self.analyticsChanges['SerialRx'] = newValue;
|
||||
|
||||
RX_CONFIG.serialrx_provider = serialRxValue;
|
||||
});
|
||||
|
||||
// select current serial RX type
|
||||
|
@ -989,6 +1018,9 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
|
|||
RX_CONFIG.fpvCamAngleDegrees = parseInt($('input[name="fpvCamAngleDegrees"]').val());
|
||||
}
|
||||
|
||||
analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self.analyticsChanges);
|
||||
self.analyticsChanges = {};
|
||||
|
||||
function save_serial_config() {
|
||||
var next_callback = save_feature_config;
|
||||
MSP.send_message(MSPCodes.MSP_SET_CF_SERIAL_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_CF_SERIAL_CONFIG), false, next_callback);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
TABS.ports = {};
|
||||
TABS.ports = {
|
||||
analyticsChanges: {},
|
||||
};
|
||||
|
||||
TABS.ports.initialize = function (callback, scrollPosition) {
|
||||
var self = this;
|
||||
|
@ -117,6 +119,9 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
function update_ui() {
|
||||
self.analyticsChanges = {};
|
||||
|
||||
self.foo.bar = 1;
|
||||
|
||||
if (semver.lt(CONFIG.apiVersion, "1.6.0")) {
|
||||
|
||||
|
@ -240,6 +245,19 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
if (serialPort.functions.indexOf(functionName) >= 0) {
|
||||
select_e.val(functionName);
|
||||
}
|
||||
|
||||
if (column === 'telemetry') {
|
||||
var initialValue = functionName;
|
||||
select_e.change(function () {
|
||||
var telemetryValue = $(this).val();
|
||||
|
||||
var newValue;
|
||||
if (telemetryValue !== initialValue) {
|
||||
newValue = $(this).find('option:selected').text();
|
||||
}
|
||||
self.analyticsChanges['Telemetry'] = newValue;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,6 +267,7 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
function on_tab_loaded_handler() {
|
||||
var self = this;
|
||||
|
||||
i18n.localizePage();
|
||||
|
||||
|
@ -265,6 +284,9 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
|
||||
function on_save_handler() {
|
||||
analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self.analyticsChanges);
|
||||
self.analyticsChanges = {};
|
||||
|
||||
// update configuration based on current ui state
|
||||
SERIAL_CONFIG.ports = [];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue