mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 11:49:51 +03:00
Important Input re-intrance bug fixed
Haier AC relability improved (buffer not save if incoming packet broken) CAN - sub-item calculation fixed continue working on MultiAC config for LH board testing shared
This commit is contained in:
@@ -46,3 +46,4 @@
|
|||||||
#HAL_SD_MODULE_DISABLED
|
#HAL_SD_MODULE_DISABLED
|
||||||
#HAL_DAC_MODULE_DISABLED
|
#HAL_DAC_MODULE_DISABLED
|
||||||
#-DMERCURY_ENABLE
|
#-DMERCURY_ENABLE
|
||||||
|
-D ROTARYENCODER
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
export PORT=cu.usbmodem144101
|
export PORT=cu.usbmodem142401
|
||||||
echo . | stty -f /dev/$PORT speed 1200
|
echo . | stty -f /dev/$PORT speed 1200
|
||||||
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -w -v -b firmware.bin -R
|
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -w -v -b firmware.bin -R
|
||||||
@@ -1 +1 @@
|
|||||||
../tools/mac/arduinoOTA -address 192.168.11.13 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
|
../tools/mac/arduinoOTA -address 192.168.11.200 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch
|
||||||
|
|||||||
221
config-examples/lh22-test.json
Normal file
221
config-examples/lh22-test.json
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
{
|
||||||
|
"dmx":[3,60],
|
||||||
|
"mqtt":["lh22-test","192.168.11.4"],
|
||||||
|
"dmxin":["led5","led6","led7","led8"],
|
||||||
|
"topics":{"root":"test2"},
|
||||||
|
"syslog":["192.168.88.2"],
|
||||||
|
"ow":{
|
||||||
|
"282F7E81E3713C59":{"emit":"t_1"}
|
||||||
|
},
|
||||||
|
"modbus":
|
||||||
|
{
|
||||||
|
"s8":{
|
||||||
|
"poll":{"irs":[[0,3]],"regs":[[0,1],31],"delay":11000},
|
||||||
|
"par":{
|
||||||
|
"co2":{"ir":3},
|
||||||
|
"meterStat":{"ir":0},
|
||||||
|
"alarmStat":{"ir":1},
|
||||||
|
"hr1":{"reg":0},
|
||||||
|
"hr2":{"reg":1},
|
||||||
|
"hr32":{"reg":31}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"term":{
|
||||||
|
"poll":{"regs":[0],"delay":12000},
|
||||||
|
"par":{
|
||||||
|
"t":{"reg":0,"type":"x10"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thmeter":{
|
||||||
|
"serial":"8N1",
|
||||||
|
"baud":4800,
|
||||||
|
"poll":{"regs":[[0,1],[2000,2001],[80,81]],"delay":3000},
|
||||||
|
"par":{
|
||||||
|
"hum" :{"reg":0,"type":"x10"},
|
||||||
|
"temp" :{"reg":1,"type":"x10"},
|
||||||
|
"slaveid" :{"reg":2000},
|
||||||
|
"baud" :{"reg":2001},
|
||||||
|
"tcalib":{"reg":80,"type":"x10"},
|
||||||
|
"hcalib":{"reg":81,"type":"x10"}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"panel":{
|
||||||
|
"serial":"8E1",
|
||||||
|
"poll":{"regs":[[39993,40008],[30000,30001]],"delay":5000},
|
||||||
|
"par":{
|
||||||
|
"fanspeed" :{"reg":40000,"prefetch":true,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7},
|
||||||
|
"settemp" :{"reg":40002,"prefetch":true,"id":12},
|
||||||
|
"alm01":{"reg":40004,"id":13},
|
||||||
|
"alm17":{"reg":40005,"id":14},
|
||||||
|
"alm33":{"reg":40006,"id":15},
|
||||||
|
"sethum" :{"reg":40007,"prefetch":true,"id":16},
|
||||||
|
"setvoc" :{"reg":40008,"prefetch":true,"map":{"val":[400,2000,0,100]},"id":17},
|
||||||
|
"roomtemp" :{"reg":30000,"type":"x10"},
|
||||||
|
"hum" :{"reg":30001},
|
||||||
|
"voc" :{"reg":30002},
|
||||||
|
"ch_temp" :{"reg":40009,"type":"x10","id":3},
|
||||||
|
"ext_temp" :{"reg":40010,"type":"x10","id":18},
|
||||||
|
"out_temp" :{"reg":40011,"type":"x10","id":19},
|
||||||
|
"floor_temp" :{"reg":40012,"type":"x10","id":20},
|
||||||
|
"ch_hum" :{"reg":40013,"id":28},
|
||||||
|
"heat_pwr":{"reg":40014,"id":29},
|
||||||
|
"extvoc":{"reg":40015,"map":{"val":[400,2000,0,100]},"id":27},
|
||||||
|
"actemp":{"reg":40016,"type":"x10","id":25},
|
||||||
|
"fanlvl":{"reg":40017,"id":21},
|
||||||
|
"floormode":{"reg":39995,"prefetch":true,"id":22},
|
||||||
|
"setfloor":{"reg":39996,"prefetch":true,"id":23},
|
||||||
|
"humpwr":{"reg":39998,"prefetch":true,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null},"id":24},
|
||||||
|
"fanauto":{"reg":39999,"prefetch":true,"map":{"cmd":[["ENABLE",1],["DISABLE",0],["AUTO",1]],"val":null},"id":7},
|
||||||
|
"acsettemp":{"reg":39994,"prefetch":true,"id":26},
|
||||||
|
"acon":{"reg":40003,"prefetch":true,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8},
|
||||||
|
"acmode" :{"reg":40001,"prefetch":true,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8},
|
||||||
|
"acfanauto":{"reg":39993,"prefetch":true,"map":{"cmd":[0,["AUTO",1]],"val":null,"def":39997},"id":2},
|
||||||
|
"acfan":{"reg":39997,"prefetch":true,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2]]},"id":2},
|
||||||
|
"y":{"reg":65512},
|
||||||
|
"mo":{"reg":65513},
|
||||||
|
"d":{"reg":65514},
|
||||||
|
"dw":{"reg":65515},
|
||||||
|
"h":{"reg":65516},
|
||||||
|
"m":{"reg":65517},
|
||||||
|
"s":{"reg":65518},
|
||||||
|
"blmind":{"reg":50051},
|
||||||
|
"blmaxd":{"reg":50052},
|
||||||
|
"blminn":{"reg":50053},
|
||||||
|
"blmaxn":{"reg":50054}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"items": {
|
||||||
|
"th":[14,[1,"thmeter",
|
||||||
|
{
|
||||||
|
"temp":{"emit":"temp","@S":null},
|
||||||
|
"hum" :{"emit":"zal2hum","@S":null},
|
||||||
|
"slaveid" :{"emit":"slaveid"},
|
||||||
|
"baud" :{"emit":"baud"},
|
||||||
|
"tcalib":{"emit":"tcalib"},
|
||||||
|
"hcalib":{"emit":"hcalib"}
|
||||||
|
}
|
||||||
|
]],
|
||||||
|
|
||||||
|
"pout0":[6,22],
|
||||||
|
"pout1":[6,23],
|
||||||
|
"pout2":[6,24],
|
||||||
|
"pout3":[6,25],
|
||||||
|
"pout4":[3,9],
|
||||||
|
"pout5":[3,8],
|
||||||
|
"pout6":[3,11],
|
||||||
|
"pout7":[3,12],
|
||||||
|
"pwm0" :[3,4],
|
||||||
|
"pwm1" :[3,5],
|
||||||
|
"pwm2" :[3,6],
|
||||||
|
"pwm3" :[3,7],
|
||||||
|
|
||||||
|
"unprot0":[6,33],
|
||||||
|
"unprot1":[6,32],
|
||||||
|
"unprot2":[6,31],
|
||||||
|
"unprot3":[6,30],
|
||||||
|
"unprot4":[6,29],
|
||||||
|
"unprot5":[6,28],
|
||||||
|
"unprot6":[6,27],
|
||||||
|
"unprot7":[6,26],
|
||||||
|
"led": [1,1],
|
||||||
|
"led2":[1,5],
|
||||||
|
"led3":[1,9],
|
||||||
|
"led4":[1,13],
|
||||||
|
"led5":[1,17],
|
||||||
|
"led6":[1,21],
|
||||||
|
"led7":[1,25],
|
||||||
|
"led8":[1,29],
|
||||||
|
"dimmer" :[0,33],
|
||||||
|
"dimmer2":[0,34],
|
||||||
|
"dimmer3":[0,35],
|
||||||
|
"dimmer4":[0,36],
|
||||||
|
"dimmer5":[0,37],
|
||||||
|
"dimmer6":[0,38],
|
||||||
|
"dimmers":[7,["dimmer","dimmer2","dimmer3","dimmer4","dimmer5","dimmer6"]],
|
||||||
|
"leds":[7,["led","led2","led3","led4","led5","led6"]],
|
||||||
|
"mbuses":[7,["mbusdim1","mbusdim2","mbusdim3","mbusdim4"]],
|
||||||
|
"all":[7,["dimmers","uouts","relays","leds"]],
|
||||||
|
"relays":[7,["pout0","pout1","pout2","pout3","pout4","pout5","pout6","pout7"]],
|
||||||
|
"uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]]
|
||||||
|
},
|
||||||
|
"in":{
|
||||||
|
"42":{"emit":"in0"},
|
||||||
|
"44":{"emit":"in1"},
|
||||||
|
"46":{"emit":"in2"},
|
||||||
|
"49":{"emit":"in3"},
|
||||||
|
"43":{"emit":"in4"},
|
||||||
|
"45":{"emit":"in5"},
|
||||||
|
"47":{"emit":"in6"},
|
||||||
|
"48":{"emit":"in7"},
|
||||||
|
"34":{"emit":"in8"},
|
||||||
|
"36":{"emit":"in9"},
|
||||||
|
"38":{"emit":"in10"},
|
||||||
|
"40":{"emit":"in11"},
|
||||||
|
"35":{"emit":"in12"},
|
||||||
|
"37":{"emit":"in13"},
|
||||||
|
"39":{"emit":"in14"},
|
||||||
|
"41":{"emit":"in15"},
|
||||||
|
|
||||||
|
"54":{"T":64,"emit":"a00","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
|
||||||
|
"55":{"T":64,"emit":"a01","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
|
||||||
|
"56":{"T":64,"emit":"a02","map":[0,1024,0,1024,10]},
|
||||||
|
"57":{"T":64,"emit":"a03","map":[0,1024,0,1024,10]},
|
||||||
|
"58":{"T":64,"emit":"a04","map":[0,1024,0,1024,10]},
|
||||||
|
"59":{"T":64,"emit":"a05","map":[0,1024,0,1024,10]},
|
||||||
|
"60":{"T":64,"emit":"a06"},
|
||||||
|
"61":{"T":64,"emit":"a07","map":[0,1024,0,1024,5]},
|
||||||
|
"62":{"T":64,"emit":"a08","map":[0,1024,0,1024,5]},
|
||||||
|
"63":{"T":64,"emit":"a09","map":[0,1024,0,1024,5]},
|
||||||
|
"64":{"T":64,"emit":"a10","map":[0,1024,0,1024,5]},
|
||||||
|
"65":{"T":64,"emit":"a11","map":[0,1024,0,1024,5]},
|
||||||
|
"66":{"T":2,"emit":"d12"},
|
||||||
|
"67":{
|
||||||
|
"T":2,
|
||||||
|
"scmd":{"emit":"d13","ecmd":"scmd"},
|
||||||
|
"rcmd":{"emit":"d13","ecmd":"rcmd"},
|
||||||
|
"lcmd":{"emit":"d13","ecmd":"lcmd"},
|
||||||
|
"click":{"emit":"d13","ecmd":"click"},
|
||||||
|
"dclick":{"emit":"d13","ecmd":"dclick"},
|
||||||
|
"tclick":{"emit":"d13","ecmd":"tclick"},
|
||||||
|
"scmd2":{"emit":"d13","ecmd":"scmd2"},
|
||||||
|
"scmd3":{"emit":"d13","ecmd":"scmd3"},
|
||||||
|
"lcmd2":{"emit":"d13","ecmd":"lcmd2"},
|
||||||
|
"lcmd3":{"emit":"d13","ecmd":"lcmd3"},
|
||||||
|
"rpcmd":{"emit":"d13","ecmd":"rpcmd"},
|
||||||
|
"rpcmd2":{"emit":"d13","ecmd":"rpcmd2"},
|
||||||
|
"rpcmd3":{"emit":"d13","ecmd":"rpcmd3"}
|
||||||
|
},
|
||||||
|
"68":{"T":2,
|
||||||
|
"scmd":{"emit":"d14","ecmd":"scmd"},
|
||||||
|
"rcmd":{"emit":"d14","ecmd":"rcmd"},
|
||||||
|
"lcmd":{"emit":"d14","ecmd":"lcmd"},
|
||||||
|
"click":{"emit":"d14","ecmd":"click"},
|
||||||
|
"dclick":{"emit":"d14","ecmd":"dclick"},
|
||||||
|
"tclick":{"emit":"d14","ecmd":"tclick"},
|
||||||
|
"scmd2":{"emit":"d14","ecmd":"scmd2"},
|
||||||
|
"scmd3":{"emit":"d14","ecmd":"scmd3"},
|
||||||
|
"lcmd2":{"emit":"d14","ecmd":"lcmd2"},
|
||||||
|
"lcmd3":{"emit":"d14","ecmd":"lcmd3"},
|
||||||
|
"rpcmd":{"emit":"d14","ecmd":"rpcmd"},
|
||||||
|
"rpcmd2":{"emit":"d14","ecmd":"rpcmd2"},
|
||||||
|
"rpcmd3":{"emit":"d14","ecmd":"rpcmd3"}
|
||||||
|
},
|
||||||
|
"69":{"T":2,
|
||||||
|
"scmd":{"emit":"d15","ecmd":"scmd"},
|
||||||
|
"rcmd":{"emit":"d15","ecmd":"rcmd"},
|
||||||
|
"lcmd":{"emit":"d15","ecmd":"lcmd"},
|
||||||
|
"click":{"emit":"d15","ecmd":"click"},
|
||||||
|
"dclick":{"emit":"d15","ecmd":"dclick"},
|
||||||
|
"tclick":{"emit":"d15","ecmd":"tclick"},
|
||||||
|
"scmd2":{"emit":"d15","ecmd":"scmd2"},
|
||||||
|
"scmd3":{"emit":"d15","ecmd":"scmd3"},
|
||||||
|
"lcmd2":{"emit":"d15","ecmd":"lcmd2"},
|
||||||
|
"lcmd3":{"emit":"d15","ecmd":"lcmd3"},
|
||||||
|
"rpcmd":{"emit":"d15","ecmd":"rpcmd"},
|
||||||
|
"rpcmd2":{"emit":"d15","ecmd":"rpcmd2"},
|
||||||
|
"rpcmd3":{"emit":"d15","ecmd":"rpcmd3"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -630,6 +630,7 @@ while (remoteConfObj)
|
|||||||
strncpy(root+rootLen, addrObj->valuestring, buflen-rootLen-1);
|
strncpy(root+rootLen, addrObj->valuestring, buflen-rootLen-1);
|
||||||
strncat(root+rootLen, "/", buflen-rootLen-1);
|
strncat(root+rootLen, "/", buflen-rootLen-1);
|
||||||
strncat(root+rootLen, "#", buflen-rootLen-1);
|
strncat(root+rootLen, "#", buflen-rootLen-1);
|
||||||
|
debugSerial.print("CAN: subscribe ");
|
||||||
debugSerial.println(root);
|
debugSerial.println(root);
|
||||||
mqttClient.subscribe(root);
|
mqttClient.subscribe(root);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,10 +272,11 @@ for (short rgbwChan=0; rgbwChan < RGBWChannels; rgbwChan++)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef _dmxout
|
#ifdef _dmxout
|
||||||
//for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
|
debugSerial.print(F("DMXIN:"));
|
||||||
//debugSerial.println();
|
for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
|
||||||
//#endif
|
debugSerial.println();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -302,6 +303,7 @@ void DMXinSetup(int channels)
|
|||||||
if (channels>(32*4)) channels = 32*4;
|
if (channels>(32*4)) channels = 32*4;
|
||||||
DMXin = new uint8_t [channels];
|
DMXin = new uint8_t [channels];
|
||||||
DMXINChannels=channels;
|
DMXINChannels=channels;
|
||||||
|
// debugSerial<<F("DMXIN: init chans:")<<channels<<endl;
|
||||||
#if defined(ARDUINO_ARCH_AVR)
|
#if defined(ARDUINO_ARCH_AVR)
|
||||||
DMXSerial.init(DMXReceiver,0,channels);
|
DMXSerial.init(DMXReceiver,0,channels);
|
||||||
if (DMXSerial.getBuffer()) {debugSerial.print(F("Init in ch:"));debugSerial.println(channels);} else debugSerial.println(F("DMXin Buffer alloc err"));
|
if (DMXSerial.getBuffer()) {debugSerial.print(F("Init in ch:"));debugSerial.println(channels);} else debugSerial.println(F("DMXin Buffer alloc err"));
|
||||||
|
|||||||
@@ -683,7 +683,7 @@ debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") <<
|
|||||||
|
|
||||||
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
|
||||||
bool Input::
|
bool Input::
|
||||||
changeState(uint8_t newState, short cause, aJsonObject * currentInputObject)
|
changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState)
|
||||||
{
|
{
|
||||||
if (!inputObj || !store) return false;
|
if (!inputObj || !store) return false;
|
||||||
|
|
||||||
@@ -693,6 +693,7 @@ if (newState == IS_REQSTATE)
|
|||||||
// Requested delayed change State and safe moment
|
// Requested delayed change State and safe moment
|
||||||
newState=store->reqState; //Retrieve requested state
|
newState=store->reqState; //Retrieve requested state
|
||||||
debugSerial<<F("Pended: #")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
|
debugSerial<<F("Pended: #")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
|
||||||
|
contactState = store->lastValue;
|
||||||
if (store->state == newState)
|
if (store->state == newState)
|
||||||
{
|
{
|
||||||
store->delayedState = false;
|
store->delayedState = false;
|
||||||
@@ -784,6 +785,20 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cause != CHECK_INTERRUPT)
|
||||||
|
{
|
||||||
|
onContactChanged(contactState);
|
||||||
|
store->delayedState=false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
store->delayedState=true;
|
||||||
|
store->lastValue = contactState;
|
||||||
|
store->reqState=newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newState == IS_NOP) return true;
|
||||||
|
|
||||||
aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item");
|
aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item");
|
||||||
aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit");
|
aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit");
|
||||||
aJsonObject *defaultCan = aJson.getObjectItem(currentInputObject, "can");
|
aJsonObject *defaultCan = aJson.getObjectItem(currentInputObject, "can");
|
||||||
@@ -835,7 +850,7 @@ void Input::contactPoll(short cause)
|
|||||||
|
|
||||||
contactPollBusy++;
|
contactPollBusy++;
|
||||||
aJsonObject * currentInputObject = getCurrentInput();
|
aJsonObject * currentInputObject = getCurrentInput();
|
||||||
changeState(IS_REQSTATE,cause,currentInputObject); //Check for postponed states transitions
|
changeState(IS_REQSTATE,cause,currentInputObject,false); //Check for postponed states transitions
|
||||||
|
|
||||||
|
|
||||||
uint8_t inputOnLevel;
|
uint8_t inputOnLevel;
|
||||||
@@ -865,15 +880,15 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_PRESSED:
|
case IS_PRESSED:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject);
|
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState);
|
||||||
else changeState(IS_LONG, cause,currentInputObject);
|
else changeState(IS_LONG, cause,currentInputObject,currentInputState);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG:
|
case IS_LONG:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT, cause,currentInputObject);
|
changeState(IS_REPEAT, cause,currentInputObject,currentInputState);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -881,7 +896,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT:
|
case IS_REPEAT:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT, cause,currentInputObject);
|
changeState(IS_REPEAT, cause,currentInputObject,currentInputState);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -889,15 +904,15 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_PRESSED2:
|
case IS_PRESSED2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
|
||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject);
|
if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState);
|
||||||
else changeState(IS_LONG2, cause,currentInputObject);
|
else changeState(IS_LONG2, cause,currentInputObject,currentInputState);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG2:
|
case IS_LONG2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT2, cause,currentInputObject);
|
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -905,7 +920,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT2:
|
case IS_REPEAT2:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT2, cause,currentInputObject);
|
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -915,17 +930,17 @@ switch (store->state) //Timer based transitions
|
|||||||
{
|
{
|
||||||
if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers
|
if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers
|
||||||
{
|
{
|
||||||
if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject); //was used
|
if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState); //was used
|
||||||
else changeState(IS_PRESSED2, cause,currentInputObject); // completely empty trippleClick section - fallback to first click handler
|
else changeState(IS_PRESSED2, cause,currentInputObject,currentInputState); // completely empty trippleClick section - fallback to first click handler
|
||||||
}
|
}
|
||||||
else changeState(IS_LONG3, cause,currentInputObject);
|
else changeState(IS_LONG3, cause,currentInputObject,currentInputState);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG3:
|
case IS_LONG3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT3, cause,currentInputObject);
|
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -933,7 +948,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_REPEAT3:
|
case IS_REPEAT3:
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
|
||||||
{
|
{
|
||||||
changeState(IS_REPEAT3, cause,currentInputObject);
|
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState);
|
||||||
store->timestamp16 = millis() & 0xFFFF;
|
store->timestamp16 = millis() & 0xFFFF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -943,7 +958,7 @@ switch (store->state) //Timer based transitions
|
|||||||
case IS_WAITPRESS:
|
case IS_WAITPRESS:
|
||||||
|
|
||||||
|
|
||||||
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject);
|
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
} //switch
|
} //switch
|
||||||
#ifdef ROTARYENCODER
|
#ifdef ROTARYENCODER
|
||||||
@@ -963,7 +978,8 @@ if (re)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} //if not INTERRUPT
|
} //if not INTERRUPT
|
||||||
if (currentInputState != store->lastValue) // value changed
|
if ((currentInputState != store->lastValue) || // value changed
|
||||||
|
(isTimeOver(store->timestamp16,millis() & 0xFFFF,T_REPEAT,0xFFFF) && getIntFromJson(currentInputObject,"repeat")))
|
||||||
{
|
{
|
||||||
if (store->bounce) store->bounce = store->bounce - 1;
|
if (store->bounce) store->bounce = store->bounce - 1;
|
||||||
else //confirmed change
|
else //confirmed change
|
||||||
@@ -981,7 +997,7 @@ if (re)
|
|||||||
} else */
|
} else */
|
||||||
|
|
||||||
{
|
{
|
||||||
// onContactChanged(currentInputState); //Legacy input - to remove later
|
////// onContactChanged(currentInputState); //Legacy input - to remove later // wrong place - INTERRUPTS
|
||||||
|
|
||||||
bool res = true;
|
bool res = true;
|
||||||
if (currentInputState) //Button pressed state transitions
|
if (currentInputState) //Button pressed state transitions
|
||||||
@@ -989,7 +1005,7 @@ if (re)
|
|||||||
switch (store->state)
|
switch (store->state)
|
||||||
{
|
{
|
||||||
case IS_IDLE:
|
case IS_IDLE:
|
||||||
res = changeState(IS_PRESSED, cause,currentInputObject);
|
res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1001,30 +1017,33 @@ if (re)
|
|||||||
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
|
||||||
!aJson.getObjectItem(currentInputObject, "dclick")
|
!aJson.getObjectItem(currentInputObject, "dclick")
|
||||||
)
|
)
|
||||||
res = changeState(IS_PRESSED, cause,currentInputObject);
|
res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
else res = changeState(IS_PRESSED2, cause,currentInputObject);
|
else res = changeState(IS_PRESSED2, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_RELEASED2:
|
case IS_RELEASED2:
|
||||||
|
|
||||||
res = changeState(IS_PRESSED3, cause,currentInputObject);
|
res = changeState(IS_PRESSED3, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
res = changeState(IS_NOP, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
switch (store->state) //Button released state transitions
|
switch (store->state) //Button released state transitions
|
||||||
{
|
{
|
||||||
case IS_PRESSED:
|
case IS_PRESSED:
|
||||||
|
|
||||||
res = changeState(IS_RELEASED, cause,currentInputObject);
|
res = changeState(IS_RELEASED, cause,currentInputObject,currentInputState);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG:
|
case IS_LONG:
|
||||||
case IS_REPEAT:
|
case IS_REPEAT:
|
||||||
case IS_WAITRELEASE:
|
case IS_WAITRELEASE:
|
||||||
res = changeState(IS_WAITPRESS, cause,currentInputObject);
|
res = changeState(IS_WAITPRESS, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_PRESSED2:
|
case IS_PRESSED2:
|
||||||
@@ -1033,8 +1052,8 @@ if (re)
|
|||||||
!aJson.getObjectItem(currentInputObject, "lcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "lcmd2") &&
|
||||||
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
|
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
|
||||||
!aJson.getObjectItem(currentInputObject, "dclick")
|
!aJson.getObjectItem(currentInputObject, "dclick")
|
||||||
) res = changeState(IS_IDLE, cause,currentInputObject);
|
) res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
||||||
else res = changeState(IS_RELEASED2, cause,currentInputObject);
|
else res = changeState(IS_RELEASED2, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_LONG2:
|
case IS_LONG2:
|
||||||
@@ -1042,8 +1061,10 @@ if (re)
|
|||||||
case IS_LONG3:
|
case IS_LONG3:
|
||||||
case IS_REPEAT3:
|
case IS_REPEAT3:
|
||||||
case IS_PRESSED3:
|
case IS_PRESSED3:
|
||||||
res = changeState(IS_IDLE, cause,currentInputObject);
|
res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
res = changeState(IS_NOP, cause,currentInputObject,currentInputState);
|
||||||
}
|
}
|
||||||
if (res) { //State changed or postponed
|
if (res) { //State changed or postponed
|
||||||
// store->logicState = currentInputState;
|
// store->logicState = currentInputState;
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ e-mail anklimov@gmail.com
|
|||||||
#define IS_REPEAT3 12u
|
#define IS_REPEAT3 12u
|
||||||
#define IS_WAITRELEASE 13u
|
#define IS_WAITRELEASE 13u
|
||||||
#define IS_REQSTATE 0xFF
|
#define IS_REQSTATE 0xFF
|
||||||
|
#define IS_NOP 0xF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ e-mail anklimov@gmail.com
|
|||||||
#define T_IDLE 600
|
#define T_IDLE 600
|
||||||
#define T_RPT 300
|
#define T_RPT 300
|
||||||
#define T_RPT_PULSE 150
|
#define T_RPT_PULSE 150
|
||||||
|
#define T_REPEAT 30000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ protected:
|
|||||||
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
|
||||||
|
|
||||||
char* getIdxField();
|
char* getIdxField();
|
||||||
bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject);
|
bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState);
|
||||||
void setupRotaryEncoder();
|
void setupRotaryEncoder();
|
||||||
|
|
||||||
aJsonObject * getCurrentInput();
|
aJsonObject * getCurrentInput();
|
||||||
|
|||||||
@@ -358,7 +358,7 @@ uint16_t getCanNum(aJsonObject* verb)
|
|||||||
|
|
||||||
char * Item::getSubItemStrById(uint8_t subItem)
|
char * Item::getSubItemStrById(uint8_t subItem)
|
||||||
{
|
{
|
||||||
if (subItem == NO_SUBITEM || (subItem | SUBITEM_IS_COMMAND)) return NULL;
|
if (subItem == NO_SUBITEM || (subItem & SUBITEM_IS_COMMAND)) return NULL;
|
||||||
if (!itemArg) return NULL;
|
if (!itemArg) return NULL;
|
||||||
aJsonObject * i = itemArg;
|
aJsonObject * i = itemArg;
|
||||||
if (i->type == aJson_Array) i=i->child;
|
if (i->type == aJson_Array) i=i->child;
|
||||||
@@ -421,17 +421,19 @@ return NO_SUBITEM;
|
|||||||
{
|
{
|
||||||
if (getCanNum(itemArr->child) == num)
|
if (getCanNum(itemArr->child) == num)
|
||||||
{
|
{
|
||||||
debugSerial<<"Find item: "<< itemArr->name << " addr:" << num << endl;
|
debugSerial<<"CAN: Find item: "<< itemArr->name << " id:" << num << "sub:" << subItem;
|
||||||
Parse();
|
Parse();
|
||||||
if (subItem | SUBITEM_IS_COMMAND)
|
if (subItem & SUBITEM_IS_COMMAND)
|
||||||
{
|
{
|
||||||
subItem &=~ SUBITEM_IS_COMMAND;
|
subItem &=~ SUBITEM_IS_COMMAND;
|
||||||
if (subItem<commandsNum) strncpy_P(defaultSubItem, commands_P[subItem], sizeof(defaultSubItem));
|
if (subItem<commandsNum) strncpy_P(defaultSubItem, commands_P[subItem], sizeof(defaultSubItem));
|
||||||
|
debugSerial<<" subcmd:"<<defaultSubItem<<endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char * subItemStr = getSubItemStrById(subItem);
|
char * subItemStr = getSubItemStrById(subItem);
|
||||||
if (subItemStr) strncpy(defaultSubItem,subItemStr,sizeof(defaultSubItem));
|
if (subItemStr) strncpy(defaultSubItem,subItemStr,sizeof(defaultSubItem));
|
||||||
|
debugSerial<<" subname:"<<defaultSubItem<<endl;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1107,7 +1109,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized)
|
|||||||
uint8_t command2Set = 0;
|
uint8_t command2Set = 0;
|
||||||
itemCmd originalCmd = cmd;
|
itemCmd originalCmd = cmd;
|
||||||
int subitemCmd = subitem2cmd(subItem);
|
int subitemCmd = subitem2cmd(subItem);
|
||||||
|
bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue();
|
||||||
/// Common (GRP & NO GRP) commands
|
/// Common (GRP & NO GRP) commands
|
||||||
switch (cmd.getCmd())
|
switch (cmd.getCmd())
|
||||||
{
|
{
|
||||||
@@ -1293,14 +1295,14 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//chActive=(isActive()>0);
|
if (chActive == -1) chActive=(isActive()>0); //need! because activities status will be changed
|
||||||
if ((suffixCode!=S_CMD) || (cmd.getCmd() != CMD_XON) || !getFlag(FLAG_DISABLED))
|
if ((suffixCode!=S_CMD) || (cmd.getCmd() != CMD_XON) || !getFlag(FLAG_DISABLED))
|
||||||
{
|
{
|
||||||
digGroup(itemArg,&cmd,subItem,authorized,flags);
|
digGroup(itemArg,&cmd,subItem,authorized,flags);
|
||||||
|
|
||||||
if ((suffixCode==S_CMD) && cmd.isValue())
|
if (oppositeCommandToBeSchedulled)//((suffixCode==S_CMD) && cmd.isValue())
|
||||||
{
|
{
|
||||||
scheduleOppositeCommand(originalCmd,-1/*chActive*/,authorized);
|
scheduleOppositeCommand(originalCmd,-1,authorized);
|
||||||
scheduledOppositeCommand = true;
|
scheduledOppositeCommand = true;
|
||||||
}
|
}
|
||||||
if (subItem && !subitemCmd) status2Send |= FLAG_SEND_IMMEDIATE;
|
if (subItem && !subitemCmd) status2Send |= FLAG_SEND_IMMEDIATE;
|
||||||
@@ -1347,8 +1349,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized)
|
|||||||
if (chActive == -1) chActive=(isActive()>0);
|
if (chActive == -1) chActive=(isActive()>0);
|
||||||
if (!chActive) //if channel was'nt active before CMD_XON
|
if (!chActive) //if channel was'nt active before CMD_XON
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
cmd.loadItemDef(this);
|
cmd.loadItemDef(this);
|
||||||
cmd.Cmd(CMD_ON);
|
cmd.Cmd(CMD_ON);
|
||||||
command2Set=CMD_XON;
|
command2Set=CMD_XON;
|
||||||
@@ -1424,7 +1424,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized)
|
|||||||
|
|
||||||
/// bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && allowRecursion && cmd.isValue();
|
/// bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && allowRecursion && cmd.isValue();
|
||||||
|
|
||||||
bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue();
|
// bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue();
|
||||||
// Commands for NON GROUP
|
// Commands for NON GROUP
|
||||||
//threating Restore, XOFF (special conditional commands)/ convert to ON, OFF and SET values
|
//threating Restore, XOFF (special conditional commands)/ convert to ON, OFF and SET values
|
||||||
switch (cmd.getCmd()) {
|
switch (cmd.getCmd()) {
|
||||||
@@ -1740,7 +1740,14 @@ if ((!driver || driver->isAllowed(cmd))
|
|||||||
|
|
||||||
//update command for HALT & XON and send MQTT status
|
//update command for HALT & XON and send MQTT status
|
||||||
if (command2Set) setCmd(command2Set | FLAG_COMMAND);
|
if (command2Set) setCmd(command2Set | FLAG_COMMAND);
|
||||||
if (operation) SendStatus(status2Send,subItem);
|
if (operation) {
|
||||||
|
SendStatus(status2Send);//,subItem);
|
||||||
|
if (oppositeCommandToBeSchedulled && subItem)
|
||||||
|
{
|
||||||
|
debugSerial<<F("CTRL: momentary event")<<endl;
|
||||||
|
SendStatusImmediate(originalCmd,status2Send,subItem,false); //XON -> OFF scheduled
|
||||||
|
}
|
||||||
|
}
|
||||||
} //alowed cmd
|
} //alowed cmd
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1934,11 +1941,11 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Item::SendStatusImmediate(itemCmd st, long sendFlags, char * subItem) {
|
int Item::SendStatusImmediate(itemCmd st, long sendFlags, char * subItem, bool retain) {
|
||||||
{
|
{
|
||||||
char addrstr[64];
|
char addrstr[64];
|
||||||
char valstr[20] = "";
|
char valstr[20] = "";
|
||||||
char cmdstr[9] = "";
|
char cmdstr[16] = "";
|
||||||
|
|
||||||
debugSerial<<"SENDSTATUS: "<<subItem<<" ";
|
debugSerial<<"SENDSTATUS: "<<subItem<<" ";
|
||||||
st.debugOut();
|
st.debugOut();
|
||||||
@@ -1997,12 +2004,12 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
(st.getArgType() == ST_PERCENTS255 || st.getArgType() == ST_HSV255 || st.getArgType() == ST_FLOAT_CELSIUS))
|
(st.getArgType() == ST_PERCENTS255 || st.getArgType() == ST_HSV255 || st.getArgType() == ST_FLOAT_CELSIUS))
|
||||||
{
|
{
|
||||||
st.toString(valstr, sizeof(valstr), FLAG_PARAMETERS,true);
|
st.toString(valstr, sizeof(valstr), FLAG_PARAMETERS,true);
|
||||||
mqttClient.publish(addrstr, valstr, true);
|
mqttClient.publish(addrstr, valstr, retain);
|
||||||
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl;
|
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl;
|
||||||
}
|
}
|
||||||
else if ((sendFlags & FLAG_COMMAND) && (strlen(cmdstr)))
|
else if ((sendFlags & FLAG_COMMAND) && (strlen(cmdstr)))
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, cmdstr, true);
|
mqttClient.publish(addrstr, cmdstr, retain);
|
||||||
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
|
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2068,7 +2075,7 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, valstr,true);
|
mqttClient.publish(addrstr, valstr,retain);
|
||||||
clearFlag(FLAG_PARAMETERS);
|
clearFlag(FLAG_PARAMETERS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2082,6 +2089,7 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
|
|
||||||
if (sendFlags & FLAG_COMMAND)
|
if (sendFlags & FLAG_COMMAND)
|
||||||
{
|
{
|
||||||
|
if (!subItem)
|
||||||
// Some additional preparing for extended set of commands:
|
// Some additional preparing for extended set of commands:
|
||||||
switch (st.getCmd()) {
|
switch (st.getCmd()) {
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
@@ -2112,6 +2120,8 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
case CMD_XON:
|
case CMD_XON:
|
||||||
if (itemType == CH_THERMO) strcpy_P(cmdstr, AUTO_P);
|
if (itemType == CH_THERMO) strcpy_P(cmdstr, AUTO_P);
|
||||||
}
|
}
|
||||||
|
else //for subItems - transpatent print
|
||||||
|
st.toString(cmdstr,sizeof(cmdstr),FLAG_COMMAND | FLAG_PARAMETERS);
|
||||||
|
|
||||||
setTopic(addrstr,sizeof(addrstr),T_OUT);
|
setTopic(addrstr,sizeof(addrstr),T_OUT);
|
||||||
strncat(addrstr, itemArr->name, sizeof(addrstr)-1);
|
strncat(addrstr, itemArr->name, sizeof(addrstr)-1);
|
||||||
@@ -2128,7 +2138,7 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, cmdstr,true);
|
mqttClient.publish(addrstr, cmdstr,retain);
|
||||||
clearFlag(FLAG_COMMAND);
|
clearFlag(FLAG_COMMAND);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2168,7 +2178,7 @@ int Item::SendStatus(long sendFlags, char * subItem) {
|
|||||||
#if not defined (NOIP)
|
#if not defined (NOIP)
|
||||||
if (mqttClient.connected() && !ethernetIdleCount)
|
if (mqttClient.connected() && !ethernetIdleCount)
|
||||||
{
|
{
|
||||||
mqttClient.publish(addrstr, cmdstr,true);
|
mqttClient.publish(addrstr, cmdstr,retain);
|
||||||
clearFlag(FLAG_FLAGS);
|
clearFlag(FLAG_FLAGS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ class Item
|
|||||||
void setSubtype(uint8_t par);
|
void setSubtype(uint8_t par);
|
||||||
int Poll(int cause);
|
int Poll(int cause);
|
||||||
int SendStatus(long sendFlags, char * subItem=NULL);
|
int SendStatus(long sendFlags, char * subItem=NULL);
|
||||||
int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL);
|
int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL, bool tetain = true);
|
||||||
int isActive();
|
int isActive();
|
||||||
int getChanType();
|
int getChanType();
|
||||||
inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));};
|
inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));};
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ if (Status() == AC_SENDING)
|
|||||||
ACSerial->write(getCRC(req, size-1));
|
ACSerial->write(getCRC(req, size-1));
|
||||||
//ACSerial->flush();
|
//ACSerial->flush();
|
||||||
store->timestamp=millisNZ();
|
store->timestamp=millisNZ();
|
||||||
debugSerial<<F("AC: ")<<portNum<<F(" <<");
|
debugSerial<<F("AC:")<<portNum<<F(" << ");
|
||||||
for (int i=0; i < size-1; i++)
|
for (int i=0; i < size-1; i++)
|
||||||
{
|
{
|
||||||
if (req[i] < 10){
|
if (req[i] < 10){
|
||||||
@@ -436,35 +436,37 @@ case AC_AWAITINGCMD: //Flusing port for 5 sec, poll status
|
|||||||
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
byte tmpdata[sizeof(store->data)];
|
||||||
if(ACSerial->available() >= 37){ //was 0
|
if(ACSerial->available() >= 37){ //was 0
|
||||||
ACSerial->readBytes(store->data, 37);
|
ACSerial->readBytes(tmpdata, 37);
|
||||||
while(ACSerial->available()){
|
while(ACSerial->available()){
|
||||||
delay(2);
|
delay(2);
|
||||||
ACSerial->read();
|
ACSerial->read();
|
||||||
}
|
}
|
||||||
|
|
||||||
debugSerial<<F("AC: ")<<portNum<<F(" >> ");
|
debugSerial<<F("AC:")<<portNum<<F(" >> ");
|
||||||
for (int i=0; i < 37-1; i++)
|
for (int i=0; i < 37-1; i++)
|
||||||
{
|
{
|
||||||
if (store->data[i] < 10){
|
if (tmpdata[i] < 10){
|
||||||
debugSerial.print("0");
|
debugSerial.print("0");
|
||||||
debugSerial.print(store->data[i], HEX);
|
debugSerial.print(tmpdata[i], HEX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debugSerial.print(store->data[i], HEX);
|
debugSerial.print(tmpdata[i], HEX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debugSerial.println('.');
|
debugSerial.println('.');
|
||||||
|
|
||||||
uint8_t crc=getCRC(store->data,36);
|
uint8_t crc=getCRC(tmpdata,36);
|
||||||
|
|
||||||
if (store->data[36] == crc)
|
if (tmpdata[36] == crc)
|
||||||
{
|
{
|
||||||
debugSerial<<F("AC: OK")<<endl;
|
debugSerial<<F("AC: OK")<<endl;
|
||||||
if (store->data[36] != store->inCheck)
|
if (tmpdata[36] != store->inCheck)
|
||||||
{ //Updated
|
{ //Updated
|
||||||
store->inCheck = store->data[36];
|
store->inCheck = tmpdata[36];
|
||||||
|
memcpy(store->data,tmpdata,sizeof(store->data));
|
||||||
InsertData(store->data, 37);
|
InsertData(store->data, 37);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,8 +126,9 @@ int out_Multivent::Poll(short cause)
|
|||||||
if (gatesObj)
|
if (gatesObj)
|
||||||
{
|
{
|
||||||
// metrics, collected from AC
|
// metrics, collected from AC
|
||||||
float acTemp = getFloatFromJson(aJson.getObjectItem(gatesObj, ""),"val",NAN);
|
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
|
||||||
int actualCmd = item->getCmd();
|
float acTemp = getFloatFromJson(a,"val",NAN);
|
||||||
|
int actualCmd = getIntFromJson (a,"mode");
|
||||||
int actualMode = CMD_FAN;
|
int actualMode = CMD_FAN;
|
||||||
if (acTemp>30.0) actualMode = CMD_HEAT;
|
if (acTemp>30.0) actualMode = CMD_HEAT;
|
||||||
else if (acTemp<15.0) actualMode = CMD_COOL;
|
else if (acTemp<15.0) actualMode = CMD_COOL;
|
||||||
@@ -189,12 +190,12 @@ int out_Multivent::Poll(short cause)
|
|||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
|
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
|
||||||
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
|
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
|
||||||
Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
break;
|
break;
|
||||||
case CMD_COOL:
|
case CMD_COOL:
|
||||||
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
|
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
|
||||||
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
|
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
|
||||||
Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CMD_HEAT:
|
case CMD_HEAT:
|
||||||
@@ -239,7 +240,8 @@ int out_Multivent::sendACcmd (int cmd)
|
|||||||
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
|
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
|
||||||
if (!a) return 0;
|
if (!a) return 0;
|
||||||
int lastCmd = getIntFromJson(a,"@lastCmd");
|
int lastCmd = getIntFromJson(a,"@lastCmd");
|
||||||
if (lastCmd && (item->getCmd() != lastCmd)) {
|
int acCmd = getIntFromJson(a,"mode");
|
||||||
|
if (lastCmd && (acCmd != lastCmd)) {
|
||||||
//debugSerial<<"VENT: AC MODE changed manually to "<<item->getCmd()<<endl;
|
//debugSerial<<"VENT: AC MODE changed manually to "<<item->getCmd()<<endl;
|
||||||
return 0;}
|
return 0;}
|
||||||
if (cmd == lastCmd) {
|
if (cmd == lastCmd) {
|
||||||
@@ -252,7 +254,7 @@ int out_Multivent::sendACcmd (int cmd)
|
|||||||
|
|
||||||
int out_Multivent::getChanType()
|
int out_Multivent::getChanType()
|
||||||
{
|
{
|
||||||
return CH_PWM;
|
return CH_THERMO; /////PWM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -274,18 +276,6 @@ switch (suffixCode)
|
|||||||
debugSerial << F("VENT:")<<F("AC air temp: ")<< cmd.getFloat()<<endl;
|
debugSerial << F("VENT:")<<F("AC air temp: ")<< cmd.getFloat()<<endl;
|
||||||
item->setExt(millisNZ());
|
item->setExt(millisNZ());
|
||||||
setValToJson(aJson.getObjectItem(gatesObj, ""),"val",cmd.getFloat());
|
setValToJson(aJson.getObjectItem(gatesObj, ""),"val",cmd.getFloat());
|
||||||
/*
|
|
||||||
int mode = CMD_FAN;
|
|
||||||
int temp = cmd.getInt();
|
|
||||||
if (temp>30) mode = CMD_HEAT;
|
|
||||||
else if (temp<17) mode = CMD_COOL;
|
|
||||||
|
|
||||||
if (item->getCmd() != mode)
|
|
||||||
{
|
|
||||||
item->setCmd(mode);
|
|
||||||
pubAction(item->isActive());
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -296,6 +286,10 @@ switch (suffixCode)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case S_MODE:
|
case S_MODE:
|
||||||
|
debugSerial << F("VENT:")<<F("AC mode: ")<< cmd.getCmd()<<endl;
|
||||||
|
setValToJson(aJson.getObjectItem(gatesObj, ""),"mode",cmd.getCmd());
|
||||||
|
return 1;
|
||||||
|
|
||||||
case S_CMD:
|
case S_CMD:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LOGBUFFER_SIZE
|
#ifndef LOGBUFFER_SIZE
|
||||||
#define LOGBUFFER_SIZE 80
|
#define LOGBUFFER_SIZE 85
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SYSLOG_ENABLE
|
#ifdef SYSLOG_ENABLE
|
||||||
|
|||||||
@@ -663,7 +663,7 @@ bool executeCommand(aJsonObject* cmd, int8_t toggle)
|
|||||||
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem, aJsonObject* defaultEmit, aJsonObject* defaultCan)
|
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem, aJsonObject* defaultEmit, aJsonObject* defaultCan)
|
||||||
//bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd)
|
//bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd)
|
||||||
{
|
{
|
||||||
//char * legacyString =NULL;
|
if (!cmd) return false;
|
||||||
aJsonObject *item = NULL;
|
aJsonObject *item = NULL;
|
||||||
aJsonObject *emit = NULL;
|
aJsonObject *emit = NULL;
|
||||||
aJsonObject *can = NULL;
|
aJsonObject *can = NULL;
|
||||||
@@ -679,7 +679,7 @@ debugSerial<<"Exec:"<<out<<endl;
|
|||||||
free (out);
|
free (out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cmd) cmdType = cmd->type;
|
cmdType = cmd->type;
|
||||||
|
|
||||||
switch (cmdType)
|
switch (cmdType)
|
||||||
{
|
{
|
||||||
@@ -1043,6 +1043,7 @@ if (a->type == aJson_Array)
|
|||||||
// TODO - human readable JSON objects as alias
|
// TODO - human readable JSON objects as alias
|
||||||
if (element && element->type == aJson_Int) return element->valueint;
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
if (element && element->type == aJson_Float) return element->valuefloat;
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Boolean) return element->valuebool;
|
||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
@@ -1055,6 +1056,8 @@ if (a->type == aJson_Object)
|
|||||||
element = aJson.getObjectItem(a, name);
|
element = aJson.getObjectItem(a, name);
|
||||||
if (element && element->type == aJson_Int) return element->valueint;
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
if (element && element->type == aJson_Float) return element->valuefloat;
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Boolean) return element->valuebool;
|
||||||
|
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user