From 0074eac5d88376193a3362f0de68196a8e46168c Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 15 Jul 2025 17:37:45 +0300 Subject: [PATCH] add server for realtime monitoring and parameters changing --- modbus_params/dictionary.dic | 216 +++++++++++++++---------------- modbus_params/main.c | 14 +- modbus_params/modbus.c | 52 +++++--- modbus_params/modbus.h | 4 +- modbus_params/modbus_param.files | 2 + modbus_params/relay.dic | 4 + modbus_params/server.c | 122 +++++++++++++++++ modbus_params/server.h | 23 ++++ 8 files changed, 312 insertions(+), 125 deletions(-) create mode 100644 modbus_params/relay.dic create mode 100644 modbus_params/server.c create mode 100644 modbus_params/server.h diff --git a/modbus_params/dictionary.dic b/modbus_params/dictionary.dic index 4aefe87..28843d8 100644 --- a/modbus_params/dictionary.dic +++ b/modbus_params/dictionary.dic @@ -33,12 +33,12 @@ F01.11 61707 0 0 # Постоянный ток торможения во вр F01.12 61708 0 0 # Время торможения пост. током во время остановки х10, сек. F01.13 61709 0 0 # Время бездействия между сменой направлений вращения х10, сек. F01.14 61710 50 0 # Частота остановки х10, Гц -F01.15 61711 0 0 # Зарезервировано -F01.16 61712 0 0 # Зарезервировано +F01.15 61711 0 1 # Зарезервировано +F01.16 61712 0 1 # Зарезервировано F01.17 61713 0 0 # Перезапуск с клемм после включения [0 — не действ. 1 - действует] F01.18 61714 0 0 # Перезапуск после потери напряжения [0 — запрет; 1 - перезапуск] F01.19 61715 10 0 # Задержка перезапуска х10, сек. [0.0 до 6000.0] (Только если F1.18 = 1) -F01.20 61716 0 0 # Зарезервировано +F01.20 61716 0 1 # Зарезервировано F01.21 61717 0 0 # Действие, если выходная частота меньше минимальной; 0 — работа на мин.частоте; 1 - остановка; 2 - работа на нулевой скорости вращения. F01.22 61718 5000 0 # Задание частоты при работе в пожарном режиме (х100), Гц. F02.00 61952 0 0 # Тип нагрузки [0 — тип G; 1 – тип P;] @@ -53,19 +53,19 @@ F02.08 61960 1264 0 # Сопротивление ротора х100, Ом (З F02.09 61961 67 0 # Индуктивность рассеивания х10, мГн (Значение после автонастройки!) F02.10 61962 956 0 # Индуктивность двигателя х10, мГн (Значение после автонастройки!) F02.11 61963 33 0 # Ток холостого хода х10, А (Значение после автонастройки!) -F02.12 61964 880 0 # Зарезервировано -F02.13 61965 810 0 # Зарезервировано -F02.14 61966 750 0 # Зарезервировано +F02.12 61964 880 1 # Зарезервировано +F02.13 61965 810 1 # Зарезервировано +F02.14 61966 750 1 # Зарезервировано F02.15 61967 0 0 # Выбор типа энкодера F02.16 61968 1024 0 # Число импульсов энкодера на оборот F02.17 61969 0 0 # Последовательность фаз энкодера ABZ F02.18 61970 1 0 # Количество пар полюсов резольвера -F02.19 61971 1 0 # Зарезервировано -F02.20 61972 3 0 # Зарезервировано -F02.21 61973 3 0 # Зарезервировано -F02.22 61974 10 0 # Зарезервировано -F02.23 61975 10 0 # Зарезервировано -F02.24 61976 1000 0 # Зарезервировано +F02.19 61971 1 1 # Зарезервировано +F02.20 61972 3 1 # Зарезервировано +F02.21 61973 3 1 # Зарезервировано +F02.22 61974 10 1 # Зарезервировано +F02.23 61975 10 1 # Зарезервировано +F02.24 61976 1000 1 # Зарезервировано F02.25 61977 1 0 # Защита от перегрузки [0 — не действует; 1 — действует;] F02.26 61978 1000 0 # Коэффициент защиты от перегрузки х10, % [F02.26 x F02.04] F03.00 62208 30 0 # Пропорциональный коэффициент контура скорости 1 @@ -119,7 +119,7 @@ F04.30 62494 50 0 # Время понижения напряжения х10, F04.31 62495 1000 0 # Максимальное выходное напряжение х10, % F04.32 62496 0 0 # Минимальное выходное напряжение х10, % F04.33 62497 1 0 # Выбор функции АВР -F04.34 62498 400 0 # Зарезервировано +F04.34 62498 400 1 # Зарезервировано F05.00 62720 0 0 # Выбор клеммы DI5 F05.01 62721 1 0 # Клемма DI1 F05.02 62722 4 0 # Клемма DI2 @@ -149,7 +149,7 @@ F05.25 62745 0 0 # Задержка включения клеммы DI7 х100 F05.26 62746 0 0 # Задержка выключения клеммы DI7 х1000, сек. F05.27 62747 0 0 # Задержка включения клеммы DI8 х1000, сек. F05.28 62748 0 0 # Задержка выключения клеммы DI8 х1000, сек. -F05.29 62749 0 0 # Зарезервировано +F05.29 62749 0 1 # Зарезервировано F05.30 62750 0 0 # Нижний предел частоты DI5 х100, КГц F05.31 62751 0 0 # Настройка нижнего предела частоты DI5 х10, % F05.32 62752 5000 0 # Верхний предел частоты DI5 х100, КГц @@ -212,46 +212,46 @@ F07.04 63236 255 0 # Параметры состояния при остан F07.05 63237 100 0 # Коэффициент частоты х100 F07.06 63238 1000 0 # Скорость вращения х10, % F07.07 63239 10 0 # Коэффициент линейной скорости х10, % -F07.08 63240 36 0 # Температура выпрямителя, С -F07.09 63241 36 0 # Температура инвертора, С -F07.10 63242 60770 0 # Версия ПО -F07.11 63243 0 0 # Время наработки, час. -F07.12 63244 0 0 # Нижний предел сигнализации AI1, В -F07.13 63245 680 0 # Верхний предел сигнализации AI1, В -F07.14 63246 0 0 # Выбор канала ограничения верхнего предела выхода ПИД-регулятора -F07.15 63247 15 0 # Номинальная мощность ПЧ х10, КВт -F07.16 63248 380 0 # Номинальное напряжение, В -F07.17 63249 75 0 # Номинальный ток х10, А -F07.18 63250 0 0 # Текущая ошибка -F07.19 63251 0 0 # Ошибка при предыдущем отключении -F07.20 63252 0 0 # Ошибка при 2-м отключении -F07.21 63253 0 0 # Ошибка при 3-м отключении -F07.22 63254 0 0 # Ошибка при 4-м отключении -F07.23 63255 0 0 # Ошибка при 5-м отключении -F07.24 63256 0 0 # Частота в момент текущей аварии х100, Гц -F07.25 63257 0 0 # Опорная частота в момент текущей аварии х100, Гц -F07.26 63258 0 0 # Выходное напряжение в момент текущей аварии, В -F07.27 63259 0 0 # Выходной ток в момент текущей аварии х10, В -F07.28 63260 0 0 # Напряжение звена постоянного тока в момент текущей аварии х10, В -F07.29 63261 0 0 # Максимальная температура ПЧ в момент текущей аварии х10, С -F07.30 63262 0 0 # Состояние входных клемм в момент текущей аварии -F07.31 63263 0 0 # Состояние выходных клемм в момент текущей аварии -F07.32 63264 0 0 # Выходная частота в момент предыдущей аварии х100, Гц -F07.33 63265 0 0 # Опорная частота в момент предыдущей аварии х100, Гц -F07.34 63266 0 0 # Выходное напряжение в момент предыдущей аварии, В -F07.35 63267 0 0 # Выходной ток в момент предыдущей аварии х10, А -F07.36 63268 0 0 # Напряжение звена постоянного тока в момент предыдущей аварии х10, В -F07.37 63269 0 0 # Максимальная температура ПЧ в момент предыдущей аварии х10, С -F07.38 63270 0 0 # Состояние входных клемм в момент предыдущей аварии -F07.39 63271 0 0 # Состояние выходных клемм в момент предыдущей аварии -F07.40 63272 0 0 # Частота в момент 2-й аварии х100, Гц -F07.41 63273 0 0 # Опорная частота в момент 2-й аварии х100, Гц -F07.42 63274 0 0 # Выходное напряжение в момент 2-й аварии, В -F07.43 63275 0 0 # Выходной ток в момент 2-й аварии х10, А -F07.44 63276 0 0 # Напряжение звена постоянного тока в момент 2-й аварии, В -F07.45 63277 0 0 # Максимальная температура ПЧ в момент 2-й аварии х10, С -F07.46 63278 0 0 # Состояние входных клемм в момент 2-й аварии -F07.47 63279 0 0 # Состояние выходных клемм в момент 2-й аварии +F07.08 63240 36 1 # Температура выпрямителя, С +F07.09 63241 36 1 # Температура инвертора, С +F07.10 63242 60770 1 # Версия ПО +F07.11 63243 0 1 # Время наработки, час. +F07.12 63244 0 1 # Нижний предел сигнализации AI1, В +F07.13 63245 680 1 # Верхний предел сигнализации AI1, В +F07.14 63246 0 1 # Выбор канала ограничения верхнего предела выхода ПИД-регулятора +F07.15 63247 15 1 # Номинальная мощность ПЧ х10, КВт +F07.16 63248 380 1 # Номинальное напряжение, В +F07.17 63249 75 1 # Номинальный ток х10, А +F07.18 63250 0 1 # Текущая ошибка +F07.19 63251 0 1 # Ошибка при предыдущем отключении +F07.20 63252 0 1 # Ошибка при 2-м отключении +F07.21 63253 0 1 # Ошибка при 3-м отключении +F07.22 63254 0 1 # Ошибка при 4-м отключении +F07.23 63255 0 1 # Ошибка при 5-м отключении +F07.24 63256 0 1 # Частота в момент текущей аварии х100, Гц +F07.25 63257 0 1 # Опорная частота в момент текущей аварии х100, Гц +F07.26 63258 0 1 # Выходное напряжение в момент текущей аварии, В +F07.27 63259 0 1 # Выходной ток в момент текущей аварии х10, В +F07.28 63260 0 1 # Напряжение звена постоянного тока в момент текущей аварии х10, В +F07.29 63261 0 1 # Максимальная температура ПЧ в момент текущей аварии х10, С +F07.30 63262 0 1 # Состояние входных клемм в момент текущей аварии +F07.31 63263 0 1 # Состояние выходных клемм в момент текущей аварии +F07.32 63264 0 1 # Выходная частота в момент предыдущей аварии х100, Гц +F07.33 63265 0 1 # Опорная частота в момент предыдущей аварии х100, Гц +F07.34 63266 0 1 # Выходное напряжение в момент предыдущей аварии, В +F07.35 63267 0 1 # Выходной ток в момент предыдущей аварии х10, А +F07.36 63268 0 1 # Напряжение звена постоянного тока в момент предыдущей аварии х10, В +F07.37 63269 0 1 # Максимальная температура ПЧ в момент предыдущей аварии х10, С +F07.38 63270 0 1 # Состояние входных клемм в момент предыдущей аварии +F07.39 63271 0 1 # Состояние выходных клемм в момент предыдущей аварии +F07.40 63272 0 1 # Частота в момент 2-й аварии х100, Гц +F07.41 63273 0 1 # Опорная частота в момент 2-й аварии х100, Гц +F07.42 63274 0 1 # Выходное напряжение в момент 2-й аварии, В +F07.43 63275 0 1 # Выходной ток в момент 2-й аварии х10, А +F07.44 63276 0 1 # Напряжение звена постоянного тока в момент 2-й аварии, В +F07.45 63277 0 1 # Максимальная температура ПЧ в момент 2-й аварии х10, С +F07.46 63278 0 1 # Состояние входных клемм в момент 2-й аварии +F07.47 63279 0 1 # Состояние выходных клемм в момент 2-й аварии F08.00 63488 100 0 # Время разгона 2 х10, сек. F08.01 63489 100 0 # Время торможения 2 х10, сек. F08.02 63490 100 0 # Время разгона 3 х10, сек. @@ -304,7 +304,7 @@ F09.09 63753 1000 0 # Верхний предел ПИД х10, % F09.10 63754 0 0 # Нижний предел ПИД х10, % F09.11 63755 0 0 # Величина сигнала обратной связи, активирущая ошибку пропажи сигнала х10, % F09.12 63756 10 0 # Задержка включения ошибки пропажи сигнала х10, сек. -F09.13 63757 0 0 # Зарезервировано +F09.13 63757 0 1 # Зарезервировано F09.14 63758 50 0 # Пропорциональная составляющая 2 (Кр2) х100 F09.15 63759 20 0 # Интегральная составляющая 2 (Ti2) х100 F09.16 63760 0 0 # Дифференциальная составляющая 2 (Td2) х100 @@ -321,7 +321,7 @@ F0A.01 64001 0 0 # Амплитуда частоты толчка х10, се F0A.02 64002 0 0 # Время увеличения частоты колебаний х10, сек. F0A.03 64003 0 0 # Время снижения частоты колебаний х10, сек. F0A.04 64004 0 0 # Установка длины, м -F0A.05 64005 0 0 # Заданная длина, м +F0A.05 64005 0 1 # Заданная длина, м F0A.06 64006 1 0 # Количество импульсов на оборот F0A.07 64007 1000 0 # Длина окружности вала х100, м F0A.08 64008 1000 0 # Множитель х1000 @@ -330,7 +330,7 @@ F0A.10 64010 0 0 # Установленное значение счетчик F0A.11 64011 0 0 # Определяемое значение счетчика F0A.12 64012 0 0 # Время работы, мин. F0A.13 64013 0 0 # Метод остановки -F0A.14 64014 0 0 # Зарезервировано +F0A.14 64014 0 1 # Зарезервировано F0B.00 64256 0 0 # Режим простого ПЛК F0B.01 64257 0 0 # Режим работы ПЛК при перебое с питанием F0B.02 64258 0 0 # Многоскоростной режим 0 х10, % @@ -387,7 +387,7 @@ F0C.14 64526 0 0 # Режимы оповещения при обнаруже F0C.15 64527 0 0 # Выбор регулировки несущей частоты F0C.16 64528 1 0 # Режим ШИМ F0C.17 64529 1 0 # Фильтр низких частот -F0C.18 64530 1 0 # Зарезервирован +F0C.18 64530 1 1 # Зарезервирован F0D.00 64768 1 0 # Метод управления вторым двигателем F0D.01 64769 1 0 # Тип нагрузки F0D.02 64770 1 0 # Тип второго двигателя @@ -401,19 +401,19 @@ F0D.09 64777 1264 0 # Сопротивление ротора двигате F0D.10 64778 67 0 # Индуктивность рассеяния двигателя 2 х10 F0D.11 64779 956 0 # Индуктивность двигателя 2 х10 F0D.12 64780 33 0 # Ток холостого хода двигателя 2 х10, А -F0D.13 64781 1 0 # Зарезервировано -F0D.14 64782 1 0 # Зарезервировано -F0D.15 64783 1 0 # Зарезервировано -F0D.16 64784 1 0 # Зарезервировано -F0D.17 64785 1 0 # Зарезервировано -F0D.18 64786 1 0 # Зарезервировано -F0D.19 64787 1 0 # Зарезервировано -F0D.20 64788 1 0 # Зарезервировано -F0D.21 64789 1 0 # Зарезервировано -F0D.22 64790 1 0 # Зарезервировано -F0D.23 64791 1 0 # Зарезервировано -F0D.24 64792 1 0 # Зарезервировано -F0D.25 64793 1 0 # Зарезервировано +F0D.13 64781 1 1 # Зарезервировано +F0D.14 64782 1 1 # Зарезервировано +F0D.15 64783 1 1 # Зарезервировано +F0D.16 64784 1 1 # Зарезервировано +F0D.17 64785 1 1 # Зарезервировано +F0D.18 64786 1 1 # Зарезервировано +F0D.19 64787 1 1 # Зарезервировано +F0D.20 64788 1 1 # Зарезервировано +F0D.21 64789 1 1 # Зарезервировано +F0D.22 64790 1 1 # Зарезервировано +F0D.23 64791 1 1 # Зарезервировано +F0D.24 64792 1 1 # Зарезервировано +F0D.25 64793 1 1 # Зарезервировано F0D.26 64794 1 0 # Защита от перегрузки для двигателя 2 F0D.27 64795 1000 0 # Обнаружение перегрузки двигателя 2 х10, % F0E.00 65024 1 0 # Сетевой адрес @@ -457,43 +457,43 @@ A01.16 41232 500 0 # Среднее значение входа AI3 х100, В A01.17 41233 500 0 # Соответствие среднему значению входа AI3 х10, % A01.18 41234 100 0 # Фильтр входа AI3 х1000, сек A01.19 41235 50 0 # Фильтр дребезга контактов х1000, сек. -A02.00 41472 0 0 # Заданная частота х100, Гц -A02.01 41473 0 0 # Выходная частота х100, Гц -A02.02 41474 0 0 # Опорная частота разгона х100, Гц -A02.03 41475 0 0 # Выходное напряжение, В -A02.04 41476 0 0 # Выходной ток х10, А -A02.05 41477 0 0 # Обороты двигателя, об/мин -A02.06 41478 0 0 # Зарезервировано -A02.07 41479 0 0 # Зарезервировано -A02.08 41480 0 0 # Выходная мощность х10, % -A02.09 41481 0 0 # Выходной момент х10, % -A02.10 41482 0 0 # Оценка частоты двигателя х100, Гц -A02.11 41483 0 0 # Напряжение звена постоянного тока, В -A02.12 41484 0 0 # Состояние дискретных входов -A02.13 41485 0 0 # Состояние дискретных выходов -A02.14 41486 0 0 # Цифровое задание частоты х100, Гц -A02.15 41487 0 0 # Зарезервировано -A02.16 41488 0 0 # Линейная скорость -A02.17 41489 0 0 # Длина импульсов -A02.18 41490 0 0 # Счетчик значения -A02.19 41491 0 0 # Напряжение на входе AI1 х100, В -A02.20 41492 0 0 # Напряжение на входе AI2 х100, В -A02.21 41493 0 0 # Напряжение на входе AI3 х100, В -A02.22 41494 0 0 # Частота на входе HDI1 х100, КГц -A02.23 41495 0 0 # Уставка ПИД х10, % -A02.24 41496 0 0 # Обратная связь ПИД х10, % -A02.25 41497 0 0 # Выходной сигнал ПИД х100, % -A02.26 41498 0 0 # Коэффициент мощности х10, % -A02.27 41499 0 0 # Время работы, мин. -A02.28 41500 0 0 # Шаг работы ПЛК -A02.29 41501 0 0 # Выходной сигнал регулятора ASR х10, % -A02.30 41502 0 0 # Напряжение на выходе A01 х100, В -A02.31 41503 0 0 # Напряжение на выходе A02 х100, В -A02.32 41504 0 0 # Ток ПЧ х10, А -A02.33 41505 0 0 # Момент х10 -A02.34 41506 0 0 # Счетчик перегрузок двигателя -A02.35 41507 0 0 # Зарезервировано -A02.36 41508 1 0 # Текущий выбор двигателя +A02.00 41472 0 1 # Заданная частота х100, Гц +A02.01 41473 0 1 # Выходная частота х100, Гц +A02.02 41474 0 1 # Опорная частота разгона х100, Гц +A02.03 41475 0 1 # Выходное напряжение, В +A02.04 41476 0 1 # Выходной ток х10, А +A02.05 41477 0 1 # Обороты двигателя, об/мин +A02.06 41478 0 1 # Зарезервировано +A02.07 41479 0 1 # Зарезервировано +A02.08 41480 0 1 # Выходная мощность х10, % +A02.09 41481 0 1 # Выходной момент х10, % +A02.10 41482 0 1 # Оценка частоты двигателя х100, Гц +A02.11 41483 0 1 # Напряжение звена постоянного тока, В +A02.12 41484 0 1 # Состояние дискретных входов +A02.13 41485 0 1 # Состояние дискретных выходов +A02.14 41486 0 1 # Цифровое задание частоты х100, Гц +A02.15 41487 0 1 # Зарезервировано +A02.16 41488 0 1 # Линейная скорость +A02.17 41489 0 1 # Длина импульсов +A02.18 41490 0 1 # Счетчик значения +A02.19 41491 0 1 # Напряжение на входе AI1 х100, В +A02.20 41492 0 1 # Напряжение на входе AI2 х100, В +A02.21 41493 0 1 # Напряжение на входе AI3 х100, В +A02.22 41494 0 1 # Частота на входе HDI1 х100, КГц +A02.23 41495 0 1 # Уставка ПИД х10, % +A02.24 41496 0 1 # Обратная связь ПИД х10, % +A02.25 41497 0 1 # Выходной сигнал ПИД х100, % +A02.26 41498 0 1 # Коэффициент мощности х10, % +A02.27 41499 0 1 # Время работы, мин. +A02.28 41500 0 1 # Шаг работы ПЛК +A02.29 41501 0 1 # Выходной сигнал регулятора ASR х10, % +A02.30 41502 0 1 # Напряжение на выходе A01 х100, В +A02.31 41503 0 1 # Напряжение на выходе A02 х100, В +A02.32 41504 0 1 # Ток ПЧ х10, А +A02.33 41505 0 1 # Момент х10 +A02.34 41506 0 1 # Счетчик перегрузок двигателя +A02.35 41507 0 1 # Зарезервировано +A02.36 41508 1 1 # Текущий выбор двигателя A03.00 41728 0 0 # Тип телеграммы A03.01 41729 1 0 # Адрес устройства A03.02 41730 0 0 # Параметр в телеграмме PZD3 (запись в ПЧ - DateOutput, %QW) diff --git a/modbus_params/main.c b/modbus_params/main.c index 77b3260..ceb01e5 100644 --- a/modbus_params/main.c +++ b/modbus_params/main.c @@ -21,12 +21,14 @@ #include #include "modbus.h" +#include "server.h" #include "verbose.h" typedef struct{ int help; // help int verbose; // verbose level (not used yet) int slave; // slave ID + int isunix; // Unix-socket char **dumpcodes; // keycodes to dump into file char **writeregs; // reg=val to write char **writecodes; // keycode=val to write @@ -36,6 +38,7 @@ typedef struct{ char *outdic; // output dictionary to save everything read from slave char *dicfile; // file with dictionary char *device; // serial device + char *node; // server port or path int baudrate; // baudrate double dTdump; // dumping time interval (s) } parameters; @@ -62,6 +65,8 @@ static sl_option_t cmdlnopts[] = { {"outdic", NEED_ARG, NULL, 'O', arg_string, APTR(&G.outdic), "output dictionary for full device dump by input dictionary registers"}, {"readr", MULT_PAR, NULL, 'r', arg_int, APTR(&G.readregs), "registers (by address) to read; multiply parameter"}, {"readc", MULT_PAR, NULL, 'R', arg_string, APTR(&G.readcodes), "registers (by keycodes, checked by dictionary) to read; multiply parameter"}, + {"node", NEED_ARG, NULL, 'N', arg_string, APTR(&G.node), "node \"IP\", or path (could be \"\\0path\" for anonymous UNIX-socket)"}, + {"unixsock", NO_ARGS, NULL, 'U', arg_int, APTR(&G.isunix), "UNIX socket instead of INET"}, end_option }; @@ -111,8 +116,15 @@ int main(int argc, char **argv){ if(G.readregs) dumpregs(G.readregs); if(G.readcodes) dumpcodes(G.readcodes); if(G.dumpfile){ + if(!setDumpT(G.dTdump)) ERRX("Can't set dumptime %g", G.dTdump); DBG("dumpfile"); - if(!rundump(G.dTdump)) signals(-1); + if(!rundump()) signals(-1); + } + if(G.node){ + DBG("Create server"); + if(!runserver(G.node, G.isunix)) signals(-1); // this function exits only after server death + } + if(G.dumpfile){ DBG("Done, wait for ctrl+C"); while(1); } diff --git a/modbus_params/modbus.c b/modbus_params/modbus.c index f708a19..c6bbbe4 100644 --- a/modbus_params/modbus.c +++ b/modbus_params/modbus.c @@ -27,8 +27,10 @@ #include "verbose.h" static FILE *dumpfile = NULL; +static char *dumpname = NULL; static dicentry_t *dumppars = NULL; static int dumpsize = 0; +static double dumpTime = 0.1; static dicentry_t *dictionary = NULL; static int dictsize = 0; @@ -167,7 +169,8 @@ int opendumpfile(const char *name){ WARN("Can't open %s", name); return FALSE; } - fprintf(dumpfile, "# time,s "); + dumpname = strdup(name); + fprintf(dumpfile, "# time,s "); for(int i = 0; i < dumpsize; ++i){ fprintf(dumpfile, "%s ", dumppars[i].code); } @@ -175,6 +178,8 @@ int opendumpfile(const char *name){ return TRUE; } +char *getdumpname(){ return dumpname;} + void closedumpfile(){ if(dumpfile && !isstopped){ if(!isstopped){ @@ -182,6 +187,7 @@ void closedumpfile(){ while(!isstopped); } fclose(dumpfile); + FREE(dumpname); } } @@ -193,7 +199,7 @@ static void *dumpthread(void *p){ double startT = sl_dtime(); while(!stopdump){ double t0 = sl_dtime(); - fprintf(dumpfile, "%6.3g", t0 - startT); + fprintf(dumpfile, "%10.3f ", t0 - startT); for(int i = 0; i < dumpsize; ++i){ if(!read_entry(&dumppars[i])) fprintf(dumpfile, "---- "); else fprintf(dumpfile, "%4d ", dumppars[i].value); @@ -205,20 +211,23 @@ static void *dumpthread(void *p){ return NULL; } -int rundump(double dT){ - if(!dumpfile){ - WARNX("Open dump file first"); - return FALSE; - } +int setDumpT(double dT){ if(dT < 0.){ WARNX("Time interval should be > 0"); return FALSE; } + dumpTime = dT; + DBG("user give dT: %g", dT); + return TRUE; +} + +int rundump(){ + if(!dumpfile){ + WARNX("Open dump file first"); + return FALSE; + } pthread_t thread; - static double T = 0.; - if(T != dT) T = dT; - DBG("user give dT: %g", T); - if(pthread_create(&thread, NULL, dumpthread, (void*)&T)){ + if(pthread_create(&thread, NULL, dumpthread, (void*)&dumpTime)){ WARN("Can't create dumping thread"); return FALSE; } @@ -237,19 +246,32 @@ void close_modbus(){ // read register and modify entry->reg; return FALSE if failed int read_entry(dicentry_t *entry){ - if(!entry) return FALSE; + if(!entry){ + WARNX("NULL instead of entry"); + return FALSE; + } int ret = TRUE; pthread_mutex_lock(&modbus_mutex); - if(modbus_read_registers(modbus_ctx, entry->reg, 1, &entry->value) < 0) ret = FALSE; + if(modbus_read_registers(modbus_ctx, entry->reg, 1, &entry->value) < 0){ + WARNX("Can't read entry by reg %u", entry->reg); + ret = FALSE; + } pthread_mutex_unlock(&modbus_mutex); return ret; } // write register value; FALSE - if failed or read-only int write_entry(dicentry_t *entry){ - if(!entry || entry->readonly) return FALSE; + if(!entry || entry->readonly){ + if(!entry) WARNX("NULL instead of entry"); + else WARNX("Can't write readonly entry %u", entry->reg); + return FALSE; + } int ret = TRUE; pthread_mutex_lock(&modbus_mutex); - if(modbus_write_register(modbus_ctx, entry->reg, entry->value) < 0) ret = FALSE; + if(modbus_write_register(modbus_ctx, entry->reg, entry->value) < 0){ + WARNX("Error writing %u to %u", entry->value, entry->reg); + ret = FALSE; + } pthread_mutex_unlock(&modbus_mutex); return ret; } diff --git a/modbus_params/modbus.h b/modbus_params/modbus.h index cab5ff7..bf409ef 100644 --- a/modbus_params/modbus.h +++ b/modbus_params/modbus.h @@ -30,7 +30,9 @@ typedef struct{ int setdumppars(char **pars); int opendumpfile(const char *name); void closedumpfile(); -int rundump(double dT); +int setDumpT(double dT); +int rundump(); +char *getdumpname(); int opendict(const char *dic); diff --git a/modbus_params/modbus_param.files b/modbus_params/modbus_param.files index 5b6d0ff..d2fac0b 100644 --- a/modbus_params/modbus_param.files +++ b/modbus_params/modbus_param.files @@ -1,5 +1,7 @@ main.c modbus.c modbus.h +server.c +server.h verbose.c verbose.h diff --git a/modbus_params/relay.dic b/modbus_params/relay.dic new file mode 100644 index 0000000..285a3af --- /dev/null +++ b/modbus_params/relay.dic @@ -0,0 +1,4 @@ +id 0000 1 0 # relay ID +test1 1 0 0 +test2 2 0 0 +test3 3 0 0 diff --git a/modbus_params/server.c b/modbus_params/server.c new file mode 100644 index 0000000..a3303f0 --- /dev/null +++ b/modbus_params/server.c @@ -0,0 +1,122 @@ +/* + * This file is part of the modbus_param project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "server.h" +#include "modbus.h" + +static sl_sock_t *s = NULL; + +// stop dump and close dump file +static sl_sock_hresult_e closedump(_U_ sl_sock_t *client, _U_ sl_sock_hitem_t *item, _U_ const char *req){ + closedumpfile(); + return RESULT_OK; +} +// open new dump file +static sl_sock_hresult_e newdump(sl_sock_t *client, _U_ sl_sock_hitem_t *item, const char *req){ + char buf[BUFSIZ]; + if(!req){ // getter + snprintf(buf, BUFSIZ-1, "%s = %s\n", item->key, getdumpname()); + sl_sock_sendstrmessage(client, buf); + return RESULT_SILENCE; + }else{ + if(!opendumpfile(req) || !rundump()) return RESULT_FAIL; + } + return RESULT_OK; +} + +static sl_sock_hitem_t handlers[] = { + {closedump, "clodump", "stop dump and close current dump file", NULL}, + {newdump, "newdump", "open new dump file or get name of current", NULL}, + {NULL, NULL, NULL, NULL} +}; + +// new connections handler (return FALSE to reject client) +static int connected(sl_sock_t *c){ + if(c->type == SOCKT_UNIX) LOGMSG("New client fd=%d connected", c->fd); + else LOGMSG("New client fd=%d, IP=%s connected", c->fd, c->IP); + return TRUE; +} +// disconnected handler +static void disconnected(sl_sock_t *c){ + if(c->type == SOCKT_UNIX) LOGMSG("Disconnected client fd=%d", c->fd); + else LOGMSG("Disconnected client fd=%d, IP=%s", c->fd, c->IP); +} + +static sl_sock_hresult_e defhandler(sl_sock_t *s, const char *str){ + if(!s || !str) return RESULT_FAIL; + char key[SL_KEY_LEN], value[SL_VAL_LEN]; + int n = sl_get_keyval(str, key, value); + if(n == 0){ + WARNX("Can't parse `%s` as reg[=val]", str); + return RESULT_BADKEY; + } + dicentry_t *entry = NULL; + int N; + if(sl_str2i(&N, key)){ // `key` is register number + entry = findentry_by_reg((uint16_t) N); + }else{ // `key` is register name + entry = findentry_by_code(key); + } + if(!entry){ + WARNX("Entry %s not found", key); + return RESULT_BADKEY; + } + if(n == 1){ // getter + if(!read_entry(entry)) return RESULT_BADKEY; + snprintf(value, SL_VAL_LEN-1, "%s=%u\n", key, entry->value); + }else{ // setter + if(!sl_str2i(&N, value)){ + WARNX("%s isn't a value of register", value); + return RESULT_BADVAL; + } + entry->value = (uint16_t)N; + if(!write_entry(entry)) return RESULT_FAIL; + return RESULT_OK; + } + sl_sock_sendstrmessage(s, value); + return RESULT_SILENCE; +} + +int runserver(const char *node, int isunix){ + if(!node){ + WARNX("Point node"); + return FALSE; + } + sl_socktype_e type = (isunix) ? SOCKT_UNIX : SOCKT_NET; + if(s) sl_sock_delete(&s); + s = sl_sock_run_server(type, node, -1, handlers); + if(!s){ + WARNX("Can't run server"); + return FALSE; + } + sl_sock_connhandler(s, connected); + sl_sock_dischandler(s, disconnected); + sl_sock_defmsghandler(s, defhandler); + while(s && s->connected){ + if(!s->rthread){ + WARNX("Server handlers thread is dead"); + break; + } + } + DBG("Close"); + sl_sock_delete(&s); + return TRUE; +} diff --git a/modbus_params/server.h b/modbus_params/server.h new file mode 100644 index 0000000..07f2cca --- /dev/null +++ b/modbus_params/server.h @@ -0,0 +1,23 @@ +/* + * This file is part of the modbus_param project. + * Copyright 2025 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +int runserver(const char *node, int isunix);