UNPKG

obniz

Version:

obniz sdk for javascript

204 lines (182 loc) 6.29 kB
const WSCommand = require('./WSCommand_.js'); const ObnizUtil = require('../utils/util'); const semver = require('semver'); module.exports = class WSCommand_Directive extends WSCommand { constructor() { super(); this.module = 1; this._CommandRegistrate = 0; this._CommandPause = 1; this._CommandResume = 2; this._CommandNotify = 3; const CommandIO = require('./WSCommand_IO'); const CommandPWM = require('./WSCommand_PWM'); this.availableCommands = [new CommandIO(), new CommandPWM()]; } // Commands init(params, originalParams) { const nameArray = ObnizUtil.string2dataArray(params.animation.name); let frame, offset = 0; if (semver.lt(this._hw.firmware, '2.0.0')) { // < 2.0.0 frame = new Uint8Array(1 + nameArray.length + 1); // name // frame[offset++] = nameArray.length + 1; frame.set(nameArray, offset); offset += nameArray.length; frame[offset++] = 0; // null string if ( params.animation.status === 'registrate' || typeof params.animation.repeat === 'number' ) { throw new Error('you need to update your firmware >= 2.0.0'); } } else { frame = new Uint8Array(1 + nameArray.length + 1 + 1 + 4); // name // frame[offset++] = nameArray.length + 1; frame.set(nameArray, offset); offset += nameArray.length; frame[offset++] = 0; // null string // type and count // let type = 0, repeat_count = 0; if (params.animation.status === 'loop') { type = 1; // auto start } if (typeof params.animation.repeat === 'number') { repeat_count = params.animation.repeat; type += 2; } frame[offset++] = type; frame[offset++] = repeat_count >> (8 * 3); frame[offset++] = repeat_count >> (8 * 2); frame[offset++] = repeat_count >> (8 * 1); frame[offset++] = repeat_count; } const commandJsonArray = params.animation.states; for (let i = 0; i < commandJsonArray.length; i++) { const obj = commandJsonArray[i]; const duration = parseInt(obj.duration * 1000); const state = obj.state; // Dry run commands let parsedCommands = JSON.parse(JSON.stringify(state)); if (!Array.isArray(parsedCommands)) { parsedCommands = [parsedCommands]; } let compressed = null; for ( let commandIndex = 0; commandIndex < parsedCommands.length; commandIndex++ ) { const frame = WSCommand.compress( this.availableCommands, parsedCommands[commandIndex] ); if (!frame) { throw new Error( '[io.animation.states.state]only io or pwm commands. Pleave provide state at least one of them.' ); } if (compressed) { let combined = new Uint8Array(compressed.length + frame.length); combined.set(compressed, 0); combined.set(frame, compressed.length); compressed = combined; } else { compressed = frame; } } if (!compressed) { throw new Error( '[io.animation.states.state]only io or pwm commands. Pleave provide state at least one of them.' ); } const length = compressed.byteLength; let commandHeader = new Uint8Array(8); commandHeader[0] = length >> (8 * 3); commandHeader[1] = length >> (8 * 2); commandHeader[2] = length >> (8 * 1); commandHeader[3] = length; commandHeader[4] = duration >> (8 * 3); commandHeader[5] = duration >> (8 * 2); commandHeader[6] = duration >> (8 * 1); commandHeader[7] = duration; const combined = new Uint8Array( frame.byteLength + commandHeader.byteLength + compressed.byteLength ); combined.set(frame, 0); combined.set(commandHeader, frame.byteLength); combined.set(compressed, frame.byteLength + commandHeader.byteLength); frame = combined; } if (frame.byteLength > 1000) { // 1kbyte over throw new Error('[io.animation]Too big animation datas'); } this.sendCommand(this._CommandRegistrate, frame); } changeState(params) { if (params.animation.status === 'resume') { const nameArray = ObnizUtil.string2dataArray(params.animation.name); let frame = new Uint8Array(nameArray.length + 2); frame[0] = nameArray.length + 1; frame.set(nameArray, 1); frame[frame.byteLength - 1] = 0; this.sendCommand(this._CommandResume, frame); } else if (params.animation.status === 'pause') { const nameArray = ObnizUtil.string2dataArray(params.animation.name); let frame = new Uint8Array(nameArray.length + 2); frame[0] = nameArray.length + 1; frame.set(nameArray, 1); frame[frame.byteLength - 1] = 0; this.sendCommand(this._CommandPause, frame); } } parseFromJson(json) { let parentCommandNotFound = false; try { super.parseFromJson(json); } catch (err) { if (err instanceof this.WSCommandNotFoundError) { parentCommandNotFound = true; } else { throw err; } } const module = json['io']; if (module === undefined) { return; } const schemaData = [ { uri: '/request/ioAnimation/init', onValid: this.init }, { uri: '/request/ioAnimation/changeState', onValid: this.changeState }, ]; const res = this.validateCommandSchema(schemaData, module, 'io', module); if (res.valid === 0 && parentCommandNotFound) { if (res.invalidButLike.length > 0) { throw new Error(res.invalidButLike[0].message); } else { let WSCommandNotFoundError = this.WSCommandNotFoundError; throw new WSCommandNotFoundError(`[io.animation]unknown command`); } } } notifyFromBinary(objToSend, func, payload) { if (func === this._CommandNotify) { const name = ObnizUtil.dataArray2string( payload.slice(2, payload.byteLength - 1) ); // remove null string objToSend['io'] = { animation: { name, status: 'finish', }, }; } else { super.notifyFromBinary(objToSend, func, payload); } } };