Не спорю, за что огромное спасибо! Но не было температуры и некоторых других показателей. Зато позволяет представлять визуально что происходит при парсинге. Что за что отвечает и при каких входных данных. Согласно Вашим выкладкам и предыдущим скетчам и была сделана табличка:
Так же нашлась примерная схема оптопорта, не считая преобразователя UART-USB Спойлер Если у Миртек такие же команды как в описании протокола Star 104 304 1.20, то команда 0x2A (Чтение записи из журнала) так же не интересна для нас.
Тогда: команда 0x10 - ReadConfigure (Чтение конфигурации) не очень интересно
Код:
Чтение конфигурации Входные данные (0 байт): Выходные данные (19 байт): 1 байт - конфигурационный байт; 1 байт - Бит 0 – автоматический переход на зимнее/летнее время (1 - включено); Бит 2,1 – действующее тарифное расписание (0- раб,1-суб,2-вос,3-спец); Бит 3 - резерв; Бит 4 - резерв; Бит 5 - резерв; Бит 6 - Включение парольной защиты чтения информации абонента; Бит 7 - резерв; 1 байт – время индикации (в секундах, 5 <= t <= 60); 1 байт - Количество попыток доступа с неправильным паролем до блокировки интерфейса, 0-отключено; 1 байт - Ресурс батарейки (полное количество месяцев работы); 1 байт - Ресурс батарейки (количество оставшихся месяцев работы); 1 байт - День сохранения месячного среза по электроэнергии; 1 байт - День сохранения месячного среза по воде; 1 байт - День сохранения месячного среза по газу; 1 байт - Интервал усреднения профилей мощности; 1 байт - Роль устройства (информационный идентификатор, см. Таблицу 2); 1 байт - Побитовая информация о наличии реле: 1-реализовано в железе, 0-отключено. (0й-4й биты - реле №0-№4) 1 байт - Побитовая информация о типе управления реле: 1-импульсом 0,5 сек., 0-уровнем. (0й-4й биты - реле №0-№4) 1 байт - Побитовая информация о статусе реле: 1-разомкнуто, 0-замкнуто. (0й-4й биты - реле №0-№4) 1 байт - Побитовая информация о наличии пломб:1-реализовано в железе, 0-отключено. (0й-4й биты - реле №0-№4) 1 байт - Побитовая информация о статусе пломб:1-реализовано в железе, 0-отключено. (0й-4й биты - реле №0-№4) 1 байт - Код модуля связи на UART1. См. таблицу кодов; 1 байт - Код модуля связи на UART1. См. таблицу кодов; 1 байт - Код модуля связи на UART1. См. таблицу кодов.
только если это брать:
Код:
1 байт - Побитовая информация о статусе реле: 1-разомкнуто, 0-замкнуто. (0й-4й биты - реле №0-№4) 1 байт - Побитовая информация о наличии пломб:1-реализовано в железе, 0-отключено. (0й-4й биты - реле №0-№4) 1 байт - Побитовая информация о статусе пломб:1-реализовано в железе, 0-отключено. (0й-4й биты - реле №0-№4)
команда 0x05 (0x04 подкоманда) не описана, возможно ошибки как и с командой 0x28 дополнительных режимов индикации, и она не имеет 14-го байта, а значит скорей всего должна формироваться с длиной 0x20 без 14-го байта и получать 3 пакета, а не 4. (надо проверять)
команда 0x0A (0x01 подкоманда) не описана данная команда вообще (возможно ошибочная).
В Ваших изысканиях указана дата 03/04/2022, что предполагает что это Вс, согласно описанию
Код:
0x1C - ReadDateTime Чтение времени и даты Входные данные (0 байт): Выходные данные (7 байт): 7 байт: секунды, минуты, часы, день недели (Пн-1,Вт-2,Ср-3,Чт-4,Пт-5,Сб-6,Вс-0), день, месяц, год.
получается, что между временем и датой - день недели, у Вас 0x00, что соответствует Вс в описании вторая строка (получение ответа) между 0x13 0x26 0x05 и 0x03 0x04 0x16 стоит 0x00 - вс (надо проверить)
Если все так, то согласно этому протоколу для нас интересны следующие команды: 0x24 - Чтение значений энергии по тарифам и суммарно, сохраненных на начало текущего и 35 предыдущих месяцев 0x25 - Чтение значений энергии по тарифам и суммарно, сохраненных на конец суток, за прошедшие 128 суток 0x29 - Чтение значений сетевого напряжения (не особо имеет смысл отдельно при запросе мгонвенных значений 0x2B 0x00)
Код:
Входные данные (1 байт): 1 байт: номер фазы, для однофазный устройств - число 1; для трехфазных устройств (числа – 1,2,3). Выходные данные (3 байт): 1 байт - номер фазы, для однофазный устройств - число 1; для трехфазных устройств (числа – 1,2,3); 2 байта - значение напряжение сети (для приведения к кВт значение необходимо делить на 100);
Address Source: Адрес программы опроса = 0xFFFF - в Ваших выкладках как раз он установлен в 0xFF 0xFF, а в скетче 0x09 0xFF, интересно что отправляет сам пульт, что бы маскироваться под него. Да и в принципе и всё.
Последний раз редактировалось SysCat Ср июн 28, 2023 21:21:11, всего редактировалось 1 раз.
...Address Source: Адрес программы опроса = 0xFFFF - в Ваших выкладках как раз он установлен в 0xFF 0xFF, а в скетче 0x09 0xFF, интересно что отправляет сам пульт, что бы маскироваться под него. Да и в принципе и всё.
вторая строка (получение ответа) между 0x13 0x26 0x05 и 0x03 0x04 0x16 стоит 0x00 - вс
между временем и датой есть байт который показывает день недели по календарю
Код:
0x1C - ReadDateTime Чтение времени и даты Входные данные (0 байт): Выходные данные (7 байт): 7 байт: секунды, минуты, часы, день недели (Пн-1,Вт-2,Ср-3,Чт-4,Пт-5,Сб-6,Вс-0), день, месяц, год.
Добавил в скетч вывод дня недели. (XX XX - номер счетчика в HEX)
Код:
Packet sent: F 73 55 20 0 XX XX FE FF 1C 0 0 0 0 5C 55 Packets received: 3 73 55 7 0 FE FF XX XX 1C A8 43 5B 0 D 33 15 3 1C 6 17 E8 55 Packet lengt: 22 7 0 FE FF XX XX 1C A8 43 5B 0 D 33 15 3 1C 6 17 E8 Last Request: 28-06-23 21:51:13 Ср
Цитата:
команда 0x05 (0x04 подкоманда) не описана, возможно ошибки как и с командой 0x28 дополнительных режимов индикации, и она не имеет 14-го байта, а значит скорей всего должна формироваться с длиной 0x20 без 14-го байта и получать 3 пакета, а не 4. (надо проверять)
Проверил, был не прав, все же используется длинный запрос с 14-м байтом, который равен следующему:
Теперь понял к чему была картинка загруженная по какой-то ссылке "CQ_DAT.jpg" вроде как от Dismas
Тогда запрос 0x05, 0x00 - запрос суммарных показаний для активной прямой энергии, а запрос 0x05, 0x04 - запрос суммарных показаний для абсолютной активной энергии, но разницы в показаниях 0x00 и 0x04 не увидел, абсолютная=прямая+обратная, странно, что не абсолютная=прямая-обратная, но мы же не продаем обратно энергию энергоснабжающей компании, поэтому реверсивная у нас должна быть равной 0, но на картинке Реактивная Прямая =0,26; Реактивная Обратная = 0,16, а Реактивная абсолютная сумма R+ + R-, хотя разумнее было бы R+ - R-, а остаток у нас к оплате, но так получается это сумма прокачанной энергии и не важно её направление, если я правильно понял . А значит, что нам полезны только команды 0x05, 0x00 и 0x05, 0x02, но нужны ли нам значения 0x05, 0x02, думаю что нет.
Цитата:
Мой пульт отправляет 0xFEFF
Поменял в скетче, поставил вместо 0x09 0xFF Ваши значения 0xFE 0xFF
Код:
transmitt_byte[7] = 0xfe; // было 0x09 transmitt_byte[8] = 0xff;
Вложения:
Комментарий к файлу: Обновления 7: добавлен день недели, замена 0x09 0xFF на 0xFE 0xFF, отрицательные косинусы, немного чистки, комментарии кода и немного логического размещение кода My_Mirtek_GW_upd7.zip [8.13 KiB]
Скачиваний: 106
Всем привет. Обновил прошивку своей esp32 на последнюю SysCat. Но ничего не работает. Подключаюсь к точке доступа, настройки вводу. К wifi подключается только если плата esp32 лежит рядом с роутером. Чуть дальше и все, нет подключения. После подключения к wifi я вижу ip платы, но не могу войти в нее. На mqtt ничего не приходит. Через serial порт если смотреть данные, то такое ощущение, что плата зависает.
Всем привет! А никто не смотрел в сторону EspEasy? Там и OTA, и вэбморда. И плагин CC1101 есть, который можно, наверное, взять за основу. Сам, к сожалению, не программист, поэтому могу поучаствовать только как тестировщик, морально и материально даже )
Всем привет. Обновил прошивку своей esp32 на последнюю SysCat. Но ничего не работает. Подключаюсь к точке доступа, настройки вводу. К wifi подключается только если плата esp32 лежит рядом с роутером. Чуть дальше и все, нет подключения. После подключения к wifi я вижу ip платы, но не могу войти в нее. На mqtt ничего не приходит. Через serial порт если смотреть данные, то такое ощущение, что плата зависает.
В прошивке нет влияния на уровень мощности Wi-fi.
А Вы физически переключили gdo0 с GPIO2 (вывод D2) на GPIO22 (вывод D22)?
GPIO2 - подключен на встроенный светодиод. Быстрые мигания 30 сек. - поднята точка доступа, Медленные мигания - попытка подключения в Вашему Wi-fi в роли клиента, Горение светодиода - подключен к MQTT серверу.
В коде был изменен номер вывода, соответственно физически тоже нужно поменять, или вернуть в коде обратно. Было:
Код:
int gdo0 = 2;
Стало:
Код:
int gdo0 = 22;
Попробуйте переключить или поменять в коде. Веб страница становится доступна только после переключения платы с режима точки доступа на режим клиента Wi-fi. Но в Serial должны выводится состояния платы:
Код:
st:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1216 ho 0 tail 12 room 4 load:0x40078000,len:10944 load:0x40080400,len:6388 entry 0x400806b4 Config version: mirtek_gw_v1 Config size: 555 Loading configurations [iwcAll] |-- [iwcSys] | |-- 'iwcThingName' with value: 'Mirtek_GW' | |-- 'iwcApPassword' with value: <hidden> - пароль на веб страницу | |-- [iwcWifi0] | | |-- 'iwcWifiSsid' with value: 'ВАША ТОЧКА ДОСТУПА' | | \-- 'iwcWifiPassword' with value: <hidden> - пароль к Вашей точке доступа | \-- 'iwcApTimeout' with value: '30' - таймер 30 сек. |-- [iwcCustom] | |-- [mqtt] | | |-- 'mqttServer' with value: 'IP адрес MQTT сервера' | | |-- 'mqttUser' with value: 'Логин на MQTT сервере' | | \-- 'mqttPass' with value: <hidden> - пароль к учетке MQTT сервера | \-- [group1] | \-- 'MeterAdress' with value: 'Номер счетчика' \-- [hidden] Ready. SPI Connection CC1101 OK - соединение с CP1101 State changing from: 0 to 2 - не знаю почему в библиотеке так, но разумнее было 0 to 1 Setting up AP: Mirtek_GW - поднята точка доступа. Роль - сервер Use password: <hidden> - по умолчанию пароль 12345678 AP IP address: 192.168.4.1 - IP адрес в режиме точки доступа для настроек AP timeout (ms): 30000 - таймер локальной точки доступа для настроек - 30 сек. State changed from: 0 to 2 - не знаю почему в библиотеке так, но разумнее было 1 to 2 State changing from: 2 to 3 Connecting to [ВАША ТОЧКА ДОСТУПА] (password is hidden) - подключение к Вашей точке доступа в роли клента WiFi timeout (ms): 30000 - таймер для подключения к Вашей точке доступа - 30 сек. State changed from: 2 to 3 WiFi connected - подключено к Вашей точке доступа IP address: ЛОКАЛЬНЫЙ IP-адрес от полученный роутера State changing from: 3 to 4 Active mDNS services: 1 Accepting connection State changed from: 3 to 4 Connecting to MQTT server... - подключение к MQTT серверу Connected! - подключен к MQTT серверу
При обновлении прошивки все настройки хранимые в памяти не переписываются, проверьте корректность настроек.
В самой структуре MQTT топика также были сделаны изменения, добавлен еще один подуровень в виде номера счетчика. Было:
Код:
"mirtek/параметры и зачения"
Стало:
Код:
"mirtek/" + (String)MeterAdressValue + "/параметры и значения"
Где (String)MeterAdressValue - номер счетчика из настроек, соответственно путь стал mirtek/12345/параметры и значения
А никто не смотрел в сторону EspEasy? Там и OTA, и вэбморда. И плагин CC1101 есть, который можно, наверное, взять за основу
Там скорей всего эта настройка рассматривается просто как "труба" UART (Serial) между ESP и CC1101, так же есть модули которые в себе. содержат дополнительный контроллер и на входе там уже UART, а не SPI как в нашем случае.
Один из примеров - принятый пакет: 73h,55h,7,0,0FFh,0FFh,7Ch,64h,1Ch,0A8h,5,5Bh,0,13h,26h,5,0,3,4,16h,73h,22h,55h Видим стандартная длинна +7 байт, а в пакете на 1 байт больше. CRC не сойдётся, нужно произвести обратный байтстаффинг, и только после этого подсчитывать CRC и сравнивать с тем, что имеется в пакете на предмет "правильности"
Согласно структуре пакета вроде предпоследний байт?? - 22h должна быть. Функции приёма и передачи пакетов я не трогал, только 1 параметр в функции формирования пакета для передачи. Я не писать, я читатель , я только один байт в параметре передачи пакета поправил, проверки CRC вроде там нет в коде, а все нужные параметры приходят и при 0x9F 0xFF, и при 0xFF 0xFF, и при 0FE 0xFF, ранее в коде то вообще в одном пакете передавали 0x9F 0xFF, а другом месте 0xFF 0xFF передавали.
При отправке стали CRC так:
Код:
//вычисляем и добавляем байт crc crc.restart(); crc.setPolynome(0xA9); for (int i = 3; i < (transmitt_byte[0] - 1); i++) { crc.add(transmitt_byte[i]); }
а при приеме пакета так:
Код:
crc.reset(); crc.setPolynome(0xA9); for (int i = 2; i < (bytecount - 2); i++) { crc.add(resultbuffer[i]); Serial.print(resultbuffer[i], HEX) Serial.print(" "); } Serial.println(); myCRC = crc.getCRC(); Serial.print("Calculate myCRC: "); Serial.println(myCRC, HEX);
Вынужден разочаровать, в данном случае, CRC 73 потому как имеет место байтстаффинг. Смотрим описание протокола обмена: При формировании пакета, если между стартовыми байтами 73 55 и стоповыми 55 имеются 73 или 55, то они заменяются на последовательности 73 22 и 73 11 соответственно. В данном конкретном случае 73 22 что эквивалентно 73. При разборе пакета необходимо проверять наличие старт-стоп последовательности а между ними наличие байтстаффинга. (Длинна пакета в любом случае остаётся правильной, о чём я говорил раньше.) После этого подсчитывать CRC сравнивать с имеющейся в пакете и только после этого парсить пакет. Если этого не делать, появляются мистические "кривые" ответы.
Это если действительно заниматься сравнением CRC и отсечением неверных пакетов, но слишком завышенные значения уже отсекаются после парсинга и на сервер в MQTT не идут, но в WEB интерфейсе будут отображаться. Конечно это не правильно, но как говорится испорчено было до меня, а разбираться в чужом коде то еще веселье, но я почти разобрался и можно будет прикрутить проверку CRC и отправка повторных запросов счетчику в случае получения некорректных битых пакетов. Вы конечно правы, просто пока руки до CRC не дошли еще, попробую разобраться с этим волшебным байстаффингом. Но всему свое время. Пока хоть и с костылями и так работает, а так бы переписать все нафиг.
...попробую разобраться с этим волшебным байстаффингом...
Он нужен по одной причине: отделить стартовую/стоповую последовательность от информационных байтов между ними, не более того. Название правда громкое, впрочем это так же как анчоус, красиво, громко а на деле - обычная хамса
Так разделение в коде происходит, ответный пакет кладется просто в массив байтов, откуда парсится тупо по элементам. Старт/стоп проверяется в условиях парсинга что они на своих местах:
Код:
if ((resultbuffer[0] == 0x73) and (resultbuffer[1] == 0x55) and (resultbuffer[2] == 0x07) and (resultbuffer[6] == (atoi(MeterAdressValue) & 0xff)) and (resultbuffer[7] == ((atoi(MeterAdressValue) >> 8) & 0xff)) and (resultbuffer[21] == 0x55))
Элементы 0, 1 - старт, 21 - стоп, остальное данные
Но Вы правы, надо сделать все по уму, чтобы перезапрашивать так же битые пакеты. Будем разбираться, пока в отпуске и далеко от пульта. Не обижайтесь!
И в описании протокола написано только:
Цитата:
Байтстаффингу подвергаются все байты пакета за исключением стартовых и стопового. Стартовая последовательность - 0х73 0х55, стоповая - 0х55, все что между ними, подлежит байтстаффингу. При байтстаффинге анализируется каждый байт, и: 0х55 заменяется на 0х73 0х11, 0х73 заменяется на 0х73 0х22. При обратном байтстаффинге проводится противоположная замена.
И немного не понимаю как он работает? Только замена определенной последовательности на определённую другую? Тут только определенные байты приводятся. Простите за глупость, но я пока не понимаю как работает этот байтстаффинг для остальных данных. С CRC всё куда понятнее и пример расчёта приведён хоть и для Delphi.
...но я пока не понимаю как работает этот байтстаффинг для остальных данных...
Странно, вроде бы однозначно написано в стандарте... ну ладно, попробую ещё раз. И так: -Стартовая последовательность имеет вид 73 55 далее идут всякие разные данные, маркером конца служит байт 55. По этим признакам находят начало/конец пакета. Теперь предположим, что в середине пакета имеется один или несколько байтов данных со значением 55. Как их рассматривать ? Как маркер конца пакета ? Или имеется байты со значением 73 , как его воспринимать ? Для того, что бы разделить данные и маркеры начала и конца, и введено это самое понятие байтстаффинг , где заменяются некоторые байты на последовательности 73 11 и 73 22. Как обрабатывать ? Находим стартовую последовательность 73 55, далее последовательно сравниваем все байты с 73, если таковой находим, проверяем следующий за ним байт, если это 11 то заменяем эти два байта на 55, если это 22 то заменяем эти два байта на 73 и так до маркера конца пакета 55. Только после этого длинна пакета будет верной, а его CRC при расчёте будет правильной. Другие байты не изменяются.
Спасибо за помощь, Dismas! Просто я думал что для других входных данных другие выходные, а оказывается все просто, только 73 и 55 в данных обрабатываем ну и соотвественно 73 11 и 73 22. Вернусь с отпуска тогда буду реализовывать это, а так же можно спокойно будет добавить проверку CRC и перезапрос битых пакетов. Вместе - сила!
Добавил обработку принятого пакета обратным байтстаффингом. Для отправляемого пакета пока вроде особо не нужен байтстаффинг, так как пока в очень крайнем случае только байты с номером счетчика могут стать 0x73 или 0x55, остальные в текущий момент отличны от них и не требуют замены.
На идеальность и оптимизированность кода не претендую:
Код:
int j = 0; //Значение компенсирующего смещения индекса for (int i = 0; i < bytecounttemp; i++) { resultbuffer [i-j] = tempbuffer[i]; //Записываем текущее значение байта из временного буфера в выходной bytecount++; //Считаем длину результирующего буфера if (tempbuffer[i] == 0x73 and (i + 1 < bytecounttemp)) { if (tempbuffer[i + 1] == 0x11) //Проверяем что последовательность 0x73 0x11 { resultbuffer[i-j] = 0x55; //Меняем последовательность 0x73 0x11 на 0x55 i++; //Пропускаем следующий байт j++; //Компенсируем индекс результирующего буфера при пропуске байта } if (tempbuffer[i + 1] == 0x22) //Проверяем что последовательность 0x73 0x22 { i++; //В результирующем буфере уже лежит 0x73 вместо 0x73 0x22, пропускаем следующий байт j++; //Компенсируем индекс результирующего буфера при пропуске байта } } }
Так же временно добавил вывод отправленного/принятого пакета в MQTT для контроля. Отключены проверки на предельные значения (ранее был такой костыль). Пока запредельных значений не прилетало, еще тестирую. Добавлена проверка CRC.
Сейчас этот форум просматривают: Google [Bot] и гости: 16
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения