-
-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathGattCharacteristic.js
More file actions
146 lines (127 loc) · 4.31 KB
/
Copy pathGattCharacteristic.js
File metadata and controls
146 lines (127 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const EventEmitter = require('events')
const BusHelper = require('./BusHelper')
const buildTypedValue = require('./buildTypedValue')
/**
* @classdesc GattCharacteristic class interacts with a GATT characteristic.
* @class GattCharacteristic
* @extends EventEmitter
* @see You can construct a GattCharacteristic object via {@link GattService#getCharacteristic} method.
*/
class GattCharacteristic extends EventEmitter {
constructor (dbus, adapter, device, service, characteristic) {
super()
this.dbus = dbus
this.adapter = adapter
this.device = device
this.service = service
this.characteristic = characteristic
this.helper = new BusHelper(dbus, 'org.bluez', `/org/bluez/${adapter}/${device}/${service}/${characteristic}`, 'org.bluez.GattCharacteristic1', { usePropsEvents: true })
}
/**
* 128-bit characteristic UUID.
* @returns {string}
*/
async getUUID () {
return this.helper.prop('UUID')
}
/**
* Defines how the characteristic value can be used.
* @returns {string[]}
*/
async getFlags () {
return this.helper.prop('Flags')
}
/**
* True, if notifications or indications on this characteristic are currently enabled.
* @returns {boolean}
*/
async isNotifying () {
return this.helper.prop('Notifying')
}
/**
* Read the value of the characteristic
* @param {number} [offset = 0]
* @returns {Buffer}
*/
async readValue (offset = 0) {
const options = {
offset: buildTypedValue('uint16', offset)
}
const payload = await this.helper.callMethod('ReadValue', options)
return Buffer.from(payload)
}
/**
* Write the value of the characteristic.
* @param {Buffer} value - Buffer containing the characteristic value.
* @param {number|Object} [optionsOrOffset = 0] - Starting offset or writing options.
* @param {number} [optionsOrOffset.offset = 0] - Starting offset.
* @param {WritingMode} [optionsOrOffset.type = reliable] - Writing mode
*/
async writeValue (value, optionsOrOffset = {}) {
if (!Buffer.isBuffer(value)) {
throw new Error('Only buffers can be wrote')
}
const options = typeof optionsOrOffset === 'number' ? { offset: optionsOrOffset } : optionsOrOffset
const mergedOptions = Object.assign({ offset: 0, type: 'reliable' }, options)
const callOptions = {
offset: buildTypedValue('uint16', mergedOptions.offset),
type: buildTypedValue('string', mergedOptions.type)
}
const { data } = value.toJSON()
await this.helper.callMethod('WriteValue', data, callOptions)
}
/**
* Write the value of the characteristic without waiting for the response.
* @param {Buffer} value - Buffer containing the characteristic value.
* @param {number} [offset = 0] - Starting offset.
* @returns {Promise}
*/
async writeValueWithoutResponse (value, offset = 0) {
return this.writeValue(value, { offset, type: 'command' })
}
/**
* Write the value of the characteristic and wait for the response.
* @param {Buffer} value - Buffer containing the characteristic value.
* @param {number} [offset = 0] - Starting offset.
* @returns {Promise}
*/
async writeValueWithResponse (value, offset = 0) {
return this.writeValue(value, { offset, type: 'request' })
}
/**
* Starts a notification session from this characteristic.
* It emits valuechanged event when receives a notification.
*/
async startNotifications () {
const cb = (propertiesChanged) => {
if ('Value' in propertiesChanged) {
const { value } = propertiesChanged.Value
this.emit('valuechanged', Buffer.from(value))
}
}
this.helper.on('PropertiesChanged', cb)
// Call StartNotify after the listener is attached in order not to lose
// the first notifications of the device.
await this.helper.callMethod('StartNotify')
}
async stopNotifications () {
await this.helper.callMethod('StopNotify')
this.helper.removeAllListeners('PropertiesChanged') // might be improved
}
async toString () {
return this.getUUID()
}
}
module.exports = GattCharacteristic
/**
* @typedef WritingMode
* @property {string} command Write without response
* @property {string} request Write with response
* @property {string} reliable Reliable Write
*/
/**
* Notification event
*
* @event GattCharacteristic#valuechanged
* @type {Buffer}
*/