mirror of
https://github.com/anklimov/lighthub
synced 2026-06-13 19:36:23 +03:00
1639 lines
44 KiB
C++
1639 lines
44 KiB
C++
#include <Arduino.h>
|
||
#include "itemCmd.h"
|
||
#include "main.h"
|
||
#include "Streaming.h"
|
||
#include "item.h"
|
||
#include "bright.h"
|
||
#include <utility/stringbuffer.h>>
|
||
|
||
#ifndef HSV_DISABLE
|
||
#ifdef ADAFRUIT_LED
|
||
#include <Adafruit_NeoPixel.h>
|
||
#else
|
||
#include "FastLED.h"
|
||
#endif
|
||
#endif
|
||
|
||
//#include "hsv2rgb.h"
|
||
|
||
int txt2cmd(char *payload) {
|
||
int cmd = CMD_UNKNOWN;
|
||
if (!payload || !payload[0]) return cmd;
|
||
|
||
// Check for command
|
||
if (*payload == '-' || (*payload >= '0' && *payload <= '9')) cmd = CMD_VOID;
|
||
else if (*payload == '%') cmd = CMD_UP;
|
||
else if (*payload == '{') cmd = CMD_JSON;
|
||
else if (*payload == '#') cmd = CMD_RGB;
|
||
else
|
||
{
|
||
for(uint8_t i=1; i<commandsNum ;i++)
|
||
if (strncmp_P(payload, commands_P[i], strlen_P(commands_P[i])) == 0)
|
||
{
|
||
// debugSerial<< i << F(" ") << pgm_read_word_near(&serialModes_P[i].mode)<< endl;
|
||
return i;
|
||
}
|
||
}
|
||
|
||
|
||
return cmd;
|
||
}
|
||
|
||
|
||
int type2num(char *payload) {
|
||
if (!payload || !payload[0]) return -1;
|
||
|
||
for(uint8_t i=0; i<ch_typeNum ;i++)
|
||
if (strncmp_P(payload, ch_type_P[i], strlen_P(ch_type_P[i])) == 0)
|
||
{
|
||
return i;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
|
||
|
||
/*!
|
||
\brief Constructor with definition of type and command
|
||
\param type - type of value (ST_???, ST_VOID by default)
|
||
\param code - code of command (CMD_VOID by default)
|
||
*/
|
||
itemCmd::itemCmd(uint8_t _type, uint8_t _code)
|
||
{
|
||
cmd.aslong=0;
|
||
param.aslong=0;
|
||
|
||
cmd.itemArgType=_type;
|
||
cmd.cmdCode=_code;
|
||
}
|
||
|
||
|
||
/*!
|
||
\brief Constructor with definition of FLOAT value in storage
|
||
\param float
|
||
\param type - type of value (ST_FLOAT or ST_FLOAT_CELSIUS or ST_FLOAT_FARENHEIT) - optional
|
||
*/
|
||
itemCmd::itemCmd(float val)
|
||
{
|
||
cmd.aslong=0;
|
||
param.aslong=0;
|
||
|
||
cmd.itemArgType=ST_FLOAT;
|
||
param.asfloat=val;
|
||
}
|
||
|
||
/*!
|
||
\brief Constructor with loading value from Item
|
||
\param Item
|
||
*/
|
||
itemCmd::itemCmd(Item *item)
|
||
{
|
||
cmd.aslong=0;
|
||
param.aslong=0;
|
||
|
||
loadItem(item);
|
||
}
|
||
|
||
/*!
|
||
\brief Constructor with textual definition of command
|
||
\param cmd - name of cmd
|
||
todo - extend to values
|
||
*/
|
||
itemCmd::itemCmd(char * _cmd)
|
||
{
|
||
//debugSerial<<"ITEMCMD:" <<_cmd<<endl;
|
||
cmd.aslong=0;
|
||
param.aslong=0;
|
||
|
||
short i=0;
|
||
int Par[4];
|
||
|
||
while (_cmd[i]) {_cmd[i]=toupper(_cmd[i]);i++;};
|
||
|
||
int cmdN = txt2cmd(_cmd);
|
||
if (cmdN>=0) cmd.cmdCode = cmdN;
|
||
|
||
bool hsvflag=false;
|
||
|
||
switch (cmd.cmdCode) {
|
||
case CMD_HSV:
|
||
hsvflag=true;
|
||
case CMD_RGB:
|
||
|
||
cmd.cmdCode=CMD_VOID;
|
||
//Parsing integers from payload
|
||
i = 0;
|
||
|
||
while (_cmd && i < 4)
|
||
Par[i++] = getIntFromStr((char **) &_cmd);
|
||
|
||
if (hsvflag)
|
||
{
|
||
setSuffix(S_HSV);
|
||
cmd.itemArgType=ST_HSV255;
|
||
switch (i) //Number of params
|
||
{
|
||
case 4:
|
||
setColorTemp(Par[3]);
|
||
case 3:
|
||
param.v=Par[2];
|
||
case 2:
|
||
setH(Par[0]);
|
||
setS(Par[1]);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
setSuffix(S_RGB);
|
||
switch (i) //Number of params
|
||
{
|
||
case 3: RGB(Par[0],Par[1],Par[2]);
|
||
break;
|
||
case 4: RGBW(Par[0],Par[1],Par[2],Par[3]);
|
||
default:;
|
||
}
|
||
}
|
||
|
||
break;
|
||
|
||
// case CMD_UNKNOWN: //Not known command
|
||
// case CMD_JSON: //JSON input (not implemented yet
|
||
// cmd.cmdCode=CMD_VOID;
|
||
// break;
|
||
|
||
default: //some known command
|
||
//case CMD_VOID:
|
||
//case CMD_UP:
|
||
//case CMD_DN:
|
||
{
|
||
itemCmd num =getNumber((char **) &_cmd);
|
||
cmd.itemArgType=num.getArgType();
|
||
param.aslong=num.param.aslong;
|
||
if (cmd.cmdCode) setSuffix(S_CMD);
|
||
}
|
||
} //switch
|
||
//debugOut();
|
||
}
|
||
|
||
itemCmd itemCmd::setChanType(short chanType)
|
||
{
|
||
cmd.itemArgType=getStoragetypeByChanType(chanType);
|
||
debugSerial<<F("Chan type:")<<chanType<<F(" -> AT:")<<cmd.itemArgType<<endl;
|
||
return *this;
|
||
}
|
||
|
||
|
||
uint8_t itemCmd::getStoragetypeByChanType(short chanType)
|
||
{
|
||
switch (chanType)
|
||
{
|
||
case CH_RGB:
|
||
case CH_RGBW:
|
||
case CH_RGBWW:
|
||
case CH_SPILED:
|
||
return ST_HSV255;
|
||
break;
|
||
case CH_AC:
|
||
case CH_THERMO:
|
||
case CH_VCTEMP:
|
||
return ST_FLOAT_CELSIUS;
|
||
break;
|
||
case CH_DIMMER:
|
||
case CH_MOTOR:
|
||
case CH_PWM:
|
||
case CH_VC:
|
||
case CH_MODBUS:
|
||
//case CH_RELAY:
|
||
//case CH_GROUP:
|
||
return ST_PERCENTS255;
|
||
break;
|
||
case CH_RELAY:
|
||
return ST_VOID;
|
||
//case CH_COUNTER:
|
||
//return ST_TENS;
|
||
default:
|
||
return ST_VOID;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
itemCmd itemCmd::setDefault()
|
||
{
|
||
switch (cmd.itemArgType){
|
||
case ST_FLOAT_CELSIUS: param.asfloat=20.;
|
||
break;
|
||
case ST_FLOAT_FARENHEIT: param.asfloat=75.;
|
||
break;
|
||
|
||
case ST_HS:
|
||
case ST_HSV255: param.h=100; param.s=0; param.v=255;
|
||
break;
|
||
case ST_PERCENTS255: param.v=255;
|
||
break;
|
||
default:
|
||
param.asInt32=0;
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
bool itemCmd::setH(uint16_t h)
|
||
{
|
||
int par=h;
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_VOID:
|
||
cmd.itemArgType=ST_HSV255;
|
||
case ST_HSV255:
|
||
if (par>365) par=365;
|
||
if (par<0) par=0;
|
||
param.h=par;
|
||
break;
|
||
|
||
default:
|
||
// debugSerial<<F("Can't assign HUE to type ")<<cmd.itemArgType<<endl;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool itemCmd::setS(uint8_t s)
|
||
{
|
||
int par=s;
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_VOID:
|
||
cmd.itemArgType=ST_HSV255;
|
||
case ST_HSV255:
|
||
if (par>100) par=100;
|
||
param.s=par;
|
||
break;
|
||
default:
|
||
// debugSerial<<F("Can't assign saturation to type ")<<cmd.itemArgType<<endl;
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
//! Setup color tempetature parameter for HSV or HSV255 types. It must be 153..500 (mireds) value.
|
||
//! Internally 1 - cold, 101 - warm light
|
||
bool itemCmd::setColorTemp(int t)
|
||
{
|
||
if (!t)
|
||
{
|
||
param.colorTemp=0;
|
||
return true;
|
||
}
|
||
int par=map(t,153,500,0,100);
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_VOID:
|
||
cmd.itemArgType=ST_HSV255;
|
||
case ST_HS:
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
if (par>100) par=100;
|
||
if (par<0) par=0;
|
||
//debugSerial<<F("Assign color temp:")<<par<<endl;
|
||
// value 0 is reserved for default/uninitialized value. Internally data stored in 1..101 range (7 bits)
|
||
param.colorTemp=par+1;
|
||
break;
|
||
default:
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//! Return color tempetature parameter from HSV or HSV255 types. return 153..500 value in success.
|
||
//! -1 - if no value stored
|
||
int itemCmd::getColorTemp()
|
||
{
|
||
if (!param.colorTemp) return -1;
|
||
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_HS:
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
|
||
return map(param.colorTemp-1,0,100,153,500);
|
||
break;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
uint16_t itemCmd::getH()
|
||
{
|
||
return param.h;
|
||
}
|
||
|
||
uint16_t itemCmd::getS()
|
||
{
|
||
return param.s;
|
||
}
|
||
|
||
|
||
bool itemCmd::incrementPercents(long int dif, long int limit )
|
||
{ long par=param.v;
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
par+=dif/TENS_BASE;
|
||
if (par>255) par=255;
|
||
if (par<0) par=0;
|
||
param.v=par;
|
||
break;
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
if (dif<TENS_BASE) // Step < 1 - convert to tens
|
||
{
|
||
par=param.asInt32*TENS_BASE;
|
||
par+=dif;
|
||
|
||
if (limit && par>limit*TENS_BASE) par=limit*TENS_BASE;
|
||
if (limit && par<0) par=0;
|
||
|
||
param.asInt32=par;
|
||
cmd.itemArgType=ST_TENS;
|
||
}
|
||
else
|
||
{
|
||
par=param.asInt32;
|
||
par+=dif/TENS_BASE;
|
||
if (limit && par>limit) par=limit;
|
||
if (limit && par<0) par=0;
|
||
param.asInt32=par;
|
||
}
|
||
break;
|
||
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
case ST_FLOAT_FARENHEIT:
|
||
par=param.asfloat;
|
||
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;
|
||
if (limit && par>limit*TENS_BASE) par=limit*TENS_BASE;
|
||
if (limit && par<0) par=0;
|
||
param.asInt32=par;
|
||
break;
|
||
|
||
default: return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool itemCmd::incrementH(long int dif)
|
||
{ int par=param.h;
|
||
switch (cmd.itemArgType)
|
||
{
|
||
//case ST_HSV:
|
||
case ST_HSV255:
|
||
par+=dif/TENS_BASE;
|
||
if (par>365) par=0;
|
||
if (par<0) par=365;
|
||
break;
|
||
default: return false;
|
||
break;
|
||
}
|
||
param.h=par;
|
||
return true;
|
||
}
|
||
|
||
bool itemCmd::incrementS(long int dif)
|
||
{int par=param.s;
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_HSV255:
|
||
par+=dif/TENS_BASE;
|
||
if (par>100) par=100;
|
||
if (par<0) par=0;
|
||
break;
|
||
|
||
default: return false;
|
||
}
|
||
param.s=par;
|
||
return true;
|
||
|
||
}
|
||
|
||
bool itemCmd::incrementTemp(long int dif)
|
||
{int par=param.colorTemp;
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_HSV255:
|
||
par+=dif/TENS_BASE;
|
||
if (par>100) par=100;
|
||
if (par<1) par=1;
|
||
break;
|
||
|
||
default: return false;
|
||
}
|
||
param.colorTemp=par;
|
||
return true;
|
||
|
||
}
|
||
|
||
|
||
itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
|
||
{
|
||
bool RGBW_flag = false;
|
||
bool toFarenheit = false;
|
||
short prefferedStorageType = getStoragetypeByChanType(chanType);
|
||
|
||
int t=from.getColorTemp();
|
||
|
||
if (t>=0)
|
||
{
|
||
setColorTemp(t);
|
||
}
|
||
cmd.suffixCode=from.cmd.suffixCode;
|
||
cmd.cmdCode=from.cmd.cmdCode;
|
||
//cmd.cmdFlag
|
||
//cmd.cmdParam
|
||
|
||
switch (cmd.itemArgType){ //Destination
|
||
case ST_HSV255:
|
||
case ST_PERCENTS255:
|
||
switch (from.cmd.itemArgType)
|
||
{
|
||
case ST_RGBW:
|
||
param.w=from.param.w;
|
||
case ST_RGB:
|
||
param.r=from.param.r;
|
||
param.g=from.param.g;
|
||
param.b=from.param.b;
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
break;
|
||
case ST_HS:
|
||
param.h=from.param.h;
|
||
param.s=from.param.s;
|
||
break;
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
param.v=constrain(from.param.asInt32,0,255);
|
||
break;
|
||
case ST_TENS:
|
||
param.v=constrain(from.param.asInt32/TENS_BASE,0,255);
|
||
break;
|
||
case ST_HSV255:
|
||
param.h=from.param.h;
|
||
param.s=from.param.s;
|
||
param.v=from.param.v;
|
||
break;
|
||
case ST_PERCENTS255:
|
||
param.v=from.param.v;
|
||
break;
|
||
case ST_FLOAT:
|
||
param.v=constrain(from.param.asfloat,0.,255.);
|
||
break;
|
||
case ST_VOID:
|
||
break;
|
||
case ST_STRING:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param.asString=from.param.asString;
|
||
break;
|
||
default:
|
||
debugSerial<<F("Wrong Assignment ")<<from.cmd.itemArgType<<F("->")<<cmd.itemArgType<<endl;
|
||
}
|
||
break;
|
||
case ST_VOID:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param=from.param;
|
||
break;
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
case ST_TENS:
|
||
switch (from.cmd.itemArgType)
|
||
{
|
||
case ST_HS:
|
||
param.v=getPercents255();
|
||
param.h=from.param.h;
|
||
param.s=from.param.s;
|
||
cmd.itemArgType=ST_HSV255;
|
||
break;
|
||
case ST_STRING:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param.asString=from.param.asString;
|
||
break;
|
||
default:
|
||
param.asInt32=from.param.asInt32;
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
}
|
||
break;
|
||
case ST_HS: //ToDo - string ?
|
||
param.v=from.getPercents255();
|
||
cmd.itemArgType=ST_HSV255;
|
||
break;
|
||
case ST_FLOAT_FARENHEIT:
|
||
toFarenheit = true;
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
switch (from.cmd.itemArgType)
|
||
{
|
||
case ST_STRING:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param.asString=from.param.asString;
|
||
break;
|
||
|
||
case ST_TENS:
|
||
//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;
|
||
break;
|
||
|
||
case ST_INT32:
|
||
param.asfloat=from.param.asInt32;
|
||
break;
|
||
case ST_UINT32:
|
||
param.asfloat=from.param.asUint32;
|
||
break;
|
||
|
||
case ST_FLOAT_FARENHEIT:
|
||
// F to C code should be here
|
||
// if (!toFarenheit) convert (from.param.asfloat); cmd.itemArgType=ST_FARENHEIT
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param.asfloat=from.param.asfloat;
|
||
break;
|
||
case ST_HSV255:
|
||
case ST_RGB:
|
||
case ST_RGBW:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param=from.param;
|
||
break;
|
||
case ST_HS:
|
||
param.v=getPercents255();
|
||
param.h=from.param.h;
|
||
param.s=from.param.s;
|
||
cmd.itemArgType=ST_HSV255;
|
||
break;
|
||
case ST_VOID:
|
||
break;
|
||
default:
|
||
debugSerial<<F("Wrong Assignment ")<<from.cmd.itemArgType<<F("->")<<cmd.itemArgType<<endl;
|
||
}
|
||
|
||
break;
|
||
|
||
case ST_RGBW:
|
||
RGBW_flag=true;
|
||
case ST_RGB:
|
||
switch (from.cmd.itemArgType)
|
||
{
|
||
case ST_STRING:
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
param.asString=from.param.asString;
|
||
break;
|
||
case ST_RGBW:
|
||
// RGBW_flag=true;
|
||
case ST_RGB:
|
||
param.asInt32=from.param.asInt32;
|
||
cmd.itemArgType=from.cmd.itemArgType;
|
||
return *this;
|
||
//break;
|
||
// Those types are not possible to apply over RGB without convertion toward HSV
|
||
case ST_FLOAT:
|
||
case ST_HS:
|
||
case ST_INT32:
|
||
case ST_PERCENTS255:
|
||
case ST_TENS:
|
||
case ST_UINT32:
|
||
{
|
||
|
||
#ifndef ADAFRUIT_LED
|
||
// Restoring HSV from RGB
|
||
CRGB rgb;
|
||
rgb.r = param.r;
|
||
rgb.g = param.g;
|
||
rgb.b = param.b;
|
||
CHSV hsv = rgb2hsv_approximate(rgb);
|
||
#endif
|
||
|
||
// Calculate volume
|
||
int vol=0;
|
||
switch (from.cmd.itemArgType)
|
||
{
|
||
case ST_PERCENTS255:
|
||
vol=from.param.v;
|
||
break;
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
vol=from.param.asInt32;
|
||
break;
|
||
case ST_TENS:
|
||
vol=from.param.asInt32/TENS_BASE;
|
||
break;
|
||
case ST_FLOAT:
|
||
vol=from.param.asfloat;
|
||
break;
|
||
case ST_HS:
|
||
#ifndef ADAFRUIT_LED
|
||
vol=hsv.v;
|
||
#else
|
||
vol=255;
|
||
#endif
|
||
}
|
||
|
||
#ifndef ADAFRUIT_LED
|
||
// Restoring HSV from RGB
|
||
from.param.h = map(hsv.h, 0, 255, 0, 365);
|
||
from.param.s = map(hsv.s, 0, 255, 0, 100);
|
||
#else
|
||
from.param.h=100;
|
||
from.param.s=0;
|
||
#endif
|
||
|
||
from.cmd.itemArgType=ST_HSV255;
|
||
from.param.v=vol;
|
||
}
|
||
// Continue processing with filled from HSV
|
||
|
||
case ST_HSV255:
|
||
{ // HSV_XX to RGB_XX translation code
|
||
int rgbSaturation=constrain(map(from.param.s, 0, 100, 0, 255),0,255);
|
||
int rgbValue = getBright255(from.param.v);
|
||
short colorT =from.param.colorTemp-1;
|
||
if (RGBW_flag)
|
||
{
|
||
if (colorT<0)
|
||
{ //ColorTemperature not set
|
||
if (rgbSaturation < 128) { // Using white
|
||
param.w=map((127 - rgbSaturation) * rgbValue, 0, 127*255, 0, 255);
|
||
int rgbvLevel = map (rgbSaturation,0,127,0,255*2);
|
||
rgbValue = map(rgbValue, 0, 255, 0, rgbvLevel);
|
||
rgbSaturation = map(rgbSaturation, 0, 127, 100, 255);
|
||
if (rgbValue>255) rgbValue = 255;
|
||
}
|
||
else
|
||
{
|
||
rgbSaturation = map(rgbSaturation, 128, 255, 100, 255);
|
||
param.w=0;
|
||
};
|
||
debugSerial<<F("Converted S:")<<rgbSaturation<<F(" Converted V:")<<rgbValue<<endl;
|
||
}
|
||
else
|
||
{
|
||
long coldPercent = map (colorT,0,100,100,30);
|
||
long hotPercent = map (colorT,0,100,30,100);
|
||
int rgbvLevel = 0;
|
||
|
||
if (rgbSaturation < 128) { // Using white
|
||
param.w=map((127 - rgbSaturation) * rgbValue *hotPercent, 0, 127*255*100, 0, 255);
|
||
rgbvLevel = map (rgbSaturation+coldPercent,0,127+100,0,255*2);
|
||
rgbValue = map(rgbValue, 0, 255, 0, rgbvLevel);
|
||
rgbSaturation = map(rgbSaturation, 0, 127, 0, 255);
|
||
if (rgbValue>255) rgbValue = 255;
|
||
}
|
||
else
|
||
{
|
||
rgbSaturation = map(rgbSaturation, 128, 255, 100, 255);
|
||
param.w=0;
|
||
};
|
||
debugSerial<<F("Cold:")<<coldPercent<<F(" Hot:")<<hotPercent<<F(" ConvS:")<<rgbSaturation<<F(" ConvV:")<<rgbValue<<F(" vLevel:")<<rgbvLevel<<endl;
|
||
}
|
||
}
|
||
|
||
#ifndef HSV_DISABLE
|
||
#ifdef ADAFRUIT_LED
|
||
Adafruit_NeoPixel strip(0, 0, 0);
|
||
uint32_t rgb = strip.ColorHSV(map(from.param.h, 0, 365, 0, 65535), rgbSaturation, rgbValue);
|
||
param.r=(rgb >> 16)& 0xFF;
|
||
param.g=(rgb >> 8) & 0xFF;
|
||
param.b=rgb & 0xFF;
|
||
#else
|
||
CRGB rgb = CHSV(map(from.param.h, 0, 365, 0, 255), rgbSaturation, rgbValue);
|
||
param.r=rgb.r;
|
||
param.g=rgb.g;
|
||
param.b=rgb.b;
|
||
#endif
|
||
#else
|
||
debugSerial<<F("HSV disabled")<<endl;
|
||
#endif
|
||
debugSerial<<F("RGBx: ");
|
||
debugOut();
|
||
break;
|
||
}
|
||
case ST_VOID:
|
||
break;
|
||
default:
|
||
debugSerial<<F("Wrong Assignment ")<<from.cmd.itemArgType<<F("->")<<cmd.itemArgType<<endl;
|
||
} //Translation to RGB_XX
|
||
break;
|
||
} //Destination
|
||
|
||
if (prefferedStorageType) convertTo(prefferedStorageType);
|
||
|
||
return *this;
|
||
}
|
||
|
||
bool itemCmd::isCommand()
|
||
{
|
||
return (cmd.cmdCode);
|
||
}
|
||
|
||
bool itemCmd::isChannelCommand()
|
||
{
|
||
if (cmd.suffixCode==S_NOTFOUND || cmd.suffixCode==S_CMD )
|
||
return (cmd.cmdCode);
|
||
else return 0;
|
||
}
|
||
bool itemCmd::isValue()
|
||
{
|
||
return (cmd.itemArgType);
|
||
}
|
||
|
||
bool itemCmd::isColor()
|
||
{
|
||
|
||
return (cmd.itemArgType==ST_HS || cmd.itemArgType==ST_HSV255 || cmd.itemArgType==ST_RGB || cmd.itemArgType==ST_RGBW);
|
||
|
||
}
|
||
|
||
long int itemCmd::getTens()
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
case ST_RGB:
|
||
case ST_RGBW:
|
||
|
||
return param.aslong*10;
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
return param.v*10;
|
||
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
case ST_FLOAT_FARENHEIT:
|
||
return param.asfloat*10.0;
|
||
case ST_TENS:
|
||
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;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
long int itemCmd::getInt()
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
case ST_RGB:
|
||
case ST_RGBW:
|
||
|
||
return param.aslong;
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
return param.v;
|
||
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
case ST_FLOAT_FARENHEIT:
|
||
return param.asfloat;
|
||
case ST_TENS:
|
||
return param.aslong/TENS_BASE;
|
||
|
||
|
||
|
||
default:
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
char* itemCmd::getString()
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_STRING:
|
||
return param.asString;
|
||
default:
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
|
||
float itemCmd::getFloat()
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
case ST_RGB:
|
||
case ST_RGBW:
|
||
|
||
return param.aslong;
|
||
case ST_TENS:
|
||
return param.aslong/TENS_BASE;
|
||
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
return param.v;
|
||
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
case ST_FLOAT_FARENHEIT:
|
||
return param.asfloat;
|
||
|
||
|
||
default:
|
||
return 0.;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
long int itemCmd::getSingleInt()
|
||
{
|
||
if (cmd.cmdCode) return cmd.cmdCode;
|
||
return getInt();
|
||
}
|
||
|
||
short itemCmd::getPercents(bool inverse)
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
if (inverse) return constrain(100-param.asInt32,0,100);
|
||
else return constrain(param.asInt32,0,100);
|
||
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
if (inverse) return map(param.v,0,255,100,0);
|
||
else return map(param.v,0,255,0,100);
|
||
|
||
case ST_FLOAT:
|
||
if (inverse) return constrain (100-param.asfloat,0,100);
|
||
else return constrain (param.asfloat,0,100);
|
||
|
||
case ST_TENS:
|
||
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;
|
||
|
||
default:
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
bool itemCmd::setPercents(int percents)
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
param.asInt32=map(percents,0,100,0,255);
|
||
break;
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
param.v=map(percents,0,100,0,255);
|
||
break;
|
||
case ST_FLOAT:
|
||
param.asfloat=map(percents,0,100,0,255);;
|
||
break;
|
||
case ST_TENS:
|
||
param.asInt32 = map(percents,0,100,0,255*TENS_BASE);;
|
||
default:
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
short itemCmd::getPercents255(bool inverse)
|
||
{
|
||
switch (cmd.itemArgType) {
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
if (inverse) return 255-constrain(param.asInt32,0,255); else return constrain(param.asInt32,0,255);
|
||
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
if (inverse) return 255-param.v; else return param.v;
|
||
|
||
case ST_FLOAT:
|
||
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/TENS_BASE,0,255); else return constrain(param.asInt32/TENS_BASE,0,255);
|
||
|
||
case ST_VOID:
|
||
return 0;
|
||
default:
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
uint8_t itemCmd::getCmd()
|
||
{
|
||
return cmd.cmdCode;
|
||
}
|
||
|
||
uint8_t itemCmd::getArgType()
|
||
{
|
||
return cmd.itemArgType;
|
||
}
|
||
|
||
itemCmd itemCmd::setArgType(uint8_t type)
|
||
{
|
||
cmd.itemArgType=type & 0xF;
|
||
return *this;
|
||
}
|
||
|
||
|
||
itemCmd itemCmd::convertTo(uint8_t type)
|
||
{
|
||
if (cmd.itemArgType == type) return *this;
|
||
debugSerial << F("Converting ") << cmd.itemArgType << F("->") << type << F(" ");
|
||
itemCmd out(type,cmd.cmdCode);
|
||
*this=out.assignFrom(*this);
|
||
debugOut();
|
||
return *this;
|
||
}
|
||
|
||
uint8_t itemCmd::getCmdParam()
|
||
{
|
||
if (isCommand()) return cmd.cmdParam;
|
||
return 0;
|
||
}
|
||
|
||
itemCmd itemCmd::Percents(int i)
|
||
{
|
||
if (i<0) i=0;
|
||
if (i>100) i=100;
|
||
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_HSV255:
|
||
case ST_PERCENTS255:
|
||
break;
|
||
default:
|
||
cmd.itemArgType=ST_PERCENTS255;
|
||
}
|
||
param.v=map(i,0,100,0,255);
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::Percents255(int i)
|
||
{
|
||
if (i<0) i=0;
|
||
if (i>255) i=255;
|
||
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_HSV255:
|
||
case ST_PERCENTS255:
|
||
param.v=i;
|
||
break;
|
||
default:
|
||
cmd.itemArgType=ST_PERCENTS255;
|
||
param.v=i;
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::Int(int32_t i)
|
||
{
|
||
cmd.itemArgType=ST_INT32;
|
||
param.asInt32=i;
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::uInt(uint32_t i)
|
||
{
|
||
cmd.itemArgType=ST_UINT32;
|
||
param.asUint32=i;
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::Float(float f)
|
||
{
|
||
cmd.itemArgType=ST_FLOAT;
|
||
param.asfloat=f;
|
||
return *this;
|
||
}
|
||
|
||
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;
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::HSV(uint16_t h, uint8_t s, uint8_t v)
|
||
{
|
||
cmd.itemArgType=ST_HSV255;
|
||
param.h=h;
|
||
param.s=s;
|
||
param.v=map(v,0,100,0,255);
|
||
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::HSV255(uint16_t h, uint8_t s, uint8_t v)
|
||
{
|
||
cmd.itemArgType=ST_HSV255;
|
||
param.h=h;
|
||
param.s=s;
|
||
param.v=v;
|
||
|
||
return *this;
|
||
}
|
||
|
||
|
||
itemCmd itemCmd::HS(uint16_t h, uint8_t s)
|
||
{
|
||
cmd.itemArgType=ST_HS;
|
||
param.h=h;
|
||
param.s=s;
|
||
|
||
return *this;
|
||
}
|
||
|
||
|
||
itemCmd itemCmd::RGB(uint8_t r, uint8_t g, uint8_t b)
|
||
{
|
||
cmd.itemArgType=ST_RGB;
|
||
param.r=r;
|
||
param.g=g;
|
||
param.b=b;
|
||
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::RGBW(uint8_t r, uint8_t g, uint8_t b, uint8_t w)
|
||
{
|
||
cmd.itemArgType=ST_RGBW;
|
||
param.r=r;
|
||
param.g=g;
|
||
param.b=b;
|
||
param.w=w;
|
||
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::Str(char * str)
|
||
{
|
||
cmd.itemArgType=ST_STRING;
|
||
param.asString = str;
|
||
return *this;
|
||
}
|
||
|
||
|
||
itemCmd itemCmd::Cmd(uint8_t i)
|
||
{
|
||
cmd.cmdCode=i;
|
||
return *this;
|
||
}
|
||
|
||
itemCmd itemCmd::Cmd(itemCmd i)
|
||
{
|
||
cmd.cmdCode=i.cmd.cmdCode;
|
||
return *this;
|
||
}
|
||
|
||
uint8_t itemCmd::getSuffix()
|
||
{
|
||
return cmd.suffixCode;
|
||
}
|
||
|
||
itemCmd itemCmd::setSuffix(uint8_t suffix)
|
||
{
|
||
cmd.suffixCode=suffix;
|
||
return *this;
|
||
}
|
||
|
||
bool itemCmd::loadItem(Item * item, uint16_t optionsFlag)
|
||
{
|
||
bool res = false;
|
||
|
||
if (item && item->isValid())
|
||
{
|
||
short subtype =item->getSubtype();
|
||
if (optionsFlag & FLAG_COMMAND) cmd.cmdCode = item->getCmd();
|
||
|
||
//if (optionsFlag & FLAG_FLAGS)
|
||
// if (item->getFlag(FLAG_DISABLED))
|
||
// cmd.cmdCode = CMD_DISABLE;
|
||
|
||
if (subtype)
|
||
{
|
||
cmd.itemArgType= subtype;
|
||
if (optionsFlag & FLAG_PARAMETERS) param.asInt32 = item->itemVal->valueint;
|
||
//debugSerial<<F("Loaded :");
|
||
//debugOut();
|
||
return true;
|
||
}
|
||
|
||
if (optionsFlag & FLAG_PARAMETERS)
|
||
switch (item->itemVal->type)
|
||
{
|
||
case aJson_Int:
|
||
|
||
Int(item->itemVal->valueint);
|
||
//debugSerial<<F("Loaded Int:");
|
||
//debugOut();
|
||
return true;
|
||
|
||
case aJson_Float:
|
||
Float(item->itemVal->valuefloat);
|
||
//debugSerial<<F("Loaded Float:");
|
||
//debugOut();
|
||
return true;
|
||
}
|
||
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
bool itemCmd::loadItemDef(Item * item, uint16_t optionsFlag)
|
||
{
|
||
//Restrieve previous channel state to "stored"
|
||
//if no values - set default values, save and put to MQTT
|
||
if (!loadItem(item,optionsFlag))
|
||
{
|
||
debugSerial<<F("No stored values - default: ");
|
||
setChanType(item->getChanType());
|
||
setDefault();
|
||
saveItem(item);
|
||
debugOut();
|
||
item->SendStatus(FLAG_PARAMETERS | FLAG_SEND_DEFFERED);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
|
||
{
|
||
if (item && item->isValid())
|
||
{
|
||
|
||
if (optionsFlag & FLAG_FLAGS)
|
||
switch (cmd.cmdCode)
|
||
{
|
||
case CMD_DISABLE:
|
||
item->setFlag(FLAG_DISABLED);
|
||
break;
|
||
|
||
case CMD_ENABLE:
|
||
item->clearFlag(FLAG_DISABLED);
|
||
//? item->clearFlag(FLAG_FREEZED); //?
|
||
break;
|
||
case CMD_FREEZE:
|
||
item->setFlag(FLAG_FREEZED);
|
||
break;
|
||
|
||
case CMD_UNFREEZE:
|
||
item->clearFlag(FLAG_FREEZED);
|
||
break;
|
||
}
|
||
if (optionsFlag & FLAG_COMMAND)
|
||
switch (cmd.cmdCode)
|
||
{
|
||
case CMD_DISABLE:
|
||
case CMD_ENABLE:
|
||
case CMD_FREEZE:
|
||
case CMD_UNFREEZE:
|
||
case CMD_RESET:
|
||
break;
|
||
default:
|
||
item->setCmd(cmd.cmdCode);
|
||
|
||
}
|
||
if (optionsFlag & FLAG_PARAMETERS)
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_FLOAT:
|
||
case ST_FLOAT_CELSIUS:
|
||
item->setFloatVal(param.asfloat);
|
||
//
|
||
break;
|
||
|
||
case ST_INT32:
|
||
case ST_UINT32:
|
||
item->setVal(param.asInt32);
|
||
break;
|
||
|
||
default:
|
||
//item->setSubtype(cmd.itemArgType);
|
||
item->setVal(param.asInt32);
|
||
item->setSubtype(cmd.itemArgType);
|
||
}
|
||
//debugSerial<<F("Saved:");
|
||
//debugOut();
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
int replaceCmdToInt(aJsonObject* verb)
|
||
{
|
||
if (verb && verb->type == aJson_String)
|
||
{
|
||
int cmd = txt2cmd(verb->valuestring);
|
||
if (cmd>0)
|
||
{
|
||
freeString(verb->valuestring);
|
||
verb->valueint=cmd;
|
||
verb->type=aJson_Int;
|
||
return verb->valueint;
|
||
}
|
||
} else if (verb && verb->type == aJson_Int) return verb->valueint;
|
||
return 0;
|
||
}
|
||
|
||
int replaceTypeToInt(aJsonObject* verb)
|
||
{
|
||
if (!verb) return -1;
|
||
switch (verb->type)
|
||
{
|
||
case aJson_Int: return verb->valueint;
|
||
case aJson_Array: return replaceTypeToInt(verb->child);
|
||
case aJson_Object: return replaceTypeToInt(aJson.getObjectItem(verb, "type"));
|
||
case aJson_String:
|
||
{
|
||
int type = type2num(verb->valuestring);
|
||
if (type>=0)
|
||
{
|
||
freeString(verb->valuestring);
|
||
verb->valueint=type;
|
||
verb->type=aJson_Int;
|
||
return verb->valueint;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
// Mapping from unified itemCmd object to some specific device-depended value
|
||
itemCmd itemCmd::doMapping(aJsonObject *mappingData)
|
||
{
|
||
if (!mappingData) return *this;
|
||
aJsonObject *cmdMapping = aJson.getObjectItem(mappingData, "cmd");
|
||
aJsonObject *matchedCmd = NULL;
|
||
|
||
if (isCommand() && cmdMapping)
|
||
switch (cmdMapping->type)
|
||
{
|
||
case aJson_Array:
|
||
{
|
||
traceSerial<<"Array mapping"<<endl;
|
||
aJsonObject *i = cmdMapping->child;
|
||
//if first array element is not array - this is default mapping value
|
||
if (i && i->type==aJson_Int)
|
||
{
|
||
matchedCmd = i;
|
||
i=i->next;
|
||
}
|
||
|
||
while (i)
|
||
{
|
||
if (i->type == aJson_Array && aJson.getArraySize(i) == 2)
|
||
{
|
||
int cmdFrom = replaceCmdToInt(aJson.getArrayItem(i,0));
|
||
aJsonObject *to = aJson.getArrayItem(i,1);
|
||
if (getCmd()==cmdFrom && to->type == aJson_Int)
|
||
{
|
||
matchedCmd=to;
|
||
break;
|
||
}
|
||
|
||
}
|
||
i=i->next;
|
||
}
|
||
}
|
||
break;
|
||
case aJson_String:
|
||
if (strcmp(cmdMapping->valuestring,"fan")==0)
|
||
switch (getCmd())
|
||
{
|
||
/*
|
||
case CMD_AUTO:
|
||
case CMD_ON:
|
||
return itemCmd().Int((uint32_t)3);
|
||
case CMD_FAN:
|
||
return itemCmd().Int((uint32_t)1);
|
||
case CMD_HEAT:
|
||
return itemCmd().Int((uint32_t)2);
|
||
*/
|
||
case CMD_OFF:
|
||
return itemCmd().Int(0);
|
||
case CMD_LOW:
|
||
return itemCmd().Int(20);
|
||
case CMD_MED:
|
||
return itemCmd().Int(128);
|
||
case CMD_HIGH:
|
||
return itemCmd().Int(255);
|
||
|
||
default:
|
||
return *this;
|
||
}
|
||
|
||
} //switch
|
||
|
||
if (matchedCmd && matchedCmd->type != aJson_NULL)
|
||
{
|
||
traceSerial<<F("MAP: cmd mapped to ")<<matchedCmd->valueint<<endl;
|
||
return itemCmd().Int(matchedCmd->valueint);
|
||
}
|
||
|
||
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
|
||
if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) >= 4)
|
||
{ //ПРЯМОЕ
|
||
//"val":[0-вход_мин, 1-вход_макс, 2-выход_мин, 3-выход_макс, 4-вход<мин_прямое, 5-вых<мин_обратное, 6-вход>макс_прямое, 7-вых>макс_обратное]
|
||
aJsonObject *leftBoundObj = aJson.getArrayItem(valMapping,4);
|
||
aJsonObject *rightBoundObj = aJson.getArrayItem(valMapping,6);
|
||
|
||
//if (getInt()<aJson.getArrayItem(valMapping,0)->valueint) return itemCmd().Int((uint32_t) 0); было если меньше левой границы то ноль. Неперь для такого поведения надо пятым элементом явно поставить ноль
|
||
|
||
if (getInt()<aJson.getArrayItem(valMapping,0)->valueint)
|
||
{
|
||
traceSerial<<F("MAP: value ")<<getInt()<<F(" is below left bound ")<<aJson.getArrayItem(valMapping,0)->valueint<<endl;
|
||
if (leftBoundObj && leftBoundObj->type == aJson_Int )
|
||
return itemCmd().Int(leftBoundObj->valueint);
|
||
else return itemCmd(ST_VOID,CMD_VOID);
|
||
}
|
||
|
||
if (getInt()>aJson.getArrayItem(valMapping,1)->valueint)
|
||
{
|
||
traceSerial<<F("MAP: value above right bound ")<<endl;
|
||
if (rightBoundObj && rightBoundObj->type == aJson_Int )
|
||
return itemCmd().Int(rightBoundObj->valueint);
|
||
else return itemCmd(ST_VOID,CMD_VOID);
|
||
}
|
||
long res = map(getInt(),
|
||
aJson.getArrayItem(valMapping,0)->valueint,aJson.getArrayItem(valMapping,1)->valueint,
|
||
aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint);
|
||
traceSerial<<F("MAP: val mapped to ")<<res<<endl;
|
||
return itemCmd().Int(res);
|
||
|
||
}
|
||
else if (valMapping && valMapping->type == aJson_NULL) return itemCmd(ST_VOID,CMD_VOID);
|
||
return *this;
|
||
}
|
||
|
||
// Mapping from some device specific value back to unified itemcmd
|
||
itemCmd itemCmd::doReverseMapping (aJsonObject *mappingData)
|
||
{
|
||
if (!mappingData) return *this;
|
||
aJsonObject *cmdMapping = aJson.getObjectItem(mappingData, "cmd");
|
||
aJsonObject *matchedCmd = NULL;
|
||
|
||
if (cmdMapping)
|
||
|
||
switch (cmdMapping->type )
|
||
{
|
||
case aJson_Array:
|
||
{
|
||
aJsonObject *i = cmdMapping->child;
|
||
//if first array element is not array - this is default mapping value, no reverse mapping, skipping
|
||
if (i && i->type==aJson_Int)
|
||
{
|
||
//matchedCmd = i;
|
||
i=i->next;
|
||
}
|
||
|
||
while (i)
|
||
{
|
||
if (i->type == aJson_Array && aJson.getArraySize(i) == 2)
|
||
{
|
||
aJsonObject *from =aJson.getArrayItem(i,0);
|
||
int cmdFrom = replaceCmdToInt(from);
|
||
aJsonObject *to = aJson.getArrayItem(i,1);
|
||
if (to->type == aJson_Int && getInt()==to->valueint)
|
||
{
|
||
matchedCmd=from;
|
||
break;
|
||
}
|
||
|
||
}
|
||
i=i->next;
|
||
}
|
||
}
|
||
break;
|
||
case aJson_String:
|
||
{
|
||
if (strcmp(cmdMapping->valuestring,"fan")==0)
|
||
{
|
||
if (getInt())
|
||
switch (constrain(map(getInt(),0,255,1,3),1,3))
|
||
{
|
||
case 1:
|
||
return itemCmd().setSuffix(S_FAN).Cmd(CMD_LOW);
|
||
case 2:
|
||
return itemCmd().setSuffix(S_FAN).Cmd(CMD_MED);
|
||
case 3:
|
||
return itemCmd().setSuffix(S_FAN).Cmd(CMD_HIGH);
|
||
}
|
||
else return itemCmd().setSuffix(S_FAN).Cmd(CMD_OFF);
|
||
}
|
||
}
|
||
}//switch
|
||
|
||
|
||
if (matchedCmd) return itemCmd().Cmd(matchedCmd->valueint);
|
||
|
||
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
|
||
if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) >= 4)
|
||
{
|
||
//ОБРАТНОЕ
|
||
//"val":[0-вход_мин, 1-вход_макс, 2-выход_мин, 3-выход_макс, 4-вход<мин_прямое, 5-вых<мин_обратное, 6-вход>макс_прямое, 7-вых>макс_обратное]
|
||
int a = aJson.getArrayItem(valMapping,0)->valueint;
|
||
int b = aJson.getArrayItem(valMapping,1)->valueint;
|
||
int c = aJson.getArrayItem(valMapping,2)->valueint;
|
||
int d = aJson.getArrayItem(valMapping,3)->valueint;
|
||
|
||
aJsonObject *leftBoundObj = aJson.getArrayItem(valMapping,5);
|
||
aJsonObject *rightBoundObj = aJson.getArrayItem(valMapping,7);
|
||
// Dev to unified
|
||
//было если меньше левой границы то ноль. Неперь для такого поведения надо 7m элементом явно поставить ноль
|
||
//if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
|
||
|
||
|
||
if (getInt()<aJson.getArrayItem(valMapping,2)->valueint)
|
||
{
|
||
if (leftBoundObj && leftBoundObj->type == aJson_Int )
|
||
return itemCmd().Int(leftBoundObj->valueint);
|
||
else return itemCmd(ST_VOID,CMD_VOID);
|
||
}
|
||
|
||
if (getInt()>aJson.getArrayItem(valMapping,3)->valueint)
|
||
{
|
||
if (rightBoundObj && rightBoundObj->type == aJson_Int )
|
||
return itemCmd().Int(rightBoundObj->valueint);
|
||
else return itemCmd(ST_VOID,CMD_VOID);
|
||
}
|
||
|
||
int diff = ((b-a)/(d-c))/2;
|
||
//return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
|
||
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,b));
|
||
//return itemCmd().Int((uint32_t) map(getInt(),c,d,a,b)+diff);
|
||
}
|
||
if (valMapping && valMapping->type == aJson_NULL) return itemCmd();
|
||
return *this;
|
||
}
|
||
|
||
|
||
char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100 )
|
||
{
|
||
|
||
if (!Buffer || !bufLen) return NULL;
|
||
*Buffer=0;
|
||
char * argPtr=Buffer;
|
||
if (isCommand() && (sendFlags & FLAG_COMMAND) && cmd.cmdCode<commandsNum)
|
||
{
|
||
int len;
|
||
strncpy_P(Buffer, commands_P[cmd.cmdCode], bufLen);
|
||
if (isValue() && (sendFlags & FLAG_PARAMETERS)) strncat(Buffer, " ", bufLen);
|
||
len=strlen(Buffer);
|
||
argPtr+=len;
|
||
bufLen-=len;
|
||
bufLen--;
|
||
}
|
||
if (isValue() && (sendFlags & FLAG_PARAMETERS))
|
||
{
|
||
//strncat(Buffer, " ", bufLen);
|
||
//bufLen--;
|
||
//argPtr++;
|
||
|
||
switch (cmd.itemArgType)
|
||
{ short colorTemp;
|
||
|
||
case ST_PERCENTS255:
|
||
snprintf(argPtr, bufLen, "%u", (scale100)?map (param.v,0,255,0,100):param.v);
|
||
break;
|
||
case ST_UINT32:
|
||
snprintf(argPtr, bufLen, "%lu", param.asUint32);
|
||
break;
|
||
case ST_INT32:
|
||
snprintf(argPtr, bufLen, "%ld", param.asInt32);
|
||
break;
|
||
case ST_TENS:
|
||
if (param.asInt32<0)
|
||
snprintf(argPtr, bufLen, "-%ld.%0"QUOTE(TENS_FRACT_LEN)"d", abs(param.asInt32)/TENS_BASE, abs(param.asInt32 % TENS_BASE));
|
||
else
|
||
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();
|
||
|
||
if (colorTemp<0 || scale100)
|
||
snprintf(argPtr, bufLen, "%d,%d,%d", param.h, param.s, (scale100)?map (param.v,0,255,0,100):param.v);
|
||
else
|
||
snprintf(argPtr, bufLen, "%d,%d,%d,%d", param.h, param.s, (scale100)?map (param.v,0,255,0,100):param.v, colorTemp);
|
||
|
||
break;
|
||
case ST_HS:
|
||
snprintf(argPtr, bufLen, "%d,%d", param.h, param.s);
|
||
|
||
break;
|
||
case ST_FLOAT_CELSIUS:
|
||
case ST_FLOAT_FARENHEIT:
|
||
case ST_FLOAT:
|
||
{
|
||
|
||
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 * 1000); // Turn into integer
|
||
// Print as parts, note that you need 0-padding for fractional bit.
|
||
|
||
if (param.asfloat < 0)
|
||
snprintf (argPtr, bufLen, "-%d.%03d", tmpInt1, tmpInt2);
|
||
else snprintf (argPtr, bufLen, "%d.%03d", tmpInt1, tmpInt2);
|
||
}
|
||
break;
|
||
case ST_RGB:
|
||
snprintf(argPtr, bufLen, "%d,%d,%d", param.r, param.g, param.b);
|
||
break;
|
||
|
||
case ST_RGBW:
|
||
snprintf(argPtr, bufLen, "%d,%d,%d,%d", param.r, param.g, param.b,param.w);
|
||
break;
|
||
|
||
case ST_STRING:
|
||
strncpy(argPtr, param.asString,bufLen);
|
||
|
||
break;
|
||
default:
|
||
;
|
||
}
|
||
}
|
||
return Buffer;
|
||
}
|
||
|
||
void itemCmd::debugOut()
|
||
{
|
||
char buf[32];
|
||
toString(buf,sizeof(buf));
|
||
debugSerial<<buf<<F(" AT:")<<getArgType()<<F(" Suff:")<<getSuffix()<<endl;
|
||
}
|
||
|
||
bool itemCmd::scale100()
|
||
{
|
||
switch (cmd.itemArgType)
|
||
{
|
||
case ST_PERCENTS255:
|
||
case ST_HSV255:
|
||
param.v=constrain(map(param.v,0,100,0,255),0,255);
|
||
return true;
|
||
}
|
||
return false;
|
||
} |