diff --git a/lighthub/colorchannel.cpp b/lighthub/colorchannel.cpp index e5170d8..312f685 100644 --- a/lighthub/colorchannel.cpp +++ b/lighthub/colorchannel.cpp @@ -6,14 +6,23 @@ #include "item.h" #include "main.h" +//colorChannel::colorChannel(Item * _item) -int out_dmx::Ctrl(itemCmd cmd, char* subItem) + +short colorChannel::getChannelAddr(short n) +{ + if (!n) return iaddr; + if (n+1>numArgs) return iaddr+n; + return item->getArg(n); +} + +int colorChannel::Ctrl(itemCmd cmd, char* subItem) { int chActive = item->isActive(); bool toExecute = (chActive>0); // execute if channel is active now int suffixCode = cmd.getSuffix(); -itemCmd st(ST_HSV); +itemCmd st(ST_HSV,CMD_VOID); if (!suffixCode) toExecute=true; //forced execute if no suffix if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command recognized , but w/o correct cmd suffix - threat it as command @@ -67,7 +76,7 @@ case S_CMD: debugSerial<SendStatus(SEND_COMMAND | SEND_PARAMETERS ); return 1; diff --git a/lighthub/colorchannel.h b/lighthub/colorchannel.h index 0cf61ce..42a19b1 100644 --- a/lighthub/colorchannel.h +++ b/lighthub/colorchannel.h @@ -9,9 +9,15 @@ class colorChannel : public abstractOut { public: - colorChannel(Item * _item):abstractOut(_item){}; + colorChannel(Item * _item):abstractOut(_item) { + iaddr = item->getArg(); //Once retrieve and store base address + if (iaddr<0) iaddr=-iaddr; + numArgs = item->getArgCount(); // and how many addresses is configured + }; int Ctrl(itemCmd cmd, char* subItem=NULL) override; virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true ) =0; - + short getChannelAddr(short n =0); protected: + short iaddr; + short numArgs; }; diff --git a/lighthub/inputs.cpp b/lighthub/inputs.cpp index be006d9..cc43cd6 100644 --- a/lighthub/inputs.cpp +++ b/lighthub/inputs.cpp @@ -23,6 +23,7 @@ e-mail anklimov@gmail.com #include "utils.h" #include #include "main.h" +#include "itemCmd.h"" #ifndef DHT_DISABLE #if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32) @@ -1012,11 +1013,11 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri Item it(item->valuestring); if (it.isValid()) { if (newValue) { //send set command - if (!scmd || scmd->type != aJson_String) it.Ctrl(CMD_ON, 0, NULL); + if (!scmd || scmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_ON)); else if (strlen(scmd->valuestring)) it.Ctrl(scmd->valuestring); } else { //send reset command - if (!rcmd || rcmd->type != aJson_String) it.Ctrl(CMD_OFF, 0, NULL); + if (!rcmd || rcmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_OFF)); else if (strlen(rcmd->valuestring)) it.Ctrl(rcmd->valuestring); } @@ -1049,10 +1050,11 @@ void Input::onAnalogChanged(float newValue) { } if (item && item->type == aJson_String) { - int intNewValue = round(newValue); + //int intNewValue = round(newValue); Item it(item->valuestring); if (it.isValid()) { - it.Ctrl(0, 1, &intNewValue, true); + //it.Ctrl(0, 1, &intNewValue, true); + it.Ctrl(itemCmd(newValue)); } } } diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 90a33f6..4496aef 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -25,6 +25,7 @@ e-mail anklimov@gmail.com #include "textconst.h" #include "main.h" #include "bright.h" +#include "itemCmd.h" #ifdef _dmxout #include "dmx.h" @@ -134,7 +135,7 @@ void Item::Parse() { case CH_RGB: case CH_DIMMER: driver = new out_dmx (this); - // debugSerial<type == aJson_Int) return 1; + if (itemArg->type == aJson_Array) return aJson.getArraySize(itemArg); + else return 0; +} /* int Item::getVal(short n) //Return Val from Value array { if (!itemVal) return -1; @@ -403,31 +411,6 @@ boolean Item::isValid() { return (itemArr && (itemArr->type == aJson_Array)); } - - -/* -void Item::copyPar (aJsonObject *itemV) -{ int n=aJson.getArraySize(itemV); - //for (int i=aJson.getArraySize(itemVal);ivalueint); -} -*/ - - -#if defined(ARDUINO_ARCH_ESP32) -void analogWrite(int pin, int val) -{ - //TBD -} -#endif - - -/* -boolean Item::getEnableCMD(int delta) { - return ((millis() - lastctrl > (unsigned long) delta));// || ((void *)itemArr != (void *) lastobj)); -} -*/ - // If retrieving subitem code ok - return it // parameter will point on the rest truncated part of subitem // or pointer to NULL of whole string converted to subitem code @@ -460,16 +443,16 @@ else return suffixCode; } -#define MAXCTRLPAR 3 +//#define MAXCTRLPAR 3 // myhome/dev/item/subItem -int Item::Ctrl(char * payload, char * subItem){ - if (!payload) return 0; - +int Item::Ctrl(char * payload, char * subItem) +{ +if (!payload) return 0; +itemCmd st(ST_VOID,CMD_VOID); int suffixCode = 0; -//int setCommand = CMD_SET; //default SET behavior now - not turn on channels -int setCommand = 0; + if ((!subItem || !strlen(subItem)) && strlen(defaultSubItem)) subItem = defaultSubItem; /// possible problem here with truncated default @@ -479,57 +462,66 @@ if (subItem && strlen(subItem)) if (!suffixCode && defaultSuffixCode) suffixCode = defaultSuffixCode; +st.setSuffix(suffixCode); + int i=0; while (payload[i]) {payload[i]=toupper(payload[i]);i++;}; int cmd = txt2cmd(payload); debugSerial<0); - itemCmd st; + itemCmd st(ST_VOID,CMD_VOID); st.loadItem(this); //Restore previous channel state to "st" //threating Toggle, Restore, XOFF special conditional commands/ convert to ON, OFF @@ -724,7 +716,7 @@ if (driver) //New style modular code } return res; } -// Legacy monolite core code + //================== switch (itemType) { case CH_GROUP://Group @@ -743,78 +735,57 @@ switch (itemType) { configLocked--; } //if } //case - } //switch -//========= -/* - bool toExecute = (chActive>0); - if (cmd>0 && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it +// rest of Legacy monolite core code (to be refactored ) + + case CH_RELAY: + { + short iaddr=getArg(); + short icmd =cmd.getCmd(); + + if (iaddr) + { + int k; + short inverse = 0; + + if (iaddr < 0) { + iaddr = -iaddr; + inverse = 1; + } + pinMode(iaddr, OUTPUT); + + if (inverse) + digitalWrite(iaddr, k = ((icmd == CMD_ON || icmd == CMD_XON) ? LOW : HIGH)); + else + digitalWrite(iaddr, k = ((icmd == CMD_ON || icmd == CMD_XON) ? HIGH : LOW)); + debugSerial<setVal(st=Parameters[0]); //Store - if (!suffixCode) - { - if (chActive>0 && !st) item->setCmd(CMD_OFF); - if (chActive==0 && st) item->setCmd(CMD_ON); - item->SendStatus(SEND_COMMAND | SEND_PARAMETERS | SEND_DEFFERED); - if (item->getExt()) item->setExt(millis()+maxOnTime); //Extend motor time - } - else item->SendStatus(SEND_PARAMETERS | SEND_DEFFERED); - - return 1; - //break; - - case S_CMD: - item->setCmd(cmd); - switch (cmd) - { - case CMD_ON: - //retrive stored values - st = item->getVal(); - - - if (st && (stsetVal(st); - - if (st) //Stored smthng - { - item->SendStatus(SEND_COMMAND | SEND_PARAMETERS); - debugSerial<setVal(st); - item->SendStatus(SEND_COMMAND | SEND_PARAMETERS ); - } - if (item->getExt()) item->setExt(millis()+maxOnTime); //Extend motor time - return 1; + #endif + } //switch - case CMD_OFF: - item->SendStatus(SEND_COMMAND); - if (item->getExt()) item->setExt(millis()+maxOnTime); //Extend motor time - return 1; - - } //switch cmd - - break; - } //switch suffix - debugSerial<0)) { - debugSerial<Ctrl(cmd, n, Parameters, send, suffixCode, subItem); - break; -*/ + //// + //case CMD_SET: + //res = driver->Ctrl(cmd, n, Parameters, send, suffixCode, subItem); + //break; + // default: res = driver->Ctrl(_itemCmd, subItem); if (cmd) setCmd(cmd); @@ -1500,7 +1449,7 @@ return 1; } - +*/ @@ -1860,7 +1809,8 @@ int Item::checkFM() { int val = 100; Item item(airGateObj->valuestring); if (item.isValid()) - item.Ctrl(0, 1, &val); + // item.Ctrl(0, 1, &val); + item.Ctrl(itemCmd(ST_PERCENTS,CMD_VOID).Percents(val)); } } } else @@ -1871,7 +1821,7 @@ int Item::checkFM() { result = node.readHoldingRegisters(2111 - 1, 1); if (result == node.ku8MBSuccess) aJson.addNumberToObject(out, "flt", (int) node.getResponseBuffer(0)); modbusBusy=0; - if (isActive()>0) Ctrl(CMD_OFF); //Shut down /// + if (isActive()>0) Off(); //Shut down /// modbusBusy=1; } else aJson.addNumberToObject(out, "flt", 0); @@ -1900,7 +1850,7 @@ int Item::checkFM() { if (ftemp > FM_OVERHEAT_CELSIUS && set) { if (mqttClient.connected() && !ethernetIdleCount) mqttClient.publish("/alarm/ovrht", itemArr->name); - Ctrl(CMD_OFF); //Shut down + Off(); //Shut down } } else debugSerial << F("Modbus polling error=") << _HEX(result); diff --git a/lighthub/item.h b/lighthub/item.h index 98f3f85..3ecb5d9 100644 --- a/lighthub/item.h +++ b/lighthub/item.h @@ -102,11 +102,12 @@ class Item boolean isValid (); boolean Setup(); void Stop(); - int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL); + //int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL); int Ctrl(itemCmd cmd, char* subItem=NULL); int Ctrl(char * payload, char * subItem=NULL); int getArg(short n=0); + short getArgCount(); //int getVal(short n); //From VAL array. Negative if no array long int getVal(); //From int val OR array uint8_t getSubtype(); @@ -125,9 +126,9 @@ class Item int SendStatus(int sendFlags); int isActive(); int getChanType(); - inline int On (){return Ctrl(CMD_ON);}; - inline int Off(){return Ctrl(CMD_OFF);}; - inline int Toggle(){return Ctrl(CMD_TOGGLE);}; + inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));}; + inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));}; + inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));}; protected: //short cmd2changeActivity(int lastActivity, short defaultCmd = CMD_SET); diff --git a/lighthub/itemCmd.cpp b/lighthub/itemCmd.cpp index 9770aae..b26ae93 100644 --- a/lighthub/itemCmd.cpp +++ b/lighthub/itemCmd.cpp @@ -43,6 +43,13 @@ itemCmd::itemCmd(uint8_t _type, uint8_t _code) cmd.cmdCode=_code; } +itemCmd::itemCmd(float val) +{ + cmd.cmdCode=0; + cmd.itemArgType=ST_FLOAT; + param.asfloat=val; +} + itemCmd itemCmd::setDefault() { switch (cmd.itemArgType){ @@ -333,34 +340,36 @@ long int itemCmd::getInt() } -short itemCmd::getPercents() +short itemCmd::getPercents(bool inverse) { switch (cmd.itemArgType) { case ST_PERCENTS: case ST_HSV: - return param.v; + if (inverse) return 100-param.v; else return param.v; case ST_PERCENTS255: case ST_HSV255: - return map(param.v,0,255,0,100); + if (inverse) return map(param.v,0,255,100,0); + else return map(param.v,0,255,0,100); default: return 0; } } -short itemCmd::getPercents255() +short itemCmd::getPercents255(bool inverse) { switch (cmd.itemArgType) { case ST_PERCENTS: case ST_HSV: - return map(param.v,0,100,0,255); + if (inverse) return map(param.v,0,100,255,0); + else return map(param.v,0,100,0,255); case ST_PERCENTS255: case ST_HSV255: - return param.v; + if (inverse) return 255-param.v; else return param.v; default: return 0; @@ -454,6 +463,27 @@ itemCmd itemCmd::HSV(uint16_t h, uint8_t s, uint8_t v) return *this; } +itemCmd itemCmd::RGB(uint8_t r, uint8_t g, uint8_t b) +{ + cmd.itemArgType=ST_RGB; + param.r=r; + param.g=g; + param.b=b; + + return *this; +} + +itemCmd itemCmd::RGBW(uint8_t r, uint8_t g, uint8_t b, uint8_t w) +{ + cmd.itemArgType=ST_RGBW; + param.r=r; + param.g=g; + param.b=b; + param.w=w; + + return *this; +} + itemCmd itemCmd::Int(uint32_t i) { cmd.itemArgType=ST_UINT32; diff --git a/lighthub/itemCmd.h b/lighthub/itemCmd.h index c872de5..7b16b8c 100644 --- a/lighthub/itemCmd.h +++ b/lighthub/itemCmd.h @@ -169,6 +169,7 @@ public: itemArgStore param; itemCmd(uint8_t _type=ST_VOID, uint8_t _code=CMD_VOID); + itemCmd(float val); itemCmd assignFrom(itemCmd from); bool loadItem(Item * item, bool includeCommand=false ); @@ -178,6 +179,8 @@ public: itemCmd Int(uint32_t i); itemCmd Cmd(uint8_t i); itemCmd HSV(uint16_t h, uint8_t s, uint8_t v); + itemCmd RGB(uint8_t r, uint8_t g, uint8_t b); + itemCmd RGBW(uint8_t r, uint8_t g, uint8_t b, uint8_t w); itemCmd setH(uint16_t); itemCmd setS(uint8_t); itemCmd setArgType(uint8_t); @@ -192,8 +195,8 @@ public: itemCmd incrementS(int16_t); long int getInt(); - short getPercents(); - short getPercents255(); + short getPercents(bool inverse=false); + short getPercents255(bool inverse=false); uint8_t getCmd(); uint8_t getArgType(); uint8_t getCmdParam(); diff --git a/lighthub/modules/out_dmx.cpp b/lighthub/modules/out_dmx.cpp index abd236c..97015c2 100644 --- a/lighthub/modules/out_dmx.cpp +++ b/lighthub/modules/out_dmx.cpp @@ -45,27 +45,44 @@ return 0; int out_dmx::getChanType() { - if (item) return item->itemType; + if (item) + { + switch (numArgs) + { + case 3: + return CH_RGB; + case 4: + return CH_RGBW; + default: + return item->itemType; + } return 0; + } } -int out_dmx::PixelCtrl(itemCmd cmd) +int out_dmx::PixelCtrl(itemCmd cmd, char* subItem, bool show) +//int out_dmx::PixelCtrl(itemCmd cmd) { -if (!item) return 0; -int iaddr = item->getArg(0); -itemCmd st(ST_RGB); +if (!item || !show) return 0; +short cType=getChanType(); + +if (cType==CH_DIMMER) //Single channel + { + DmxWrite(iaddr, cmd.getPercents255()); + return 1; + } + +itemCmd st(ST_RGB,CMD_VOID); st.assignFrom(cmd); - switch (getChanType()) - { case CH_DIMMER: - DmxWrite(iaddr + 3, cmd.getPercents255()); - break; + switch (cType) + { case CH_RGBW: - DmxWrite(iaddr + 3, st.param.w); + DmxWrite(getChannelAddr(3), st.param.w); case CH_RGB: DmxWrite(iaddr, st.param.r); - DmxWrite(iaddr + 1, st.param.g); - DmxWrite(iaddr + 2, st.param.b); + DmxWrite(getChannelAddr(1), st.param.g); + DmxWrite(getChannelAddr(2), st.param.b); break; default: ; } diff --git a/lighthub/modules/out_dmx.h b/lighthub/modules/out_dmx.h index 85e76d7..d582f05 100644 --- a/lighthub/modules/out_dmx.h +++ b/lighthub/modules/out_dmx.h @@ -5,19 +5,21 @@ #include #include +#include "colorchannel.h" -class out_dmx : public abstractOut { +class out_dmx : public colorChannel { public: - out_dmx(Item * _item):abstractOut(_item){}; + out_dmx(Item * _item):colorChannel(_item){}; int Setup() override; int Poll(short cause) override; int Stop() override; int Status() override; int isActive() override; int getChanType() override; - int Ctrl(itemCmd cmd, char* subItem=NULL) override; - int PixelCtrl(itemCmd cmd); +// int Ctrl(itemCmd cmd, char* subItem=NULL) override; +// int PixelCtrl(itemCmd cmd) override; + virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true ) override; protected: }; diff --git a/lighthub/modules/out_modbus.cpp b/lighthub/modules/out_modbus.cpp index 9c6e0de..30ff83f 100644 --- a/lighthub/modules/out_modbus.cpp +++ b/lighthub/modules/out_modbus.cpp @@ -342,7 +342,7 @@ int out_Modbus::Ctrl(itemCmd cmd, char* subItem) { int chActive = item->isActive(); bool toExecute = (chActive>0); -itemCmd st(ST_UINT32); +itemCmd st(ST_UINT32,CMD_VOID); int suffixCode = cmd.getSuffix(); if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it diff --git a/lighthub/modules/out_motor.cpp b/lighthub/modules/out_motor.cpp index 7cff267..79b1ea8 100644 --- a/lighthub/modules/out_motor.cpp +++ b/lighthub/modules/out_motor.cpp @@ -216,7 +216,7 @@ int out_Motor::Ctrl(itemCmd cmd, char* subItem) int chActive = item->isActive(); bool toExecute = (chActive>0); int suffixCode = cmd.getSuffix(); -itemCmd st(ST_PERCENTS); +itemCmd st(ST_PERCENTS,CMD_VOID); if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it item->setFlag(ACTION_NEEDED); diff --git a/lighthub/modules/out_pwm.cpp b/lighthub/modules/out_pwm.cpp index 96cbb3f..de4c9ea 100644 --- a/lighthub/modules/out_pwm.cpp +++ b/lighthub/modules/out_pwm.cpp @@ -9,9 +9,50 @@ static int driverStatus = CST_UNKNOWN; +#if defined(ARDUINO_ARCH_ESP32) +void analogWrite(int pin, int val) +{ + //TBD +} +#endif + int out_pwm::Setup() { debugSerial< PWM frequency is 31000 Hz + //prescaler = 2 ---> PWM frequency is 4000 Hz + //prescaler = 3 ---> PWM frequency is 490 Hz (default value) + //prescaler = 4 ---> PWM frequency is 120 Hz + //prescaler = 5 ---> PWM frequency is 30 Hz + //prescaler = 6 ---> PWM frequency is <20 Hz +#if defined(__AVR_ATmega2560__) + int tval = 7; // this is 111 in binary and is used as an eraser + TCCR4B &= ~tval; // this operation (AND plus NOT), set the three bits in TCCR2B to 0 + TCCR3B &= ~tval; + tval = 2; + TCCR4B |= tval; + TCCR3B |= tval; +#endif + driverStatus = CST_INITIALIZED; return 1; } @@ -19,6 +60,19 @@ return 1; int out_pwm::Stop() { debugSerial<itemType; + if (item) + { + switch (numArgs) + { + case 3: + return CH_RGB; + case 4: + return CH_RGBW; + default: + return item->itemType; + } + } return 0; } -int out_pwm::PixelCtrl(itemCmd cmd) +int out_pwm::PixelCtrl(itemCmd cmd, char* subItem, bool show) { -if (!item) return 0; -int iaddr = item->getArg(0); -itemCmd st(ST_RGB); +if (!item || !iaddr || !show) return 0; + +bool inverse = (item->getArg()<0); +short cType = getChanType(); + +if (cType=CH_PWM) + { short k; + analogWrite(iaddr, k=cmd.getPercents255(inverse)); + debugSerial< #include "colorchannel.h" -class out_dmx : public colorChannel { +class out_pwm : public colorChannel { public: out_pwm(Item * _item):colorChannel(_item){}; @@ -18,9 +18,9 @@ public: int isActive() override; int getChanType() override; //int Ctrl(itemCmd cmd, char* subItem=NULL) override; - //int PixelCtrl(itemCmd cmd) override; int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true ) override; protected: + short numChannels; }; #endif diff --git a/lighthub/modules/out_spiled.cpp b/lighthub/modules/out_spiled.cpp index e6eb44d..1753d87 100644 --- a/lighthub/modules/out_spiled.cpp +++ b/lighthub/modules/out_spiled.cpp @@ -109,7 +109,7 @@ int out_SPILed::getChanType() return CH_RGBW; } -int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show ); +int out_SPILed::PixelCtrl(itemCmd cmd, char* subItem, bool show ) //int out_SPILed::PixelCtrl(itemCmd cmd, int from, int to, bool show) { @@ -123,7 +123,7 @@ int from=0, to=numLeds-1; //All LEDs on the strip by default debugSerial<