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 UBLOX AssistNow support to configurator #2123

Merged
merged 11 commits into from
Jun 24, 2024
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ sources.js = [
'./js/msp/MSPCodes.js',
'./js/msp/MSPHelper.js',
'./js/msp/MSPchainer.js',
'./js/ublox/UBLOX.js',
'./js/port_handler.js',
'./js/connection/connection.js',
'./js/connection/connectionBle.js',
Expand Down
10 changes: 10 additions & 0 deletions js/configurator_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,16 @@ $(function() {
$('a', activeTab).trigger('click');
}

globalSettings.store = store;
globalSettings.unitType = store.get('unit_type', UnitType.none);
globalSettings.mapProviderType = store.get('map_provider_type', 'osm');
globalSettings.mapApiKey = store.get('map_api_key', '');
globalSettings.assistnowApiKey = store.get('assistnow_api_key', '');
globalSettings.proxyURL = store.get('proxyurl', 'http://192.168.1.222/mapproxy/service?');
globalSettings.proxyLayer = store.get('proxylayer', 'your_proxy_layer_name');
globalSettings.showProfileParameters = store.get('show_profile_parameters', 1);
globalSettings.assistnowOfflineData = store.get('assistnow_offline_data', []);
globalSettings.assistnowOfflineDate = store.get('assistnow_offline_date', 0);
updateProfilesHighlightColours();

var cliAutocomplete = store.get('cli_autocomplete', true);
Expand Down Expand Up @@ -340,6 +344,7 @@ $(function() {
$('#proxylayer').val(globalSettings.proxyLayer);
$('#showProfileParameters').prop('checked', globalSettings.showProfileParameters);
$('#cliAutocomplete').prop('checked', globalSettings.cliAutocomplete);
$('#assistnow-api-key').val(globalSettings.assistnowApiKey);

i18n.getLanguages().forEach(lng => {
$('#languageOption').append("<option value='{0}'>{1}</option>".format(lng, i18n.getMessage("language_" + lng)));
Expand Down Expand Up @@ -383,6 +388,11 @@ $(function() {
store.set('proxylayer', $(this).val());
globalSettings.proxyLayer = $(this).val();
});
$('#assistnow-api-key').on('change', function () {
store.set('assistnow_api_key', $(this).val());
globalSettings.assistnowApiKey = $(this).val();
});

$('#demoModeReset').on('click', function () {
SITLProcess.deleteEepromFile('demo.bin');
});
Expand Down
8 changes: 8 additions & 0 deletions js/globalSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ var globalSettings = {
// tree target for documents
docsTreeLocation: 'master',
cliAutocomplete: true,
assistnowApiKey: null,
assistnowOfflineData: [],
assistnowOfflineDate: 0,
store: null,
saveAssistnowData: function() {
this.store.set('assistnow_offline_data', this.assistnowOfflineData);
this.store.set('assistnow_offline_date', this.assistnowOfflineDate);
}
};

module.exports = { globalSettings, UnitType };
2 changes: 2 additions & 0 deletions js/msp/MSPCodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ var MSPCodes = {
MSP2_INAV_FW_APPROACH: 0x204A,
MSP2_INAV_SET_FW_APPROACH: 0x204B,

MSP2_INAV_GPS_UBLOX_COMMAND: 0x2050,

MSP2_INAV_RATE_DYNAMICS: 0x2060,
MSP2_INAV_SET_RATE_DYNAMICS: 0x2061,

Expand Down
11 changes: 9 additions & 2 deletions js/msp/MSPHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -1588,11 +1588,14 @@ var mspHelper = (function () {
FC.OSD_CUSTOM_ELEMENTS .items.push(customElement)
}
break;
case MSPCodes.MSP2_INAV_GPS_UBLOX_COMMAND:
// Just and ACK from the fc.
break;

default:
console.log('Unknown code detected: ' + dataHandler.code);
console.log('Unknown code detected: 0x' + dataHandler.code.toString(16));
} else {
console.log('FC reports unsupported message error: ' + dataHandler.code);
console.log('FC reports unsupported message error: 0x' + dataHandler.code.toString(16));
}

// trigger callbacks, cleanup/remove callback after trigger
Expand Down Expand Up @@ -3383,6 +3386,10 @@ var mspHelper = (function () {
MSP.send_message(MSPCodes.MSP2_SET_CF_SERIAL_CONFIG, mspHelper.crunch(MSPCodes.MSP2_SET_CF_SERIAL_CONFIG), false, callback);
};

self.sendUbloxCommand = function (ubloxData, callback) {
MSP.send_message(MSPCodes.MSP2_INAV_GPS_UBLOX_COMMAND, ubloxData, false, callback);
};

return self;
})();

Expand Down
239 changes: 239 additions & 0 deletions js/ublox/UBLOX.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
'use strict';

const semver = require('semver');

require('./../injected_methods');
const jBox = require('./../libraries/jBox/jBox.min');
const i18n = require('./../localization');
const { GUI } = require('./../gui');
const { globalSettings } = require('../globalSettings');
const Store = require('electron-store');


var ublox = (function () {
var self = {};
var assistnowOnline = null;
var assistnowOffline = null;

// m7 = aid, not supported
// m8+ = mga
const fmt="mga";;
const gnss="gps,gal,bds,glo,qzss";

const onlineServers = [
'online-live1.services.u-blox.com',
'online-live2.services.u-blox.com',
];

const period=5

const offline_gnss="gps,gal,bds,glo";
const offline_alm="gps,gal,bds,glo";

const offlineServers = [
'offline-live1.services.u-blox.com',
'offline-live2.services.u-blox.com'
];

self.init = function() {

};

var hasFirstHeader;
var hasSecondHeader;
var ubxClass;
var ubxId;
var lenLow;
var lenHigh;
var payloadLen;
var skipped;
var currentCommand;

function resetUbloxState() {
//console.log("Reset ublox state");
hasFirstHeader = false;
hasSecondHeader = false;
ubxClass = false;
ubxId = false;
lenLow = false;
lenHigh = false;
payloadLen = 0;
skipped = 0;
currentCommand = [];
}

function splitUbloxData(ubxBytesBuffer) {
//console.log("type of data: " +typeof(ubxBytesBuffer));
//console.log("splitUbloxData: " + ubxBytesBuffer.byteLength);
let ubxBytes = new DataView(ubxBytesBuffer);

var ubxCommands = []
resetUbloxState()

for(var i = 0; i < ubxBytes.byteLength;++i) {
let c = ubxBytes.getUint8(i);
//console.log("byte: 0x" + c.toString(16));
if (!hasFirstHeader) {
if (c == 0xb5) {
//console.log("First header");
hasFirstHeader = true;
currentCommand.push(c);
continue;
}
else
{
resetUbloxState();
continue;
}
}
if (!hasSecondHeader) {
if (c == 0x62) {
//console.log("Second header");
hasSecondHeader = true;
currentCommand.push(c);
continue;
}
else
{
resetUbloxState();
continue;
}
}
if (!ubxClass) {
ubxClass = true;
//console.log("ubxClass: 0x"+ (c).toString(16));
currentCommand.push(c)
continue;
}
if (!ubxId) {
ubxId = true;
//console.log("ubxId: 0x"+ (c).toString(16));
currentCommand.push(c);
continue;
}
if (!lenLow) {
//console.log("Len low");
lenLow = true;
//(int) c
payloadLen = c;
currentCommand.push(c);
continue;
}
if (!lenHigh) {
//console.log("Len high");
lenHigh = true;
// (int)c
payloadLen = (c << 8) | payloadLen;
//console.log("Payload len " + payloadLen);
payloadLen += 2; // add crc bytes;
currentCommand.push(c);
continue
}
if (skipped < payloadLen - 1) {
//console.log("payload + crc");
skipped = skipped + 1;
currentCommand.push(c);
continue;
}
if (skipped == payloadLen - 1) {
skipped = skipped + 1;
currentCommand.push(c);
ubxCommands.push(currentCommand);
//console.log("Adding command");
resetUbloxState();
continue;
}
}
return ubxCommands
}

function getBinaryData(url, successCallback, failCallback) {
const req = new XMLHttpRequest();
req.open("GET", url, true);
req.responseType = "arraybuffer";

if (successCallback != null) {
req.onload = (event) => {
successCallback(req.response);
};
}

if (failCallback != null) {
req.onerror = (event) => {
failCallback(event);
}
}

req.send(null);
}


function loadError(event) {
GUI.alert(i18n.getMessage("gpsAssistnowLoadDataError"));
console.log(i18n.getMessage("gpsAssistnowLoadDataError") + ':' + event.toString());
}

// For more info on assistnow, check:
// https://developer.thingstream.io/guides/location-services/assistnow-user-guide
// Currently only supported for M8+ units
self.loadAssistnowOffline = function(callback) {

let url = `https://${ offlineServers[0] }/GetOfflineData.ashx?token=${globalSettings.assistnowApiKey};gnss=${offline_gnss};format=${fmt};period=${period};resolution=1;alm=${offline_alm};`
//console.log(url);

function processOfflineData(data) {
if(globalSettings.assistnowOfflineData == null || ((Date.now() / 1000)-globalSettings.assistnowOfflineDate) > (60*60*24*3)) {
console.log("AssistnowOfflineData older than 3 days, refreshing.");
globalSettings.assistnowOfflineData = splitUbloxData(data);
globalSettings.assistnowOfflineDate = Math.floor(Date.now() / 1000);
globalSettings.saveAssistnowData();
} else {
console.log("AssitnowOfflineData newer than 3 days. Re-using.");
}
//console.log("Assitnow offline commands:" + globalSettings.assistnowOfflineData.length);
callback(globalSettings.assistnowOfflineData);
}

getBinaryData(url, processOfflineData, loadError);
//$.get(url, processOfflineData).fail(function() {GUI.alert("Error loading Offline data")});
};

self.loadAssistnowOnline = function(callback) {
//url = "https://online-live1.services.u-blox.com/GetOnlineData.ashx?token=" + online_token + ";gnss=" + gnss + ";datatype=eph,alm,aux,pos;format=" + fmt + ";"
let url = `https://${ onlineServers[0] }/GetOnlineData.ashx?token=${globalSettings.assistnowApiKey};gnss=${ gnss };datatype=eph,alm,aux,pos;format=${ fmt }`;

function processOnlineData(data) {
assistnowOnline = splitUbloxData(data);

//console.log("Assitnow online commands:" + assistnowOnline.length);
callback(assistnowOnline);
}

//$.get(url, processOnlineData).fail(function() {GUI.alert("Error loading Offline data")});
getBinaryData(url, processOnlineData, loadError);
}

self.isAssistnowDataRelevant = function(ubxMessage, cy, cm, cd) {
if ((ubxMessage[2] == 0x13 /*UBX_CLASS_MGA*/) && (ubxMessage[3] == 0x20 /*UBX_MGA_ANO*/))
{
// UBX-MGA-ANO
const payloadOffset = 6;
if (((ubxMessage[payloadOffset + 4] + 2000) == cy) && (ubxMessage[payloadOffset + 5] == cm) && (ubxMessage[payloadOffset + 6] == cd))
{
//console.log("UBX-MGA_ANO date matches");
return true;
}
} else {
//console.log("UBX-CMD: class: 0x" + ubxMessage[2].toString(16) + " id: 0x" + ubxMessage[3].toString(16));
return true;
}

return false;
}


return self;
})();


module.exports = ublox;
24 changes: 24 additions & 0 deletions locale/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -5911,5 +5911,29 @@
},
"maintenanceFlushSettingsCache": {
"message": "Flush settings cache"
},
"gpsOptions": {
"message": "GPS Options"
},
"gpsOptionsAssistnowToken": {
"message": "AssitNow Token"
},
"gpsLoadAssistnowOfflineButton": {
"message": "Load AssistNow Offline"
},
"gpsLoadAssistnowOnlineButton": {
"message": "Load AssistNow Online"
},
"gpsAssistnowStart": {
"message": "AssistNow data transfer starting..."
},
"gpsAssistnowDone": {
"message": "AssistNow data transfer complete."
},
"gpsAssistnowUpdate": {
"message": "AssistNow messages sent."
},
"gpsAssistnowLoadDataError": {
"message": "Error loading AssistNow data."
}
}
6 changes: 6 additions & 0 deletions tabs/gps.html
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,11 @@
<div class="btn save_btn">
<a class="save" href="#" data-i18n="configurationButtonSave"></a>
</div>
<div class="btn save_btn">
<a class="loadAssistnowOnline" href="#" data-i18n="gpsLoadAssistnowOnlineButton"></a>
</div>
<div class="btn save_btn">
<a class="loadAssistnowOffline" href="#" data-i18n="gpsLoadAssistnowOfflineButton"></a>
</div>
</div>
</div>
Loading
Loading