Инструменты пользователя

Инструменты сайта


настройка_modbus

Функциональность драйвера Modbus v2

LightHub можно настроить на работу в качестве шлюза с фактически любым устройством, поддерживающим Modbus RTU и работающем в режиме Slave

В отличии от v1, драйвер можно настроить на работу в качестве шлюза с фактически любым устройством, поддерживающим Modbus RTU и работающем в режиме Slave Поддерживается как чтение так и запись в modbus устройства

Раздел "modbus" конфигурации

В корневом разделе modbus конфигурации описывается библиотека используемых типов устройств.

Для каждого устройства в библиотеки возможно задать такие параметры как скорость обмена (раздел baud) /параметры четности (раздел serial), назначение и тип регистров (раздел par), а также, интервал и параметры опроса этих регистров (раздел poll)

раздел par

Данный раздел содержит информацию о назначении каждого опрашиваемого или управляемого регистра (или групп регистров) используемого устройства. Раздел состоит из JSON объектов следующего формата:

"t_heat":{"reg":8,"map":[0,1024,0,1024],"type":"i16"},

В примере выше:

  • «t_heat» - имя параметра устройства.
  • «reg» - регистр (или стартовый HOLDING REGISTER) параметра
  • «ir: - INPUT REGISTER или «reg»- HOLDING REGISTER или «coil»: COIL или «din» - DISCRETE INPUT
  • «map» - правила преобразования (TBD)
  • «type»:«i16» - указывает, что значение - 16-ти битное число со знаком

Возможные варианты типов:

  • i16 - знаковый 16-ти битный регистр (по умолчанию)
  • i32 - знаковый 32-ти битный регистр (первый регистр - младшие биты, следующий - старшие)
  • u16 - беззнаковый 16-ти битный регистр
  • u32 - беззнаковый 32-ти битный регистр (первый регистр - младшие биты, следующий - старшие)
  • i8h - старшие 8 бит регистра (при записи значения, другие 8 бит будут заполнены значением 0xFF)
  • i8l - старшие 8 бит регистра (при записи значения, другие 8 бит будут заполнены значением 0xFF)
  • x10 - дробное число с точностью до 0.1 полученное путем деления значения 16 битного регистра со знаком на 10 (часто используется в разных устройствах для кодирования температуры, например, значение 124 в регистре соответствует 12,4)
  • 100 - дробное число с точностью до 0.01 полученное путем деления значения 16 битного регистра со знаком на 100

раздел poll

задает интервал и параметры опроса регистров устройства

Причем, в целях оптимизации обмена, можно опрашивать устройство командой чтения группы регистров. Пример:

"poll":{"regs":[[40000,40014],[30000,30002],40099],"delay":10000}

Обозначает, что с интервалом 10 сек будут произведены следующие три опроса:

  • Команда чтения группы из 15-ти регистров с 40000 по 40014
  • Команда чтения группы из 3-x регистров с 30000 по 30002
  • Команда чтения одиночного регистра 40099

Для каждого из успешно прочитанных регистров, проводится поиск соответствия в разделе par и ir Если есть запись, соответствующая данному регистру, прочитанные значения преобразовываются (см описание map) и направляются в MQTT и/или локальным объектам контроллера

Отправка происходит, если с момента последнего опроса значение регистра изменилось кроме regs допустимы irs и coils

Или вот пример для сенсора Sensair S8 Опрашиваем INPUT REGISTERS 0-3,21,25-30 и HOLDING REGISTERS 0,1,31

   "sensair":{"baud":9600,
             "poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
             "par":{
                            "co2":{"ir":3},
                            "meterStat":{"ir":0},
                            "alarmStat":{"ir":1},
                            "outStat":{"ir":0},
                            "pwm":{"ir":21},
                            "typeid":{"ir":25,"type":"u32"},
                            "mapver":{"ir":27},
                            "fwver":{"ir":28},
                            "sensorid":{"ir":29,"type":"u32"},
                            "ack":{"reg":0},
                            "command":{"reg":1},
                            "abc":{"reg":31}
                            
                            
             }

А вот пример подключения Modbus адаптера кондиционера Haier

"modbus":
  {
    "haier":{"baud":9600,
             "poll":{"regs":[[0,3]],"irs":[[0,1]],"coils":[0],"delay":5000},
             "par":{
                            "pwr":{"coil":0,"map":{"cmd":[1,["OFF",0]],"val":null, "def":"acmode"},"id":1},
                            "acmode":{"reg":1,"map":{"cmd":[["FAN_ONLY",4],["HEAT",2],["COOL",1],["DRY",3],["AUTO",5]],"val":null},"id":1},
                            "$temp":{"ir":0},
                            "$fault":{"ir":1},
                            "set":{"reg":0,"id":2},
                            "fan":{"reg":2,"id":7,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2],["AUTO",4]]}},
                            "lock":{"reg":3,"map":{"cmd":[["OFF",1],["ON",4]]}}
                            
                    }       
       }
    
  },
  
