node-red-contrib-mysensors
Version:
Mysensors related nodes, for decoding / encoding mysensors serial protocol and MQTT topic, and wrapping arbitrary messages into mysensors compatible messages
129 lines (128 loc) • 4.92 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MysensorsController = void 0;
const auto_decode_1 = require("./decoder/auto-decode");
const mysensors_mqtt_1 = require("./decoder/mysensors-mqtt");
const mysensors_serial_1 = require("./decoder/mysensors-serial");
const mysensors_msg_1 = require("./mysensors-msg");
const mysensors_types_1 = require("./mysensors-types");
const date_fns_tz_1 = require("date-fns-tz");
class MysensorsController {
constructor(database, handleIds, timeResponse, timeZone, measurementSystem, mqttRoot, addSerialNewline) {
this.database = database;
this.handleIds = handleIds;
this.timeResponse = timeResponse;
this.timeZone = timeZone;
this.measurementSystem = measurementSystem;
this.mqttRoot = mqttRoot;
this.addSerialNewline = addSerialNewline;
}
async messageHandler(IncommingMsg) {
const msg = await (0, auto_decode_1.AutoDecode)(IncommingMsg);
if (!msg) {
return;
}
await this.updateHeard(msg);
if (msg.messageType === mysensors_types_1.mysensor_command.C_PRESENTATION) {
await this.database.child(msg.nodeId, msg.childSensorId, msg.subType, msg.payload);
}
if (msg.messageType !== mysensors_types_1.mysensor_command.C_INTERNAL) {
return;
}
switch (msg.subType) {
case mysensors_types_1.mysensor_internal.I_ID_REQUEST:
return this.encode(await this.handleIdRequest(msg));
case mysensors_types_1.mysensor_internal.I_SKETCH_NAME:
case mysensors_types_1.mysensor_internal.I_SKETCH_VERSION:
await this.handleSketchVersion(msg);
break;
case mysensors_types_1.mysensor_internal.I_LOG_MESSAGE:
await this.handleDebug(msg);
break;
case mysensors_types_1.mysensor_internal.I_TIME:
return this.encode(await this.handleTimeResponse(msg));
case mysensors_types_1.mysensor_internal.I_CONFIG:
return this.encode(await this.handleConfig(msg));
case mysensors_types_1.mysensor_internal.I_BATTERY_LEVEL:
await this.handleBattery(msg);
break;
}
}
async updateHeard(msg) {
await this.database.nodeHeard(msg.nodeId);
await this.database.childHeard(msg.nodeId, msg.childSensorId);
}
async handleConfig(msg) {
if (this.measurementSystem === 'N') {
return;
}
return {
...msg,
payload: this.measurementSystem
};
}
async handleTimeResponse(msg) {
if (!this.timeResponse || !msg.messageType) {
return;
}
const msgCopy = { ...msg };
msgCopy.subType = mysensors_types_1.mysensor_internal.I_TIME;
if (this.timeZone === 'Z') {
msgCopy.payload = Math.trunc(new Date().getTime() / 1000).toString();
}
else {
msgCopy.payload = Math.trunc((0, date_fns_tz_1.utcToZonedTime)(new Date(), this.timeZone).getTime() / 1000).toString();
}
return msgCopy;
}
async handleIdRequest(msg) {
if (!this.handleIds) {
return;
}
const newNodeId = await this.database.getFreeNodeId();
if (!newNodeId) {
return;
}
return {
...msg,
subType: mysensors_types_1.mysensor_internal.I_ID_RESPONSE,
payload: newNodeId.toString()
};
}
async handleDebug(msg) {
const r = /TSF:MSG:READ,(\d+)-(\d+)-(\d+)/;
const m = r.exec(msg.payload);
if (!m) {
return;
}
return this.database.setParent(Number(m[1]), Number(m[2]));
}
async handleBattery(msg) {
await this.database.setBatteryLevel(msg.nodeId, Number(msg.payload));
}
async handleSketchVersion(msg) {
if (msg.subType === mysensors_types_1.mysensor_internal.I_SKETCH_VERSION) {
return this.database.sketchVersion(msg.nodeId, msg.payload);
}
else if (msg.subType === mysensors_types_1.mysensor_internal.I_SKETCH_NAME) {
return this.database.sketchName(msg.nodeId, msg.payload);
}
}
encode(msg) {
if (!msg) {
return;
}
let encoder;
if (msg.origin === mysensors_msg_1.MsgOrigin.serial) {
encoder = new mysensors_serial_1.MysensorsSerial(undefined, undefined, this.addSerialNewline);
}
else if (msg.origin === mysensors_msg_1.MsgOrigin.mqtt) {
encoder = new mysensors_mqtt_1.MysensorsMqtt();
}
if (!encoder) {
return msg;
}
return encoder.encode({ ...msg, topicRoot: this.mqttRoot });
}
}
exports.MysensorsController = MysensorsController;