pins protection,core fixes for grp ch stat& sched

This commit is contained in:
Климов Андрей Николаевич
2023-10-25 00:28:26 +03:00
parent 1e58ad90eb
commit 45d925ba88
13 changed files with 126 additions and 66 deletions

View File

@@ -60,7 +60,7 @@ toExecute = true;
case S_SET:
//case S_ESET:
case S_HSV:
PixelCtrl(cmd, subItem, toExecute);
PixelCtrl(cmd, subItem, toExecute, authorized);
return 1;
case S_CMD:
//item->setCmd(cmd.getCmd());
@@ -74,13 +74,13 @@ case S_CMD:
cmd.saveItem(item);
item->SendStatus(FLAG_PARAMETERS | FLAG_SEND_DEFFERED);
};
PixelCtrl(cmd,subItem, true);
PixelCtrl(cmd,subItem, true, authorized);
// item->SendStatus(FLAG_COMMAND | FLAG_PARAMETERS );
return 1;
case CMD_OFF:
cmd.param.asInt32=0;
PixelCtrl(cmd, subItem, true);
PixelCtrl(cmd, subItem, true,authorized);
// item->SendStatus(FLAG_COMMAND);
return 1;

View File

@@ -16,7 +16,7 @@ public:
};
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized=false) override;
int getDefaultStorageType()override;
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true ) =0;
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) =0;
short getChannelAddr(short n =0);
// int isActive() override;
protected:

View File

