From c0fb0e8122fc246c625aa75144d58a0359589a7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= <ondra@ondrovo.com>
Date: Wed, 3 Jul 2024 12:45:55 +0200
Subject: [PATCH] make demo server interactive

---
 src/main.c | 189 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 131 insertions(+), 58 deletions(-)

diff --git a/src/main.c b/src/main.c
index 83d2f97..1ce35ba 100644
--- a/src/main.c
+++ b/src/main.c
@@ -12,83 +12,156 @@ ModbusException_t startOfAccess(ModbusSlave_t *ms, ModbusFunction_t fcx, uint8_t
 
 void endOfAccess(ModbusSlave_t *ms) { printf("End of access\n"); }
 
+typedef struct {
+    uint16_t num;
+    uint16_t value;
+} register_slot_t;
+
+typedef struct {
+    uint16_t num;
+    bool value;
+} coil_slot_t;
+
+//@formatter:off
+static register_slot_t holdings[] = {
+    {1, 10},
+    {2, 20},
+    {3, 30},
+    {4, 40},
+    {5, 50},
+    {7, 70},
+    {0xffff, 0}
+};
+
+static register_slot_t inputs[] = {
+    {1, 11},
+    {2, 21},
+    {3, 31},
+    {4, 41},
+    {5, 51},
+    {7, 71},
+    {0xffff, 0}
+};
+
+static coil_slot_t coils[] = {
+    {1, 1},
+    {2, 0},
+    {3, 1},
+    {4, 0},
+    {5, 1},
+    {7, 1},
+    {0xffff, 0}
+};
+
+static coil_slot_t discretes[] = {
+    {1, 0},
+    {2, 1},
+    {3, 1},
+    {4, 1},
+    {5, 1},
+    {7, 0},
+    {0xffff, 0}
+};
+//@formatter:on
+
+
 ModbusException_t readHolding(ModbusSlave_t *ms, uint16_t i, uint16_t *out) {
     printf("rh %d\n", i);
-    switch (i) {
-        case 107:
-            *out = 0xAE41;
-            break;
-        case 108:
-            *out = 0x5652;
-            break;
-        case 109:
-            *out = 0x4340;
-            break;
-        default:
-            return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
+
+    const register_slot_t *p = holdings;
+    while (p->num != 0xffff) {
+        if (p->num == i) {
+            *out = p->value;
+            return 0;
+        }
+        p++;
     }
-    return 0;
+
+    return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
 }
+
 ModbusException_t readInput(ModbusSlave_t *ms, uint16_t i, uint16_t *out) {
     printf("ri %d\n", i);
-    switch (i) {
-        case 8:
-            *out = 0xa;
-            break;
-        default:
-            return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
+
+    const register_slot_t *p = inputs;
+    while (p->num != 0xffff) {
+        if (p->num == i) {
+            *out = p->value;
+            return 0;
+        }
+        p++;
     }
-    return 0;
+
+    return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
 }
-ModbusException_t readCoil(ModbusSlave_t *ms, uint16_t i, bool *out) {
-    uint8_t store[] = {
-            0b11001101, 0b01101011, 0b10110010, 0b00001110, 0b00011011,
-    };
 
-    if (i >= 19 && i <= 55) {
-        int pos = i - 19;
-        *out = 0 != (store[pos / 8] & (1 << (pos % 8)));
-    } else {
-        return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
+ModbusException_t readCoil(ModbusSlave_t *ms, uint16_t i, bool *out) {
+    const coil_slot_t *p = coils;
+    while (p->num != 0xffff) {
+        if (p->num == i) {
+            *out = p->value;
+            return 0;
+        }
+        p++;
     }
-    return 0;
+
+    return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
 }
-ModbusException_t readDiscrete(ModbusSlave_t *ms, uint16_t i, bool *out) {
-    uint8_t store[] = {
-            0b10101100,
-            0b11011011,
-            0b00110101,
-    };
 
-    if (i >= 196 && i <= 217) {
-        int pos = i - 196;
-        *out = 0 != (store[pos / 8] & (1 << (pos % 8)));
-    } else {
-        return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
+ModbusException_t readDiscrete(ModbusSlave_t *ms, uint16_t i, bool *out) {
+    const coil_slot_t *p = discretes;
+    while (p->num != 0xffff) {
+        if (p->num == i) {
+            *out = p->value;
+            return 0;
+        }
+        p++;
     }
-    return 0;
+
+    return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
 }
 
 ModbusException_t writeCoil(ModbusSlave_t *pSlave, uint16_t i, bool b) {
     printf("Write coil %d <- %d\n", i, b);
-    return 0;
+
+    coil_slot_t *p = coils;
+    while (p->num != 0) {
+        if (p->num == i) {
+            p->value = b;
+            return 0;
+        }
+        p++;
+    }
+
+    return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
 }
-ModbusException_t writeHolding(ModbusSlave_t *pSlave, uint16_t i, uint16_t i1) {
-    printf("Write reg %d <- %d\n", i, i1);
-    return 0;
+
+ModbusException_t writeHolding(ModbusSlave_t *pSlave, uint16_t i, uint16_t val) {
+    printf("Write reg %d <- %d\n", i, val);
+
+    register_slot_t *p = holdings;
+    while (p->num != 0) {
+        if (p->num == i) {
+            p->value = val;
+            return 0;
+        }
+        p++;
+    }
+
+    return MB_EXCEPTION_ILLEGAL_DATA_ADDRESS;
 }
 
 static ModbusSlave_t ms = {
-        .addr = 1,
-        .proto = MB_PROTO_TCP,
-        .startOfAccess = startOfAccess,
-        .endOfAccess = endOfAccess,
-        .readHolding = readHolding,
-        .readInput = readInput,
-        .readCoil = readCoil,
-        .readDiscrete = readDiscrete,
-        .writeCoil = writeCoil,
-        .writeHolding = writeHolding,
+    .addr = 1,
+    .proto = MB_PROTO_TCP,
+    .startOfAccess = startOfAccess,
+    .endOfAccess = endOfAccess,
+    .readHolding = readHolding,
+    .readInput = readInput,
+    .readCoil = readCoil,
+    .readDiscrete = readDiscrete,
+    .writeCoil = writeCoil,
+    .writeHolding = writeHolding,
 };
 
 int msg_received_fce(int fd, const simple_msg_t *msg) {
@@ -103,8 +176,8 @@ int msg_received_fce(int fd, const simple_msg_t *msg) {
         return 1; // kick the client
 
     simple_msg_t resp = {
-            .data = resp_buf,
-            .len = resp_size,
+        .data = resp_buf,
+        .len = resp_size,
     };
     simple_tcp_send(fd, &resp);