"items": { 
    
  "ac_2":[14,[128,
                  "haier",
                  {
                  "pwr":{"emit":"home/s_out/ac_2/cmd","@V":null},
                  "$temp":{"emit":"home/s_out/ac_2/$temp","@S":null},
                  "$fault":{"emit":"home/s_out/ac_2/$fault"},
                  "set":{"emit":"home/s_out/ac_2/set"},
                  "acmode":{"emit":"home/s_out/ac_2/$mode","@V":null},
                  "fan":{"emit":"home/s_out/ac_2/fan","@V":null},
                  "lock":{"emit":"home/s_out/ac_2/lock","@V":null}
                  }
                  ]
              ]
          }
}                

Разделы baud и serial

Пример:

              "baud":9600,
              "serial":"8E1"

Соответственно, скорость обмена (по умолчанию, 9600) и параметр четности порта Параметр четности - одно из значений ниже. По умолчанию 8N1

«8E1»,»8N1«,»8E2«, «8N2», «8O1», «8O2», «8M1», «8S1», «7E1», «7N1», «7E2», «7N2», «7O1», «7O2», «7M1», «7S1»

Раздел "items" конфигурации

В данном разделе задаются конкретные modbus устройства по шаблону, определенному в разделе modbus

  "items": {
    "dimer1":[14,[1,
                  "dim4",
                     {
                      "ch1":{"emit":"aaa1,"item":"localdimmer1"},
                      "ch2":{"emit":"abc/aaa2"},
                      "ch3":{"item":"localdimmer3"},
                      "ch4":[{"emit":"aaa4,"item":"localdimmer4"},{"emit":"aaa44,"item":"localdimmer44"}]                  
                      }
                  ]
              ],

В данном примере, создается item (объект) dimer1 с типом 14 (modbus v2) адресом modbus=1, на основе библиотечного устройства «dim4»

Устройство опрашивается согласно настройкам в библиотеке. А вот результаты опроса используются согласно настройкам в items. В данном примере,

  • «ch1» передается в MQTT топик «myhome/s_out/aaa1» плюс локальному устройству «localdimmer1»
  • «ch2» передается в MQTT топик «abc/aaa2» (если в названии топика есть / - он не дополняется слева статусным префиксом)
  • «ch3» передается локальному устройству «localdimmer3»
  • «ch4» передается в MQTT топик «myhome/s_out/aaa4» и «myhome/s_out/aaa44», локальному устройству «localdimmer4» и «localdimmer44» (использован массив из двух JSON объектов)

Строки ch1 - ch4 в данном примере, определенные в третем параметре массива конфигурации, далее будем называть «именованными параметрами modbus item»

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

myhome/in/dimer1/ch1/set

(Здесь и далее для простоты предполагаем что mqtt префикс по-умолчанию myhome и обращение через broadcast имя устройства in)

«ch1» используется как subItem устройства (ставится между именем item и суффиксом)

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

NB. Не надо именовать данные параметры именами стандартных суффиксов (set, cmd, fan и пр) (см. полный перечень стандартных суффиксов)

Также, возможно управлять не отдельными subItem - ами modbus устройства, а устройством в целом, по аналогии с тем, как это делается для всех типичных item-ов LightHub. То есть, задавать один общий параметр устройства через суффикс /set, команды через суффикс /cmd и пр (см. полный перечень стандартных суффиксов)

Для этого в разделе шаблона устройства, в описании конкретного параметра modbus можно задать связь параметра с конкретным суффиксом при помощи значения «id»=N, где N - цифровой идентификатор стандартного суффикса (см. полный перечень стандартных суффиксов)

Далее, соберем фрагменты в более полный пример:

"modbus":
  {
    "airset":{
              "baud":9600,
              "serial":"8N1",
              "poll":{"regs":[1,[8,24]],"delay":1000},
              "par":{ 
                            "t_heat":{"reg":8,"map":[0,1024,0,1024],"type":"i16"},
                            "mode":{"reg":24}
                  
              }
              },
    "dim4":{
             "poll":{"regs":[[0,4]],"delay":10000},
             "par":{
                            "ch1":{"reg":0},
                            "ch2":{"reg":1},
                            "ch3":{"reg":2},
                            "ch4":{"reg":3}
             }
            },
            
    "sensair":{"baud":9600,
             "poll":{"irs":[[0,3],21,[25,30]],"regs":[0,1,31],"delay":1000},
             "par":{
                            "co2":{"ir":3},
                            "meterStat":{"ir":0},
                            "alarmStat":{"ir":1},
                            "outStat":{"ir":0},
                            "pwm":{"ir":21},
                            "typeid":{"ir":25,"type":"u32"},
                            "mapver":{"ir":27},
                            "fwver":{"ir":28},
                            "sensorid":{"ir":29,"type":"u32"},
                            "ack":{"reg":0},
                            "command":{"reg":1},
                            "abc":{"reg":31}
                            
                            
             }
          
    }
   },        
    "panel":{
            "poll":{"regs":[[40000,40014],[30000,30002]],"delay":10000},
             "par":{
                            "fan"  :{"reg":40000},
                            "mode" :{"reg":40001},
                            "set"  :{"reg":40002},
                            "pwr"  :{"reg":40003},
                            "alm01":{"reg":40004},
                            "alm17":{"reg":40005},
                            "alm33":{"reg":40006},
                            "sethum" :{"reg":40007},
                            "setvoc" :{"reg":40008},
                            
                            "temp" :{"reg":30000},
                            "hum"  :{"reg":30001},
                            "voc"  :{"reg":30002},
                            
                            "ch_temp"  :{"reg":40009},
                            "ext_temp" :{"reg":40010},
                            "out_temp" :{"reg":40011},
                            "water_temp" :{"reg":40012},
                            "ch_hum"  :{"reg":40013},
                            "heat_pwr":{"reg":40014}
             }   
    }
  },
  

  "items": {
    "airset1":[14,[10,"airset",{"t_heat":{"emit":"aaa"}}]],
    "panel1":[14,[2,"panel"]],
    "dimer1":[14,[1,"dim4",
                     {
                      "ch1":{"emit":"aaa1,"item":"localdimmer1"},
                      "ch2":{"emit":"abc/aaa2"},
                      "ch3":{"item":"localdimmer3"},
                      "ch4":[{"emit":"aaa4,"item":"localdimmer4"},{"emit":"aaa44,"item":"localdimmer44"}]                  
                      }
                  ]
              ]
           },
    "sensair1":[14,[254,
                  "sensair",
                  {"co2":{"emit":"co2"}}                  
                  ]
              ]
 }

}                        
           

