Skip to content

Commit 9c2b8aa

Browse files
committed
Now also forward manufacturer data with Espruino's manufacturer ID in a specific way
1 parent 92c9fda commit 9c2b8aa

File tree

2 files changed

+88
-36
lines changed

2 files changed

+88
-36
lines changed

README.md

+67-30
Original file line numberDiff line numberDiff line change
@@ -142,33 +142,88 @@ can then connect to any Bluetooth LE device within range of EspruinoHub.
142142
you could use [TinyDash](https://github.com/espruino/TinyDash) with the code
143143
from `www/mqtt.html` to display the latest BLE data that you have received.
144144

145+
### MQTT / Node-RED
145146

146-
### Node-RED / MQTT
147-
148-
You can access Node-RED using `http://localhost:1880`
147+
If set up, you can access Node-RED using `http://localhost:1880`
149148

150149
Once you add UI elements and click `Deploy` they'll be visible at `http://localhost:1880/ui`
151150

152151
The easiest way to get data is to add an MQTT listener node that requests
153152
`/ble/advertise/#` (`#` is a wildcard). This will output all information received
154-
via advertising.
153+
via advertising (see 'Advertising Data' below).
154+
155+
For more info on available MQTT commands see the 'MQTT Bridge' section below.
156+
157+
Check out http://www.espruino.com/Puck.js+Node-RED for a proper introduction
158+
on using Node-RED.
159+
160+
### MQTT Command-line
161+
162+
You can use the Mosquitto command-line tools to send and receive MQTT data
163+
that will make `EspruinoHub` do things:
164+
165+
```
166+
# listen to all, verbose
167+
mosquitto_sub -h localhost -t "/#" -v
168+
169+
# listen to any device advertising a 1809 temperature characteristic and
170+
# output *just* the temperature
171+
mosquitto_sub -h localhost -t "/ble/advertise/+/temp"
172+
173+
# Test publish
174+
mosquitto_pub -h localhost -t test/topic -m "Hello world"
175+
```
176+
177+
For more info on available MQTT commands see the 'MQTT Bridge' section below.
178+
179+
180+
MQTT bridge
181+
-----------
182+
183+
### Advertising
155184

156-
Useful MQTT advertising parts are:
185+
Data that is received via bluetooth advertising will be relayed over MQTT in the following format:
157186

158187
* `/ble/presence/DEVICE` - 1 or 0 depending on whether device has been seen or not
159188
* `/ble/advertise/DEVICE` - JSON for device's broadcast name, rssi and manufacturer-specific data
160-
* `/ble/advertise/DEVICE/manufacturer/COMPANY` - Manufacturer-specific data (without leading company code)
189+
* `/ble/advertise/DEVICE/manufacturer/COMPANY` - Manufacturer-specific data (without leading company code) encoded in base16. To decode use `var data = Buffer.from(msg.payload, 'hex');`
161190
* `/ble/advertise/DEVICE/rssi` - Device signal strength
162191
* `/ble/advertise/DEVICE/SERVICE` - Raw service data (as a JSON Array of bytes)
163-
* `/ble/advertise/DEVICE/PRETTY` or `/ble/PRETTY/DEVICE` - Decoded service data. `temp` is the obvious one
164-
165-
To decode the hex-encoded manufacturer-specific data, try:
192+
* `/ble/advertise/DEVICE/PRETTY` or `/ble/PRETTY/DEVICE` - Decoded service data based on the decoding in `attributes.js`
193+
* `1809` decodes to `temp` (Temperature in C)
194+
* `180f` decodes to `battery`
195+
* `feaa` decodes to `url` (Eddystone)
196+
* `2a6d` decodes to `pressure` (Pressure in pa)
197+
* `2a6e` decodes to `temp` (Temperature in C)
198+
* `2a6f` decodes to `humidity` (Humidity in %)
199+
* `ffff` decodes to `data` (This is not a standard - however it's useful for debugging or quick tests)
200+
* `/ble/advertise/DEVICE/espruino` - If manufacturer data is broadcast Espruino's manufacturer ID `0x0590` **and** it is valid JSON, it is rebroadcast. If an object like `{"a":5,"b":10}` is sent, `/ble/advertise/DEVICE/a` and `/ble/advertise/DEVICE/b` will also be sent.
201+
202+
You can take advantage of Espruino's manufacturer ID `0x0590` to relay JSON over
203+
Bluetooth LE advertising using the following code on an Espruino board:
166204

167205
```
168-
var data = Buffer.from(msg.payload.manufacturerData, 'hex');
206+
var data = {a:1,b:2};
207+
NRF.setAdvertising({},{
208+
showName:false,
209+
manufacturer:0x0590,
210+
manufacturerData:JSON.stringify(data)
211+
});
169212
```
170213

171-
You can also connect to a device:
214+
This will create the folling MQTT topics:
215+
216+
* `/ble/advertise/fd:ee:e9:b7:6a:40/espruino` -> `{"a":10,"b":15}`
217+
* `/ble/advertise/fd:ee:e9:b7:6a:40/a` -> `1`
218+
* `/ble/advertise/fd:ee:e9:b7:6a:40/b` -> `2`
219+
220+
Note that **you only have 24 characters available for JSON**, so try to use
221+
the shortest field names possible and avoid floating point values that can
222+
be very long when converted to a String.
223+
224+
### Connections
225+
226+
You can also connect to a device using MQTT packets:
172227

173228
* `/ble/write/DEVICE/SERVICE/CHARACTERISTIC` connects and writes to the charactertistic
174229
* `/ble/read/DEVICE/SERVICE/CHARACTERISTIC` connects and reads from the charactertistic
@@ -193,25 +248,7 @@ on a Puck.js BLE UART connection with:
193248

194249
Once a `/ble/write/DEVICE/SERVICE/CHARACTERISTIC` has been executed, a `/ble/written/DEVICE/SERVICE/CHARACTERISTIC` packet will be sent in response.
195250

196-
**You can also gather historical data over MQTT - see the `History` section
197-
below.**
198-
199-
### MQTT Command-line
200-
201-
These commands use the Mosquitto command-line tools:
202-
203-
```
204-
# listen to all, verbose
205-
mosquitto_sub -h localhost -t /# -v
206-
207-
# Test publish
208-
mosquitto_pub -h localhost -t test/topic -m "Hello world"
209-
```
210-
211-
You can use the commands in the section above to make things happen from the command-line.
212-
213-
History
214-
-------
251+
### History
215252

216253
EspruinoHub contains code (`libs/history.js`) that subscribes to any MQTT data
217254
beginning with `/ble/` and that then stores logs of the average value

lib/discovery.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ function onDiscovery(peripheral) {
8888

8989
// Split out the manufacturer specific data
9090
mqtt.send("/ble/advertise/"+id+"/manufacturer/"+manu, JSON.stringify(rest));
91+
if (manu=="0590") {
92+
var str = "";
93+
for (var i=0;i<rest.length;i+=2)
94+
str += String.fromCharCode(parseInt(rest.substr(i,2),16));
95+
var j;
96+
try {
97+
j = JSON.parse(str);
98+
mqtt.send("/ble/advertise/"+id+"/espruino", str);
99+
if ("object"==typeof j)
100+
for (var key in j)
101+
mqtt.send("/ble/advertise/"+id+"/"+key, JSON.stringify(j[key]));
102+
} catch (e) {
103+
// it's not valid JSON, leave it
104+
}
105+
}
91106
}
92107
else {
93108
// No manufacturer specific data
@@ -144,21 +159,21 @@ function checkIfBroken() {
144159
if (packetsReceived==0 && lastPacketsReceived==0) {
145160
log("BLE broken? No advertising packets in "+ config.ble_timeout +" seconds - restarting!");
146161
process.exit(1);
147-
}
162+
}
148163
} else {
149164
packetsReceived = 1; // don't restart as we were supposed to not be advertising
150-
}
165+
}
151166
lastPacketsReceived = packetsReceived;
152167
packetsReceived = 0;
153168
}
154169

155170
exports.init = function() {
156171
noble.on('stateChange', onStateChange);
157172
noble.on('discover', onDiscovery);
158-
noble.on('scanStart', function() {
159-
isScanning=true;
173+
noble.on('scanStart', function() {
174+
isScanning=true;
160175
scanStartTime = Date.now();
161-
log("Scanning started.");
176+
log("Scanning started.");
162177
});
163178
noble.on('scanStop', function() { isScanning=false; log("Scanning stopped.");});
164179
setInterval(checkForPresence, 1000);
@@ -174,7 +189,7 @@ exports.restartScan = function() {
174189
}
175190
}
176191

177-
exports.stopScan = function() {
192+
exports.stopScan = function() {
178193
if (isScanning) {
179194
noble.stopScanning();
180195
}

0 commit comments

Comments
 (0)