Cumulative changes/pre-release

This commit is contained in:
Климов Андрей Николаевич
2023-04-02 17:27:02 +03:00
parent 3e0566cf07
commit ec306c4934
32 changed files with 734 additions and 367 deletions

View File

@@ -1,7 +1,7 @@
#-DW5500_CS_PIN=53 #-DW5500_CS_PIN=53
-DDMX_SMOOTH -DDMX_SMOOTH
-DSYSLOG_ENABLE -DSYSLOG_ENABLE
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1 #-DMODBUS_SERIAL_PARAM=SERIAL_8E1
-DARTNET_ENABLE -DARTNET_ENABLE
-DOTA -DOTA
-DSTATUSLED -DSTATUSLED

View File

@@ -26,6 +26,10 @@
#-DmodbusSerial=Serial1 #-DmodbusSerial=Serial1
#-DMODBUS_DEBUG #-DMODBUS_DEBUG
#-DMODBUS_UART_RX_PIN=16
#-DMODBUS_UART_TX_PIN=17
#-DmodbusSerial=Serial2
# Use default pins for modbus UART # Use default pins for modbus UART
#-DMODBUS_UART_RX_PIN=-1 #-DMODBUS_UART_RX_PIN=-1
#-DMODBUS_UART_TX_PIN=-1 #-DMODBUS_UART_TX_PIN=-1

View File

@@ -12,8 +12,8 @@
-DTIMER_INT -DTIMER_INT
#-DFLASH_OFFSET=-256 #-DFLASH_OFFSET=-256
# Serial parameters for LEGACY Modbus # default MODBUS Serial parameters for LEGACY Modbus and MODBUS over IP
-DMODBUS_DIMMER_PARAM=SERIAL_8E1 #-DMODBUS_SERIAL_PARAM=SERIAL_8E1
#Set Logariphmic law for DMX channels bright #Set Logariphmic law for DMX channels bright
-DBRIGHT_LOG -DBRIGHT_LOG

View File

@@ -1,4 +1,4 @@
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1 #-DMODBUS_SERIAL_PARAM=SERIAL_8E1
-DAVR_DMXOUT_PIN=18 -DAVR_DMXOUT_PIN=18
-DSYSLOG_ENABLE -DSYSLOG_ENABLE
-DWiz5100 -DWiz5100

View File

@@ -1,5 +1,5 @@
-DWiz5500 -DWiz5500
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1 #-DMODBUS_SERIAL_PARAM=SERIAL_8E1
-DAVR_DMXOUT_PIN=18 -DAVR_DMXOUT_PIN=18
-DSYSLOG_ENABLE -DSYSLOG_ENABLE
#-DPID_DISABLE #-DPID_DISABLE

View File

@@ -1,5 +1,5 @@
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1 #-DMODBUS_SERIAL_PARAM=SERIAL_8E1
#-DAVR_DMXOUT_PIN=18 #-DAVR_DMXOUT_PIN=18
-DDMX_DISABLE -DDMX_DISABLE
-DMODBUS_DISABLE -DMODBUS_DISABLE

View File

@@ -1,9 +1,9 @@
#-DMODBUS_DIMMER_PARAM=SERIAL_8E1 #-DMODBUS_SERIAL_PARAM=SERIAL_8E1
#-DAVR_DMXOUT_PIN=18 #-DAVR_DMXOUT_PIN=18
-DDMX_DISABLE -DDMX_DISABLE
-DMODBUS_DISABLE -DMODBUS_DISABLE
#-DMBUS_DISABLE -DMBUS_DISABLE
#-DOWIRE_DISABLE #-DOWIRE_DISABLE
-DDHT_DISABLE -DDHT_DISABLE
-DCOUNTER_DISABLE -DCOUNTER_DISABLE

Binary file not shown.

View File

@@ -12,6 +12,8 @@ int abstractOut::isActive()
case CMD_VOID: case CMD_VOID:
return 0; return 0;
break; break;
case CMD_ON: //trying (PWM ON set=0 issue)
return 1;
default: default:
st.loadItem(item); st.loadItem(item);
return st.getPercents255(); return st.getPercents255();

View File

@@ -10,6 +10,7 @@ public:
abstractOut(Item * _item):abstractCh(){item=_item;}; abstractOut(Item * _item):abstractCh(){item=_item;};
virtual int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) =0; virtual int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) =0;
virtual int isActive(); virtual int isActive();
virtual bool isAllowed(itemCmd cmd){return true;};
virtual itemCmd getDefaultOnVal(){return itemCmd().Percents255(255);}; virtual itemCmd getDefaultOnVal(){return itemCmd().Percents255(255);};
virtual int getChanType(){return 0;} virtual int getChanType(){return 0;}
virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead

View File

