From fa7c94b908db10a95d1ce319b6f0ea9932962797 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Tue, 24 Oct 2023 13:13:22 +0300 Subject: [PATCH] progress --- README.md | 47 +++++++++ data.db | Bin 12288 -> 12288 bytes events/index.js | 12 +++ public/css/dist.css | 92 ++++++----------- public/index.html | 158 ++++++++++++++++++++++++------ public/js/api.js | 25 +++++ public/js/app.js | 76 ++++++++++++-- public/js/services/app.service.js | 27 +++++ routes/api.router.js | 4 +- 9 files changed, 336 insertions(+), 105 deletions(-) create mode 100644 README.md create mode 100644 events/index.js create mode 100644 public/js/api.js create mode 100644 public/js/services/app.service.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..f530f7f --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +``` +modbus-logger-app +├─ .gitignore +├─ .prettierrc +├─ app +│ └─ index.js +├─ config +│ ├─ database.config.js +│ ├─ env.config.js +│ └─ modbus-client.config.js +├─ data.db +├─ index.d.ts +├─ jsconfig.json +├─ middlewares +│ ├─ index.js +│ └─ validate-body.middleware.js +├─ nodemon.json +├─ package-lock.json +├─ package.json +├─ public +│ ├─ css +│ │ ├─ dist.css +│ │ ├─ dygraphs.css +│ │ └─ main.css +│ ├─ index.html +│ └─ js +│ ├─ alpine.js +│ ├─ app.js +│ └─ dygraphs.min.js +├─ routes +│ ├─ api.router.js +│ └─ index.js +├─ scripts +│ └─ db-init.script.js +├─ server.js +├─ services +│ ├─ app.service.js +│ └─ index.js +├─ sql +│ └─ init-schema.sql +├─ tailwind.config.js +├─ utils +│ └─ database.util.js +└─ validators + └─ index.js + +``` diff --git a/data.db b/data.db index 1092d8513b3d386af132a9af74a28ffc83f0a09a..b695e92441ce054857d6ea2694172ce6761d7866 100644 GIT binary patch delta 96 zcmZojXh@hK&A4HrjI-bd2EDYGybKHsjJ!J-cz5t0-Yh8K!Mk|}uMZO&BmZLt{>PgI r70&W&>Hw8!05J$iGjKBq%QJ!5Od-wzhDPRk20&=Y_>K9+A_V~emUtC- delta 72 zcmZojXh@hK%~&{5##ykCLC^jsF9QPuBkv9d-W~jhHwy}Q@NVA0>%+vxAi%)De}A)} W!dZSE9iS2@P@Gt(v6)-pD?b3GH4zv9 diff --git a/events/index.js b/events/index.js new file mode 100644 index 0000000..e1f06a1 --- /dev/null +++ b/events/index.js @@ -0,0 +1,12 @@ +import EventEmmiter from "events"; + +const globalEventEmmiter = new EventEmmiter(); + +/** + * Start logging data from modbus slaves + */ +globalEventEmmiter.on("log:start", (pollInterval) => {}); + +globalEventEmmiter.on("log:stop", () => {}); + +export { globalEventEmmiter }; diff --git a/public/css/dist.css b/public/css/dist.css index dda78a9..71deb23 100644 --- a/public/css/dist.css +++ b/public/css/dist.css @@ -587,18 +587,6 @@ video { opacity: 0.7; } -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border-width: 0; -} - .visible { visibility: visible; } @@ -628,32 +616,24 @@ video { margin-left: auto; } -.mt-3 { - margin-top: 0.75rem; -} - .mr-2 { margin-right: 0.5rem; } -.mt-2 { - margin-top: 0.5rem; +.mt-16 { + margin-top: 4rem; } -.mt-6 { - margin-top: 1.5rem; +.mt-3 { + margin-top: 0.75rem; } .mt-4 { margin-top: 1rem; } -.mt-10 { - margin-top: 2.5rem; -} - -.mt-16 { - margin-top: 4rem; +.mt-2 { + margin-top: 0.5rem; } .block { @@ -676,18 +656,6 @@ video { height: 0.25rem; } -.h-8 { - height: 2rem; -} - -.h-12 { - height: 3rem; -} - -.h-24 { - height: 6rem; -} - .h-20 { height: 5rem; } @@ -696,26 +664,6 @@ video { width: 0.25rem; } -.w-8 { - width: 2rem; -} - -.w-12 { - width: 3rem; -} - -.w-36 { - width: 9rem; -} - -.w-32 { - width: 8rem; -} - -.w-24 { - width: 6rem; -} - .w-20 { width: 5rem; } @@ -750,6 +698,24 @@ video { flex-direction: column; } +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + +.space-y-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); +} + +.space-y-10 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2.5rem * var(--tw-space-y-reverse)); +} + .rounded-sm { border-radius: 0.125rem; } @@ -813,16 +779,16 @@ video { font-style: italic; } -.text-gray-700 { - --tw-text-opacity: 1; - color: rgb(55 65 81 / var(--tw-text-opacity)); -} - .text-gray-200 { --tw-text-opacity: 1; color: rgb(229 231 235 / var(--tw-text-opacity)); } +.text-gray-700 { + --tw-text-opacity: 1; + color: rgb(55 65 81 / var(--tw-text-opacity)); +} + .filter { filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } diff --git a/public/index.html b/public/index.html index 5a95dfe..23f05d1 100644 --- a/public/index.html +++ b/public/index.html @@ -13,58 +13,152 @@
-

Main page

+

Monitoring page

+
-
-
+
+

Setup configuration

Fill in the required configuration settings to connect to the Modbus network.


-
+
+ app config state: +

+          
+
- - -
- - - - - + +
-
- - +
+
+ + +
- - +
+ + +
+
- - +
+
+ + +
- - +
+ + +
- - +
+ + +
+ +
+ + +
+ +
+ + +
-
- +
+ + +
+ +
+
diff --git a/public/js/api.js b/public/js/api.js new file mode 100644 index 0000000..82caf60 --- /dev/null +++ b/public/js/api.js @@ -0,0 +1,25 @@ +const urlPrefix = "/api"; + +export default { + async patch(path, data) { + const response = await fetch(`${urlPrefix}${path}`, { + method: "PATCH", + body: new URLSearchParams(data), + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }); + return response; + }, + + async post(path, data) { + const response = await fetch(`${urlPrefix}${path}`, { + method: "POST", + body: new URLSearchParams(data), + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }); + return response; + }, +}; diff --git a/public/js/app.js b/public/js/app.js index f9998b2..3f6b371 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,18 +1,35 @@ // @ts-nocheck import "./alpine.js"; +import api from "./api.js"; document.addEventListener("alpine:init", async () => { Alpine.store("app", { is_configured: false, - config: null, + /** + * Default configuration + */ + config: { + mb_connection_type: "TCP", + mb_tcp_ip: "127.0.0.1", + mb_tcp_port: 502, + mb_rtu_path: "", + mb_rtu_baud: 9600, + mb_rtu_data_bits: 8, + mb_rtu_stop_bits: 1, + mb_rtu_parity: "even", + log_interval_ms: 1000, + }, currentPage: "loading", async init() { - const { config } = await (await fetch("/api/app/config")).json(); - const { is_configured } = await (await fetch("/api/app/is_configured")).json(); - this.is_configured = is_configured; - this.config = config; + const config = await fetch("/api/app/config"); + const is_configured = await fetch("/api/app/is_configured"); - if (is_configured) { + if (config.ok && is_configured.ok) { + this.config = (await config.json()).config; + this.is_configured = (await is_configured.json()).is_configured; + } + + if (this.is_configured) { this.currentPage = "monitoring"; return; } @@ -21,9 +38,52 @@ document.addEventListener("alpine:init", async () => { }, }); - Alpine.data("configAppModal", () => ({ + Alpine.data("configApp", () => ({ + selectedConnectionType: "TCP", + isLoading: false, async configurateApp() { - console.log("Configuration app..."); + try { + const { + mb_connection_type, + mb_tcp_ip, + mb_tcp_port, + mb_rtu_path, + mb_rtu_baud, + mb_rtu_parity, + mb_rtu_data_bits, + mb_rtu_stop_bits, + log_interval_ms, + } = this.$store.app.config; + + if (mb_connection_type === "TCP") { + await api.patch("/app/config", { + mb_connection_type, + mb_tcp_ip, + mb_tcp_port, + log_interval_ms, + }); + + await api.post("/modbus/connect"); + + this.$store.app.currentPage = "monitoring"; + return; + } + + if (mb_connection_type === "RTU") { + await api.patch("/app/config", { + mb_rtu_path, + mb_rtu_parity, + mb_rtu_data_bits, + mb_rtu_stop_bits, + mb_rtu_baud, + }); + await api.post("/modbus_connect"); + this.$store.app.currentPage = "monitoring"; + return; + } + } catch (error) { + console.error("Error while configuring app."); + } }, })); }); diff --git a/public/js/services/app.service.js b/public/js/services/app.service.js new file mode 100644 index 0000000..912f6f2 --- /dev/null +++ b/public/js/services/app.service.js @@ -0,0 +1,27 @@ +import api from "../api"; + +export async function configurateApp(config) { + const { + mb_connection_type, + mb_tcp_ip, + mb_tcp_port, + mb_rtu_path, + mb_rtu_parity, + mb_rtu_data_bits, + mb_rtu_stop_bits, + mb_rtu_baud, + log_interval_ms, + } = config; + let data = {}; + + if (config.mb_connection_type === "TCP") { + data = { mb_connection_type, mb_tcp_ip, mb_tcp_port, log_interval_ms }; + } + + if (config.mb_connection_type === "RTU") { + data = { mb_rtu_path, mb_rtu_parity, mb_rtu_data_bits, mb_rtu_stop_bits, mb_rtu_baud }; + } + + const configRes = await api.patch("/app/config", data); + if (configRes.ok) await api.post("/modbus/connect"); +} diff --git a/routes/api.router.js b/routes/api.router.js index a13df36..6d8f088 100644 --- a/routes/api.router.js +++ b/routes/api.router.js @@ -52,7 +52,7 @@ apiRouter.patch("/app/config", validateBodyMiddleware(appConfigSchema), async (r [mb_tcp_ip, mb_tcp_port, payload.log_interval_ms], ); - return res.status(200).send("Updated"); + return res.status(200).send("Config Updated."); } /* Update RTU configuration */ @@ -71,7 +71,7 @@ apiRouter.patch("/app/config", validateBodyMiddleware(appConfigSchema), async (r `, [mb_rtu_path, mb_rtu_baud, mb_rtu_parity, mb_rtu_data_bits, mb_rtu_stop_bits, payload.log_interval_ms], ); - return res.status(200).send("Updated."); + return res.status(200).send("Config updated."); } return res.status(400).send("Undefined Modbus connection type.");