mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 03:39:49 +03:00
MBUS refactoring,
AC Haier tolerance for comm errors(CRC check), MERCURY - not blocking MBUS if failed (delay added if login fail) Kernel fixes (flags, Locks) Multivent to multichannel virtual AC converted (interim) PID library forked and changed
This commit is contained in:
@@ -3,6 +3,9 @@
|
|||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "abstractout.h"
|
#include "abstractout.h"
|
||||||
#include "itemCmd.h"
|
#include "itemCmd.h"
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "textconst.h"
|
||||||
|
|
||||||
int abstractOut::isActive()
|
int abstractOut::isActive()
|
||||||
|
|
||||||
{itemCmd st;
|
{itemCmd st;
|
||||||
@@ -37,4 +40,39 @@ int abstractOut::Status()
|
|||||||
void abstractOut::setStatus(uint8_t status)
|
void abstractOut::setStatus(uint8_t status)
|
||||||
{
|
{
|
||||||
if (item && item->itemArr) item->itemArr->subtype = status & 0xF;
|
if (item && item->itemArr) item->itemArr->subtype = status & 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int abstractOut::pubAction(bool state)
|
||||||
|
{
|
||||||
|
char subtopic[10]="/";
|
||||||
|
char val[10];
|
||||||
|
|
||||||
|
strcat_P(subtopic,action_P);
|
||||||
|
short cmd=item->getCmd();
|
||||||
|
if (state)
|
||||||
|
switch(cmd)
|
||||||
|
{
|
||||||
|
case CMD_COOL:
|
||||||
|
strcpy_P(val,cooling_P);
|
||||||
|
break;
|
||||||
|
//case CMD_AUTO:
|
||||||
|
//case CMD_HEAT:
|
||||||
|
//case CMD_ON:
|
||||||
|
//
|
||||||
|
// break;
|
||||||
|
case CMD_DRY:
|
||||||
|
strcpy_P(val,drying_P);
|
||||||
|
break;
|
||||||
|
case CMD_FAN:
|
||||||
|
strcpy_P(val,fan_P);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy_P(val,heating_P);
|
||||||
|
}
|
||||||
|
else //turned off
|
||||||
|
if (cmd==CMD_OFF) strcpy_P(val,off_P);
|
||||||
|
else strcpy_P(val,idle_P);
|
||||||
|
return publishTopic(item->itemArr->name,val,subtopic);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,9 @@ public:
|
|||||||
// virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead
|
// virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead
|
||||||
virtual int Status() override;
|
virtual int Status() override;
|
||||||
virtual void setStatus(uint8_t status) override;
|
virtual void setStatus(uint8_t status) override;
|
||||||
int Setup() override;
|
int Setup() override;
|
||||||
protected:
|
protected:
|
||||||
|
int pubAction(bool state);
|
||||||
|
|
||||||
Item * item;
|
Item * item;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -953,11 +953,11 @@ int Item::scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized)
|
|||||||
nextCmd.Cmd(CMD_ENABLE);
|
nextCmd.Cmd(CMD_ENABLE);
|
||||||
break;
|
break;
|
||||||
case CMD_FREEZE:
|
case CMD_FREEZE:
|
||||||
if (getFlag(FLAG_FREEZED) && !isScheduled()) return 0;
|
if ((getFlag(FLAG_FREEZED) == FLAG_FREEZED) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_UNFREEZE);
|
nextCmd.Cmd(CMD_UNFREEZE);
|
||||||
break;
|
break;
|
||||||
case CMD_UNFREEZE:
|
case CMD_UNFREEZE:
|
||||||
if (!getFlag(FLAG_FREEZED) && !isScheduled()) return 0;
|
if (!(getFlag(FLAG_FREEZED) == FLAG_FREEZED) && !isScheduled()) return 0;
|
||||||
nextCmd.Cmd(CMD_FREEZE);
|
nextCmd.Cmd(CMD_FREEZE);
|
||||||
break;
|
break;
|
||||||
case CMD_HALT:
|
case CMD_HALT:
|
||||||
@@ -1014,6 +1014,7 @@ int Item::scheduleCommand(itemCmd cmd,bool authorized)
|
|||||||
// -1 system error
|
// -1 system error
|
||||||
// -4 invalid argument
|
// -4 invalid argument
|
||||||
// -5 unauthorized
|
// -5 unauthorized
|
||||||
|
// -6 disabled
|
||||||
int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized)
|
int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized)
|
||||||
{
|
{
|
||||||
int fr = freeRam();
|
int fr = freeRam();
|
||||||
@@ -1050,6 +1051,31 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
//debugSerial<<endl;
|
//debugSerial<<endl;
|
||||||
if (subItem && subItem[0] == '$') {debugSerial<<F("Skipped homie stuff")<<endl;return -4; }
|
if (subItem && subItem[0] == '$') {debugSerial<<F("Skipped homie stuff")<<endl;return -4; }
|
||||||
if (!itemArr) return -1;
|
if (!itemArr) return -1;
|
||||||
|
|
||||||
|
if (!suffixCode && cmd.isCommand()) suffixCode=S_CMD;
|
||||||
|
switch (suffixCode)
|
||||||
|
{
|
||||||
|
case S_CMD:
|
||||||
|
case S_CTRL:
|
||||||
|
case S_DELAYED:
|
||||||
|
if (cmd.isCommand() && getFlag(FLAG_LOCKED_CMD) && cmd.getCmd()!=CMD_UNFREEZE)
|
||||||
|
{
|
||||||
|
errorSerial<<F("CTRL: channel frozen")<<endl;
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_VAL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (cmd.isValue() && getFlag(FLAG_LOCKED_SET))
|
||||||
|
{
|
||||||
|
errorSerial<<F("CTRL: channel frozen")<<endl;
|
||||||
|
return -6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// DELAYED COMMANDS processing
|
/// DELAYED COMMANDS processing
|
||||||
if (suffixCode == S_DELAYED)
|
if (suffixCode == S_DELAYED)
|
||||||
@@ -1062,7 +1088,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
bool scale100 = false;
|
bool scale100 = false;
|
||||||
bool invalidArgument = false;
|
bool invalidArgument = false;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
uint16_t status2Send = 0;
|
long status2Send = 0;
|
||||||
uint8_t command2Set = 0;
|
uint8_t command2Set = 0;
|
||||||
itemCmd originalCmd = cmd;
|
itemCmd originalCmd = cmd;
|
||||||
|
|
||||||
@@ -1565,7 +1591,14 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
|
|||||||
} // NO GROUP
|
} // NO GROUP
|
||||||
if (invalidArgument) return -4;
|
if (invalidArgument) return -4;
|
||||||
|
|
||||||
if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
if ((!driver || driver->isAllowed(cmd))
|
||||||
|
// && (
|
||||||
|
// //!getFlag(FLAG_FREEZED)
|
||||||
|
// (suffixCode == S_VAL)
|
||||||
|
// || (cmd.isCommand() && !getFlag(FLAG_LOCKED_CMD))
|
||||||
|
// || (cmd.isValue() && !getFlag(FLAG_LOCKED_SET))
|
||||||
|
// )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (driver) //New style modular code
|
if (driver) //New style modular code
|
||||||
@@ -1714,7 +1747,7 @@ if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
|
|||||||
} //alowed cmd
|
} //alowed cmd
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorSerial<<F("CTRL: Command blocked by driver or channel frozen")<<endl;
|
errorSerial<<F("CTRL: Command blocked by driver")<<endl;
|
||||||
if ((status2Send & FLAG_FLAGS) && operation)
|
if ((status2Send & FLAG_FLAGS) && operation)
|
||||||
{
|
{
|
||||||
cmd.saveItem(this,FLAG_FLAGS);
|
cmd.saveItem(this,FLAG_FLAGS);
|
||||||
@@ -1888,7 +1921,7 @@ void Item::sendDelayedStatus()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Item::SendStatus(int sendFlags, char * subItem) {
|
int Item::SendStatus(long sendFlags, char * subItem) {
|
||||||
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 | FLAG_FLAGS));
|
setFlag(sendFlags & (FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS));
|
||||||
@@ -1904,13 +1937,13 @@ int Item::SendStatus(int sendFlags, char * subItem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Item::SendStatusImmediate(itemCmd st, int sendFlags, char * subItem) {
|
int Item::SendStatusImmediate(itemCmd st, long sendFlags, char * subItem) {
|
||||||
{
|
{
|
||||||
char addrstr[64];
|
char addrstr[64];
|
||||||
char valstr[20] = "";
|
char valstr[20] = "";
|
||||||
char cmdstr[9] = "";
|
char cmdstr[9] = "";
|
||||||
|
|
||||||
debugSerial<<"SENDSTATUS: "<<subItem;
|
debugSerial<<"SENDSTATUS: "<<subItem<<" ";
|
||||||
st.debugOut();
|
st.debugOut();
|
||||||
|
|
||||||
#ifdef CANDRV
|
#ifdef CANDRV
|
||||||
@@ -2007,7 +2040,15 @@ int Item::SendStatus(int sendFlags, char * subItem) {
|
|||||||
|
|
||||||
if (sendFlags & FLAG_SEND_DELAYED)
|
if (sendFlags & FLAG_SEND_DELAYED)
|
||||||
strncat_P(addrstr, suffix_P[S_DELAYED], sizeof(addrstr)-1);
|
strncat_P(addrstr, suffix_P[S_DELAYED], sizeof(addrstr)-1);
|
||||||
else strncat_P(addrstr, suffix_P[S_SET], sizeof(addrstr)-1);
|
else
|
||||||
|
switch (st.getSuffix())
|
||||||
|
{
|
||||||
|
case S_FAN:
|
||||||
|
strncat_P(addrstr, suffix_P[S_FAN], sizeof(addrstr)-1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strncat_P(addrstr, suffix_P[S_SET], sizeof(addrstr)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Preparing parameters payload //////////
|
// Preparing parameters payload //////////
|
||||||
@@ -2102,7 +2143,7 @@ int Item::SendStatus(int sendFlags, char * subItem) {
|
|||||||
if (getFlag(FLAG_DISABLED))
|
if (getFlag(FLAG_DISABLED))
|
||||||
strcpy_P(cmdstr, DISABLE_P);
|
strcpy_P(cmdstr, DISABLE_P);
|
||||||
|
|
||||||
else if (getFlag(FLAG_FREEZED))
|
else if (getFlag(FLAG_FREEZED) == FLAG_FREEZED)
|
||||||
strcpy_P(cmdstr, FREEZE_P);
|
strcpy_P(cmdstr, FREEZE_P);
|
||||||
|
|
||||||
else strcpy_P(cmdstr, ENABLE_P);
|
else strcpy_P(cmdstr, ENABLE_P);
|
||||||
|
|||||||
@@ -138,8 +138,8 @@ class Item
|
|||||||
void setFloatVal(float par);
|
void setFloatVal(float par);
|
||||||
void setSubtype(uint8_t par);
|
void setSubtype(uint8_t par);
|
||||||
int Poll(int cause);
|
int Poll(int cause);
|
||||||
int SendStatus(int sendFlags, char * subItem=NULL);
|
int SendStatus(long sendFlags, char * subItem=NULL);
|
||||||
int SendStatusImmediate(itemCmd st, int sendFlags, char * subItem=NULL);
|
int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL);
|
||||||
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));};
|
||||||
|
|||||||
@@ -1211,7 +1211,7 @@ 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);
|
//? item->clearFlag(FLAG_FREEZED); //?
|
||||||
break;
|
break;
|
||||||
case CMD_FREEZE:
|
case CMD_FREEZE:
|
||||||
item->setFlag(FLAG_FREEZED);
|
item->setFlag(FLAG_FREEZED);
|
||||||
|
|||||||
@@ -104,21 +104,40 @@ const ch_type ch_type_P[] PROGMEM =
|
|||||||
#define CMD_JSON -2
|
#define CMD_JSON -2
|
||||||
|
|
||||||
//FLAGS
|
//FLAGS
|
||||||
#define FLAG_SEND_IMMEDIATE 0x1UL
|
|
||||||
#define FLAG_COMMAND 0x100UL
|
|
||||||
#define FLAG_PARAMETERS 0x200UL
|
|
||||||
#define FLAG_FLAGS 0x400UL
|
|
||||||
#define FLAG_SEND_RETRY 0x800UL
|
|
||||||
#define FLAG_SEND_DEFFERED 0x1000UL
|
|
||||||
#define FLAG_SEND_DELAYED 0x2000UL
|
|
||||||
#define FLAG_ACTION_NEEDED 0x4000UL
|
|
||||||
#define FLAG_ACTION_IN_PROCESS 0x8000UL
|
|
||||||
|
|
||||||
#define FLAG_DISABLED 0x10000UL
|
//#define FLAG_COMMAND 0x100UL
|
||||||
#define FLAG_FREEZED 0x20000UL
|
//#define FLAG_PARAMETERS 0x200UL
|
||||||
|
//#define FLAG_FLAGS 0x400UL
|
||||||
|
//#define FLAG_SEND_RETRY 0x800UL
|
||||||
|
//#define FLAG_SEND_DEFFERED 0x1000UL
|
||||||
|
//#define FLAG_SEND_DELAYED 0x2000UL
|
||||||
|
//#define FLAG_ACTION_NEEDED 0x4000UL
|
||||||
|
//#define FLAG_ACTION_IN_PROCESS 0x8000UL
|
||||||
|
//#define FLAG_DISABLED 0x10000UL
|
||||||
|
//#define FLAG_FREEZED 0x20000UL
|
||||||
|
//#define FLAG_HALTED 0x40000UL
|
||||||
|
//#define FLAG_XON 0x80000UL
|
||||||
|
|
||||||
|
#define FLAG_DISABLED 0x100UL
|
||||||
|
#define FLAG_LOCKED_CMD 0x200UL
|
||||||
|
#define FLAG_LOCKED_SET 0x400UL
|
||||||
|
#define FLAG_FREEZED 0x600UL
|
||||||
|
|
||||||
|
#define FLAG_SEND_DEFFERED 0x800UL
|
||||||
|
#define FLAG_COMMAND 0x1000UL
|
||||||
|
#define FLAG_PARAMETERS 0x2000UL
|
||||||
|
#define FLAG_FLAGS 0x4000UL
|
||||||
|
|
||||||
|
#define FLAG_SEND_RETRY 0x8000UL
|
||||||
|
|
||||||
|
#define FLAG_ACTION_NEEDED 0x10000UL
|
||||||
|
#define FLAG_ACTION_IN_PROCESS 0x20000UL
|
||||||
#define FLAG_HALTED 0x40000UL
|
#define FLAG_HALTED 0x40000UL
|
||||||
#define FLAG_XON 0x80000UL
|
#define FLAG_XON 0x80000UL
|
||||||
|
#define FLAG_SEND_DELAYED 0x100000UL
|
||||||
|
|
||||||
|
|
||||||
|
#define FLAG_SEND_IMMEDIATE 0x1UL
|
||||||
#define FLAG_NOT_SEND_CAN 0x2UL
|
#define FLAG_NOT_SEND_CAN 0x2UL
|
||||||
|
|
||||||
int txt2cmd (char * payload);
|
int txt2cmd (char * payload);
|
||||||
|
|||||||
@@ -551,28 +551,6 @@ void printMACAddress() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
char* getStringFromConfig(aJsonObject * a, int i)
|
|
||||||
{
|
|
||||||
aJsonObject * element = NULL;
|
|
||||||
if (!a) return NULL;
|
|
||||||
if (a->type == aJson_Array)
|
|
||||||
element = aJson.getArrayItem(a, i);
|
|
||||||
// TODO - human readable JSON objects as alias
|
|
||||||
|
|
||||||
if (element && element->type == aJson_String) return element->valuestring;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* getStringFromConfig(aJsonObject * a, char * name)
|
|
||||||
{
|
|
||||||
aJsonObject * element = NULL;
|
|
||||||
if (!a) return NULL;
|
|
||||||
if (a->type == aJson_Object)
|
|
||||||
element = aJson.getObjectItem(a, name);
|
|
||||||
if (element && element->type == aJson_String) return element->valuestring;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OTA
|
#ifdef OTA
|
||||||
const char defaultPassword[] PROGMEM = QUOTE(DEFAULT_OTA_PASSWORD);
|
const char defaultPassword[] PROGMEM = QUOTE(DEFAULT_OTA_PASSWORD);
|
||||||
void setupOTA(void)
|
void setupOTA(void)
|
||||||
@@ -608,7 +586,7 @@ void setupSyslog()
|
|||||||
|
|
||||||
udpSyslogArr = aJson.getObjectItem(root, "syslog");
|
udpSyslogArr = aJson.getObjectItem(root, "syslog");
|
||||||
if (udpSyslogArr && (n = aJson.getArraySize(udpSyslogArr))) {
|
if (udpSyslogArr && (n = aJson.getArraySize(udpSyslogArr))) {
|
||||||
char *syslogServer = getStringFromConfig(udpSyslogArr, 0);
|
char *syslogServer = getStringFromJson(udpSyslogArr, 0);
|
||||||
|
|
||||||
if (n>1) syslogPort = aJson.getArrayItem(udpSyslogArr, 1)->valueint;
|
if (n>1) syslogPort = aJson.getArrayItem(udpSyslogArr, 1)->valueint;
|
||||||
|
|
||||||
@@ -619,7 +597,7 @@ void setupSyslog()
|
|||||||
udpSyslog.server(syslogServer, syslogPort);
|
udpSyslog.server(syslogServer, syslogPort);
|
||||||
udpSyslog.deviceHostname(syslogDeviceHostname);
|
udpSyslog.deviceHostname(syslogDeviceHostname);
|
||||||
|
|
||||||
if (mqttArr) deviceName = getStringFromConfig(mqttArr, 0);
|
if (mqttArr) deviceName = getStringFromJson(mqttArr, 0);
|
||||||
if (deviceName) udpSyslog.appName(deviceName);
|
if (deviceName) udpSyslog.appName(deviceName);
|
||||||
else udpSyslog.appName(lighthub);
|
else udpSyslog.appName(lighthub);
|
||||||
udpSyslog.defaultPriority(LOG_KERN);
|
udpSyslog.defaultPriority(LOG_KERN);
|
||||||
@@ -1119,7 +1097,7 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
deviceName = getStringFromConfig(mqttArr, 0);
|
deviceName = getStringFromJson(mqttArr, 0);
|
||||||
if (!deviceName) deviceName = (char*) lighthub;
|
if (!deviceName) deviceName = (char*) lighthub;
|
||||||
|
|
||||||
infoSerial<<F("Device Name:")<<deviceName<<endl;
|
infoSerial<<F("Device Name:")<<deviceName<<endl;
|
||||||
@@ -1132,13 +1110,13 @@ void ip_ready_config_loaded_connecting_to_broker() {
|
|||||||
|
|
||||||
//debugSerial<<F("N:")<<n<<endl;
|
//debugSerial<<F("N:")<<n<<endl;
|
||||||
|
|
||||||
char *servername = getStringFromConfig(mqttArr, 1);
|
char *servername = getStringFromJson(mqttArr, 1);
|
||||||
if (n >= 3) port = aJson.getArrayItem(mqttArr, 2)->valueint;
|
if (n >= 3) port = aJson.getArrayItem(mqttArr, 2)->valueint;
|
||||||
if (n >= 4) user = getStringFromConfig(mqttArr, 3);
|
if (n >= 4) user = getStringFromJson(mqttArr, 3);
|
||||||
//if (!loadFlash(OFFSET_MQTT_PWD, passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
//if (!loadFlash(OFFSET_MQTT_PWD, passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
||||||
if (!sysConf.getMQTTpwd(passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
if (!sysConf.getMQTTpwd(passwordBuf, sizeof(passwordBuf)) && (n >= 5))
|
||||||
{
|
{
|
||||||
password = getStringFromConfig(mqttArr, 4);
|
password = getStringFromJson(mqttArr, 4);
|
||||||
infoSerial<<F("Using MQTT password from config")<<endl;
|
infoSerial<<F("Using MQTT password from config")<<endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -455,12 +455,15 @@ debugSerial<<F("AC: ")<<portNum<<F(" >> ");
|
|||||||
debugSerial.print(store->data[i], HEX);
|
debugSerial.print(store->data[i], HEX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (store->data[36] == getCRC(store->data,36))
|
||||||
if (store->data[36] != store->inCheck){
|
{
|
||||||
store->inCheck = store->data[36];
|
if (store->data[36] != store->inCheck){
|
||||||
InsertData(store->data, 37);
|
store->inCheck = store->data[36];
|
||||||
debugSerial<<F("AC: OK");
|
InsertData(store->data, 37);
|
||||||
|
debugSerial<<F("AC: OK");
|
||||||
|
}
|
||||||
|
else debugSerial<<F("AC: Bad CRC");
|
||||||
}
|
}
|
||||||
|
|
||||||
debugSerial.println();
|
debugSerial.println();
|
||||||
|
|||||||
@@ -346,6 +346,7 @@ if (!getConfig()) return 0;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
store->timestamp = millisNZ();
|
||||||
setStatus(CST_INITIALIZED);
|
setStatus(CST_INITIALIZED);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,47 @@ int str2regSize(char * str)
|
|||||||
return (int) PAR_I16;
|
return (int) PAR_I16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO irs etc
|
||||||
|
char * getParamNameByReg(aJsonObject * parameters, int regnum)
|
||||||
|
{
|
||||||
|
if (!parameters) return NULL;
|
||||||
|
|
||||||
|
aJsonObject * i = parameters->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
aJsonObject * regObj = aJson.getObjectItem(i, "reg");
|
||||||
|
if (regObj && regObj->type == aJson_Int && regObj->valueint == regnum)
|
||||||
|
{
|
||||||
|
debugSerial<<F("MBUS: ")<<i->name<<F(" added by num ")<<regnum<<endl;
|
||||||
|
return i->name;
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool haveAction(aJsonObject * execObj)
|
||||||
|
{
|
||||||
|
aJsonObject * j = execObj->child;
|
||||||
|
switch (execObj->type)
|
||||||
|
{
|
||||||
|
case aJson_Object:
|
||||||
|
while (j)
|
||||||
|
{
|
||||||
|
if (j->name && *j->name && (*j->name != '@')) return true;
|
||||||
|
j=j->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case aJson_Array:
|
||||||
|
while (j)
|
||||||
|
{
|
||||||
|
if (haveAction(j)) return true;
|
||||||
|
j=j->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool out_Modbus::getConfig()
|
bool out_Modbus::getConfig()
|
||||||
{
|
{
|
||||||
// Retrieve and store template values from global modbus settings
|
// Retrieve and store template values from global modbus settings
|
||||||
@@ -124,11 +165,112 @@ bool out_Modbus::getConfig()
|
|||||||
else {store->pollingRegisters=NULL;store->pollingInterval = 1000;store->pollingIrs=NULL;}
|
else {store->pollingRegisters=NULL;store->pollingInterval = 1000;store->pollingIrs=NULL;}
|
||||||
|
|
||||||
store->parameters=aJson.getObjectItem(templateObj, "par");
|
store->parameters=aJson.getObjectItem(templateObj, "par");
|
||||||
|
|
||||||
|
// initializing @S where needed
|
||||||
|
|
||||||
|
if (store->parameters)
|
||||||
|
{
|
||||||
|
// Creating for parameters where prefetch required
|
||||||
|
debugSerial<<F("Adding prefetch regs:")<<endl;
|
||||||
|
aJsonObject * i = store->parameters->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
aJsonObject * prefetchObj = aJson.getObjectItem(i, "prefetch");
|
||||||
|
if (prefetchObj && prefetchObj->type == aJson_Boolean && prefetchObj->valuebool)
|
||||||
|
{
|
||||||
|
createLastMeasured(i->name);
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugSerial<<F("Adding referred regs:")<<endl;
|
||||||
|
i = store->parameters->child;
|
||||||
|
// Creating for parameters used in references from another parameters
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
aJsonObject * mapObj = aJson.getObjectItem(i, "map");
|
||||||
|
if (mapObj)
|
||||||
|
{
|
||||||
|
aJsonObject * defObj = aJson.getObjectItem(mapObj, "def");
|
||||||
|
if (defObj && defObj->type == aJson_Int)
|
||||||
|
{
|
||||||
|
createLastMeasured(getParamNameByReg(store->parameters,defObj->valueint));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defObj && defObj->type == aJson_String)
|
||||||
|
{
|
||||||
|
createLastMeasured(defObj->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
debugSerial<<F("Adding regs with actions:")<<endl;
|
||||||
|
// Check - if action configured for object and create
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
if (itemParametersObj)
|
||||||
|
{
|
||||||
|
i = itemParametersObj->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
if (haveAction(i)) createLastMeasured(i);
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
//store->addr=item->getArg(0);
|
//store->addr=item->getArg(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int out_Modbus::createLastMeasured(char * name)
|
||||||
|
{
|
||||||
|
if (!name) return false;
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
return createLastMeasured(aJson.getObjectItem(itemParametersObj,name));
|
||||||
|
}
|
||||||
|
|
||||||
|
int out_Modbus::createLastMeasured(aJsonObject * execObj)
|
||||||
|
{
|
||||||
|
if (!execObj) return false;
|
||||||
|
|
||||||
|
aJsonObject * markObj = execObj;
|
||||||
|
if (execObj->type == aJson_Array)
|
||||||
|
{
|
||||||
|
markObj = execObj->child;
|
||||||
|
//storeLastValue = true;
|
||||||
|
}
|
||||||
|
if (!markObj) return false;
|
||||||
|
|
||||||
|
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
|
||||||
|
if (lastMeasured) return false;
|
||||||
|
|
||||||
|
debugSerial<<F("MBUS: Add @S: ")<<execObj->name<<endl;
|
||||||
|
aJson.addNumberToObject(markObj, "@S", (long) 0);
|
||||||
|
|
||||||
|
lastMeasured = aJson.getObjectItem(markObj,"@S");
|
||||||
|
if (!lastMeasured) return false;
|
||||||
|
lastMeasured->subtype |= MB_VALUE_OUTDATED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * out_Modbus::getLastMeasured(char * name)
|
||||||
|
{
|
||||||
|
if (!name) return NULL;
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
return getLastMeasured (aJson.getObjectItem(itemParametersObj,name));
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * out_Modbus::getLastMeasured(aJsonObject * execObj)
|
||||||
|
{
|
||||||
|
if (!execObj) return NULL;
|
||||||
|
if (execObj->type == aJson_Array) execObj = execObj->child;
|
||||||
|
aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S");
|
||||||
|
if (lastMeasured && lastMeasured->type == aJson_Int) return lastMeasured;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int out_Modbus::Setup()
|
int out_Modbus::Setup()
|
||||||
{
|
{
|
||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
@@ -330,12 +472,9 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
||||||
{
|
{
|
||||||
//Searching item param for nested mapping
|
//Searching item param for nested mapping
|
||||||
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
|
//Retrive previous data
|
||||||
if (itemParObj)
|
aJsonObject *lastMeasured = getLastMeasured(defMappingObj->valuestring);
|
||||||
{
|
if (lastMeasured)
|
||||||
//Retrive previous data
|
|
||||||
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
|
|
||||||
if (lastMeasured && lastMeasured->type ==aJson_Int)
|
|
||||||
{
|
{
|
||||||
traceSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
|
traceSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
|
||||||
//Searching template param for nested mapping
|
//Searching template param for nested mapping
|
||||||
@@ -384,8 +523,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
} //nested have lastMeasured
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -411,52 +549,31 @@ 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)
|
||||||
{
|
{
|
||||||
|
// if (!doExecution || haveAction(execObj)) //if no action in execObj - do not save last value to avoid confuse further recurrent check
|
||||||
bool storeLastValue = true;
|
// {
|
||||||
if (doExecution)
|
|
||||||
{
|
|
||||||
storeLastValue=false;
|
|
||||||
// Check - if no action configured for object - not need to store last value - let requrent process do it
|
|
||||||
|
|
||||||
aJsonObject * i = execObj->child;
|
|
||||||
while (i && !storeLastValue)
|
|
||||||
{
|
|
||||||
if (i->name && *i->name && (*i->name != '@')) storeLastValue = true;
|
|
||||||
i=i->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aJsonObject * markObj = execObj;
|
|
||||||
if (execObj->type == aJson_Array)
|
|
||||||
{
|
|
||||||
markObj = execObj->child;
|
|
||||||
storeLastValue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (storeLastValue)
|
|
||||||
{
|
|
||||||
//Retrive previous data
|
//Retrive previous data
|
||||||
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
|
aJsonObject *lastMeasured = getLastMeasured(execObj);
|
||||||
if (lastMeasured)
|
if (lastMeasured)
|
||||||
{
|
{
|
||||||
if (lastMeasured->type == aJson_Int)
|
|
||||||
{
|
|
||||||
if (lastMeasured->valueint == param)
|
if (lastMeasured->valueint == param)
|
||||||
*submitParam=false; //supress repeating execution for same val
|
{
|
||||||
|
//if recurrent call but value was readed before
|
||||||
|
if (!doExecution && !(lastMeasured->subtype & MB_VALUE_OUTDATED))
|
||||||
|
{
|
||||||
|
*submitParam=true; //never used
|
||||||
|
lastMeasured->subtype|=MB_VALUE_OUTDATED;
|
||||||
|
return mappedParam;
|
||||||
|
}
|
||||||
|
*submitParam=false; //supress repeating execution for same val
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lastMeasured->valueint=param;
|
lastMeasured->valueint=param;
|
||||||
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
|
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
|
||||||
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else //No container to store value yet
|
// }
|
||||||
{
|
|
||||||
debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl;
|
|
||||||
aJson.addNumberToObject(markObj, "@S", (long) param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (executeWithoutCheck)
|
if (executeWithoutCheck)
|
||||||
{
|
{
|
||||||
@@ -474,6 +591,12 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (*submitParam && doExecution)
|
if (*submitParam && doExecution)
|
||||||
{
|
{
|
||||||
// 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 * markObj = execObj;
|
||||||
|
if (execObj->type == aJson_Array)
|
||||||
|
{
|
||||||
|
markObj = execObj->child;
|
||||||
|
//storeLastValue = true;
|
||||||
|
}
|
||||||
aJsonObject *settedValue = aJson.getObjectItem(markObj,"@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))
|
||||||
{
|
{
|
||||||
@@ -491,14 +614,14 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (settedValue && !(execObj->subtype & MB_NEED_SEND))
|
if (settedValue && !(execObj->subtype & MB_NEED_SEND))
|
||||||
settedValue->valueint=param;
|
settedValue->valueint=param;
|
||||||
}
|
}
|
||||||
}
|
} //to be executed
|
||||||
}
|
} //ExecObj
|
||||||
}
|
} //item Parameters
|
||||||
//if (submitRecurrentOut) *submitParam=true; //if requrrent check has submit smth - report it.
|
|
||||||
return mappedParam;
|
return mappedParam;
|
||||||
}
|
} //reg == regNum
|
||||||
paramObj=paramObj->next;
|
paramObj=paramObj->next;
|
||||||
}
|
} //while
|
||||||
return itemCmd();
|
return itemCmd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,14 +741,14 @@ if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valueboo
|
|||||||
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramName);
|
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramName);
|
||||||
if (execObj)
|
if (execObj)
|
||||||
{
|
{
|
||||||
aJsonObject * markObj = execObj;
|
//aJsonObject * markObj = execObj;
|
||||||
if (execObj->type == aJson_Array) markObj = execObj->child;
|
//if (execObj->type == aJson_Array) markObj = execObj->child;
|
||||||
//Retrive previous data
|
//Retrive previous data
|
||||||
lastMeasured = aJson.getObjectItem(markObj,"@S");
|
lastMeasured = getLastMeasured(execObj);// aJson.getObjectItem(markObj,"@S");
|
||||||
if (lastMeasured)
|
if (lastMeasured)
|
||||||
{
|
{
|
||||||
if (lastMeasured->type == aJson_Int)
|
//if (lastMeasured->type == aJson_Int)
|
||||||
{
|
// {
|
||||||
traceSerial<<F(" Last:")<<lastMeasured->valueint<< F(" Now:") << localBuffer<<endl;
|
traceSerial<<F(" Last:")<<lastMeasured->valueint<< F(" Now:") << localBuffer<<endl;
|
||||||
|
|
||||||
if (lastMeasured->valueint != localBuffer)
|
if (lastMeasured->valueint != localBuffer)
|
||||||
@@ -645,7 +768,7 @@ if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valueboo
|
|||||||
|
|
||||||
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
|
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
|
||||||
}
|
}
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,5 +49,9 @@ protected:
|
|||||||
void initLine();
|
void initLine();
|
||||||
int sendModbus(char * paramName, aJsonObject * outValue);
|
int sendModbus(char * paramName, aJsonObject * outValue);
|
||||||
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
|
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
|
||||||
|
int createLastMeasured(char * name);
|
||||||
|
int createLastMeasured(aJsonObject * execObj);
|
||||||
|
aJsonObject * getLastMeasured(char * name);
|
||||||
|
aJsonObject * getLastMeasured(aJsonObject * execObj);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
|
||||||
void out_Multivent::getConfig()
|
void out_Multivent::getConfig()
|
||||||
@@ -14,6 +15,7 @@ void out_Multivent::getConfig()
|
|||||||
gatesObj = NULL;
|
gatesObj = NULL;
|
||||||
if (!item || !item->itemArg || item->itemArg->type != aJson_Object) return;
|
if (!item || !item->itemArg || item->itemArg->type != aJson_Object) return;
|
||||||
gatesObj = item->itemArg;
|
gatesObj = item->itemArg;
|
||||||
|
//acTemp=(float) item->getExt();
|
||||||
}
|
}
|
||||||
|
|
||||||
int out_Multivent::Setup()
|
int out_Multivent::Setup()
|
||||||
@@ -21,30 +23,81 @@ int out_Multivent::Setup()
|
|||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
//getConfig();
|
//getConfig();
|
||||||
|
|
||||||
//Expand Argument storage to 2
|
|
||||||
//for (int i = aJson.getArraySize(item->itemArg); i < 2; i++)
|
|
||||||
// aJson.addItemToArray(item->itemArg, aJson.createItem( (long int) 0));
|
|
||||||
|
|
||||||
//Allocate objects to store persistent data in config tree
|
//Allocate objects to store persistent data in config tree
|
||||||
if (gatesObj /*&& aJson.getArraySize(item->itemArg)>=2*/)
|
if (gatesObj)
|
||||||
{
|
{
|
||||||
aJsonObject * i = gatesObj->child;
|
aJsonObject * i = gatesObj->child;
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
if (i->name && *i->name)
|
if (i->name && *i->name)
|
||||||
{
|
{
|
||||||
aJsonObject * setObj = aJson.getObjectItem(i, "set");
|
aJsonObject * fanObj = aJson.getObjectItem(i, "fan");
|
||||||
if (!setObj) aJson.addNumberToObject(i, "set", (long int) -1);
|
if (!fanObj) {aJson.addNumberToObject(i, "fan", (long int) -1);fanObj = aJson.getObjectItem(i, "fan");}
|
||||||
|
|
||||||
aJsonObject * cmdObj = aJson.getObjectItem(i, "cmd");
|
aJsonObject * cmdObj = aJson.getObjectItem(i, "cmd");
|
||||||
if (!cmdObj) aJson.addNumberToObject(i, "cmd", (long int) -1);
|
if (!cmdObj) {aJson.addNumberToObject(i, "cmd", (long int) -1);cmdObj = aJson.getObjectItem(i, "cmd");}
|
||||||
|
|
||||||
aJsonObject * outObj = aJson.getObjectItem(i, "out");
|
aJsonObject * outObj = aJson.getObjectItem(i, "out");
|
||||||
if (!outObj) aJson.addNumberToObject(i, "out", (long int) -1);
|
if (!outObj) {aJson.addNumberToObject(i, "out", (long int) -1);outObj = aJson.getObjectItem(i, "out");}
|
||||||
|
|
||||||
|
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
|
||||||
|
if (pidObj && pidObj->type == aJson_Array && aJson.getArraySize(pidObj)>=3)
|
||||||
|
{
|
||||||
|
aJsonObject * setObj = aJson.getObjectItem(i, "set");
|
||||||
|
if (!setObj) {aJson.addNumberToObject(i, "set", (float) 20.1);setObj = aJson.getObjectItem(i, "set");}
|
||||||
|
else if (setObj->type != aJson_Float) {setObj->valuefloat = 20.0;setObj->type= aJson_Float;}
|
||||||
|
|
||||||
|
aJsonObject * valObj = aJson.getObjectItem(i, "val");
|
||||||
|
if (!valObj) {aJson.addNumberToObject(i, "val", (float) 20.1);valObj = aJson.getObjectItem(i, "val");}
|
||||||
|
else if (valObj->type != aJson_Float) {valObj->valuefloat = 20.0;valObj->type= aJson_Float;}
|
||||||
|
|
||||||
|
aJsonObject * poObj = aJson.getObjectItem(i, "po");
|
||||||
|
if (!poObj) {aJson.addNumberToObject(i, "po", (float) -1.1);poObj = aJson.getObjectItem(i, "po");}
|
||||||
|
else if (poObj->type != aJson_Float) {poObj->valuefloat = -2.0;valObj->type= aJson_Float;}
|
||||||
|
|
||||||
|
float kP = 1.0;
|
||||||
|
float kI = 0.0;
|
||||||
|
float kD = 0.0;
|
||||||
|
|
||||||
|
int direction = DIRECT;
|
||||||
|
aJsonObject * param = aJson.getArrayItem(pidObj, 0);
|
||||||
|
if (param->type == aJson_Float) kP=param->valuefloat;
|
||||||
|
else if (param->type == aJson_Int) kP=param->valueint;
|
||||||
|
if (kP<0)
|
||||||
|
{
|
||||||
|
kP=-kP;
|
||||||
|
direction=REVERSE;
|
||||||
|
}
|
||||||
|
param = aJson.getArrayItem(pidObj, 1);
|
||||||
|
if (param->type == aJson_Float) kI=param->valuefloat;
|
||||||
|
else if (param->type == aJson_Int) kI=param->valueint;
|
||||||
|
|
||||||
|
param = aJson.getArrayItem(pidObj, 2);
|
||||||
|
if (param->type == aJson_Float) kD=param->valuefloat;
|
||||||
|
else if (param->type == aJson_Int) kD=param->valueint;
|
||||||
|
|
||||||
|
float dT=5.0;
|
||||||
|
if (aJson.getArraySize(pidObj)==4)
|
||||||
|
{
|
||||||
|
param = aJson.getArrayItem(pidObj, 3);
|
||||||
|
if (param->type == aJson_Float) dT=param->valuefloat;
|
||||||
|
else if (param->type == aJson_Int) dT=param->valueint;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugSerial << "VENT: X:" << (long int) &valObj->valuefloat << "-" << (long int)&poObj->valuefloat <<"="<< (long int)&setObj->valuefloat<<endl;
|
||||||
|
pidObj->valueint = (long int) new PID (&valObj->valuefloat, &poObj->valuefloat, &setObj->valuefloat, kP, kI, kD, direction);
|
||||||
|
debugSerial << "VENT: Y:" << (long int)((PID*) pidObj->valueint)->myInput << "-" << (long int)((PID*) pidObj->valueint)->myOutput <<"="<< (long int)((PID*) pidObj->valueint)->mySetpoint<<endl;
|
||||||
|
|
||||||
|
((PID*) pidObj->valueint)->SetMode (AUTOMATIC);
|
||||||
|
((PID*) pidObj->valueint)->SetSampleTime(dT*1000.0);
|
||||||
|
debugSerial << F ("VENT: PID P=")<<kP<<" I="<<kI<<" D="<<kD<< endl;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i=i->next;
|
i=i->next;
|
||||||
}
|
}
|
||||||
debugSerial << F ("VENT: init")<< endl;
|
debugSerial << F ("VENT: init")<< endl;
|
||||||
|
item->setExt(0);
|
||||||
setStatus(CST_INITIALIZED);
|
setStatus(CST_INITIALIZED);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -57,13 +110,87 @@ return 0;
|
|||||||
int out_Multivent::Stop()
|
int out_Multivent::Stop()
|
||||||
{
|
{
|
||||||
debugSerial << F ("VENT: De-Init") << endl;
|
debugSerial << F ("VENT: De-Init") << endl;
|
||||||
|
if (gatesObj)
|
||||||
|
{
|
||||||
|
aJsonObject * i = gatesObj->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
if (i->name && *i->name)
|
||||||
|
{
|
||||||
|
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
|
||||||
|
if (pidObj && pidObj->valueint)
|
||||||
|
{
|
||||||
|
delete ((PID *) pidObj->valueint);
|
||||||
|
pidObj->valueint = 0;//NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
setStatus(CST_UNKNOWN);
|
setStatus(CST_UNKNOWN);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int out_Multivent::Poll(short cause)
|
int out_Multivent::Poll(short cause)
|
||||||
{
|
{
|
||||||
return 0;
|
if (cause == POLLING_SLOW && item->getExt() && isTimeOver(item->getExt(),millisNZ(),60000L))
|
||||||
|
{
|
||||||
|
item->setExt(0);
|
||||||
|
item->setCmd((isActive())?CMD_ON:CMD_OFF); // if AC temp unknown - change state to ON or OFF instead HEAT|COOL|FAN
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gatesObj)
|
||||||
|
{
|
||||||
|
aJsonObject * i = gatesObj->child;
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
if (i->name && *i->name)
|
||||||
|
{
|
||||||
|
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
|
||||||
|
if (pidObj && pidObj->valueint)
|
||||||
|
{
|
||||||
|
PID * p = (PID *) pidObj->valueint;
|
||||||
|
if (p->Compute())
|
||||||
|
{
|
||||||
|
aJsonObject * outObj = aJson.getObjectItem(i,"po");
|
||||||
|
if (outObj && outObj->type == aJson_Float)
|
||||||
|
{
|
||||||
|
debugSerial<<F("VENT: ")
|
||||||
|
<<item->itemArr->name<<"/"<<i->name
|
||||||
|
<<F(" in:")<<p->GetIn()<<F(" set:")<<p->GetSet()<<F(" out:")<<p->GetOut()
|
||||||
|
// <<F(" in:")<<getFloatFromJson(i,"val")<<(" set:")<<getFloatFromJson(i,"set")<<F(" out:")<<outObj->valuefloat
|
||||||
|
<<" P:"<<p->GetKp()<<" I:"<<p->GetKi()<<" D:"<<p->GetKd()<<((p->GetDirection())?" Rev ":" Dir ")<<((p->GetMode())?" A":" M");
|
||||||
|
debugSerial<<endl;
|
||||||
|
|
||||||
|
|
||||||
|
switch (item->getCmd())
|
||||||
|
{
|
||||||
|
case CMD_HEAT:
|
||||||
|
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
|
||||||
|
debugSerial<<F("VENT: PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
|
||||||
|
|
||||||
|
Ctrl(itemCmd().Percents255(outObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
|
break;
|
||||||
|
case CMD_COOL:
|
||||||
|
//case CMD_FAN: // if PIB using for vent
|
||||||
|
//case CMD_ON: // AC temp unknown - assuming that PID used for vent
|
||||||
|
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
|
||||||
|
debugSerial<<F("VENT: PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
|
||||||
|
Ctrl(itemCmd().Percents255(outObj->valuefloat).setSuffix(S_FAN),i->name);
|
||||||
|
break;
|
||||||
|
// if FAN_ONLY (AC report room temp regularry) - not use internal PID - let be on external control via /fan
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i=i->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
int out_Multivent::getChanType()
|
int out_Multivent::getChanType()
|
||||||
@@ -79,6 +206,24 @@ 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
|
||||||
|
|
||||||
|
if (suffixCode == S_VAL && !subItem && cmd.isValue())
|
||||||
|
{
|
||||||
|
//item->setExt((long)cmd.getFloat());
|
||||||
|
debugSerial << F("VENT:")<<F("AC air temp: ")<< cmd.getFloat()<<endl;
|
||||||
|
item->setExt(millisNZ());
|
||||||
|
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;
|
||||||
|
}
|
||||||
aJsonObject * i = NULL;
|
aJsonObject * i = NULL;
|
||||||
|
|
||||||
if (cmd.isCommand() && cmd.getSuffix()==S_FAN)
|
if (cmd.isCommand() && cmd.getSuffix()==S_FAN)
|
||||||
@@ -110,46 +255,33 @@ int maxPercent=0;
|
|||||||
|
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
|
aJsonObject * fanObj=aJson.getObjectItem(i, "fan");
|
||||||
aJsonObject * setObj=aJson.getObjectItem(i, "set");
|
|
||||||
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
||||||
aJsonObject * cascadeObj=aJson.getObjectItem(i, "cas");
|
aJsonObject * cascadeObj=aJson.getObjectItem(i, "cas");
|
||||||
if (setObj && cmdObj && setObj->type==aJson_Int && cmdObj->type==aJson_Int)
|
|
||||||
|
aJsonObject * setObj=aJson.getObjectItem(i, "set");
|
||||||
|
aJsonObject * pidObj=aJson.getObjectItem(i, "pid");
|
||||||
|
if (fanObj && cmdObj && fanObj->type==aJson_Int && cmdObj->type==aJson_Int)
|
||||||
{
|
{
|
||||||
|
|
||||||
int V =aJson.getObjectItem(i,"V")->valueint;
|
int V = getIntFromJson(i,"V",60);
|
||||||
int requestedV=0;
|
int requestedV=0;
|
||||||
|
|
||||||
if (subItem && !strcmp (i->name,subItem))
|
if (subItem && !strcmp (i->name,subItem))
|
||||||
{
|
{
|
||||||
if (cmdObj && cmd.isCommand())
|
|
||||||
{
|
|
||||||
cmdObj->valueint = cmd.getCmd();
|
|
||||||
//publishTopic(i->name,cmdObj->valueint,"/set");
|
|
||||||
switch (cmd.getCmd())
|
|
||||||
{
|
|
||||||
case CMD_ON:
|
|
||||||
cmd.Percents255(setObj->valueint);
|
|
||||||
break;
|
|
||||||
case CMD_OFF:
|
|
||||||
cmd.Percents255(0);
|
|
||||||
}
|
|
||||||
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (setObj->valueint<20))
|
|
||||||
{
|
|
||||||
setObj->valueint=30;
|
|
||||||
cmd.Percents255(30);
|
|
||||||
//if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_COMMAND|FLAG_PARAMETERS,i->name);
|
switch (suffixCode)
|
||||||
}
|
{
|
||||||
|
|
||||||
else if (setObj && cmdObj && suffixCode == S_FAN && cmd.isValue())
|
case S_FAN:
|
||||||
|
if (cmd.isValue())
|
||||||
{
|
{
|
||||||
|
|
||||||
if (cmd.getInt())
|
if (cmd.getInt())
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (cmdObj->valueint == CMD_OFF || cmdObj->valueint == -1)
|
if (cmdObj->valueint == CMD_OFF)// || cmdObj->valueint == -1)
|
||||||
{
|
{
|
||||||
debugSerial<<"VENT: Turning ON"<<endl;
|
debugSerial<<"VENT: Turning ON"<<endl;
|
||||||
cmdObj->valueint = CMD_ON;
|
cmdObj->valueint = CMD_ON;
|
||||||
@@ -157,42 +289,111 @@ while (i)
|
|||||||
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name);
|
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
setObj->valueint = cmd.getInt();
|
fanObj->valueint = cmd.getInt();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
|
if (cmdObj->valueint == CMD_ON)// != CMD_OFF && cmdObj->valueint != -1)
|
||||||
{ debugSerial<<"VENT: Turning OFF"<<endl;
|
{ debugSerial<<"VENT: Turning OFF"<<endl;
|
||||||
cmdObj->valueint = CMD_OFF;
|
cmdObj->valueint = CMD_OFF;
|
||||||
cmd.Cmd(CMD_OFF);
|
cmd.Cmd(CMD_OFF);
|
||||||
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name);
|
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
setObj->valueint = 0;
|
fanObj->valueint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fanObj->valueint = cmd.getInt();
|
||||||
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS|FLAG_COMMAND,i->name);
|
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS|FLAG_COMMAND,i->name);
|
||||||
}
|
}
|
||||||
|
if (!cmd.isCommand()) break; // if have command i FAN suffix - continue processing
|
||||||
else if (setObj && cmd.isValue())
|
case S_CMD:
|
||||||
|
if (cmd.isCommand())
|
||||||
{
|
{
|
||||||
setObj->valueint = cmd.getPercents255();
|
long sendFlags = 0;
|
||||||
//publishTopic(i->name,setObj->valueint,"/set");
|
|
||||||
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
|
||||||
|
switch (cmd.getCmd())
|
||||||
|
{
|
||||||
|
case CMD_ON:
|
||||||
|
cmd.Percents255(fanObj->valueint);
|
||||||
|
cmd.setSuffix(S_FAN);
|
||||||
|
sendFlags |= FLAG_COMMAND | FLAG_PARAMETERS;
|
||||||
|
cmdObj->valueint = cmd.getCmd();
|
||||||
|
break;
|
||||||
|
case CMD_OFF:
|
||||||
|
cmd.Percents255(0);
|
||||||
|
cmd.setSuffix(S_FAN);
|
||||||
|
sendFlags |= FLAG_COMMAND | FLAG_PARAMETERS;
|
||||||
|
cmdObj->valueint = cmd.getCmd();
|
||||||
|
break;
|
||||||
|
case CMD_ENABLE:
|
||||||
|
if (pidObj && pidObj->valueint) ((PID *) pidObj->valueint)->SetMode(AUTOMATIC);
|
||||||
|
sendFlags |= FLAG_FLAGS;
|
||||||
|
break;
|
||||||
|
case CMD_DISABLE:
|
||||||
|
if (pidObj && pidObj->valueint) ((PID *) pidObj->valueint)->SetMode(MANUAL);
|
||||||
|
sendFlags |= FLAG_FLAGS;
|
||||||
|
break;
|
||||||
|
case CMD_AUTO:
|
||||||
|
case CMD_COOL:
|
||||||
|
case CMD_HEAT:
|
||||||
|
case CMD_FAN:
|
||||||
|
case CMD_DRY:
|
||||||
|
sendFlags |= FLAG_COMMAND;
|
||||||
|
cmdObj->valueint = cmd.getCmd();
|
||||||
|
break;
|
||||||
|
//todo - halt-rest-xon-xoff-low-med-hi
|
||||||
}
|
}
|
||||||
|
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (fanObj->valueint<20))
|
||||||
|
{
|
||||||
|
fanObj->valueint=30;
|
||||||
|
cmd.Percents255(30);
|
||||||
|
//if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,sendFlags,i->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case S_SET:
|
||||||
|
if (cmd.isValue())
|
||||||
|
{
|
||||||
|
if (!setObj) {aJson.addNumberToObject(i, "set", (float) cmd.getFloat()); setObj = aJson.getObjectItem(i, "set"); }
|
||||||
|
else {setObj->valuefloat = cmd.getFloat();setObj->type = aJson_Float;}
|
||||||
|
//publishTopic(i->name,setObj->valuefloat,"/set");
|
||||||
|
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_VAL:
|
||||||
|
if (cmd.isValue())
|
||||||
|
{
|
||||||
|
aJsonObject * valObj = aJson.getObjectItem(i, "val");
|
||||||
|
if (!valObj) {aJson.addNumberToObject(i, "val", (float) cmd.getFloat()); setObj = aJson.getObjectItem(i, "val");}
|
||||||
|
else {valObj->valuefloat = cmd.getFloat();valObj->type= aJson_Float;}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (cascadeObj) executeCommand(cascadeObj,-1,cmd);
|
if (cascadeObj) executeCommand(cascadeObj,-1,cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
|
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
|
||||||
{
|
{
|
||||||
requestedV=V*setObj->valueint;
|
requestedV=V*fanObj->valueint;
|
||||||
activeV+=requestedV;
|
activeV+=requestedV;
|
||||||
|
|
||||||
if (setObj->valueint>maxPercent )
|
if (fanObj->valueint>maxPercent )
|
||||||
{
|
{
|
||||||
maxRequestedV=requestedV;
|
maxRequestedV=requestedV;
|
||||||
maxV=V;
|
maxV=V;
|
||||||
maxPercent=setObj->valueint;
|
maxPercent=fanObj->valueint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalV+=V;
|
totalV+=V;
|
||||||
@@ -207,10 +408,13 @@ int fanV=activeV/totalV;
|
|||||||
debugSerial << F("VENT: Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max req:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl;
|
debugSerial << F("VENT: Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max req:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl;
|
||||||
|
|
||||||
//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));
|
||||||
|
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).setSuffix(S_FAN));
|
||||||
|
/*
|
||||||
if (fanV)
|
if (fanV)
|
||||||
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd(CMD_ON));
|
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd(CMD_ON));
|
||||||
else
|
else
|
||||||
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV));
|
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV)); */
|
||||||
|
|
||||||
//Move gates only if fan is actually on
|
//Move gates only if fan is actually on
|
||||||
if (!fanV) return 1;
|
if (!fanV) return 1;
|
||||||
|
|
||||||
@@ -219,18 +423,20 @@ if (gatesObj) i = gatesObj->child; //Pass 2: re-distribute airflow
|
|||||||
|
|
||||||
while (i)
|
while (i)
|
||||||
{
|
{
|
||||||
int V =aJson.getObjectItem(i,"V")->valueint;
|
|
||||||
|
int V = getIntFromJson(i,"V",60);
|
||||||
|
|
||||||
|
|
||||||
aJsonObject * outObj=aJson.getObjectItem(i, "out");
|
aJsonObject * outObj=aJson.getObjectItem(i, "out");
|
||||||
aJsonObject * setObj=aJson.getObjectItem(i, "set");
|
aJsonObject * fanObj=aJson.getObjectItem(i, "fan");
|
||||||
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
|
||||||
|
|
||||||
if (outObj && setObj && cmdObj && outObj->type==aJson_Int && setObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
|
if (outObj && fanObj && cmdObj && outObj->type==aJson_Int && fanObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
|
||||||
{
|
{
|
||||||
long int out = 0;
|
long int out = 0;
|
||||||
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1 && maxRequestedV)
|
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1 && maxRequestedV)
|
||||||
{
|
{
|
||||||
int requestedV=V*setObj->valueint;
|
int requestedV=V*fanObj->valueint;
|
||||||
out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV;
|
out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV;
|
||||||
debugSerial<<F("VENT: ")<<i->name<<F(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
|
debugSerial<<F("VENT: ")<<i->name<<F(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <abstractout.h>
|
#include <abstractout.h>
|
||||||
#include <item.h>
|
#include <item.h>
|
||||||
#include "itemCmd.h"
|
#include "itemCmd.h"
|
||||||
|
#include <PID_v1.h>
|
||||||
|
|
||||||
|
|
||||||
//static int8_t motorQuote = 0;
|
//static int8_t motorQuote = 0;
|
||||||
@@ -22,5 +23,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void getConfig();
|
void getConfig();
|
||||||
aJsonObject * gatesObj;
|
aJsonObject * gatesObj;
|
||||||
|
//float acTemp;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
|
|||||||
item->clearFlag(FLAG_ACTION_NEEDED);
|
item->clearFlag(FLAG_ACTION_NEEDED);
|
||||||
|
|
||||||
itemCmd value((float) (store->output));
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
class pidPersistent : public chPersistent {
|
class pidPersistent : public chPersistent {
|
||||||
public:
|
public:
|
||||||
PID * pid;
|
PID * pid;
|
||||||
double output;
|
iotype output;
|
||||||
double input;
|
iotype input;
|
||||||
double setpoint;
|
iotype setpoint;
|
||||||
float prevOut;
|
float prevOut;
|
||||||
uint32_t alarmTimer;
|
uint32_t alarmTimer;
|
||||||
bool alarmArmed;
|
bool alarmArmed;
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ int out_relay::Setup()
|
|||||||
{
|
{
|
||||||
abstractOut::Setup();
|
abstractOut::Setup();
|
||||||
|
|
||||||
debugSerial<<F("Relay-Out #")<<pin<<F(" init")<<endl;
|
debugSerial<<F("relayCtr: ")<<F("pin#")<<pin<<F(" init")<<endl;
|
||||||
if (isProtectedPin(pin)) {errorSerial<<F("pin disabled")<<endl;return 0;}
|
if (isProtectedPin(pin)) {errorSerial<<F("relayCtr: ")<<F("pin disabled")<<endl;return 0;}
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
digitalWrite(pin,INACTIVE);
|
digitalWrite(pin,INACTIVE);
|
||||||
if (item) item->setExt(0);
|
if (item) item->setExt(0);
|
||||||
@@ -52,7 +52,7 @@ return 1;
|
|||||||
|
|
||||||
int out_relay::Stop()
|
int out_relay::Stop()
|
||||||
{
|
{
|
||||||
debugSerial<<F("Relay-Out #")<<pin<<F(" stop")<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Relay-Out #")<<pin<<F(" stop")<<endl;
|
||||||
pinMode(pin, INPUT);
|
pinMode(pin, INPUT);
|
||||||
setStatus(CST_UNKNOWN);
|
setStatus(CST_UNKNOWN);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -60,39 +60,12 @@ return 1;
|
|||||||
|
|
||||||
void out_relay::relay(bool state)
|
void out_relay::relay(bool state)
|
||||||
{
|
{
|
||||||
char subtopic[10]="/";
|
|
||||||
char val[10];
|
|
||||||
digitalWrite(pin,(state)?ACTIVE:INACTIVE);
|
digitalWrite(pin,(state)?ACTIVE:INACTIVE);
|
||||||
if (period<1000) return;
|
if (period<1000) return;
|
||||||
debugSerial<<F("Out ")<<pin<<F(" is ")<<(state)<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Out ")<<pin<<F(" is ")<<(state)<<endl;
|
||||||
|
pubAction(state);
|
||||||
|
//debugSerial << F("OUT: ")<<F("pub action ") << F(":")<<item->itemArr->name<<subtopic<<F("=>")<<val<<endl;
|
||||||
|
|
||||||
strcat_P(subtopic,action_P);
|
|
||||||
short cmd=item->getCmd();
|
|
||||||
if (state)
|
|
||||||
switch(cmd)
|
|
||||||
{
|
|
||||||
case CMD_COOL:
|
|
||||||
strcpy_P(val,cooling_P);
|
|
||||||
break;
|
|
||||||
//case CMD_AUTO:
|
|
||||||
//case CMD_HEAT:
|
|
||||||
//case CMD_ON:
|
|
||||||
//
|
|
||||||
// break;
|
|
||||||
case CMD_DRY:
|
|
||||||
strcpy_P(val,drying_P);
|
|
||||||
break;
|
|
||||||
case CMD_FAN:
|
|
||||||
strcpy_P(val,fan_P);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
strcpy_P(val,heating_P);
|
|
||||||
}
|
|
||||||
else //turned off
|
|
||||||
if (cmd==CMD_OFF) strcpy_P(val,off_P);
|
|
||||||
else strcpy_P(val,idle_P);
|
|
||||||
|
|
||||||
debugSerial << F("pub action ") << publishTopic(item->itemArr->name,val,subtopic)<<F(":")<<item->itemArr->name<<subtopic<<F("=>")<<val<<endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -197,11 +170,11 @@ case S_CMD:
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debugSerial<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
|
||||||
} //switch cmd
|
} //switch cmd
|
||||||
|
|
||||||
default:
|
default:
|
||||||
debugSerial<<F("Unknown suffix ")<<suffixCode<<endl;
|
debugSerial<<F("relayCtr: ")<<F("Unknown suffix ")<<suffixCode<<endl;
|
||||||
} //switch suffix
|
} //switch suffix
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -991,5 +991,76 @@ return crcStream.getCRC16();
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
char* getStringFromJson(aJsonObject * a, int i)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
element = aJson.getArrayItem(a, i);
|
||||||
|
// TODO - human readable JSON objects as alias
|
||||||
|
|
||||||
|
if (element && element->type == aJson_String) return element->valuestring;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* getStringFromJson(aJsonObject * a, char * name)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
if (element && element->type == aJson_String) return element->valuestring;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getIntFromJson(aJsonObject * a, int i, long def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
element = aJson.getArrayItem(a, i);
|
||||||
|
// TODO - human readable JSON objects as alias
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
long getIntFromJson(aJsonObject * a, char * name, long def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getFloatFromJson(aJsonObject * a, int i, float def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Array)
|
||||||
|
element = aJson.getArrayItem(a, i);
|
||||||
|
// TODO - human readable JSON objects as alias
|
||||||
|
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getFloatFromJson(aJsonObject * a, char * name, float def)
|
||||||
|
{
|
||||||
|
aJsonObject * element = NULL;
|
||||||
|
if (!a) return NULL;
|
||||||
|
if (a->type == aJson_Object)
|
||||||
|
element = aJson.getObjectItem(a, name);
|
||||||
|
|
||||||
|
if (element && element->type == aJson_Float) return element->valuefloat;
|
||||||
|
//if (element && element->type == aJson_Int) return element->valueint;
|
||||||
|
return def;
|
||||||
|
}
|
||||||
#pragma message(VAR_NAME_VALUE(debugSerial))
|
#pragma message(VAR_NAME_VALUE(debugSerial))
|
||||||
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD))
|
||||||
|
|||||||
@@ -82,7 +82,12 @@ bool checkToken(char * token, char * data);
|
|||||||
bool isProtectedPin(short pin);
|
bool isProtectedPin(short pin);
|
||||||
bool i2cReset();
|
bool i2cReset();
|
||||||
uint16_t getCRC(aJsonObject * in);
|
uint16_t getCRC(aJsonObject * in);
|
||||||
|
char* getStringFromJson(aJsonObject * a, int i);
|
||||||
|
char* getStringFromJson(aJsonObject * a, char * name);
|
||||||
|
long getIntFromJson(aJsonObject * a, int i, long def = 0);
|
||||||
|
long getIntFromJson(aJsonObject * a, char * name, long def = 0);
|
||||||
|
float getFloatFromJson(aJsonObject * a, int i, float def = 0.0);
|
||||||
|
float getFloatFromJson(aJsonObject * a, char * name, float def = 0.0);
|
||||||
#ifdef CANDRV
|
#ifdef CANDRV
|
||||||
#include "util/crc16_.h"
|
#include "util/crc16_.h"
|
||||||
class CRCStream : public Stream
|
class CRCStream : public Stream
|
||||||
|
|||||||
@@ -114,7 +114,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
; br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
TimerInterrupt_Generic
|
TimerInterrupt_Generic
|
||||||
d00616/arduino-NVM @ ^0.9.1
|
d00616/arduino-NVM @ ^0.9.1
|
||||||
|
|
||||||
@@ -183,7 +184,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
; br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
|
||||||
@@ -255,7 +257,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
;ESPmDNS
|
;ESPmDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
@@ -323,7 +326,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
rweather/Crypto
|
rweather/Crypto
|
||||||
@@ -390,7 +394,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
;https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
;https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
|
||||||
@@ -464,7 +469,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
rweather/Crypto
|
rweather/Crypto
|
||||||
@@ -516,7 +522,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
|
||||||
@@ -612,7 +619,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA.git
|
https://github.com/anklimov/ArduinoOTA.git
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
;ArduinoMDNS
|
;ArduinoMDNS
|
||||||
;MDNS
|
;MDNS
|
||||||
ESP8266mDNS
|
ESP8266mDNS
|
||||||
@@ -665,7 +673,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
|
||||||
@@ -731,7 +740,8 @@ lib_deps =
|
|||||||
https://github.com/anklimov/ArduinoOTA
|
https://github.com/anklimov/ArduinoOTA
|
||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/rlogiacco/CircularBuffer
|
https://github.com/rlogiacco/CircularBuffer
|
||||||
@@ -785,7 +795,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
https://github.com/arcao/Syslog.git
|
https://github.com/arcao/Syslog.git
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.gitv
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
|
|
||||||
@@ -842,7 +853,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
SPI
|
SPI
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
@@ -910,7 +922,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
SPI
|
SPI
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
ArduinoMDNS
|
ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
@@ -979,7 +992,8 @@ lib_deps =
|
|||||||
Adafruit MCP23017 Arduino Library
|
Adafruit MCP23017 Arduino Library
|
||||||
Adafruit BusIO
|
Adafruit BusIO
|
||||||
SPI
|
SPI
|
||||||
br3ttb/PID@^1.2.1
|
;br3ttb/PID@^1.2.1
|
||||||
|
https://github.com/anklimov/Arduino-PID-Library.git
|
||||||
; ArduinoMDNS
|
; ArduinoMDNS
|
||||||
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
https://github.com/khoih-prog/TimerInterrupt_Generic.git
|
||||||
https://github.com/anklimov/ModbusMaster
|
https://github.com/anklimov/ModbusMaster
|
||||||
|
|||||||
Reference in New Issue
Block a user