add GPS Time Server
parent
ae5b7ba7b9
commit
24c84f9ba6
12
apps.json
12
apps.json
|
|
@ -2369,5 +2369,17 @@
|
||||||
{"name":"isoclock.app.js","url":"isoclock.js"},
|
{"name":"isoclock.app.js","url":"isoclock.js"},
|
||||||
{"name":"isoclock.img","url":"isoclock-icon.js","evaluate":true}
|
{"name":"isoclock.img","url":"isoclock-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{ "id": "gpstimeserver",
|
||||||
|
"name": "GPS Time Server",
|
||||||
|
"icon": "widget.png",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "A widget which automatically starts the GPS and turns Bangle.js into a Bluetooth time server.",
|
||||||
|
"tags": "widget",
|
||||||
|
"type": "widget",
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{"name":"gpstimeserver.wid.js","url":"widget.js"}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: New Widget!
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
# GPS Time Server
|
||||||
|
|
||||||
|
A widget which automatically starts the GPS and turns Bangle.js into a Bluetooth time server, UUID 0x1805.
|
||||||
|
|
||||||
|
Other Espruino Bluetooth devices can then find it and use it to synchronise time.
|
||||||
|
|
||||||
|
**Note:** Because GPS is kept on, you'll need to keep your Bangle.js on charge for this to be useful.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Just install this widget, and from then on any app which loads widgets will
|
||||||
|
display the icon  in the top left, and Bangle.js will be
|
||||||
|
broadcasting the current time to any device that connects.
|
||||||
|
|
||||||
|
## Technical
|
||||||
|
|
||||||
|
This implements the [Bluetooth Time Service](https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=292957) listed [here](https://www.bluetooth.com/specifications/gatt/).
|
||||||
|
|
||||||
|
The Bluetooth docs are verbose and hard to read, so here's a rundown of how it works.
|
||||||
|
|
||||||
|
* The Bangle advertises service `0x1805`
|
||||||
|
* You connect to it, and request service `0x1805` and characteristic `0x2A2B`
|
||||||
|
* A 10 byte array is returned:
|
||||||
|
|
||||||
|
```
|
||||||
|
[
|
||||||
|
year_lowbyte,
|
||||||
|
year_highbyte,
|
||||||
|
month,
|
||||||
|
day_of_month,
|
||||||
|
hours,
|
||||||
|
minutes,
|
||||||
|
seconds,
|
||||||
|
day_of_week, // 1=monday...7=sunday
|
||||||
|
subseconds, // 0..255
|
||||||
|
update_reason // 0=unknown currently
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
//NRF.requestDevice({ filters: [{ services: ['1805'] }] }).then(print)
|
||||||
|
|
||||||
|
var gatt;
|
||||||
|
NRF.connect("c7:4b:2e:c6:f5:45 random").then(function(g) {
|
||||||
|
gatt = g;
|
||||||
|
return gatt.getPrimaryService("1805");
|
||||||
|
}).then(function(service) {
|
||||||
|
return service.getCharacteristic("2A2B");
|
||||||
|
}).then(function(c) {
|
||||||
|
return c.readValue();
|
||||||
|
}).then(function(d) {
|
||||||
|
console.log("Got:", JSON.stringify(d.buffer));
|
||||||
|
var year = d.getUint16(0,1);
|
||||||
|
// ...
|
||||||
|
gatt.disconnect();
|
||||||
|
}).catch(function(e) {
|
||||||
|
console.log("Something's broken.",e);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
(() => {
|
||||||
|
|
||||||
|
function getBLECurrentTimeData(d) {
|
||||||
|
var updateReason = 0; // unknown update reason
|
||||||
|
return [
|
||||||
|
d.getFullYear()&0xFF,
|
||||||
|
d.getFullYear()>>8,
|
||||||
|
d.getMonth()+1,
|
||||||
|
d.getDate(),
|
||||||
|
d.getHours(),
|
||||||
|
d.getMinutes(),
|
||||||
|
d.getSeconds(),
|
||||||
|
d.getDay() ? d.getDay() : 7/*sunday*/,
|
||||||
|
Math.floor(d.getMilliseconds()*255/1000),
|
||||||
|
updateReason
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
NRF.setServices({
|
||||||
|
0x1805 : {
|
||||||
|
0x2A2B : {
|
||||||
|
value : getBLECurrentTimeData(new Date()),
|
||||||
|
readable : true,
|
||||||
|
notify : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, { advertise: [ '1805' ] });
|
||||||
|
|
||||||
|
Bangle.on('GPS', function(fix) {
|
||||||
|
if (fix.time !== undefined) {
|
||||||
|
NRF.updateServices({
|
||||||
|
0x1805 : {
|
||||||
|
0x2A2B : {
|
||||||
|
value : getBLECurrentTimeData(fix.time),
|
||||||
|
notify : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Bangle.setGPSPower(1);
|
||||||
|
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
g.reset();
|
||||||
|
g.drawImage(require("heatshrink").decompress(atob("i0XxH+CR0HhEHEyEOi1AAAMWhAUNisW6/XwICBi0PHpgUC69WAYUWIpcVxAVGsgsLi2sCAOsg4EDiwVPlZYCCoUzss6IwxBE68rDYJBBldlAAVeNpIADNoNdxIWDssrCYMJgKZDF4SZCxGtCollmcJAALFDnTFE1utxNdrtXq9WqwVDeJAVB1tdrwABFgM6maOKwQWCIQgbBmQVJmQVCCwlXF4LoKCoaHDCoSgFAAldCwYtCqxbCLRQVECwNWr4VBr4VJmYWFrpcDCpM6neJC4pdCChEsss7C4+IFRI4DC4LBKCpBQLAAgA=")), this.x, this.y);
|
||||||
|
}
|
||||||
|
WIDGETS["gpstimeserver"]={
|
||||||
|
area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right)
|
||||||
|
width: 24, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout
|
||||||
|
draw:draw // called to draw the widget
|
||||||
|
};
|
||||||
|
})()
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
Loading…
Reference in New Issue