Сounter mod, core & modbus tuned for 1/100th prec

This commit is contained in:
2022-04-06 10:21:39 +03:00
parent 9bf3d561bd
commit b3af9865c7
11 changed files with 370 additions and 82 deletions

View File

@@ -51,6 +51,7 @@ e-mail anklimov@gmail.com
#include "modules/out_multivent.h" #include "modules/out_multivent.h"
#include "modules/out_uartbridge.h" #include "modules/out_uartbridge.h"
#include "modules/out_relay.h" #include "modules/out_relay.h"
#include "modules/out_counter.h"
#ifdef ELEVATOR_ENABLE #ifdef ELEVATOR_ENABLE
#include "modules/out_elevator.h" #include "modules/out_elevator.h"
@@ -205,6 +206,12 @@ void Item::Parse() {
driver = new out_elevator (this); driver = new out_elevator (this);
// debugSerial<<F("AC driver created")<<endl; // debugSerial<<F("AC driver created")<<endl;
break; break;
#endif
#ifndef COUNTER_DISABLE
case CH_COUNTER:
driver = new out_counter (this);
// debugSerial<<F("AC driver created")<<endl;
break;
#endif #endif
default: ; default: ;
} }
@@ -417,7 +424,7 @@ void Item::setVal(long int par) // Only store if VAL is int (autogenerated or c
//debugSerial<<F(" Store ")<<F(" Val=")<<par<<endl; //debugSerial<<F(" Store ")<<F(" Val=")<<par<<endl;
itemVal->valueint = par; itemVal->valueint = par;
itemVal->type = aJson_Int; itemVal->type = aJson_Int;
if (itemVal->subtype==ST_TENS) itemVal->subtype=ST_INT32; if (itemVal->subtype==ST_TENS) itemVal->subtype=ST_INT32; //???
} }
void Item::setFloatVal(float par) // Only store if VAL is int (autogenerated or config-defined) void Item::setFloatVal(float par) // Only store if VAL is int (autogenerated or config-defined)
@@ -426,7 +433,7 @@ void Item::setFloatVal(float par) // Only store if VAL is int (autogenerated or
//debugSerial<<F(" Store ")<<F(" Val=")<<par<<endl; //debugSerial<<F(" Store ")<<F(" Val=")<<par<<endl;
itemVal->valuefloat = par; itemVal->valuefloat = par;
itemVal->type = aJson_Float; itemVal->type = aJson_Float;
if (itemVal->subtype==ST_TENS) itemVal->subtype=ST_FLOAT; if (itemVal->subtype==ST_TENS) itemVal->subtype=ST_FLOAT; //???
} }
void Item::setSubtype(uint8_t par) // Only store if VAL is int (autogenerated or config-defined) void Item::setSubtype(uint8_t par) // Only store if VAL is int (autogenerated or config-defined)
@@ -525,6 +532,22 @@ else
return suffixCode; return suffixCode;
} }
long int Item::limitSetValue()
{
int _itemType = itemType;
if (driver) _itemType = driver->getChanType();
switch (_itemType)
{
case CH_COUNTER:
return 0;
case CH_THERMO:
return 80;
default:
return 255;
}
}
// myhome/dev/item/subItem // myhome/dev/item/subItem
int Item::Ctrl(char * payload, char * subItem) int Item::Ctrl(char * payload, char * subItem)
{ {
@@ -638,6 +661,14 @@ st.setSuffix(suffixCode);
return Ctrl(st,subItem); return Ctrl(st,subItem);
} }
case CMD_UP:
case CMD_DN:
{
itemCmd Par0 = getNumber((char **) &payload);
Par0.Cmd(cmd);
Par0.setSuffix(suffixCode);
return Ctrl(Par0, subItem);
}
default: //some known command default: //some known command
{ {
int32_t intParam = getInt((char **) &payload); int32_t intParam = getInt((char **) &payload);
@@ -852,8 +883,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_UP: case CMD_UP:
{ {
itemCmd fallbackCmd=cmd; itemCmd fallbackCmd=cmd;
short step=0; long step=0;
if (cmd.isValue()) step=cmd.getInt(); if (cmd.isValue()) step=cmd.getTens_raw();
if (!step) step=DEFAULT_INC_STEP; if (!step) step=DEFAULT_INC_STEP;
if (cmd.getCmd() == CMD_DN) step=-step; if (cmd.getCmd() == CMD_DN) step=-step;
@@ -867,7 +898,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
toExecute=true; toExecute=true;
case S_SET: case S_SET:
if (cmd.incrementPercents(step)) if (cmd.incrementPercents(step,(suffixCode==S_NOTFOUND)?100:limitSetValue()))
{ {
status2Send |= SEND_PARAMETERS | SEND_DEFFERED; status2Send |= SEND_PARAMETERS | SEND_DEFFERED;
} else {cmd=fallbackCmd;invalidArgument=true;} } else {cmd=fallbackCmd;invalidArgument=true;}
@@ -1121,6 +1152,7 @@ if (status2Send) cmd.saveItem(this,status2Send);
if (driver) //New style modular code if (driver) //New style modular code
{ {
res = driver->Ctrl(cmd, subItem, toExecute); res = driver->Ctrl(cmd, subItem, toExecute);
if (driver->getChanType() == CH_THERMO) status2Send |= SEND_IMMEDIATE;
//if (res==-1) status2Send=0; ///////not working //if (res==-1) status2Send=0; ///////not working
} }
else else

View File

@@ -59,6 +59,7 @@ e-mail anklimov@gmail.com
#define CH_RGBWW 17 #define CH_RGBWW 17
#define CH_MULTIVENT 18 #define CH_MULTIVENT 18
#define CH_ELEVATOR 19 #define CH_ELEVATOR 19
#define CH_COUNTER 20
//#define CHANNEL_TYPES 13 //#define CHANNEL_TYPES 13
@@ -146,7 +147,7 @@ class Item
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));}; inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
protected: protected:
long int limitSetValue();
int VacomSetFan (itemCmd st); int VacomSetFan (itemCmd st);
int VacomSetHeat(itemCmd st); int VacomSetHeat(itemCmd st);
int modbusDimmerSet(itemCmd st); int modbusDimmerSet(itemCmd st);

View File

@@ -113,6 +113,8 @@ uint8_t itemCmd::getStoragetypeByChanType(short chanType)
break; break;
case CH_RELAY: case CH_RELAY:
return ST_VOID; return ST_VOID;
//case CH_COUNTER:
//return ST_TENS;
default: default:
return ST_VOID; return ST_VOID;
} }
@@ -236,13 +238,14 @@ uint16_t itemCmd::getS()
return param.s; return param.s;
} }
bool itemCmd::incrementPercents(int16_t dif)
{ int par=param.v; bool itemCmd::incrementPercents(long int dif, long int limit )
{ long par=param.v;
switch (cmd.itemArgType) switch (cmd.itemArgType)
{ {
case ST_PERCENTS255: case ST_PERCENTS255:
case ST_HSV255: case ST_HSV255:
par+=dif; par+=dif/TENS_BASE;
if (par>255) par=255; if (par>255) par=255;
if (par<0) par=0; if (par<0) par=0;
param.v=par; param.v=par;
@@ -251,9 +254,9 @@ bool itemCmd::incrementPercents(int16_t dif)
case ST_INT32: case ST_INT32:
case ST_UINT32: case ST_UINT32:
par=param.asInt32; par=param.asInt32;
par+=dif; par+=dif/TENS_BASE;
if (par>100) par=100; if (par>limit) par=limit;
if (par<0) par=0; if (limit && par<0) par=0;
param.asInt32=par; param.asInt32=par;
break; break;
@@ -261,18 +264,18 @@ bool itemCmd::incrementPercents(int16_t dif)
case ST_FLOAT_CELSIUS: case ST_FLOAT_CELSIUS:
case ST_FLOAT_FARENHEIT: case ST_FLOAT_FARENHEIT:
par=param.asfloat; par=param.asfloat;
par+=dif; par+=dif/TENS_BASE;
if (par>100) par=100; if (limit && par>limit) par=limit;
if (par<0) par=0; if (limit && par<0) par=0;
param.asfloat=par; param.asfloat=par;
break; break;
case ST_TENS: case ST_TENS:
par=param.asInt32; par=param.asInt32;
par+=dif*10; par+=dif;
if (par>1000) par=1000; // if (par>100*TENS_BASE) par=100*TENS_BASE;
if (par<0) par=0; // if (par<0) par=0;
param.asInt32=par; param.asInt32=par;
break; break;
@@ -282,13 +285,13 @@ bool itemCmd::incrementPercents(int16_t dif)
return true; return true;
} }
bool itemCmd::incrementH(int16_t dif) bool itemCmd::incrementH(long int dif)
{ int par=param.h; { int par=param.h;
switch (cmd.itemArgType) switch (cmd.itemArgType)
{ {
//case ST_HSV: //case ST_HSV:
case ST_HSV255: case ST_HSV255:
par+=dif; par+=dif/TENS_BASE;
if (par>365) par=0; if (par>365) par=0;
if (par<0) par=365; if (par<0) par=365;
break; break;
@@ -299,12 +302,12 @@ param.h=par;
return true; return true;
} }
bool itemCmd::incrementS(int16_t dif) bool itemCmd::incrementS(long int dif)
{int par=param.s; {int par=param.s;
switch (cmd.itemArgType) switch (cmd.itemArgType)
{ {
case ST_HSV255: case ST_HSV255:
par+=dif; par+=dif/TENS_BASE;
if (par>100) par=100; if (par>100) par=100;
if (par<0) par=0; if (par<0) par=0;
break; break;
@@ -356,7 +359,7 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
param.v=constrain(from.param.asInt32,0,255); param.v=constrain(from.param.asInt32,0,255);
break; break;
case ST_TENS: case ST_TENS:
param.v=constrain(from.param.asInt32/10,0,255); param.v=constrain(from.param.asInt32/TENS_BASE,0,255);
break; break;
case ST_HSV255: case ST_HSV255:
param.h=from.param.h; param.h=from.param.h;
@@ -420,7 +423,9 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
break; break;
case ST_TENS: case ST_TENS:
param.asfloat=from.param.asInt32/10.; //param.asfloat=(float) from.param.asInt32/(float)TENS_BASE;
param.asInt32 = from.param.asInt32;
cmd.itemArgType=from.cmd.itemArgType;
break; break;
case ST_PERCENTS255: case ST_PERCENTS255:
param.asfloat=from.param.v; param.asfloat=from.param.v;
@@ -507,7 +512,7 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
vol=from.param.asInt32; vol=from.param.asInt32;
break; break;
case ST_TENS: case ST_TENS:
vol=from.param.asInt32/10; vol=from.param.asInt32/TENS_BASE;
break; break;
case ST_FLOAT: case ST_FLOAT:
vol=from.param.asfloat; vol=from.param.asfloat;
@@ -654,12 +659,36 @@ long int itemCmd::getTens()
case ST_FLOAT_FARENHEIT: case ST_FLOAT_FARENHEIT:
return param.asfloat*10.0; return param.asfloat*10.0;
case ST_TENS: case ST_TENS:
return param.aslong; return param.aslong/(TENS_BASE/10);
default: default:
return 0; return 0;
} }
} }
long int itemCmd::getTens_raw()
{
switch (cmd.itemArgType) {
case ST_INT32:
case ST_UINT32:
case ST_RGB:
case ST_RGBW:
return param.aslong*TENS_BASE;
case ST_PERCENTS255:
case ST_HSV255:
return param.v*TENS_BASE;
case ST_FLOAT:
case ST_FLOAT_CELSIUS:
case ST_FLOAT_FARENHEIT:
return param.asfloat*(float)TENS_BASE;
case ST_TENS:
return param.aslong;
default:
return 0;
}
}
@@ -682,7 +711,7 @@ long int itemCmd::getInt()
case ST_FLOAT_FARENHEIT: case ST_FLOAT_FARENHEIT:
return param.asfloat; return param.asfloat;
case ST_TENS: case ST_TENS:
return param.aslong/10; return param.aslong/TENS_BASE;
@@ -714,7 +743,7 @@ float itemCmd::getFloat()
return param.aslong; return param.aslong;
case ST_TENS: case ST_TENS:
return param.aslong/10; return param.aslong/TENS_BASE;
case ST_PERCENTS255: case ST_PERCENTS255:
case ST_HSV255: case ST_HSV255:
@@ -758,8 +787,8 @@ short itemCmd::getPercents(bool inverse)
else return constrain (param.asfloat,0,100); else return constrain (param.asfloat,0,100);
case ST_TENS: case ST_TENS:
if (inverse) return constrain (100-param.asInt32/10,0,100); if (inverse) return constrain (100-param.asInt32/TENS_BASE,0,100);
else return constrain(param.asInt32/10,0,100); else return constrain(param.asInt32/TENS_BASE,0,100);
case ST_VOID: case ST_VOID:
return 0; return 0;
@@ -784,7 +813,7 @@ bool itemCmd::setPercents(int percents)
param.asfloat=map(percents,0,100,0,255);; param.asfloat=map(percents,0,100,0,255);;
break; break;
case ST_TENS: case ST_TENS:
param.asInt32 = map(percents,0,100,0,2550);; param.asInt32 = map(percents,0,100,0,255*TENS_BASE);;
default: default:
return false; return false;
} }
@@ -807,7 +836,7 @@ short itemCmd::getPercents255(bool inverse)
if (inverse) return 255-constrain(param.asfloat,0,255); else return constrain(param.asfloat,0,255); if (inverse) return 255-constrain(param.asfloat,0,255); else return constrain(param.asfloat,0,255);
case ST_TENS: case ST_TENS:
if (inverse) return 255-constrain(param.asInt32/10,0,255); else return constrain(param.asInt32/10,0,255); if (inverse) return 255-constrain(param.asInt32/TENS_BASE,0,255); else return constrain(param.asInt32/TENS_BASE,0,255);
case ST_VOID: case ST_VOID:
return 0; return 0;
@@ -906,6 +935,13 @@ itemCmd itemCmd::Float(float f)
} }
itemCmd itemCmd::Tens(int32_t i) itemCmd itemCmd::Tens(int32_t i)
{
cmd.itemArgType=ST_TENS;
param.asInt32=i*(TENS_BASE/10);
return *this;
}
itemCmd itemCmd::Tens_raw(int32_t i)
{ {
cmd.itemArgType=ST_TENS; cmd.itemArgType=ST_TENS;
param.asInt32=i; param.asInt32=i;
@@ -1002,7 +1038,7 @@ bool itemCmd::loadItem(Item * item, uint16_t optionsFlag)
if (subtype) if (subtype)
{ {
cmd.itemArgType= subtype; cmd.itemArgType= subtype;
if (optionsFlag & SEND_PARAMETERS) param.asInt32 = item->getVal(); if (optionsFlag & SEND_PARAMETERS) param.asInt32 = item->itemVal->valueint;
//debugSerial<<F("Loaded :"); //debugSerial<<F("Loaded :");
//debugOut(); //debugOut();
return true; return true;
@@ -1067,8 +1103,9 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
break; break;
default: default:
item->setSubtype(cmd.itemArgType); //item->setSubtype(cmd.itemArgType);
item->setVal(param.asInt32); item->setVal(param.asInt32);
item->setSubtype(cmd.itemArgType);
} }
debugSerial<<F("Saved:"); debugSerial<<F("Saved:");
debugOut(); debugOut();
@@ -1135,7 +1172,7 @@ char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100
snprintf(argPtr, bufLen, "%ld", param.asInt32); snprintf(argPtr, bufLen, "%ld", param.asInt32);
break; break;
case ST_TENS: case ST_TENS:
snprintf(argPtr, bufLen, "%ld.%d", param.asInt32/10, abs(param.asInt32 % 10)); snprintf(argPtr, bufLen, "%ld.%0"QUOTE(TENS_FRACT_LEN)"d", param.asInt32/TENS_BASE, abs(param.asInt32 % TENS_BASE));
break; break;
case ST_HSV255: case ST_HSV255:
colorTemp=getColorTemp(); colorTemp=getColorTemp();
@@ -1158,12 +1195,12 @@ char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100
float tmpVal = (param.asfloat < 0) ? -param.asfloat : param.asfloat; float tmpVal = (param.asfloat < 0) ? -param.asfloat : param.asfloat;
int tmpInt1 = tmpVal; // Get the integer int tmpInt1 = tmpVal; // Get the integer
float tmpFrac = tmpVal - tmpInt1; // Get fraction float tmpFrac = tmpVal - tmpInt1; // Get fraction
int tmpInt2 = trunc(tmpFrac * 100); // Turn into integer int tmpInt2 = trunc(tmpFrac * 1000); // Turn into integer
// Print as parts, note that you need 0-padding for fractional bit. // Print as parts, note that you need 0-padding for fractional bit.
if (param.asfloat < 0) if (param.asfloat < 0)
snprintf (argPtr, bufLen, "-%d.%02d", tmpInt1, tmpInt2); snprintf (argPtr, bufLen, "-%d.%03d", tmpInt1, tmpInt2);
else snprintf (argPtr, bufLen, "%d.%02d", tmpInt1, tmpInt2); else snprintf (argPtr, bufLen, "%d.%03d", tmpInt1, tmpInt2);
} }
break; break;
case ST_RGB: case ST_RGB:

View File

@@ -169,6 +169,7 @@ public:
itemCmd Int(uint32_t i); itemCmd Int(uint32_t i);
itemCmd Float(float f); itemCmd Float(float f);
itemCmd Tens(int32_t i); itemCmd Tens(int32_t i);
itemCmd Tens_raw(int32_t i);
itemCmd Cmd(uint8_t i); itemCmd Cmd(uint8_t i);
itemCmd HSV(uint16_t h, uint8_t s, uint8_t v); itemCmd HSV(uint16_t h, uint8_t s, uint8_t v);
itemCmd HSV255(uint16_t h, uint8_t s, uint8_t v); itemCmd HSV255(uint16_t h, uint8_t s, uint8_t v);
@@ -192,12 +193,13 @@ public:
uint8_t getSuffix(); uint8_t getSuffix();
itemCmd setSuffix(uint8_t suffix); itemCmd setSuffix(uint8_t suffix);
bool incrementPercents(int16_t); bool incrementPercents(long int, long int limit);
bool incrementH(int16_t); bool incrementH(long int);
bool incrementS(int16_t); bool incrementS(long int);
long int getInt(); long int getInt();
long int getTens(); long int getTens();
long int getTens_raw();
float getFloat(); float getFloat();
char * getString(); char * getString();
long int getSingleInt(); long int getSingleInt();

View File

@@ -0,0 +1,132 @@
#ifndef COUNTER_DISABLE
#include "modules/out_counter.h"
#include "Arduino.h"
#include "options.h"
#include "Streaming.h"
#include "item.h"
#include "main.h"
//#include "dmx.h"
static int driverStatus = CST_UNKNOWN;
void out_counter::getConfig()
{
if (!item) return;
impulse = item->getFloatArg(0);
period = item->getFloatArg(1)*1000.0;
}
int out_counter::Setup()
{
abstractOut::Setup();
driverStatus = CST_INITIALIZED;
return 1;
}
int out_counter::Stop()
{
driverStatus = CST_UNKNOWN;
return 1;
}
int out_counter::Status()
{
return driverStatus;
}
int out_counter::Poll(short cause)
{
if (!item) return 0;
uint32_t timer = item->getExt();
if (timer && isTimeOver(timer,millis(),period))
{
item->setExt(millisNZ());
itemCmd st;
st.loadItem(item);
float val = st.getFloat();
//short cmd = st.getCmd();
val+=period;
st.Float(val);
st.saveItem(item);
}
return 0;
};
int out_counter::Ctrl(itemCmd cmd, char* subItem, bool toExecute)
{
debugSerial<<F("Counter: ");
cmd.debugOut();
int suffixCode;
if (cmd.isCommand()) suffixCode = S_CMD;
else suffixCode = cmd.getSuffix();
switch(suffixCode)
{
case S_NOTFOUND:
// turn on and set
toExecute = true;
case S_SET:
if (toExecute)
{
if (cmd.getPercents255())
{
if (!item->getExt())
{
item->setExt(millisNZ());
//relay(true);
}
}
else
{
item->setExt(0);
}
}
return 1;
case S_CMD:
switch (cmd.getCmd())
{
case CMD_ON:
case CMD_HEAT:
case CMD_COOL:
case CMD_AUTO:
case CMD_FAN:
case CMD_DRY:
if (!item->getExt())
{
item->setExt(millisNZ());
//relay(true);
}
return 1;
case CMD_OFF:
item->setExt(0);
return 1;
default:
debugSerial<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
} //switch cmd
default:
debugSerial<<F("Unknown suffix ")<<suffixCode<<endl;
} //switch suffix
return 0;
}
int out_counter::getChanType()
{
return CH_COUNTER;
}
#endif

View File

@@ -0,0 +1,26 @@
#pragma once
#include "options.h"
#ifndef COUNTER_DISABLE
#include <abstractout.h>
#include <item.h>
class out_counter : public abstractOut {
public:
out_counter(Item * _item):abstractOut(_item){ getConfig();};
void getConfig();
int Setup() override;
int Poll(short cause) override;
int Stop() override;
int Status() override;
int getChanType() override;
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true) override;
protected:
float impulse;
uint32_t period;
};
#endif

View File

@@ -39,6 +39,7 @@ struct serial_t
#define PAR_U8H 7 #define PAR_U8H 7
#define PAR_U8L 8 #define PAR_U8L 8
#define PAR_TENS 9 #define PAR_TENS 9
#define PAR_100 10
const reg_t regSize_P[] PROGMEM = const reg_t regSize_P[] PROGMEM =
@@ -51,7 +52,8 @@ const reg_t regSize_P[] PROGMEM =
{ "i8l", (uint8_t) PAR_I8L }, { "i8l", (uint8_t) PAR_I8L },
{ "u8h", (uint8_t) PAR_U8H }, { "u8h", (uint8_t) PAR_U8H },
{ "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 }
} ; } ;
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t) #define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
@@ -233,7 +235,7 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
bool is8bit = false; bool is8bit = false;
while (paramObj) while (paramObj)
{ {
aJsonObject *regObj; 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;
@@ -257,12 +259,13 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
case PAR_I16: case PAR_I16:
//isSigned=true; //isSigned=true;
param=data;
mappedParam.Int((int32_t)data); mappedParam.Int((int32_t)data);
break; break;
case PAR_U16: case PAR_U16:
param=data;
mappedParam.Int((uint32_t)data); mappedParam.Int((uint32_t)data);
//param=data;
break; break;
case PAR_I32: case PAR_I32:
//isSigned=true; //isSigned=true;
@@ -288,7 +291,14 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
break; break;
case PAR_TENS: case PAR_TENS:
param=data;
mappedParam.Tens((int32_t) data); mappedParam.Tens((int32_t) data);
break;
case PAR_100:
param=data;
mappedParam.Tens_raw(data * (TENS_BASE/100));
mappedParam.Float((int32_t) data/100.);
} }
if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object)) if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object))
@@ -306,16 +316,24 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S"); aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S");
if (lastMeasured) if (lastMeasured)
{ {
if (lastMeasured->valueint == mappedParam.getSingleInt()) if (lastMeasured->valueint == param)
submitParam=false; //supress repeating execution for same val submitParam=false; //supress repeating execution for same val
else lastMeasured->valueint=mappedParam.getSingleInt(); else lastMeasured->valueint=param;
} }
else //No container to store value yet else //No container to store value yet
{ {
debugSerial<<F("Add @S: ")<<paramObj->name<<endl; debugSerial<<F("Add @S: ")<<paramObj->name<<endl;
aJson.addNumberToObject(execObj, "@S", mappedParam.getSingleInt()); aJson.addNumberToObject(execObj, "@S", (long) param);
}
if (submitParam)
{ // Compare with last submitted val
aJsonObject *settedValue = aJson.getObjectItem(execObj,"@V");
if (settedValue && (settedValue->valueint == param))
{
debugSerial<<F("Ignored - equal with setted val")<<endl;
}
else executeCommand(execObj, -1, mappedParam);
} }
if (submitParam) executeCommand(execObj, -1, mappedParam);
} }
} }
if (!is8bit) return 1; if (!is8bit) return 1;
@@ -387,7 +405,7 @@ void out_Modbus::initLine()
node.begin(item->getArg(0), modbusSerial); node.begin(item->getArg(0), modbusSerial);
} }
int out_Modbus::sendModbus(char * paramName, uint32_t value, uint8_t regType) int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
{ {
if (!store) return -1; if (!store) return -1;
aJsonObject * templateParamObj = aJson.getObjectItem(store->parameters, paramName); aJsonObject * templateParamObj = aJson.getObjectItem(store->parameters, paramName);
@@ -401,9 +419,12 @@ int out_Modbus::sendModbus(char * paramName, uint32_t value, uint8_t regType)
// 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_U16: case PAR_U16:
//res = node.writeSingleRegister(regObj->valueint,value);
//break;
case PAR_I16:
case PAR_TENS: case PAR_TENS:
case PAR_100:
res = node.writeSingleRegister(regObj->valueint,value); res = node.writeSingleRegister(regObj->valueint,value);
break; break;
@@ -424,7 +445,7 @@ int out_Modbus::sendModbus(char * paramName, uint32_t value, uint8_t regType)
res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8); res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8);
break; break;
} }
debugSerial<<F("MB_SEND Res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<value<<endl; debugSerial<<F("MB_SEND Res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<value<<F(" ival:")<<(int32_t) value<<endl;
return ( res == 0); return ( res == 0);
} }
@@ -458,6 +479,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
break; break;
case 0: //fault case 0: //fault
execObj->subtype |= MB_SEND_ERROR; execObj->subtype |= MB_SEND_ERROR;
errorSerial<<F("MBus ")<<execObj->name<<F(" send error")<<endl;
break; 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;
@@ -578,6 +600,9 @@ aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
break; break;
case PAR_TENS: case PAR_TENS:
Value=cmd.getTens(); Value=cmd.getTens();
break;
case PAR_100:
Value=cmd.getTens_raw()*(100/TENS_BASE);
} }
debugSerial<<F("MB suffix:")<<suffixStr<< F(" Val: ")<<Value<<endl; debugSerial<<F("MB suffix:")<<suffixStr<< F(" Val: ")<<Value<<endl;
@@ -587,6 +612,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) if (execObj && execObj->type == aJson_Object)
{ {
aJsonObject *polledValue = aJson.getObjectItem(execObj,"@S");
if (polledValue && (polledValue->valueint == Value))
{
debugSerial<<F("Ignored - not changed")<<endl;
}
else
{ //Schedule update
execObj->subtype |= MB_NEED_SEND; execObj->subtype |= MB_NEED_SEND;
aJsonObject *outValue = aJson.getObjectItem(execObj,"@V"); aJsonObject *outValue = aJson.getObjectItem(execObj,"@V");
@@ -594,6 +627,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ {
outValue->valueint=Value; outValue->valueint=Value;
outValue->subtype =regType; outValue->subtype =regType;
polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
} }
else //No container to store value yet else //No container to store value yet
{ {
@@ -604,6 +638,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
} }
} }
} }
}

View File

@@ -45,6 +45,6 @@ protected:
int findRegister(int registerNum, int posInBuffer, int regType); int findRegister(int registerNum, int posInBuffer, int regType);
void pollModbus(aJsonObject * reg, int regType); void pollModbus(aJsonObject * reg, int regType);
void initLine(); void initLine();
int sendModbus(char * paramName, uint32_t value, uint8_t regType); int sendModbus(char * paramName, int32_t value, uint8_t regType);
}; };
#endif #endif

View File

@@ -276,8 +276,6 @@ int out_pid::getChanType()
int out_pid::Ctrl(itemCmd cmd, char* subItem, bool toExecute) int out_pid::Ctrl(itemCmd cmd, char* subItem, bool toExecute)
{ {
if (!store || !store->pid || (Status() != CST_INITIALIZED)) return 0; if (!store || !store->pid || (Status() != CST_INITIALIZED)) 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
@@ -307,6 +305,12 @@ case S_SET:
if (!cmd.isValue()) return 0; if (!cmd.isValue()) return 0;
store->setpoint=cmd.getFloat(); store->setpoint=cmd.getFloat();
debugSerial<<F("Setpoint:")<<store->setpoint<<endl; debugSerial<<F("Setpoint:")<<store->setpoint<<endl;
{
aJsonObject * itemCascadeObj = aJson.getArrayItem(item->itemArg, 2);
if (itemCascadeObj) executeCommand(itemCascadeObj,-1,cmd);
}
//cmd.saveItem(item); //cmd.saveItem(item);
//item->SendStatus(SEND_PARAMETERS); //item->SendStatus(SEND_PARAMETERS);
return 1; return 1;

View File

@@ -1,5 +1,10 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#define TENS_FRACT_LEN 2
#define TENS_BASE 100
#define DEFAULT_FILESIZE_LIMIT 65535 #define DEFAULT_FILESIZE_LIMIT 65535
#ifndef MAX_JSON_CONF_SIZE #ifndef MAX_JSON_CONF_SIZE

View File

@@ -116,31 +116,45 @@ int getInt(char **chan) {
// Function return first retrived number and move pointer to position next after ',' // Function return first retrived number and move pointer to position next after ','
itemCmd getNumber(char **chan) { itemCmd getNumber(char **chan) {
itemCmd val(ST_TENS,CMD_VOID); itemCmd val(ST_TENS,CMD_VOID);
int fract =0;
if (chan && *chan && **chan) if (chan && *chan && **chan)
{ {
//Skip non-numeric values //Skip non-numeric values
while (**chan && !(**chan == '-' || (**chan >= '0' && **chan<='9'))) *chan += 1; while (**chan && !(**chan == '-' || (**chan >= '0' && **chan<='9'))) *chan += 1;
int ch = atoi(*chan);
long fractnumbers = 0;
short fractlen = 0;
short intlen = 0;
char * intptr = * chan;
if (*intptr == '-') intptr ++;
while (isDigit(*(intptr+intlen))) intlen++;
char * fractptr = strchr(*chan,'.'); char * fractptr = strchr(*chan,'.');
if (fractptr) if (fractptr)
{ {
// fract = atoi(fractptr); fractptr ++;
// *chan = fractptr; while (isDigit(*(fractptr+fractlen))) fractlen++;
fractptr += 1;
fract = constrain(*fractptr-'0',0,9); for (short i=0;i<TENS_FRACT_LEN;i++)
{
fractnumbers = fractnumbers * 10;
if (isDigit(*(fractptr+i))) fractnumbers += constrain(*(fractptr+i)-'0',0,9);
} }
}
if (!fractlen) val.Int(atol(*chan));
else if (fractlen<=TENS_FRACT_LEN && intlen+TENS_FRACT_LEN<=9)
{
long intpart = atol(*chan);
val.Tens_raw(intpart*TENS_BASE+((intpart>=0)?fractnumbers:-fractnumbers));
}
else
val.Float(atof(*chan));
//Move pointer to next element (after ,) //Move pointer to next element (after ,)
*chan = strchr(*chan, ','); *chan = strchr(*chan, ',');
if (*chan) *chan += 1; if (*chan) *chan += 1;
//debugSerialPort.print(F("Par:")); debugSerialPort.println(ch);
if (fract)
val.Tens(ch*10+((ch>0)?fract:-fract));
else
val.Int((int32_t)ch);
} }
//val.debugOut(); //val.debugOut();
return val; return val;