Подавление повторных значений

В процессе опроса устройств, драйвер запоминает последнее считанное из регистра modbus значение во внутреннюю переменную @S внутри именованного параметра item

Если значение не изменилось с последнего считывания - операция по отправки значения в modbus или локальному обьекту не производится

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

Пример - панель управления климатом Zentec. Измерения влажности передаются каждый раз:

"modbus":
  {

    "panel":{
            "serial":"8E1",
            "poll":{"regs":[[40000,40014],[30000,30002]],"delay":10000},
             "par":{
                            "fan"  :{"reg":40000,"map":[1,[0,7,0,100]],"id":11},
                            "mode" :{"reg":40001,"mapcmd":[2,[[1,"FAN_ONLY"],[2,"HEAT"],[4,"COOL"],[8,"AUTO"]]]},
                            "settemp"  :{"reg":40002,"id":12},
                            "pwr"  :{"reg":40003,"mapcmd":[2,[[0,2],[1,1]]]},
                            "alm01":{"reg":40004},
                            "alm17":{"reg":40005},
                            "alm33":{"reg":40006},
                            "sethum" :{"reg":40007,"id":13},
                            "setvoc" :{"reg":40008,"id":14},
                            
                            "roomtemp" :{"reg":30000,"type":"x10"},
                            "hum"  :{"reg":30001},
                            "voc"  :{"reg":30002},
                            
                            "ch_temp"  :{"reg":40009,"type":"x10","id":15},
                            "ext_temp" :{"reg":40010,"type":"x10","id":16},
                            "out_temp" :{"reg":40011,"type":"x10","id":17},
                            "water_temp" :{"reg":40012,"type":"x10","id":18},
                            "ch_hum"  :{"reg":40013},
                            "heat_pwr":{"reg":40014}
             }   
    }
  },
 items:{
    "p_zal3":[14,[2,"panel",
              {
                "fan" :{"emit":"edem/air/vents/zal3/fan"},
                "mode":{"emit":"edem/air/vents/zal3/mode"},
                "pwr" :{"emit":"edem/air/vents/zal3/pwr"},
                
                "sethum":{"emit":"edem/air/humzal3/set"},
                "hum"   :{"emit":"edem/air/humzal3/val","@S":null},
                
                "setvoc":{"emit":"edem/air/voczal3/set"},
                "voc"   :{"emit":"edem/air/voczal3/val"},
                
                "settemp"   :{"item":"tzal3/set"},
                "roomtemp"  :{"emit":"edem/fl2/term_bedr/1/val"},
                "ch_temp":{},
                "ch_hum":{},
                "ext_temp":{},
                "out_temp":{},
                "water_temp":{},
                "heat_pwr":{}
              }  
              ]]
}              

