Из MQTT в ModBusTCP

Просмотр 15 сообщений - с 1 по 15 (из 23 всего)
  • Автор
    Сообщения
  • #43218
    IvanovVladimir
    Участник

    (Минимально) У меня есть 2 канала, один modbus tcp (101), второй MQTT (102). Оба канала настроены как входной\выходной. При отправке команды с брокера MQTT в скаду я меняю значение канала 102. Я хотел, чтобы без МАУ у меня значение из 102 канала при получении команды передавалось в канал 101 и отправлялась команда в ПЛК к привязанному регистру. Алгоритм прост, при получении команды на 102 канал, я сравниваю полученное значение из MQTT сообщения с значением 101 канала и если они различны записываю в 101 канал новое значение от имени пользователя, чтобы команда в ПЛК тоже полетела (без пользователя просто меняется значение на сервере но команда не отправляется на ПЛК). Столкнулся с еще одной проблемой и не понимаю как решить, вот алгоритм:
    1) отправляю mqtt на 102 канал со значением 0
    2) канал 101 становится 0 и отправляет команду на плк
    3) через мнемосхему отправляю переключателем команду на изменение значения канала 101 в 1
    4) команда отправляется и в плк
    5) отправляю команду 0 в канал 102 по MQTT
    6) значение канала 101 и соответственно команда к плк происходит только через минуту
    Описание: Если в канале 102 значение одинаковое с тем которое я отправляю по MQTT то значение копируется в 101 и отправляется на плк только через минуту, если в канале 102 значение отличается от того что я отправляю по MQTT то значение в 101 меняется сразу как и отправка команды на ПЛК.

    Я написал модуль в котором настраиваю из каких каналов в какие должно копироваться значение. Подскажите как мне исправить ошибку с отложенной отправкой команды на ПЛК?

    Код модуля логики (функция обработки):
    public override void OnCurrentDataProcessed(Slice slice)
    {
    if (slice?.CnlNums == null || moduleConfig.Mappings.Count == 0)
    return;

    foreach (int changedCnlNum in slice.CnlNums)
    {
    foreach (var mapping in moduleConfig.Mappings)
    {
    if (changedCnlNum == mapping.SourceCnl)
    {
    // Получаем актуальное значение исходного канала (только что обновлённое)
    CnlData sourceData = ServerContext.GetCurrentData(mapping.SourceCnl);
    if (!sourceData.IsDefined)
    continue;

    double newVal = sourceData.Val;

    // Получаем текущее значение целевого канала
    CnlData targetData = ServerContext.GetCurrentData(mapping.TargetCnl);

    // Если целевой канал не определён или его значение отличается от пришедшего
    if (!targetData.IsDefined || Math.Abs(targetData.Val — newVal) > double.Epsilon)
    {
    TeleCommand cmd = new TeleCommand(mapping.TargetCnl, newVal, moduleConfig.UserID);
    ServerContext.SendCommand(cmd);

    if (moduleConfig.VerboseLog)
    Log.WriteInfo($»[{Code}] Канал {mapping.SourceCnl}→{mapping.TargetCnl}, значение={newVal}»);
    else
    Log.WriteAction($»[{Code}] Команда отправлена в канал {mapping.TargetCnl}»);
    }
    else
    {
    if (moduleConfig.VerboseLog)
    Log.WriteInfo($»[{Code}] Значение в целевом канале {mapping.TargetCnl} уже равно {newVal}, пропуск.»);
    }
    }
    }
    }
    }

    • Тема изменена 1 месяц, 1 неделя назад пользователем Mikhail.
    #43230
    IvanovVladimir
    Участник

    Может там нужно как то статус менять канала или привязываться к событию…? Чтобы отработала команда сразу а не при следующем чтении архива сервером в течение минуты

    • Ответ изменён 1 месяц, 1 неделя назад пользователем IvanovVladimir.
    #43233
    manjey73
    Участник

    Вы уверены что команда отложенная? а не то, что вы видите ее изменение после режима «Чтение после команды» ?

    #43234
    manjey73
    Участник

    Если у вас длительный опрос, то команда выставляется в очередь, когда опрос заканчивается, отсылается команда, потом идет чтение после команды и только тогда вы видите изменение.

    #43237
    IvanovVladimir
    Участник

    Я уверен что команда отложенная так как ПЛК рядом со мной физически и я смотрю значения непосредственно как в администраторе так и в веб интерфейсе. Еще если действовать по тому алгоритму то в логах будет четко видно, что:
    12:00:00 — получена команда по mqtt
    12:00:39 — отправлена команда на плк
    12:00:43 — получена команда по mqtt
    12:01:39 — отправлена команда на плк
    12:01:23 — получена команда по mqtt
    12:02:39 — отправлена команда на плк

    то есть команда на плк отправляется после команды mqtt, но только ровно в конкретное время с интервалом в минуту, это не то чтобы задержка, это изменение применилось, но сервер его обработал только по минутному таймеру

    #43238
    IvanovVladimir
    Участник

    06.05.2026 16:08:05 Enterprise HaiWell HaiWell — M1 Определён, Вкл
    06.05.2026 16:08:43 Enterprise HaiWell HaiWell — M0 Определён, Вкл
    06.05.2026 16:26:52 Enterprise HaiWell HaiWell — M0 Хороший, Откл
    06.05.2026 16:26:52 Enterprise HaiWell HaiWell — M1 Хороший, Откл
    06.05.2026 16:26:53 Enterprise HaiWell HaiWell — M0 Определён, Откл
    06.05.2026 16:26:53 Enterprise HaiWell HaiWell — M1 Определён, Откл
    06.05.2026 16:27:04 Enterprise HaiWell HaiWell — M1 Определён, Вкл
    06.05.2026 16:27:05 Enterprise HaiWell HaiWell — M0 Определён, Вкл
    06.05.2026 16:27:28 Enterprise HaiWell HaiWell — M0 Хороший, Откл
    06.05.2026 16:27:28 Enterprise HaiWell HaiWell — M1 Хороший, Откл
    06.05.2026 16:27:29 Enterprise HaiWell HaiWell — M0 Определён, Вкл
    06.05.2026 16:27:29 Enterprise HaiWell HaiWell — M1 Определён, Вкл
    06.05.2026 16:27:30 Enterprise HaiWell HaiWell — M0 Определён, Откл
    06.05.2026 16:27:30 Enterprise HaiWell HaiWell — M1 Определён, Откл
    06.05.2026 16:27:43 Enterprise HaiWell HaiWell — M1 Определён, Вкл
    06.05.2026 16:27:43 Enterprise HaiWell HaiWell — M0 Определён, Вкл
    06.05.2026 16:28:28 Enterprise HaiWell HaiWell — M0 Хороший, Откл
    06.05.2026 16:28:28 Enterprise HaiWell HaiWell — M1 Хороший, Откл
    06.05.2026 16:28:29 Enterprise HaiWell HaiWell — M0 Определён, Вкл
    06.05.2026 16:28:29 Enterprise HaiWell HaiWell — M1 Определён, Вкл
    06.05.2026 16:28:29 Enterprise HaiWell HaiWell — M0 Определён, Откл
    06.05.2026 16:28:29 Enterprise HaiWell HaiWell — M1 Определён, Откл

    вот прям логи, тут я игрался со статусами, вдруг это триггер на изменение команды сразу будет, но нет
    там где статус Хороший это отложенная по какой то причине команда на изменение по mqtt, в них видно период ровно в 1 минуту, хотя отправлял я их сразу после включения каналов вручную без mqtt

    2026-05-06 16:26:52 Приём myparam2 = {
    «test»: {
    «i…
    Подписанные устройства: 2
    Hello from JS. Topic: myparam2

    2026-05-06 16:27:11 Приём myparam2 = {
    «test»: {
    «i…
    Подписанные устройства: 2
    Hello from JS. Topic: myparam2

    2026-05-06 16:27:52 Приём myparam2 = {
    «test»: {
    «i…
    Подписанные устройства: 2
    Hello from JS. Topic: myparam2

    #43239
    manjey73
    Участник

    Оставьте в опросе Modbus только один регистр на опрос, в который вы отправляете команду. И сделайте то же самое.

    Сколько времени пройдет?

    #43240
    IvanovVladimir
    Участник

    Уже пробовал, лог получаю аналогичный

    #43243
    IvanovVladimir
    Участник

    Данная ошибка у меня возникает только с условием, если значение посылаемое по mqtt совпадает с тем значением канала к которому она привязана. Если текущее значение привязанного канала не совпадает с тем, что было получено в команде тогда отправка команды на плк происходит сразу.

    #43244
    manjey73
    Участник

    ааа, тогда возможно надо что-то в коде добавить или изменить, чтобы все равно отправить.
    Откровенно говоря, я у себя наоборот делал, чтобы ничего не отправлялось, если значение совпадает, какой в этом смысл?

    #43256
    IvanovVladimir
    Участник

    Есть два канала, 101 и 102
    101 канал привязан к регистру плк через ModBusTCP
    102 канал привязан к значению получаемого пакета MQTT
    Запускаем веб
    101 — 1
    102 — —
    отправляем сообщение по mqtt со значением 0
    101 — 0 (изменена моим модулем)
    102 — 0
    *отправлена команда в ПЛК в связи с изменением значения канала 101
    в вебе изменяем значение канала 101 на 1
    101 — 1
    102 — 0
    *отправлена команда в ПЛК в связи с изменением значения канала 101
    отправляем сообщение по mqtt со значением 0, чтобы отключить регистр в ПЛК ранее включенный через вебморду скады
    101 — 1
    102 — 0
    *ждем до минуты пока сервер просканирует архив (я предполагаю что он это делает)
    101 — 0 (изменена моим модулем)
    102 — 0
    *отправлена команда в ПЛК в связи с изменением значения канала 101
    отправляем сообщение по mqtt со значением 1
    101 — 1 (изменена моим модулем)
    102 — 1
    *отправлена команда в ПЛК в связи с изменением значения канала 101

    То есть ждать отправки команды на плк приходится только в тех случаях когда значение канала 102 совпадает с тем значением что я вновь передаю на него по mqtt

    Алгоритм программы которая мне нужна максимально на самом деле прост:
    1) создается таблица привязок в свойствах модуля, где я указываю из какого канала (Х) в какой (У) мне необходимо передать значение (в примере из канала 102 в канал 101)
    2) при получении нового значения на Х, проверяется есть ли разница между полученным сообщением и значением У
    3) если значения разные то необходимо изменить значение У на значение Х, что должно приводить к немедленной отправки команды на ПЛК

    Если обобщить я хочу иметь возможность управлять ПЛК не только из веб-морды скады, но и используя команды mqtt из внешней системы. Чтобы я мог изменить значение регистров ПЛК как по MQTT, так и непосредственно из интерфейса скады

    #43257
    IvanovVladimir
    Участник

    Для реализации такого управления я начал писать модуль который будет перебрасывать значения с каналов mqtt на каналы modbustcp, чтобы посредством этого отправлялись команды на ПЛК

    #43258
    manjey73
    Участник

    А почему вы не используете метод public override void OnIteration() у него вызов раз 10 в секунду.

    #43259
    IvanovVladimir
    Участник

    Это будет сильно нагружать систему ведь мне придется каждую итерацию опрашивать все каналы и при различии применять изменения, думаю при 5к+ каналов это начнет люто тормозить. В то время как OnCurrentDataProcessed вызывается по событию, что более правильно.

    #43260
    IvanovVladimir
    Участник

    В целом мой метод работает идеально, кроме случая когда я получаю по mqtt такое же значение, как в канале к нему привязанном, не в канале который отправляет данные на плк по modbustcp, а в канале который привязан к данному mqtt. Почему то конкретно в этом случае изменение канала modbus идет с задержкой. Вопрос в том как мне искусственно кодом триггернуть сиюминутное изменение канала modbus и отправки команды на ПЛК? Что такого происходит когда значения канала mqtt отличается от полученного сообщения, чего не происходит когда они одинаковые

    https://disk.360.yandex.ru/i/NDlbF0qTr621dQ

Просмотр 15 сообщений - с 1 по 15 (из 23 всего)
  • Для ответа в этой теме необходимо авторизоваться.