@@ -598,14 +598,12 @@ if (suffixCode == S_RAW)
ic.setSuffix(suffixCode);
return Ctrl(ic,subItem);
}
//debugSerial<<F("SuffixCode: ")<<suffixCode<<endl;
bool authorized = false;
char * authPos = strchr(payload,'@');
if (authPos)
{
*authPos=0;
//char * authToken=payload;
authorized = checkToken(payload,authPos+1);
payload=authPos+1;
}
@@ -614,7 +612,6 @@ int i=0;
while (payload[i]) {payload[i]=toupper(payload[i]);i++;};
int cmd = txt2cmd(payload);
//debugSerial<<F("Txt2Cmd:")<<cmd<<endl;
itemCmd st(ST_VOID,cmd);
@@ -770,30 +767,50 @@ aJsonObject *timestampObj = aJson.getArrayItem(itemArr, I_TIMESTAMP);
return 0;
}
int Item::scheduleOppositeCommand(itemCmd cmd,bool authorized)
int Item::scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized)
{
itemCmd nextCmd=cmd;
switch (cmd.getCmd()){
case CMD_XON: nextCmd.Cmd(CMD_XOFF);
case CMD_XON:
if (isActiveNow && !isScheduled()) return 0;
nextCmd.Cmd(CMD_XOFF);
break;
case CMD_XOFF: nextCmd.Cmd(CMD_XON);
case CMD_XOFF:
if (!isActiveNow && !isScheduled()) return 0;
nextCmd.Cmd(CMD_XON);
break;
case CMD_ON: nextCmd.Cmd(CMD_OFF);
case CMD_ON:
if (isActiveNow && !isScheduled()) return 0;
nextCmd.Cmd(CMD_OFF);
break;
case CMD_OFF: nextCmd.Cmd(CMD_ON);
case CMD_OFF:
if (!isActiveNow && !isScheduled()) return 0;
nextCmd.Cmd(CMD_ON);
break;
case CMD_ENABLE: nextCmd.Cmd(CMD_DISABLE);
case CMD_ENABLE:
if (!getFlag(FLAG_DISABLED) && !isScheduled()) return 0;
nextCmd.Cmd(CMD_DISABLE);
break;
case CMD_DISABLE: nextCmd.Cmd(CMD_ENABLE);
case CMD_DISABLE:
if (getFlag(FLAG_DISABLED) && !isScheduled()) return 0;
nextCmd.Cmd(CMD_ENABLE);
break;
case CMD_FREEZE: nextCmd.Cmd(CMD_UNFREEZE);
case CMD_FREEZE:
if (getFlag(FLAG_FREEZED) && !isScheduled()) return 0;
nextCmd.Cmd(CMD_UNFREEZE);
break;
case CMD_UNFREEZE: nextCmd.Cmd(CMD_FREEZE);
case CMD_UNFREEZE:
if (!getFlag(FLAG_FREEZED) && !isScheduled()) return 0;
nextCmd.Cmd(CMD_FREEZE);
break;
case CMD_HALT: nextCmd.Cmd(CMD_RESTORE);
case CMD_HALT:
if (!isActiveNow && !isScheduled()) return 0;
nextCmd.Cmd(CMD_RESTORE);
break;
case CMD_RESTORE: nextCmd.Cmd(CMD_HALT);
case CMD_RESTORE:
if (isActiveNow && !isScheduled()) return 0;
nextCmd.Cmd(CMD_HALT);
break;
case CMD_TOGGLE: nextCmd.Cmd(CMD_TOGGLE);
break;
@@ -1033,6 +1050,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
}
if (itemType==CH_GROUP)
{
bool scheduledOppositeCommand = false;
if (fr<350)
{
errorSerial<<F("CTRL: Not enough memory for group operation")<<endl;
@@ -1042,16 +1060,23 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
{
chActive=(isActive()>0);
digGroup(itemArg,&cmd,subItem,authorized);
if ((suffixCode==S_CMD) && cmd.isValue())
{
scheduleOppositeCommand(cmd,chActive,authorized);
scheduledOppositeCommand = true;
}
}
res=1;
// Post-processing of group command - converting HALT,REST,XON,XOFF to conventional ON/OFF for status
switch (cmd.getCmd()) {
int t;
case CMD_RESTORE: // individual for group members
switch (t = getCmd()) {
case CMD_HALT: //previous command was HALT ?
if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
///if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
debugSerial << F("CTRL: Restored from:") << t << endl;
cmd.loadItemDef(this);
cmd.Cmd(CMD_ON); //turning on
@@ -1065,7 +1090,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
case CMD_XOFF: // individual for group members
switch (t = getCmd()) {
case CMD_XON: //previous command was CMD_XON ?
if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
///if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
debugSerial << F("CTRL: Turned off from:") << t << endl;
cmd.Cmd(CMD_OFF); //turning Off
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
@@ -1082,7 +1107,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
{
if (chActive == -1) chActive=(isActive()>0);
if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
///if ((suffixCode==S_CMD) && cmd.isValue() && (!chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
if (!chActive) //if channel was'nt active before CMD_XON
@@ -1109,7 +1134,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
break;
case CMD_HALT:
if (chActive == -1) chActive=(isActive()>0);
if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
///if ((suffixCode==S_CMD) && cmd.isValue() && (chActive || isScheduled())) scheduleOppositeCommand(cmd,authorized);
if (chActive) //if channel was active before CMD_HALT /// HERE bug - if cmd == On but 0 = active
{
cmd.Cmd(CMD_OFF);
@@ -1126,7 +1151,12 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
status2Send |= FLAG_SEND_IMMEDIATE;
if (cmd.isChannelCommand()) status2Send |= FLAG_COMMAND;
if (cmd.isValue() || cmd.loadItem(this,FLAG_PARAMETERS)) status2Send |= FLAG_PARAMETERS; ;
if (cmd.isValue() || cmd.loadItem(this,FLAG_PARAMETERS)) status2Send |= FLAG_PARAMETERS;
if (scheduledOppositeCommand) status2Send &=~FLAG_PARAMETERS;
// UPDATE internal variables for GROUP
if (status2Send) cmd.saveItem(this,status2Send);
} // end GROUP
else
@@ -1156,7 +1186,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
///// return 0;
}
}
bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && allowRecursion && cmd.isValue();
// Commands for NON GROUP
//threating Restore, XOFF (special conditional commands)/ convert to ON, OFF and SET values
switch (cmd.getCmd()) {
@@ -1164,8 +1194,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
case CMD_RESTORE: // individual for group members
switch (t = getCmd()) {
case CMD_HALT: //previous command was HALT ?
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
// if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
debugSerial << F("CTRL: Restored from:") << t << endl;
cmd.loadItemDef(this);
@@ -1182,8 +1212,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
case CMD_XOFF: // individual for group members
switch (t = getCmd()) {
case CMD_XON: //previous command was CMD_XON ?
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
debugSerial << F("CTRL: Turned off from:") << t << endl;
toExecute=true;
cmd.Cmd(CMD_OFF); //turning Off
@@ -1199,8 +1229,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
case CMD_XON:
if (!getFlag(FLAG_DISABLED))
{
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
if (!chActive) //if channel was'nt active before CMD_XON
{
@@ -1226,8 +1256,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
break;
case CMD_HALT:
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
if (chActive) //if channel was active before CMD_HALT
{
cmd.Cmd(CMD_OFF);
@@ -1251,16 +1281,16 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
if (getCmd() == CMD_HALT) return 3; //Halted, ignore OFF
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
status2Send |= FLAG_COMMAND | FLAG_SEND_IMMEDIATE;
toExecute=true;
break;
case CMD_ON:
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!chActive || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
if (!cmd.isChannelCommand()) //Command for driver, not for whole channel
{
@@ -1302,8 +1332,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
status2Send |= FLAG_FLAGS;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if (allowRecursion && cmd.isValue() && (getFlag(FLAG_DISABLED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if (allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
break;
case CMD_DISABLE:
@@ -1311,8 +1341,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
status2Send |= FLAG_FLAGS;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!getFlag(FLAG_DISABLED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
break;
case CMD_UNFREEZE:
@@ -1320,8 +1350,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
status2Send = FLAG_FLAGS;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (getFlag(FLAG_FREEZED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
break;
case CMD_FREEZE:
@@ -1330,8 +1360,8 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
command2Set = 0;
toExecute=true;
//debugSerial<<F("Disable Flag is:")<<getFlag(FLAG_DISABLED)<<endl;
if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue() && (!getFlag(FLAG_FREEZED) || isScheduled())) //invoked not as group part, delayed, non Active or re-schedule
scheduleOppositeCommand(cmd,authorized);
//if ((suffixCode==S_CMD) && allowRecursion && cmd.isValue()) //invoked not as group part, delayed, non Active or re-schedule
// scheduleOppositeCommand(cmd,chActive,authorized);
break;
default:
@@ -1339,6 +1369,12 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
if (cmd.isValue()) status2Send |= FLAG_PARAMETERS;
toExecute=true;
} //Switch commands
if (oppositeCommandToBeSchedulled) //invoked not as group part, delayed
{
scheduleOppositeCommand(cmd,chActive,authorized);
status2Send &=~FLAG_PARAMETERS;
}
} // NO GROUP
if (invalidArgument) return -4;

View File

@@ -149,7 +149,7 @@ class Item
inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));};
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
int scheduleCommand(itemCmd cmd, bool authorized);
int scheduleOppositeCommand(itemCmd cmd,bool authorized);
int scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized);
int isScheduled();
protected:

View File

@@ -1439,6 +1439,9 @@ setupSyslog();
if (cmd<1) it.setCmd(CMD_OFF);
it.setFlag(FLAG_COMMAND);
if (it.itemVal) it.setFlag(FLAG_PARAMETERS);
if (isProtectedPin(pin)) {errorSerial<<F("pin protected: ")<<pin<<endl; break;}
pinMode(pin, OUTPUT);
digitalWrite(pin, false); //Initially, all thermostates are LOW (OFF for electho heaters, open for water NO)
debugSerial<<F("Thermo:")<<pin<<F("=LOW")<<F(";");
@@ -1447,12 +1450,16 @@ setupSyslog();
{
int k;
pinMode(pin, OUTPUT);
if (isProtectedPin(pin)) digitalWrite (pin,LOW);
else
{
if (inverse)
digitalWrite(pin, k = ((cmd == CMD_ON) ? LOW : HIGH));
else
digitalWrite(pin, k = ((cmd == CMD_ON) ? HIGH : LOW));
debugSerial<<F("Pin:")<<pin<<F("=")<<k<<F(";");
}
}
break;
} //switch
} //isValid
@@ -2922,6 +2929,7 @@ enum heaterMode {HEATER_HEAT,HEATER_OFF,HEATER_ERROR};
void thermoRelay(int pin, heaterMode on)
{
int thermoPin = abs(pin);
if(isProtectedPin(thermoPin)) {errorSerial<<F("pin disabled ")<<thermoPin<<endl;return;}
pinMode(thermoPin, OUTPUT);
if (on == HEATER_ERROR)

View File

@@ -51,7 +51,7 @@ int out_dmx::getChanType()
return 0;
}
int out_dmx::PixelCtrl(itemCmd cmd, char* subItem, bool show)
int out_dmx::PixelCtrl(itemCmd cmd, char* subItem, bool show, bool authorized)
//int out_dmx::PixelCtrl(itemCmd cmd)
{
if (!item || !show) return 0;

View File

@@ -18,7 +18,7 @@ public:
int getChanType() override;
// int Ctrl(itemCmd cmd, char* subItem=NULL) override;
// int PixelCtrl(itemCmd cmd) override;
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true) override;
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false) override;
protected:
};

View File

@@ -51,6 +51,7 @@ int out_Motor::Setup()
abstractOut::Setup();
getConfig();
debugSerial.println("Motor: Init");
if (isProtectedPin(pinUp)||isProtectedPin(pinDown)) {errorSerial<<F("pin disabled")<<endl;return 0;}
pinMode(pinUp,OUTPUT);
pinMode(pinDown,OUTPUT);
@@ -71,11 +72,13 @@ return 1;
int out_Motor::Stop()
{
debugSerial.println("Motor: De-Init");
item->setExt(0);
driverStatus = CST_UNKNOWN;
if (isProtectedPin(pinUp)||isProtectedPin(pinDown)) {errorSerial<<F("pin disabled")<<endl;return 0;}
digitalWrite(pinUp,INACTIVE);
digitalWrite(pinDown,INACTIVE);
item->setExt(0);
driverStatus = CST_UNKNOWN;
return 1;
}
@@ -117,6 +120,8 @@ if (!item->getFlag(FLAG_ACTION_IN_PROCESS))
else return 0;
}
if (isProtectedPin(pinUp)||isProtectedPin(pinDown)) {return 0;}
uint32_t motorOfftime = item->getExt();
itemCmd st;
st.loadItem(item);

View File

@@ -112,7 +112,7 @@ int out_pwm::getChanType()
return 0;
}
int out_pwm::PixelCtrl(itemCmd cmd, char* subItem, bool show)
int out_pwm::PixelCtrl(itemCmd cmd, char* subItem, bool show, bool authorized)
{
if (!item || !iaddr || !show) return 0;
@@ -132,6 +132,7 @@ switch (cmd.getCmd()){
{
case CH_PWM:
{ short k;
if (authorized || !isProtectedPin(iaddr))
analogWrite(iaddr, k=cmd.getPercents255(inverse));
debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<endl;
return 1;
@@ -151,13 +152,20 @@ itemCmd st(storageType,CMD_VOID);
st.assignFrom(cmd);
switch (cType)
{
{ short pin;
case CH_RGBW:
analogWrite(getChannelAddr(3), st.param.w);
pin=getChannelAddr(3);
if (authorized || !isProtectedPin(pin)) analogWrite(pin, st.param.w);
case CH_RGB:
analogWrite(iaddr, st.param.r);
analogWrite(getChannelAddr(1), st.param.g);
analogWrite(getChannelAddr(2), st.param.b);
if (authorized || !isProtectedPin(iaddr)) analogWrite(iaddr, st.param.r);
pin=getChannelAddr(1);
if (authorized || !isProtectedPin(pin)) analogWrite(pin, st.param.g);
pin=getChannelAddr(2);
if (authorized || !isProtectedPin(pin)) analogWrite(pin, st.param.b);
break;
default: ;
}

View File

@@ -17,7 +17,7 @@ public:
int getChanType() override;
//int Ctrl(itemCmd cmd, char* subItem=NULL) override;
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true ) override;
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) override;
protected:
short numChannels;

View File

@@ -37,7 +37,7 @@ int out_relay::Setup()
abstractOut::Setup();
debugSerial<<F("Relay-Out #")<<pin<<F(" init")<<endl;
if (isProtectedPin(pin)) {errorSerial<<F("pin disabled")<<endl;return 0;}
pinMode(pin, OUTPUT);
digitalWrite(pin,INACTIVE);
if (item) item->setExt(0);
@@ -148,6 +148,9 @@ int out_relay::Ctrl(itemCmd cmd, char* subItem, bool toExecute,bool authorized)
debugSerial<<F("relayCtr: ");
cmd.debugOut();
if ((subItem && !strcmp_P(subItem,action_P)) || !item) return 0;
if (isProtectedPin(pin)) {return 0;}
int suffixCode;
if (cmd.isCommand()) suffixCode = S_CMD;
else suffixCode = cmd.getSuffix();

View File

@@ -98,7 +98,7 @@ int out_SPILed::getChanType()
return CH_RGBW;
}
int out_SPILed::PixelCtrl(itemCmd cmd, char* subItem, bool show )
int out_SPILed::PixelCtrl(itemCmd cmd, char* subItem, bool show, bool authorized )
//int out_SPILed::PixelCtrl(itemCmd cmd, int from, int to, bool show)
{

View File

@@ -22,7 +22,7 @@ public:
int getChanType() override;
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override;
//int Ctrl(itemCmd cmd, char* subItem=NULL) override;
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true ) override;
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) override;
//int PixelCtrl(itemCmd cmd, int from =0 , int to = 1024, bool show = 1) override;
int numLeds;
int8_t pin;