Files
lighthub/item.cpp
2017-10-02 14:13:45 +03:00

554 lines
14 KiB
C++

#include "item.h"
#include "aJSON.h"
#include <DmxSimple.h>
#include "FastLED.h"
#include <ModbusMaster.h>
#include <PubSubClient2.h>
extern int modbusSet(int addr, uint16_t _reg, int _mask, uint16_t value);
extern PubSubClient client;
//extern const char* outprefix;
const char outprefix[] PROGMEM = "/myhome/s_out/";
static unsigned long lastctrl = 0;
static aJsonObject * lastobj = NULL;
int txt2cmd (char * payload)
{
int cmd=0;
// Check for command
if (strcmp(payload,"ON")==0) cmd=CMD_ON;
else if (strcmp(payload,"OFF")==0) cmd=CMD_OFF;
else if (strcmp(payload,"REST")==0) cmd=CMD_RESTORE;
else if (strcmp(payload,"TOGGLE")==0) cmd=CMD_TOGGLE;
else if (strcmp(payload,"HALT")==0) cmd=CMD_HALT;
return cmd;
}
Item::Item(char * name) //Constructor
{
if (name)
itemArr= aJson.getObjectItem(items, name);
else itemArr=NULL;
if (isValid())
{
// Todo - avoid static enlarge for every types
for (int i=aJson.getArraySize(itemArr);i<4;i++) aJson.addItemToArray(itemArr,aJson.createItem(int(0))); //Enlarge item to 4 elements. VAL=int if no other definition in conf
itemType = aJson.getArrayItem(itemArr,I_TYPE)->valueint;
itemArg = aJson.getArrayItem(itemArr,I_ARG);
itemVal = aJson.getArrayItem(itemArr,I_VAL);
Serial.print(F(" Item:"));
Serial.println(name);
Serial.print(itemType);Serial.print(":");Serial.println(getArg());
}
}
uint8_t Item::getCmd()
{
aJsonObject *t = aJson.getArrayItem(itemArr,I_CMD);
if (t)
return t->valueint;
else return -1;
}
void Item::setCmd(uint8_t cmd)
{
aJsonObject *t = aJson.getArrayItem(itemArr,I_CMD);
if (t)
t->valueint=cmd;
}
int Item::getArg() //Return arg int or first array element if Arg is array
{ if (!itemArg) return -1;
if (itemArg->type==aJson_Int) return itemArg->valueint;
else if (itemArg->type==aJson_Array) return aJson.getArrayItem(itemArg,0)->valueint;
else return -2;
}
/*
int Item::getVal(short n) //Return Val from Value array
{ if (!itemVal) return -1;
else if (itemVal->type==aJson_Array)
{
aJsonObject *t = aJson.getArrayItem(itemVal,n);
if (t) return t->valueint;
else return -3;
}
else return -2;
}
*/
long int Item::getVal() //Return Val if val is int or first elem of Value array
{ if (!itemVal) return -1;
if (itemVal->type==aJson_Int) return itemVal->valueint;
else if (itemVal->type==aJson_Array)
{
aJsonObject *t = aJson.getArrayItem(itemVal,0);
if (t) return t->valueint;
else return -3;
}
else return -2;
}
/*
void Item::setVal(short n, int par) // Only store if VAL is array defined in config to avoid waste of RAM
{
if (!itemVal || itemVal->type!=aJson_Array) return;
Serial.print(F(" Store p="));Serial.print(n);Serial.print(F(" Val="));Serial.println(par);
for (int i=aJson.getArraySize(itemVal);i<=n;i++) aJson.addItemToArray(itemVal,aJson.createItem(int(0))); //Enlarge array of Values
aJsonObject *t = aJson.getArrayItem(itemVal,n);
if (t) t->valueint=par;
}
*/
void Item::setVal(long int par) // Only store if VAL is int (autogenerated or config-defined)
{
if (!itemVal || itemVal->type!=aJson_Int) return;
Serial.print(F(" Store "));Serial.print(F(" Val="));Serial.println(par);
itemVal->valueint=par;
}
boolean Item::isValid ()
{
return (itemArr && (itemArr->type==aJson_Array));
}
/*
void Item::copyPar (aJsonObject *itemV)
{ int n=aJson.getArraySize(itemV);
//for (int i=aJson.getArraySize(itemVal);i<n;i++) aJson.addItemToArray(itemVal,aJson.createItem(int(0))); //Enlarge array of Values
for (int i=0;i<n;i++) setPar(i,aJson.getArrayItem(itemV,i)->valueint);
}
*/
boolean Item::getEnableCMD(int delta)
{
return ((millis()-lastctrl>(unsigned long) delta) );//|| (itemArr!=lastobj));
}
int Item::Ctrl(short cmd, short n, int * Par, boolean send)
{
Serial.print(F("Cmd="));Serial.println(cmd);
//va_list vl;
int _Par[3]={0,0,0};
if (Par==NULL) Par=_Par;
int iaddr=getArg();
HSVstore st;
//Store Parameter(s) into json VAL
switch (cmd)
{
case CMD_TOGGLE:
switch (getCmd())
{
case CMD_ON:
case CMD_SET:
cmd=CMD_OFF;
break;
case CMD_OFF:
case CMD_HALT:
cmd=CMD_ON;
break;
}//switch old cmd
break;
case CMD_RESTORE:
if (itemType!=CH_GROUP) //individual threating of channels
switch (getCmd())
{ case CMD_HALT:
// Serial.print("LastCmd:");Serial.println(t);
cmd=CMD_ON;
break;
}//switch old cmd
} //switch cmd
switch (cmd)
{
case 0: //no command
setCmd(CMD_SET);
switch (itemType)
{
case CH_GROUP:
case CH_RGBW: //only if configured VAL array
st.h=Par[0];
st.s=Par[1];
st.v=Par[2];
setVal(st.aslong);
break;
case CH_DIMMER: //Everywhere, in flat VAL
case CH_MODBUS:
case CH_THERMO:
case CH_VC:
case CH_VCTEMP:
setVal(Par[0]);
}//itemtype
lastctrl=millis(); //last controlled object ond timestamp update
lastobj =itemArr;
break;
case CMD_ON: //retrive stored values
if (getCmd()!=CMD_ON)
{
st.aslong=getVal();//Serial.print("Returned getVal: ");Serial.println(st.aslong);
if (st.aslong>=0)
{
Par[0]=st.h;
Par[1]=st.s;
Par[2]=st.v;
}
for (short i=0;i<3 ;i++)
{
Serial.print(F("Restored: "));Serial.print(i);Serial.print("=");Serial.println(Par[i]);
}
setCmd(cmd);
}
else
{ //Double ON - apply special preset
switch (itemType)
{
case CH_RGBW:
Serial.println(F("White: "));
itemType=CH_WHITE;
// Par[2]=getVal(2);
// if (Par[2]<0)
Par[2]=100;
break;
}
}
break;
case CMD_OFF:
Par[0]=0;Par[1]=0;Par[2]=0;
setCmd(cmd);
break;
case CMD_HALT:
if (getCmd()!=CMD_OFF)
{
Par[0]=0;Par[1]=0;Par[2]=0;
setCmd(cmd);
Serial.print(itemType);Serial.println(" Halted");
}
}//switch cmd
/*
Serial.print("go: ");
for (short i=0;i<3 ;i++)
{
Serial.print(i);Serial.print("=");Serial.println(Par[i]);
}
*/
if (send) SendCmd(cmd,n,Par);
switch (itemType)
{
case CH_DIMMER: //Dimmed light
DmxSimple.write(iaddr, map(Par[0],0,100,0,255));
break;
case CH_RGBW: //Colour RGBW
{
int k;
DmxSimple.write(iaddr+3, k=map((100-Par[1])*Par[2],0,10000,0,255));
Serial.print(F("W:"));Serial.println(k);
}
case CH_RGB: // RGB
{
CRGB rgb= CHSV(map(Par[0],0,365,0,255),map(Par[1],0,100,0,255),map(Par[2],0,100,0,255));
DmxSimple.write(iaddr, rgb.r);
DmxSimple.write(iaddr+1, rgb.g);
DmxSimple.write(iaddr+2, rgb.b);
break; }
case CH_WHITE:
DmxSimple.write(iaddr, 0);
DmxSimple.write(iaddr+1, 0);
DmxSimple.write(iaddr+2, 0);
DmxSimple.write(iaddr+3, map(Par[2],0,100,0,255));
break;
case CH_MODBUS:
{
if ((itemArg->type == aJson_Array) && (aJson.getArraySize(itemArg)==3))
{
int _addr= aJson.getArrayItem(itemArg,0)->valueint;
int _reg = aJson.getArrayItem(itemArg,1)->valueint;
int _mask= aJson.getArrayItem(itemArg,2)->valueint;
modbusSet(_addr,_reg,_mask,map(Par[0],0,100,0,0x1f));
}
break;}
case CH_GROUP://Group
{
//aJsonObject *groupArr= aJson.getArrayItem(itemArr, 1);
if (itemArg->type==aJson_Array)
{
aJsonObject *i =itemArg->child;
while (i)
{
Item it (i->valuestring);
// it.copyPar(itemVal);
it.Ctrl(cmd,n,Par,true);
i=i->next;
} //while
} //if
} //case
break;
case CH_RELAY:
{int k;
pinMode(iaddr,OUTPUT);
digitalWrite(iaddr,k=((cmd==CMD_ON)?HIGH:LOW));
Serial.print(F("Pin:"));Serial.print(iaddr);Serial.print(F("="));Serial.println(k);
break;
case CH_THERMO:
///thermoSet(name,cmd,Par1); all cativities done - update temp & cmd
break;
case CH_PWM:
pinMode(iaddr,OUTPUT);
//timer 0 for pin 13 and 4
//timer 1 for pin 12 and 11
//timer 2 for pin 10 and 9
//timer 3 for pin 5 and 3 and 2
//timer 4 for pin 8 and 7 and 6
//prescaler = 1 ---> PWM frequency is 31000 Hz
//prescaler = 2 ---> PWM frequency is 4000 Hz
//prescaler = 3 ---> PWM frequency is 490 Hz (default value)
//prescaler = 4 ---> PWM frequency is 120 Hz
//prescaler = 5 ---> PWM frequency is 30 Hz
//prescaler = 6 ---> PWM frequency is <20 Hz
int tval = 7; // this is 111 in binary and is used as an eraser
TCCR4B &= ~tval; // this operation (AND plus NOT), set the three bits in TCCR2B to 0
TCCR3B &= ~tval;
tval=2;
TCCR4B|=tval;
TCCR3B|=tval;
analogWrite(iaddr,k=map(Par[0],0,100,0,255));
Serial.print(F("Pin:"));Serial.print(iaddr);Serial.print(F("="));Serial.println(k);
break;
}
case CH_VC:
VacomSetFan(getArg(),Par[0]);
break;
case CH_VCTEMP:
{
Item it (itemArg->valuestring);
if (it.isValid() && it.itemType==CH_VC)
VacomSetHeat(it.getArg(),Par[0],cmd);
break;
}
} // switch itemtype
// break;
}
/*
short thermoSet(char * name, short cmd, short t)
{
if (items)
{
aJsonObject *item= aJson.getObjectItem(items, name);
if (item && (item->type==aJson_Array) && (aJson.getArrayItem(item, I_TYPE)->valueint==CH_THERMO))
{
for (int i=aJson.getArraySize(item);i<4;i++) aJson.addItemToArray(item,aJson.createItem(int(0))); //Enlarge item to 4 elements
if (!cmd) aJson.getArrayItem(item, I_VAL)->valueint=t;
aJson.getArrayItem(item, I_CMD)->valueint=cmd;
}
}
}
*/
void PooledItem::Idle()
{
if (PoolingInterval)
{
Pool();
next=millis()+PoolingInterval;
}
};
/*
addr 10d
Снять аварию 42001 (2001=7d1) =>4
[22:20:33] Write task has completed successfully
[22:20:33] <= Response: 0A 06 07 D0 00 04 89 FF
[22:20:32] => Poll: 0A 06 07 D0 00 04 89 FF
100%
2003-> 10000
[22:24:05] Write task has completed successfully
[22:24:05] <= Response: 0A 06 07 D2 27 10 33 C0
[22:24:05] => Poll: 0A 06 07 D2 27 10 33 C0
ON
2001->1
[22:24:50] Write task has completed successfully
[22:24:50] <= Response: 0A 06 07 D0 00 01 49 FC
[22:24:50] => Poll: 0A 06 07 D0 00 01 49 FC
OFF
2001->0
[22:25:35] Write task has completed successfully
[22:25:35] <= Response: 0A 06 07 D0 00 00 88 3C
[22:25:34] => Poll: 0A 06 07 D0 00 00 88 3C
POOL 2101x10
[22:27:29] <= Response: 0A 03 14 00 23 00 00 27 10 13 88 0B 9C 00 32 00 F8 00 F2 06 FA 01 3F AD D0
[22:27:29] => Poll: 0A 03 08 34 00 0A 87 18
*/
int Item::Pool()
{
}
extern short modbusBusy;
extern ModbusMaster node;
int Item::VacomSetFan (int addr, int8_t val)
{
Serial.print("VC#");Serial.print(addr);Serial.print("=");Serial.println(val);
if (modbusBusy) return -1;
modbusBusy=1;
uint8_t j, result;
uint16_t data[1];
node.begin(9600,SERIAL_8N1,13);
node.setSlave(addr);
if (val) {
node.writeSingleRegister(2001-1,4+1);//delay(500);
//node.writeSingleRegister(2001-1,1);
}
else node.writeSingleRegister(2001-1,0);
delay (500);
node.writeSingleRegister(2003-1,val*100);
/*
result = node.readHoldingRegisters(2003, 10);
// do something with data if read is successful
if (result == node.ku8MBSuccess)
{ Serial.print(F(" FM Val :"));
for (j = 0; j < 10; j++)
{
data[j] = node.getResponseBuffer(j);
Serial.print(data[j],HEX);Serial.print("-");
}
Serial.println();
} else {Serial.print(F("Modbus pooling error=")); Serial.println(result,HEX); }
*/
modbusBusy=0;
}
int Item::VacomSetHeat(int addr, int8_t val, int8_t cmd)
{
Serial.print("VC#");Serial.print(addr);Serial.print("=");Serial.print(val);Serial.print(" cmd=");Serial.println(cmd);
}
int Item::SendCmd(short cmd,short n, int * Par)
{
char addrstr[32];
char addrbuf[17];
char valstr[16];
strcpy_P (addrstr,outprefix);
strncat (addrstr,itemArr->name,sizeof(addrstr)); ////
switch (cmd)
{
case CMD_ON:
strcpy(valstr,"ON");
break;
case CMD_OFF:
case CMD_HALT:
strcpy(valstr,"OFF");
break;
// TODO send Par
//case 0:
//case CMD_SET:
///////////sprintf(valstr,"%d",Par[0]);
default:
return -1;
}
Serial.print(addrstr);Serial.print("->");Serial.println(valstr);
client.publish(addrstr, valstr);
return 0;
}