@stoprocent/bleno 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jshintrc +5 -0
- package/LICENSE +20 -0
- package/README.md +409 -0
- package/binding.gyp +17 -0
- package/examples/battery-service/README.md +14 -0
- package/examples/battery-service/battery-level-characteristic.js +45 -0
- package/examples/battery-service/battery-service.js +16 -0
- package/examples/battery-service/main.js +28 -0
- package/examples/battery-service/package-lock.json +1314 -0
- package/examples/battery-service/package.json +20 -0
- package/examples/blink1/README.md +44 -0
- package/examples/blink1/blink1-fade-rgb-characteristic.js +42 -0
- package/examples/blink1/blink1-rgb-characteristic.js +38 -0
- package/examples/blink1/blink1-service.js +19 -0
- package/examples/blink1/device-information-service.js +19 -0
- package/examples/blink1/hardware-revision-characteristic.js +32 -0
- package/examples/blink1/main.js +32 -0
- package/examples/blink1/serial-number-characteristic.js +21 -0
- package/examples/echo/characteristic.js +45 -0
- package/examples/echo/main.js +33 -0
- package/examples/pizza/README.md +16 -0
- package/examples/pizza/peripheral.js +57 -0
- package/examples/pizza/pizza-bake-characteristic.js +40 -0
- package/examples/pizza/pizza-crust-characteristic.js +52 -0
- package/examples/pizza/pizza-service.js +20 -0
- package/examples/pizza/pizza-toppings-characteristic.js +41 -0
- package/examples/pizza/pizza.js +58 -0
- package/examples/uart/main.js +23 -0
- package/index.d.ts +153 -0
- package/index.js +1 -0
- package/lib/bleno.js +231 -0
- package/lib/characteristic.js +91 -0
- package/lib/descriptor.js +17 -0
- package/lib/hci-socket/acl-stream.js +37 -0
- package/lib/hci-socket/bindings.js +219 -0
- package/lib/hci-socket/crypto.js +74 -0
- package/lib/hci-socket/gap.js +212 -0
- package/lib/hci-socket/gatt.js +1028 -0
- package/lib/hci-socket/hci-status.json +67 -0
- package/lib/hci-socket/hci.js +796 -0
- package/lib/hci-socket/mgmt.js +89 -0
- package/lib/hci-socket/smp.js +160 -0
- package/lib/hci-socket/vs.js +156 -0
- package/lib/mac/binding.gyp +39 -0
- package/lib/mac/bindings.js +12 -0
- package/lib/mac/src/ble_peripheral_manager.h +32 -0
- package/lib/mac/src/ble_peripheral_manager.mm +241 -0
- package/lib/mac/src/bleno_mac.h +26 -0
- package/lib/mac/src/bleno_mac.mm +167 -0
- package/lib/mac/src/callbacks.h +76 -0
- package/lib/mac/src/callbacks.mm +124 -0
- package/lib/mac/src/napi_objc.h +30 -0
- package/lib/mac/src/napi_objc.mm +286 -0
- package/lib/mac/src/noble_mac.h +34 -0
- package/lib/mac/src/noble_mac.mm +260 -0
- package/lib/mac/src/objc_cpp.h +27 -0
- package/lib/mac/src/objc_cpp.mm +144 -0
- package/lib/mac/src/peripheral.h +23 -0
- package/lib/primary-service.js +19 -0
- package/lib/resolve-bindings.js +19 -0
- package/lib/uuid-util.js +7 -0
- package/package.json +77 -0
- package/prebuilds/android-arm/node.napi.armv7.node +0 -0
- package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
- package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
- package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
- package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
- package/prebuilds/linux-x64/node.napi.musl.node +0 -0
- package/prebuilds/win32-ia32/node.napi.node +0 -0
- package/prebuilds/win32-x64/node.napi.node +0 -0
- package/test/characteristic.test.js +174 -0
- package/test/descriptor.test.js +46 -0
- package/test/mocha.setup.js +0 -0
- package/with-bindings.js +5 -0
- package/with-custom-binding.js +6 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "battery-service",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "BLE (Bluetooth Low Energy) Battery Service",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=0.10"
|
|
8
|
+
},
|
|
9
|
+
"os": [
|
|
10
|
+
"darwin",
|
|
11
|
+
"linux"
|
|
12
|
+
],
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "Don Coleman",
|
|
15
|
+
"url": "https://github.com/don"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@abandonware/bleno": "~0.5.1-3"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
bleno - [blink(1)](http://thingm.com/products/blink-1/) example
|
|
2
|
+
===============================================
|
|
3
|
+
This example allows you to control a [ThingM](http://thingm.com/) [blink(1)](http://thingm.com/products/blink-1/) via BLE.
|
|
4
|
+
|
|
5
|
+
It uses bleno and [node-blink1](https://github.com/sandeepmistry/node-blink1) and requires a blink(1) to be connected via USB.
|
|
6
|
+
|
|
7
|
+
See [main file](https://github.com/sandeepmistry/bleno/blob/master/examples/blink1/main.js) for entry point.
|
|
8
|
+
|
|
9
|
+
[Device Information service](https://github.com/sandeepmistry/bleno/blob/master/examples/blink1/device-information-service.js)
|
|
10
|
+
-----------------------------------
|
|
11
|
+
|
|
12
|
+
UUID: [0x180A](https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml)
|
|
13
|
+
|
|
14
|
+
__Characteristics:__
|
|
15
|
+
|
|
16
|
+
* [Serial Number](https://github.com/sandeepmistry/bleno/blob/master/examples/blink1/serial-number-characteristic.js)
|
|
17
|
+
* UUID: [0x2a25](https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.serial_number_string.xml)
|
|
18
|
+
* Properties: read
|
|
19
|
+
* Description: read the blink(1)'s serial number
|
|
20
|
+
|
|
21
|
+
* [Hardware Revision](https://github.com/sandeepmistry/bleno/blob/master/examples/blink1/hardware-revision-characteristic.js)
|
|
22
|
+
* UUID: [0x2a27](https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.hardware_revision_string.xml)
|
|
23
|
+
* Properties: read
|
|
24
|
+
* Description: read the blink(1)'s version
|
|
25
|
+
|
|
26
|
+
blink(1) service
|
|
27
|
+
--------------------
|
|
28
|
+
UUID: 0x01010101010101010101010101010101
|
|
29
|
+
|
|
30
|
+
__Characteristics:__
|
|
31
|
+
|
|
32
|
+
* [RGB](https://github.com/sandeepmistry/bleno/blob/master/examples/blink1/blink1-rgb-characteristic.js)
|
|
33
|
+
* UUID: 01010101010101010101010101524742
|
|
34
|
+
* Properties: write, write without response
|
|
35
|
+
* Description: Set the blink(1)'s color
|
|
36
|
+
* Data format is: RRGGBB (3 bytes) - single byte for each color
|
|
37
|
+
|
|
38
|
+
* [Fade RGB](https://github.com/sandeepmistry/bleno/blob/master/examples/blink1/blink1-fade-rgb-characteristic.js)
|
|
39
|
+
* UUID: 01010101010101010166616465524742
|
|
40
|
+
* Properties: write, write without response, notify
|
|
41
|
+
* Description: Fade the blink(1)'s color and notication when fade is complete
|
|
42
|
+
* Data format is: TTTTRRGGBB (5 bytes)
|
|
43
|
+
* TTTT - fade time in milliseconds (Little Endian)
|
|
44
|
+
* RRGGBB (3 bytes) - single byte for each color
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const BlenoCharacteristic = bleno.Characteristic;
|
|
3
|
+
const BlenoDescriptor = bleno.Descriptor;
|
|
4
|
+
|
|
5
|
+
class Blink1FaceRGBCharacteristic extends BlenoCharacteristic {
|
|
6
|
+
constructor (blink1) {
|
|
7
|
+
super({
|
|
8
|
+
uuid: '01010101010101010166616465524742',
|
|
9
|
+
properties: ['write', 'writeWithoutResponse', 'notify'],
|
|
10
|
+
descriptors: [
|
|
11
|
+
new BlenoDescriptor({
|
|
12
|
+
uuid: '2901',
|
|
13
|
+
value: 'fade blink(1) RGB value'
|
|
14
|
+
})
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
this.blink1 = blink1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
onWriteRequest (data, offset, withoutResponse, callback) {
|
|
22
|
+
if (offset) {
|
|
23
|
+
callback(this.RESULT_ATTR_NOT_LONG);
|
|
24
|
+
} else if (data.length !== 5) {
|
|
25
|
+
callback(this.RESULT_INVALID_ATTRIBUTE_LENGTH);
|
|
26
|
+
} else {
|
|
27
|
+
const fadeMillis = data.readUInt16LE(0);
|
|
28
|
+
const r = data.readUInt8(2);
|
|
29
|
+
const g = data.readUInt8(3);
|
|
30
|
+
const b = data.readUInt8(4);
|
|
31
|
+
|
|
32
|
+
this.blink1.fadeToRGB(fadeMillis, r, g, b, () => {
|
|
33
|
+
if (this.updateValueCallback) {
|
|
34
|
+
this.updateValueCallback(Buffer.from([r, g, b]));
|
|
35
|
+
}
|
|
36
|
+
callback(this.RESULT_SUCCESS);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = Blink1FaceRGBCharacteristic;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const BlenoCharacteristic = bleno.Characteristic;
|
|
3
|
+
const BlenoDescriptor = bleno.Descriptor;
|
|
4
|
+
|
|
5
|
+
class Blink1RGBCharacteristic extends BlenoCharacteristic {
|
|
6
|
+
constructor (blink1) {
|
|
7
|
+
super({
|
|
8
|
+
uuid: '01010101010101010101010101524742',
|
|
9
|
+
properties: ['write', 'writeWithoutResponse'],
|
|
10
|
+
descriptors: [
|
|
11
|
+
new BlenoDescriptor({
|
|
12
|
+
uuid: '2901',
|
|
13
|
+
value: 'set blink(1) RGB value'
|
|
14
|
+
})
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
this.blink1 = blink1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
onWriteRequest (data, offset, withoutResponse, callback) {
|
|
22
|
+
if (offset) {
|
|
23
|
+
callback(this.RESULT_ATTR_NOT_LONG);
|
|
24
|
+
} else if (data.length !== 3) {
|
|
25
|
+
callback(this.RESULT_INVALID_ATTRIBUTE_LENGTH);
|
|
26
|
+
} else {
|
|
27
|
+
const r = data.readUInt8(0);
|
|
28
|
+
const g = data.readUInt8(1);
|
|
29
|
+
const b = data.readUInt8(2);
|
|
30
|
+
|
|
31
|
+
this.blink1.setRGB(r, g, b, () => {
|
|
32
|
+
callback(this.RESULT_SUCCESS);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = Blink1RGBCharacteristic;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const BlenoPrimaryService = bleno.PrimaryService;
|
|
3
|
+
|
|
4
|
+
const Blink1RGBCharacteristic = require('./blink1-rgb-characteristic');
|
|
5
|
+
const Blink1FadeRGBCharacteristic = require('./blink1-fade-rgb-characteristic');
|
|
6
|
+
|
|
7
|
+
class Blink1Service extends BlenoPrimaryService {
|
|
8
|
+
constructor (blink1) {
|
|
9
|
+
super({
|
|
10
|
+
uuid: '01010101010101010101010101010101',
|
|
11
|
+
characteristics: [
|
|
12
|
+
new Blink1RGBCharacteristic(blink1),
|
|
13
|
+
new Blink1FadeRGBCharacteristic(blink1)
|
|
14
|
+
]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = Blink1Service;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const BlenoPrimaryService = bleno.PrimaryService;
|
|
3
|
+
|
|
4
|
+
const SerialNumberCharacteristic = require('./serial-number-characteristic');
|
|
5
|
+
const HardwareRevisionCharacteristic = require('./hardware-revision-characteristic');
|
|
6
|
+
|
|
7
|
+
class DeviceInformationService extends BlenoPrimaryService {
|
|
8
|
+
constructor (blink1) {
|
|
9
|
+
super({
|
|
10
|
+
uuid: '180a',
|
|
11
|
+
characteristics: [
|
|
12
|
+
new SerialNumberCharacteristic(blink1),
|
|
13
|
+
new HardwareRevisionCharacteristic(blink1)
|
|
14
|
+
]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = DeviceInformationService;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const BlenoCharacteristic = bleno.Characteristic;
|
|
3
|
+
const BlenoDescriptor = bleno.Descriptor;
|
|
4
|
+
|
|
5
|
+
class HardwareRevisionCharacteristic extends BlenoCharacteristic {
|
|
6
|
+
constructor (blink1) {
|
|
7
|
+
super({
|
|
8
|
+
uuid: '2a27',
|
|
9
|
+
properties: ['read'],
|
|
10
|
+
descriptors: [
|
|
11
|
+
new BlenoDescriptor({
|
|
12
|
+
uuid: '2901',
|
|
13
|
+
value: 'blink(1) version'
|
|
14
|
+
})
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
this.blink1 = blink1;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
onReadRequest (offset, callback) {
|
|
22
|
+
if (offset) {
|
|
23
|
+
callback(this.RESULT_ATTR_NOT_LONG, null);
|
|
24
|
+
} else {
|
|
25
|
+
this.blink1.version((version) => {
|
|
26
|
+
callback(this.RESULT_SUCCESS, Buffer.from(version));
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = HardwareRevisionCharacteristic;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const Blink1 = require('node-blink1');
|
|
2
|
+
|
|
3
|
+
const bleno = require('../..');
|
|
4
|
+
|
|
5
|
+
const DeviceInformationService = require('./device-information-service');
|
|
6
|
+
const Blink1Service = require('./blink1-service');
|
|
7
|
+
|
|
8
|
+
const blink1 = new Blink1();
|
|
9
|
+
|
|
10
|
+
const deviceInformationService = new DeviceInformationService(blink1);
|
|
11
|
+
const blink1Service = new Blink1Service(blink1);
|
|
12
|
+
|
|
13
|
+
bleno.on('stateChange', function (state) {
|
|
14
|
+
console.log('on -> stateChange: ' + state);
|
|
15
|
+
|
|
16
|
+
if (state === 'poweredOn') {
|
|
17
|
+
bleno.startAdvertising('blink1', [blink1Service.uuid]);
|
|
18
|
+
} else {
|
|
19
|
+
bleno.stopAdvertising();
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
bleno.on('advertisingStart', function (error) {
|
|
24
|
+
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));
|
|
25
|
+
|
|
26
|
+
if (!error) {
|
|
27
|
+
bleno.setServices([
|
|
28
|
+
deviceInformationService,
|
|
29
|
+
blink1Service
|
|
30
|
+
]);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const BlenoCharacteristic = bleno.Characteristic;
|
|
3
|
+
const BlenoDescriptor = bleno.Descriptor;
|
|
4
|
+
|
|
5
|
+
class SerialNumberCharacteristic extends BlenoCharacteristic {
|
|
6
|
+
constructor (blink1) {
|
|
7
|
+
super({
|
|
8
|
+
uuid: '2a25',
|
|
9
|
+
properties: ['read'],
|
|
10
|
+
value: Buffer.from(blink1.serialNumber),
|
|
11
|
+
descriptors: [
|
|
12
|
+
new BlenoDescriptor({
|
|
13
|
+
uuid: '2901',
|
|
14
|
+
value: 'blink(1) serial number'
|
|
15
|
+
})
|
|
16
|
+
]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = SerialNumberCharacteristic;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
|
|
3
|
+
const BlenoCharacteristic = bleno.Characteristic;
|
|
4
|
+
|
|
5
|
+
class EchoCharacteristic extends BlenoCharacteristic {
|
|
6
|
+
constructor () {
|
|
7
|
+
super({
|
|
8
|
+
uuid: 'ec0e',
|
|
9
|
+
properties: ['read', 'write', 'notify'],
|
|
10
|
+
value: null
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
this._value = Buffer.alloc(0);
|
|
14
|
+
this._updateValueCallback = null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
onReadRequest (offset, callback) {
|
|
18
|
+
console.log('EchoCharacteristic - onReadRequest: value = ' + this._value.toString('hex'));
|
|
19
|
+
callback(this.RESULT_SUCCESS, this._value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
onWriteRequest (data, offset, withoutResponse, callback) {
|
|
23
|
+
this._value = data;
|
|
24
|
+
console.log('EchoCharacteristic - onWriteRequest: value = ' + this._value.toString('hex'));
|
|
25
|
+
|
|
26
|
+
if (this._updateValueCallback) {
|
|
27
|
+
console.log('EchoCharacteristic - onWriteRequest: notifying');
|
|
28
|
+
this._updateValueCallback(this._value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
callback(this.RESULT_SUCCESS);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
onSubscribe (maxValueSize, updateValueCallback) {
|
|
35
|
+
console.log('EchoCharacteristic - onSubscribe');
|
|
36
|
+
this._updateValueCallback = updateValueCallback;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
onUnsubscribe () {
|
|
40
|
+
console.log('EchoCharacteristic - onUnsubscribe');
|
|
41
|
+
this._updateValueCallback = null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = EchoCharacteristic;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
|
|
3
|
+
const BlenoPrimaryService = bleno.PrimaryService;
|
|
4
|
+
|
|
5
|
+
const EchoCharacteristic = require('./characteristic');
|
|
6
|
+
|
|
7
|
+
console.log('bleno - echo');
|
|
8
|
+
|
|
9
|
+
bleno.on('stateChange', function (state) {
|
|
10
|
+
console.log('on -> stateChange: ' + state);
|
|
11
|
+
|
|
12
|
+
if (state === 'poweredOn') {
|
|
13
|
+
bleno.setAddress('11:22:44:55:99:10');
|
|
14
|
+
bleno.startAdvertising('echo', ['ec00']);
|
|
15
|
+
} else {
|
|
16
|
+
bleno.stopAdvertising();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
bleno.on('advertisingStart', function (error) {
|
|
21
|
+
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));
|
|
22
|
+
|
|
23
|
+
if (!error) {
|
|
24
|
+
bleno.setServices([
|
|
25
|
+
new BlenoPrimaryService({
|
|
26
|
+
uuid: 'ec00',
|
|
27
|
+
characteristics: [
|
|
28
|
+
new EchoCharacteristic()
|
|
29
|
+
]
|
|
30
|
+
})
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# BLE Pizza Service
|
|
2
|
+
|
|
3
|
+
This is an example program demonstrating BLE connectivity between a peripheral running bleno, and a central running noble.
|
|
4
|
+
|
|
5
|
+
The service represents a robotic pizza oven, with the following characteristics:
|
|
6
|
+
|
|
7
|
+
* crust - read / write. A value representing the type of pizza crust (normal, thin, or deep dish)
|
|
8
|
+
* toppings - read / write. A value representing which toppings to include (pepperoni, mushrooms, extra cheese, etc.)
|
|
9
|
+
* bake - write / notify. The value written is the temperature at which to bake the pizza. When baking is finished, the central is notified with a bake result (half baked, crispy, burnt, etc.)
|
|
10
|
+
|
|
11
|
+
To run the peripheral example:
|
|
12
|
+
|
|
13
|
+
node peripheral
|
|
14
|
+
|
|
15
|
+
And on another computer, connect as a central from [noble](https://github.com/sandeepmistry/noble/tree/master/examples/pizza).
|
|
16
|
+
You can also use a [web app](http://strangesast.github.io/bleno-web-pizza-example) using [Web Bluetooth](https://developers.google.com/web/updates/2015/07/interact-with-ble-devices-on-the-web).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Require bleno peripheral library.
|
|
3
|
+
// https://github.com/sandeepmistry/bleno
|
|
4
|
+
//
|
|
5
|
+
const bleno = require('../..');
|
|
6
|
+
|
|
7
|
+
//
|
|
8
|
+
// Pizza
|
|
9
|
+
// * has crust
|
|
10
|
+
// * has toppings
|
|
11
|
+
// * can be baked
|
|
12
|
+
//
|
|
13
|
+
const pizza = require('./pizza');
|
|
14
|
+
|
|
15
|
+
//
|
|
16
|
+
// The BLE Pizza Service!
|
|
17
|
+
//
|
|
18
|
+
const PizzaService = require('./pizza-service');
|
|
19
|
+
|
|
20
|
+
//
|
|
21
|
+
// A name to advertise our Pizza Service.
|
|
22
|
+
//
|
|
23
|
+
const name = 'PizzaSquat';
|
|
24
|
+
const pizzaService = new PizzaService(new pizza.Pizza());
|
|
25
|
+
|
|
26
|
+
//
|
|
27
|
+
// Wait until the BLE radio powers on before attempting to advertise.
|
|
28
|
+
// If you don't have a BLE radio, then it will never power on!
|
|
29
|
+
//
|
|
30
|
+
bleno.on('stateChange', function (state) {
|
|
31
|
+
if (state === 'poweredOn') {
|
|
32
|
+
//
|
|
33
|
+
// We will also advertise the service ID in the advertising packet,
|
|
34
|
+
// so it's easier to find.
|
|
35
|
+
//
|
|
36
|
+
bleno.startAdvertising(name, [pizzaService.uuid], function (err) {
|
|
37
|
+
if (err) {
|
|
38
|
+
console.log(err);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
} else {
|
|
42
|
+
bleno.stopAdvertising();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
bleno.on('advertisingStart', function (err) {
|
|
47
|
+
if (!err) {
|
|
48
|
+
console.log('advertising...');
|
|
49
|
+
//
|
|
50
|
+
// Once we are advertising, it's time to set up our services,
|
|
51
|
+
// along with our characteristics.
|
|
52
|
+
//
|
|
53
|
+
bleno.setServices([
|
|
54
|
+
pizzaService
|
|
55
|
+
]);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
|
|
3
|
+
class PizzaBakeCharacteristic extends bleno.Characteristic {
|
|
4
|
+
constructor (pizza) {
|
|
5
|
+
super({
|
|
6
|
+
uuid: '13333333333333333333333333330003',
|
|
7
|
+
properties: ['notify', 'write'],
|
|
8
|
+
descriptors: [
|
|
9
|
+
new bleno.Descriptor({
|
|
10
|
+
uuid: '2901',
|
|
11
|
+
value: 'Bakes the pizza and notifies when done baking.'
|
|
12
|
+
})
|
|
13
|
+
]
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
this.pizza = pizza;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
onWriteRequest (data, offset, withoutResponse, callback) {
|
|
20
|
+
if (offset) {
|
|
21
|
+
callback(this.RESULT_ATTR_NOT_LONG);
|
|
22
|
+
} else if (data.length !== 2) {
|
|
23
|
+
callback(this.RESULT_INVALID_ATTRIBUTE_LENGTH);
|
|
24
|
+
} else {
|
|
25
|
+
const temperature = data.readUInt16BE(0);
|
|
26
|
+
const self = this;
|
|
27
|
+
this.pizza.once('ready', function (result) {
|
|
28
|
+
if (self.updateValueCallback) {
|
|
29
|
+
const responseData = Buffer.alloc(1);
|
|
30
|
+
responseData.writeUInt8(result, 0);
|
|
31
|
+
self.updateValueCallback(responseData);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
this.pizza.bake(temperature);
|
|
35
|
+
callback(this.RESULT_SUCCESS);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = PizzaBakeCharacteristic;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
const { PizzaCrust } = require('./pizza');
|
|
3
|
+
|
|
4
|
+
class PizzaCrustCharacteristic extends bleno.Characteristic {
|
|
5
|
+
constructor (pizza) {
|
|
6
|
+
super({
|
|
7
|
+
uuid: '13333333333333333333333333330001',
|
|
8
|
+
properties: ['read', 'write'],
|
|
9
|
+
descriptors: [
|
|
10
|
+
new bleno.Descriptor({
|
|
11
|
+
uuid: '2901',
|
|
12
|
+
value: 'Gets or sets the type of pizza crust.'
|
|
13
|
+
})
|
|
14
|
+
]
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
this.pizza = pizza;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
onWriteRequest (data, offset, withoutResponse, callback) {
|
|
21
|
+
if (offset) {
|
|
22
|
+
callback(this.RESULT_ATTR_NOT_LONG);
|
|
23
|
+
} else if (data.length !== 1) {
|
|
24
|
+
callback(this.RESULT_INVALID_ATTRIBUTE_LENGTH);
|
|
25
|
+
} else {
|
|
26
|
+
const crust = data.readUInt8(0);
|
|
27
|
+
switch (crust) {
|
|
28
|
+
case PizzaCrust.NORMAL:
|
|
29
|
+
case PizzaCrust.DEEP_DISH:
|
|
30
|
+
case PizzaCrust.THIN:
|
|
31
|
+
this.pizza.crust = crust;
|
|
32
|
+
callback(this.RESULT_SUCCESS);
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
callback(this.RESULT_UNLIKELY_ERROR);
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onReadRequest (offset, callback) {
|
|
42
|
+
if (offset) {
|
|
43
|
+
callback(this.RESULT_ATTR_NOT_LONG, null);
|
|
44
|
+
} else {
|
|
45
|
+
const data = Buffer.alloc(1);
|
|
46
|
+
data.writeUInt8(this.pizza.crust, 0);
|
|
47
|
+
callback(this.RESULT_SUCCESS, data);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = PizzaCrustCharacteristic;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
|
|
3
|
+
const PizzaCrustCharacteristic = require('./pizza-crust-characteristic');
|
|
4
|
+
const PizzaToppingsCharacteristic = require('./pizza-toppings-characteristic');
|
|
5
|
+
const PizzaBakeCharacteristic = require('./pizza-bake-characteristic');
|
|
6
|
+
|
|
7
|
+
class PizzaService extends bleno.PrimaryService {
|
|
8
|
+
constructor (pizza) {
|
|
9
|
+
super({
|
|
10
|
+
uuid: '13333333333333333333333333333337',
|
|
11
|
+
characteristics: [
|
|
12
|
+
new PizzaCrustCharacteristic(pizza),
|
|
13
|
+
new PizzaToppingsCharacteristic(pizza),
|
|
14
|
+
new PizzaBakeCharacteristic(pizza)
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = PizzaService;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const bleno = require('../..');
|
|
2
|
+
|
|
3
|
+
class PizzaToppingsCharacteristic extends bleno.Characteristic {
|
|
4
|
+
constructor (pizza) {
|
|
5
|
+
super({
|
|
6
|
+
uuid: '13333333333333333333333333330002',
|
|
7
|
+
properties: ['read', 'write'],
|
|
8
|
+
descriptors: [
|
|
9
|
+
new bleno.Descriptor({
|
|
10
|
+
uuid: '2901',
|
|
11
|
+
value: 'Gets or sets the pizza toppings.'
|
|
12
|
+
})
|
|
13
|
+
]
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
this.pizza = pizza;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
onWriteRequest (data, offset, withoutResponse, callback) {
|
|
20
|
+
if (offset) {
|
|
21
|
+
callback(this.RESULT_ATTR_NOT_LONG);
|
|
22
|
+
} else if (data.length !== 2) {
|
|
23
|
+
callback(this.RESULT_INVALID_ATTRIBUTE_LENGTH);
|
|
24
|
+
} else {
|
|
25
|
+
this.pizza.toppings = data.readUInt16BE(0);
|
|
26
|
+
callback(this.RESULT_SUCCESS);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onReadRequest (offset, callback) {
|
|
31
|
+
if (offset) {
|
|
32
|
+
callback(this.RESULT_ATTR_NOT_LONG, null);
|
|
33
|
+
} else {
|
|
34
|
+
const data = Buffer.alloc(2);
|
|
35
|
+
data.writeUInt16BE(this.pizza.toppings, 0);
|
|
36
|
+
callback(this.RESULT_SUCCESS, data);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = PizzaToppingsCharacteristic;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const events = require('events');
|
|
2
|
+
|
|
3
|
+
class Pizza extends events.EventEmitter {
|
|
4
|
+
constructor () {
|
|
5
|
+
super();
|
|
6
|
+
this.toppings = PizzaToppings.NONE;
|
|
7
|
+
this.crust = PizzaCrust.NORMAL;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
bake (temperature) {
|
|
11
|
+
const time = temperature * 10;
|
|
12
|
+
console.log('baking pizza at', temperature, 'degrees for', time, 'milliseconds');
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
const result =
|
|
15
|
+
temperature < 350
|
|
16
|
+
? PizzaBakeResult.HALF_BAKED
|
|
17
|
+
: temperature < 450
|
|
18
|
+
? PizzaBakeResult.BAKED
|
|
19
|
+
: temperature < 500
|
|
20
|
+
? PizzaBakeResult.CRISPY
|
|
21
|
+
: temperature < 600
|
|
22
|
+
? PizzaBakeResult.BURNT
|
|
23
|
+
: PizzaBakeResult.ON_FIRE;
|
|
24
|
+
this.emit('ready', result);
|
|
25
|
+
}, time);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const PizzaToppings = {
|
|
30
|
+
NONE: 0,
|
|
31
|
+
PEPPERONI: 1 << 0,
|
|
32
|
+
MUSHROOMS: 1 << 1,
|
|
33
|
+
EXTRA_CHEESE: 1 << 2,
|
|
34
|
+
BLACK_OLIVES: 1 << 3,
|
|
35
|
+
CANADIAN_BACON: 1 << 4,
|
|
36
|
+
PINEAPPLE: 1 << 5,
|
|
37
|
+
BELL_PEPPERS: 1 << 6,
|
|
38
|
+
SAUSAGE: 1 << 7
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const PizzaCrust = {
|
|
42
|
+
NORMAL: 0,
|
|
43
|
+
DEEP_DISH: 1,
|
|
44
|
+
THIN: 2
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const PizzaBakeResult = {
|
|
48
|
+
HALF_BAKED: 0,
|
|
49
|
+
BAKED: 1,
|
|
50
|
+
CRISPY: 2,
|
|
51
|
+
BURNT: 3,
|
|
52
|
+
ON_FIRE: 4
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
module.exports.Pizza = Pizza;
|
|
56
|
+
module.exports.PizzaToppings = PizzaToppings;
|
|
57
|
+
module.exports.PizzaCrust = PizzaCrust;
|
|
58
|
+
module.exports.PizzaBakeResult = PizzaBakeResult;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const bleno = require('../../with-custom-binding')({
|
|
2
|
+
bindParams: {
|
|
3
|
+
uart: {
|
|
4
|
+
port: '/dev/tty...',
|
|
5
|
+
baudRate: 1000000
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
bleno.on('stateChange', state => {
|
|
11
|
+
console.log('on -> stateChange: ' + state);
|
|
12
|
+
|
|
13
|
+
if (state === 'poweredOn') {
|
|
14
|
+
bleno.setAddress('11:22:33:44:55:66');
|
|
15
|
+
bleno.startAdvertisingIBeacon('a2744045-7004-4da9-8ed3-6d2d9a208c0a', 1234, 5678);
|
|
16
|
+
} else {
|
|
17
|
+
bleno.stopAdvertising();
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
bleno.on('advertisingStart', error => {
|
|
22
|
+
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));
|
|
23
|
+
});
|