SR1568 и noname RS232/485 proto

Подключил контроллер SR1568 (солнечных панелей) на выделенный отдельный порт, отправляю команду (у которой простой фиксированный ответ) используя serial_tool:

Полученный ответ не совпадает с тем, который д.быть согласно документации(команда номер 2):

Такая же ситуация с остальными командами - ответы все есть, но выглядят некорректно…

Ответы идемпотентны и приходят на все команды, т.е. проблема только с корректным декодированием ответа…
Китайцы подняли руки вверх и отправили на все четыре…
повторив трижды “это не 485”

Может быть есть идеи как правильно декодировать ответ?

SR1568 Communication protocol.pdf (1,1 МБ)

Здравствуйте.

У нас уже поднималась схожая тема в 2020г.

This document describe protocols for server to communicate with SR1568 via RS485

По документу и структуре команд видно, что это не протокол Modbus.

Наш контроллер поддерживает только Modbus RTU посредством RS-485.

Добрый день.
Да я разве об этом спрашивал?
Вы не сообщили миру ничего нового и не ответили по существу заданного вопроса.

Добрый день,
Предлагаю начать с трёх пунктов
1)Удостоверьтесь что отключён драйвер wb-mqtt-serial, он может мешать использованию порта
systemctl stop wb-mqtt-serial # Остановка
(systemctl start wb-mqtt-serial #Для запуска после экспериментов)
2) Можете отправить ту же команду ADS123:GET_PRODUCT\r\n без пробела, судя по мануалу в командах нет пробелов(байт 0x20).
3) Так же можно отправлять другие команды или отправлять несуществующие в мануале команды, и понять возвращается разное или одно и то же. Возможно что мы получаем код ошибки ошибку.

Так в первом посте Вы декодируете запрос, а не ответ

п.1 Как он может мешать? Есть ли возможность указать драйверу какие порты использовать, а какие не трогать? Будет ли добавлена возможность включать дебаг логирование на конкретном порту (а не везде-и-вся, как сейчас)?
В общем случае, зачем останавливать wb-mqtt-serial, если целевая работа это как раз опрос порта при одновременно работающем драйвере…
Правильнее было бы иметь возможноть указать ему с какими портами работать…

п.2 Смотрели невнимательно - на скрине видно, что в команде присутствует пробел. При вызове без пробела ответа нет:

п.3 Пробовал, в основном ответы всегда повторяющиеся (в командах где ожидается фиксированный ответ), но на команды, где возвращаются переменные параметры, приходят разные ответы

я могу дать доступ, если есть желание попробовать

Смотрели невнимательно, есть два скрина - первый с декодом команды, ниже - с декодом ответа.

Вот еще пример команды и ответа:

Вставлю сюда ответ на ADS123:GET_PRODUCT текстом, может кто-нибудь решит этот пазл… убрав/добавив/переставив байты/префикс/суффикс…

serial_tool -b 9600 -p N -d 8 -s 1 -t 1 /dev/ttyMOD1
serial_tool on /dev/ttyMOD1: 9600 8N1.0
Enter your commands below in HEX form.
All characters but 0-9,a-f including spaces are ignored.
Press Control-D or Control-C to leave the application.
Press [Enter] to print received data

4144533132333a4745545f50524f44554354200d0a
<< 41 11 9A 29 23 46 46 1D 47 15 A2 E9 09 25 4A 12 A4 95 43 51 02 34 49 A5 8C 35 D9 84 D4 90 C1

Добрый день.
Вместо serial_tool я бы сразу использоваал RPC вызов штатного драйвера, так: Dooya DT82 (Onviz MR-2234F) - #15 от пользователя BrainRoot
Это немного удобнее чем вручную конвертировать.
Для примера:

//08_29_test_01.js
var inputStr = "4144533132333a4745545f50524f44554354200d0a";
inputStr = inputStr.replace(/ /g, '')

var outStr = "";

for (var i = 0; i < inputStr.length; i=i+2){
  var tempStr = inputStr.slice(i, i+2)
  outStr = outStr +"|"+ String.fromCharCode("0x"+tempStr);
  //log.info(i, tempStr)
}

log.info("outStr", outStr);

Выдает:

2024-08-29 12:37:29outStr |A|D|S|1|2|3|:|G|E|T|_|P|R|O|D|U|C|T| | |

Что ожидаемо.
Но вот для “41 11 9A 29 23 46 46 1D 47 15 A2 E9 09 25 4A 12 A4 95 43 51 02 34 49 A5 8C 35 D9 84 D4 90 C1”

outStr |A||š|)|#|F|F||G||¢|é| |%|J||¤|•|C|Q||4|I|¥|Œ|5|Ù|„|Ô||Á

Вместо (ожидаемых) байтов, кроме первого/
41 (верно)
44 → 11
53 ->9A
31 → 29

для 44(0b00100010) получаем 11(0b10001000)
Что видим? Сдвиг на 2 бит.
для 53(0b11001010) - (0b01011001) - тоже сдвиг но на 4. Банально похоже на то что устройство одает два стопбита.
Советую подключить логанализатор и снять обмен.

1 лайк

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

идея по сдвижкой выглядит хорошо, продолжаю пробовать варианты, но пока к сожалению ничего не выходит…

