mirror of
https://github.com/anklimov/lighthub
synced 2025-12-06 11:49:51 +03:00
mbus coils, discr inputs, new logic. AC - feedback
This commit is contained in:
@@ -369,21 +369,21 @@ int Item::getArg(short n) //Return arg int or first array element if Arg is arra
|
|||||||
|
|
||||||
float Item::getFloatArg(short n) //Return arg float or first array element if Arg is array
|
float Item::getFloatArg(short n) //Return arg float or first array element if Arg is array
|
||||||
{
|
{
|
||||||
if (!itemArg) return 0;//-1;
|
if (!itemArg) return 0.0;//-1;
|
||||||
if ((itemArg->type == aJson_Array) && ( n < aJson.getArraySize(itemArg)))
|
if ((itemArg->type == aJson_Array) && ( n < aJson.getArraySize(itemArg)))
|
||||||
{
|
{
|
||||||
aJsonObject * obj = aJson.getArrayItem(itemArg, n);
|
aJsonObject * obj = aJson.getArrayItem(itemArg, n);
|
||||||
if (obj && obj->type == aJson_Int) return obj->valueint;
|
if (obj && obj->type == aJson_Int) return static_cast<float> (obj->valueint);
|
||||||
if (obj && obj->type == aJson_Float) return obj->valuefloat;
|
if (obj && obj->type == aJson_Float) return obj->valuefloat;
|
||||||
return 0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!n)
|
else if (!n)
|
||||||
{
|
{
|
||||||
if (itemArg->type == aJson_Int) return itemArg->valueint;
|
if (itemArg->type == aJson_Int) return static_cast<float>(itemArg->valueint);
|
||||||
else if (itemArg->type == aJson_Float) return itemArg->valuefloat;
|
else if (itemArg->type == aJson_Float) return itemArg->valuefloat;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short Item::getArgCount()
|
short Item::getArgCount()
|
||||||
|
|||||||
@@ -2192,12 +2192,33 @@ void setup_main() {
|
|||||||
#endif
|
#endif
|
||||||
//debugSerialPort << "Checkin EEPROM integrity (signature)"<<endl;
|
//debugSerialPort << "Checkin EEPROM integrity (signature)"<<endl;
|
||||||
|
|
||||||
if (!sysConf.isValidSysConf())
|
bool needClean = false;
|
||||||
|
#ifdef CONFIG_CLEAN_PIN
|
||||||
|
pinMode(CONFIG_CLEAN_PIN,INPUT_PULLUP);
|
||||||
|
int i = 0;
|
||||||
|
while ((digitalRead(CONFIG_CLEAN_PIN)==LOW) && !needClean)
|
||||||
|
{
|
||||||
|
|
||||||
|
statusLED.set(ledRED);
|
||||||
|
delay(500);
|
||||||
|
statusLED.set(ledGREEN);
|
||||||
|
delay(500);
|
||||||
|
statusLED.set(ledBLUE);
|
||||||
|
delay(500);
|
||||||
|
if (i>4) needClean = true;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (needClean) cmdFunctionClearEEPROM(0, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!sysConf.isValidSysConf() || needClean)
|
||||||
{
|
{
|
||||||
#if defined(debugSerialPort) && !defined(NOSERIAL)
|
#if defined(debugSerialPort) && !defined(NOSERIAL)
|
||||||
debugSerialPort.println(F("No valid EEPROM data. Initializing."));
|
debugSerialPort.println(F("Initializing EEPROM."));
|
||||||
#endif
|
#endif
|
||||||
sysConf.clear();
|
cmdFunctionClearEEPROM(0, NULL);
|
||||||
|
//sysConf.clear();
|
||||||
}
|
}
|
||||||
else debugSerialPort << F("EEPROM signature ok")<<endl;
|
else debugSerialPort << F("EEPROM signature ok")<<endl;
|
||||||
// scan_i2c_bus();
|
// scan_i2c_bus();
|
||||||
@@ -2884,7 +2905,9 @@ void thermoLoop(void) {
|
|||||||
int thermoStateCommand = thermostat.getCmd();
|
int thermoStateCommand = thermostat.getCmd();
|
||||||
float curTemp = (float) tStore.tempX100/100.;
|
float curTemp = (float) tStore.tempX100/100.;
|
||||||
bool active = thermostat.isActive();
|
bool active = thermostat.isActive();
|
||||||
|
//float overHeatTemp = thermostat.getFloatArg(1);
|
||||||
|
//if (overHeatTemp == 0.) overHeatTemp = THERMO_OVERHEAT_CELSIUS;
|
||||||
|
float overHeatTemp = THERMO_OVERHEAT_CELSIUS;
|
||||||
debugSerial << F(" Set:") << thermoSetting << F(" Cur:") << curTemp
|
debugSerial << F(" Set:") << thermoSetting << F(" Cur:") << curTemp
|
||||||
<< F(" cmd:") << thermoStateCommand;
|
<< F(" cmd:") << thermoStateCommand;
|
||||||
|
|
||||||
@@ -2900,7 +2923,7 @@ void thermoLoop(void) {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Not expired yet
|
{ // Not expired yet
|
||||||
if (curTemp > THERMO_OVERHEAT_CELSIUS) mqttClient.publish("/alarm/ovrht", thermoItem->name);
|
if (curTemp > overHeatTemp) mqttClient.publish("/alarm/ovrht", thermoItem->name);
|
||||||
|
|
||||||
if (!active) thermoRelay(thermoPin,HEATER_OFF);//OFF
|
if (!active) thermoRelay(thermoPin,HEATER_OFF);//OFF
|
||||||
else if (curTemp < thermoSetting - THERMO_GIST_CELSIUS) thermoRelay(thermoPin,HEATER_HEAT);//ON
|
else if (curTemp < thermoSetting - THERMO_GIST_CELSIUS) thermoRelay(thermoPin,HEATER_HEAT);//ON
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ extern bool disableCMD;
|
|||||||
#define AC_IDLE CST_INITIALIZED
|
#define AC_IDLE CST_INITIALIZED
|
||||||
#define AC_SENDING 2
|
#define AC_SENDING 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}; // Команда опроса
|
||||||
|
|
||||||
byte on[] = {255,255,10,0,0,0,0,0,1,1,77,2,91}; // Включение кондиционера
|
byte on[] = {255,255,10,0,0,0,0,0,1,1,77,2,91}; // Включение кондиционера
|
||||||
@@ -66,6 +66,20 @@ void out_AC::getConfig(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void out_AC::SubmitParameters(const char * name, itemCmd value){
|
||||||
|
|
||||||
|
if (!item || !item->itemArg) return;
|
||||||
|
if ((item->itemArg->type == aJson_Array) && ( 1 < aJson.getArraySize(item->itemArg)))
|
||||||
|
{
|
||||||
|
aJsonObject * callbackObj = aJson.getArrayItem(item->itemArg, 1);
|
||||||
|
if (callbackObj && callbackObj->type == aJson_Object)
|
||||||
|
{
|
||||||
|
aJsonObject * execObj = aJson.getObjectItem(callbackObj,name);
|
||||||
|
if (execObj) executeCommand(execObj,-1,value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void out_AC::InsertData(byte data[], size_t size){
|
void out_AC::InsertData(byte data[], size_t size){
|
||||||
|
|
||||||
int fresh =0;
|
int fresh =0;
|
||||||
@@ -77,7 +91,8 @@ void out_AC::InsertData(byte data[], size_t size){
|
|||||||
int fan_spd = 0;
|
int fan_spd = 0;
|
||||||
|
|
||||||
|
|
||||||
char s_mode[10];
|
char s_buffer[10];
|
||||||
|
itemCmd icmd;
|
||||||
|
|
||||||
set_tmp = data[B_SET_TMP]+16;
|
set_tmp = data[B_SET_TMP]+16;
|
||||||
if (set_tmp>40 || set_tmp<16) return;
|
if (set_tmp>40 || set_tmp<16) return;
|
||||||
@@ -128,18 +143,47 @@ void out_AC::InsertData(byte data[], size_t size){
|
|||||||
//publishTopic(item->itemArr->name, (long) fan_spd,"/fan");
|
//publishTopic(item->itemArr->name, (long) fan_spd,"/fan");
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
s_buffer[0]='\0';
|
||||||
|
switch (fan_spd){
|
||||||
|
case 0x00:
|
||||||
|
strcpy_P(s_buffer,HIGH_P);
|
||||||
|
icmd.Cmd(CMD_HIGH);
|
||||||
|
break;
|
||||||
|
case 0x01:
|
||||||
|
strcpy_P(s_buffer,MED_P);
|
||||||
|
icmd.Cmd(CMD_MED);
|
||||||
|
break;
|
||||||
|
case 0x02:
|
||||||
|
strcpy_P(s_buffer,LOW_P);
|
||||||
|
icmd.Cmd(CMD_LOW);
|
||||||
|
break;
|
||||||
|
case 0x03:
|
||||||
|
strcpy_P(s_buffer,AUTO_P);
|
||||||
|
icmd.Cmd(CMD_AUTO);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy_P(s_buffer,ERROR_P);
|
||||||
|
icmd.Cmd(CMD_VOID);
|
||||||
|
}
|
||||||
|
publishTopic(item->itemArr->name, s_buffer,"/fan");
|
||||||
|
SubmitParameters("fan",icmd);
|
||||||
|
|
||||||
|
/*
|
||||||
if (fan_spd == 0x00){
|
if (fan_spd == 0x00){
|
||||||
publishTopic(item->itemArr->name, "high","/fan");
|
publishTopic(item->itemArr->name, "high","/fan");
|
||||||
|
SubmitParameters("fan","")
|
||||||
}
|
}
|
||||||
if (fan_spd == 0x01){
|
if (fan_spd == 0x01){
|
||||||
publishTopic(item->itemArr->name, "medium","/fan");
|
publishTopic(item->itemArr->name, "medium","/fan");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fan_spd == 0x02){
|
if (fan_spd == 0x02){
|
||||||
publishTopic(item->itemArr->name, "low","/fan");
|
publishTopic(item->itemArr->name, "low","/fan");
|
||||||
}
|
}
|
||||||
if (fan_spd == 0x03){
|
if (fan_spd == 0x03){
|
||||||
publishTopic(item->itemArr->name, "auto","/fan");
|
publishTopic(item->itemArr->name, "auto","/fan");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (swing == 0x00)
|
if (swing == 0x00)
|
||||||
publishTopic(item->itemArr->name, "OFF","/swing");
|
publishTopic(item->itemArr->name, "OFF","/swing");
|
||||||
@@ -159,33 +203,47 @@ void out_AC::InsertData(byte data[], size_t size){
|
|||||||
publishTopic(item->itemArr->name,(long)set_tmp,"/set");
|
publishTopic(item->itemArr->name,(long)set_tmp,"/set");
|
||||||
if (cur_tmp!=255) publishTopic(item->itemArr->name, (long)cur_tmp, "/temp");
|
if (cur_tmp!=255) publishTopic(item->itemArr->name, (long)cur_tmp, "/temp");
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
s_mode[0]='\0';
|
|
||||||
|
//itoa(set_tmp,s_buffer,10);
|
||||||
|
//SubmitParameters("set",itemCmd().Int((int32_t)set_tmp).setSuffix(S_SET));
|
||||||
|
SubmitParameters("set",itemCmd().Int((int32_t)set_tmp));
|
||||||
|
|
||||||
|
//itoa(cur_tmp,s_buffer,10);
|
||||||
|
SubmitParameters("temp",itemCmd().Int((int32_t)cur_tmp).setSuffix(S_VAL));
|
||||||
|
|
||||||
|
s_buffer[0]='\0';
|
||||||
|
|
||||||
if (store->mode == 0x00){
|
if (store->mode == 0x00){
|
||||||
strcpy_P(s_mode,AUTO_P);
|
strcpy_P(s_buffer,AUTO_P);icmd.Cmd(CMD_AUTO);
|
||||||
}
|
}
|
||||||
else if (store->mode == 0x01){
|
else if (store->mode == 0x01){
|
||||||
strcpy_P(s_mode,COOL_P);
|
strcpy_P(s_buffer,COOL_P);icmd.Cmd(CMD_COOL);
|
||||||
}
|
}
|
||||||
else if (store->mode == 0x02){
|
else if (store->mode == 0x02){
|
||||||
strcpy_P(s_mode,HEAT_P);
|
strcpy_P(s_buffer,HEAT_P);icmd.Cmd(CMD_HEAT);
|
||||||
}
|
}
|
||||||
else if (store->mode == 0x03){
|
else if (store->mode == 0x03){
|
||||||
strcpy_P(s_mode,FAN_ONLY_P);
|
strcpy_P(s_buffer,FAN_ONLY_P);icmd.Cmd(CMD_FAN);
|
||||||
}
|
}
|
||||||
else if (store->mode == 0x04){
|
else if (store->mode == 0x04){
|
||||||
strcpy_P(s_mode,DRY_P);
|
strcpy_P(s_buffer,DRY_P);icmd.Cmd(CMD_DRY);
|
||||||
}
|
}
|
||||||
else if (store->mode == 109){
|
else if (store->mode == 109){
|
||||||
strcpy_P(s_mode,ERROR_P);
|
strcpy_P(s_buffer,ERROR_P);icmd.Cmd(CMD_VOID);
|
||||||
}
|
}
|
||||||
|
|
||||||
publishTopic(item->itemArr->name, (long) store->mode, "/mode");
|
publishTopic(item->itemArr->name, (long) store->mode, "/mode");
|
||||||
|
|
||||||
|
if (!(store->power & 0x01)) {strcpy_P(s_buffer,OFF_P);icmd.Cmd(CMD_OFF);}
|
||||||
|
publishTopic(item->itemArr->name, s_buffer,"/cmd");
|
||||||
|
SubmitParameters("cmd",icmd);
|
||||||
|
/*
|
||||||
if (store->power & 0x01)
|
if (store->power & 0x01)
|
||||||
publishTopic(item->itemArr->name, s_mode,"/cmd");
|
publishTopic(item->itemArr->name, s_buffer,"/cmd");
|
||||||
|
|
||||||
else publishTopic(item->itemArr->name, "OFF","/cmd");
|
else publishTopic(item->itemArr->name, "OFF","/cmd");
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
String raw_str;
|
String raw_str;
|
||||||
char raw[75];
|
char raw[75];
|
||||||
@@ -220,6 +278,10 @@ if (item->itemArr->subtype == AC_SENDING)
|
|||||||
while (store->timestamp && !isTimeOver(store->timestamp,millis(),150)) yield();
|
while (store->timestamp && !isTimeOver(store->timestamp,millis(),150)) yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#if defined (__SAM3X8E__)
|
||||||
|
//if (item->getArg(0)==2) preTransmission();
|
||||||
|
//#endif
|
||||||
|
|
||||||
ACSerial->write(req, size - 1);
|
ACSerial->write(req, size - 1);
|
||||||
ACSerial->write(getCRC(req, size-1));
|
ACSerial->write(getCRC(req, size-1));
|
||||||
//ACSerial->flush();
|
//ACSerial->flush();
|
||||||
@@ -238,6 +300,9 @@ if (item->itemArr->subtype == AC_SENDING)
|
|||||||
}
|
}
|
||||||
debugSerial.println();
|
debugSerial.println();
|
||||||
item->itemArr->subtype = AC_SENDING;
|
item->itemArr->subtype = AC_SENDING;
|
||||||
|
// #if defined (__SAM3X8E__)
|
||||||
|
// if (item->getArg(0)==2) postTransmission();
|
||||||
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned char toHex( char ch ){
|
inline unsigned char toHex( char ch ){
|
||||||
@@ -268,6 +333,7 @@ if (!portNum)// && (g_APinDescription[0].ulPinType == PIO_PA8A_URXD))
|
|||||||
pinMode(0, INPUT_PULLUP);
|
pinMode(0, INPUT_PULLUP);
|
||||||
#if debugSerial == Serial
|
#if debugSerial == Serial
|
||||||
infoSerial<<F("AC: Serial used by AC - disabling serial logging and cmd")<<endl;
|
infoSerial<<F("AC: Serial used by AC - disabling serial logging and cmd")<<endl;
|
||||||
|
Serial.flush();
|
||||||
//sysConf.setSerialDebuglevel(0);
|
//sysConf.setSerialDebuglevel(0);
|
||||||
serialDebugLevel = 0;
|
serialDebugLevel = 0;
|
||||||
disableCMD=true;
|
disableCMD=true;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
int getChanType() override;
|
int getChanType() override;
|
||||||
int getDefaultStorageType(){return ST_FLOAT_CELSIUS;};
|
int getDefaultStorageType(){return ST_FLOAT_CELSIUS;};
|
||||||
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override;
|
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override;
|
||||||
|
void SubmitParameters(const char * name, itemCmd value);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
acPersistent * store;
|
acPersistent * store;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ struct serial_t
|
|||||||
#define PAR_U8L 8
|
#define PAR_U8L 8
|
||||||
#define PAR_TENS 9
|
#define PAR_TENS 9
|
||||||
#define PAR_100 10
|
#define PAR_100 10
|
||||||
|
#define PAR_COIL 11
|
||||||
|
|
||||||
|
|
||||||
const reg_t regSize_P[] PROGMEM =
|
const reg_t regSize_P[] PROGMEM =
|
||||||
@@ -55,6 +56,7 @@ const reg_t regSize_P[] PROGMEM =
|
|||||||
{ "u8l", (uint8_t) PAR_U8L },
|
{ "u8l", (uint8_t) PAR_U8L },
|
||||||
{ "x10", (uint8_t) PAR_TENS },
|
{ "x10", (uint8_t) PAR_TENS },
|
||||||
{ "100", (uint8_t) PAR_100 }
|
{ "100", (uint8_t) PAR_100 }
|
||||||
|
// { "bit", (uint8_t) PAR_COIL }
|
||||||
} ;
|
} ;
|
||||||
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
|
||||||
|
|
||||||
@@ -151,6 +153,8 @@ bool out_Modbus::getConfig()
|
|||||||
{
|
{
|
||||||
store->pollingRegisters=aJson.getObjectItem(pollObj, "regs");
|
store->pollingRegisters=aJson.getObjectItem(pollObj, "regs");
|
||||||
store->pollingIrs=aJson.getObjectItem(pollObj, "irs");
|
store->pollingIrs=aJson.getObjectItem(pollObj, "irs");
|
||||||
|
store->pollingCoils=aJson.getObjectItem(pollObj, "coils");
|
||||||
|
store->poolingDiscreteIns=aJson.getObjectItem(pollObj, "dins");
|
||||||
aJsonObject * delayObj= aJson.getObjectItem(pollObj, "delay");
|
aJsonObject * delayObj= aJson.getObjectItem(pollObj, "delay");
|
||||||
if (delayObj) store->pollingInterval = delayObj->valueint;
|
if (delayObj) store->pollingInterval = delayObj->valueint;
|
||||||
else store->pollingInterval = 1000;
|
else store->pollingInterval = 1000;
|
||||||
@@ -243,30 +247,40 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
//bool is8bit = false;
|
//bool is8bit = false;
|
||||||
while (paramObj)
|
while (paramObj)
|
||||||
{
|
{
|
||||||
|
int8_t parType = PAR_I16;
|
||||||
aJsonObject *regObj=NULL;
|
aJsonObject *regObj=NULL;
|
||||||
switch (regType) {
|
switch (regType) {
|
||||||
case MODBUS_HOLDING_REG_TYPE: regObj = aJson.getObjectItem(paramObj, "reg");
|
case MODBUS_HOLDING_REG_TYPE:
|
||||||
|
regObj = aJson.getObjectItem(paramObj, "reg");
|
||||||
break;
|
break;
|
||||||
case MODBUS_INPUT_REG_TYPE: regObj = aJson.getObjectItem(paramObj, "ir");
|
case MODBUS_INPUT_REG_TYPE:
|
||||||
|
regObj = aJson.getObjectItem(paramObj, "ir");
|
||||||
|
break;
|
||||||
|
case MODBUS_COIL_REG_TYPE:
|
||||||
|
regObj = aJson.getObjectItem(paramObj, "coil");
|
||||||
|
parType = PAR_COIL;
|
||||||
|
break;
|
||||||
|
case MODBUS_DISCRETE_REG_TYPE:
|
||||||
|
regObj = aJson.getObjectItem(paramObj, "din");
|
||||||
|
parType = PAR_COIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regObj && regObj->valueint ==registerNum)
|
if (regObj && regObj->valueint ==registerNum)
|
||||||
{
|
{
|
||||||
aJsonObject *typeObj = aJson.getObjectItem(paramObj, "type");
|
|
||||||
aJsonObject *mapObj = aJson.getObjectItem(paramObj, "map");
|
|
||||||
aJsonObject *idObj = aJson.getObjectItem(paramObj, "id");
|
aJsonObject *idObj = aJson.getObjectItem(paramObj, "id");
|
||||||
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
||||||
uint16_t data = node.getResponseBuffer(posInBuffer);
|
uint16_t data = node.getResponseBuffer(posInBuffer);
|
||||||
int8_t regType = PAR_I16;
|
|
||||||
uint32_t param =0;
|
|
||||||
itemCmd mappedParam;
|
|
||||||
bool executeWithoutCheck=false; //Afler recurrent check, all dublicatess and suppressing checked by recurrent
|
bool executeWithoutCheck=false; //Afler recurrent check, all dublicatess and suppressing checked by recurrent
|
||||||
bool submitRecurrentOut = false; //false if recurrent check find duplicates
|
bool submitRecurrentOut = false; //false if recurrent check find duplicates
|
||||||
char buf[16];
|
char buf[16];
|
||||||
|
|
||||||
//bool isSigned=false;
|
uint32_t param =0;
|
||||||
if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
|
itemCmd mappedParam;
|
||||||
switch(regType) {
|
aJsonObject *typeObj = aJson.getObjectItem(paramObj, "type");
|
||||||
|
aJsonObject *mapObj = aJson.getObjectItem(paramObj, "map");
|
||||||
|
|
||||||
|
if (typeObj && typeObj->type == aJson_String) parType=str2regSize(typeObj->valuestring);
|
||||||
|
switch(parType) {
|
||||||
|
|
||||||
case PAR_I16:
|
case PAR_I16:
|
||||||
//isSigned=true;
|
//isSigned=true;
|
||||||
@@ -278,6 +292,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
param=data;
|
param=data;
|
||||||
mappedParam.Int((uint32_t)data);
|
mappedParam.Int((uint32_t)data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAR_I32:
|
case PAR_I32:
|
||||||
//isSigned=true;
|
//isSigned=true;
|
||||||
param = swap(data ) | swap(node.getResponseBuffer(posInBuffer+1)<<16);
|
param = swap(data ) | swap(node.getResponseBuffer(posInBuffer+1)<<16);
|
||||||
@@ -310,15 +325,104 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
param=data;
|
param=data;
|
||||||
mappedParam.Tens_raw((int16_t) data * (TENS_BASE/100));
|
mappedParam.Tens_raw((int16_t) data * (TENS_BASE/100));
|
||||||
mappedParam.Float((int32_t) (int16_t) data/100.);
|
mappedParam.Float((int32_t) (int16_t) data/100.);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAR_COIL:
|
||||||
|
param = (node.getResponseBuffer(posInBuffer/16) >> (posInBuffer % 16)) & 1;
|
||||||
|
mappedParam.Int((uint32_t)param);
|
||||||
}
|
}
|
||||||
|
|
||||||
debugSerial << F("MBUSD: got ")<<mappedParam.toString(buf,sizeof(buf))<< F(" from ")<<regType<<F(":")<<paramObj->name<<endl;
|
debugSerial << F("MBUSD: got ")<<mappedParam.toString(buf,sizeof(buf))<< F(" from type ")<<parType<<F(":")<<paramObj->name<<endl;
|
||||||
|
|
||||||
if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object))
|
if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object))
|
||||||
{
|
{
|
||||||
mappedParam=mappedParam.doReverseMapping(mapObj);
|
mappedParam=mappedParam.doReverseMapping(mapObj);
|
||||||
if (!mappedParam.isCommand() && !mappedParam.isValue()) //Not mapped
|
if (!mappedParam.isCommand() && !mappedParam.isValue()) //Not mapped
|
||||||
{
|
{
|
||||||
|
aJsonObject *defMappingObj;
|
||||||
|
defMappingObj = aJson.getObjectItem(mapObj, "def");
|
||||||
|
if (defMappingObj)
|
||||||
|
{
|
||||||
|
switch (defMappingObj->type)
|
||||||
|
{
|
||||||
|
case aJson_Int: //register/coil/.. number
|
||||||
|
debugSerial<<F("Searching reg#")<<defMappingObj->valueint<<endl;
|
||||||
|
if ((defMappingObj->valueint>= registerFrom) && (defMappingObj->valueint<=registerTo))
|
||||||
|
{
|
||||||
|
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
|
||||||
|
executeWithoutCheck=true;
|
||||||
|
}
|
||||||
|
else errorSerial<<F("reg# out of range")<<endl;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case aJson_String: // parameter name
|
||||||
|
debugSerial<<F("Searching reg: ")<<defMappingObj->valuestring<<endl;
|
||||||
|
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
||||||
|
{
|
||||||
|
//Searching item param for nested mapping
|
||||||
|
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
|
||||||
|
if (itemParObj)
|
||||||
|
{
|
||||||
|
//aJsonObject * markObj = execObj;
|
||||||
|
//if (execObj->type == aJson_Array) markObj = execObj->child;
|
||||||
|
//Retrive previous data
|
||||||
|
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
|
||||||
|
if (lastMeasured && lastMeasured->type ==aJson_Int)
|
||||||
|
{
|
||||||
|
debugSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
|
||||||
|
//Searching template param for nested mapping
|
||||||
|
aJsonObject * templateParObj = aJson.getObjectItem(store->parameters,defMappingObj->valuestring);
|
||||||
|
if (templateParObj)
|
||||||
|
{
|
||||||
|
int8_t nestedParType = PAR_I16;
|
||||||
|
|
||||||
|
aJsonObject * nestedTypeObj = aJson.getObjectItem(templateParObj, "type");
|
||||||
|
if (nestedTypeObj && nestedTypeObj->type == aJson_String) parType=str2regSize(nestedTypeObj->valuestring);
|
||||||
|
|
||||||
|
switch(nestedParType) {
|
||||||
|
case PAR_I16:
|
||||||
|
case PAR_I32:
|
||||||
|
mappedParam.Int((int32_t)lastMeasured->valueint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAR_U32:
|
||||||
|
case PAR_U16:
|
||||||
|
case PAR_U8L:
|
||||||
|
case PAR_U8H:
|
||||||
|
case PAR_COIL:
|
||||||
|
mappedParam.Int((uint32_t)lastMeasured->valueint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAR_TENS:
|
||||||
|
mappedParam.Tens((int16_t) data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAR_100:
|
||||||
|
mappedParam.Tens_raw((int16_t) lastMeasured->valueint * (TENS_BASE/100));
|
||||||
|
mappedParam.Float((int32_t) (int16_t) lastMeasured->valueint/100.);
|
||||||
|
break;
|
||||||
|
default: errorSerial<<F("Invalid regtype")<<endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
aJsonObject * nestedMapObj = aJson.getObjectItem(templateParObj, "map");
|
||||||
|
if (nestedMapObj && (nestedMapObj->type==aJson_Array || nestedMapObj->type==aJson_Object)) mappedParam=mappedParam.doReverseMapping(nestedMapObj);
|
||||||
|
debugSerial << F("MBUSD: NestedMapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
|
||||||
|
|
||||||
|
if (!(lastMeasured->subtype & MB_VALUE_OUTDATED))
|
||||||
|
{
|
||||||
|
executeWithoutCheck=true;
|
||||||
|
submitRecurrentOut=true;
|
||||||
|
lastMeasured->subtype|= MB_VALUE_OUTDATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
aJsonObject *nextRegObj = NULL;
|
aJsonObject *nextRegObj = NULL;
|
||||||
int registerType = 0;
|
int registerType = 0;
|
||||||
|
|
||||||
@@ -328,15 +432,26 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
{
|
{
|
||||||
nextRegObj = aJson.getObjectItem(paramObj, "nextir");
|
nextRegObj = aJson.getObjectItem(paramObj, "nextir");
|
||||||
if (nextRegObj) registerType=MODBUS_INPUT_REG_TYPE;
|
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->type) ==aJson_Int && (nextRegObj->valueint>= registerFrom) && (nextRegObj->valueint<=registerTo))
|
if (registerType && nextRegObj && (nextRegObj->type) ==aJson_Int && (nextRegObj->valueint>= registerFrom) && (nextRegObj->valueint<=registerTo))
|
||||||
{
|
{
|
||||||
debugSerial<<F("Recurrent searching nextreg")<<endl;
|
debugSerial<<F("Recurrent searching nextreg")<<endl;
|
||||||
mappedParam = findRegister(nextRegObj->valueint,nextRegObj->valueint-registerFrom,registerType,registerFrom,registerTo,false,&submitRecurrentOut);
|
mappedParam = findRegister(nextRegObj->valueint,nextRegObj->valueint-registerFrom,registerType,registerFrom,registerTo,false,&submitRecurrentOut);
|
||||||
executeWithoutCheck=true;
|
executeWithoutCheck=true;
|
||||||
}
|
}
|
||||||
else errorSerial<<F("nextreg out of range")<<endl;
|
else errorSerial<<F("nextreg out of range")<<endl;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
debugSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
|
debugSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
|
||||||
@@ -368,7 +483,11 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
|
|||||||
{
|
{
|
||||||
if (lastMeasured->valueint == param)
|
if (lastMeasured->valueint == param)
|
||||||
*submitParam=false; //supress repeating execution for same val
|
*submitParam=false; //supress repeating execution for same val
|
||||||
else lastMeasured->valueint=param;
|
else
|
||||||
|
{
|
||||||
|
lastMeasured->valueint=param;
|
||||||
|
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //No container to store value yet
|
else //No container to store value yet
|
||||||
@@ -416,7 +535,6 @@ return itemCmd();
|
|||||||
{
|
{
|
||||||
if (!reg) return;
|
if (!reg) return;
|
||||||
reg=reg->child;
|
reg=reg->child;
|
||||||
//aJsonObject * reg = store->pollingRegisters->child;
|
|
||||||
while (reg)
|
while (reg)
|
||||||
{
|
{
|
||||||
switch (reg->type)
|
switch (reg->type)
|
||||||
@@ -424,11 +542,9 @@ return itemCmd();
|
|||||||
case aJson_Int:
|
case aJson_Int:
|
||||||
{
|
{
|
||||||
int registerNum = reg->valueint;
|
int registerNum = reg->valueint;
|
||||||
//if (readModbus(registerNum,MODBUS_HOLDING_REG_TYPE,1))
|
|
||||||
if (readModbus(registerNum,regType,1))
|
if (readModbus(registerNum,regType,1))
|
||||||
{
|
{
|
||||||
findRegister(registerNum,0,regType,registerNum,registerNum);
|
findRegister(registerNum,0,regType,registerNum,registerNum);
|
||||||
// data = node.getResponseBuffer(j);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -438,14 +554,12 @@ return itemCmd();
|
|||||||
int registerFrom=aJson.getArrayItem(reg, 0)->valueint;
|
int registerFrom=aJson.getArrayItem(reg, 0)->valueint;
|
||||||
int registerTo=aJson.getArrayItem(reg, 1)->valueint;
|
int registerTo=aJson.getArrayItem(reg, 1)->valueint;
|
||||||
|
|
||||||
//if (readModbus(registerFrom,MODBUS_HOLDING_REG_TYPE,registerTo-registerFrom+1))
|
|
||||||
if (readModbus(registerFrom,regType,registerTo-registerFrom+1))
|
if (readModbus(registerFrom,regType,registerTo-registerFrom+1))
|
||||||
{ debugSerial<<endl;
|
{ debugSerial<<endl;
|
||||||
for(int i=registerFrom;i<=registerTo;i++)
|
for(int i=registerFrom;i<=registerTo;i++)
|
||||||
{
|
{
|
||||||
findRegister(i,i-registerFrom,regType,registerFrom,registerTo);
|
findRegister(i,i-registerFrom,regType,registerFrom,registerTo);
|
||||||
}
|
}
|
||||||
//data = node.getResponseBuffer(j);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -481,7 +595,13 @@ int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
|
|||||||
if (!templateParamObj) {errorSerial<<F(" internal send error - no template")<<endl; return -1;}
|
if (!templateParamObj) {errorSerial<<F(" internal send error - no template")<<endl; return -1;}
|
||||||
|
|
||||||
aJsonObject * regObj = aJson.getObjectItem(templateParamObj, "reg");
|
aJsonObject * regObj = aJson.getObjectItem(templateParamObj, "reg");
|
||||||
if (!regObj) {errorSerial<<F(" internal send error - no regObj")<<endl; return -2;}
|
|
||||||
|
if (!regObj)
|
||||||
|
{
|
||||||
|
regObj = aJson.getObjectItem(templateParamObj, "coil");
|
||||||
|
if (!regObj) {errorSerial<<F(" internal send error - no reg/coil")<<endl; return -2;}
|
||||||
|
else regType = PAR_COIL;
|
||||||
|
}
|
||||||
|
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
@@ -513,6 +633,9 @@ int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
|
|||||||
case PAR_I8H:
|
case PAR_I8H:
|
||||||
res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8);
|
res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8);
|
||||||
break;
|
break;
|
||||||
|
case PAR_COIL:
|
||||||
|
res = node.writeSingleCoil (regObj->valueint,value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
mbusSlenceTimer = millisNZ();
|
mbusSlenceTimer = millisNZ();
|
||||||
debugSerial<<F("Res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<value<<endl;
|
debugSerial<<F("Res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<value<<endl;
|
||||||
@@ -530,7 +653,8 @@ aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
|
|||||||
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
||||||
{
|
{
|
||||||
aJsonObject *execObj = itemParametersObj->child;
|
aJsonObject *execObj = itemParametersObj->child;
|
||||||
while (execObj && (execObj->type == aJson_Object) || (execObj->type == aJson_Array) )
|
bool onceSendOk=false;
|
||||||
|
while (execObj && ((execObj->type == aJson_Object) || (execObj->type == aJson_Array)) && !onceSendOk)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((execObj->subtype & MB_NEED_SEND) && !(execObj->subtype & MB_SEND_ERROR))
|
if ((execObj->subtype & MB_NEED_SEND) && !(execObj->subtype & MB_SEND_ERROR))
|
||||||
@@ -553,6 +677,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;
|
||||||
///return 1; //relax
|
///return 1; //relax
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -597,7 +722,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if some polling configured
|
// if some polling configured
|
||||||
if (store->pollingRegisters || store->pollingIrs)
|
if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store->poolingDiscreteIns)
|
||||||
{
|
{
|
||||||
debugSerial<<F("MBUSD: Poll ")<< item->itemArr->name << endl;
|
debugSerial<<F("MBUSD: Poll ")<< item->itemArr->name << endl;
|
||||||
modbusBusy=1;
|
modbusBusy=1;
|
||||||
@@ -610,6 +735,8 @@ if (store->pollingRegisters || store->pollingIrs)
|
|||||||
|
|
||||||
pollModbus(store->pollingRegisters,MODBUS_HOLDING_REG_TYPE);
|
pollModbus(store->pollingRegisters,MODBUS_HOLDING_REG_TYPE);
|
||||||
pollModbus(store->pollingIrs,MODBUS_INPUT_REG_TYPE);
|
pollModbus(store->pollingIrs,MODBUS_INPUT_REG_TYPE);
|
||||||
|
pollModbus(store->pollingCoils,MODBUS_COIL_REG_TYPE);
|
||||||
|
pollModbus(store->poolingDiscreteIns ,MODBUS_DISCRETE_REG_TYPE);
|
||||||
debugSerial<<F("MBUSD: endPoll ")<< item->itemArr->name << endl;
|
debugSerial<<F("MBUSD: endPoll ")<< item->itemArr->name << endl;
|
||||||
|
|
||||||
//Non blocking waiting to release line
|
//Non blocking waiting to release line
|
||||||
@@ -709,7 +836,11 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
|
aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
|
||||||
if (polledValue && outValue->type == aJson_Int) polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
|
if (polledValue && outValue->type == aJson_Int)
|
||||||
|
{
|
||||||
|
polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
|
||||||
|
polledValue->subtype&=~MB_VALUE_OUTDATED;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ public:
|
|||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
aJsonObject * pollingRegisters;
|
aJsonObject * pollingRegisters;
|
||||||
aJsonObject * pollingIrs;
|
aJsonObject * pollingIrs;
|
||||||
|
aJsonObject * pollingCoils;
|
||||||
|
aJsonObject * poolingDiscreteIns;
|
||||||
aJsonObject * parameters;
|
aJsonObject * parameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MB_NEED_SEND 8
|
#define MB_NEED_SEND 8
|
||||||
#define MB_SEND_ERROR 4
|
#define MB_SEND_ERROR 4
|
||||||
#define MB_SEND_ATTEMPTS 3
|
#define MB_SEND_ATTEMPTS 3
|
||||||
|
#define MB_VALUE_OUTDATED 1
|
||||||
|
|
||||||
|
|
||||||
class out_Modbus : public abstractOut {
|
class out_Modbus : public abstractOut {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#define MIN_PWM 70
|
#define MIN_PWM 70
|
||||||
// The number of simultaniusly working motors
|
// The number of simultaniusly working motors
|
||||||
#ifndef MOTOR_QUOTE
|
#ifndef MOTOR_QUOTE
|
||||||
#define MOTOR_QUOTE 1
|
#define MOTOR_QUOTE 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int8_t motorQuote = MOTOR_QUOTE;
|
static int8_t motorQuote = MOTOR_QUOTE;
|
||||||
|
|||||||
Reference in New Issue
Block a user