mirror of
https://github.com/sergeyyarkov/modbus-logger.git
synced 2026-10-11 18:38:51 +03:00
progres
This commit is contained in:
parent
fa7c94b908
commit
a6173f27e9
@ -624,6 +624,10 @@ video {
|
|||||||
margin-top: 4rem;
|
margin-top: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-3 {
|
.mt-3 {
|
||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
}
|
}
|
||||||
@ -632,10 +636,6 @@ video {
|
|||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mt-2 {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@ -694,28 +694,28 @@ video {
|
|||||||
resize: both;
|
resize: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-col {
|
.flex-col {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.justify-between {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.space-y-3 > :not([hidden]) ~ :not([hidden]) {
|
.space-y-3 > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-y-reverse: 0;
|
--tw-space-y-reverse: 0;
|
||||||
margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
|
margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
margin-bottom: calc(0.75rem * 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 {
|
.rounded-sm {
|
||||||
border-radius: 0.125rem;
|
border-radius: 0.125rem;
|
||||||
}
|
}
|
||||||
@ -761,6 +761,10 @@ video {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.align-middle {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
.text-2xl {
|
.text-2xl {
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
@ -789,6 +793,15 @@ video {
|
|||||||
color: rgb(55 65 81 / var(--tw-text-opacity));
|
color: rgb(55 65 81 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-red-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(220 38 38 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-70 {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
.filter {
|
.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);
|
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);
|
||||||
}
|
}
|
||||||
@ -828,6 +841,11 @@ hr {
|
|||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: all !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.dark\:text-gray-600 {
|
.dark\:text-gray-600 {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
|
|||||||
@ -24,3 +24,8 @@ input {
|
|||||||
hr {
|
hr {
|
||||||
@apply my-2;
|
@apply my-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
pointer-events: all !important;
|
||||||
|
}
|
||||||
|
|||||||
@ -26,11 +26,11 @@
|
|||||||
Fill in the required configuration settings to connect to the Modbus network.
|
Fill in the required configuration settings to connect to the Modbus network.
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
<div>
|
<!-- <div>
|
||||||
<span>app config state:</span>
|
<span>app config state:</span>
|
||||||
<pre x-text="JSON.stringify($store.app.config, undefined, 2)"></pre>
|
<pre x-text="JSON.stringify($store.app.config, undefined, 2)"></pre>
|
||||||
</div>
|
</div> -->
|
||||||
<form @submit.prevent="configurateApp" action="#">
|
<form @submit.prevent="configurateApp()" action="#">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<label class="block" for="connection_type">Network type</label>
|
<label class="block" for="connection_type">Network type</label>
|
||||||
@ -157,8 +157,20 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3 flex flex-row justify-between items-center">
|
||||||
<button class="btn ml-auto" type="submit">Save</button>
|
<div>
|
||||||
|
<button
|
||||||
|
x-bind:disabled="isLoading"
|
||||||
|
x-bind:class="isLoading && 'opacity-70'"
|
||||||
|
class="btn ml-auto"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="text-red-600" x-text="errorMessage">Error while connection to Modbus network</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,15 @@
|
|||||||
const urlPrefix = "/api";
|
const urlPrefix = "/api";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response handler
|
||||||
|
* @param {Response} response
|
||||||
|
*/
|
||||||
|
async function handle(response) {
|
||||||
|
const data = await response.json();
|
||||||
|
if (!response.ok) return Promise.reject((data && data.message) || response.statusText);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async patch(path, data) {
|
async patch(path, data) {
|
||||||
const response = await fetch(`${urlPrefix}${path}`, {
|
const response = await fetch(`${urlPrefix}${path}`, {
|
||||||
@ -9,7 +19,7 @@ export default {
|
|||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return response;
|
return handle(response);
|
||||||
},
|
},
|
||||||
|
|
||||||
async post(path, data) {
|
async post(path, data) {
|
||||||
@ -20,6 +30,13 @@ export default {
|
|||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return response;
|
return await handle(response);
|
||||||
|
},
|
||||||
|
|
||||||
|
async get(path) {
|
||||||
|
const response = await fetch(`${urlPrefix}${path}`, {
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
return await handle(response);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,28 +21,33 @@ document.addEventListener("alpine:init", async () => {
|
|||||||
},
|
},
|
||||||
currentPage: "loading",
|
currentPage: "loading",
|
||||||
async init() {
|
async init() {
|
||||||
const config = await fetch("/api/app/config");
|
try {
|
||||||
const is_configured = await fetch("/api/app/is_configured");
|
const { config } = await api.get("/app/config");
|
||||||
|
const { is_configured } = await api.get("/app/is_configured");
|
||||||
|
|
||||||
if (config.ok && is_configured.ok) {
|
this.is_configured = is_configured;
|
||||||
this.config = (await config.json()).config;
|
|
||||||
this.is_configured = (await is_configured.json()).is_configured;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.is_configured) {
|
if (config) this.config = config;
|
||||||
|
if (is_configured) {
|
||||||
this.currentPage = "monitoring";
|
this.currentPage = "monitoring";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentPage = "configuration";
|
this.currentPage = "configuration";
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error("Error on initializing app.");
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Alpine.data("configApp", () => ({
|
Alpine.data("configApp", () => ({
|
||||||
selectedConnectionType: "TCP",
|
selectedConnectionType: "TCP",
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
|
errorMessage: "",
|
||||||
async configurateApp() {
|
async configurateApp() {
|
||||||
try {
|
this.isLoading = true;
|
||||||
|
this.errorMessage = "";
|
||||||
|
let data = {};
|
||||||
const {
|
const {
|
||||||
mb_connection_type,
|
mb_connection_type,
|
||||||
mb_tcp_ip,
|
mb_tcp_ip,
|
||||||
@ -56,34 +61,38 @@ document.addEventListener("alpine:init", async () => {
|
|||||||
} = this.$store.app.config;
|
} = this.$store.app.config;
|
||||||
|
|
||||||
if (mb_connection_type === "TCP") {
|
if (mb_connection_type === "TCP") {
|
||||||
await api.patch("/app/config", {
|
data = {
|
||||||
mb_connection_type,
|
mb_connection_type,
|
||||||
mb_tcp_ip,
|
mb_tcp_ip,
|
||||||
mb_tcp_port,
|
mb_tcp_port,
|
||||||
log_interval_ms,
|
log_interval_ms,
|
||||||
});
|
};
|
||||||
|
|
||||||
await api.post("/modbus/connect");
|
|
||||||
|
|
||||||
this.$store.app.currentPage = "monitoring";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mb_connection_type === "RTU") {
|
if (mb_connection_type === "RTU") {
|
||||||
await api.patch("/app/config", {
|
data = {
|
||||||
|
mb_connection_type,
|
||||||
mb_rtu_path,
|
mb_rtu_path,
|
||||||
mb_rtu_parity,
|
mb_rtu_parity,
|
||||||
mb_rtu_data_bits,
|
mb_rtu_data_bits,
|
||||||
mb_rtu_stop_bits,
|
mb_rtu_stop_bits,
|
||||||
mb_rtu_baud,
|
mb_rtu_baud,
|
||||||
});
|
log_interval_ms,
|
||||||
await api.post("/modbus_connect");
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
await api.patch("/app/config", data);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await api.post("/modbus/connect");
|
||||||
this.$store.app.currentPage = "monitoring";
|
this.$store.app.currentPage = "monitoring";
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error while configuring app.");
|
this.errorMessage = "Modbus connection error.";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isLoading = false;
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
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");
|
|
||||||
}
|
|
||||||
@ -25,7 +25,7 @@ const apiRouter = express.Router();
|
|||||||
apiRouter.get("/app/config", async (req, res, next) => {
|
apiRouter.get("/app/config", async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const data = await appService.getConfig(db);
|
const data = await appService.getConfig(db);
|
||||||
if (!data) return res.status(404).json({ config: null });
|
if (!data) return res.status(200).json({ config: null });
|
||||||
return res.status(200).json({ config: data });
|
return res.status(200).json({ config: data });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
@ -52,7 +52,7 @@ apiRouter.patch("/app/config", validateBodyMiddleware(appConfigSchema), async (r
|
|||||||
[mb_tcp_ip, mb_tcp_port, payload.log_interval_ms],
|
[mb_tcp_ip, mb_tcp_port, payload.log_interval_ms],
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.status(200).send("Config Updated.");
|
return res.status(200).json({ message: "Config Updated." });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update RTU configuration */
|
/* Update RTU configuration */
|
||||||
@ -71,10 +71,10 @@ 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],
|
[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("Config updated.");
|
return res.status(200).json({ message: "Config updated." });
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(400).send("Undefined Modbus connection type.");
|
return res.status(400).json({ message: "Undefined Modbus connection type." });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ apiRouter.get("/app/is_configured", async (req, res, next) => {
|
|||||||
const config = await appService.getConfig(db);
|
const config = await appService.getConfig(db);
|
||||||
let is_configured = false;
|
let is_configured = false;
|
||||||
|
|
||||||
if (!config) return res.status(200).send({ is_configured });
|
if (!config) return res.status(200).json({ is_configured });
|
||||||
|
|
||||||
const isValuesExists = (colPrefix) => {
|
const isValuesExists = (colPrefix) => {
|
||||||
const keys = Object.keys(config).filter((k) => k.includes(colPrefix));
|
const keys = Object.keys(config).filter((k) => k.includes(colPrefix));
|
||||||
@ -99,7 +99,7 @@ apiRouter.get("/app/is_configured", async (req, res, next) => {
|
|||||||
if (config.mb_connection_type === "TCP") is_configured = isValuesExists("mb_tcp");
|
if (config.mb_connection_type === "TCP") is_configured = isValuesExists("mb_tcp");
|
||||||
if (config.mb_connection_type === "RTU") is_configured = isValuesExists("mb_rtu");
|
if (config.mb_connection_type === "RTU") is_configured = isValuesExists("mb_rtu");
|
||||||
|
|
||||||
return res.status(200).send({ is_configured });
|
return res.status(200).json({ is_configured });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ apiRouter.get("/app/is_configured", async (req, res, next) => {
|
|||||||
apiRouter.post("/modbus/connect", async (req, res, next) => {
|
apiRouter.post("/modbus/connect", async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const config = await appService.getConfig(db);
|
const config = await appService.getConfig(db);
|
||||||
if (!config) return res.status(400).send("Application is not configured");
|
if (!config) return res.status(400).json({ message: "Application is not configured" });
|
||||||
|
|
||||||
if (modbusClient.isOpen) {
|
if (modbusClient.isOpen) {
|
||||||
modbusClient.close(undefined);
|
modbusClient.close(undefined);
|
||||||
@ -120,7 +120,7 @@ apiRouter.post("/modbus/connect", async (req, res, next) => {
|
|||||||
|
|
||||||
if (config.mb_connection_type === "TCP") {
|
if (config.mb_connection_type === "TCP") {
|
||||||
await modbusClient.connectTCP(config.mb_tcp_ip, { port: config.mb_tcp_port });
|
await modbusClient.connectTCP(config.mb_tcp_ip, { port: config.mb_tcp_port });
|
||||||
return res.status(200).send("Connected.");
|
return res.status(200).json({ message: "Connected." });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.mb_connection_type === "RTU") {
|
if (config.mb_connection_type === "RTU") {
|
||||||
@ -130,10 +130,10 @@ apiRouter.post("/modbus/connect", async (req, res, next) => {
|
|||||||
parity: config.mb_rtu_parity,
|
parity: config.mb_rtu_parity,
|
||||||
stopBits: config.mb_rtu_stop_bits,
|
stopBits: config.mb_rtu_stop_bits,
|
||||||
});
|
});
|
||||||
return res.status(200).send("Connected.");
|
return res.status(200).json({ message: "Connected." });
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(400).send("Connection type is invalid.");
|
return res.status(400).json({ message: "Connection type is invalid." });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ apiRouter.post("/modbus/connect", async (req, res, next) => {
|
|||||||
|
|
||||||
apiRouter.post("/modbus/close", (req, res, next) => {
|
apiRouter.post("/modbus/close", (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
if (!modbusClient.isOpen) return res.status(400).send("Already closed.");
|
if (!modbusClient.isOpen) return res.status(400).json({ message: "Already closed." });
|
||||||
modbusClient.close(undefined);
|
modbusClient.close(undefined);
|
||||||
modbusClient.destroy(undefined);
|
modbusClient.destroy(undefined);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -149,4 +149,24 @@ apiRouter.post("/modbus/close", (req, res, next) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
apiRouter.get("/modbus/data_stream", async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
if (!modbusClient.isOpen) return res.status(503).json({ message: "Modbus connection closed." });
|
||||||
|
|
||||||
|
res.setHeader("Cache-Control", "no-cache");
|
||||||
|
res.setHeader("Content-Type", "text/event-stream");
|
||||||
|
res.setHeader("Connection", "keep-alive");
|
||||||
|
|
||||||
|
let interval = setInterval(async () => {
|
||||||
|
const { data } = await modbusClient.readHoldingRegisters(0, 1);
|
||||||
|
res.write("event: messsage\n");
|
||||||
|
res.write(`data: ${JSON.stringify({ data })}`);
|
||||||
|
res.write("\n\n");
|
||||||
|
}, 1000);
|
||||||
|
req.on("close", () => clearInterval(interval));
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export { apiRouter };
|
export { apiRouter };
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
CREATE TABLE IF NOT EXISTS "app_config" (
|
CREATE TABLE IF NOT EXISTS "app_config" (
|
||||||
"id" INTEGER,
|
"id" INTEGER,
|
||||||
"mb_connection_type" VARCHAR(3) NOT NULL DEFAULT "RTU" CHECK(mb_connection_type IN ('TCP','RTU')),
|
"mb_connection_type" VARCHAR(3) NOT NULL DEFAULT "RTU" CHECK(mb_connection_type IN ('TCP','RTU')),
|
||||||
"mb_tcp_ip" VARCHAR(15),
|
"mb_tcp_ip" VARCHAR(15) NOT NULL DEFAULT "127.0.0.1",
|
||||||
"mb_tcp_port" INTEGER,
|
"mb_tcp_port" INTEGER NOT NULL DEFAULT 502,
|
||||||
"mb_rtu_path" VARCHAR(10),
|
"mb_rtu_path" VARCHAR(10) NOT NULL DEFAULT "",
|
||||||
"mb_rtu_baud" REAL,
|
"mb_rtu_baud" INTEGER NOT NULL DEFAULT 9600,
|
||||||
"mb_rtu_parity" VARCHAR(5) CHECK(mb_rtu_parity IN ("even", "odd", "none")),
|
"mb_rtu_parity" VARCHAR(5) NOT NULL DEFAULT "none" CHECK(mb_rtu_parity IN ("even", "odd", "none")),
|
||||||
"mb_rtu_data_bits" INTEGER,
|
"mb_rtu_data_bits" INTEGER NOT NULL DEFAULT 8,
|
||||||
"mb_rtu_stop_bits" INTEGER,
|
"mb_rtu_stop_bits" INTEGER NOT NULL DEFAULT 1,
|
||||||
"log_interval_ms" INTEGER DEFAULT 1000 NOT NULL,
|
"log_interval_ms" INTEGER DEFAULT 1000 NOT NULL,
|
||||||
CONSTRAINT "id_unique" CHECK(id=0),
|
CONSTRAINT "id_unique" CHECK(id=0),
|
||||||
CONSTRAINT "min_interval_check" CHECK(log_interval_ms >= 1000)
|
CONSTRAINT "min_interval_check" CHECK(log_interval_ms >= 1000)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user