diff --git a/controllers/modbus.controller.js b/controllers/modbus.controller.js index 9f34f9b..3305220 100644 --- a/controllers/modbus.controller.js +++ b/controllers/modbus.controller.js @@ -224,7 +224,7 @@ export const modbusController = { const streamInterval = setInterval(async () => { try { device.display_values = await db.all(`SELECT * FROM "display_values" WHERE slave_id = ?`, [slave_id]) - const data = await modbusService.readDataFromDevice(device, device.g_display_reg_type); + const data = await modbusService.readDataFromDevice(device); res.write("event: message\n"); res.write(`data: ${JSON.stringify(data)}\n\n`); } catch (error) { diff --git a/data.db b/data.db index 9790eae..76368a9 100644 Binary files a/data.db and b/data.db differ diff --git a/index.d.ts b/index.d.ts index 5e81d19..f5b8b77 100644 --- a/index.d.ts +++ b/index.d.ts @@ -30,4 +30,9 @@ export type ModbusDevice = { g_y_label: string | null; is_logging: boolean; display_values?: DisplayValue[] +} + +export type EventDataStream = { + graph: { value: number; format: NumberType } | null; + displayValues: DisplayValue[]; } \ No newline at end of file diff --git a/migrations/001-init.sql b/migrations/001-init.sql index 1cc312b..073ba83 100644 --- a/migrations/001-init.sql +++ b/migrations/001-init.sql @@ -22,7 +22,7 @@ CREATE TABLE IF NOT EXISTS "modbus_slaves" ( "id" INTEGER CHECK (id >= 1 AND id <= 255), "name" VARCHAR(256) NOT NULL, "g_display_reg_addr" INTEGER CHECK(g_display_reg_addr >= 0 AND g_display_reg_addr <= 65534) DEFAULT NULL, - "g_display_reg_type" VARCHAR(3) CHECK(g_display_reg_type IN("HR", "IR")) DEFAULT "HR", + "g_display_reg_type" VARCHAR(3) CHECK(g_display_reg_type IN("HR", "IR")) DEFAULT "IR", "g_display_reg_format" VARCHAR(5) CHECK(g_display_reg_format IN("UI16", "I16", "UI32", "I32", "FP32")) DEFAULT "UI16", "g_y_label" VARCHAR(40) DEFAULT "Label", "is_logging" BOOLEAN NOT NULL DEFAULT FALSE, @@ -34,6 +34,7 @@ CREATE TABLE IF NOT EXISTS "display_values" ( "name" VARCHAR(32) NOT NULL, "slave_id" INTEGER NOT NULL, "reg_addr" INTEGER DEFAULT 0 NOT NULL CHECK(reg_addr >= 0 AND reg_addr <= 65534), + -- "reg_type" VARCHAR(3) CHECK(reg_type IN("HR", "IR", "DI", "DO")) DEFAULT "IR", "reg_format" INTEGER NOT NULL CHECK(reg_format IN(16, 32)) DEFAULT 16, PRIMARY KEY("id"), FOREIGN KEY("slave_id") REFERENCES modbus_slaves("id") ON DELETE CASCADE diff --git a/public/js/app.js b/public/js/app.js index e0f7a46..0142c7a 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -148,7 +148,7 @@ document.addEventListener("alpine:init", async () => { } dataStreamSource.onmessage = (e) => { const data = JSON.parse(e.data); - + console.log('[SSE Message]', data); if (data.graph !== null) { graphData.push([new Date(), data.graph.value]); if (g === null) { diff --git a/services/modbus.service.js b/services/modbus.service.js index 159ca46..f66c419 100644 --- a/services/modbus.service.js +++ b/services/modbus.service.js @@ -4,36 +4,65 @@ import * as utils from '#root/utils/index.js' export const modbusService = { /** * @param {import("..").ModbusDevice} device - * @param {"HR" | "IR"} type + * @return {Promise} */ - async readDataFromDevice(device, type = 'HR') { - const { g_display_reg_format: g_format, g_display_reg_addr: g_reg_addr } = device; - let readLength = 1; // 16 bits default + async readDataFromDevice(device) { + const { g_display_reg_format, g_display_reg_addr, g_display_reg_type } = device; + + /** @type {import("..").EventDataStream} */ + const data = { graph: null, displayValues: [] }; modbusClient.setID(device.id); - - if (g_format?.includes('32')) readLength = 2; - if (g_format?.includes('64')) readLength = 4; - if (g_format?.includes('128')) readLength = 8; - let graphValue; - if (type === 'HR') graphValue = await modbusClient.readHoldingRegisters(g_reg_addr, readLength); - if (type === 'IR') graphValue = await modbusClient.readInputRegisters(g_reg_addr, readLength); + /* Read data for graph */ + if (g_display_reg_addr !== null) { + const graphValue = await this.readModbusRegisters(g_display_reg_addr, g_display_reg_type, g_display_reg_format); + data.graph = { + value: utils.readNumberFromBuf(graphValue, device.g_display_reg_format, 'BE'), + format: g_display_reg_format + } + } + /* Read data for display values */ if (device.display_values) { for (const value of device.display_values) { - value.data = Buffer.from((await modbusClient.readHoldingRegisters(value.reg_addr, 1)).buffer).readUInt16BE(); - } + value.data = Buffer.from((await this.readModbusRegisters(value.reg_addr, 'HR', 'UI16'))).readUInt16BE(); + } } - const graph = (g_reg_addr !== null ? { - value: utils.readNumberFromBuf(graphValue.buffer, device.g_display_reg_format, 'BE'), - format: g_format - } : null); + data.displayValues = device.display_values; - return { - graph, - displayValues: device.display_values + return data; + }, + + /** + * @param {number} addr + * @param {"HR" | "IR" | "DI"} type + * @param {import("..").NumberType} format + * @return {Promise} buffer data + */ + async readModbusRegisters(addr, type, format) { + let data; + let len = 1; + + if (format.includes('32')) len = 2; + if (format.includes('64')) len = 4; + if (format.includes('128')) len = 8; + + switch (type) { + case 'HR': + data = await modbusClient.readHoldingRegisters(addr, len); + break; + case 'IR': + data = await modbusClient.readInputRegisters(addr, len); + break; + case 'DI': + data = await modbusClient.readDiscreteInputs(addr, len); + break; + default: + throw new Error('Incorrect modbus register type!'); } + + return data.buffer; } } \ No newline at end of file