/** * Payload Encoder for Milesight Network Server * * Copyright 2024 Milesight IoT * * @product WT101 */ function Encode(fPort, obj) { var encoded = milesightDeviceEncoder(obj); return encoded; } function milesightDeviceEncoder(payload) { var encoded = []; if ("reboot" in payload) { encoded = encoded.concat(reboot(payload.reboot)); } if ("report_status" in payload) { encoded = encoded.concat(reportStatus(payload.report_status)); } if ("sync_time" in payload) { encoded = encoded.concat(syncTime(payload.sync_time)); } if ("report_interval" in payload) { encoded = encoded.concat(setReportInterval(payload.report_interval)); } if ("timezone" in payload) { encoded = encoded.concat(setTimeZone(payload.timezone)); } if ("temperature_calibration" in payload) { encoded = encoded.concat(setTemperatureCalibration(payload.temperature_calibration.enable, payload.temperature_calibration.temperature)); } if ("temperature_control" in payload && "enable" in payload.temperature_control) { encoded = encoded.concat(setTemperatureControl(payload.temperature_control.enable)); } if ("temperature_control" in payload && "mode" in payload.temperature_control) { encoded = encoded.concat(setTemperatureControlMode(payload.temperature_control.mode)); } if ("temperature_target" in payload) { encoded = encoded.concat(setTemperatureTarget(payload.temperature_target, payload.temperature_error)); } if ("open_window_detection" in payload) { encoded = encoded.concat(setOpenWindowDetection(payload.open_window_detection.enable, payload.open_window_detection.temperautre_theshold, payload.open_window_detection.time)); } if ("restore_open_window_detection" in payload) { encoded = encoded.concat(restoreOpenWindowDetection(payload.restore_open_window_detection)); } if ("valve_opening" in payload) { encoded = encoded.concat(setValveOpening(payload.valve_opening)); } if ("valve_calibration" in payload) { encoded = encoded.concat(setValveCalibration(payload.valve_calibration)); } if ("valve_control_algorithm" in payload) { encoded = encoded.concat(setValveControlAlgorithm(payload.valve_control_algorithm)); } if ("freeze_protection_config" in payload) { encoded = encoded.concat(setFreezeProtection(payload.freeze_protection_config.enable, payload.freeze_protection_config.temperature)); } if ("child_lock_config" in payload) { encoded = encoded.concat(setChildLockEnable(payload.child_lock_config.enable)); } return encoded; } /** * device reboot * @param {boolean} reboot * @example payload: { "reboot": 1 }, output: FF10FF */ function reboot(reboot) { var reboot_values = [0, 1]; if (reboot_values.indexOf(reboot) == -1) { throw new Error("reboot must be one of " + reboot_values.join(", ")); } if (reboot === 0) { return []; } return [0xff, 0x10, 0xff]; } /** * sync time * @param {boolean} sync_time * @example { "sync_time": 1 } output: FF4AFF */ function syncTime(sync_time) { var sync_time_values = [0, 1]; if (sync_time_values.indexOf(sync_time) === -1) { throw new Error("sync_time must be one of " + sync_time_values.join(", ")); } if (sync_time === 0) { return []; } return [0xff, 0x4a, 0xff]; } /** * @param {boolean} report_status * @example payload: { "report_status": 1 }, output: FF28FF */ function reportStatus(report_status) { var report_status_values = [0, 1]; if (report_status_values.indexOf(report_status) == -1) { throw new Error("report_status must be one of " + report_status_values.join(", ")); } if (report_status === 0) { return []; } return [0xff, 0x28, 0xff]; } /** * time zone configuration * @param {number} timezone range: [-12, 12] * @example payload: { "timezone": -4 }, output: FF17D8FF * @example payload: { "timezone": 8 }, output: FF175000 */ function setTimeZone(timezone) { if (typeof timezone !== "number") { throw new Error("timezone must be a number"); } if (timezone < -12 || timezone > 12) { throw new Error("timezone must be between -12 and 12"); } var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0x17); buffer.writeInt16LE(timezone * 10); return buffer.toBytes(); } /** * report interval configuration * @param {number} report_interval uint: minute * @example payload: { "report_interval": 10 }, output: FF8E000A00 */ function setReportInterval(report_interval) { if (typeof report_interval !== "number") { throw new Error("report_interval must be a number"); } var buffer = new Buffer(5); buffer.writeUInt8(0xff); buffer.writeUInt8(0x8e); buffer.writeUInt8(0x00); buffer.writeUInt16LE(report_interval); return buffer.toBytes(); } /** * temperature calibration configuration * @param {boolean} enable * @param {number} temperature uint: Celcius * @example payload: { "temperature_calibration": { "enable": 1, "temperature": 5 } }, output: FFAB013200 * @example payload: { "temperature_calibration": { "enable": 1, "temperature": -5 } }, output: FFAB01CEFF * @example payload: { "temperature_calibration": { "enable": 0 } }, output: FFAB000000 */ function setTemperatureCalibration(enable, temperature) { var temperature_calibration_enable_values = [0, 1]; if (temperature_calibration_enable_values.indexOf(enable) == -1) { throw new Error("temperature_calibration.enable must be one of " + temperature_calibration_enable_values.join(", ")); } if (enable && typeof temperature !== "number") { throw new Error("temperature_calibration.temperature must be a number"); } var buffer = new Buffer(5); buffer.writeUInt8(0xff); buffer.writeUInt8(0xab); buffer.writeUInt8(enable); buffer.writeInt16LE(temperature * 10); return buffer.toBytes(); } /** * temperature control enable configuration * @param {boolean} enable * @example payload: { "temperature_control": { "enable": 1 } }, output: FFB301 */ function setTemperatureControl(enable) { var temperature_control_enable_values = [0, 1]; if (temperature_control_enable_values.indexOf(enable) == -1) { throw new Error("temperature_control.enable must be one of " + temperature_control_enable_values.join(", ")); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0xb3); buffer.writeUInt8(enable); return buffer.toBytes(); } /** * temperature control mode configuration * @param {string} mode, values: (0: auto, 1: manual) * @example * - payload: { "temperature_control": { "mode": 0 } } output: FFAE00 * - payload: { "temperature_control": { "mode": 1 } } output: FFAE01 */ function setTemperatureControlMode(mode) { var temperature_control_mode_values = [0, 1]; if (temperature_control_mode_values.indexOf(mode) == -1) { throw new Error("temperature_control.mode must be one of " + temperature_control_mode_values.join(", ")); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0xae); buffer.writeUInt8(mode); return buffer.toBytes(); } /** * temperature target configuration * @param {number} temperature_target uint: Celcius * @param {number} temperature_error uint: Celcius * @example payload: { "temperature_target": 10, "temperature_error": 0.1 }, output: FFB10A0100 * @example payload: { "temperature_target": 28, "temperature_error": 5 }, output: FFB11C3200 */ function setTemperatureTarget(temperature_target, temperature_error) { if (typeof temperature_target !== "number") { throw new Error("temperature_target must be a number"); } /* if (typeof temperature_error !== "number") { throw new Error("temperature_error must be a number"); }*/ temperature_error=1; var buffer = new Buffer(4); buffer.writeUInt8(0xff); buffer.writeUInt8(0xb1); buffer.writeInt8(temperature_target); buffer.writeUInt16LE(temperature_error * 10); return buffer.toBytes(); } /** * open window detection configuration * * @param {boolean} enable * @param {number} temperautre_theshold uint: Celcius * @param {number} time uint: minute * @example payload: { "open_window_detection": { "enable": 1, "temperautre_theshold": 2, "time": 1 } }, output: FFAF01140100 * @example payload: { "open_window_detection": { "enable": 1, "temperautre_theshold": 10, "time": 1440 } }, output: FFAF0164A005 * @example payload: { "open_window_detection": { "enable": 0 } }, output: FFAF000000 */ function setOpenWindowDetection(enable, temperautre_theshold, time) { var open_window_detection_enable_values = [0, 1]; if (open_window_detection_enable_values.indexOf(enable) == -1) { throw new Error("open_window_detection.enable must be one of " + open_window_detection_enable_values.join(", ")); } if (enable && typeof temperautre_theshold !== "number") { throw new Error("open_window_detection.temperautre_theshold must be a number"); } if (enable && typeof time !== "number") { throw new Error("open_window_detection.time must be a number"); } var buffer = new Buffer(6); buffer.writeUInt8(0xff); buffer.writeUInt8(0xaf); buffer.writeUInt8(enable); // open window detection enable buffer.writeInt8(temperautre_theshold * 10); // temperautre theshold buffer.writeUInt16LE(time); // time return buffer.toBytes(); } /** * restore open window detection status * @param {boolean} restore_open_window_detection * @example payload: { "restore_open_window_detection": 1 }, output: FF57FF */ function restoreOpenWindowDetection(restore_open_window_detection) { var restore_open_window_detection_values = [0, 1]; if (restore_open_window_detection_values.indexOf(restore_open_window_detection) == -1) { throw new Error("restore_open_window_detection must be one of " + restore_open_window_detection_values.join(", ")); } if (restore_open_window_detection === 0) { return []; } return [0xff, 0x57, 0xff]; } /** * valve opening configuration * @param {number} valve_opening uint: percentage, range: [0, 100] * @example payload: { "valve_opening": 50 }, output: FFB432 */ function setValveOpening(valve_opening) { if (typeof valve_opening !== "number") { throw new Error("valve_opening must be a number"); } if (valve_opening < 0 || valve_opening > 100) { throw new Error("valve_opening must be between 0 and 100"); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0xb4); buffer.writeUInt8(valve_opening); // valve opening percentage return buffer.toBytes(); } /** * valve calibration * @param {boolean} valve_calibration * @example payload: { "valve_calibration": 1 }, output: FFADFF */ function setValveCalibration(valve_calibration) { var valve_calibration_values = [0, 1]; if (valve_calibration_values.indexOf(valve_calibration) == -1) { throw new Error("valve_calibration must be one of " + valve_calibration_values.join(", ")); } if (valve_calibration === 0) { return []; } return [0xff, 0xad, 0xff]; } /** * valve control algorithm * @param {string} valve_control_algorithm values: (0: rate, 1: pid) * @example payload: { "valve_control_algorithm": 0 }, output: FFAC00 */ function setValveControlAlgorithm(valve_control_algorithm) { var valve_control_algorithm_values = [0, 1]; if (valve_control_algorithm_values.indexOf(valve_control_algorithm) == -1) { throw new Error("valve_control_algorithm must be one of " + valve_control_algorithm_values.join(", ")); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0xac); buffer.writeUInt8(valve_control_algorithm_values.indexOf(valve_control_algorithm)); return buffer.toBytes(); } /** * freeze protection configuration * @param {boolean} enable * @param {number} temperature uint: Celcius * @example payload: { "freeze_protection_config": { "enable": 1, "temperature": 5 } }, output: FFB0013200 * @example payload: { "freeze_protection_config": { "enable": 0 } }, output: FFB0000000 */ function setFreezeProtection(enable, temperature) { var freeze_protection_enable_values = [0, 1]; if (freeze_protection_enable_values.indexOf(enable) == -1) { throw new Error("freeze_protection_config.enable must be one of " + freeze_protection_enable_values.join(", ")); } if (enable && typeof temperature !== "number") { throw new Error("freeze_protection_config.temperature must be a number"); } var buffer = new Buffer(5); buffer.writeUInt8(0xff); buffer.writeUInt8(0xb0); buffer.writeUInt8(enable); buffer.writeInt16LE(temperature * 10); // temperature return buffer.toBytes(); } /** * child lock configuration * @param {boolean} enable values: (0: disable, 1: enable) * @example payload: { "child_lock_config": { enable: 1 } }, output: FF2501 */ function setChildLockEnable(enable) { var child_lock_enable_values = [0, 1]; if (child_lock_enable_values.indexOf(enable) == -1) { throw new Error("child_lock_config.enable must be one of " + child_lock_enable_values.join(", ")); } var buffer = new Buffer(3); buffer.writeUInt8(0xff); buffer.writeUInt8(0x25); buffer.writeUInt8(enable); return buffer.toBytes(); } function Buffer(size) { this.buffer = new Array(size); this.offset = 0; for (var i = 0; i < size; i++) { this.buffer[i] = 0; } } Buffer.prototype._write = function (value, byteLength, isLittleEndian) { for (var index = 0; index < byteLength; index++) { var shift = isLittleEndian ? index << 3 : (byteLength - 1 - index) << 3; this.buffer[this.offset + index] = (value & (0xff << shift)) >> shift; } }; Buffer.prototype.writeUInt8 = function (value) { this._write(value, 1, true); this.offset += 1; }; Buffer.prototype.writeInt8 = function (value) { this._write(value < 0 ? value + 0x100 : value, 1, true); this.offset += 1; }; Buffer.prototype.writeUInt16LE = function (value) { this._write(value, 2, true); this.offset += 2; }; Buffer.prototype.writeInt16LE = function (value) { this._write(value < 0 ? value + 0x10000 : value, 2, true); this.offset += 2; }; Buffer.prototype.writeUInt32LE = function (value) { this._write(value, 4, true); this.offset += 4; }; Buffer.prototype.writeInt32LE = function (value) { this._write(value < 0 ? value + 0x100000000 : value, 4, true); this.offset += 4; }; Buffer.prototype.toBytes = function () { return this.buffer; };