read display values

This commit is contained in:
Sergey Yarkov 2023-11-02 14:43:39 +03:00
parent 076e3b7aba
commit 92d5449246
9 changed files with 41 additions and 27 deletions

View File

@ -75,7 +75,8 @@ export const modbusController = {
'id', dv.id, 'id', dv.id,
'name', dv.name, 'name', dv.name,
'reg_addr', dv.reg_addr, 'reg_addr', dv.reg_addr,
'reg_format', dv.reg_format 'reg_format', dv.reg_format,
'reg_type', dv.reg_type
), ', ' ), ', '
) || ']' END AS display_values ) || ']' END AS display_values
FROM modbus_slaves AS ms FROM modbus_slaves AS ms

BIN
data.db

Binary file not shown.

4
index.d.ts vendored
View File

@ -10,6 +10,7 @@ export type AppConfig = {
log_interval_ms: number; log_interval_ms: number;
}; };
export type RegisterType = "HR" | "IR"
export type NumberType = 'UI16' | 'I16' | 'UI32' | 'I32' | 'FP32' export type NumberType = 'UI16' | 'I16' | 'UI32' | 'I32' | 'FP32'
export type DisplayValue = { export type DisplayValue = {
@ -18,7 +19,8 @@ export type DisplayValue = {
name: string; name: string;
slave_id: number; slave_id: number;
reg_addr: number; reg_addr: number;
reg_format: number; reg_format: NumberType;
reg_type: RegisterType;
} }
export type ModbusDevice = { export type ModbusDevice = {

View File

@ -34,8 +34,8 @@ CREATE TABLE IF NOT EXISTS "display_values" (
"name" VARCHAR(32) NOT NULL, "name" VARCHAR(32) NOT NULL,
"slave_id" INTEGER NOT NULL, "slave_id" INTEGER NOT NULL,
"reg_addr" INTEGER DEFAULT 0 NOT NULL CHECK(reg_addr >= 0 AND reg_addr <= 65534), "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_type" VARCHAR(3) NOT NULL CHECK(reg_type IN("HR", "IR")) DEFAULT "IR",
"reg_format" INTEGER NOT NULL CHECK(reg_format IN(16, 32)) DEFAULT 16, "reg_format" VARCHAR(5) NOT NULL CHECK(reg_format IN("UI16", "I16", "UI32", "I32", "FP32")) DEFAULT "UI16",
PRIMARY KEY("id"), PRIMARY KEY("id"),
FOREIGN KEY("slave_id") REFERENCES modbus_slaves("id") ON DELETE CASCADE FOREIGN KEY("slave_id") REFERENCES modbus_slaves("id") ON DELETE CASCADE
); );
@ -64,16 +64,17 @@ INSERT INTO "modbus_slaves" (
(4, "Device #4", NULL, NULL, NULL, "Label 4", 0); (4, "Device #4", NULL, NULL, NULL, "Label 4", 0);
INSERT INTO "display_values" ( INSERT INTO "display_values" (
"id", "name", "slave_id", "reg_addr", "reg_format" "id", "name", "slave_id", "reg_addr", "reg_format", "reg_type"
) VALUES ) VALUES
(1, "CV1", 1, 10, 16), (1, "CV1", 1, 10, "UI16", "IR"),
(2, "CV2", 1, 11, 16), (2, "CV2", 1, 11, "I16", "IR"),
(3, "SP", 1, 12, 16), (3, "SP", 1, 12, "UI32", "IR"),
(4, "CV1", 2, 13, 16), (4, "CV1", 2, 13, "I32", "IR"),
(5, "CV2", 2, 14, 16), (5, "CV2", 2, 14, "I16", "IR"),
(6, "SP", 2, 15, 16), (6, "SP", 2, 15, "UI16", "IR"),
(7, "CV1", 3, 16, 16), (7, "CV1", 3, 16, "UI16", "HR"),
(8, "SP", 3, 17, 16); (8, "CV2", 3, 17, "FP32", "HR"),
(9, "SP", 3, 15, "UI16", "IR");
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Down -- Down
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -238,6 +238,7 @@
<div class="flex flex-col"> <div class="flex flex-col">
<span>Value: <span x-text="value?.data"></span></span> <span>Value: <span x-text="value?.data"></span></span>
<span>Reg Addr: <span x-text="value?.reg_addr"></span></span> <span>Reg Addr: <span x-text="value?.reg_addr"></span></span>
<span>Reg Type: <span x-text="value?.reg_type"></span></span>
<span>Format: <span x-text="value?.reg_format"></span></span> <span>Format: <span x-text="value?.reg_format"></span></span>
</div> </div>
</div> </div>

View File

@ -32,10 +32,10 @@ document.addEventListener("alpine:init", async () => {
const { is_configured } = await api.get("/app/is_configured"); const { is_configured } = await api.get("/app/is_configured");
this.is_configured = is_configured; this.is_configured = is_configured;
connStatusEventSource.onmessage = (e) => (this.is_opened = e.data === "true");
if (config) this.config = config; if (config) this.config = config;
if (is_configured) { if (is_configured) {
connStatusEventSource.onmessage = (e) => (this.is_opened = e.data === "true");
await utils.wait(500); await utils.wait(500);
this.currentPage = "monitoring"; this.currentPage = "monitoring";
return; return;

View File

@ -7,7 +7,7 @@ export const modbusService = {
* @return {Promise<import("..").EventDataStream>} * @return {Promise<import("..").EventDataStream>}
*/ */
async readDataFromDevice(device) { async readDataFromDevice(device) {
const { g_display_reg_format, g_display_reg_addr, g_display_reg_type } = device; const { g_display_reg_format, g_display_reg_addr, g_display_reg_type, display_values } = device;
/** @type {import("..").EventDataStream} */ /** @type {import("..").EventDataStream} */
const data = { graph: null, displayValues: [] }; const data = { graph: null, displayValues: [] };
@ -16,22 +16,22 @@ export const modbusService = {
/* Read data for graph */ /* Read data for graph */
if (g_display_reg_addr !== null) { if (g_display_reg_addr !== null) {
const graphValue = await this.readModbusRegisters(g_display_reg_addr, g_display_reg_type, g_display_reg_format); const graphValueBuf = await this.readModbusRegisters(g_display_reg_addr, g_display_reg_type, g_display_reg_format);
data.graph = { data.graph = {
value: utils.readNumberFromBuf(graphValue, device.g_display_reg_format, 'BE'), value: utils.readNumberFromBuf(graphValueBuf, device.g_display_reg_format, 'BE'),
format: g_display_reg_format format: g_display_reg_format
} }
} }
/* Read data for display values */ /* Read data for display values */
if (device.display_values) { if (display_values) {
for (const value of device.display_values) { for (const v of device.display_values) {
value.data = Buffer.from((await this.readModbusRegisters(value.reg_addr, 'HR', 'UI16'))).readUInt16BE(); const displayValueBuf = await this.readModbusRegisters(v.reg_addr, v.reg_type, v.reg_format)
v.data = utils.readNumberFromBuf(displayValueBuf, v.reg_format, 'BE')
data.displayValues.push(v);
} }
} }
data.displayValues = device.display_values;
return data; return data;
}, },
@ -45,9 +45,15 @@ export const modbusService = {
let data; let data;
let len = 1; let len = 1;
if (format.includes('32')) len = 2; switch (format) {
if (format.includes('64')) len = 4; case 'UI32':
if (format.includes('128')) len = 8; case 'I32':
case 'FP32':
len = 2;
break;
default:
break;
}
switch (type) { switch (type) {
case 'HR': case 'HR':

View File

@ -9,11 +9,13 @@ export function readNumberFromBuf(buf, type, order) {
if (type === 'UI16' && order === 'BE') return Buffer.from(buf).readUInt16BE(); if (type === 'UI16' && order === 'BE') return Buffer.from(buf).readUInt16BE();
if (type === 'I16' && order === 'BE') return Buffer.from(buf).readInt16BE(); if (type === 'I16' && order === 'BE') return Buffer.from(buf).readInt16BE();
if (type === 'UI32' && order === 'BE') return Buffer.from(buf).readUint32BE(); if (type === 'UI32' && order === 'BE') return Buffer.from(buf).readUint32BE();
if (type === 'I32' && order === 'BE') return Buffer.from(buf).readInt32BE();
if (type === 'FP32' && order === 'BE') return Buffer.from(buf).readFloatBE(); if (type === 'FP32' && order === 'BE') return Buffer.from(buf).readFloatBE();
/* Little-Endian */ /* Little-Endian */
if (type === 'UI16' && order === 'LE') return Buffer.from(buf).readUInt16LE(); if (type === 'UI16' && order === 'LE') return Buffer.from(buf).readUInt16LE();
if (type === 'I16' && order === 'LE') return Buffer.from(buf).readInt16LE(); if (type === 'I16' && order === 'LE') return Buffer.from(buf).readInt16LE();
if (type === 'UI32' && order === 'LE') return Buffer.from(buf).readUint32LE(); if (type === 'UI32' && order === 'LE') return Buffer.from(buf).readUint32LE();
if (type === 'I32' && order === 'LE') return Buffer.from(buf).readInt32LE();
if (type === 'FP32' && order === 'LE') return Buffer.from(buf).readFloatLE(); if (type === 'FP32' && order === 'LE') return Buffer.from(buf).readFloatLE();
} }

View File

@ -5,7 +5,8 @@ export const displayValueSchema = object({
name: string().required(), name: string().required(),
slave_id: number().required(), slave_id: number().required(),
reg_addr: number().min(0).max(65534).required(), reg_addr: number().min(0).max(65534).required(),
reg_format: number().oneOf([16, 32]).required() reg_format: string().oneOf(["UI16", "I16", "UI32", "I32", "FP32"]).required(),
reg_type: string().oneOf(["HR", "IR"]).required()
}) })
export const removeDisplayValueSchema = displayValueSchema.pick(['id']); export const removeDisplayValueSchema = displayValueSchema.pick(['id']);