UNPKG

node-noble-xiaomi-kingsmith-r1-pro-walkingpad

Version:

node noble xiaomi kingsmith r1 pro walkingpad

245 lines (214 loc) 6.3 kB
var async = require('async'); var noble = require('noble'); let minimalCommandSpace = 500; let previousCommandTime = 0; let pauseStats = false; let peripheralIdOrAddress = '574c4d191bfc'; let char1 = null; let char2 = null; let meterObjects = []; let timeObjects = []; let speed, distance, timeInSeconds; let serviceUUID = 'fe00'; // commands let commands = { // startBelt: [0xf7, 0xa2, 0x04, 0x01, 0xa7, 0xfd], // working startBelt: [247, 162, 4, 1, 0xff, 253], changeSpeed0: [247, 162, 1, 0, 0xff, 253], changeSpeed60: [247, 162, 1, 60, 0xff, 253], changeSpeed80: [247, 162, 1, 80, 0xff, 253], changeSpeed30: [247, 162, 1, 30, 0xff, 253], askStats: [247, 162, 0, 0, 162, 253], }; const reducer = (previousValue, currentValue) => previousValue + currentValue; let fixCRC = function (array) { // cmd[-2] = sum(cmd[1:-2]) % 256 let sum = 0; for (let i = 1; i < array.length - 2; i++) { sum += array[i]; } let crc = sum % 256; array[array.length - 2] = crc; }; // fixCRC(commands.startBelt); noble.on('stateChange', function (state) { if (state === 'poweredOn') { // // Once the BLE radio has been powered on, it is possible // to begin scanning for services. Pass an empty array to // scan for all services (uses more time and power). // console.log('scanning...'); noble.startScanning([serviceUUID], false); } else { noble.stopScanning(); } }); noble.on('discover', function (peripheral) { // we found a peripheral, stop scanning noble.stopScanning(); // // The advertisment data contains a name, power level (if available), // certain advertised service uuids, as well as manufacturer data, // which could be formatted as an iBeacon. // // // Once the peripheral has been discovered, then connect to it. // peripheral.connect(function (err) { // // Once the peripheral has been connected, then discover the // services and characteristics of interest. // peripheral.discoverServices([serviceUUID], function (err, services) { services.forEach(function (service) { // // This must be the service we were looking for. // console.log('found service:', service.uuid); // // So, discover its characteristics. // service.discoverCharacteristics([], function (err, characteristics) { characteristics.forEach(function (characteristic) { // // Loop through each characteristic and match them to the // UUIDs that we know about. // console.log('found characteristic:', characteristic.uuid); // save the charaaacteristics if (characteristic.uuid == 'fe01') { char1 = characteristic; } if (characteristic.uuid == 'fe02') { char2 = characteristic; } }); // Check to see if we found all of our characteristics. if (char1 && char2) { // // We did, so run the program! // program(); } else { console.log('missing characteristics'); } }); }); }); }); }); async function sendCommand(cmd) { fixCRC(cmd); var dif = new Date().getTime() - previousCommandTime; console.log(dif); if (dif < minimalCommandSpace) { await sleep(minimalCommandSpace - dif); } sendCommandRaw(cmd); } function sendCommandRaw(cmd) { previousCommandTime = new Date().getTime(); var tmpBuf = new Buffer.from(cmd); char2.write(tmpBuf, false, function (err) { // console.log('sendCommandRaw: ' + cmd); // console.log(err); }); } let program = async function () { console.log(char1); char1.on('read', function (data, isNotification) { decodeStats(data); }); char1.subscribe(function (err) {}); // Asking for stats setInterval(askForStats, 1500); myCourse(); }; // Ez course 1km, ~12 mins let myCourse = async () => { // Get ready await sleep(5000); // Start belt (wait 5 seconds until the belt is started (3... 2... 1...)) sendCommand(commands.startBelt); await sleep(5000); // Set speed to 4km/h setSpeed(40); // Wait until we hit the 200 meters await meters(20); // Set speed to 5km/h setSpeed(50); // Wait until we hit the 600 meters await meters(60); // Set speed to 6km/h setSpeed(60); // Wait until we hit the 1000 meters await meters(100); // Set speed to 0km/h setSpeed(0); }; function setSpeed(speed) { let speedCmd = [247, 162, 1, speed, 0xff, 253]; sendCommand(speedCmd); } async function meters(value) { let promiseResolve; let prom = new Promise((resolve) => { promiseResolve = resolve; }); let metersObj = { meters: value, promise: prom, resolver: promiseResolve, }; meterObjects.push(metersObj); return metersObj.promise; } async function timers(value) { let promiseResolve; let prom = new Promise((resolve) => { promiseResolve = resolve; }); let timersObj = { time: value, promise: prom, resolver: promiseResolve, }; timeObjects.push(timersObj); return timersObj.promise; } function askForStats() { if (pauseStats) return; sendCommand(commands.askStats); } function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } let decodeStats = function (data) { if (data[0] === 0xf8 && data[1] === 0xa2) { speed = data[3]; distance = data.readUIntBE(8, 3); timeInSeconds = data.readUIntBE(5, 3); console.log(`speed: ${speed}`); console.log(`distance: ${distance}`); console.log(`timeInSeconds: ${timeInSeconds}`); // Check for meter objects meterObjects.forEach((meterObject) => { if (distance >= meterObject.meters) { console.log(`promises complete====================================`); meterObject.resolver(); meterObjects = meterObjects.filter((item) => item !== meterObject); } }); timeObjects.forEach((timeObj) => { if (timeInSeconds >= timeObj.time) { console.log(`promises complete====================================`); timeObj.resolver(); timeObjects = timeObjects.filter((item) => item !== timeObj); } }); } else { } };