Skip to content

Commit

Permalink
Modbus mapping, AC swing, vent, pwm relay fix
Browse files Browse the repository at this point in the history
  • Loading branch information
anklimov committed Oct 2, 2022
1 parent a17ea0b commit 891701c
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 70 deletions.
13 changes: 9 additions & 4 deletions lighthub/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1122,12 +1122,14 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
toExecute=true;
break;
}

if (chActive)
{
debugSerial<<F("ON:Already Active\n");
setCmd(CMD_ON);
SendStatus(SEND_COMMAND | SEND_DEFFERED);
return 3;
}

//newly added. For climate commands need to restore previous temperature
case CMD_AUTO:
case CMD_COOL:
Expand Down Expand Up @@ -1433,9 +1435,10 @@ int Item::SendStatus(int sendFlags) {

int Item::SendStatusImmediate(itemCmd st, int sendFlags, char * subItem) {
{
char addrstr[48];
char addrstr[64];
char valstr[20] = "";
char cmdstr[9] = "";
//debugSerial<<"SSI "<<subItem<<endl;
st.debugOut();
if (sendFlags & SEND_COMMAND)
{
Expand Down Expand Up @@ -1469,9 +1472,10 @@ int Item::SendStatus(int sendFlags) {
// myhome/s_out/item - mix: value and command


if (mqttClient.connected() && !ethernetIdleCount && !subItem)
if (mqttClient.connected() && !ethernetIdleCount)
{

if (!subItem)
{
setTopic(addrstr,sizeof(addrstr),T_OUT);
strncat(addrstr, itemArr->name, sizeof(addrstr)-1);

Expand All @@ -1490,6 +1494,7 @@ int Item::SendStatus(int sendFlags) {
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;

}
} //!subItem
}
else
{
Expand Down
10 changes: 4 additions & 6 deletions lighthub/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,19 @@ e-mail anklimov@gmail.com
#include "itemCmd.h"

#define S_NOTFOUND 0
//#define S_SETnCMD 0
#define S_CMD 1
#define S_SET 2
//#define S_ESET 4
#define S_VAL 3
#define S_DELAYED 4
#define S_HSV 5
#define S_RGB 6
#define S_FAN 7
#define S_MODE 8
#define S_HUE 9
#define S_SAT 10
#define S_TEMP 11
#define S_VAL 12
#define S_DELAYED 13
#define S_RAW 14
#define S_ADDITIONAL 14
#define S_RAW 12
#define S_ADDITIONAL 12

#define CH_DIMMER 0 //DMX 1-4 ch
#define CH_RGBW 1 //DMX 4 ch
Expand Down
157 changes: 141 additions & 16 deletions lighthub/itemCmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1128,53 +1128,178 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
return false;
}

int replaceCmdToInt(aJsonObject* verb)
{
if (verb && verb->type == aJson_String)
{
int cmd = txt2cmd(verb->valuestring);
if (cmd>0)
{
free(verb->valuestring);
verb->valueint=cmd;
verb->type=aJson_Int;
return verb->valueint;
}
} else if (verb && verb->type == aJson_Int) return verb->valueint;
return 0;
}

// Mapping from unified itemCmd object to some specific device-depended value
itemCmd itemCmd::doMapping(aJsonObject *mappingData)
{
if (isCommand())
if (!mappingData) return *this;
aJsonObject *cmdMapping = aJson.getObjectItem(mappingData, "cmd");
aJsonObject *matchedCmd = NULL;

if (isCommand() && cmdMapping)
switch (cmdMapping->type)
{
case aJson_Array:
{
debugSerial<<"Array mapping"<<endl;
aJsonObject *i = cmdMapping->child;
//if first array element is not array - this is default mapping value
if (i && i->type==aJson_Int)
{
matchedCmd = i;
i=i->next;
}

while (i)
{
if (i->type == aJson_Array && aJson.getArraySize(i) == 2)
{
int cmdFrom = replaceCmdToInt(aJson.getArrayItem(i,0));
aJsonObject *to = aJson.getArrayItem(i,1);
if (getCmd()==cmdFrom && to->type == aJson_Int)
{
matchedCmd=to;
break;
}

}
i=i->next;
}
}
case aJson_String:
if (strcmp(cmdMapping->valuestring,"fan")==0)
switch (getCmd())
{
/*
case CMD_AUTO:
case CMD_ON:
return itemCmd().Int((uint32_t)3);
case CMD_OFF:
return itemCmd().Int((uint32_t)0);
case CMD_FAN:
return itemCmd().Int((uint32_t)1);
case CMD_HEAT:
return itemCmd().Int((uint32_t)2);

*/
case CMD_OFF:
return itemCmd().Int((uint32_t)0);
case CMD_LOW:
return itemCmd().Int((uint32_t)10);
return itemCmd().Int((uint32_t)20);
case CMD_MED:
return itemCmd().Int((uint32_t)128);
case CMD_HIGH:
return itemCmd().Int((uint32_t)255);

default:
return itemCmd().Int((uint32_t)0);
return *this;
}

} //switch

if (matchedCmd) return itemCmd().Int((uint32_t)matchedCmd->valueint);

aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4)
{
if (getInt()<aJson.getArrayItem(valMapping,0)->valueint) return itemCmd().Int((uint32_t) 0);
return itemCmd().Int((uint32_t)
map(getInt(),
aJson.getArrayItem(valMapping,0)->valueint,aJson.getArrayItem(valMapping,1)->valueint,
aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint));
}
return *this;
}
itemCmd itemCmd::doReverseMapping (aJsonObject *mappingData)

// Mapping from some device specific value back to unified itemcmd
itemCmd itemCmd::doReverseMapping (aJsonObject *mappingData)
{
return *this;
}
if (!mappingData) return *this;
aJsonObject *cmdMapping = aJson.getObjectItem(mappingData, "cmd");
aJsonObject *matchedCmd = NULL;

if (cmdMapping)

int itemCmd::doMappingCmd(aJsonObject *mappingData)
{
return 0;
switch (cmdMapping->type )
{
case aJson_Array:
{
aJsonObject *i = cmdMapping->child;
//if first array element is not array - this is default mapping value
if (i && i->type==aJson_Int)
{
matchedCmd = i;
i=i->next;
}

}
int itemCmd::doReverseMappingCmd (aJsonObject *mappingData)
while (i)
{
if (i->type == aJson_Array && aJson.getArraySize(i) == 2)
{
aJsonObject *from =aJson.getArrayItem(i,0);
int cmdFrom = replaceCmdToInt(from);
aJsonObject *to = aJson.getArrayItem(i,1);
if (to->type == aJson_Int && getInt()==to->valueint)
{
matchedCmd=from;
break;
}

{
return 0;
}
i=i->next;
}
}
break;
case aJson_String:
{
if (strcmp(cmdMapping->valuestring,"fan")==0)
{
if (getInt())
switch (constrain(map(getInt(),0,255,1,3),1,3))
{
case 1:
return itemCmd().setSuffix(S_FAN).Cmd(CMD_LOW);
case 2:
return itemCmd().setSuffix(S_FAN).Cmd(CMD_MED);
case 3:
return itemCmd().setSuffix(S_FAN).Cmd(CMD_HIGH);
}
else return itemCmd().setSuffix(S_FAN).Cmd(CMD_OFF);
}
}
}//switch


if (matchedCmd) return itemCmd().Cmd(matchedCmd->valueint);

aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4)
{
int a = aJson.getArrayItem(valMapping,0)->valueint;
int b = aJson.getArrayItem(valMapping,1)->valueint;
int c = aJson.getArrayItem(valMapping,2)->valueint;
int d = aJson.getArrayItem(valMapping,3)->valueint;

if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
int diff = ((b-a)/(d-c))/2;
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
}
return *this;
}


char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100 )
{

Expand Down
10 changes: 4 additions & 6 deletions lighthub/itemCmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ typedef char cmdstr[9];
const cmdstr commands_P[] PROGMEM =
{
"","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE",
"HEAT","COOL","AUTO","FAN_ONLY","DRY","STOP","HIGH","MEDIUM","LOW",
"TRUE","FALSE","ENABLED","DISABLED","RGB","HSV"
"HEAT","COOL","AUTO","FAN_ONLY","DRY","STOP","HIGH","MEDIUM","LOW","ENABLE","DISABLE",
"TRUE","FALSE","RGB","HSV"
};
#define commandsNum sizeof(commands_P)/sizeof(cmdstr)

Expand All @@ -50,8 +50,8 @@ const cmdstr commands_P[] PROGMEM =
#define CMD_HIGH 0x10 /// AC/Vent fan level HIGH
#define CMD_MED 0x11 /// AC/Vent fan level MEDIUM
#define CMD_LOW 0x12 /// AC/Vent fan level LOW
#define CMD_ENABLED 0x13 /// Aliase for ON
#define CMD_DISABLED 0x14 /// Aliase for OFF
#define CMD_ENABLE 0x13 /// for PID regulator
#define CMD_DISABLE 0x14 /// for PID regulator
#define CMD_TRUE 0x15 /// Aliase for ON
#define CMD_FALSE 0x16 /// Aliase for OFF
#define CMD_RGB 0x17
Expand Down Expand Up @@ -222,8 +222,6 @@ class itemCmd

itemCmd doMapping(aJsonObject *mappingData);
itemCmd doReverseMapping (aJsonObject *mappingData);
int doMappingCmd(aJsonObject *mappingData);
int doReverseMappingCmd (aJsonObject *mappingData);
bool scale100();

};
Expand Down
16 changes: 3 additions & 13 deletions lighthub/modules/out_ac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,7 @@ const char LOCK_P[] PROGMEM = "lock";
const char QUIET_P[] PROGMEM = "queit";
const char SWING_P[] PROGMEM = "swing";
const char RAW_P[] PROGMEM = "raw";
//const char IDLE_P[] PROGMEM = "IDLE";
/*
extern const char HEAT_P[] PROGMEM;
extern const char COOL_P[] PROGMEM;
extern const char AUTO_P[] PROGMEM;
extern const char FAN_ONLY_P[] PROGMEM;
extern const char DRY_P[] PROGMEM;
extern const char HIGH_P[] PROGMEM;
extern const char MED_P[] PROGMEM;
extern const char LOW_P[] PROGMEM;
*/

void out_AC::InsertData(byte data[], size_t size){

char s_mode[10];
Expand Down Expand Up @@ -405,11 +395,11 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
switch (cmd.getCmd())
{
case CMD_ON:
data[B_LOCK_REM] = 3;
data[B_SWING] = 3;
publishTopic(item->itemArr->name,"ON","/swing");
break;
case CMD_OFF:
data[B_LOCK_REM] = 0;
data[B_SWING] = 0;
publishTopic(item->itemArr->name,"OFF","/swing");
break;
default:
Expand Down
27 changes: 17 additions & 10 deletions lighthub/modules/out_modbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,15 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
mappedParam.Tens_raw(data * (TENS_BASE/100));
mappedParam.Float((int32_t) data/100.);
}

if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object))
mappedParam.doMapping(mapObj);

debugSerial << F("MB got ")<<mappedParam.toString(buf,sizeof(buf))<< F(" from ")<<regType<<F(":")<<paramObj->name<<endl;

if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object))
{
mappedParam=mappedParam.doReverseMapping(mapObj);
debugSerial << F("Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
}

if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name);
Expand All @@ -329,13 +332,16 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
aJson.addNumberToObject(execObj, "@S", (long) param);
}
if (submitParam)
{ // Compare with last submitted val
{
//#ifdef MB_SUPPRESS_OUT_EQ_IN
// Compare with last submitted val (if @V NOT marked as NULL in config)
aJsonObject *settedValue = aJson.getObjectItem(execObj,"@V");
if (settedValue && (settedValue->valueint == param))
if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param))
{
debugSerial<<F("Ignored - equal with setted val")<<endl;
}
else executeCommand(execObj, -1, mappedParam);
else executeCommand(execObj, -1, mappedParam);
//#endif
}
}
}
Expand Down Expand Up @@ -598,18 +604,19 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
execObj->subtype |= MB_NEED_SEND;

aJsonObject *outValue = aJson.getObjectItem(execObj,"@V");
if (outValue)
if (outValue) // Existant. Preserve original @type
{
outValue->valueint=Value;
outValue->subtype =regType;
polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
outValue->subtype =regType & 0xF;
if (outValue->type == aJson_Int) polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
}
else //No container to store value yet
// If no @V in config - creating with INT type - normal behavior - no supress in-to-out
{
debugSerial<<F("Add @V: ")<<execObj->name<<endl;
aJson.addNumberToObject(execObj, "@V", Value);
outValue = aJson.getObjectItem(execObj,"@V");
if (outValue) outValue->subtype =regType;
if (outValue) outValue->subtype =regType & 0xF;
}
}
}
Expand Down
Loading

0 comments on commit 891701c

Please sign in to comment.