С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_uartbridge.h"
#include "modules/out_relay.h"
#include "modules/out_counter.h"
#ifdef ELEVATOR_ENABLE
#include "modules/out_elevator.h"
@@ -205,6 +206,12 @@ void Item::Parse() {
driver = new out_elevator (this);
// debugSerial<<F("AC driver created")<<endl;
break;
#endif
#ifndef COUNTER_DISABLE
case CH_COUNTER:
driver = new out_counter (this);
// debugSerial<<F("AC driver created")<<endl;
break;
#endif
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;
itemVal->valueint = par;
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)
@@ -426,7 +433,7 @@ void Item::setFloatVal(float par) // Only store if VAL is int (autogenerated or
//debugSerial<<F(" Store ")<<F(" Val=")<<par<<endl;
itemVal->valuefloat = par;
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)
@@ -525,6 +532,22 @@ else
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
int Item::Ctrl(char * payload, char * subItem)
{
@@ -638,6 +661,14 @@ st.setSuffix(suffixCode);
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
{
int32_t intParam = getInt((char **) &payload);
@@ -852,8 +883,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
case CMD_UP:
{
itemCmd fallbackCmd=cmd;
short step=0;
if (cmd.isValue()) step=cmd.getInt();
long step=0;
if (cmd.isValue()) step=cmd.getTens_raw();
if (!step) step=DEFAULT_INC_STEP;
if (cmd.getCmd() == CMD_DN) step=-step;
@@ -867,7 +898,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion)
toExecute=true;
case S_SET:
if (cmd.incrementPercents(step))
if (cmd.incrementPercents(step,(suffixCode==S_NOTFOUND)?100:limitSetValue()))
{
status2Send |= SEND_PARAMETERS | SEND_DEFFERED;
} else {cmd=fallbackCmd;invalidArgument=true;}
@@ -1121,6 +1152,7 @@ if (status2Send) cmd.saveItem(this,status2Send);
if (driver) //New style modular code
{
res = driver->Ctrl(cmd, subItem, toExecute);
if (driver->getChanType() == CH_THERMO) status2Send |= SEND_IMMEDIATE;
//if (res==-1) status2Send=0; ///////not working
}
else

View File

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

View File

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

View File

@@ -169,6 +169,7 @@ public:
itemCmd Int(uint32_t i);
itemCmd Float(float f);
itemCmd Tens(int32_t i);
itemCmd Tens_raw(int32_t i);
itemCmd Cmd(uint8_t i);
itemCmd HSV(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();
itemCmd setSuffix(uint8_t suffix);
bool incrementPercents(int16_t);
bool incrementH(int16_t);
bool incrementS(int16_t);
bool incrementPercents(long int, long int limit);
bool incrementH(long int);
bool incrementS(long int);
long int getInt();
long int getTens();
long int getTens_raw();
float getFloat();
char * getString();
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_U8L 8
#define PAR_TENS 9
#define PAR_100 10
const reg_t regSize_P[] PROGMEM =
@@ -51,7 +52,8 @@ const reg_t regSize_P[] PROGMEM =
{ "i8l", (uint8_t) PAR_I8L },
{ "u8h", (uint8_t) PAR_U8H },
{ "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)
@@ -233,7 +235,7 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
bool is8bit = false;
while (paramObj)
{
aJsonObject *regObj;
aJsonObject *regObj=NULL;
switch (regType) {
case MODBUS_HOLDING_REG_TYPE: regObj = aJson.getObjectItem(paramObj, "reg");
break;
@@ -257,12 +259,13 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
case PAR_I16:
//isSigned=true;
param=data;
mappedParam.Int((int32_t)data);
break;
case PAR_U16:
param=data;
mappedParam.Int((uint32_t)data);
//param=data;
break;
case PAR_I32:
//isSigned=true;
@@ -288,7 +291,14 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
break;
case PAR_TENS:
param=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))
@@ -306,16 +316,24 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType)
aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S");
if (lastMeasured)
{
if (lastMeasured->valueint == mappedParam.getSingleInt())
if (lastMeasured->valueint == param)
submitParam=false; //supress repeating execution for same val
else lastMeasured->valueint=mappedParam.getSingleInt();
else lastMeasured->valueint=param;
}
else //No container to store value yet
{
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;
@@ -387,7 +405,7 @@ void out_Modbus::initLine()
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;
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);
switch(regType) {
case PAR_I16:
case PAR_U16:
//res = node.writeSingleRegister(regObj->valueint,value);
//break;
case PAR_I16:
case PAR_TENS:
case PAR_100:
res = node.writeSingleRegister(regObj->valueint,value);
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);
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);
}
@@ -458,6 +479,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
break;
case 0: //fault
execObj->subtype |= MB_SEND_ERROR;
errorSerial<<F("MBus ")<<execObj->name<<F(" send error")<<endl;
break;
default: //param not found
errorSerial<<F("MBus param ")<<execObj->name<<F(" not found")<<endl;
@@ -578,6 +600,9 @@ aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
break;
case PAR_TENS:
Value=cmd.getTens();
break;
case PAR_100:
Value=cmd.getTens_raw()*(100/TENS_BASE);
}
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);
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;
aJsonObject *outValue = aJson.getObjectItem(execObj,"@V");
@@ -594,6 +627,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{
outValue->valueint=Value;
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
{
@@ -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);
void pollModbus(aJsonObject * reg, int regType);
void initLine();
int sendModbus(char * paramName, uint32_t value, uint8_t regType);
int sendModbus(char * paramName, int32_t value, uint8_t regType);
};
#endif

View File

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

View File

@@ -1,5 +1,10 @@
#pragma once
#include <Arduino.h>
#define TENS_FRACT_LEN 2
#define TENS_BASE 100
#define DEFAULT_FILESIZE_LIMIT 65535
#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 ','
itemCmd getNumber(char **chan) {
itemCmd val(ST_TENS,CMD_VOID);
int fract =0;
if (chan && *chan && **chan)
{
//Skip non-numeric values
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,'.');
if (fractptr)
{
// fract = atoi(fractptr);
// *chan = fractptr;
fractptr += 1;
fract = constrain(*fractptr-'0',0,9);
fractptr ++;
while (isDigit(*(fractptr+fractlen))) fractlen++;
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 ,)
*chan = strchr(*chan, ',');
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();
return val;