Как мы искали адреса регистров в памяти прибора

от автора

Коллеги, добрый день!

Возникла у нас проблема: поменяли несколько приборов ТЭМ-104. Прошивка у приборов не изменилась — S10X v3.07 и осталась как и на старых версиях. ТЭМ-104 — это прибор учёта теплоносителя. При опросе использовали следующие адреса регистров:

8704 — температура ПТР
8708 — температура ОТР
8768 — объёмный расход теплоносителя ПТР
8772 — объёмный расход теплоносителя ОТР

⚠️ Проблема

В регистрах нуль. Посмотрели логи, data → 00 00, то есть буквально прибор отвечает нормально, но в кадре данных нуль (00 00). Нас интересовали мгновенные (real-time) параметры для отображения на мнемосхеме:

  • температура

  • давление (при наличии датчика)

  • объемный расход

Очевидно, что данные куда-то переехали, в другую область памяти (любия фишка производителя).

🔍 Проверка гипотезы

Встал вопрос, а что делать, как достать данные из прибора? Первая мысль, проверить, а шлет ли прибор вообще real-time данные. Подключились через Tesmastat (заводское ПО), прочитали мгновенные и архивные показания, проблем нет (скриншот прилагаю). Значит проблема не в приборах, а в адресах регистров.

🧠 Решение

Решили, что надо подсмотреть, какие запроса отправляет Tesmastat и какие ответы получает, то есть проверить логику работы request/response. Wireshark отпал сразу, так как отдел защиты информации запрещает перехватывать трафик ЛВС. Решили локально перехватить трафик при общении между Tesmastat и TЭМ-104 и написать свой скрипт — sniffer.

Sniffer (подключение через rs-485/232)

Sniffer № 1 $max_len_request=1024$max_len_response=1024$sleep = 1000$out=New-Object System.IO.Ports.SerialPort COM4, 9600, None,8,one$in=New-Object System.IO.Ports.SerialPort COM14, 9600, None,8,one$latin1 = [System.Text.Encoding]::GetEncoding("ISO-8859-1")$in.Encoding = $latin1$out.Encoding = $latin1try {    $in.Open()    $out.Open()    while ($true) {        if ($out.BytesToRead -gt 0) {            [byte[]]$data = New-Object byte[] $max_len_response            $count_byte_response = $out.Read($data, 0, $max_len_response)            $in.Write($data, 0, $count_byte_response)            Write-Host ("Ответ:")  -ForegroundColor Red            Write-Host ($data[0..($count_byte_response - 1)] | ForEach-Object { "{0:X2}" -f $_})  -ForegroundColor Red            Write-Host ("Длина: $count_byte_response" )  -ForegroundColor Red            Write-Host "`n" -NoNewLine        }        [System.Threading.Thread]::Sleep($sleep)        if ($in.BytesToRead -gt 0) {                        [byte[]]$data = New-Object byte[] $max_len_request            $count_byte_request = $in.Read($data, 0, $max_len_request)            $out.Write($data, 0, $count_byte_request)            Write-Host ("Запрос:" )  -ForegroundColor Green            Write-Host ($data[0..($count_byte_request - 1)] | ForEach-Object { "{0:X2}" -f $_}) -ForegroundColor Green            Write-Host ("Длина: $count_byte_request" )  -ForegroundColor Green            Write-Host "`n" -NoNewLine        }            }} finally {    $in.Close()    $out.Close()}

Можно было выполнить подключение через Moxa NPort, но суть не меняется.

🛠️ Реализация

  1. Запускаем Tesmastat

  2. Запрашиваем мгновенные значения

  3. Перехватываем весь трафик

  4. Анализируем перехваченный трафик

Получаем сырой request/response.. Приступаем к реализации.

📦 Чтение текущих данных

📦 Пример перехвата

🔎 Поиск значений

Для поиска нужных значений, взяли в Tesmastat мгновенные показания, для температуры: 65 градусов по трубопроводу ОТР –> переводим в HEX и ищем в перехвате совпадение. Таким образом находим нужный блок данных, понимаем, на какой адрес он пришел и определяем адрес регистра.

🎯 Результат

В итоге нашли следующие регистры:

  • ПТР расход теплоносителя57992

  • ОТР расход теплоносителя57996

  • ПТР температура теплоносителя57856

  • ОТП температура теплоносителя57860

Для работы нашей мнемосхемы этого достаточно.

Заключение

Для работы приходится выдвигаться в место непосредственной локации прибора. Если у вас нет проблем с информационной безопасностью, то всё это можно делать непосредственно с рабочего места (не забудт остановить опрос со стороны автоматизированной системы).

Теперь сразу отвечу тем, кто скажет: а почему вы не взяли описание протокола опроса прибора. Потому что там внятно не описано, где искать real-time показания, плюс к тому же есть смещение. Мы искали информацию, звонили поставщикам. Были варианты, но они не сработали.

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

Спасибо всем, кто дочитал!

Надеюсь, этот опыт будет полезен.

ссылка на оригинал статьи https://habr.com/ru/articles/1030430/