From b7331beab4ebf23f548d214400e08909467060d6 Mon Sep 17 00:00:00 2001 From: Andrey Klimov Date: Sun, 6 May 2018 17:45:29 +0300 Subject: [PATCH] Modbus dimmer channel generalization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example: "items": { "modbusdev":[4,[96,0,0,255]] } Note: this config example available at URL http://lazyhome.ru/de-ad-be-ef-fe-07.config.json - so just set mac address of device by command “mac de:ad:be:ef:fe:07” for test. Item notation: 4 - Modbus dimmer item type Param1: = 96 - Decimal address of modbus device Param2: = 0 - Modbus register to write (and read while polling) Param3: = 0 - mask (optional. Default value “-1” - see below for explanations) Param4:= 255 - Maximum Value for scaling MQTT input value to register value (Optional. Default MaxValue 0x3f. It is equivalent of “100" on input. If value == 0 - no scaling) Mask: if mask == 1 - Value comes to most significant byte of 16 bit register word, another byte = 0xff if mask == 0 - Value comes to least significant byte of 16 bit register word, another byte = 0xff any other mask - put Value as 16 bit word without any modification if mask == -1 (or parameter omitted) - no register polling --- lighthub/item.cpp | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/lighthub/item.cpp b/lighthub/item.cpp index a4d3008..5d552d7 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -121,8 +121,10 @@ void Item::setCmd(uint8_t cmd) { int Item::getArg(short n) //Return arg int or first array element if Arg is array { if (!itemArg) return -1; - if (itemArg->type == aJson_Int) return itemArg->valueint; - else if (itemArg->type == aJson_Array) return aJson.getArrayItem(itemArg, n)->valueint; + if (itemArg->type == aJson_Int){ + if (!n) return itemArg->valueint; else return -1; + } + if ((itemArg->type == aJson_Array) && ( n < aJson.getArraySize(itemArg))) return aJson.getArrayItem(itemArg, n)->valueint; else return -2; } @@ -456,13 +458,16 @@ int Item::Ctrl(short cmd, short n, int *Parameters, boolean send) { #ifdef _modbus case CH_MODBUS: { - - if ((itemArg->type == aJson_Array) && (aJson.getArraySize(itemArg) == 3)) { + short numpar=0; + if ((itemArg->type == aJson_Array) && ((numpar = aJson.getArraySize(itemArg)) >= 2)) { int _addr = aJson.getArrayItem(itemArg, 0)->valueint; int _reg = aJson.getArrayItem(itemArg, 1)->valueint; - int _mask = aJson.getArrayItem(itemArg, 2)->valueint; - - modbusDimmerSet(_addr, _reg, _mask, map(Par[0], 0, 100, 0, 0x3f)); + int _mask = -1; + if (numpar >= 3) _mask = aJson.getArrayItem(itemArg, 2)->valueint; + int _maxval = 0x3f; + if (numpar >=4) _maxval = aJson.getArrayItem(itemArg, 3)->valueint; + if (_maxval) modbusDimmerSet(_addr, _reg, _mask, map(Par[0], 0, 100, 0, _maxval)); + else modbusDimmerSet(_addr, _reg, _mask, Par[0]); } break; } @@ -833,12 +838,14 @@ int Item::modbusDimmerSet(int addr, uint16_t _reg, int _mask, uint16_t value) { node.begin(addr, modbusSerial); - if (_mask) { + switch (_mask) { + case 1: value <<= 8; value |= (0xff); - } else { + break; + case 0: value &= 0xff; - value |= (0xff00); + value |= (0xff00); } Serial.print(addr); @@ -1022,10 +1029,17 @@ int Item::checkModbusDimmer() { int Item::checkModbusDimmer(int data) { short mask = getArg(2); + if (mask < 0) return 0; + + short maxVal = getArg(3); + if (maxVal<=0) maxVal = 0x3f; + int d = data; - if (mask) d >>= 8; - d &= 0xff; - d = map(d, 0, 0x3f, 0, 100); + if (mask == 1) d >>= 8; + if (mask == 0 || mask == 1) d &= 0xff; + + if (maxVal) d = map(d, 0, maxVal, 0, 100); + int cmd = getCmd(); //Serial.println(d); if (getVal() != d || d && cmd == CMD_OFF || d && cmd == CMD_HALT) //volume changed or turned on manualy