iobroker.wireless-mbus
Version:
Receive data from Wireless Meter-Bus (wM-Bus) devices like gas or electricity meters
118 lines (95 loc) • 3.36 kB
JavaScript
;
const HciMessage = require('./HciMessage');
const SerialDevice = require('./SerialDevice');
/* eslint-disable no-unused-vars */
//Endpoint Identifier
const DEVMGMT_ID = 0x01;
const RADIOLINK_ID = 0x02;
const RADIOLINKTEST_ID = 0x03;
const HWTEST_ID = 0x04;
//Device Management Message Identifier
const DEVMGMT_MSG_SET_CONFIG_REQ = 0x03;
const DEVMGMT_MSG_SET_CONFIG_RSP = 0x04;
//Link modes
const LINK_MODE_S1 = 0x00;
const LINK_MODE_S1m = 0x01;
const LINK_MODE_S2 = 0x02;
const LINK_MODE_T1 = 0x03;
const LINK_MODE_T2 = 0x04;
const LINK_MODE_R2 = 0x05;
const LINK_MODE_C1A = 0x06;
const LINK_MODE_C1B = 0x07;
const LINK_MODE_C2A = 0x08;
const LINK_MODE_C2B = 0x09;
/* eslint-enable no-unused-vars */
class ImstReceiver extends SerialDevice {
constructor(options, mode, onMessage, onError, loggerFunction) {
super(options, mode, onMessage, onError, loggerFunction);
this.log.setPrefix('IMST');
this.frameType = 'A';
}
buildPayloadPackage(command, payload) {
return new HciMessage()
.setPayload(DEVMGMT_ID, command, payload)
.setCrc(true)
.build();
}
checkAndExtractMessage() {
const length = this.parserBuffer.length;
const expectedLength = HciMessage.tryToGetLength(this.parserBuffer);
if ((expectedLength !== -1) && (length >= expectedLength)) {
const messageBuffer = this.parserBuffer.subarray(0, expectedLength);
this.parserBuffer = this.parserBuffer.subarray(expectedLength);
return messageBuffer;
} else {
return null;
}
}
validateResponse(pkg, response) {
const mPkg = new HciMessage();
mPkg.parse(pkg);
const mResponse = new HciMessage();
mResponse.parse(response);
if (mPkg.setupResponse().messageId != mResponse.messageId) {
throw new Error('MessageId mismatch!');
}
}
parseRawMessage(messageBuffer) {
const hciMessage = new HciMessage();
const parseResult = hciMessage.parse(messageBuffer);
if (parseResult !== true) {
this.log.info(parseResult);
}
return {
frameType: this.frameType,
containsCrc: false,
rawData: this.prefixPayloadWithLength(hciMessage.payload),
rssi: hciMessage.rssi,
ts: hciMessage.hasTimestamp ? hciMessage.timestamp : new Date().getTime()
};
}
prefixPayloadWithLength(payload) {
return Buffer.concat([Buffer.from([payload.length]), payload]);
}
getMode() {
switch (this.mode) {
case 'S': return LINK_MODE_S1;
case 'CA': return LINK_MODE_C1A;
case 'CB': return LINK_MODE_C1B;
default: return LINK_MODE_T1;
}
}
async setModeAndDisableSleepMode() {
const mode = this.getMode();
this.frameType = (mode == LINK_MODE_C1B ? 'B' : 'A');
if (mode > 0x09) {
throw new Error(`Invalid mode! ${mode}`);
}
await this.sendPackage(DEVMGMT_MSG_SET_CONFIG_REQ, Buffer.from([0x00, 0x03, 0x00, mode, 0x08, 0x00]));
this.log.info(`Receiver set to ${this.mode}-MODE`);
}
async initDevice() {
await this.setModeAndDisableSleepMode();
}
}
module.exports = ImstReceiver;