Last active
February 11, 2020 21:57
-
-
Save birkir/e2010a37917b9cd4e9f9bf693880cdc4 to your computer and use it in GitHub Desktop.
GPS Plugin for BMW ibus interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This plugin will emit events with GPS coordinates | |
* | |
* const gps = new GPSPlugin(); | |
* gps.on('gps', ({ lat, lng, alt }) => console.log(lat, lng, alt)); | |
* MINI.addPlugin(gps); | |
*/ | |
class GPSPlugin { | |
/** | |
* @var {bool} Flag determines if GPS has a fix or not. | |
*/ | |
isFixed = false; | |
/** | |
* @var {object} List of attached events. | |
*/ | |
events = { | |
gps: () => {}, | |
}; | |
/** | |
* Attach a event listener | |
* | |
* @todo Use event emitter | |
* @param {string} Name of event | |
* @param {function} Callback function | |
*/ | |
on(name, cb) { | |
this.events[name] = cb; | |
} | |
/** | |
* Check if last bit in byte is true | |
* | |
* 0000 0101 -> true | |
* 1100 -> false | |
* | |
* @param {byte} | |
* @return {bool} | |
*/ | |
toBool(byte) { | |
return Boolean(+(byte >>> 0).toString(2).split('').pop()); | |
} | |
/** | |
* Convert 5 bytes to a single coordinate | |
* | |
* 00 36 42 06 61 = 0036°42'06.6" = -36.88516666666666 | |
* | |
* @param {array} Bytes of [deg0, deg1, minutes, fragment+signed] | |
* @return {float} /-?0+\.0+/ | |
*/ | |
toDD(bytes) { | |
const deg = Number(bytes.slice(0, 2).map(d => d.toString(16)).join('')); | |
const min = Number(bytes[2].toString(16)); | |
const frag = String(bytes[4].toString(16))[0] / 10; | |
const sec = Number(bytes[3].toString(16)) + frag; | |
const signed = this.toBool(bytes[4].toString(16)); | |
const dd = deg + min / 60 + sec / (60 * 60); | |
console.log(deg, min, sec, frag, signed, dd); | |
return signed ? -dd : dd; | |
} | |
/** | |
* Convert three bytes to UTC Date | |
* 06 13 49 = 06:13:49 (hh:mm:ss) | |
* @param {array} | |
* @return {Date} | |
*/ | |
toUTC([hh, mm, ss]) { | |
const date = new Date(); | |
date.setHours(hh.toString(16)); | |
date.setMinutes(mm.toString(16)); | |
date.setSeconds(ss.toString(16)); | |
return date; | |
} | |
/** | |
* Fired from ibus driver. | |
* @param {object} IBus message | |
* @return {void} | |
*/ | |
onMessage({ src, dst, msg }) { | |
if (src === 0x7F && dst === 0xC8) { | |
if (msg[0] === 0xA2) { | |
// Check if GPS has a fix or not | |
this.isFixed = this.toBool(msg[1]); | |
// Parse latitude | |
const lat = this.toDD(msg.slice(2, 7)); | |
// Parse longitude | |
const lng = this.toDD(msg.slice(7, 12)); | |
// Cast two bytes to 16 bit integer | |
const alt = (msg[12] << 8) + msg[13]; | |
// Parse UTC date | |
const utc = this.toUTC(msg.slice(15, 18)); | |
// Dispatch the event | |
this.events.gps({ lat, lng, alt, utc }); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment