node-red-contrib-netvar-utils
Version:
Network Variable List utility nodes for node-red
121 lines • 4.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.compilePacketEmitter = void 0;
const constants_1 = require("../../shared/constants");
const util_1 = require("../../shared/util");
const util_2 = require("./util");
/**
* Renders expression that writes to buffer based on type
*/
function renderWriteExpression(type, size) {
switch (type) {
case 'BOOL':
return 'buffer.writeUInt8(value ? 1 : 0, offset)';
case 'BYTE':
case 'USINT':
return 'buffer.writeUInt8(value, offset)';
case 'SINT':
return 'buffer.writeInt8(value, offset)';
case 'WORD':
case 'UINT':
return 'buffer.writeUInt16LE(value, offset)';
case 'INT':
return 'buffer.writeInt16LE(value, offset)';
case 'DWORD':
case 'UDINT':
case 'TIME':
case 'TIME_OF_DAY':
return 'buffer.writeUInt32LE(value, offset)';
case 'DATE':
case 'DATE_AND_TIME':
return 'buffer.writeUInt32LE(value / 1000, offset)';
case 'DINT':
return 'buffer.writeInt32LE(value, offset)';
case 'LWORD':
case 'ULINT':
return 'buffer.writeBigUInt64LE(value, offset)';
case 'LINT':
return 'buffer.writeBigInt64LE(value, offset)';
case 'REAL':
return 'buffer.writeFloatLE(value, offset)';
case 'LREAL':
return 'buffer.writeDoubleLE(value, offset)';
case 'STRING':
return `buffer.write(value.slice(0, ${size - 1}), offset, ${size} , \'ascii\')`;
default:
throw new TypeError('Unrecognized data type');
}
}
/**
* Renders `ForStatement` that creates a array object based on definition
*/
function renderForStatement(definition) {
const { dimensions, type, size, begin, end } = definition;
const length = dimensions.length;
const indexNames = util_1.times(length, util_2.generateSafeVariableName);
const prefix = `target['${definition.name}']`;
const ranges = util_2.getForStatementRanges(dimensions, begin, end);
let string = '';
for (const range of ranges) {
const { begin, end } = range;
let valueExpression = prefix;
let idx = 0;
while (idx < dimensions.length && begin[idx] === end[idx]) {
valueExpression += `[${begin[idx]}]`;
idx++;
}
const sameIndexUntil = idx;
// Render for statements
for (let i = sameIndexUntil; i < dimensions.length; i++) {
string += 'for (';
string += `let ${indexNames[i]}=${begin[i]};`;
string += `${indexNames[i]}<${end[i]};`;
string += `${indexNames[i]}++) {\n`;
}
string += `value = ${valueExpression}`;
for (let i = sameIndexUntil; i < dimensions.length; i++)
string += `[${indexNames[i]}]`;
string += '\n';
string += `${renderWriteExpression(type, size)}\n`;
string += `offset += ${size}\n`;
for (let i = sameIndexUntil; i < dimensions.length; i++)
string += '}\n';
}
return string;
}
/**
* Renders the block for writing the values in `target` object to defined packets
*/
function renderWriteStatement(definition) {
let string = '';
if (definition.isArray) {
string += `${renderForStatement(definition)}\n`;
}
else {
string += `value = target['${definition.name}']\n`;
string += `${renderWriteExpression(definition.type, definition.size)}\n`;
string += `offset += ${definition.size}\n`;
}
return string;
}
/**
* Compiles the function that emits packets according to the packet definition
*/
function compilePacketEmitter(packet, listId) {
let fn = `let offset = ${constants_1.PACKET_HEADER_SIZE}\n`
+ `let buffer = Buffer.alloc(${packet.size})\n`
// Write header to buffer
+ `buffer.write('${constants_1.NETVAR_PROTOCOL_ID}', ${constants_1.OFFSET_PROTOCOL}, 'ascii')\n`
+ `buffer.writeUInt16LE(${listId}, ${constants_1.OFFSET_LIST_ID})\n`
+ `buffer.writeUInt16LE(${packet.index}, ${constants_1.OFFSET_PACKET_INDEX})\n`
+ `buffer.writeUInt16LE(${packet.variableCount}, ${constants_1.OFFSET_VAR_COUNT})\n`
+ `buffer.writeUInt16LE(${packet.size}, ${constants_1.OFFSET_PACKET_SIZE})\n`
+ `buffer.writeUInt32LE(counter, ${constants_1.OFFSET_COUNTER})\n`
+ 'let value = 0\n';
for (const definition of packet.definitions)
fn += renderWriteStatement(definition);
fn += 'return buffer\n';
return new Function('target', 'counter', fn);
}
exports.compilePacketEmitter = compilePacketEmitter;
//# sourceMappingURL=compile-emitter.js.map