mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-15 20:35:23 +03:00
Added analytics for board type, MCU id, configurator build type. Also improved status display.
This commit is contained in:
parent
ac003d1405
commit
c690eadcbd
6 changed files with 156 additions and 28 deletions
|
@ -142,7 +142,7 @@ input[type="number"]::-webkit-inner-spin-button {
|
||||||
.logo_text {
|
.logo_text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
width: 200px;
|
width: 260px;
|
||||||
left: 80px;
|
left: 80px;
|
||||||
top: 50px;
|
top: 50px;
|
||||||
color: #949494;
|
color: #949494;
|
||||||
|
@ -156,7 +156,7 @@ input[type="number"]::-webkit-inner-spin-button {
|
||||||
|
|
||||||
@media all and (min-width: 1125px) {
|
@media all and (min-width: 1125px) {
|
||||||
#logo {
|
#logo {
|
||||||
margin-top: 18px;
|
margin-top: 9px;
|
||||||
width: 340px;
|
width: 340px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Analytics = function (trackingId, userId, appName, appVersion, changesetId, buildType, checkForDebugVersions, optOut, debugMode) {
|
var Analytics = function (trackingId, userId, appName, appVersion, changesetId, os, checkForDebugVersions, optOut, debugMode, buildType) {
|
||||||
this._trackingId = trackingId;
|
this._trackingId = trackingId;
|
||||||
|
|
||||||
this.setOptOut(optOut);
|
this.setOptOut(optOut);
|
||||||
|
@ -43,10 +43,14 @@ var Analytics = function (trackingId, userId, appName, appVersion, changesetId,
|
||||||
MCU_ID: 'mcuId',
|
MCU_ID: 'mcuId',
|
||||||
LOGGING_STATUS: 'loggingStatus',
|
LOGGING_STATUS: 'loggingStatus',
|
||||||
LOG_SIZE: 'logSize',
|
LOG_SIZE: 'logSize',
|
||||||
|
TARGET_NAME: 'targetName',
|
||||||
|
BOARD_NAME: 'boardName',
|
||||||
|
MANUFACTURER_ID: 'manufacturerId',
|
||||||
|
MCU_TYPE: 'mcuType',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.DIMENSIONS = {
|
this.DIMENSIONS = {
|
||||||
CONFIGURATOR_BUILD_TYPE: 1,
|
CONFIGURATOR_OS: 1,
|
||||||
BOARD_TYPE: 2,
|
BOARD_TYPE: 2,
|
||||||
FIRMWARE_TYPE: 3,
|
FIRMWARE_TYPE: 3,
|
||||||
FIRMWARE_VERSION: 4,
|
FIRMWARE_VERSION: 4,
|
||||||
|
@ -60,6 +64,11 @@ var Analytics = function (trackingId, userId, appName, appVersion, changesetId,
|
||||||
MCU_ID: 12,
|
MCU_ID: 12,
|
||||||
CONFIGURATOR_CHANGESET_ID: 13,
|
CONFIGURATOR_CHANGESET_ID: 13,
|
||||||
CONFIGURATOR_USE_DEBUG_VERSIONS: 14,
|
CONFIGURATOR_USE_DEBUG_VERSIONS: 14,
|
||||||
|
TARGET_NAME: 15,
|
||||||
|
BOARD_NAME: 16,
|
||||||
|
MANUFACTURER_ID: 17,
|
||||||
|
MCU_TYPE: 18,
|
||||||
|
CONFIGURATOR_BUILD_TYPE: 19,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.METRICS = {
|
this.METRICS = {
|
||||||
|
@ -67,9 +76,10 @@ var Analytics = function (trackingId, userId, appName, appVersion, changesetId,
|
||||||
LOG_SIZE: 2,
|
LOG_SIZE: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.setDimension(this.DIMENSIONS.CONFIGURATOR_BUILD_TYPE, buildType);
|
this.setDimension(this.DIMENSIONS.CONFIGURATOR_OS, os);
|
||||||
this.setDimension(this.DIMENSIONS.CONFIGURATOR_CHANGESET_ID, changesetId);
|
this.setDimension(this.DIMENSIONS.CONFIGURATOR_CHANGESET_ID, changesetId);
|
||||||
this.setDimension(this.DIMENSIONS.CONFIGURATOR_USE_DEBUG_VERSIONS, checkForDebugVersions);
|
this.setDimension(this.DIMENSIONS.CONFIGURATOR_USE_DEBUG_VERSIONS, checkForDebugVersions);
|
||||||
|
this.setDimension(this.DIMENSIONS.CONFIGURATOR_BUILD_TYPE, buildType);
|
||||||
|
|
||||||
this.resetFlightControllerData();
|
this.resetFlightControllerData();
|
||||||
this.resetFirmwareData();
|
this.resetFirmwareData();
|
||||||
|
@ -124,6 +134,10 @@ Analytics.prototype._rebuildFlightControllerEvent = function () {
|
||||||
this.setDimension(this.DIMENSIONS.LOGGING_STATUS, this._flightControllerData[this.DATA.LOGGING_STATUS]);
|
this.setDimension(this.DIMENSIONS.LOGGING_STATUS, this._flightControllerData[this.DATA.LOGGING_STATUS]);
|
||||||
this.setDimension(this.DIMENSIONS.MCU_ID, this._flightControllerData[this.DATA.MCU_ID]);
|
this.setDimension(this.DIMENSIONS.MCU_ID, this._flightControllerData[this.DATA.MCU_ID]);
|
||||||
this.setMetric(this.METRICS.LOG_SIZE, this._flightControllerData[this.DATA.LOG_SIZE]);
|
this.setMetric(this.METRICS.LOG_SIZE, this._flightControllerData[this.DATA.LOG_SIZE]);
|
||||||
|
this.setMetric(this.DIMENSIONS.TARGET_NAME, this._flightControllerData[this.DATA.TARGET_NAME]);
|
||||||
|
this.setMetric(this.DIMENSIONS.BOARD_NAME, this._flightControllerData[this.DATA.BOARD_NAME]);
|
||||||
|
this.setMetric(this.DIMENSIONS.MANUFACTURER_ID, this._flightControllerData[this.DATA.MANUFACTURER_ID]);
|
||||||
|
this.setMetric(this.DIMENSIONS.MCU_TYPE, this._flightControllerData[this.DATA.MCU_TYPE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Analytics.prototype.setFlightControllerData = function (property, value) {
|
Analytics.prototype.setFlightControllerData = function (property, value) {
|
||||||
|
|
47
src/js/fc.js
47
src/js/fc.js
|
@ -60,7 +60,7 @@ var COPY_PROFILE;
|
||||||
var DEFAULT;
|
var DEFAULT;
|
||||||
|
|
||||||
var FC = {
|
var FC = {
|
||||||
resetState: function() {
|
resetState: function () {
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
apiVersion: "0.0.0",
|
apiVersion: "0.0.0",
|
||||||
flightControllerIdentifier: '',
|
flightControllerIdentifier: '',
|
||||||
|
@ -86,6 +86,14 @@ var FC = {
|
||||||
armingDisableFlags: 0,
|
armingDisableFlags: 0,
|
||||||
armingDisabled: false,
|
armingDisabled: false,
|
||||||
runawayTakeoffPreventionDisabled: false,
|
runawayTakeoffPreventionDisabled: false,
|
||||||
|
boardIdentifier: "",
|
||||||
|
boardVersion: 0,
|
||||||
|
commCapabilities: 0,
|
||||||
|
targetName: "",
|
||||||
|
boardName: "",
|
||||||
|
manufacturerId: "",
|
||||||
|
signature: [],
|
||||||
|
mcuTypeId: 255,
|
||||||
};
|
};
|
||||||
|
|
||||||
BF_CONFIG = {
|
BF_CONFIG = {
|
||||||
|
@ -456,5 +464,42 @@ var FC = {
|
||||||
dterm_notch_hz: 260,
|
dterm_notch_hz: 260,
|
||||||
yaw_lowpass_hz: 100,
|
yaw_lowpass_hz: 100,
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
MCU_TYPES: {
|
||||||
|
0: "SIMULATOR",
|
||||||
|
1: "F103",
|
||||||
|
2: "F303",
|
||||||
|
3: "F40X",
|
||||||
|
4: "F411",
|
||||||
|
5: "F446",
|
||||||
|
6: "F722",
|
||||||
|
7: "F745",
|
||||||
|
8: "F746",
|
||||||
|
9: "F765",
|
||||||
|
255: "Unknown MCU",
|
||||||
|
},
|
||||||
|
|
||||||
|
getHardwareName: function () {
|
||||||
|
let name;
|
||||||
|
if (CONFIG.targetName) {
|
||||||
|
name = CONFIG.targetName;
|
||||||
|
} else {
|
||||||
|
name = CONFIG.boardIdentifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG.boardName && CONFIG.boardName !== name) {
|
||||||
|
name = CONFIG.boardName + "(" + name + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CONFIG.manufacturerId) {
|
||||||
|
name = CONFIG.manufacturerId + "/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
},
|
||||||
|
|
||||||
|
getMcuType: function () {
|
||||||
|
return FC.MCU_TYPES[CONFIG.mcuTypeId];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var nwGui = getNwGui();
|
||||||
|
|
||||||
var googleAnalytics = analytics;
|
var googleAnalytics = analytics;
|
||||||
var analytics = undefined;
|
var analytics = undefined;
|
||||||
|
|
||||||
|
@ -16,6 +18,17 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getNwGui() {
|
||||||
|
var gui = null;
|
||||||
|
try {
|
||||||
|
gui = require('nw.gui');
|
||||||
|
} catch (ex) {
|
||||||
|
console.log("Could not require 'nw.gui', maybe inside chrome");
|
||||||
|
}
|
||||||
|
|
||||||
|
return gui;
|
||||||
|
}
|
||||||
|
|
||||||
function checkSetupAnalytics(callback) {
|
function checkSetupAnalytics(callback) {
|
||||||
if (!analytics) {
|
if (!analytics) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
|
@ -32,6 +45,10 @@ function checkSetupAnalytics(callback) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getBuildType() {
|
||||||
|
return nwGui ? 'NW.js' : 'Chrome';
|
||||||
|
}
|
||||||
|
|
||||||
function setupAnalytics(result) {
|
function setupAnalytics(result) {
|
||||||
var userId;
|
var userId;
|
||||||
if (result.userId) {
|
if (result.userId) {
|
||||||
|
@ -48,7 +65,7 @@ function setupAnalytics(result) {
|
||||||
|
|
||||||
var debugMode = typeof process === "object" && process.versions['nw-flavor'] === 'sdk';
|
var debugMode = typeof process === "object" && process.versions['nw-flavor'] === 'sdk';
|
||||||
|
|
||||||
analytics = new Analytics('UA-123002063-1', userId, 'Betaflight Configurator', getManifestVersion(), CONFIGURATOR.gitChangesetId, GUI.operating_system, checkForDebugVersions, optOut, debugMode);
|
analytics = new Analytics('UA-123002063-1', userId, 'Betaflight Configurator', getManifestVersion(), CONFIGURATOR.gitChangesetId, GUI.operating_system, checkForDebugVersions, optOut, debugMode, getBuildType());
|
||||||
|
|
||||||
function logException(exception) {
|
function logException(exception) {
|
||||||
analytics.sendException(exception.stack);
|
analytics.sendException(exception.stack);
|
||||||
|
@ -64,15 +81,14 @@ function setupAnalytics(result) {
|
||||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' })
|
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' })
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
if (nwGui) {
|
||||||
var gui = require('nw.gui');
|
var win = nwGui.Window.get();
|
||||||
var win = gui.Window.get();
|
|
||||||
win.on('close', function () {
|
win.on('close', function () {
|
||||||
sendCloseEvent();
|
sendCloseEvent();
|
||||||
|
|
||||||
this.close(true);
|
this.close(true);
|
||||||
});
|
});
|
||||||
} catch (ex) {
|
} else {
|
||||||
// Looks like we're in Chrome - but the event does not actually get fired
|
// Looks like we're in Chrome - but the event does not actually get fired
|
||||||
chrome.runtime.onSuspend.addListener(sendCloseEvent);
|
chrome.runtime.onSuspend.addListener(sendCloseEvent);
|
||||||
}
|
}
|
||||||
|
@ -698,15 +714,21 @@ function generateFilename(prefix, suffix) {
|
||||||
return filename + '.' + suffix;
|
return filename + '.' + suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFirmwareVersion(firmwareVersion, firmwareId, hardwareId) {
|
function getTargetVersion(hardwareId) {
|
||||||
|
var versionText = '';
|
||||||
|
|
||||||
|
if (hardwareId) {
|
||||||
|
versionText += i18n.getMessage('versionLabelTarget') + ': ' + hardwareId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionText;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFirmwareVersion(firmwareVersion, firmwareId) {
|
||||||
var versionText = '';
|
var versionText = '';
|
||||||
|
|
||||||
if (firmwareVersion) {
|
if (firmwareVersion) {
|
||||||
versionText += i18n.getMessage('versionLabelFirmware') + ': ' + firmwareId + ' ' + firmwareVersion;
|
versionText += i18n.getMessage('versionLabelFirmware') + ': ' + firmwareId + ' ' + firmwareVersion;
|
||||||
|
|
||||||
if (hardwareId) {
|
|
||||||
versionText += ' (' + i18n.getMessage('versionLabelTarget') + ': ' + hardwareId + ')';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return versionText;
|
return versionText;
|
||||||
|
@ -719,7 +741,9 @@ function getConfiguratorVersion() {
|
||||||
function updateTopBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
function updateTopBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
||||||
var versionText = getConfiguratorVersion() + '<br />';
|
var versionText = getConfiguratorVersion() + '<br />';
|
||||||
|
|
||||||
versionText = versionText + getFirmwareVersion(firmwareVersion, firmwareId, hardwareId);
|
versionText = versionText + getFirmwareVersion(firmwareVersion, firmwareId) + '<br />';
|
||||||
|
|
||||||
|
versionText = versionText + getTargetVersion(hardwareId);
|
||||||
|
|
||||||
$('#logo .logo_text').html(versionText);
|
$('#logo .logo_text').html(versionText);
|
||||||
}
|
}
|
||||||
|
@ -727,12 +751,19 @@ function updateTopBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
||||||
function updateStatusBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
function updateStatusBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
||||||
var versionText = '';
|
var versionText = '';
|
||||||
|
|
||||||
versionText = versionText + getFirmwareVersion(firmwareVersion, firmwareId, hardwareId);
|
versionText = versionText + getFirmwareVersion(firmwareVersion, firmwareId);
|
||||||
|
|
||||||
if (versionText !== '') {
|
if (versionText !== '') {
|
||||||
versionText = versionText + ', ';
|
versionText = versionText + ', ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let targetVersion = getTargetVersion(hardwareId);
|
||||||
|
versionText = versionText + targetVersion;
|
||||||
|
|
||||||
|
if (targetVersion !== '') {
|
||||||
|
versionText = versionText + ', ';
|
||||||
|
}
|
||||||
|
|
||||||
versionText = versionText + getConfiguratorVersion() + ' (' + CONFIGURATOR.gitChangesetId + ')';
|
versionText = versionText + getConfiguratorVersion() + ' (' + CONFIGURATOR.gitChangesetId + ')';
|
||||||
|
|
||||||
$('#status-bar .version').text(versionText);
|
$('#status-bar .version').text(versionText);
|
||||||
|
@ -752,19 +783,15 @@ function getManifestVersion(manifest) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function openNewWindowsInExternalBrowser() {
|
function openNewWindowsInExternalBrowser() {
|
||||||
try {
|
if (nwGui) {
|
||||||
var gui = require('nw.gui');
|
|
||||||
|
|
||||||
//Get the current window
|
//Get the current window
|
||||||
var win = gui.Window.get();
|
var win = nwGui.Window.get();
|
||||||
|
|
||||||
//Listen to the new window event
|
//Listen to the new window event
|
||||||
win.on('new-win-policy', function (frame, url, policy) {
|
win.on('new-win-policy', function (frame, url, policy) {
|
||||||
gui.Shell.openExternal(url);
|
gui.Shell.openExternal(url);
|
||||||
policy.ignore();
|
policy.ignore();
|
||||||
});
|
});
|
||||||
} catch (ex) {
|
|
||||||
console.log("require does not exist, maybe inside chrome");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
|
||||||
function MspHelper () {
|
function MspHelper () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -34,6 +33,8 @@ function MspHelper () {
|
||||||
MSC: 2,
|
MSC: 2,
|
||||||
MSC_UTC: 3
|
MSC_UTC: 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.SIGNATURE_LENGTH = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
MspHelper.prototype.reorderPwmProtocols = function (protocol) {
|
MspHelper.prototype.reorderPwmProtocols = function (protocol) {
|
||||||
|
@ -710,12 +711,49 @@ MspHelper.prototype.process_data = function(dataHandler) {
|
||||||
}
|
}
|
||||||
CONFIG.boardIdentifier = identifier;
|
CONFIG.boardIdentifier = identifier;
|
||||||
CONFIG.boardVersion = data.readU16();
|
CONFIG.boardVersion = data.readU16();
|
||||||
|
|
||||||
if (semver.gte(CONFIG.apiVersion, "1.35.0")) {
|
if (semver.gte(CONFIG.apiVersion, "1.35.0")) {
|
||||||
CONFIG.boardType = data.readU8();
|
CONFIG.boardType = data.readU8();
|
||||||
} else {
|
} else {
|
||||||
CONFIG.boardType = 0;
|
CONFIG.boardType = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CONFIG.targetName = "";
|
||||||
|
if (semver.gte(CONFIG.apiVersion, "1.37.0")) {
|
||||||
|
CONFIG.commCapabilities = data.readU8();
|
||||||
|
|
||||||
|
let length = data.readU8();
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
CONFIG.targetName += String.fromCharCode(data.readU8());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CONFIG.commCapabilities = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG.boardName = "";
|
||||||
|
CONFIG.manufacturerId = "";
|
||||||
|
CONFIG.signature = [];
|
||||||
|
if (semver.gte(CONFIG.apiVersion, "1.39.0")) {
|
||||||
|
let length = data.readU8();
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
CONFIG.boardName += String.fromCharCode(data.readU8());
|
||||||
|
}
|
||||||
|
|
||||||
|
length = data.readU8();
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
CONFIG.manufacturerId += String.fromCharCode(data.readU8());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < self.SIGNATURE_LENGTH; i++) {
|
||||||
|
CONFIG.signature.push(data.readU8());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (semver.gte(CONFIG.apiVersion, "1.41.0")) {
|
||||||
|
CONFIG.mcuTypeId = data.readU8();
|
||||||
|
} else {
|
||||||
|
CONFIG.mcuTypeId = 255;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSPCodes.MSP_NAME:
|
case MSPCodes.MSP_NAME:
|
||||||
|
|
|
@ -254,10 +254,14 @@ function onOpen(openInfo) {
|
||||||
|
|
||||||
MSP.send_message(MSPCodes.MSP_BOARD_INFO, false, false, function () {
|
MSP.send_message(MSPCodes.MSP_BOARD_INFO, false, false, function () {
|
||||||
analytics.setFlightControllerData(analytics.DATA.BOARD_TYPE, CONFIG.boardIdentifier);
|
analytics.setFlightControllerData(analytics.DATA.BOARD_TYPE, CONFIG.boardIdentifier);
|
||||||
|
analytics.setFlightControllerData(analytics.DATA.TARGET_NAME, CONFIG.targetName);
|
||||||
|
analytics.setFlightControllerData(analytics.DATA.BOARD_NAME, CONFIG.boardName);
|
||||||
|
analytics.setFlightControllerData(analytics.DATA.MANUFACTURER_ID, CONFIG.manufacturerId);
|
||||||
|
analytics.setFlightControllerData(analytics.DATA.MCU_TYPE, FC.getMcuType());
|
||||||
|
|
||||||
GUI.log(i18n.getMessage('boardInfoReceived', [CONFIG.boardIdentifier, CONFIG.boardVersion]));
|
GUI.log(i18n.getMessage('boardInfoReceived', [FC.getHardwareName(), CONFIG.boardVersion]));
|
||||||
updateStatusBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier, CONFIG.boardIdentifier);
|
updateStatusBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier, FC.getHardwareName());
|
||||||
updateTopBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier, CONFIG.boardIdentifier);
|
updateTopBarVersion(CONFIG.flightControllerVersion, CONFIG.flightControllerIdentifier, FC.getHardwareName());
|
||||||
|
|
||||||
MSP.send_message(MSPCodes.MSP_UID, false, false, function () {
|
MSP.send_message(MSPCodes.MSP_UID, false, false, function () {
|
||||||
var uniqueDeviceIdentifier = 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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue