mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 03:39:49 +03:00
MODBUS: prefetch option for write reg (check-before-write),
AC: suppressing garbage status after CMD, PID: NOT_FILTER_PID_OUT for repeating values^ by default
This commit is contained in:
@@ -23,6 +23,8 @@ extern bool disableCMD;
|
|||||||
#define AC_UNKNOWN CST_UNKNOWN
|
#define AC_UNKNOWN CST_UNKNOWN
|
||||||
#define AC_IDLE CST_INITIALIZED
|
#define AC_IDLE CST_INITIALIZED
|
||||||
#define AC_SENDING CST_USER
|
#define AC_SENDING CST_USER
|
||||||
|
#define AC_AWAITINGCMD CST_USER+1
|
||||||
|
#define AC_POLL CST_USER+2
|
||||||
|
|
||||||
//byte inCheck = 0;
|
//byte inCheck = 0;
|
||||||
byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса
|
byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса
|
||||||
@@ -237,6 +239,7 @@ SubmitParameters("fan",icmd);
|
|||||||
if (!(store->power & 0x01)) {strcpy_P(s_buffer,OFF_P);icmd.Cmd(CMD_OFF);}
|
if (!(store->power & 0x01)) {strcpy_P(s_buffer,OFF_P);icmd.Cmd(CMD_OFF);}
|
||||||
publishTopic(item->itemArr->name, s_buffer,"/cmd");
|
publishTopic(item->itemArr->name, s_buffer,"/cmd");
|
||||||
SubmitParameters("cmd",icmd);
|
SubmitParameters("cmd",icmd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (store->power & 0x01)
|
if (store->power & 0x01)
|
||||||
publishTopic(item->itemArr->name, s_buffer,"/cmd");
|
publishTopic(item->itemArr->name, s_buffer,"/cmd");
|
||||||
@@ -393,16 +396,46 @@ case AC_SENDING:
|
|||||||
store->timestamp=millisNZ();
|
store->timestamp=millisNZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case AC_AWAITINGCMD: //Flusing port for 5 sec, poll status
|
||||||
|
|
||||||
|
if (store->timestamp && isTimeOver(store->timestamp,millis(),5000))
|
||||||
|
{
|
||||||
|
setStatus(AC_POLL);
|
||||||
|
store->timestamp=millisNZ();
|
||||||
|
store->inCheck=0;
|
||||||
|
debugSerial<<F("AC: Unmute")<<endl;
|
||||||
|
}
|
||||||
|
while(ACSerial->available())
|
||||||
|
{
|
||||||
|
delay(2);
|
||||||
|
ACSerial->read();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case AC_IDLE:
|
||||||
|
if (store->timestamp && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING)) setStatus(AC_POLL);
|
||||||
|
if (cause!=POLLING_SLOW) return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AC_POLL:
|
||||||
|
if (cause!=POLLING_SLOW) return false;
|
||||||
|
|
||||||
|
debugSerial.println(F("AC: Polling"));
|
||||||
|
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
||||||
|
store->timestamp=millisNZ();
|
||||||
|
setStatus(AC_IDLE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cause!=POLLING_SLOW) return false;
|
/*if (cause!=POLLING_SLOW) return false;
|
||||||
|
|
||||||
if ((Status() == AC_IDLE) && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING))
|
if ((Status() == AC_IDLE) && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING))
|
||||||
{
|
{
|
||||||
debugSerial.println(F("AC: Polling"));
|
debugSerial.println(F("AC: Polling"));
|
||||||
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if(ACSerial->available() >= 37){ //was 0
|
if(ACSerial->available() >= 37){ //was 0
|
||||||
ACSerial->readBytes(store->data, 37);
|
ACSerial->readBytes(store->data, 37);
|
||||||
while(ACSerial->available()){
|
while(ACSerial->available()){
|
||||||
@@ -468,7 +501,10 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
|
|||||||
|
|
||||||
case S_CMD:
|
case S_CMD:
|
||||||
// s_mode[0]='\0';
|
// s_mode[0]='\0';
|
||||||
store->inCheck=0;
|
|
||||||
|
store->timestamp=millisNZ();
|
||||||
|
setStatus(AC_AWAITINGCMD);
|
||||||
|
|
||||||
switch (cmd.getCmd())
|
switch (cmd.getCmd())
|
||||||
{
|
{
|
||||||
case CMD_ON:
|
case CMD_ON:
|
||||||
@@ -476,7 +512,7 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
|
|||||||
store->data[B_POWER] = store->power;
|
store->data[B_POWER] = store->power;
|
||||||
store->data[B_POWER] |= 1;
|
store->data[B_POWER] |= 1;
|
||||||
SendData(on, sizeof(on)/sizeof(byte));
|
SendData(on, sizeof(on)/sizeof(byte));
|
||||||
// publishTopic(item->itemArr->name,"ON","/cmd");
|
//publishTopic(item->itemArr->name,"ON","/cmd"); //
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
case CMD_OFF:
|
case CMD_OFF:
|
||||||
@@ -484,7 +520,7 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
|
|||||||
store->data[B_POWER] = store->power;
|
store->data[B_POWER] = store->power;
|
||||||
store->data[B_POWER] &= ~1;
|
store->data[B_POWER] &= ~1;
|
||||||
SendData(off, sizeof(off)/sizeof(byte));
|
SendData(off, sizeof(off)/sizeof(byte));
|
||||||
// publishTopic(item->itemArr->name,"OFF","/cmd");
|
publishTopic(item->itemArr->name,"OFF","/cmd"); //
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
@@ -532,62 +568,63 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
|
|||||||
|
|
||||||
case S_FAN:
|
case S_FAN:
|
||||||
s_speed[0]='\0';
|
s_speed[0]='\0';
|
||||||
switch (cmd.getCmd())
|
switch (cmd.getCmd())
|
||||||
{
|
{
|
||||||
case CMD_AUTO:
|
case CMD_AUTO:
|
||||||
store->data[B_FAN_SPD] = 3;
|
store->data[B_FAN_SPD] = 3;
|
||||||
strcpy_P(s_speed,AUTO_P);
|
strcpy_P(s_speed,AUTO_P);
|
||||||
break;
|
break;
|
||||||
case CMD_HIGH:
|
case CMD_HIGH:
|
||||||
store->data[B_FAN_SPD] = 0;
|
store->data[B_FAN_SPD] = 0;
|
||||||
strcpy_P(s_speed,HIGH_P);
|
strcpy_P(s_speed,HIGH_P);
|
||||||
break;
|
break;
|
||||||
case CMD_MED:
|
case CMD_MED:
|
||||||
store->data[B_FAN_SPD] = 1;
|
store->data[B_FAN_SPD] = 1;
|
||||||
strcpy_P(s_speed,MED_P);
|
strcpy_P(s_speed,MED_P);
|
||||||
break;
|
break;
|
||||||
case CMD_LOW:
|
case CMD_LOW:
|
||||||
store->data[B_FAN_SPD] = 2;
|
store->data[B_FAN_SPD] = 2;
|
||||||
strcpy_P(s_speed,LOW_P);
|
strcpy_P(s_speed,LOW_P);
|
||||||
break;
|
break;
|
||||||
case CMD_OFF:
|
case CMD_OFF:
|
||||||
store->inCheck=0;
|
store->inCheck=0;
|
||||||
store->data[B_POWER] = store->power;
|
store->timestamp=millisNZ();
|
||||||
store->data[B_POWER] &= ~1;
|
store->data[B_POWER] = store->power;
|
||||||
SendData(off, sizeof(off)/sizeof(byte));
|
store->data[B_POWER] &= ~1;
|
||||||
return 1;
|
SendData(off, sizeof(off)/sizeof(byte));
|
||||||
default:
|
return 1;
|
||||||
{
|
default:
|
||||||
uint8_t speed = 0;
|
{
|
||||||
if (cmd.getInt()) speed = map(cmd.getInt(),1,255,1,3);
|
uint8_t speed = 0;
|
||||||
store->inCheck=0;
|
if (cmd.getInt()) speed = map(cmd.getInt(),1,255,1,3);
|
||||||
switch (speed) {
|
store->inCheck=0;
|
||||||
case 0:
|
switch (speed) {
|
||||||
store->data[B_POWER] = store->power;
|
case 0:
|
||||||
store->data[B_POWER] &= ~1;
|
store->data[B_POWER] = store->power;
|
||||||
SendData(off, sizeof(off)/sizeof(byte));
|
store->data[B_POWER] &= ~1;
|
||||||
return 1;
|
SendData(off, sizeof(off)/sizeof(byte));
|
||||||
case 1:
|
return 1;
|
||||||
store->data[B_FAN_SPD] = 2;
|
case 1:
|
||||||
strcpy_P(s_speed,LOW_P);
|
store->data[B_FAN_SPD] = 2;
|
||||||
store->data[B_POWER] = store->power;
|
strcpy_P(s_speed,LOW_P);
|
||||||
store->data[B_POWER] |= 1;
|
store->data[B_POWER] = store->power;
|
||||||
break;
|
store->data[B_POWER] |= 1;
|
||||||
case 2:
|
break;
|
||||||
store->data[B_FAN_SPD] = 1;
|
case 2:
|
||||||
strcpy_P(s_speed,MED_P);
|
store->data[B_FAN_SPD] = 1;
|
||||||
store->data[B_POWER] = store->power;
|
strcpy_P(s_speed,MED_P);
|
||||||
store->data[B_POWER] |= 1;
|
store->data[B_POWER] = store->power;
|
||||||
break;
|
store->data[B_POWER] |= 1;
|
||||||
case 3:
|
break;
|
||||||
store->data[B_FAN_SPD] = 0;
|
case 3:
|
||||||
strcpy_P(s_speed,HIGH_P);
|
store->data[B_FAN_SPD] = 0;
|
||||||
store->data[B_POWER] = store->power;
|
strcpy_P(s_speed,HIGH_P);
|
||||||
store->data[B_POWER] |= 1;
|
store->data[B_POWER] = store->power;
|
||||||
}
|
store->data[B_POWER] |= 1;
|
||||||
}
|
}
|
||||||
//TODO - mapping digits to speed
|
}
|
||||||
}
|
//TODO - mapping digits to speed
|
||||||
|
}
|
||||||
publishTopic(item->itemArr->name,s_speed,"/fan");
|
publishTopic(item->itemArr->name,s_speed,"/fan");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -60,45 +60,6 @@ const reg_t regSize_P[] PROGMEM =
|
|||||||
} ;
|
} ;
|
||||||
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
||||||
|
|
||||||
/*
|
|
||||||
const serial_t serialModes_P[] PROGMEM =
|
|
||||||
{
|
|
||||||
{ "8E1", (serialParamType) SERIAL_8E1},//(uint16_t) US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_EVEN },
|
|
||||||
{ "8N1", (serialParamType) SERIAL_8N1},
|
|
||||||
{ "8E2", (serialParamType) SERIAL_8E2},
|
|
||||||
{ "8N2", (serialParamType) SERIAL_8N2},
|
|
||||||
{ "8O1", (serialParamType) SERIAL_8O1},
|
|
||||||
{ "8O2", (serialParamType) SERIAL_8O2},
|
|
||||||
// { "8M1", SERIAL_8M1},
|
|
||||||
// { "8S1", SERIAL_8S1},
|
|
||||||
{ "7E1", (serialParamType) SERIAL_7E1},//(uint16_t) US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_EVEN },
|
|
||||||
{ "7N1", (serialParamType) SERIAL_7N1},
|
|
||||||
{ "7E2", (serialParamType) SERIAL_7E2},
|
|
||||||
{ "7N2", (serialParamType) SERIAL_7N2},
|
|
||||||
{ "7O1", (serialParamType) SERIAL_7O1},
|
|
||||||
{ "7O2", (serialParamType) SERIAL_7O2}
|
|
||||||
// { "7M1", SERIAL_7M1},
|
|
||||||
// { "7S1", SERIAL_7S1}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
#define serialModesNum sizeof(serialModes_P)/sizeof(serial_t)
|
|
||||||
|
|
||||||
serialParamType str2SerialParam(char * str)
|
|
||||||
{ debugSerial<<str<<F(" =>");
|
|
||||||
for(uint8_t i=0; i<serialModesNum && str;i++)
|
|
||||||
if (strcmp_P(str, serialModes_P[i].verb) == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
//debugSerial<< i << F(" ") << pgm_read_word_near(&serialModes_P[i].mode)<< endl;
|
|
||||||
if (sizeof(serialModesNum)==4)
|
|
||||||
return pgm_read_dword_near(&serialModes_P[i].mode);
|
|
||||||
else
|
|
||||||
return pgm_read_word_near(&serialModes_P[i].mode);
|
|
||||||
}
|
|
||||||
debugSerial<< F("Default serial mode N81 used");
|
|
||||||
return static_cast<serialParamType> (SERIAL_8N1);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
|
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
|
||||||
|
|
||||||
int str2regSize(char * str)
|
int str2regSize(char * str)
|
||||||
@@ -223,6 +184,7 @@ switch (regType) {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
debugSerial<<F("MBUS: Not supported reg type\n");
|
debugSerial<<F("MBUS: Not supported reg type\n");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
mbusSlenceTimer = millisNZ();
|
mbusSlenceTimer = millisNZ();
|
||||||
if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<_HEX(result)<<endl;
|
if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<_HEX(result)<<endl;
|
||||||
@@ -347,7 +309,19 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
|
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
|
||||||
executeWithoutCheck=true;
|
executeWithoutCheck=true;
|
||||||
}
|
}
|
||||||
else errorSerial<<F("reg# out of range")<<endl;
|
else
|
||||||
|
{
|
||||||
|
debugSerial<<F("def reg# ")<<defMappingObj->valueint<<F(" out of range buffer, fetching")<<endl;
|
||||||
|
////to prevent CORRUPTION if using same buffer
|
||||||
|
uint16_t localBuffer;
|
||||||
|
node.setResponseBuffer(&localBuffer,1);
|
||||||
|
if (readModbus(defMappingObj->valueint,regType,1))
|
||||||
|
{
|
||||||
|
mappedParam = findRegister(defMappingObj->valueint,0,regType,defMappingObj->valueint,defMappingObj->valueint,false,&submitRecurrentOut);
|
||||||
|
executeWithoutCheck=true;
|
||||||
|
}
|
||||||
|
node.setDefaultResponseBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case aJson_String: // parameter name
|
case aJson_String: // parameter name
|
||||||
@@ -358,8 +332,6 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
|
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
|
||||||
if (itemParObj)
|
if (itemParObj)
|
||||||
{
|
{
|
||||||
//aJsonObject * markObj = execObj;
|
|
||||||
//if (execObj->type == aJson_Array) markObj = execObj->child;
|
|
||||||
//Retrive previous data
|
//Retrive previous data
|
||||||
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
|
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
|
||||||
if (lastMeasured && lastMeasured->type ==aJson_Int)
|
if (lastMeasured && lastMeasured->type ==aJson_Int)
|
||||||
@@ -417,37 +389,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
}
|
||||||
aJsonObject *nextRegObj = NULL;
|
|
||||||
int registerType = 0;
|
|
||||||
|
|
||||||
nextRegObj = aJson.getObjectItem(paramObj, "nextreg");
|
|
||||||
if (nextRegObj) registerType=MODBUS_HOLDING_REG_TYPE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextRegObj = aJson.getObjectItem(paramObj, "nextir");
|
|
||||||
if (nextRegObj) registerType=MODBUS_INPUT_REG_TYPE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextRegObj = aJson.getObjectItem(paramObj, "nextcoil");
|
|
||||||
if (nextRegObj) registerType=MODBUS_COIL_REG_TYPE;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextRegObj = aJson.getObjectItem(paramObj, "nextdin");
|
|
||||||
if (nextRegObj) registerType=MODBUS_DISCRETE_REG_TYPE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (registerType && nextRegObj && (nextRegObj->type) ==aJson_Int && (nextRegObj->valueint>= registerFrom) && (nextRegObj->valueint<=registerTo))
|
|
||||||
{
|
|
||||||
debugSerial<<F("Recurrent searching nextreg")<<endl;
|
|
||||||
mappedParam = findRegister(nextRegObj->valueint,nextRegObj->valueint-registerFrom,registerType,registerFrom,registerTo,false,&submitRecurrentOut);
|
|
||||||
executeWithoutCheck=true;
|
|
||||||
}
|
|
||||||
else errorSerial<<F("nextreg out of range")<<endl;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
traceSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
|
traceSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
|
||||||
} //mapping
|
} //mapping
|
||||||
@@ -481,6 +423,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
lastMeasured->valueint=param;
|
lastMeasured->valueint=param;
|
||||||
|
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
|
||||||
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -495,7 +438,12 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
if (executeWithoutCheck)
|
if (executeWithoutCheck)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (doExecution && (submitRecurrentOut || *submitParam)) executeCommand(execObj, -1, mappedParam);
|
if (doExecution && (submitRecurrentOut || *submitParam))
|
||||||
|
{
|
||||||
|
executeCommand(execObj, -1, mappedParam);
|
||||||
|
*submitParam=true; //if requrrent check has submit smth - report it.
|
||||||
|
}
|
||||||
|
|
||||||
return mappedParam;
|
return mappedParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,6 +466,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//if (submitRecurrentOut) *submitParam=true; //if requrrent check has submit smth - report it.
|
||||||
return mappedParam;
|
return mappedParam;
|
||||||
}
|
}
|
||||||
paramObj=paramObj->next;
|
paramObj=paramObj->next;
|
||||||
@@ -582,7 +531,7 @@ void out_Modbus::initLine()
|
|||||||
node.begin(item->getArg(0), modbusSerial);
|
node.begin(item->getArg(0), modbusSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
|
int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
|
||||||
{
|
{
|
||||||
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
|
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
|
||||||
|
|
||||||
@@ -595,45 +544,118 @@ int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
|
|||||||
{
|
{
|
||||||
regObj = aJson.getObjectItem(templateParamObj, "coil");
|
regObj = aJson.getObjectItem(templateParamObj, "coil");
|
||||||
if (!regObj) {errorSerial<<F(" internal send error - no reg/coil")<<endl; return -2;}
|
if (!regObj) {errorSerial<<F(" internal send error - no reg/coil")<<endl; return -2;}
|
||||||
else regType = PAR_COIL;
|
else outValue->subtype = PAR_COIL;
|
||||||
}
|
}
|
||||||
|
if (regObj->type != aJson_Int) {errorSerial<<F(" Reg/coil must be int")<<endl; return -2;}
|
||||||
|
|
||||||
|
aJsonObject * prefetchObj = aJson.getObjectItem(templateParamObj, "prefetch");
|
||||||
|
aJsonObject *lastMeasured = NULL;
|
||||||
|
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
// int8_t regType = PAR_I16;
|
if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valuebool)
|
||||||
// aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
|
{
|
||||||
// if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
|
int modbusRegType = (outValue->subtype == PAR_COIL) ? MODBUS_COIL_REG_TYPE:MODBUS_HOLDING_REG_TYPE;
|
||||||
|
debugSerial<<F("\nMBUS: prefetching ")<<paramName<<F(" #") <<regObj->valueint << " type:" << modbusRegType << " ";
|
||||||
|
|
||||||
switch(regType) {
|
/// to prevent CORRUPTIOIN if using same buffer
|
||||||
|
uint16_t localBuffer;
|
||||||
|
node.setResponseBuffer(&localBuffer,1);
|
||||||
|
|
||||||
|
bool successRead = readModbus(regObj->valueint,modbusRegType,1);
|
||||||
|
|
||||||
|
|
||||||
|
if (successRead)
|
||||||
|
{
|
||||||
|
#ifdef PREFETCH_EXEC_IMMEDIALELLY
|
||||||
|
// option to execute if changed immediatelly
|
||||||
|
bool submited = false;
|
||||||
|
findRegister(regObj->valueint,0,modbusRegType,regObj->valueint,regObj->valueint,true,&submited);
|
||||||
|
node.setDefaultResponseBuffer();
|
||||||
|
|
||||||
|
if (submited)
|
||||||
|
{
|
||||||
|
debugSerial << F("MBUS:")<<paramName<< (" val changed. Write cancelled")<<endl;
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
else debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Option to skip writing if change, let next polling take of change
|
||||||
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
|
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
||||||
|
{
|
||||||
|
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramName);
|
||||||
|
if (execObj)
|
||||||
|
{
|
||||||
|
aJsonObject * markObj = execObj;
|
||||||
|
if (execObj->type == aJson_Array) markObj = execObj->child;
|
||||||
|
//Retrive previous data
|
||||||
|
lastMeasured = aJson.getObjectItem(markObj,"@S");
|
||||||
|
if (lastMeasured)
|
||||||
|
{
|
||||||
|
if (lastMeasured->type == aJson_Int)
|
||||||
|
{
|
||||||
|
traceSerial<<F(" Last:")<<lastMeasured->valueint<< F(" Now:") << localBuffer<<endl;
|
||||||
|
|
||||||
|
if (lastMeasured->valueint != localBuffer)
|
||||||
|
{
|
||||||
|
debugSerial << F("MBUS:")<<paramName<< F(" val changed.")<<endl;
|
||||||
|
node.setDefaultResponseBuffer();
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
node.setDefaultResponseBuffer();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch(outValue->subtype) {
|
||||||
case PAR_U16:
|
case PAR_U16:
|
||||||
case PAR_I16:
|
case PAR_I16:
|
||||||
case PAR_TENS:
|
case PAR_TENS:
|
||||||
case PAR_100:
|
case PAR_100:
|
||||||
res = node.writeSingleRegister(regObj->valueint,value);
|
res = node.writeSingleRegister(regObj->valueint,outValue->valueint);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PAR_I32:
|
case PAR_I32:
|
||||||
case PAR_U32:
|
case PAR_U32:
|
||||||
res = node.writeSingleRegister(regObj->valueint,swap(value & 0xFFFF));
|
res = node.writeSingleRegister(regObj->valueint,swap(outValue->valueint & 0xFFFF));
|
||||||
res += node.writeSingleRegister(regObj->valueint+1,swap(value >> 16)) ;
|
res += node.writeSingleRegister(regObj->valueint+1,swap(outValue->valueint >> 16)) ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAR_U8L:
|
case PAR_U8L:
|
||||||
case PAR_I8L:
|
case PAR_I8L:
|
||||||
res = node.writeSingleRegister(regObj->valueint,value & 0xFF);
|
res = node.writeSingleRegister(regObj->valueint,outValue->valueint & 0xFF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAR_U8H:
|
case PAR_U8H:
|
||||||
case PAR_I8H:
|
case PAR_I8H:
|
||||||
res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8);
|
res = node.writeSingleRegister(regObj->valueint,(outValue->valueint & 0xFFFF)>> 8);
|
||||||
break;
|
break;
|
||||||
case PAR_COIL:
|
case PAR_COIL:
|
||||||
res = node.writeSingleCoil (regObj->valueint,value);
|
res = node.writeSingleCoil (regObj->valueint,outValue->valueint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mbusSlenceTimer = millisNZ();
|
mbusSlenceTimer = millisNZ();
|
||||||
debugSerial<<F("MBUS res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<value<<endl;
|
debugSerial<<F("MBUS res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<outValue->valueint<<endl;
|
||||||
|
|
||||||
|
//If wrote - suppress action on poll
|
||||||
|
if ((res ==0) && (outValue->type == aJson_Int) && lastMeasured && (lastMeasured->type == aJson_Int)) lastMeasured->valueint = outValue->valueint;
|
||||||
|
|
||||||
|
|
||||||
return ( res == 0);
|
return ( res == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,7 +696,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
{
|
{
|
||||||
savedValue = outValue->valueint;
|
savedValue = outValue->valueint;
|
||||||
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" ";
|
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" ";
|
||||||
sendRes = sendModbus(execObj->name,outValue->valueint,outValue->subtype);
|
sendRes = sendModbus(execObj->name,outValue);
|
||||||
}
|
}
|
||||||
while (savedValue != outValue->valueint); //repeat sending if target value changed while we're waited for mbus responce
|
while (savedValue != outValue->valueint); //repeat sending if target value changed while we're waited for mbus responce
|
||||||
|
|
||||||
@@ -683,6 +705,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
case 1: //success
|
case 1: //success
|
||||||
execObj->subtype&=~ MB_NEED_SEND;
|
execObj->subtype&=~ MB_NEED_SEND;
|
||||||
onceSendOk=true;
|
onceSendOk=true;
|
||||||
|
if (outValue->type == aJson_Int)
|
||||||
///return 1; //relax
|
///return 1; //relax
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -692,6 +715,11 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++;
|
if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++;
|
||||||
errorSerial<<"Attempt: "<< (execObj->subtype & 3) <<endl;
|
errorSerial<<"Attempt: "<< (execObj->subtype & 3) <<endl;
|
||||||
break;
|
break;
|
||||||
|
case -3:
|
||||||
|
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" sending cancelled")<<endl;
|
||||||
|
//outValue->valueint=
|
||||||
|
execObj->subtype&=~ MB_NEED_SEND;
|
||||||
|
break;
|
||||||
default: //param not found
|
default: //param not found
|
||||||
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl;
|
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl;
|
||||||
execObj->subtype&=~ MB_NEED_SEND;
|
execObj->subtype&=~ MB_NEED_SEND;
|
||||||
@@ -778,6 +806,7 @@ int8_t regType = PAR_I16;
|
|||||||
aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
|
aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
|
||||||
aJsonObject * mapObj = aJson.getObjectItem(templateParamObj, "map");
|
aJsonObject * mapObj = aJson.getObjectItem(templateParamObj, "map");
|
||||||
|
|
||||||
|
|
||||||
if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
|
if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
|
||||||
switch(regType) {
|
switch(regType) {
|
||||||
case PAR_I16:
|
case PAR_I16:
|
||||||
@@ -811,20 +840,14 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr);
|
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr);
|
||||||
if (execObj && ((execObj->type == aJson_Object) || (execObj->type == aJson_Array)))
|
if (execObj && ((execObj->type == aJson_Object) || (execObj->type == aJson_Array)))
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
aJsonObject *polledValue = aJson.getObjectItem(execObj,"@S");
|
|
||||||
if (polledValue && polledValue->type == aJson_Int && (polledValue->valueint == Value))
|
|
||||||
{
|
|
||||||
debugSerial<<F("Ignored - not changed")<<endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
else */
|
|
||||||
{ //Schedule update
|
aJsonObject * markObj = execObj;
|
||||||
|
if (execObj->type == aJson_Array) markObj = execObj->child;
|
||||||
|
|
||||||
|
//Schedule update
|
||||||
execObj->subtype |= MB_NEED_SEND;
|
execObj->subtype |= MB_NEED_SEND;
|
||||||
|
|
||||||
aJsonObject * markObj = execObj;
|
|
||||||
if (execObj->type == aJson_Array) markObj = execObj->child;
|
|
||||||
|
|
||||||
aJsonObject *outValue = aJson.getObjectItem(markObj,"@V");
|
aJsonObject *outValue = aJson.getObjectItem(markObj,"@V");
|
||||||
if (outValue) // Existant. Preserve original @type
|
if (outValue) // Existant. Preserve original @type
|
||||||
{
|
{
|
||||||
@@ -839,15 +862,17 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
outValue = aJson.getObjectItem(markObj,"@V");
|
outValue = aJson.getObjectItem(markObj,"@V");
|
||||||
if (outValue) outValue->subtype =regType & 0xF;
|
if (outValue) outValue->subtype =regType & 0xF;
|
||||||
}
|
}
|
||||||
|
/* Conflict with pre-fetching
|
||||||
aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
|
aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
|
||||||
if (polledValue && outValue->type == aJson_Int)
|
if (polledValue && outValue->type == aJson_Int)
|
||||||
{
|
{
|
||||||
|
traceSerial<<"MBUS: not Stored "<<Value<<" to @S of "<<item->itemArr->name<<":"<<templateParamObj->name<<endl;
|
||||||
polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
|
polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
|
||||||
polledValue->subtype&=~MB_VALUE_OUTDATED;
|
polledValue->subtype&=~MB_VALUE_OUTDATED;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ protected:
|
|||||||
itemCmd findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution = true, bool * submitParam = NULL);
|
itemCmd findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution = true, bool * submitParam = NULL);
|
||||||
void pollModbus(aJsonObject * reg, int regType);
|
void pollModbus(aJsonObject * reg, int regType);
|
||||||
void initLine();
|
void initLine();
|
||||||
int sendModbus(char * paramName, int32_t value, uint8_t regType);
|
int sendModbus(char * paramName, aJsonObject * outValue);
|
||||||
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
|
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
|
|||||||
if (store->alarmArmed) debugSerial << F(" <ALM>");
|
if (store->alarmArmed) debugSerial << F(" <ALM>");
|
||||||
debugSerial<<endl;
|
debugSerial<<endl;
|
||||||
|
|
||||||
if (((abs(store->output-store->prevOut)>OUTPUT_TRESHOLD) || (item->getFlag(FLAG_ACTION_NEEDED))) && !store->alarmArmed)
|
if (( (NOT_FILTER_PID_OUT || (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);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#ifndef NOT_FILTER_PID_OUT
|
||||||
|
#define NOT_FILTER_PID_OUT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DHCP_ATTEMPTS_FALLBACK 3
|
#define DHCP_ATTEMPTS_FALLBACK 3
|
||||||
#define TENS_FRACT_LEN 2
|
#define TENS_FRACT_LEN 2
|
||||||
#define TENS_BASE 100
|
#define TENS_BASE 100
|
||||||
@@ -84,10 +88,17 @@
|
|||||||
//#define T_ATTEMPTS 200
|
//#define T_ATTEMPTS 200
|
||||||
//#define IET_TEMP 0
|
//#define IET_TEMP 0
|
||||||
//#define IET_ATTEMPTS 1
|
//#define IET_ATTEMPTS 1
|
||||||
|
#ifndef THERMO_GIST_CELSIUS
|
||||||
#define THERMO_GIST_CELSIUS 1.
|
#define THERMO_GIST_CELSIUS 1.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef THERMO_OVERHEAT_CELSIUS
|
||||||
#define THERMO_OVERHEAT_CELSIUS 38.
|
#define THERMO_OVERHEAT_CELSIUS 38.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FM_OVERHEAT_CELSIUS
|
||||||
#define FM_OVERHEAT_CELSIUS 40.
|
#define FM_OVERHEAT_CELSIUS 40.
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MIN_VOLUME
|
#ifndef MIN_VOLUME
|
||||||
#define MIN_VOLUME 20
|
#define MIN_VOLUME 20
|
||||||
|
|||||||
Reference in New Issue
Block a user