Также, по-умолчанию, контроллер выполняет какие-то действия, только если регистр Модбас устройства поменялся не в результате записи в него со стороны контроллера(такая логика сделана, чтобы избежать зацикливания нотификаций)

Например, если в регистре число 3 а мы записали в него 5 - никаких действий при опросе не произойдет. А вот если значение в регистре изменилось в результате каких-то внутренних процессов устройства (например, пользователь изменил значение температуры на панеле) - это значение будет обработано.

Данную фильтрацию можно отменить, если в настройке параметра добавить переменную @V типа, отличного от целого. Например так:

"fan" :{"emit":"edem/air/vents/zal3/fan","@V":null},

В этом случае, после того, как мы что-то записали в регистр, при следующем же опросе устройства, это будет обнаружено (если значение изменилось) и будут предприняты настроенные действия (например, значение будет отправлено по MQTT и отобразится в мобильном приложении Home Assistant)

И еще один фильтр: при попытке записать в регистр значение, не отличающееся от последнего полученного при опросе, такая попытка будет проигнорирована. Такое поведение отключить нельзя.

Запись в Modbus устройство

Параметры Модбас устройства можно записывать аналогично, со всеми остальными items контроллера - с использованием MQTT, прямым обращением из других items контроллера, через http API

Рассмотрим на примере вентустановки:

Скорость можно поменять, обращаясь к «суб-топику» fanspeed vent/fanspeed/set (для прямого обращения по api или как к item-у) Для обращения через MQTT топик будет выглядеть как myhome/devicename/vent/fanspeed/set

Внимание, для названий субтопиков следует избегать стандартных имен суффиксов (cmd,set,hsv,rgb,fan,mode,hue,sat,temp,val,del,raw)

Параметры fanmin и fanmax доступны только на запись (контроллер не будет отслеживать изменение их значений)

также, есть возможность «прикрепить» параметры к стандартным суффиксам item-а (set,cmd,fan и пр), указав числовой параметр id, соответствующий данному стандартному суффиксу в описании этого параметра.

Перечень суффиксов:

CMD  1
SET  2
HSV  5
RGB  6
FAN  7
MODE 8
HUE  9
SAT  10
TEMP 11
VAL  12
DELAYED 13
RAW 14 

в примере ниже, это значит, что альтернативный описанному метод поменять скорость: vent/fan

А при записи в vent/cmd это значение установится как в регистр 41 (параметр on) так и в регистр 43 (параметр pmode) так как у них указан одинаковый id=1, соответствующий суффиксу /cmd

"modbus":
  {
    "airset":{
              "baud":9600,
              "serial":"8E1",
              "poll":{"regs":[[0,60],1008],"delay":2000},
              "par":{ 
                            "rtemp":{"reg":5,"type":"100", "mode":"r"},
                            
                            "fanmin":{"reg":50,"type":"u8l"},
                            "fanmax":{"reg":51,"type":"u8l"},
                            
                            "on":{"reg":41,"type":"u8l","id":1},
                            "fanspeed":{"reg":42,"type":"u8l","id":7},
                            "pmode":{"reg":43,"type":"u8l","id":1,"map":{}},
                            "tset":{"reg":44,"type":"u8l","id":2},
                            "numspeed":{"reg":60,"type":"u8l"},
                            "fault":{"reg":1008}
              }
              }
  },

  
  "items": {
  
  "vent":[14,[247,"airset",
    
    {
      "tset":{"emit":"edem/s_out/vent/tset/set","@V":null},
      "pmode":{"emit":"edem/s_out/vent/pmode/set","@V":null},
      "fanspeed":{"emit":"edem/s_out/vent/fanspeed/set","@V":null},
      "on":{"emit":"edem/s_out/vent/on/set","@V":null},
      
      "rtemp":{"emit":"edem/s_out/vent/rtemp"},
      
      "fanmin":{},
      "fanmax":{}

    }
    ]],  
  
  }
  

Mapping значений и команд контроллера в регистры Modbus

