UNPKG

zwack

Version:

Simulate an indoor bicycle trainer with BLE (Bluetooth Low Energy)

93 lines (81 loc) 3.3 kB
var debugCSP = require('debug')('zwack:csp'); const Bleno = require('@abandonware/bleno'); // Spec //https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.cycling_power_measurement.xml class CyclingPowerMeasurementCharacteristic extends Bleno.Characteristic { constructor() { super({ uuid: '2A63', value: null, properties: ['notify'], descriptors: [ new Bleno.Descriptor({ uuid: '2901', value: 'Cycling Power Measurement', }), new Bleno.Descriptor({ // Client Characteristic Configuration uuid: '2902', value: Buffer.alloc(2), }), new Bleno.Descriptor({ // Server Characteristic Configuration uuid: '2903', value: Buffer.alloc(2), }), ], }); this._updateValueCallback = null; } onSubscribe(maxValueSize, updateValueCallback) { debugCSP('[CyclingPowerMeasurementCharacteristic] client subscribed to PM'); this._updateValueCallback = updateValueCallback; return this.RESULT_SUCCESS; } onUnsubscribe() { debugCSP('[CyclingPowerMeasurementCharacteristic] client unsubscribed from PM'); this._updateValueCallback = null; return this.RESULT_UNLIKELY_ERROR; } notify(event) { if (!('watts' in event) && !('rev_count' in event)) { // ignore events with no power and no crank data return this.RESULT_SUCCESS; } var buffer = new Buffer(8); // flags // 00000001 - 1 - 0x001 - Pedal Power Balance Present // 00000010 - 2 - 0x002 - Pedal Power Balance Reference // 00000100 - 4 - 0x004 - Accumulated Torque Present // 00001000 - 8 - 0x008 - Accumulated Torque Source // 00010000 - 16 - 0x010 - Wheel Revolution Data Present // 00100000 - 32 - 0x020 - Crank Revolution Data Present // 01000000 - 64 - 0x040 - Extreme Force Magnitudes Present // 10000000 - 128 - 0x080 - Extreme Torque Magnitudes Present if ('rev_count' in event) { buffer.writeUInt16LE(0x020, 0); } else { buffer.writeUInt16LE(0x00, 0); } if ('watts' in event) { var watts = event.watts; debugCSP('power: ' + watts); buffer.writeInt16LE(watts, 2); } if ('rev_count' in event) { event.rev_count = event.rev_count % 65536; //debugCSP("rev_count: " + event.rev_count); buffer.writeUInt16LE(event.rev_count, 4); var now = Date.now(); var now_1024 = Math.floor((now * 1e3) / 1024); var event_time = now_1024 % 65536; // rolls over every 64 seconds debugCSP('event time: ' + event_time); buffer.writeUInt16LE(event_time, 6); } if (this._updateValueCallback) { this._updateValueCallback(buffer); } return this.RESULT_SUCCESS; } } module.exports = CyclingPowerMeasurementCharacteristic;