Вообще, вся суть в топике, но расскажу всю цепочку рассуждений.
Завязка
У меня сгорел основной мозг в котельной, когда на улице было под 30 градусов мороза, а под руками лежал блок SWK с реле WB-MR6-LV, взятые под другую котельную и ждавшие своего часа. Накидал программу управления в SWK, протянул провода к сигналам реле, протянул датчик, развел проводку, запустил систему, дома тепло, все в безопасности. Но WB-MR6-LV хоть и имеет внутри реле наминалом в 16А, само обозначено наминалом в 10А, и при реальном токе в 14А на каждой линии явно работало на пределе своих возможностей. Система работала “по теплоносителю”, температуру которого нужно было подбирать под погоду, при том, что датчиков температуры всех возможных видов у меня по дому разбросано с десяток, и раз уж в котельную зашел более продвинутый мозг, хотелось бы регулировать работу котла по температуре в помещении, а не в трубе.
По этим причинам были закуплены wb-8.5 и WB-MRWL3 с номиналом в 20А, чтобы подключить котельную к остальным датчикам, которые напрямую со SW не женятся, но легко цепляются к MQTT брокеру.
Разочарование
Пришло железо. Пытаясь настроить связь WB-8.5 и SWK, понимаю, что can вырезали, адаптер не выпустили, под стик надо самому собирать ядро и это вообще никто нормально еще не тестировал и не проверял, самый рабочий ответ, который нашел “покупайте WB-7”, но уже поздно, да и не очень хочется брать контроллер предыдущего поколения из-за одного капризного устройства.
Кульминация
В этот момент обратил внимание на переключатель “Режим CAN-UDP моста” в настройках SWK, и включил этот режим. Второй контроллер у меня занимается подогревом ГВС, и расположен немного в другом месте, но в той же сети. На нем также была активирована данная настройка, и, о чудо, они нашли друг-друга и отобразились в обоих интерфейсах. Дальше мысль уже простая, если контроллеры как-то разговаривают друг с другом через UDP, в чем проблема добавить еще одного участника в этот канал?
Написал в поддержку SW и пошел исследовать вопрос. В документации глухо, написано, что мост есть, но ни как он реализован, ни как к нему подключиться нигде не написано. Фича и фича, жмите галочку, радуйтесь, что работает.
Ладно, раз кроме этой галочки ничего нет, значит как-то контроллеры зондируют сеть, чтобы искать своих братьев. Слушаем сеть:
❯ sudo tcpdump -ni wlan0 -s 0 -vv '(udp or tcp) and host 192.168.1.123'
tcpdump: listening on wlan0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
23:07:38.099979 IP (tos 0x0, ttl 255, id 18385, offset 0, flags [none], proto UDP (17), length 32)
192.168.1.123.31987 > 255.255.255.255.31987: [udp sum ok] UDP, length 4
23:08:38.105770 IP (tos 0x0, ttl 255, id 18392, offset 0, flags [none], proto UDP (17), length 32)
192.168.1.123.31987 > 255.255.255.255.31987: [udp sum ok] UDP, length 4
А вот и широковещательные запросы, судя по частоте и содержанию, на данные из can не похожи, слишком редкие, да и информации маловато.
Наверное, нужно как-то подписаться на участие в can рассылке, чтобы получать информацию из моста. Путем долгого тыкания пальцем в небо, таки получается заставить систему нам чего-то отвечать.
# В отдельном терминале отправляем запрос
❯ printf '\xAB\x66\x00\x00' | ncat -u -w1 192.168.1.123 31987
По предыдущей команде продолжаем слушать, информация начинает литься рекой, пакеты разной длинны
23:19:02.030546 IP (tos 0x0, ttl 255, id 19142, offset 0, flags [none], proto UDP (17), length 124)
192.168.1.123.31987 > 192.168.1.123.31987: [udp sum ok] UDP, length 96
23:19:02.616727 IP (tos 0x0, ttl 255, id 19144, offset 0, flags [none], proto UDP (17), length 220)
192.168.1.123.31987 > 192.168.1.123.31987: [udp sum ok] UDP, length 192
23:19:03.008650 IP (tos 0x0, ttl 255, id 19146, offset 0, flags [none], proto UDP (17), length 172)
192.168.1.123.31987 > 192.168.1.123.31987: [udp sum ok] UDP, length 144
23:19:03.416359 IP (tos 0x0, ttl 255, id 19148, offset 0, flags [none], proto UDP (17), length 124)
192.168.1.123.31987 > 192.168.1.123.31987: [udp sum ok] UDP, length 96
Заглянем внутрь:
❯ sudo tcpdump -ni wlan0 -s 0 -X 'udp and (host 192.168.1.123) and (port 31987)'
23:25:54.294701 IP 192.168.1.123.31987 > 192.168.1.123.31987: UDP, length 72
0x0000: 4500 0064 4d7f 0000 ff11 e7ba c0a8 0279 E..dM..........y
0x0010: c0a8 0285 7cf3 7cf3 0050 92f4 ab66 0100 ....|.|..P...f..
0x0020: 1644 0110 0001 0401 0201 0000 0000 0000 .D..............
0x0030: ff01 0000 ab66 0100 1643 0110 0001 0501 .....f...C......
0x0040: 0101 ba01 0000 0000 d0d6 0020 ab66 0100 .............f..
0x0050: 1641 0100 0001 0406 0700 0000 0000 0000 .A..............
0x0060: 0000 0000 ....
23:25:55.348544 IP 192.168.1.123.31987 > 192.168.1.123.31987: UDP, length 24
0x0000: 4500 0034 4d81 0000 ff11 e7e8 c0a8 0279 E..4M..........y
0x0010: c0a8 0285 7cf3 7cf3 0020 459e ab66 0100 ....|.|...E..f..
0x0020: 0646 0110 0001 040a 0100 0000 0000 0000 .F..............
0x0030: 80f2 0020 ....
В лоб значения не читаются, но по внешнему виду очевидно, что это как раз и есть содержимое can-udp моста, осталось только понять как именно кодируется этот поток и, теоретически, можно лить данные с него в виртуальный can и пробрасывать в уже работающий драйвер wb-mqtt-smartweb
В этот момент пришел ответ от поддержки SW, приводить его не буду, но для меня стало понятно, что помощи там не будет. Силы бороться с ветряными мельницами у меня иссякли, я вырвал с щита котроллер SWK, поставил WB-8.5 c WB-MRWL3, и на коленке написал термостатическое управление по температуре теплоносителя.
var termo_0 = 'wb-w1/28-xxxxxxxxxx'
var heaterState = 0
var ps = new PersistentStorage("thermostat", {global: true});
function setHeater(value){
if(heaterState == value) return
heaterState = value
dev['wb-mr3_xxx/K1'] = heaterState >= 1
dev['wb-mr3_xxx/K2'] = heaterState >= 2
dev['wb-mr3_xxx/K3'] = heaterState >= 3
}
defineVirtualDevice('thermostat', {
title: {en: 'termo', ru: 'термо'} ,
cells: {
setpoint: {
title: "Уставка",
type: "range",
value: ps["setpoint"] || 50,
max: 100,
min: 1
},
hysteresis:{
title: "Гистерезис",
type: "range",
value: ps['hysteresis'] || 1.0,
max: 5,
min: 0.1
}
}
});
defineRule("thermoPersistant", {
whenChanged: ["thermostat/setpoint", "thermostat/hysteresis"],
then: function(newValue, devName, cellName) {
ps[cellName] = newValue
}
})
defineRule("test_whenChanged", {
whenChanged: [termo_0],
then: function (newValue, devName, cellName) {
var setpoint = dev['thermostat/setpoint']
var hysteresis = dev['thermostat/hysteresis']
if(newValue < setpoint - hysteresis && heaterState < 3) {
setHeater(3)
} else if ( newValue > setpoint + hysteresis && heaterState > 0){
setHeater(0)
}
}
});
Крутилку прокинул в HA, чтобы можно было по месту подстраивть температуру, понемногу переписываю логику работы контроллера котла.
Вопрос
Насколько мне подсказывает интуиция, метод, которым я пытался подрубить SWK к WB жизнеспособен, и (если исключить тот факт, что SW разработали для этого отдельную железку и впаривают ее по неадекватной, на мой взгляд, цене) может быть доведен до рабочей реализации. Так ли это, и может ли с этим кто-то помочь?
У меня мотивация копаться в этом одному сильно угасла, но, т.к. это может кому-то помочь и из собственного любопытства, согласен посодействовать, да и мой второй контроллер можно тогда будет нормально в HA пробросить для аналитики.