UNPKG

obniz

Version:

obniz sdk for javascript

187 lines (186 loc) 5.94 kB
"use strict"; /** * @packageDocumentation * @ignore */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WSCommandManager = void 0; const WSSchema_1 = __importDefault(require("./WSSchema")); const strict_event_emitter_1 = require("strict-event-emitter"); class WSCommandManager { constructor(commandClasses) { this.moduleNo2Name = {}; this.events = new strict_event_emitter_1.StrictEventEmitter(); this.commandClasses = commandClasses; this.commands = {}; this.createCommandInstances(); } static get schema() { return WSSchema_1.default; } createCommandInstances() { for (const name in this.commandClasses) { if (!Object.prototype.hasOwnProperty.call(this.commandClasses, name)) { continue; } const key = name; const classObj = this.commandClasses[key]; const instance = new classObj(); this.commands[key] = instance; this.moduleNo2Name[instance.module] = name; instance.parsed = (module, func, payload) => { this.events.emit('binaryGenerated', module, func, payload); }; } } getCommandInstance(name) { return this.commands[name]; } getCommandInstanceByModule(module) { return this.commands[this.moduleNo2Name[module]]; } framed(module, func, payload) { let payload_length = 0; if (payload) { payload_length = payload.length; } let length_type; if (payload_length <= 0x3f) { length_type = 0; } else if (payload_length <= 0x3fff) { length_type = 1; } else if (payload_length <= 0x3fffffff) { length_type = 2; } else { throw new Error('too big payload'); } let length_extra_bytse = length_type === 0 ? 0 : length_type === 1 ? 1 : 3; const header_length = 3 + length_extra_bytse; const result = new Uint8Array(header_length + payload_length); let index = 0; result[index++] = module & 0x7f; result[index++] = func; result[index++] = (length_type << 6) | (payload_length >> (length_extra_bytse * 8)); while (length_extra_bytse > 0) { length_extra_bytse--; result[index++] = payload_length >> (length_extra_bytse * 8); } if (payload_length === 0 || !payload) { return result; } else { result.set(payload, header_length); return result; } } /** * Dequeue a next wscommands from binary array. * * @param buf binary array received from obniz cloud. * @returns chunk */ dequeueOne(buf) { if (!buf || buf.byteLength === 0) { return null; } if (buf.byteLength < 3) { throw new Error('something wrong. buf less than 3'); } if (buf[0] & 0x80) { throw new Error('reserved bit 1'); } const module = 0x7f & buf[0]; const func = buf[1]; const length_type = (buf[2] >> 6) & 0x3; const length_extra_bytse = length_type === 0 ? 0 : length_type === 1 ? 1 : 3; if (length_type === 4) { throw new Error('invalid length'); } let length = (buf[2] & 0x3f) << (length_extra_bytse * 8); let index = 3; let shift = length_extra_bytse; while (shift > 0) { shift--; length += buf[index] << (shift * 8); index++; } return { module, func, payload: buf.slice(3 + length_extra_bytse, 3 + length_extra_bytse + length), raw: buf, next: buf.slice(3 + length_extra_bytse + length), }; } /** * json to binary * * @param json */ compress(json) { let ret = null; const append = (module, func, payload) => { const frame = this.framed(module, func, payload); if (ret) { const combined = new Uint8Array(ret.length + frame.length); combined.set(ret, 0); combined.set(frame, ret.length); ret = combined; } else { ret = frame; } }; this.events.on('binaryGenerated', append); for (const [name, wscommand] of Object.entries(this.commands)) { wscommand.parseFromJson(json); } this.events.off('binaryGenerated', append); return ret; } binary2frame(data) { const payloads = []; while (data !== null) { const frame = this.dequeueOne(data); if (!frame) { break; } payloads.push({ func: frame.func, module: frame.module, payload: frame.payload, raw: frame.raw, }); data = frame.next; } return payloads; } frame2json(frame) { const obj = {}; for (const [, command] of Object.entries(this.commands)) { if (command.module === frame.module) { command.notifyFromBinary(obj, frame.func, frame.payload); break; } } return obj; } binary2Json(data) { const frames = this.binary2frame(data); const json = frames.map((f) => this.frame2json(f)); return json; } setHw(obj) { for (const [, command] of Object.entries(this.commands)) { command.setHw(obj); } } } exports.WSCommandManager = WSCommandManager;