Рассмотрим на примере вентустановки Допустим, регистр 41 отвечает за включение установки. Соответственно, в него надо записать «1» для всех рабочих режимов:

  • AUTO
  • ON
  • HEAT
  • FAN_ONLY

Для команды OFF записываем 0

Это реализуется строкой

"on":{"reg":41,"type":"u8l","id":1,"map":{"cmd":[["OFF",0],["ON",1],["AUTO",1],["HEAT",1],["FAN_ONLY",1]]}}

наличие «id»=1 позволяет не только напрямую управлять данным регистром при помощи именованного параметра «on» (топика air/on/set) но и привязать его к командному суффиксу канала

Соответственно, доступно управление по командному топику air/cmd

В нашей вентустановке за переключение режима работы (нагрев-вентиляция-авто) отвечает отдельный регистр 43

настроим отображение режима работы на требуемые значения данного регистра и, также, привяжем это отображение к командному топику («id»:1)

"pmode":{"reg":43,"type":"u8l","id":1,"map":{"cmd":[["AUTO",3],["HEAT",2],["FAN_ONLY",1]]}},

теперь при переключении режимов в регистр 43 будет записываться 3 для Авторежима, 2 - для режима нагрева, 1 - для режима вентиляции

Еще лайфхак:

"humpwr":{"reg":39998,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null}},

В примере выше, в значения регистра будет маппироваться только команда, поступающая на humpwr. Команда ON в 1, команда OFF в 0

первый null перед массивом соответствия команда → значение по умолчанию, которое будет использоваться если не удастся подобрать команду. (null тут можно не указывать) Если не подобрали - пытаемся преобразовать по значению

Если не использовать «val»:null - то значения, отправляемые в humpwr/set будут передаваться в регистр без преобразований. Использование null обеспечивает игнорирование значений (не команд)

(описание не завершено)

"modbus":
  {
    "airset":{
              "baud":9600,
              "serial":"8E1",
              "poll":{"regs":[[0,60],1008],"delay":2000},
              "par":{ 
      
                            "on":{"reg":41,"type":"u8l","id":1,"map":{"cmd":[["OFF",0],["ON",1],["AUTO",1],["HEAT",1],["FAN_ONLY",1]]}},
                            "fanspeed":{"reg":42,"type":"u8l","id":7,"map":{"cmd":"fan"}},
                            "offbyfan":{"reg":41,"type":"u8l","id":7,"map":{"cmd":[1,["OFF",0]]}},
                            "pmode":{"reg":43,"type":"u8l","id":1,"map":{"cmd":[["AUTO",3],["HEAT",2],["FAN_ONLY",1]]}},
                            "tset":{"reg":44,"type":"u8l","id":2},

                            "di":{"reg":47,"type":"u8l"},
                            "dp":{"reg":48,"type":"u8l"},
                            "dt":{"reg":49,"type":"u8l"},

                            "fault":{"reg":1008}
              }
              }
  }
},
"items":
{
  "vent":[14,[247,"airset",
    
    {
      "tset":{"emit":"edem/s_out/vent/set","@V":null},
      "pmode":{"emit":"edem/s_out/vent/cmd","@V":null},
      "fanspeed":{"emit":"edem/s_out/vent/fan","@V":null},
      "on":{"emit":"edem/s_out/vent/oncmd","@V":null},
      
      "ruheat":{"emit":"edem/s_out/vent/ruheat"},
      "ruslow":{"emit":"edem/s_out/vent/rupump"},
      "ramode":{"emit":"edem/s_out/vent/ramode"},
      "rfanspd":{"emit":"edem/s_out/vent/rfanspd"},
      "rfanlvl":{"emit":"edem/s_out/vent/rfanlvl"},
      "rpumpon":{"emit":"edem/s_out/vent/rpumpon"},
      "rtemp":{"emit":"edem/s_out/vent/rtemp"},
      "rtempset":{"emit":"edem/s_out/vent/rtempset"},
      "fault":{"emit":"edem/s_out/vent/fault"},
      
      "tautoheat":{},
      "tautocool":{},
      "di":{},
      "dp":{},
      "dt":{},
      "fanmin":{},
      "fanmax":{},
      "tmreheat":{},
      "tairfreeze":{},
      "twaterstart":{},
      "twatershut":{},
      "twateridle":{},
      "fanauto":{"emit":"edem/s_out/vent/fanauto/set","@V":null},
      "numspeed":{},
      "offbyfan":{}
    }
    ]]
}      
настройка_modbus.txt · Последнее изменение: 2024/05/21 23:47 — Admin