1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-20 14:55:15 +03:00

Added Google analytics collection.

This commit is contained in:
mikeller 2018-08-01 01:12:24 +12:00
parent 5b0a6349a7
commit 8d5d81f9cf
10 changed files with 277 additions and 4 deletions

64
src/js/Analytics.js Normal file
View file

@ -0,0 +1,64 @@
'use strict';
var Analytics = function (serviceName, trackingId, operatingSystem) {
this.eventBuilder = analytics.EventBuilder;
this.service = analytics.getService(serviceName);
this.tracker = this.service.getTracker(trackingId);
this.DATA = {
BOARD_TYPE: 'boardType',
FIRMWARE_TYPE: 'firmwareType',
FIRMWARE_VERSION: 'firmwareVersion',
API_VERSION: 'apiVersion',
MCU_ID: 'mcuId',
};
this.DIMENSIONS = {
OS: 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.resetFlightControllerData();
};
Analytics.prototype.setTrackingPermitted = function (permitted) {
this.service.getConfig().addCallback(function(config) {
config.setTrackingPermitted(permitted);
});
}
Analytics.prototype.send = function (event) {
this.tracker.send(event);
}
Analytics.prototype.sendAppView = function (viewName) {
this.tracker.sendAppView(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.setFlightControllerData = function (property, value) {
this.flightControllerData[property] = value;
this.rebuildFlightControllerEvent();
}
Analytics.prototype.resetFlightControllerData = function () {
this.flightControllerData = {};
this.rebuildFlightControllerEvent();
}

View file

@ -1,19 +1,60 @@
'use strict';
var analytics;
openNewWindowsInExternalBrowser();
//Asynchronous configuration to be done.
//When finish the startProcess() function must be called
$(document).ready(function () {
i18n.init(function() {
startProcess();
setupAnalytics();
initializeSerialBackend();
});
});
function setupAnalytics() {
analytics = new Analytics('com.betaflight.configurator', 'UA-123002063-1', GUI.operating_system);
chrome.storage.local.get('userId', function (result) {
var userId;
if (result.userId) {
userId = result.userId;
} else {
var uid = new ShortUniqueId();
userId = uid.randomUUID(13);
chrome.storage.local.set({'userId': userId});
}
analytics.tracker.set('userId', userId);
analytics.tracker.set('sessionControl', 'start');
analytics.send(analytics.APPLICATION_EVENT.action('AppStart'))
function sendCloseEvent() {
analytics.send(analytics.APPLICATION_EVENT.action('AppClose'))
analytics.tracker.set('sessionControl', 'end');
}
try {
var gui = require('nw.gui');
var win = gui.Window.get();
win.on('close', function () {
sendCloseEvent();
this.close(true);
});
} catch (ex) {
// Looks like we're in Chrome - but the event does not actually get fired
chrome.runtime.onSuspend.addListener(sendCloseEvent);
}
startProcess();
});
}
//Process to execute to real start the app
function startProcess() {
// translate to user-selected language
i18n.localizePage();
@ -113,6 +154,8 @@ function startProcess() {
GUI.tab_switch_in_progress = false;
}
analytics.sendAppView(tab);
switch (tab) {
case 'landing':
TABS.landing.initialize(content_ready);
@ -249,6 +292,28 @@ function startProcess() {
$('div.checkForConfiguratorUnstableVersions').hide();
}
chrome.storage.local.get('analyticsOptOut', function (result) {
if (result.analyticsOptOut) {
$('div.analyticsOptOut input').prop('checked', true);
}
$('div.analyticsOptOut input').change(function () {
var checked = $(this).is(':checked');
chrome.storage.local.set({'analyticsOptOut': checked});
if (checked) {
analytics.send(analytics.APPLICATION_EVENT.action('OptOut'));
}
analytics.setTrackingPermitted(!checked);
if (!checked) {
analytics.send(analytics.APPLICATION_EVENT.action('OptIn'));
}
}).change();
});
chrome.storage.local.get('userLanguageSelect', function (result) {
var userLanguage_e = $('div.userLanguage select');

View file

@ -1,6 +1,8 @@
'use strict';
var mspHelper;
var analyticsTimer;
function initializeSerialBackend() {
GUI.updateManualPortVisibility = function(){
@ -124,6 +126,14 @@ function initializeSerialBackend() {
function finishClose(finishedCallback) {
var wasConnected = CONFIGURATOR.connectionValid;
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('Disconnected'));
if (analyticsTimer) {
analyticsTimer.send();
analyticsTimer = undefined;
}
analytics.resetFlightControllerData();
serial.disconnect(onClosed);
MSP.disconnect_cleanup();
@ -200,13 +210,17 @@ function onOpen(openInfo) {
// request configuration data
MSP.send_message(MSPCodes.MSP_API_VERSION, false, false, function () {
analytics.setFlightControllerData(analytics.DATA.API_VERSION, CONFIG.apiVersion);
GUI.log(i18n.getMessage('apiVersionReceived', [CONFIG.apiVersion]));
if (semver.gte(CONFIG.apiVersion, CONFIGURATOR.apiVersionAccepted)) {
MSP.send_message(MSPCodes.MSP_FC_VARIANT, false, false, function () {
analytics.setFlightControllerData(analytics.DATA.FIRMWARE_TYPE, CONFIG.flightControllerIdentifier);
if (CONFIG.flightControllerIdentifier === 'BTFL') {
MSP.send_message(MSPCodes.MSP_FC_VERSION, false, false, function () {
analytics.setFlightControllerData(analytics.DATA.FIRMWARE_VERSION, CONFIG.flightControllerVersion);
GUI.log(i18n.getMessage('fcInfoReceived', [CONFIG.flightControllerIdentifier, CONFIG.flightControllerVersion]));
updateStatusBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier);
@ -217,13 +231,19 @@ function onOpen(openInfo) {
GUI.log(i18n.getMessage('buildInfoReceived', [CONFIG.buildInfo]));
MSP.send_message(MSPCodes.MSP_BOARD_INFO, false, false, function () {
analytics.setFlightControllerData(analytics.DATA.BOARD_TYPE, CONFIG.boardIdentifier);
GUI.log(i18n.getMessage('boardInfoReceived', [CONFIG.boardIdentifier, CONFIG.boardVersion]));
updateStatusBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier, CONFIG.boardIdentifier);
updateTopBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier, CONFIG.boardIdentifier);
MSP.send_message(MSPCodes.MSP_UID, false, false, function () {
GUI.log(i18n.getMessage('uniqueDeviceIdReceived', [CONFIG.uid[0].toString(16) + CONFIG.uid[1].toString(16) + CONFIG.uid[2].toString(16)]));
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');
GUI.log(i18n.getMessage('uniqueDeviceIdReceived', [uniqueDeviceIdentifier]));
if (semver.gte(CONFIG.apiVersion, "1.20.0")) {
MSP.send_message(MSPCodes.MSP_NAME, false, false, function () {
@ -240,6 +260,8 @@ function onOpen(openInfo) {
});
});
} else {
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('ConnectionRefused'));
var dialog = $('.dialogConnectWarning')[0];
$('.dialogConnectWarning-content').html(i18n.getMessage('firmwareTypeNotSupported'));
@ -254,6 +276,8 @@ function onOpen(openInfo) {
}
});
} else {
analytics.send(analytics.FLIGHT_CONTROLLER_EVENT.action('ConnectionRefused'));
var dialog = $('.dialogConnectWarning')[0];
$('.dialogConnectWarning-content').html(i18n.getMessage('firmwareVersionNotSupported', [CONFIGURATOR.apiVersionAccepted]));
@ -268,6 +292,8 @@ function onOpen(openInfo) {
}
});
} else {
analytics.send(analytics.APPLICATION_EVENT.action('SerialPortFailed'));
console.log('Failed to open serial port');
GUI.log(i18n.getMessage('serialPortOpenFail'));