@@ -293,6 +293,19 @@ bool systemConfig::setConfigFlags(systemConfigFlags flags)
return setConfigFlags(flags); return setConfigFlags(flags);
} }
bool systemConfig::getDHCPfallback()
{
systemConfigFlags flags = getConfigFlags();
return flags.dhcpFallback;
}
bool systemConfig::setDHCPfallback(bool flag)
{
systemConfigFlags flags = getConfigFlags();
flags.dhcpFallback=flag;
return setConfigFlags(flags);
}
bool systemConfig::getLoadHTTPConfig() bool systemConfig::getLoadHTTPConfig()
{ {
systemConfigFlags flags = getConfigFlags(); systemConfigFlags flags = getConfigFlags();

View File

@@ -61,6 +61,9 @@ class systemConfig {
bool saveETAG(); bool saveETAG();
bool loadETAG(); bool loadETAG();
bool getDHCPfallback();
bool setDHCPfallback(bool flag);
systemConfigFlags getConfigFlags(); systemConfigFlags getConfigFlags();
bool setConfigFlags(systemConfigFlags flags); bool setConfigFlags(systemConfigFlags flags);

View File

@@ -541,9 +541,9 @@ void setupIpmodbus(){
// Calculate Modbus RTU character timeout and frame delay // Calculate Modbus RTU character timeout and frame delay
byte bits = // number of bits per character (11 in default Modbus RTU settings) byte bits = // number of bits per character (11 in default Modbus RTU settings)
1 + // start bit 1 + // start bit
(((MODBUS_DIMMER_PARAM & 0x06) >> 1) + 5) + // data bits (((MODBUS_SERIAL_PARAM & 0x06) >> 1) + 5) + // data bits
(((MODBUS_DIMMER_PARAM & 0x08) >> 3) + 1); // stop bits (((MODBUS_SERIAL_PARAM & 0x08) >> 3) + 1); // stop bits
if (((MODBUS_DIMMER_PARAM & 0x30) >> 4) > 1) bits += 1; // parity bit (if present) if (((MODBUS_SERIAL_PARAM & 0x30) >> 4) > 1) bits += 1; // parity bit (if present)
//bits = 11; //bits = 11;
int T = ((unsigned long)bits * 1000000UL) / MODBUS_SERIAL_BAUD; // time to send 1 character over serial in microseconds int T = ((unsigned long)bits * 1000000UL) / MODBUS_SERIAL_BAUD; // time to send 1 character over serial in microseconds

View File

@@ -107,7 +107,7 @@ int txt2subItem(char *payload) {
if (!payload || !strlen(payload)) return S_NOTFOUND; if (!payload || !strlen(payload)) return S_NOTFOUND;
// Check for command // Check for command
if (strcmp_P(payload, SET_P) == 0) cmd = S_SET; if (strcmp_P(payload, SET_P) == 0) cmd = S_SET;
//else if (strcmp_P(payload, ESET_P) == 0) cmd = S_ESET; else if (strcmp_P(payload, CTRL_P) == 0) cmd = S_CTRL;
else if (strcmp_P(payload, CMD_P) == 0) cmd = S_CMD; else if (strcmp_P(payload, CMD_P) == 0) cmd = S_CMD;
else if (strcmp_P(payload, MODE_P) == 0) cmd = S_MODE; else if (strcmp_P(payload, MODE_P) == 0) cmd = S_MODE;
else if (strcmp_P(payload, HSV_P) == 0) cmd = S_HSV; else if (strcmp_P(payload, HSV_P) == 0) cmd = S_HSV;
@@ -326,7 +326,7 @@ uint32_t Item::getFlag (uint32_t flag)
aJsonObject *itemCmd = aJson.getArrayItem(itemArr, I_CMD); aJsonObject *itemCmd = aJson.getArrayItem(itemArr, I_CMD);
if (itemCmd && (itemCmd->type == aJson_Int)) if (itemCmd && (itemCmd->type == aJson_Int))
{ {
return itemCmd->valueint & flag & FLAG_MASK; return (uint32_t) itemCmd->valueint & flag & FLAG_MASK;
} }
return 0; return 0;
} }
@@ -572,7 +572,12 @@ long int Item::limitSetValue()
int Item::Ctrl(char * payload, char * subItem) int Item::Ctrl(char * payload, char * subItem)
{ {
if (!payload) return 0; if (!payload) return 0;
int fr = freeRam();
if (fr < minimalMemory)
{
errorSerial<<F("CTRL/txt: OutOfMemory: ")<<fr<<endl;
return -1;
}
int suffixCode = 0; int suffixCode = 0;
@@ -741,51 +746,54 @@ bool digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem)
return false; return false;
} }
//Main routine to control Item
//Return values
// 1 complete
// 3 complete, no action, target reached
// -3 ignored
// -1 system error
// -4 invalid argument
int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
{
uint32_t time=millis(); int Item::isScheduled()
int suffixCode = cmd.getSuffix(); {
bool operation = isNotRetainingStatus(); aJsonObject *timestampObj = aJson.getArrayItem(itemArr, I_TIMESTAMP);
if (timestampObj && (timestampObj->subtype > 0))
if ((!subItem || !strlen(subItem)) && strlen(defaultSubItem)) {
subItem = defaultSubItem; /// possible problem here with truncated default return timestampObj->subtype;
}
return 0;
}
if (!suffixCode && subItem && strlen(subItem)) int Item::scheduleOppositeCommand(itemCmd cmd)
{ {
suffixCode = retrieveCode(&subItem); itemCmd nextCmd=cmd;
if (!cmd.getSuffix()) cmd.setSuffix(suffixCode);
} switch (cmd.getCmd()){
case CMD_XON: nextCmd.Cmd(CMD_XOFF);
break;
case CMD_XOFF: nextCmd.Cmd(CMD_XON);
break;
case CMD_ON: nextCmd.Cmd(CMD_OFF);
break;
case CMD_OFF: nextCmd.Cmd(CMD_ON);
break;
case CMD_ENABLE: nextCmd.Cmd(CMD_DISABLE);
break;
case CMD_DISABLE: nextCmd.Cmd(CMD_ENABLE);
break;
case CMD_FREEZE: nextCmd.Cmd(CMD_UNFREEZE);
break;
case CMD_UNFREEZE: nextCmd.Cmd(CMD_FREEZE);
break;
case CMD_HALT: nextCmd.Cmd(CMD_RESTORE);
break;
case CMD_RESTORE: nextCmd.Cmd(CMD_HALT);
break;
default: return 0;
}
debugSerial<<F("CTRL: Schedule cmd ")<<nextCmd.getCmd()<<F(" for (ms):")<<nextCmd.getInt()<<endl;
scheduleCommand(nextCmd);
return 1;
}
int Item::scheduleCommand(itemCmd cmd)
{
if (!itemArr) return 0;
if (!suffixCode && defaultSuffixCode)
{
suffixCode = defaultSuffixCode;
if (!cmd.getSuffix()) cmd.setSuffix(suffixCode);
}
int fr = freeRam();
debugSerial<<F("RAM=")<<fr<<F(" Item=")<<itemArr->name<<F(" Sub=")<<subItem<<F(" ");
if (fr < 200)
{
errorSerial<<F("OutOfMemory!\n")<<endl;
return -1;
}
cmd.debugOut();
//debugSerial<<endl;
if (subItem && subItem[0] == '$') {debugSerial<<F("Skipped homie stuff")<<endl;return -4; }
if (!itemArr) return -1;
/// DELAYED COMMANDS processing
if (suffixCode == S_DELAYED)
{
for (int i = aJson.getArraySize(itemArr); i <= I_TIMESTAMP; i++) for (int i = aJson.getArraySize(itemArr); i <= I_TIMESTAMP; i++)
aJson.addItemToArray(itemArr, aJson.createNull()); aJson.addItemToArray(itemArr, aJson.createNull());
@@ -807,6 +815,56 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
return 1; return 1;
} }
return 0; return 0;
}
//Main routine to control Item
//Return values
// 1 complete
// 3 complete, no action, target reached
// -3 ignored
// -1 system error
// -4 invalid argument
int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
{
int fr = freeRam();
if (fr < minimalMemory)
{
errorSerial<<F("CTRL: OutOfMemory: ")<<fr<<endl;
return -1;
}
{
uint32_t time=millis();
int suffixCode = cmd.getSuffix();
bool operation = isNotRetainingStatus();
if ((!subItem || !strlen(subItem)) && strlen(defaultSubItem))
subItem = defaultSubItem; /// possible problem here with truncated default
if (!suffixCode && subItem && strlen(subItem))
{
suffixCode = retrieveCode(&subItem);
if (!cmd.getSuffix()) cmd.setSuffix(suffixCode);
}
if (!suffixCode && defaultSuffixCode)
{
suffixCode = defaultSuffixCode;
if (!cmd.getSuffix()) cmd.setSuffix(suffixCode);
}
debugSerial<<F("CTRL: RAM=")<<fr<<F(" Item=")<<itemArr->name<<F(" Sub=")<<subItem<<F(" ");
cmd.debugOut();
//debugSerial<<endl;
if (subItem && subItem[0] == '$') {debugSerial<<F("Skipped homie stuff")<<endl;return -4; }
if (!itemArr) return -1;
/// DELAYED COMMANDS processing
if (suffixCode == S_DELAYED)
{
return scheduleCommand(cmd);
} }
/// ///
int8_t chActive = -1; int8_t chActive = -1;
@@ -827,6 +885,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
switch (suffixCode) switch (suffixCode)
{ {
case S_NOTFOUND: //For empty (universal) OPENHAB suffix - turn ON/OFF automatically case S_NOTFOUND: //For empty (universal) OPENHAB suffix - turn ON/OFF automatically
if (subItem) {debugSerial<<F("CTRL: Unknown suffix")<<endl; break;}; // if some unknown suffix
toExecute=true; toExecute=true;
scale100=true; //openHab topic format scale100=true; //openHab topic format
chActive=(isActive()>0); chActive=(isActive()>0);
@@ -950,11 +1009,12 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
{ {
if (fr<350) if (fr<350)
{ {
errorSerial<<F("Not enough memory for group operation")<<endl; errorSerial<<F("CTRL: Not enough memory for group operation")<<endl;
return -1; return -1;
} }
if (allowRecursion && itemArg->type == aJson_Array && operation) if (allowRecursion && itemArg->type == aJson_Array && operation)
{ {
chActive=(isActive()>0);
digGroup(itemArg,&cmd,subItem); digGroup(itemArg,&cmd,subItem);
} }
res=1; res=1;
@@ -965,7 +1025,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_RESTORE: // individual for group members case CMD_RESTORE: // individual for group members
switch (t = getCmd()) { switch (t = getCmd()) {
case CMD_HALT: //previous command was HALT ? case CMD_HALT: //previous command was HALT ?
debugSerial << F("Restored from:") << t << endl; if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd);
debugSerial << F("CTRL: Restored from:") << t << endl;
cmd.loadItemDef(this); cmd.loadItemDef(this);
cmd.Cmd(CMD_ON); //turning on cmd.Cmd(CMD_ON); //turning on
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE; status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
@@ -978,20 +1039,30 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_XOFF: // individual for group members case CMD_XOFF: // individual for group members
switch (t = getCmd()) { switch (t = getCmd()) {
case CMD_XON: //previous command was CMD_XON ? case CMD_XON: //previous command was CMD_XON ?
debugSerial << F("Turned off from:") << t << endl; if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd);
debugSerial << F("CTRL: Turned off from:") << t << endl;
cmd.Cmd(CMD_OFF); //turning Off cmd.Cmd(CMD_OFF); //turning Off
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE; status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
break; break;
default: default:
debugSerial << F("XOFF skipped. Prev cmd:") << t <<endl; debugSerial << F("CTRL: XOFF skipped. Prev cmd:") << t <<endl;
return 3; return 3;
} }
break; break;
case CMD_XON: case CMD_XON:
chActive=(isActive()>0);
if (!getFlag(FLAG_DISABLED))
{
if (chActive == -1) chActive=(isActive()>0);
if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd);
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;
@@ -999,13 +1070,21 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
} }
else else
{ {
debugSerial<<F("XON:Already Active\n"); debugSerial<<F("CTRL: XON:Already Active\n");
return 3; return 3;
} }
}
else
{
debugSerial<<F("CTRL: XON: Disabled\n");
return 3;
}
break; break;
case CMD_HALT: case CMD_HALT:
chActive=(isActive()>0); if (chActive == -1) chActive=(isActive()>0);
if (chActive) //if channel was active before CMD_HALT if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd);
if (chActive) //if channel was active before CMD_HALT /// HERE bug - if cmd == On but 0 = active
{ {
cmd.Cmd(CMD_OFF); cmd.Cmd(CMD_OFF);
command2Set=CMD_HALT; command2Set=CMD_HALT;
@@ -1013,7 +1092,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
} }
else else
{ {
debugSerial<<F("HALT:Already Inactive\n"); debugSerial<<F("CTRL: HALT:Already Inactive\n");
return 3; return 3;
} }
break; break;
@@ -1028,7 +1107,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
{ // NON GROUP part { // NON GROUP part
if (chActive<0) chActive = (isActive()>0); if (chActive<0) chActive = (isActive()>0);
toExecute=chActive || toExecute; // Execute if active toExecute=chActive || toExecute; // Execute if active
debugSerial<<F("Active:")<<chActive<<F( " Exec:")<<toExecute<<endl; debugSerial<<F("CTRL: Active:")<<chActive<<F( " Exec:")<<toExecute<<endl;
if (subItem) if (subItem)
{ {
//Check if subitem is some sort of command //Check if subitem is some sort of command
@@ -1040,7 +1119,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
{ {
if (subitemCmd != prevCmd) if (subitemCmd != prevCmd)
{ {
debugSerial<<F("Ignored, channel cmd=")<<prevCmd<<endl; debugSerial<<F("CTRL: Ignored, channel cmd=")<<prevCmd<<endl;
return -3; return -3;
} }
subItem=NULL; subItem=NULL;
@@ -1059,7 +1138,10 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_RESTORE: // individual for group members case CMD_RESTORE: // individual for group members
switch (t = getCmd()) { switch (t = getCmd()) {
case CMD_HALT: //previous command was HALT ? case CMD_HALT: //previous command was HALT ?
debugSerial << F("Restored from:") << t << endl; if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
debugSerial << F("CTRL: Restored from:") << t << endl;
cmd.loadItemDef(this); cmd.loadItemDef(this);
toExecute=true; toExecute=true;
if (itemType == CH_THERMO) cmd.Cmd(CMD_AUTO); //// if (itemType == CH_THERMO) cmd.Cmd(CMD_AUTO); ////
@@ -1074,33 +1156,52 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_XOFF: // individual for group members case CMD_XOFF: // individual for group members
switch (t = getCmd()) { switch (t = getCmd()) {
case CMD_XON: //previous command was CMD_XON ? case CMD_XON: //previous command was CMD_XON ?
debugSerial << F("Turned off from:") << t << endl; if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
debugSerial << F("CTRL: Turned off from:") << t << endl;
toExecute=true; toExecute=true;
cmd.Cmd(CMD_OFF); //turning Off cmd.Cmd(CMD_OFF); //turning Off
clearFlag(FLAG_XON);
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE; status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
break; break;
default: default:
debugSerial << F("XOFF skipped. Prev cmd:") << t <<endl; debugSerial << F("CTRL: XOFF skipped. Prev cmd:") << t <<endl;
return 3; return 3;
} }
break; break;
case CMD_XON: case CMD_XON:
if (!chActive) //if channel was'nt active before CMD_XON if (!getFlag(FLAG_DISABLED))
{ {
cmd.loadItemDef(this); if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
cmd.Cmd(CMD_ON); scheduleOppositeCommand(cmd);
command2Set=CMD_XON;
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE; if (!chActive) //if channel was'nt active before CMD_XON
toExecute=true; {
}
else cmd.loadItemDef(this);
{ cmd.Cmd(CMD_ON);
debugSerial<<F("XON:Already Active\n"); command2Set=CMD_XON;
return 3; setFlag(FLAG_XON);
} status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
toExecute=true;
}
else
{
debugSerial<<F("CTRL: XON:Already Active\n");
return 3;
}
}
else
{
debugSerial<<F("CTRL: XON: Disabled\n");
return 3;
}
break; break;
case CMD_HALT: case CMD_HALT:
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
if (chActive) //if channel was active before CMD_HALT if (chActive) //if channel was active before CMD_HALT
{ {
cmd.Cmd(CMD_OFF); cmd.Cmd(CMD_OFF);
@@ -1110,7 +1211,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
} }
else else
{ {
debugSerial<<F("HALT:Already Inactive\n"); debugSerial<<F("CTRL: HALT:Already Inactive\n");
return 3; return 3;
} }
break; break;
@@ -1123,11 +1224,18 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
} }
if (getCmd() == CMD_HALT) return 3; //Halted, ignore OFF if (getCmd() == CMD_HALT) return 3; //Halted, ignore OFF
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE; status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
toExecute=true; toExecute=true;
break; break;
case CMD_ON: case CMD_ON:
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
if (!cmd.isChannelCommand()) //Command for driver, not for whole channel if (!cmd.isChannelCommand()) //Command for driver, not for whole channel
{ {
toExecute=true; toExecute=true;
@@ -1135,7 +1243,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
} }
if (chActive) if (chActive)
{ {
debugSerial<<F("ON:Already Active\n"); debugSerial<<F("CTRL: ON:Already Active\n");
setCmd(CMD_ON); setCmd(CMD_ON);
SendStatus(FLAG_COMMAND | FLAG_SEND_DEFFERED); SendStatus(FLAG_COMMAND | FLAG_SEND_DEFFERED);
return 3; return 3;
@@ -1163,6 +1271,43 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_UP: case CMD_UP:
break; break;
case CMD_ENABLE:
//clearFlag(FLAG_DISABLED); //saveItem have this
status2Send |= FLAG_FLAGS;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if (allowRecursion && cmd.isValue() && (getFlag(FLAG_DISABLED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
break;
case CMD_DISABLE:
//setFlag(FLAG_DISABLED); //saveItem have this
status2Send |= FLAG_FLAGS;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!getFlag(FLAG_DISABLED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
break;
case CMD_UNFREEZE:
//clearFlag(FLAG_DISABLED); //saveItem have this
status2Send = FLAG_FLAGS;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (getFlag(FLAG_FREEZED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
break;
case CMD_FREEZE:
//setFlag(FLAG_DISABLED); //saveItem have this
status2Send = FLAG_FLAGS;
command2Set = 0;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!getFlag(FLAG_FREEZED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd);
break;
default: default:
if (cmd.isCommand()) status2Send |= FLAG_COMMAND; if (cmd.isCommand()) status2Send |= FLAG_COMMAND;
if (cmd.isValue()) status2Send |= FLAG_PARAMETERS; if (cmd.isValue()) status2Send |= FLAG_PARAMETERS;
@@ -1170,110 +1315,145 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
} //Switch commands } //Switch commands
} // NO GROUP } // NO GROUP
if (invalidArgument) return -4; if (invalidArgument) return -4;
// UPDATE internal variables
if (status2Send) cmd.saveItem(this,status2Send);
//debugSerial<<F("sts:")<<status2Send<<endl;
if (driver) //New style modular code if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
{
res = driver->Ctrl(cmd, subItem, toExecute);
if (driver->getChanType() == CH_THERMO) status2Send |= FLAG_SEND_IMMEDIATE;
//if (res==-1) status2Send=0; ///////not working
}
else
{ {
switch (itemType) { // UPDATE internal variables
/// rest of Legacy monolite core code (to be refactored ) BEGIN /// if (status2Send) cmd.saveItem(this,status2Send);
case CH_RELAY: //debugSerial<<F("sts:")<<status2Send<<endl;
{
short iaddr=getArg();
short icmd =cmd.getCmd();
if (iaddr) if (driver) //New style modular code
{ {
int k; res = driver->Ctrl(cmd, subItem, toExecute);
short inverse = 0; if (driver->getChanType() == CH_THERMO) status2Send |= FLAG_SEND_IMMEDIATE;
//if (res==-1) status2Send=0; ///////not working
if (iaddr < 0) { if (status2Send & FLAG_FLAGS) res =1; //ENABLE & DISABLE processed by core
iaddr = -iaddr; }
inverse = 1; else
} {
if (iaddr <= (short) PINS_COUNT && iaddr>0) switch (itemType) {
{ /// rest of Legacy monolite core code (to be refactored ) BEGIN ///
pinMode(iaddr, OUTPUT); case CH_RELAY:
if (cmd.isCommand())
if (inverse)
digitalWrite(iaddr, k = ((icmd == CMD_ON || icmd == CMD_AUTO) ? LOW : HIGH));
else
digitalWrite(iaddr, k = ((icmd == CMD_ON || icmd == CMD_AUTO) ? HIGH : LOW));
debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<endl;
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
res=1;
}
}
break;
}
case CH_THERMO:
switch (suffixCode)
{
case S_VAL:
//S_NOTFOUND:
{
thermostatStore tStore;
tStore.asint=getExt();
if (!tStore.timestamp16) mqttClient.publish("/alarmoff/snsr", itemArr->name);
tStore.tempX100=cmd.getFloat()*100.; //Save measurement
tStore.timestamp16=millisNZ(8) & 0xFFFF; //And timestamp
debugSerial<<F(" T:")<<tStore.tempX100<<F(" TS:")<<tStore.timestamp16<<endl;
setExt(tStore.asint);
res=1;
}
break;
case S_SET:
status2Send |= FLAG_PARAMETERS | FLAG_SEND_IMMEDIATE;
res=1;
//st.saveItem(this);
break;
case S_CMD:
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
res=1;
}
break;
#ifndef MODBUS_DISABLE
case CH_MODBUS:
if (toExecute && !(chActive && cmd.getCmd()==CMD_ON && !cmd.isValue()))
{ {
int vol;
if (!chActive && cmd.getCmd()== CMD_ON && (vol=cmd.getPercents())<MIN_VOLUME && vol>=0)
short iaddr=getArg();
short icmd =cmd.getCmd();
if (iaddr)
{
int k;
short inverse = 0;
if (iaddr < 0) {
iaddr = -iaddr;
inverse = 1;
}
if (iaddr <= (short) PINS_COUNT && iaddr>0)
{ {
cmd.setPercents(INIT_VOLUME); pinMode(iaddr, OUTPUT);
status2Send |= FLAG_PARAMETERS | FLAG_SEND_IMMEDIATE;
};
res=modbusDimmerSet(cmd); switch (icmd){
case CMD_AUTO:
case CMD_COOL:
case CMD_ON:
case CMD_DRY:
case CMD_FAN:
case CMD_XON:
digitalWrite(iaddr, k = (inverse) ? LOW : HIGH);
break;
case CMD_OFF:
case CMD_HALT:
case CMD_XOFF:
digitalWrite(iaddr, k = (inverse) ? HIGH : LOW);
}
/*
if (inverse)
digitalWrite(iaddr, k = ((icmd == CMD_ON || icmd == CMD_AUTO) ? LOW : HIGH));
else
digitalWrite(iaddr, k = ((icmd == CMD_ON || icmd == CMD_AUTO) ? HIGH : LOW));
*/
debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<endl;
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
res=1;
}
}
break;
} }
break;
case CH_VC:
if (toExecute && !(chActive && cmd.getCmd()==CMD_ON && !cmd.isValue())) res=VacomSetFan(cmd);
break;
case CH_VCTEMP:
if (toExecute && !(chActive && cmd.getCmd()==CMD_ON && !cmd.isValue())) res=VacomSetHeat(cmd);
break;
#endif
/// rest of Legacy monolite core code (to be refactored ) END ///
} //switch case CH_THERMO:
} //else (nodriver) switch (suffixCode)
{
case S_VAL:
//S_NOTFOUND:
{
thermostatStore tStore;
tStore.asint=getExt();
if (!tStore.timestamp16) mqttClient.publish("/alarmoff/snsr", itemArr->name);
tStore.tempX100=cmd.getFloat()*100.; //Save measurement
tStore.timestamp16=millisNZ(8) & 0xFFFF; //And timestamp
debugSerial<<F(" T:")<<tStore.tempX100<<F(" TS:")<<tStore.timestamp16<<endl;
setExt(tStore.asint);
res=1;
}
break;
case S_SET:
status2Send |= FLAG_PARAMETERS | FLAG_SEND_IMMEDIATE;
res=1;
//st.saveItem(this);
break;
case S_CMD:
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
res=1;
}
break;
//update command for HALT & XON and send MQTT status
if (command2Set) setCmd(command2Set | FLAG_COMMAND);
if (operation) SendStatus(status2Send);
debugSerial<<F("Ctrl Res:")<<res<<F(" time:")<<millis()-time<<endl; #ifndef MODBUS_DISABLE
case CH_MODBUS:
if (toExecute && !(chActive && cmd.getCmd()==CMD_ON && !cmd.isValue()))
{
int vol;
if (!chActive && cmd.getCmd()== CMD_ON && (vol=cmd.getPercents())<MIN_VOLUME && vol>=0)
{
cmd.setPercents(INIT_VOLUME);
status2Send |= FLAG_PARAMETERS | FLAG_SEND_IMMEDIATE;
};
res=modbusDimmerSet(cmd);
}
break;
case CH_VC:
if (toExecute && !(chActive && cmd.getCmd()==CMD_ON && !cmd.isValue())) res=VacomSetFan(cmd);
break;
case CH_VCTEMP:
if (toExecute && !(chActive && cmd.getCmd()==CMD_ON && !cmd.isValue())) res=VacomSetHeat(cmd);
break;
#endif
/// rest of Legacy monolite core code (to be refactored ) END ///
} //switch
} //else (nodriver)
//update command for HALT & XON and send MQTT status
if (command2Set) setCmd(command2Set | FLAG_COMMAND);
if (operation) SendStatus(status2Send);
} //alowed cmd
else
{
errorSerial<<F("CTRL: Command blocked by driver or channel frozen")<<endl;
if ((status2Send & FLAG_FLAGS) && operation)
{
cmd.saveItem(this,FLAG_FLAGS);
SendStatus(FLAG_FLAGS);
}
}
debugSerial<<F("CTRL: Res:")<<res<<F(" time:")<<millis()-time<<endl;
return res; return res;
}
} }
void printActiveStatus(bool active) void printActiveStatus(bool active)
@@ -1379,7 +1559,15 @@ if (timestampObj)
if (remain <0 && abs(remain)< 0xFFFFFFFFUL/2) if (remain <0 && abs(remain)< 0xFFFFFFFFUL/2)
{ {
SendStatusImmediate(st,FLAG_SEND_DELAYED); int fr = freeRam();
SendStatusImmediate(st,FLAG_SEND_DELAYED);
if (fr < minimalMemory)
{
errorSerial<<F("CTRL/poll: OutOfMemory: ")<<fr<<endl;
return -1;
}
Ctrl(itemCmd(ST_VOID,cmd)); Ctrl(itemCmd(ST_VOID,cmd));
timestampObj->subtype=0; timestampObj->subtype=0;
} }
@@ -1430,7 +1618,7 @@ void Item::sendDelayedStatus()
int Item::SendStatus(int sendFlags) { int Item::SendStatus(int sendFlags) {
if (sendFlags & FLAG_SEND_IMMEDIATE) sendFlags &= ~ (FLAG_SEND_IMMEDIATE | FLAG_SEND_DEFFERED); if (sendFlags & FLAG_SEND_IMMEDIATE) sendFlags &= ~ (FLAG_SEND_IMMEDIATE | FLAG_SEND_DEFFERED);
if ((sendFlags & FLAG_SEND_DEFFERED) || freeRam()<150 || (!isNotRetainingStatus() )) { if ((sendFlags & FLAG_SEND_DEFFERED) || freeRam()<150 || (!isNotRetainingStatus() )) {
setFlag(sendFlags & (FLAG_COMMAND | FLAG_PARAMETERS)); setFlag(sendFlags & (FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS));
debugSerial<<F("Status deffered\n"); debugSerial<<F("Status deffered\n");
return -1; return -1;
} }
@@ -1438,7 +1626,7 @@ int Item::SendStatus(int sendFlags) {
{ {
itemCmd st(ST_VOID,CMD_VOID); itemCmd st(ST_VOID,CMD_VOID);
st.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS); st.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS);
sendFlags |= getFlag(FLAG_COMMAND | FLAG_PARAMETERS); //if some delayed status is pending sendFlags |= getFlag(FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS); //if some delayed status is pending
//debugSerial<<F("ssi:")<<sendFlags<<endl; //debugSerial<<F("ssi:")<<sendFlags<<endl;
return SendStatusImmediate(st,sendFlags); return SendStatusImmediate(st,sendFlags);
} }
@@ -1462,10 +1650,11 @@ int Item::SendStatus(int sendFlags) {
case CMD_COOL: case CMD_COOL:
case CMD_DRY: case CMD_DRY:
case CMD_FAN: case CMD_FAN:
case CMD_ENABLE:
case CMD_DISABLE:
strcpy_P(cmdstr, ON_P); strcpy_P(cmdstr, ON_P);
break; break;
//case CMD_ENABLE:
//case CMD_DISABLE:
// break;
case CMD_OFF: case CMD_OFF:
case CMD_HALT: case CMD_HALT:
strcpy_P(cmdstr, OFF_P); strcpy_P(cmdstr, OFF_P);
@@ -1487,7 +1676,7 @@ int Item::SendStatus(int sendFlags) {
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
{ {
if (!subItem) if (!subItem )
{ {
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);
@@ -1501,7 +1690,7 @@ int Item::SendStatus(int sendFlags) {
mqttClient.publish(addrstr, valstr, true); mqttClient.publish(addrstr, valstr, true);
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl; debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl;
} }
else if (sendFlags & FLAG_COMMAND) else if ((sendFlags & FLAG_COMMAND) && (strlen(cmdstr)))
{ {
mqttClient.publish(addrstr, cmdstr, true); mqttClient.publish(addrstr, cmdstr, true);
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl; debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
@@ -1584,12 +1773,12 @@ int Item::SendStatus(int sendFlags) {
case CMD_FAN: case CMD_FAN:
strcpy_P(cmdstr, FAN_ONLY_P); strcpy_P(cmdstr, FAN_ONLY_P);
break; break;
case CMD_ENABLE: //case CMD_ENABLE:
strcpy_P(cmdstr, ENABLE_P); // strcpy_P(cmdstr, ENABLE_P);
break; // break;
case CMD_DISABLE: //case CMD_DISABLE:
strcpy_P(cmdstr, DISABLE_P); // strcpy_P(cmdstr, DISABLE_P);
break; // break;
case CMD_ON: case CMD_ON:
case CMD_XON: case CMD_XON:
if (itemType == CH_THERMO) strcpy_P(cmdstr, AUTO_P); if (itemType == CH_THERMO) strcpy_P(cmdstr, AUTO_P);
@@ -1617,6 +1806,43 @@ int Item::SendStatus(int sendFlags) {
return 0; return 0;
} }
} }
// Send ctrl
if (sendFlags & FLAG_FLAGS)
{
if (getFlag(FLAG_DISABLED))
strcpy_P(cmdstr, DISABLE_P);
else if (getFlag(FLAG_FREEZED))
strcpy_P(cmdstr, FREEZE_P);
else strcpy_P(cmdstr, ENABLE_P);
//else strcpy_P(cmdstr, UNFREEZE_P);
setTopic(addrstr,sizeof(addrstr),T_OUT);
strncat(addrstr, itemArr->name, sizeof(addrstr)-1);
if (subItem)
{
strncat(addrstr, "/", sizeof(addrstr)-1);
strncat(addrstr, subItem, sizeof(addrstr)-1);
}
strncat(addrstr, "/", sizeof(addrstr)-1);
strncat_P(addrstr, CTRL_P, sizeof(addrstr)-1);
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
if (mqttClient.connected() && !ethernetIdleCount)
{
mqttClient.publish(addrstr, cmdstr,true);
clearFlag(FLAG_FLAGS);
}
else
{
setFlag(sendFlags);
return 0;
}
}
return 1; return 1;
} }
} }
@@ -1821,7 +2047,7 @@ int Item::VacomSetFan(itemCmd st) {
//uint8_t j;//, result; //uint8_t j;//, result;
//uint16_t data[1]; //uint16_t data[1];
modbusSerial.begin(9600, fmPar); modbusSerial.begin(MODBUS_FM_BAUD, MODBUS_FM_PARAM);
node.begin(addr, modbusSerial); node.begin(addr, modbusSerial);
if (val) { if (val) {
@@ -1866,7 +2092,7 @@ int addr;
} }
modbusBusy = 1; modbusBusy = 1;
modbusSerial.begin(9600, fmPar); modbusSerial.begin(MODBUS_FM_BAUD, MODBUS_FM_PARAM);
node.begin(addr, modbusSerial); node.begin(addr, modbusSerial);
uint16_t regval; uint16_t regval;
@@ -1903,7 +2129,7 @@ int Item::modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint
}; };
modbusBusy = 1; modbusBusy = 1;
modbusSerial.begin(MODBUS_SERIAL_BAUD, dimPar); modbusSerial.begin(MODBUS_SERIAL_BAUD, MODBUS_SERIAL_PARAM);
node.begin(addr, modbusSerial); node.begin(addr, modbusSerial);
uint8_t t; uint8_t t;
switch (_mask) { switch (_mask) {
@@ -1971,7 +2197,7 @@ int Item::checkFM() {
// aJson.addStringToObject(out,"type", "rect"); // aJson.addStringToObject(out,"type", "rect");
modbusSerial.begin(9600, fmPar); modbusSerial.begin(MODBUS_FM_BAUD, MODBUS_FM_PARAM);
node.begin(getArg(), modbusSerial); node.begin(getArg(), modbusSerial);
@@ -2090,7 +2316,7 @@ int Item::checkModbusDimmer() {
//node.setSlave(addr); //node.setSlave(addr);
modbusSerial.begin(MODBUS_SERIAL_BAUD, dimPar); modbusSerial.begin(MODBUS_SERIAL_BAUD, MODBUS_SERIAL_PARAM);
node.begin(addr, modbusSerial); node.begin(addr, modbusSerial);
switch (_regType) { switch (_regType) {

View File

@@ -149,6 +149,7 @@ class Item
inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));}; inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));};
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));}; inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
int scheduleCommand(itemCmd cmd); int scheduleCommand(itemCmd cmd);
int scheduleOppositeCommand(itemCmd cmd);
int isScheduled(); int isScheduled();
protected: protected:

View File

@@ -108,6 +108,7 @@ uint8_t itemCmd::getStoragetypeByChanType(short chanType)
case CH_PWM: case CH_PWM:
case CH_VC: case CH_VC:
case CH_MODBUS: case CH_MODBUS:
//case CH_RELAY:
//case CH_GROUP: //case CH_GROUP:
return ST_PERCENTS255; return ST_PERCENTS255;
break; break;
@@ -1115,13 +1116,23 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
case CMD_ENABLE: case CMD_ENABLE:
item->clearFlag(FLAG_DISABLED); item->clearFlag(FLAG_DISABLED);
item->clearFlag(FLAG_FREEZED);
break; break;
case CMD_FREEZE:
item->setFlag(FLAG_FREEZED);
break;
case CMD_UNFREEZE:
item->clearFlag(FLAG_FREEZED);
break;
} }
if (optionsFlag & FLAG_COMMAND) if (optionsFlag & FLAG_COMMAND)
switch (cmd.cmdCode) switch (cmd.cmdCode)
{ {
case CMD_DISABLE: case CMD_DISABLE:
case CMD_ENABLE: case CMD_ENABLE:
case CMD_FREEZE:
case CMD_UNFREEZE:
break; break;
default: default:
item->setCmd(cmd.cmdCode); item->setCmd(cmd.cmdCode);

View File

@@ -26,8 +26,10 @@ typedef char cmdstr[9];
const cmdstr commands_P[] PROGMEM = const cmdstr commands_P[] PROGMEM =
{ {
"","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE", "","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE",
"HEAT","COOL","AUTO","FAN_ONLY","DRY","STOP","HIGH","MEDIUM","LOW","ENABLE","DISABLE", "ENABLE","DISABLE","UNFREEZE","FREEZE",
"TRUE","FALSE","RGB","HSV" "AUTO","FAN_ONLY",
"HIGH","MEDIUM","LOW",
"HEAT","COOL","DRY","STOP","RGB","HSV"
}; };
#define commandsNum sizeof(commands_P)/sizeof(cmdstr) #define commandsNum sizeof(commands_P)/sizeof(cmdstr)
@@ -41,20 +43,24 @@ const cmdstr commands_P[] PROGMEM =
#define CMD_XOFF 7 /// OFF only if was previously turned on by CMD_XON #define CMD_XOFF 7 /// OFF only if was previously turned on by CMD_XON
#define CMD_UP 8 /// increase #define CMD_UP 8 /// increase
#define CMD_DN 9 /// decrease #define CMD_DN 9 /// decrease
#define CMD_HEAT 0xa /// Thermostat/AC set to HEATing mode
#define CMD_COOL 0xb /// Thermostat/AC set to COOLing mode #define CMD_ENABLE 0xa /// for PID regulator and XON/XOFF - chan limitation
#define CMD_AUTO 0xc /// Thermostat/AC set to Auto mode #define CMD_DISABLE 0xb /// for PID regulator
#define CMD_FAN 0xd /// AC set to Fan-only mode #define CMD_UNFREEZE 0xc /// Aliase for ON
#define CMD_DRY 0xe /// AC set to Dry mode #define CMD_FREEZE 0xd /// Aliase for OFF
#define CMD_STOP 0xf /// stop dimming (for further use)
#define CMD_AUTO 0xe /// Thermostat/AC set to Auto mode
#define CMD_FAN 0xf /// AC set to Fan-only mode
#define CMD_HIGH 0x10 /// AC/Vent fan level HIGH #define CMD_HIGH 0x10 /// AC/Vent fan level HIGH
#define CMD_MED 0x11 /// AC/Vent fan level MEDIUM #define CMD_MED 0x11 /// AC/Vent fan level MEDIUM
#define CMD_LOW 0x12 /// AC/Vent fan level LOW #define CMD_LOW 0x12 /// AC/Vent fan level LOW
#define CMD_ENABLE 0x13 /// for PID regulator
#define CMD_DISABLE 0x14 /// for PID regulator #define CMD_HEAT 0x13 /// Thermostat/AC set to HEATing mode
#define CMD_TRUE 0x15 /// Aliase for ON #define CMD_COOL 0x14 /// Thermostat/AC set to COOLing mode
#define CMD_FALSE 0x16 /// Aliase for OFF #define CMD_DRY 0x15 /// AC set to Dry mode
#define CMD_STOP 0x16 /// stop dimming (for further use)
#define CMD_RGB 0x17 #define CMD_RGB 0x17
#define CMD_HSV 0x18 #define CMD_HSV 0x18
@@ -78,7 +84,7 @@ const cmdstr commands_P[] PROGMEM =
#define FLAG_ACTION_IN_PROCESS 0x8000UL #define FLAG_ACTION_IN_PROCESS 0x8000UL
#define FLAG_DISABLED 0x10000UL #define FLAG_DISABLED 0x10000UL
#define FLAG_DISABLED_ALL 0x20000UL #define FLAG_FREEZED 0x20000UL
#define FLAG_HALTED 0x40000UL #define FLAG_HALTED 0x40000UL
#define FLAG_XON 0x80000UL #define FLAG_XON 0x80000UL

View File

@@ -39,8 +39,8 @@ e-mail anklimov@gmail.com
Syslog udpSyslog(udpSyslogClient, SYSLOG_PROTO_BSD); Syslog udpSyslog(udpSyslogClient, SYSLOG_PROTO_BSD);
static char syslogDeviceHostname[16]; static char syslogDeviceHostname[16];
#if defined(debugSerialPort) #if defined(debugSerialPort) && !defined(NOSERIAL)
Streamlog debugSerial(&debugSerialPort,LOG_DEBUG,&udpSyslog); Streamlog debugSerial(&debugSerialPort,LOG_DEBUG,&udpSyslog);
Streamlog errorSerial(&debugSerialPort,LOG_ERROR,&udpSyslog,ledRED); Streamlog errorSerial(&debugSerialPort,LOG_ERROR,&udpSyslog,ledRED);
Streamlog infoSerial (&debugSerialPort,LOG_INFO,&udpSyslog); Streamlog infoSerial (&debugSerialPort,LOG_INFO,&udpSyslog);
#else #else
@@ -50,7 +50,7 @@ static char syslogDeviceHostname[16];
#endif #endif
#else #else
#if defined(debugSerialPort) #if defined(debugSerialPort) && !defined(NOSERIAL)
Streamlog debugSerial(&debugSerialPort,LOG_DEBUG); Streamlog debugSerial(&debugSerialPort,LOG_DEBUG);
Streamlog errorSerial(&debugSerialPort,LOG_ERROR, ledRED); Streamlog errorSerial(&debugSerialPort,LOG_ERROR, ledRED);
Streamlog infoSerial (&debugSerialPort,LOG_INFO); Streamlog infoSerial (&debugSerialPort,LOG_INFO);
@@ -139,6 +139,7 @@ bool owReady = false;
bool configOk = false; // At least once connected to MQTT bool configOk = false; // At least once connected to MQTT
bool configLoaded = false; bool configLoaded = false;
bool initializedListeners = false; bool initializedListeners = false;
uint8_t DHCP_failures = 0;
volatile int8_t ethernetIdleCount =0; volatile int8_t ethernetIdleCount =0;
volatile int8_t configLocked = 0; volatile int8_t configLocked = 0;
@@ -762,7 +763,8 @@ lan_status lanLoop() {
wdt_dis(); wdt_dis();
if (lanStatus >= HAVE_IP_ADDRESS) if (lanStatus >= HAVE_IP_ADDRESS)
{ {
int etherStatus = Ethernet.maintain(); int etherStatus = 0;
if (!DHCP_failures) etherStatus = Ethernet.maintain();
#ifndef Wiz5500 #ifndef Wiz5500
#define NO_LINK 5 #define NO_LINK 5
@@ -1108,7 +1110,11 @@ if (WiFi.status() == WL_CONNECTED) {
IPAddress ip, dns, gw, mask; IPAddress ip, dns, gw, mask;
int res = 1; int res = 1;
infoSerial<<F("Starting lan")<<endl; infoSerial<<F("Starting lan")<<endl;
if (sysConf.getIP(ip)) { bool loadAddressRes = sysConf.getIP(ip);
if ( loadAddressRes &&
(!sysConf.getDHCPfallback() || (DHCP_failures >= DHCP_ATTEMPTS_FALLBACK))
)
{
infoSerial<<F("Loaded from flash IP:"); infoSerial<<F("Loaded from flash IP:");
printIPAddress(ip); printIPAddress(ip);
if (sysConf.getDNS(dns)) { if (sysConf.getDNS(dns)) {
@@ -1142,6 +1148,7 @@ if (WiFi.status() == WL_CONNECTED) {
if (res == 0) { if (res == 0) {
errorSerial<<F("Failed to configure Ethernet using DHCP. You can set ip manually!")<<F("'ip [ip[,dns[,gw[,subnet]]]]' - set static IP\n"); errorSerial<<F("Failed to configure Ethernet using DHCP. You can set ip manually!")<<F("'ip [ip[,dns[,gw[,subnet]]]]' - set static IP\n");
DHCP_failures++;
lanStatus = DO_REINIT;//-10; lanStatus = DO_REINIT;//-10;
//timerLanCheckTime = millis();// + DHCP_RETRY_INTERVAL; //timerLanCheckTime = millis();// + DHCP_RETRY_INTERVAL;
#ifdef RESET_PIN #ifdef RESET_PIN
@@ -1149,8 +1156,25 @@ if (WiFi.status() == WL_CONNECTED) {
#endif #endif
} else { } else {
infoSerial<<F("Got IP address:"); infoSerial<<F("Got IP address:");
printIPAddress(Ethernet.localIP()); ip=Ethernet.localIP();
printIPAddress(ip);
infoSerial<<endl; infoSerial<<endl;
sysConf.setIP(ip);
dns=Ethernet.dnsServerIP();
sysConf.setDNS(dns);
gw=Ethernet.gatewayIP();
sysConf.setGW(gw);
mask=Ethernet.subnetMask();
sysConf.setMask(mask);
sysConf.setDHCPfallback(true);
DHCP_failures = 0;
lanStatus = HAVE_IP_ADDRESS; lanStatus = HAVE_IP_ADDRESS;
} }
}//DHCP }//DHCP
@@ -1608,6 +1632,7 @@ int cmdFunctionIp(int arg_cnt, char **args)
printIPAddress(current_mask); */ printIPAddress(current_mask); */
//} //}
infoSerial<<F("Saved\n"); infoSerial<<F("Saved\n");
sysConf.setDHCPfallback(false);
return 200; return 200;
} }
@@ -1757,7 +1782,7 @@ if (!sysConf.getServer(configServer,sizeof(configServer)))
// FILE is the return STREAM type of the HTTPClient // FILE is the return STREAM type of the HTTPClient
configStream = hclient.getURI(URI,NULL,get_header); configStream = hclient.getURI(URI,NULL,get_header);
responseStatusCode = hclient.getLastReturnCode(); responseStatusCode = hclient.getLastReturnCode();
//debugSerial<<F("http retcode ")<<responseStatusCode<<endl;delay(100); debugSerial<<F("http retcode ")<<responseStatusCode<<endl;delay(100);
//wdt_en(); //wdt_en();
if (configStream != NULL) { if (configStream != NULL) {
@@ -2101,12 +2126,12 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
void setup_main() { void setup_main() {
#if (SERIAL_BAUD) #if (SERIAL_BAUD)
#if defined(debugSerialPort) #if defined(debugSerialPort) && !defined(NOSERIAL)
debugSerialPort.begin(SERIAL_BAUD); debugSerialPort.begin(SERIAL_BAUD);
#endif #endif
#else #else
#if not defined (__SAM3X8E__) && defined (debugSerialPort) #if not defined (__SAM3X8E__) && defined (debugSerialPort) && !defined(NOSERIAL)
debugSerialPort.begin(); debugSerialPort.begin();
#endif #endif
delay(1000); delay(1000);
@@ -2125,13 +2150,13 @@ void setup_main() {
if(SPIFFS.begin()) if(SPIFFS.begin())
#endif #endif
{ {
#if defined(debugSerialPort) #if defined(debugSerialPort) && !defined(NOSERIAL)
debugSerialPort.println("SPIFFS Initialize....ok"); debugSerialPort.println("SPIFFS Initialize....ok");
#endif #endif
} }
else else
{ {
#if defined(debugSerialPort) #if defined(debugSerialPort) && !defined(NOSERIAL)
debugSerialPort.println("SPIFFS Initialization...failed"); debugSerialPort.println("SPIFFS Initialization...failed");
#endif #endif
} }
@@ -2148,7 +2173,7 @@ void setup_main() {
if (!sysConf.isValidSysConf()) if (!sysConf.isValidSysConf())
{ {
#if defined(debugSerialPort) #if defined(debugSerialPort) && !defined(NOSERIAL)
debugSerialPort.println(F("No valid EEPROM data. Initializing.")); debugSerialPort.println(F("No valid EEPROM data. Initializing."));
#endif #endif
sysConf.clear(); sysConf.clear();
@@ -2185,7 +2210,7 @@ void setup_main() {
#else #else
pinMode(TXEnablePin, OUTPUT); pinMode(TXEnablePin, OUTPUT);
#endif #endif
modbusSerial.begin(MODBUS_SERIAL_BAUD,dimPar); modbusSerial.begin(MODBUS_SERIAL_BAUD,MODBUS_SERIAL_PARAM);
node.idle(&modbusIdle); node.idle(&modbusIdle);
node.preTransmission(preTransmission); node.preTransmission(preTransmission);
node.postTransmission(postTransmission); node.postTransmission(postTransmission);
@@ -2277,11 +2302,17 @@ infoSerial<<F("\nFirmware MAC Address " QUOTE(CUSTOM_FIRMWARE_MAC));
#endif #endif
#ifdef _modbus #ifdef _modbus
infoSerial<<F("\n(+)MODBUS " QUOTE(MODBUS_DIMMER_PARAM) " at " QUOTE(modbusSerial) " speed:" QUOTE(MODBUS_SERIAL_BAUD)); infoSerial<<F("\n(+)MODBUS " QUOTE(MODBUS_SERIAL_PARAM) " at " QUOTE(modbusSerial) " speed:" QUOTE(MODBUS_SERIAL_BAUD));
#else #else
infoSerial<<F("\n(-)MODBUS"); infoSerial<<F("\n(-)MODBUS");
#endif #endif
#ifdef IPMODBUS
infoSerial<<F("\n(+)IPMODBUS ");// QUOTE(MODBUS_TCP_PARAM) " at " QUOTE(modbusSerial) " speed:" QUOTE(MODBUS_TCP_BAUD));
#else
infoSerial<<F("\n(-)IPMODBUS");
#endif
#ifndef OWIRE_DISABLE #ifndef OWIRE_DISABLE
infoSerial<<F("\n(+)OWIRE"); infoSerial<<F("\n(+)OWIRE");
#ifdef USE_1W_PIN #ifdef USE_1W_PIN
@@ -2400,13 +2431,17 @@ infoSerial<<F("\n(-)MULTIVENT");
infoSerial<<F("\n(+)HUMIDIFIER"); infoSerial<<F("\n(+)HUMIDIFIER");
#endif #endif
#ifdef NOSERIAL
infoSerial<<F("\nNOSERIAL");
#endif
#ifdef ELEVATOR_ENABLE #ifdef ELEVATOR_ENABLE
infoSerial<<F("\n(+)ELEVATOR"); infoSerial<<F("\n(+)ELEVATOR");
#endif #endif
#ifdef IPMODBUS //#ifdef IPMODBUS
infoSerial<<F("\n(+)IPMODBUS"); //infoSerial<<F("\n(+)IPMODBUS");
#endif //#endif
infoSerial<<endl; infoSerial<<endl;
// WDT_Disable( WDT ) ; // WDT_Disable( WDT ) ;
@@ -2432,18 +2467,23 @@ void publishStat(){
uint32_t ut = millis()/1000UL; uint32_t ut = millis()/1000UL;
if (!mqttClient.connected() || ethernetIdleCount) return; if (!mqttClient.connected() || ethernetIdleCount) return;
setTopic(topic,sizeof(topic),T_DEV); setTopic(topic,sizeof(topic),T_DEV);
strncat_P(topic, stats_P, sizeof(topic)); strncat_P(topic, stats_P, sizeof(topic)-1);
strncat(topic, "/", sizeof(topic)); strncat(topic, "/", sizeof(topic));
strncat_P(topic, freeheap_P, sizeof(topic)); strncat_P(topic, freeheap_P, sizeof(topic)-1);
printUlongValueToStr(intbuf, fr); printUlongValueToStr(intbuf, fr);
mqttClient.publish(topic,intbuf,true); mqttClient.publish(topic,intbuf,true);
setTopic(topic,sizeof(topic),T_DEV); setTopic(topic,sizeof(topic),T_DEV);
strncat_P(topic, stats_P, sizeof(topic)); strncat_P(topic, stats_P, sizeof(topic)-1);
strncat(topic, "/", sizeof(topic)); strncat(topic, "/", sizeof(topic));
strncat_P(topic, uptime_P, sizeof(topic)); strncat_P(topic, uptime_P, sizeof(topic)-1);
printUlongValueToStr(intbuf, ut); printUlongValueToStr(intbuf, ut);
mqttClient.publish(topic,intbuf,true); mqttClient.publish(topic,intbuf,true);
setTopic(topic,sizeof(topic),T_DEV);
strncat_P(topic, state_P, sizeof(topic)-1);
strncpy_P(intbuf, ready_P, sizeof(intbuf)-1);
mqttClient.publish(topic,intbuf,true);
} }
void setupMacAddress() { void setupMacAddress() {

View File

@@ -14,7 +14,7 @@
#define INTERVAL_AC_POLLING 5000L #define INTERVAL_AC_POLLING 5000L
static int driverStatus = CST_UNKNOWN; //static int driverStatus = CST_UNKNOWN;
static int fresh =0; static int fresh =0;
static int power = 0; static int power = 0;
@@ -39,6 +39,32 @@ const char QUIET_P[] PROGMEM = "queit";
const char SWING_P[] PROGMEM = "swing"; const char SWING_P[] PROGMEM = "swing";
const char RAW_P[] PROGMEM = "raw"; const char RAW_P[] PROGMEM = "raw";
void out_AC::getConfig(){
ACSerial=&AC_Serial;
if (item->getArgCount())
switch(portNum=item->getArg(0)){
case 0: ACSerial=&Serial;
break;
//#if defined (Serial1)
case 1: ACSerial=&Serial1;
break;
//#endif
//#if defined (Serial2)
case 2: ACSerial=&Serial2;
break;
//#endif
//#if defined (Serial3)
case 3: ACSerial=&Serial3;
break;
//#endif
}
}
void out_AC::InsertData(byte data[], size_t size){ void out_AC::InsertData(byte data[], size_t size){
char s_mode[10]; char s_mode[10];
@@ -177,11 +203,11 @@ byte getCRC(byte req[], size_t size){
} }
void out_AC::SendData(byte req[], size_t size){ void out_AC::SendData(byte req[], size_t size){
AC_Serial.write(req, size - 1); ACSerial->write(req, size - 1);
AC_Serial.write(getCRC(req, size-1)); ACSerial->write(getCRC(req, size-1));
//AC_Serial.flush(); //ACSerial->flush();
item->setExt(millisNZ()); item->setExt(millisNZ());
debugSerial.print("AirCon<<"); debugSerial<<F("AirCon ")<<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){
@@ -206,23 +232,30 @@ inline unsigned char toHex( char ch ){
int out_AC::Setup() int out_AC::Setup()
{ {
abstractOut::Setup(); abstractOut::Setup();
debugSerial<<F("AC Init")<<endl; if (!item) return 0;
AC_Serial.begin(9600); debugSerial<<F("AC Init: ")<<portNum<<endl;
driverStatus = CST_INITIALIZED; if (!portNum)// && (g_APinDescription[0].ulPinType == PIO_PA8A_URXD))
{
pinMode(0, INPUT_PULLUP);
}
ACSerial->begin(9600);
item->itemArr->subtype = CST_INITIALIZED;
//driverStatus = CST_INITIALIZED;
return 1; return 1;
} }
int out_AC::Stop() int out_AC::Stop()
{ {
debugSerial<<F("AC De-Init")<<endl; if (!item) return 0;
debugSerial<<F("AC De-Init: ")<<portNum<<endl;
driverStatus = CST_UNKNOWN; item->itemArr->subtype = CST_UNKNOWN;
return 1; return 1;
} }
int out_AC::Status() int out_AC::Status()
{ {
return driverStatus; if (!item) return 0;
return item->itemArr->subtype;
} }
int out_AC::isActive() int out_AC::isActive()
@@ -240,16 +273,34 @@ if (cause!=POLLING_SLOW) return false;
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
} }
if(AC_Serial.available() >= 37){ //was 0 if(ACSerial->available() >= 37){ //was 0
AC_Serial.readBytes(data, 37); ACSerial->readBytes(data, 37);
while(AC_Serial.available()){ while(ACSerial->available()){
delay(2); delay(2);
AC_Serial.read(); ACSerial->read();
} }
debugSerial<<F("AirCon ")<<portNum<<F(" >> ");
for (int i=0; i < 37-1; i++)
{
if (data[i] < 10){
debugSerial.print("0");
debugSerial.print(data[i], HEX);
}
else
{
debugSerial.print(data[i], HEX);
}
}
if (data[36] != inCheck){ if (data[36] != inCheck){
inCheck = data[36]; inCheck = data[36];
InsertData(data, 37); InsertData(data, 37);
debugSerial<<F(" OK");
} }
debugSerial.println();
} }
return true; return true;
}; };
@@ -434,8 +485,8 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
hexbyte[0] = buf[i] ; hexbyte[0] = buf[i] ;
hexbyte[1] = buf[i+1] ; hexbyte[1] = buf[i+1] ;
data[i/2] = (toHex(hexbyte[0]) << 4) | toHex(hexbyte[1]); data[i/2] = (toHex(hexbyte[0]) << 4) | toHex(hexbyte[1]);
AC_Serial.write(data, 37); ACSerial->write(data, 37);
AC_Serial.flush(); ACSerial->flush();
publishTopic("RAW", buf); publishTopic("RAW", buf);
} }
*/ */
@@ -474,12 +525,12 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
data[9] = 1; data[9] = 1;
data[10] = 77; data[10] = 77;
data[11] = 95; data[11] = 95;
AC_Serial.flush(); ACSerial->flush();
uint32_t ts=item->getExt(); uint32_t ts=item->getExt();
while (ts && !isTimeOver(ts,millis(),100)) yield(); while (ts && !isTimeOver(ts,millis(),100)) yield();
SendData(data, sizeof(data)/sizeof(byte)); SendData(data, sizeof(data)/sizeof(byte));
//InsertData(data, sizeof(data)/sizeof(byte)); //InsertData(data, sizeof(data)/sizeof(byte));
//AC_Serial.flush(); //ACSerial->flush();
//item->setExt(millisNZ()); //item->setExt(millisNZ());
return 1; return 1;
} }

View File

@@ -24,7 +24,8 @@ extern void modbusIdle(void) ;
class out_AC : public abstractOut { class out_AC : public abstractOut {
public: public:
out_AC(Item * _item):abstractOut(_item){}; out_AC(Item * _item):abstractOut(_item){getConfig();};
void getConfig();
int Setup() override; int Setup() override;
int Poll(short cause) override; int Poll(short cause) override;
int Stop() override; int Stop() override;
@@ -33,9 +34,16 @@ public:
int getChanType() override; int getChanType() override;
int getDefaultStorageType(){return ST_FLOAT_CELSIUS;}; int getDefaultStorageType(){return ST_FLOAT_CELSIUS;};
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override;
protected: protected:
void InsertData(byte data[], size_t size); void InsertData(byte data[], size_t size);
void SendData(byte req[], size_t size); void SendData(byte req[], size_t size);
uint8_t portNum;
#if defined (__SAM3X8E__)
UARTClass *ACSerial;
#else
HardwareSerial *ACSerial;
#endif
}; };
#endif #endif

View File

@@ -358,8 +358,10 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name); aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name);
if (execObj) if (execObj)
{ {
aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child;
//Retrive previous data //Retrive previous data
aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S"); aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
if (lastMeasured) if (lastMeasured)
{ {
if (lastMeasured->type == aJson_Int) if (lastMeasured->type == aJson_Int)
@@ -372,7 +374,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
else //No container to store value yet else //No container to store value yet
{ {
debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl; debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl;
aJson.addNumberToObject(execObj, "@S", (long) param); aJson.addNumberToObject(markObj, "@S", (long) param);
} }
@@ -386,7 +388,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
if (*submitParam) if (*submitParam)
{ {
// Compare with last submitted val (if @V NOT marked as NULL in config) // Compare with last submitted val (if @V NOT marked as NULL in config)
aJsonObject *settedValue = aJson.getObjectItem(execObj,"@V"); aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V");
if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param)) if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param))
{ {
debugSerial<<F("MBUSD: Ignored - equal with setted val")<<endl; debugSerial<<F("MBUSD: Ignored - equal with setted val")<<endl;
@@ -473,11 +475,14 @@ void out_Modbus::initLine()
int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType) int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
{ {
if (!store) return -1; if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
aJsonObject * templateParamObj = aJson.getObjectItem(store->parameters, paramName); aJsonObject * templateParamObj = aJson.getObjectItem(store->parameters, paramName);
if (!templateParamObj) return -1; if (!templateParamObj) {errorSerial<<F(" internal send error - no template")<<endl; return -1;}
aJsonObject * regObj = aJson.getObjectItem(templateParamObj, "reg"); aJsonObject * regObj = aJson.getObjectItem(templateParamObj, "reg");
if (!regObj) return -2; if (!regObj) {errorSerial<<F(" internal send error - no regObj")<<endl; return -2;}
int res = -1; int res = -1;
// int8_t regType = PAR_I16; // int8_t regType = PAR_I16;
@@ -525,11 +530,16 @@ aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj && itemParametersObj->type ==aJson_Object) if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ {
aJsonObject *execObj = itemParametersObj->child; aJsonObject *execObj = itemParametersObj->child;
while (execObj && execObj->type == aJson_Object) while (execObj && (execObj->type == aJson_Object) || (execObj->type == aJson_Array) )
{ {
if ((execObj->subtype & MB_NEED_SEND) && !(execObj->subtype & MB_SEND_ERROR)) if ((execObj->subtype & MB_NEED_SEND) && !(execObj->subtype & MB_SEND_ERROR))
{ {
aJsonObject *outValue = aJson.getObjectItem(execObj,"@V");
aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child;
aJsonObject *outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) if (outValue)
{ {
modbusBusy=1; modbusBusy=1;
@@ -571,7 +581,7 @@ if (isTimeOver(store->timestamp,millis(),store->pollingInterval) && ( !mbusSlenc
if (itemParametersObj && itemParametersObj->type ==aJson_Object) if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ {
aJsonObject *execObj = itemParametersObj->child; aJsonObject *execObj = itemParametersObj->child;
while (execObj && execObj->type == aJson_Object) while (execObj && (execObj->type == aJson_Object) || (execObj->type == aJson_Array))
{ {
if (execObj->subtype & MB_SEND_ERROR) execObj->subtype&=~ MB_SEND_ERROR; if (execObj->subtype & MB_SEND_ERROR) execObj->subtype&=~ MB_SEND_ERROR;
if ((execObj->subtype & 0x3) >= MB_SEND_ATTEMPTS) if ((execObj->subtype & 0x3) >= MB_SEND_ATTEMPTS)
@@ -667,7 +677,7 @@ aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj && itemParametersObj->type ==aJson_Object) if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ {
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr); aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr);
if (execObj && execObj->type == aJson_Object) if (execObj && (execObj->type == aJson_Object) || (execObj->type == aJson_Array))
{ {
/* /*
aJsonObject *polledValue = aJson.getObjectItem(execObj,"@S"); aJsonObject *polledValue = aJson.getObjectItem(execObj,"@S");
@@ -680,7 +690,10 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ //Schedule update { //Schedule update
execObj->subtype |= MB_NEED_SEND; execObj->subtype |= MB_NEED_SEND;
aJsonObject *outValue = aJson.getObjectItem(execObj,"@V"); aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child;
aJsonObject *outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) // Existant. Preserve original @type if (outValue) // Existant. Preserve original @type
{ {
outValue->valueint=Value; outValue->valueint=Value;
@@ -690,12 +703,12 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
// If no @V in config - creating with INT type - normal behavior - no supress in-to-out // If no @V in config - creating with INT type - normal behavior - no supress in-to-out
{ {
debugSerial<<F("Add @V: ")<<execObj->name<<endl; debugSerial<<F("Add @V: ")<<execObj->name<<endl;
aJson.addNumberToObject(execObj, "@V", Value); aJson.addNumberToObject(markObj, "@V", Value);
outValue = aJson.getObjectItem(execObj,"@V"); outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) outValue->subtype =regType & 0xF; if (outValue) outValue->subtype =regType & 0xF;
} }
aJsonObject *polledValue = aJson.getObjectItem(execObj,"@S"); aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
if (polledValue && outValue->type == aJson_Int) polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling if (polledValue && outValue->type == aJson_Int) polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
} }

View File

@@ -50,7 +50,7 @@ int out_Motor::Setup()
{ {
abstractOut::Setup(); abstractOut::Setup();
getConfig(); getConfig();
debugSerial.println("Motor Init"); debugSerial.println("Motor: Init");
pinMode(pinUp,OUTPUT); pinMode(pinUp,OUTPUT);
pinMode(pinDown,OUTPUT); pinMode(pinDown,OUTPUT);
@@ -70,7 +70,7 @@ return 1;
int out_Motor::Stop() int out_Motor::Stop()
{ {
debugSerial.println("Motor De-Init"); debugSerial.println("Motor: De-Init");
digitalWrite(pinUp,INACTIVE); digitalWrite(pinUp,INACTIVE);
digitalWrite(pinDown,INACTIVE); digitalWrite(pinDown,INACTIVE);
@@ -145,13 +145,13 @@ if (curPos>255) curPos=255;
} }
if (motorOfftime && isTimeOver(motorOfftime,millis(),maxOnTime)) if (motorOfftime && isTimeOver(motorOfftime,millis(),maxOnTime))
{dif = 0; debugSerial<<F("Motor timeout")<<endl;} {dif = 0; debugSerial<<F("Motor: timeout")<<endl;}
else if (curPos>=0) else if (curPos>=0)
dif=targetPos-curPos; dif=targetPos-curPos;
else else
dif=targetPos-255/2; // Have No feedback dif=targetPos-255/2; // Have No feedback
debugSerial<<F("In:")<<pinFeedback<<F(" Val:")<<fb<<F("/")<<curPos<<F("->")<<targetPos<<F(" delta:")<<dif<<endl; debugSerial<<F("Motor: in:")<<pinFeedback<<F(" Val:")<<fb<<F("/")<<curPos<<F("->")<<targetPos<<F(" delta:")<<dif<<endl;
if (dif<-POS_ERR) if (dif<-POS_ERR)
{ {
@@ -241,7 +241,7 @@ else
} }
else //Target zone else //Target zone
{ debugSerial.println("Target"); { debugSerial.println("Motor: Target");
digitalWrite(pinUp,INACTIVE); digitalWrite(pinUp,INACTIVE);
digitalWrite(pinDown,INACTIVE); digitalWrite(pinDown,INACTIVE);
item->setExt(0); item->setExt(0);
@@ -263,10 +263,7 @@ int out_Motor::getChanType()
int out_Motor::Ctrl(itemCmd cmd, char* subItem , bool toExecute) int out_Motor::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
{ {
//int chActive = item->isActive();
//bool toExecute = (chActive>0);
int suffixCode = cmd.getSuffix(); int suffixCode = cmd.getSuffix();
//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 if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
item->setFlag(FLAG_ACTION_NEEDED); item->setFlag(FLAG_ACTION_NEEDED);
@@ -276,30 +273,15 @@ switch(suffixCode)
case S_NOTFOUND: case S_NOTFOUND:
// turn on and set // turn on and set
toExecute = true; toExecute = true;
debugSerial<<F("Forced execution"); debugSerial<<F("Motor: Forced execution");
case S_SET: case S_SET:
//case S_ESET: //case S_ESET:
if (!cmd.isValue()) return 0; if (!cmd.isValue()) return 0;
// item->setVal(cmd.getPercents());
if (item->getExt()) item->setExt(millisNZ()); //Extend motor time if (item->getExt()) item->setExt(millisNZ()); //Extend motor time
/*
st.assignFrom(cmd);
//Store
st.saveItem(item);
if (!suffixCode)
{
if (chActive>0 && !st.getPercents()) item->setCmd(CMD_OFF);
if (chActive==0 && st.getPercents()) item->setCmd(CMD_ON);
item->SendStatus(FLAG_COMMAND | FLAG_PARAMETERS | FLAG_SEND_DEFFERED);
if (item->getExt()) item->setExt(millisNZ()); //Extend motor time
}
else item->SendStatus(FLAG_PARAMETERS | FLAG_SEND_DEFFERED);
*/
return 1; return 1;
//break; //break;
case S_CMD: case S_CMD:
//item->setCmd(cmd.getCmd());
switch (cmd.getCmd()) switch (cmd.getCmd())
{ {
case CMD_ON: case CMD_ON:
@@ -307,7 +289,6 @@ case S_CMD:
return 1; return 1;
case CMD_OFF: case CMD_OFF:
////item->SendStatus(FLAG_COMMAND);
if (item->getExt()) item->setExt(millisNZ()); //Extend motor time if (item->getExt()) item->setExt(millisNZ()); //Extend motor time
return 1; return 1;

View File

@@ -97,6 +97,7 @@ int out_Multivent::getChanType()
int out_Multivent::Ctrl(itemCmd cmd, char* subItem , bool toExecute) int out_Multivent::Ctrl(itemCmd cmd, char* subItem , bool toExecute)
{ {
if (cmd.getCmd()==CMD_DISABLE || cmd.getCmd()==CMD_ENABLE) return 0;
int suffixCode = cmd.getSuffix(); int suffixCode = cmd.getSuffix();
if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
@@ -229,6 +230,9 @@ debugSerial << F("Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd((fanV)?CMD_ON:CMD_OFF)); executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd((fanV)?CMD_ON:CMD_OFF));
//Move gates only if fan is actually on
if (!fanV) return 1;
i=NULL; i=NULL;
if (gatesObj) i = gatesObj->child; //Pass 2: re-distribute airflow if (gatesObj) i = gatesObj->child; //Pass 2: re-distribute airflow
@@ -250,11 +254,11 @@ while (i)
debugSerial<<i->name<<(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl; debugSerial<<i->name<<(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
} }
// executeCommand(i,-1,itemCmd().Percents255(out));
if (out != outObj->valueint) if ((out != outObj->valueint))
{ {
//report out //report out
executeCommand(i,-1,itemCmd().Percents255(out)); executeCommand(i,-1,itemCmd().Percents255(out));
outObj->valueint=out; outObj->valueint=out;
} }
} }
@@ -262,37 +266,6 @@ while (i)
} }
return 1; return 1;
switch(suffixCode)
{
case S_NOTFOUND:
// turn on and set
toExecute = true;
debugSerial<<F("Forced execution");
case S_SET:
if (!cmd.isValue()) return 0;
return 1;
//break;
case S_CMD:
//item->setCmd(cmd.getCmd());
switch (cmd.getCmd())
{
case CMD_ON:
return 1;
case CMD_OFF:
return 1;
} //switch cmd
break;
} //switch suffix
debugSerial<<F("Unknown cmd")<<endl;
return 0;
} }
#endif #endif

View File

@@ -26,7 +26,7 @@ bool out_pid::getConfig()
aJsonObject * kPIDObj = aJson.getArrayItem(item->itemArg, 0); aJsonObject * kPIDObj = aJson.getArrayItem(item->itemArg, 0);
if (!kPIDObj || kPIDObj->type != aJson_Array) if (!kPIDObj || kPIDObj->type != aJson_Array)
{ {
errorSerial<<F("Invalid PID param array.")<<endl; errorSerial<<F("PID: Invalid param array.")<<endl;
return false; return false;
} }
double outMin=0.; double outMin=0.;
@@ -103,7 +103,7 @@ bool out_pid::getConfig()
if (limits) store->pid->SetOutputLimits(outMin,outMax); if (limits) store->pid->SetOutputLimits(outMin,outMax);
store->pid->SetSampleTime(dT*1000.0); store->pid->SetSampleTime(dT*1000.0);
return true;} return true;}
else errorSerial<<F("PID already initialized")<<endl; else errorSerial<<F("PID: already initialized")<<endl;
return false; return false;
} }
@@ -120,7 +120,7 @@ store->pid=NULL;
//store->timestamp=millis(); //store->timestamp=millis();
if (getConfig()) if (getConfig())
{ {
infoSerial<<F("PID config loaded ")<< item->itemArr->name<<endl; infoSerial<<F("PID: config loaded ")<< item->itemArr->name<<endl;
//item->On(); // Turn ON pid by default //item->On(); // Turn ON pid by default
// if (item->getCmd()) item->setFlag(FLAG_COMMAND); // if (item->getCmd()) item->setFlag(FLAG_COMMAND);
// if (item->itemVal) item->setFlag(FLAG_PARAMETERS); // if (item->itemVal) item->setFlag(FLAG_PARAMETERS);
@@ -129,7 +129,7 @@ if (getConfig())
return 1; return 1;
} }
else else
{ errorSerial<<F("PID config error")<<endl; { errorSerial<<F("PID: config error")<<endl;
store->driverStatus = CST_FAILED; store->driverStatus = CST_FAILED;
return 0; return 0;
} }
@@ -138,7 +138,7 @@ else
int out_pid::Stop() int out_pid::Stop()
{ {
debugSerial.println("PID De-Init"); debugSerial.println("PID: De-Init");
if (store) delete (store->pid); if (store) delete (store->pid);
delete store; delete store;
item->setPersistent(NULL); item->setPersistent(NULL);
@@ -163,30 +163,33 @@ int out_pid::Poll(short cause)
{ {
if (cause==POLLING_SLOW) return 0; if (cause==POLLING_SLOW) return 0;
if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCmd()!=CMD_OFF)) if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCmd()!=CMD_OFF))
{ {
//double prevOut=store->output; if (item->getCmd() != CMD_OFF && ! item->getFlag(FLAG_DISABLED))
//itemCmd st;
//st.loadItem(item);
//short cmd = st.getCmd();
if (item->getCmd() != CMD_OFF && /* item->getCmd() != CMD_DISABLE*/ ! item->getFlag(FLAG_DISABLED))
{ {
if(store->pid->Compute() ) if(store->pid->Compute() )
{ {
float alarmVal; float alarmVal;
if (store->alarmArmed && ((alarmVal=getAlarmVal())>=0.)) store->output=alarmVal; if (store->alarmArmed && ((alarmVal=getAlarmVal())>=0.)) store->output=alarmVal;
debugSerial<<F("PID ")<<item->itemArr->name<<F(" set:")<<store->setpoint<<F(" in:")<<store->input<<(" out:") << store->output <<F(" P:")<<store->pid->GetKp() <<F(" I:")<<store->pid->GetKi() <<F(" D:")<<store->pid->GetKd();
if (store->alarmArmed) debugSerial << F(" Alarm"); debugSerial<<F("PID: ")<<item->itemArr->name<<F(" set:")<<store->setpoint<<F(" in:")<<store->input<<(" out:") << store->output <<F(" P:")<<store->pid->GetKp() <<F(" I:")<<store->pid->GetKi() <<F(" D:")<<store->pid->GetKd();
//if (item->getFlag(FLAG_DISABLED)) debugSerial << F(" <DIS>");
if (store->alarmArmed) debugSerial << F(" <ALM>");
debugSerial<<endl; debugSerial<<endl;
if (((abs(store->output-store->prevOut)>OUTPUT_TRESHOLD) || (item->getCmd() == CMD_ENABLE)) && !store->alarmArmed) if (((abs(store->output-store->prevOut)>OUTPUT_TRESHOLD) || (item->getFlag(FLAG_ACTION_NEEDED))) && !store->alarmArmed)
{ {
aJsonObject * oCmd = aJson.getArrayItem(item->itemArg, 1); aJsonObject * oCmd = aJson.getArrayItem(item->itemArg, 1);
if ((item->getCmd() == CMD_ENABLE) && (store->output>0.))
if (((store->prevOut == 0.) && (store->output>0)) || item->getFlag(FLAG_ACTION_NEEDED))
// if ((item->getFlag(FLAG_ACTION_NEEDED)) && (store->output>0.))
{ {
executeCommand(oCmd,-1,itemCmd().Cmd(CMD_ON)); executeCommand(oCmd,-1,itemCmd().Cmd(CMD_ON));
item->setCmd(CMD_VOID); // item->clearFlag(FLAG_ACTION_NEEDED);
} }
itemCmd value((float) (store->output));// * (100./255.)));
item->clearFlag(FLAG_ACTION_NEEDED);
itemCmd value((float) (store->output));
value.setSuffix(S_SET); value.setSuffix(S_SET);
executeCommand(oCmd,-1,value); executeCommand(oCmd,-1,value);
store->prevOut=store->output; store->prevOut=store->output;
@@ -198,7 +201,8 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
alarm(true); alarm(true);
} }
} }
} }
return 1;//store->pollingInterval; return 1;//store->pollingInterval;
}; };
@@ -208,7 +212,7 @@ float out_pid::getAlarmVal()
aJsonObject * kPIDObj = aJson.getArrayItem(item->itemArg, 0); aJsonObject * kPIDObj = aJson.getArrayItem(item->itemArg, 0);
if (!kPIDObj || kPIDObj->type != aJson_Array) if (!kPIDObj || kPIDObj->type != aJson_Array)
{ {
errorSerial<<F("Invalid PID param array.")<<endl; errorSerial<<F("PID: Invalid param array.")<<endl;
return -1.; return -1.;
} }
@@ -244,7 +248,7 @@ float out_pid::getAlarmVal()
else if (!alarmValDefined) outAlarm = 255.; else if (!alarmValDefined) outAlarm = 255.;
} }
} }
debugSerial<<F("Alarm value: ")<<outAlarm<< " "; // debugSerial<<F("Alarm value: ")<<outAlarm<< " ";
return outAlarm; return outAlarm;
} }
@@ -295,7 +299,7 @@ case S_VAL:
// Input value for PID // Input value for PID
if (!cmd.isValue()) return 0; if (!cmd.isValue()) return 0;
store->input=cmd.getFloat(); store->input=cmd.getFloat();
debugSerial<<F("Input value:")<<store->input<<endl; debugSerial<<F("PID: ")<< item->itemArr->name <<F(" Input value:")<<store->input<<endl;
store->alarmTimer=millis(); store->alarmTimer=millis();
if (store->alarmArmed) if (store->alarmArmed)
@@ -309,11 +313,11 @@ return 1;
case S_NOTFOUND: case S_NOTFOUND:
case S_SET: case S_SET:
//case S_ESET:
// Setpoint for PID // Setpoint for PID
if (!cmd.isValue()) return 0; if (!cmd.isValue()) return 0;
store->setpoint=cmd.getFloat(); store->setpoint=cmd.getFloat();
debugSerial<<F("Setpoint:")<<store->setpoint<<endl; debugSerial<<F("PID: ")<< item->itemArr->name <<F(" Setpoint:")<<store->setpoint<<endl;
{ {
aJsonObject * itemCascadeObj = aJson.getArrayItem(item->itemArg, 2); aJsonObject * itemCascadeObj = aJson.getArrayItem(item->itemArg, 2);
@@ -345,11 +349,14 @@ case S_CTRL:
case CMD_DRY: case CMD_DRY:
executeCommand(oCmd,-1,value); executeCommand(oCmd,-1,value);
executeCommand(oCmd,-1,itemCmd().Cmd((item->getFlag(FLAG_DISABLED))?CMD_DISABLE:CMD_ENABLE));
item->SendStatus(FLAG_FLAGS);
return 1; return 1;
case CMD_ENABLE: case CMD_ENABLE:
//item->setCmd(CMD_ENABLE); //item->setCmd(CMD_ENABLE);
//item->SendStatus(FLAG_COMMAND); //item->SendStatus(FLAG_COMMAND);
item->setFlag(FLAG_ACTION_NEEDED);
executeCommand(oCmd,-1,value); executeCommand(oCmd,-1,value);
store->prevOut=-2.0; store->prevOut=-2.0;
return 1; return 1;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#define DHCP_ATTEMPTS_FALLBACK 3
#define TENS_FRACT_LEN 2 #define TENS_FRACT_LEN 2
#define TENS_BASE 100 #define TENS_BASE 100
@@ -138,12 +138,22 @@
#define MODBUS_SERIAL_BAUD 9600 #define MODBUS_SERIAL_BAUD 9600
#endif #endif
#ifndef MODBUS_DIMMER_PARAM #ifndef MODBUS_SERIAL_PARAM
#define MODBUS_DIMMER_PARAM SERIAL_8N1 #define MODBUS_SERIAL_PARAM SERIAL_8N1
#endif #endif
#define dimPar MODBUS_DIMMER_PARAM /*
#define fmPar SERIAL_8N1 #ifndef MODBUS_TCP_BAUD
#define MODBUS_TCP_BAUD 9600
#endif
#ifndef MODBUS_TCP_PARAM
#define MODBUS_TCP_PARAM SERIAL_8N1
#endif
*/
#define MODBUS_FM_BAUD 9600
#define MODBUS_FM_PARAM SERIAL_8N1
#ifndef SERIAL_BAUD #ifndef SERIAL_BAUD
#define SERIAL_BAUD 115200 #define SERIAL_BAUD 115200
@@ -303,7 +313,7 @@
//#ifdef M5STACK //#ifdef M5STACK
//#define debugSerial M5.Lcd //#define debugSerial M5.Lcd
//#endif //#endif
#ifdef noSerial #ifdef NOSERIAL
#undef debugSerialPort #undef debugSerialPort
#else #else
#ifndef debugSerialPort #ifndef debugSerialPort
@@ -346,3 +356,9 @@
//#define PINS_COUNT NUM_DIGITAL_PINS //#define PINS_COUNT NUM_DIGITAL_PINS
#define isAnalogPin(p) ((p >= 14) && (p<=21)) #define isAnalogPin(p) ((p >= 14) && (p<=21))
#endif #endif
#ifdef AVR
#define minimalMemory 200
#else
#define minimalMemory 1200
#endif

View File

@@ -30,7 +30,7 @@ Streamlog::Streamlog (SerialPortType * _serialPort, uint8_t _severity, uint8_t
severity=_severity; severity=_severity;
} }
#endif #endif
/*
void Streamlog::begin(unsigned long speed) void Streamlog::begin(unsigned long speed)
{ {
if (serialPort) serialPort->begin(speed); if (serialPort) serialPort->begin(speed);
@@ -40,6 +40,7 @@ void Streamlog::end()
{ {
if (serialPort) serialPort->end(); if (serialPort) serialPort->end();
}; };
*/
int Streamlog::available(void) int Streamlog::available(void)
{ {
@@ -79,7 +80,7 @@ if (syslogInitialized && (udpDebugLevel>=severity))
} }
else else
{ {
if (logBufferPos<LOGBUFFER_SIZE-1 && (ch!='\r')) logBuffer[logBufferPos++]=ch; if ((logBufferPos<LOGBUFFER_SIZE-1) && (ch!='\r')) logBuffer[logBufferPos++]=ch;
} }
} }
#endif #endif
@@ -87,8 +88,8 @@ if (syslogInitialized && (udpDebugLevel>=severity))
#if defined (STATUSLED) #if defined (STATUSLED)
if ((ch=='\n') && ledPattern) statusLED.flash(ledPattern); if ((ch=='\n') && ledPattern) statusLED.flash(ledPattern);
#endif #endif
#if !defined(noSerial)
if (serialPort && (serialDebugLevel>=severity)) return serialPort->write(ch); if (serialPort && (serialDebugLevel>=severity)) serialPort->write(ch);
#endif
return 1; return 1;
}; };

View File

@@ -36,8 +36,8 @@ class Streamlog : public Print
#else #else
Streamlog (SerialPortType * _serialPort, uint8_t _severity = LOG_DEBUG, uint8_t _ledPattern = 0); Streamlog (SerialPortType * _serialPort, uint8_t _severity = LOG_DEBUG, uint8_t _ledPattern = 0);
#endif #endif
void begin(unsigned long speed); //void begin(unsigned long speed);
void end() ; //void end() ;
int available(void); int available(void);
int peek(void); int peek(void);

View File

@@ -27,7 +27,8 @@ const char EEPROM_signature[] = EEPROM_SIGNATURE;
uint8_t notGetConfigFromHTTP:1; uint8_t notGetConfigFromHTTP:1;
uint8_t udpDebugLevel:3; uint8_t udpDebugLevel:3;
uint8_t notSaveSuccedConfig:1; uint8_t notSaveSuccedConfig:1;
uint8_t spare2; uint8_t dhcpFallback:1;
uint8_t spare2:7;
uint16_t sysConfigHash; uint16_t sysConfigHash;
}; };
} systemConfigFlags; } systemConfigFlags;

View File

@@ -114,7 +114,8 @@ const char LOW_P[] PROGMEM = "LOW";
const char ERROR_P[] PROGMEM = "ERR"; const char ERROR_P[] PROGMEM = "ERR";
const char ENABLE_P[] PROGMEM = "ENABLE"; const char ENABLE_P[] PROGMEM = "ENABLE";
const char DISABLE_P[] PROGMEM = "DISABLE"; const char DISABLE_P[] PROGMEM = "DISABLE";
const char FREEZE_P[] PROGMEM = "FREEZE";
const char UNFREEZE_P[] PROGMEM = "UNFREEZE";
// SubTopics // SubTopics
const char SET_P[] PROGMEM = "set"; const char SET_P[] PROGMEM = "set";

View File

@@ -207,7 +207,7 @@ unsigned long freeRam() {
extern char _end; extern char _end;
extern "C" char *sbrk(int i); extern "C" char *sbrk(int i);
unsigned long freeRam() { unsigned long freeRam() {
char *ramstart = (char *) 0x20070000; char *ramstart = (char *) 0x20070000;
char *ramend = (char *) 0x20088000; char *ramend = (char *) 0x20088000;
char *heapend = sbrk(0); char *heapend = sbrk(0);
@@ -719,6 +719,13 @@ switch (cmdType)
Item it(item->valuestring); Item it(item->valuestring);
if (it.isValid()) if (it.isValid())
{ {
int fr = freeRam();
if (fr < minimalMemory)
{
errorSerial<<F("CTRL/exec: OutOfMemory: ")<<fr<<endl;
return -1;
}
if (itemCommand) it.Ctrl(itemCommand); if (itemCommand) it.Ctrl(itemCommand);
else it.Ctrl(_itemCmd); else it.Ctrl(_itemCmd);
} }

View File

@@ -55,7 +55,7 @@ void SetAddr(char * out, uint8_t* addr);
uint8_t HEX2DEC(char i); uint8_t HEX2DEC(char i);
int getInt(char ** chan); int getInt(char ** chan);
itemCmd getNumber(char ** chan); itemCmd getNumber(char ** chan);
unsigned long freeRam (); unsigned long freeRam ();
void parseBytes(const char* str, char separator, byte* bytes, int maxBytes, int base); void parseBytes(const char* str, char separator, byte* bytes, int maxBytes, int base);
int log(const char *str, ...); int log(const char *str, ...);
void printFloatValueToStr(char *valstr, float value); void printFloatValueToStr(char *valstr, float value);

View File

@@ -331,6 +331,7 @@ monitor_speed = 115200
platform = atmelavr platform = atmelavr
board = megaatmega2560 board = megaatmega2560
upload_port = net:192.168.88.2:23000 upload_port = net:192.168.88.2:23000
_upload_command = custom-build-flags/upload_mega2560slim-5100 $SOURCE
framework = arduino framework = arduino
build_flags = !python get_build_flags.py mega2560slim-5100 build_flags = !python get_build_flags.py mega2560slim-5100
extra_scripts = post:toBin.py extra_scripts = post:toBin.py