Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ELRS UID - Co-authored-by: @jeffpearce #3097

Merged
merged 4 commits into from Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -2,6 +2,7 @@ module.exports = {
parserOptions: {
ecmaVersion: 2020,
sourceType: "module",
allowImportExportEverywhere: true,
},
extends: ["plugin:vue/recommended"],
env: {
Expand Down
5 changes: 5 additions & 0 deletions gulpfile.js
Expand Up @@ -1101,6 +1101,11 @@ function cordova_execbrowserify(file) {
const destpath = file.replace(filename, '');
console.log(`Include required modules in ${file}`);
return browserify(file, { ignoreMissing: true })
.transform("babelify", {
presets: ["@babel/preset-env"],
sourceMaps: false,
global:true,
ignore: [/\/node_modules\/(?!md5.js\/)/] })
.bundle()
.pipe(source(filename))
.pipe(gulp.dest(destpath));
Expand Down
5 changes: 4 additions & 1 deletion locales/en/messages.json
Expand Up @@ -2192,6 +2192,9 @@
"receiverButtonBindMessage": {
"message": "Bind request sent to the flight controller."
},
"receiverButtonPassphrase": {
"message": "Passphrase"
},
"receiverButtonSticks": {
"message": "Control sticks"
},
Expand Down Expand Up @@ -6821,7 +6824,7 @@
"description": "Warning message that shows up at the top of the preset sources dialog"
},
"presetsNoPresetsFound": {
"message": "No presets found for the given search paramteres",
"message": "No presets found for the given search parameters",
"description": "Message that apprears on presets tab if no presets were found"
},
"presetsTooManyPresetsFound": {
Expand Down
4 changes: 4 additions & 0 deletions package.json
Expand Up @@ -51,8 +51,11 @@
"node": "16.x"
},
"dependencies": {
"@babel/eslint-parser": "^7.19.1",
"@babel/preset-env": "^7.20.2",
"@fortawesome/fontawesome-free": "^5.13.0",
"@panter/vue-i18next": "^0.15.2",
"babelify": "^10.0.0",
"bluebird": "^3.7.2",
"bonjour": "^3.5.0",
"djv": "^2.1.4",
Expand All @@ -67,6 +70,7 @@
"jquery-ui-npm": "^1.12.0",
"lru_map": "^0.3.3",
"marked": "^4.1.1",
"md5.js": "^1.3.5",
"multicast-dns": "^7.2.5",
"multiple-select": "^1.5.2",
"nw-vue-devtools-prebuilt": "^0.0.10",
Expand Down
11 changes: 11 additions & 0 deletions src/css/tabs/receiver.less
Expand Up @@ -605,6 +605,17 @@
margin-bottom: 0;
}
}
.elrsContainer {
float: left;
width: calc(100% - 20px);
}
.elrsUid {
float: left;
width: calc(100% - 20px);
}
.elrsPassphrase {
margin-left: 5px;
}
.gui_box_titlebar {
margin-bottom: 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/js/fc.js
Expand Up @@ -555,6 +555,7 @@ const FC = {
rcSmoothingAutoFactor: 0,
usbCdcHidType: 0,
rcSmoothingMode: 0,
elrsUid: 0,
};

this.FAILSAFE_CONFIG = {
Expand Down
10 changes: 10 additions & 0 deletions src/js/msp/MSPHelper.js
Expand Up @@ -1087,6 +1087,13 @@ MspHelper.prototype.process_data = function(dataHandler) {
FC.RX_CONFIG.rcSmoothingAutoFactor = data.readU8();
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
FC.RX_CONFIG.rcSmoothingMode = data.readU8();
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) {
const elrsUidLength = 6;
FC.RX_CONFIG.elrsUid = [];
for (let i = 0; i < elrsUidLength; i++) {
FC.RX_CONFIG.elrsUid.push(data.readU8());
}
}
}
}
}
Expand Down Expand Up @@ -2057,6 +2064,9 @@ MspHelper.prototype.crunch = function(code, modifierCode = undefined) {
.push8(FC.RX_CONFIG.rcSmoothingAutoFactor);
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
buffer.push8(FC.RX_CONFIG.rcSmoothingMode);
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) {
FC.RX_CONFIG.elrsUid.forEach((b) => buffer.push8(b));
}
}
}
}
Expand Down
80 changes: 77 additions & 3 deletions src/js/tabs/receiver.js
@@ -1,16 +1,44 @@
import { i18n } from "../localization";

const MD5 = require('md5.js');

const receiver = {
rateChartHeight: 117,
analyticsChanges: {},
needReboot: false,
elrsPassphraseEnabled: false,
};

