node-open-protocol-desoutter
Version:
200 lines (154 loc) • 7.48 kB
JavaScript
/*
Copyright 2018 Smart-Tech Controle e Automação
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
;
/*jshint esversion: 6, node: true*/
const util = require('util');
const { Transform } = require('stream');
const constants = require("./constants.json");
const encodingOP = constants.defaultEncoder;
const helpers = require("./helpers.js");
const pad = helpers.padLeft;
var debug = util.debuglog('open-protocol');
/**
* @class
* @name Header
* @param {object} Header
* @param {number} Header.mid The MID describes how to interpret the message.
* @param {number} Header.revision The MID Revision is unique per MID and is used in case different versions are available for the same MID.
* @param {boolean} Header.noAck The No Ack Flag is used when setting a subscription.
* @param {number} Header.stationID The station the message is addressed to in the case of controller with multi-station configuration.
* @param {number} Header.spindleID The spindle the message is addressed to in the case several spindles are connected to the same controller.
* @param {number} Header.sequenceNumber For acknowledging on “Link Level” with MIDs 0997 and 0998.
* @param {number} Header.messageParts Linking function can be up to 9 = possible to send 9*9999 bytes messages. ~ 90 kB.
* @param {number} Header.messageNumber Linking function, can be 1- 9 at message length > 9999.
* @param {buffer | string} Header.payload the user's data
*/
class OpenProtocolSerializer extends Transform {
/**
* @class OpenProtocolSerializer
* @description This class performs the serialization of the MID header.
* This transforms MID (object) in MID (Buffer).
* @param {Object} opts an object with the option passed to the constructor
*/
constructor(opts) {
opts = opts || {};
opts.writableObjectMode = true;
super(opts);
debug("new openProtocolSerializer");
}
_transform(chunk, encoding, cb) {
debug("openProtocolSerializer _transform", chunk);
chunk.mid = Number(chunk.mid);
if (isNaN(chunk.mid) || chunk.mid < 1 || chunk.mid > 9999) {
cb(new Error(`Invalid MID [${chunk.mid}]`));
debug("openProtocolSerializer _transform err-mid:", chunk);
return;
}
if (chunk.revision === " " || chunk.revision === 0 || chunk.revision === undefined) {
chunk.revision = 1;
}
chunk.revision = Number(chunk.revision);
if (isNaN(chunk.revision) || chunk.revision < 0 || chunk.revision > 999) {
cb(new Error(`Invalid revision [${chunk.revision}]`));
debug("openProtocolSerializer _transform err-revision:", chunk);
return;
}
if (chunk.stationID === " " ||chunk.stationID === undefined) {
chunk.stationID = 1;
}
chunk.stationID = Number(chunk.stationID);
if (isNaN(chunk.stationID) || chunk.stationID < 0 || chunk.stationID > 99) {
cb(new Error(`Invalid stationID [${chunk.stationID}]`));
debug("openProtocolSerializer _transform err-stationID:", chunk);
return;
}
if (chunk.spindleID === " " ||chunk.spindleID === undefined) {
chunk.spindleID = 1;
}
chunk.spindleID = Number(chunk.spindleID);
if (isNaN(chunk.spindleID) || chunk.spindleID < 0 || chunk.spindleID > 99) {
cb(new Error(`Invalid spindleID [${chunk.spindleID}]`));
debug("openProtocolSerializer _transform err-spindleID:", chunk);
return;
}
if (chunk.sequenceNumber === " " || chunk.sequenceNumber === undefined) {
chunk.sequenceNumber = 0;
}
chunk.sequenceNumber = Number(chunk.sequenceNumber);
if (isNaN(chunk.sequenceNumber) || chunk.sequenceNumber < 0 || chunk.sequenceNumber > 99) {
cb(new Error(`Invalid sequenceNumber [${chunk.sequenceNumber}]`));
debug("openProtocolSerializer _transform err-sequenceNumber:", chunk);
return;
}
if (chunk.messageParts === " " || chunk.messageParts === undefined) {
chunk.messageParts = 0;
}
chunk.messageParts = Number(chunk.messageParts);
if (isNaN(chunk.messageParts) || chunk.messageParts < 0 || chunk.messageParts > 9) {
cb(new Error(`Invalid messageParts [${chunk.messageParts}]`));
debug("openProtocolSerializer _transform err-messageParts:", chunk);
return;
}
if (chunk.messageNumber === " " || chunk.messageNumber === undefined) {
chunk.messageNumber = 0;
}
chunk.messageNumber = Number(chunk.messageNumber);
if (isNaN(chunk.messageNumber) || chunk.messageNumber < 0 || chunk.messageNumber > 9) {
cb(new Error(`Invalid messageNumber [${chunk.messageNumber}]`));
debug("openProtocolSerializer _transform err-messageNumber:", chunk);
return;
}
if(chunk.payload === undefined){
chunk.payload = "";
}
if (!Buffer.isBuffer(chunk.payload) && typeof chunk.payload !== "string") {
cb(new Error(`Invalid payload [${chunk.payload}]`));
debug("openProtocolSerializer _transform err-payload:", chunk);
return;
}
let sizePayload = chunk.payload.length;
let sizeMessage = 21 + sizePayload;
let buf = Buffer.alloc(sizeMessage);
buf.write(pad(sizeMessage - 1, 4), 0, 4, encodingOP);
buf.write(pad(chunk.mid, 4), 4, 4, encodingOP);
/*
Copyright 2021 Jeremy London
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Desoutter controllers did not like the version number.
Sending blank characters for this header option got it to work
*/
/*
Removes extra serialization code that is not needed by Desoutter controller
*/
buf.write(' ', 8, encodingOP);
buf.write(chunk.payload.toString(encodingOP), 20, encodingOP);
buf.write("\u0000", sizeMessage, encodingOP);
debug("openProtocolSerializer _transform publish", buf);
this.push(buf);
cb();
}
_destroy() {
//no-op, needed to handle older node versions
}
}
module.exports = OpenProtocolSerializer;