DomoEsp_v1/DomoEsp_v01_/sens_domo_mqtt.cpp.bak

908 lines
22 KiB
C++

#include "sens_domo_mqtt.h"
//funciones generales
//**************************************************************************************************************************************************
//funcion para decidir cuando enviar info de sensores por mqtt
bool pasa_incre( unsigned long *tt, unsigned long incre)
{
unsigned long t=millis();
if(t<*tt)
{
*tt=t;
return true;
}
if((*tt+incre)>=t)
return false;
*tt=t;
return true;
}
//**************************************************************************************************************************************************
//funcion para decidir cuando enviar info de sensores por mqtt
bool pasa_incre( volatile unsigned long *tt, unsigned long incre)
{
unsigned long t=millis();
if(t<*tt)
{
*tt=t;
return true;
}
if((*tt+incre)>=t)
return false;
*tt=t;
return true;
}
//**************************************************************************************************************************************************
void conecta_serie(int veloc)
{
if(DEBUG_PS)
{
Serial.begin(veloc);
delay(10);
}
}
/**************************************************************************************************************************************************
void envia_serie(char* s)
{
if(DEBUG_PS)
Serial.print(s);
}
//**************************************************************************************************************************************************
void envia_serieln(char* s)
{
if(DEBUG_PS)
Serial.println(s);
}*/
//**************************************************************************************************************************************************
void Ceprom_manager::fin_grabacion()
{
EEPROM.commit();
}
//**************************************************************
Ceprom_manager::Ceprom_manager()
{
nb=0;
}
//**************************************************************
void Ceprom_manager::leeb(byte *p)
{
*p=EEPROM.read(nb++);
}
//**************************************************************
void Ceprom_manager::grabab(byte p)
{
EEPROM.write(nb++, p);
}
//**************************************************************
void Ceprom_manager::graba_st(char *st)
{
for(int i=strlen(st); i>0; i--)
{
Ceprom_manager::grabab(*st);
st++;
}
}
//**************************************************************
void Ceprom_manager::cursor(int pos)
{
nb=pos;
}
//**************************************************************
Csens_mqtt::Csens_mqtt()
{
tipo=SENS_NO_ASIG;//tipo sensor
val=0;
pin=-1;//pin de conexion
topic[0]=0;
//-----------------------------
//especificas
val_old=0;
t=0;
retard=0;
id=0;
pun=NULL;
}
//**************************************************************
Csens_mqtt::~Csens_mqtt()
{
}
//**************************************************************
bool Csens_mqtt::envia_mqtt(PubSubClient *client_qqtt, char *top, bool envia)
{
if(pin<0)
return false;
char buffer_t[32];
char buf[24];
//SimpleDHT22 dht22;
//Adafruit_BMP085 bmp;//para la presion
//RCSwitch rf = RCSwitch();//para rfin
switch(tipo)
{
case(SENS_NO_ASIG):
return true;
case(SENS_DHT22)://pilla temperatura y humedad
{
float temperature = 0;
float humidity = 0;
int err = SimpleDHTErrSuccess;
for(int i=0; i<4; i++)
{
err = ((SimpleDHT22*)pun)->read2(pin, &temperature, &humidity, NULL);
if (err != SimpleDHTErrSuccess)
{
delay(20);
continue;
}
break;
}
if(err!=SimpleDHTErrSuccess)
{
temperature=255;
humidity=255;
if(envia)
envia_serieln("envio dht con error");
}
if(!envia)
return true;
//construlle topic--------------
sprintf(buffer_t, "%s%s/t",top, topic);
dtostrf(temperature,3, 2, buf);
//envia_serie(buffer_t);
//envia_serieln(buf);
client_qqtt->publish(buffer_t, buf);
sprintf(buffer_t, "%s%s/h",top, topic);
dtostrf(humidity,3, 2, buf);
client_qqtt->publish(buffer_t, buf);
return true;
}
case(SENS_BMP180):
{
float temperature = ((Adafruit_BMP085*)pun)->readTemperature();
int presb = ((Adafruit_BMP085*)pun)->readPressure();//pascales
float altb = ((Adafruit_BMP085*)pun)->readAltitude();
//envia tempe-------------------------------
sprintf(buffer_t, "%s%s/t",top, topic);
dtostrf(temperature,3, 2, buf);
client_qqtt->publish(buffer_t, buf);
//envia presion barometrica-----------------
sprintf(buffer_t, "%s%s/p",top, topic);
sprintf(buf,"%d",presb);
client_qqtt->publish(buffer_t, buf);
//envia altura barometrica-------------------
sprintf(buffer_t, "%s%s/a",top, topic);
dtostrf(altb,3, 2, buf);
client_qqtt->publish(buffer_t, buf);
return true;
}
case(SENS_ANALOG_IN):
{
float aux;
/* envia_serie("val: ");
envia_serie(val);
envia_serie(" pin: ");
envia_serieln(pin);*/
if(val)
aux=100.*((float)(1024- analogRead(pin)))/1024;
else
aux=100.*((float)(analogRead(pin)))/1024;
dtostrf(aux,3, 2, buf);
sprintf(buffer_t, "%s%s",top,topic );
//envia_serie(buffer_t);
//envia_serieln(buf);
client_qqtt->publish(buffer_t, buf);
return true;
}
case(SENS_DIGI_IN_OUT):
{
if (envia)
{
sprintf(buffer_t, "%s%s", top, topic);
sprintf(buf, "%d", (int)val);
client_qqtt->publish(buffer_t, buf);
}
else
{
sprintf(buffer_t, "%s%s/set",top, topic);
sprintf(buf,"%d",(int) val);
client_qqtt->publish(buffer_t, buf);
}
return true;
}
case(SENS_DIGI_IN):
{
sprintf(buffer_t, "%s%s",top, topic);
sprintf(buf,"%d",(int) val);
client_qqtt->publish(buffer_t, buf);
//envia_serie(buffer_t);
//envia_serieln(buffer);
return true;
}
case(SENS_DIGI_OUT):
{
sprintf(buffer_t, "%s%s/get",top, topic);
sprintf(buf,"%d",(int) val);
client_qqtt->publish(buffer_t, buf);
return true;
}
case(SENS_RF_DATA_IN):
{
sprintf(buffer_t, "%s%s",top, topic);
sprintf(buf,"%d",(int) val);
client_qqtt->publish(buffer_t, buf);
return true;
}
default:
return false;
}
}
//**************************************************************
bool Csens_mqtt::get(char *conf)
{
sprintf(conf, "<%d;%d;%d;%s;%d;%d;%d;%d;>",
(int)tipo, (int)val, pin, topic, (int)val_old, t, retard/1000, id);
envia_serieln(conf);
return true;
}
//**************************************************************
bool Csens_mqtt::set(char *conf)
{
/*
//la trama empieza por < y acaba por> y se pone la info de las variables de la clase:
byte tipo;//tipo sensor
byte val;//se usa para guradar valor en algunos sensores y flags en otros
int pin;//pin de conexion
char topic[8];//topic de mqtt que se anadira
//-----------------------------
//especificas
byte val_old;
volatile unsigned long t;
unsigned long retard;
long id;
separadas por ;
*/
envia_serieln("entra en set");
int i=0, j, k;
char res[17];
if(conf[i]=='<')
{
i++;
}
else
return false;
k=0;
j=0;
while(conf[i]!='>')
{
if(!conf[i])
{
envia_serieln("sale por fin");
return false;
}
if(conf[i]==';')
{
res[j]=0;
j=0;
switch(k)
{
case(0):
tipo= atoi(res);
break;
case(1):
val=atoi(res);
break;
case(2):
pin=atoi(res);
break;
case(3):
strcpy(topic,res);
// tipo=(byte)atoi(res);
break;
case(4):
val_old=atoi(res);
break;
case(5):
t=atoi(res);//atoll
break;
case(6):
retard=1000*atoi(res);//atoll
break;
case(7):
id=atol(res);
break;
}
k++;
}
else
{
res[j]=conf[i];
j++;
if(j>=16)
{
envia_serieln("sin memo en set");
return false;
}
}
i++;
}
envia_serieln(k);
return k>7;
//sprintf(conf, "<%d;%d;%d;%s;%d;%ld;%ld;%ld",(int)tipo, (int)val, pin, topic, (int)val_old, t, retard, id);
//return true;
}
//**************************************************************
void Csens_domo_mqtt::para_sens()
{
int i;
for(i=0; i<n_inter; i++)
detachInterrupt(digitalPinToInterrupt(sen[ind_interrup[i]].pin));
rf.disableReceive();
rf.disableTransmit();
n_inter=0;
n_rf_in=0;
bmppillado=false;
rf_in_pillado=false;
rf_out_pillado=false;
//deshabilita interrupciones
//attachInterrupt(digitalPinToInterrupt(sen[ind_interrup[i]].pin), 0, RISING);
}
//**************************************************************
bool Csens_domo_mqtt::inicia( int i )
{
switch(sen[i].tipo)
{
case(Csens_mqtt::SENS_NO_ASIG):
return true;
case(Csens_mqtt::SENS_DHT22)://pilla temperatura y humedad
{
sen[i].pun=&cdht;
sen[i].envia_mqtt(client_qqtt, top, false);
return true;
}
case(Csens_mqtt::SENS_BMP180):
{
if(bmppillado)
{
envia_serie("Error en sensor ");
envia_serie(i);
envia_serieln(" solo se puede un bmp a la vez");
return false;
}
sen[i].pun=&bmp;
#if CONEXION_ETERNET
Wire.begin();
#else
//Wire.begin(bmp_pin_sda, bmp_pin_scl);
Wire.begin( sen[i].id,sen[i].pin);
#endif
int i=0;
while(!bmp.begin(), i<300)
{
i++;
delay(10);
}
if(i>=300)
{
envia_serie("Error en sensor ");
envia_serie(i);
envia_serieln("BMP no se puede inicializar");
// return false;//puede que este bien
}
bmppillado=true;
return true;
}
case(Csens_mqtt::SENS_RF_IN):
{
if(rf_in_pillado)
return false;
rf_in_pillado=true;
rf.enableReceive(sen[i].pin);
//rf.setPulseLength(150);
return true;
}
case(Csens_mqtt::SENS_RF_OUT):
{
if(rf_out_pillado)
return false;
rf_out_pillado=true;
rf.enableTransmit(sen[i].pin);
return true;
}
case(Csens_mqtt::SENS_RF_DATA_IN):
{
if(n_rf_in>=MAX_RF_IN_SENS_MQTT)
{
envia_serie("Error en sensor ");
envia_serie(i);
envia_serieln("rf_in sin espacio para mas");
return false;
}
envia_serie("rf_data retard: ");
envia_serieln(sen[i].retard);
ind_rf_in[n_rf_in]=i;
n_rf_in++;
return true;
}
case(Csens_mqtt::SENS_ANALOG_IN):
{
return true;//no necesita nada
}
case(Csens_mqtt::SENS_DIGI_IN):
{
if(n_inter>=MAX_INTERRUP_SENS_MQTT)
{
envia_serie("Error en sensor ");
envia_serie(i);
envia_serieln("digi_in sin espacio para las interrupciones");
return false;
}
ind_interrup[n_inter]=i;
envia_serie("inicia din ");
pinMode(sen[i].pin, INPUT);
//digitalWrite(sen[i].pin, sen[i].val);
atachea(n_inter++);
envia_serie("iniciado din ");
return true;
}
case(Csens_mqtt::SENS_DIGI_OUT):
{
pinMode(sen[i].pin, OUTPUT);
digitalWrite(sen[i].pin, sen[i].val);
return true;
}
case(Csens_mqtt::SENS_DIGI_IN_OUT):
{
if (n_inter >= MAX_INTERRUP_SENS_MQTT)
{
envia_serie("Error en sensor ");
envia_serie(i);
envia_serieln("digi_in_out sin espacio para las interrupciones");
return false;
}
pinMode(sen[i].pin, OUTPUT);
digitalWrite(sen[i].pin, sen[i].val);
ind_interrup[n_inter] = i;
envia_serie("inicia digi_in_out ");
pinMode(sen[i].id, INPUT);
atachea(n_inter++);
envia_serie("iniciado din ");
return true;
}
default:
break;
}
return false;
}
//**************************************************************
Csens_domo_mqtt::Csens_domo_mqtt()
{
rf=RCSwitch();
n=0;
flags=0;
bmppillado= rf_in_pillado= rf_out_pillado = false;
n_inter=0;
t_rev_interrup=1000;
t_inter=0;
n_rf_in=0;
pclase_sens_domo_mq=(void*)this;
}
//**************************************************************
bool Csens_domo_mqtt::conf()
{
Ceprom_manager ep;
char buf[64];
int nb, nn;
n=0;
//lee version-----------------------------
buf[0]=0;
ep.leeb((byte*)buf);
if((byte)buf[0]!=(byte)VERSION_SENS_MQTT)
{
envia_serieln("Version no reconocida");
return false;//sin configuracion
}
for (nn=0; nn<MAX_SENS_MQTT; nn++)
{
nb=0;
ep.leeb((byte*)buf);
if(buf[nb]!='<')
break;//terminado
while(buf[nb]!='>' || nb>=64)
{
ep.leeb((byte*)&buf[++nb]);
}
if(buf[nb]!='>')
break;
buf[++nb]=0;
//envia_serie("conf lee ");
//envia_serieln(buf);
if(sen[n].set(buf))
n++;
else
{
envia_serie("Error al leer sensor ");
envia_serieln(buf);
}
}
envia_serie("lee ");
envia_serie(n);
envia_serieln(" sensores");
return n>0;
}
//**************************************************************
void Csens_domo_mqtt::envia_comunes()
{
for(int i=0;i<n;i++)
{
switch(sen[i].tipo)
{
case(Csens_mqtt::SENS_ANALOG_IN):
case(Csens_mqtt::SENS_DHT22):
case(Csens_mqtt::SENS_BMP180):
case(Csens_mqtt::SENS_DIGI_OUT):
case(Csens_mqtt::SENS_DIGI_IN):
case(Csens_mqtt::SENS_DIGI_IN_OUT):
sen[i].envia_mqtt(client_qqtt, top, true);
break;
default:
break;
}
}
}
//**************************************************************
void Csens_domo_mqtt::del(int i)
{
for(;i<n-1;i++)
sen[i]=sen[i+1];
n--;
}
//**************************************************************
void Csens_domo_mqtt::subscribe_mqtt()
{
char buffer_t[32];
for(int i=0;i<n;i++)
{
switch(sen[i].tipo)
{
case(Csens_mqtt::SENS_DIGI_IN_OUT):
case(Csens_mqtt::SENS_DIGI_OUT):
{
sprintf(buffer_t, "%s%s/set",top,sen[i].topic );
envia_serie("suscribe: ");
envia_serieln(buffer_t);
client_qqtt->subscribe(buffer_t);
break;
}
default:
break;
}
}
}
//**************************************************************
bool Csens_domo_mqtt::on_mqtt(char* topic, char* payload)
{
char buffer_t[32];
int j;
//descompone topic
//busca sensor------------------
for(int i=0;i<n;i++)
{
switch(sen[i].tipo)
{
case(Csens_mqtt::SENS_DIGI_IN_OUT):
case(Csens_mqtt::SENS_DIGI_OUT):
{
//revisa si es esta
sprintf(buffer_t, "%s/set",sen[i].topic);
if(strcmp(buffer_t, topic))
break;//este no es
j=atoi(payload);
if(j==0 || j==1)
sen[i].val=j;
else
envia_serieln("valor para sensor digital no valido");
sprintf(buffer_t, "On mqtt se escribe valor %s",payload);
envia_serieln(buffer_t);
digitalWrite( sen[i].pin, sen[i].val);
sen[i].envia_mqtt(client_qqtt, top, true);
return true;
}
default:
break;
}
}
return false;
}
//**************************************************************
//funciones auxiliares de interrupcion-------------------------------
//chapuza que no se como hacerlo de otra manera
ICACHE_RAM_ATTR void interrupcion0()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(0);
}
ICACHE_RAM_ATTR void interrupcion1()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(1);
}
ICACHE_RAM_ATTR void interrupcion2()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(2);
}
ICACHE_RAM_ATTR void interrupcion3()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(3);
}
ICACHE_RAM_ATTR void interrupcion4()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(4);
}
ICACHE_RAM_ATTR void interrupcion5()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(5);
}
ICACHE_RAM_ATTR void interrupcion6()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(6);
}
ICACHE_RAM_ATTR void interrupcion7()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(7);
}
ICACHE_RAM_ATTR void interrupcion8()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(8);
}
ICACHE_RAM_ATTR void interrupcion9()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(9);
}
ICACHE_RAM_ATTR void interrupcion10()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(10);
}
ICACHE_RAM_ATTR void interrupcion11()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(11);
}
ICACHE_RAM_ATTR void interrupcion12()
{
((Csens_domo_mqtt*) pclase_sens_domo_mq)->on_interrupcion(12);
}
//**************************************************************
void Csens_domo_mqtt::atachea(int i)
{
if(bloqueo_sens)
return;
//la otra parte de la chapuza que no se me ocurre otra manera
envia_serie("atachea din ");
envia_serie(i);
envia_serie(" pin ");
envia_serieln(sen[ind_interrup[i]].pin);
int pin = sen[ind_interrup[i]].pin;
if (sen[ind_interrup[i]].tipo == Csens_mqtt::SENS_DIGI_IN_OUT)
pin = sen[ind_interrup[i]].id;
switch(i)
{
case(0):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion0, CHANGE);
break;
case(1):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion1, CHANGE);
break;
case(2):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion2, CHANGE);
break;
case(3):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion3, CHANGE);
break;
case(4):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion4, CHANGE);
break;
case(5):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion5, CHANGE);
break;
case(6):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion6, CHANGE);
break;
case(7):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion7, CHANGE);
break;
case(8):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion8, CHANGE);
break;
case(9):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion9, CHANGE);
break;
case(10):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion10, CHANGE);
break;
case(11):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion11, CHANGE);
break;
case(12):
attachInterrupt(digitalPinToInterrupt(pin), interrupcion12, CHANGE);
break;
}
}
//***************************************************************
void Csens_domo_mqtt::on_interrupcion(int i)
{
envia_serie("On interrup ");
int j=ind_interrup[i];
envia_serieln(j);
if (sen[j].retard == 0)
{
sen[j].val_old = 1;
sen[j].t = millis();
}
else
{
sen[j].val = 1;
sen[j].t = millis();
}
}
//**************************************************************
void Csens_domo_mqtt::revisa_interrupciones()
{
int j, i;
//interrupciones puras------------------------------
for(j=0; j<n_inter; j++)
{
i=ind_interrup[j];
if (sen[i].retard == 0)
{
if (sen[i].val_old)
{
noInterrupts();
sen[i].val_old = 0;
interrupts();
envia_serieln("revisa din on");
if (sen[i].tipo == Csens_mqtt::SENS_DIGI_IN_OUT)
{
sen[i].val = digitalRead(sen[i].id);
envia_serieln("readDigital ");
envia_serieln( sen[i].val);
sen[i].envia_mqtt(client_qqtt, top, false);
}
else
{
sen[i].val = digitalRead(sen[i].pin);
sen[i].envia_mqtt(client_qqtt, top, true);
}
}
}
else if( sen[i].val && !sen[i].val_old )
{
envia_serieln("revisa din on");
sen[i].val_old=1;
if (sen[i].tipo == Csens_mqtt::SENS_DIGI_IN_OUT)
{
sen[i].envia_mqtt(client_qqtt, top, false);
}
else
sen[i].envia_mqtt(client_qqtt, top, true);
}
}
if(!pasa_incre(&t_inter, t_rev_interrup))//comprueba vuelta a estados normales
return;
bool envia;
//interrupciones puras------------------------------------------
for(j=0; j<n_inter; j++)
{
if (sen[i].retard == 0)
continue;
i=ind_interrup[j];
envia=false;
if(sen[i].val_old )
{
noInterrupts();
if(pasa_incre(&sen[i].t, ( unsigned long)sen[i].retard))
{
sen[i].val_old=sen[i].val=0;//vuelve a estado normal
envia=true;
envia_serieln("revisa din off");
}
interrupts();
}
if(envia)
{
if (sen[i].tipo == Csens_mqtt::SENS_DIGI_IN_OUT)
{
sen[i].envia_mqtt(client_qqtt, top, false);//envia info
}
else
sen[i].envia_mqtt(client_qqtt, top, true);//envia info
}
}
//interrupciones rf-----------------------------------------
for(j=0; j<n_rf_in; j++)
{
i=ind_rf_in[j];
if( sen[i].val_old && pasa_incre(&sen[i].t, ( unsigned long)sen[i].retard))
{
sen[i].val_old=sen[i].val=0;//vuelve a estado normal
envia_serieln("revisa rf off ");
//envia_serieln(sen[i].retard);
sen[i].envia_mqtt(client_qqtt, top, true);
}
}
}
//**************************************************************
void Csens_domo_mqtt::revisa_rf()
{
if(!rf_in_pillado || !rf.available())
return;
long val = rf.getReceivedValue();//pilla id
rf.resetAvailable();
int i, j;
//busca entre ids conocidos
for(j=0; j<n_rf_in; j++)
{
i=ind_rf_in[j];
if(sen[i].id==val)
break;
}
if(j>=n_rf_in)
{
envia_serie("rf no reconocido: ");
envia_serieln(val);
return;//id no reconocido
}
//envia_serie("rf on detectado: ");
//envia_serieln(val);
//actualiza valor--------------------------------------------
sen[i].val=1;
sen[i].t=millis();
if(!sen[i].val_old)
{
sen[i].envia_mqtt(client_qqtt, top, true);
sen[i].val_old=1;
}
}
//**************************************************************
bool Csens_domo_mqtt::graba_conf()
{
envia_serieln("Graba config");
char buf[64];
bool res=true;
Ceprom_manager ep;
buf[0]=(byte)VERSION_SENS_MQTT;
ep.grabab((byte)buf[0]);
for(int i=0; i<n; i++)
{
if(!sen[i].get(buf))//peticion de info de sensor
{
res=false;
envia_serie("Error al grabar configuracion, sensor: ");
envia_serieln(i);
}
else
ep.graba_st(buf);
}
ep.grabab(0);
ep.fin_grabacion();
return res;
}
//**************************************************************