пока что не вижу вариантов, как из нижней двоичной последовательности получить верхнюю…

вот в строчном виде что приходит
4351023449A58C35D984D490C1 => 01000011 01010001 00000010 00110100 01001001 10100101 10001100 00110101 11011001 10000100 11010100 10010000 11000001

вот что должно приходить
ADS123:SR1568 => 01000001 01000100 01010011 00110001 00110010 00110011 00111010 01010011 01010010 00110001 00110101 00110110 00111000

длины строк совпадают:
если принять что ожидаемый ответ - ADS123:GET_PRODUCTADS123:SR1568, то это 32 символа

получаемый ответ - 41119A292346461D4715A2E909254A12A4954351023449A58C35D984D490C1 это тоже ровно 32 символа…

а почему в вашей записи младшие биты слева?
в канале они тоже в таком порядке приходят?

Да, сначала младший.
Я советую попробовать
Screenshot_20240830_171037
и разобрать принятое как там описано. Не исключено что “текстовый” вариант просто не поддерживается.

Get_stat неудобно разбирать, по ому что там переменные величины… нужно сначала понять принцип декодирования, а потом все остальное будет делом техники…
Поясните пожалуйста как выполнился сдвиг на 4… когда вместо 53 получилось 9a.

Не арабскому уму непривычно разбирать строки, когда младший бит слева…

А оно возвращается так как в документации?

Посмотрел еще раз, - да, пожалуй я ошибся, не получается если дальше по байтам идти.

да, GET_STAT возвращает строку фиксированной длины и периодически символы в ответе меняются, что говорит о том, что данные датчиков считываются и измененные показания корректно отображаются …

Ну, отлично. Возможно в версии прошивки не поддерживаются более “новые” команды.

Вопрос не решен, ответы на GET_STAT приходят, формат выглядит корректно, но с декодированием такая же беда. Вот пример:

>> 4144533132333A4745545F535441542036310D0A
<< 41 11 9A 29 23 46 46 1D 47 15 A2 E9 69 25 95 41 51 02 14 24 34 D4 90 C1 20 9D 05 24 92 4E 99 61 AD 02 14 64 E4 11 23 88 35 C9 E4 91 23 88 35 FF 38 B9 04 24 92 4E 99 61 AD 12 49 A7 99 61 AD 12 49 A7 99 61 AD 02 08 E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 24 10 40 00 00 00 00 00 00 00 00 00 00 4E BD 72 2A 02 E4 D2 93 53 26 88 38 E1 FC 38 B9 84 04 11 44 18 2E C1 04 11 44 18 2E C1 04 11 44 10 20 C1 E4 11 C0 00 00 DB 01 AA 99 02 04 D1 4A 29 31 D5 64 84 14 E4 11 46 19 2E C1 FC 30 C5 54 FC

Что именно делаете с полученным ответом, что не получается? Да, как минимум байт 2 - значение 0x9a не соответствует допустимому диапазону для “System
index(1~23)”
Если (предположить) рассмотреть гипотезу что полученные данные как-то портятся именно трансивером контролллера - то целесообразно попробовать то же самое на компьютере, используя другой трансивер (адаптер).

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

Думаю что “трансивером” там ничего не портится, какой ему смысл что-то портить или перекодировать, там сам контроллер панелей изначально шлет неверно закодированную строку…
Как пример, если из ответа выделить подстроку

47 15 A2 E9 69 25 95 41 51 02 14 24 34 D4 90 C1 CC FD 14 90 48 39 65 85 5A 02 14 04 E4 D1 23 88 35 E5 E4 D1 46 10 36
FF 34 B9 44 24 92 4E 99 61 AD 12 49 A7 99 61 AD 12 49 A7 99 61 AD 02 08 E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 01 24 10 40 00 00 00 00 00 00 00 00 00 00

то, согласно доке, в ней просматириваются следующие значения (двигаясь с конца строки)

47 15 A2 E9 69 25 95 41 51 02 14 24 34 D4 90 C1 CC FD 14 90 48 39 65 85 5A 02 14 04 E4 D1 23 88 35 E5 E4 D1 46 10 36
FF 34 B9 44 24 92 4E 99 61 AD 12 49 <= это температура 1 A7 99 61 AD 12 49 <= это температура 2 A7 99 61 AD 02 08 <= это температура 3 (E0 00 00 00 00 00 00 00 00 00) <= эти 10 байт пока пропускаем (00 00 00 00 00 01 01 24 10 40) <= эти 10 байт пока пропускаем 00 00 00 00 00 00 00 00 00 00 <= 10 байт ManualStatus

Из этого следует, что точка-разделитель целой и дробной части числа, приходит как ad вместо 2e (2e hex это 46 десятичных, chr(46) = ‘.’)
Чтобы получить из 2e => ad, нужно к 2e прибавить 127 десятичных…

Я пробовал к каждому символу ответа прибавлять 127 и отбрасывать старший бит, но все равно строка остается не декодируемой…

Я думаю, что нужно цепляться логическим анализатором, записывать хотя бы один запрос-ответ и разбираться со скоростью, четностью, стопами, и вообще может там инвертированное. А вот потом уже разбираться с мусором в ответе.