receiver.initialize = function (callback) {
const tab = this;

if (GUI.active_tab !== 'receiver') {
GUI.active_tab = 'receiver';
GUI.active_tab = 'receiver';

function lookup_elrs_passphrase(uidString) {
const passphraseMap = ConfigStorage.get('passphrase_map').passphrase_map || {};

return passphraseMap[uidString] ?? 0;
}

function save_elrs_passphrase(uidString, passphrase) {
const passphraseMap = ConfigStorage.get('passphrase_map').passphrase_map ?? {};

passphraseMap[uidString] = passphrase;
ConfigStorage.set({'passphrase_map': passphraseMap});
}

function elrs_passphrase_to_bytes(text) {
let uidBytes = [0,0,0,0,0,0];

if (text) {
const bindingPhraseFull = `-DMY_BINDING_PHRASE="${text}"`;
const md5stream = new MD5();
md5stream.end(bindingPhraseFull);
const buffer = md5stream.read().subarray(0, 6);
uidBytes = Uint8Array.from(buffer);
}

return uidBytes;
}

function get_rc_data() {
Expand Down Expand Up @@ -336,8 +364,34 @@ receiver.initialize = function (callback) {
},
});
}
}

if (FC.FEATURE_CONFIG.features.isEnabled('RX_SPI') && FC.RX_CONFIG.rxSpiProtocol == 19 && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) {
tab.elrsPassphraseEnabled = true;

const elrsUid = $('span.elrsUid');
const elrsUidString = FC.RX_CONFIG.elrsUid.join(',');

elrsUid.text(elrsUidString);

const elrsPassphrase = $('input.elrsPassphrase');

const passphraseString = lookup_elrs_passphrase(elrsUidString);
if (passphraseString) {
elrsPassphrase.val(passphraseString);
}
elrsPassphrase.on('keyup', function() {
const passphrase = elrsPassphrase.val();
if (passphrase) {
elrsUid.text(elrs_passphrase_to_bytes(passphrase));
} else {
elrsUid.text("0.0.0.0.0.0");
}
updateSaveButton(true);
});
} else {
tab.elrsPassphraseEnabled = false;
}
}

// UI Hooks

Expand Down Expand Up @@ -381,19 +435,26 @@ receiver.initialize = function (callback) {
}
}

function checkShowElrsPassphrase() {
$('#elrsContainer').toggle(tab.elrsPassphraseEnabled);
$('input.elrsUid').toggle(tab.elrsPassphraseEnabled);
}

$(featuresElement).filter('select').change(function () {
const element = $(this);
FC.FEATURE_CONFIG.features.updateData(element);
updateTabList(FC.FEATURE_CONFIG.features);
if (element.attr('name') === 'rxMode') {
checkShowSerialRxBox();
checkShowSpiRxBox();
checkShowElrsPassphrase();
updateSaveButton(true);
}
});

checkShowSerialRxBox();
checkShowSpiRxBox();
checkShowElrsPassphrase();
updateSaveButton();

$('a.refresh').click(function () {
Expand Down Expand Up @@ -442,6 +503,19 @@ receiver.initialize = function (callback) {
FC.RX_CONFIG.rcSmoothingAutoFactor = parseInt($('input[name="rcSmoothingAutoFactor-number"]').val());
}

if (tab.elrsPassphraseEnabled) {
const elrsUidChars = $('span.elrsUid')[0].innerText.split(',').map(uidChar => parseInt(uidChar, 10));
if (elrsUidChars.length === 6) {
FC.RX_CONFIG.elrsUid = elrsUidChars;

const elrsUid = $('span.elrsUid')[0].innerText;
const elrsPassphrase = $('input.elrsPassphrase').val();
save_elrs_passphrase(elrsUid, elrsPassphrase);
} else {
FC.RX_CONFIG.elrsUid = [0, 0, 0, 0, 0, 0];
}
}

function save_rssi_config() {
MSP.send_message(MSPCodes.MSP_SET_RSSI_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_RSSI_CONFIG), false, save_rc_configs);
}
Expand Down
9 changes: 9 additions & 0 deletions src/tabs/receiver.html
Expand Up @@ -59,6 +59,15 @@
</select>
<span i18n="configurationSpiRX"></span>
</div>
<div id="elrsContainer" class="elrsContainer spacer_box">
<div >
<input type="text" class="elrsPassphrase">
<span i18n="receiverButtonPassphrase"></span><br/>
</div>
<div>
<span class="elrsUid"></span>
</div>
</div>
</div>
</div>

Expand Down