Se añade version anterior

master
Gerardo 2022-01-18 22:12:47 +01:00
parent 991f2856bb
commit 6bacb65e2c
14 changed files with 3419 additions and 1 deletions

@ -1 +0,0 @@
Subproject commit 310874dac84bf8a72171da4714ccac40f5b9f9ad

View File

@ -0,0 +1,41 @@
#include "DomoEspManager.h"
DomoEspManager::DomoEspManager()
{
vars.config(&avar, &topics);
sens.Config(&vars);
}
void DomoEspManager::inicia(PubSubClient *mqttClient, WiFiClient* espClient, DomoConfig* conf)
{
wifi.inicia(espClient, conf->ssidWifi, conf->keyWifi);
mqtt.inicia(mqttClient,conf->ideEsp, conf->hostMQTT, conf->portMQTT, this);
//pasar funcion de configuracion de añadir sensores
conf->ConfigSens(&sens);
vars.inicia(mqttClient);
sens.inicia();
}
void DomoEspManager::loop()
{
if(!wifi.loop())
return;
if(!mqtt.loop())
return;
sens.loop();
vars.loop();
}
void DomoEspManager::OnMqtt(char* topic, char* payload)
{
vars.OnMqtt(topic, payload);
}
void DomoEspManager::SubscribeMqtt(PubSubClient *client_mqtt)
{
}

View File

@ -0,0 +1,62 @@
#ifndef DomoEspManagerDef
#define DomoEspManagerDef 1
//#include <ESP8266WiFi.h>//este para esp8266
//#include <PubSubClient.h>
#include <SPI.h>
/*
#include <SimpleDHT.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
*/
#include "MqttVarManager.h"
#include "MqttUtiles.h"
#include "MqttSensManager.h"
class PubSubClient;
class WiFiClient;
class MqttSensManager;
/*
* clase principal
*/
class DomoConfig
{
public:
char ssidWifi[24];
char keyWifi[32];
char ideEsp[16];//identificador unico por esp
char hostMQTT[16];
int portMQTT;
virtual void ConfigSens(MqttSensManager* sens)=0;
};
//TODO falta funcion en configuracion para añadir sensores y variables
class DomoEspManager: public MqttReceiver
{
public:
//variables-------------
MqttVarArray avar;
MqttTopicAttay topics;
MqttVarManager vars;
MqttSensManager sens;
WifiManager wifi;
MqttManager mqtt;
//PubSubClient client_qqtt(WifiManager::espClient);
DomoEspManager();
//PubSubClient client_qqtt(espClient);
void inicia(PubSubClient *mqttClient, WiFiClient* espClient, DomoConfig* conf);
void loop();
//funciones auxiliares
virtual void OnMqtt(char* topic, char* payload);
virtual void SubscribeMqtt(PubSubClient *client_mqtt);
};
#endif

View File

@ -0,0 +1,119 @@
/*
* Software basico sersor domotica con esp8266 / esp32 nodemcu
* Controlado por mqtt
* ---------------------------------------------------------------
* compatible con:
* sensor temperatura y humedad hdt22
* sensores digitales de entrada (gestionado por interrupciones)
* presion y altura por sensor bmp180
* sensores digitales de salida
* receptor rf
* emisor rf
* --------------------------------------------------------------
*/
/*
* la temperatura se tiene que cambiar a digital interrupcion
*/
/*falta transimsion en rf out
Y PROBAR RF*/
#define VERSION_PROG "V0201"//indica version del programa
//#define CONEXION_ETERNET 0//indica si la conexion es ethernet o wifi (para aruino uno)
//falta guardar estado de relees en eprom--------------------------
//**************************************************
//**************************************************************************************************************************************************
//**************************************************************************************************************************************************
//**************************************************************************************************************************************************
/*#ifndef DO
#define D0 16
#endif
#ifndef D1
#define D1 5
#endif
#ifndef D2
#define D2 4
#endif
#ifndef D3
#define D3 0
#endif
#ifndef D4
#define D4 2
#endif
#ifndef D5
#define D5 14
#endif
#ifndef D6
#define D6 12
#endif
#ifndef D7
#define D7 13
#endif
#ifndef D8
#define D8 15
#endif
//**************************************************************************************************************************************************
//**************************************************************************************************************************************************
//**************************************************************************************************************************************************
//**************************************************************************************************************************************************
//includes
/*
#if CONEXION_ETERNET
#include <Ethernet.h>//para arduino uno con ethernet
#else
#include <ESP8266WiFi.h>//este para esp8266
//#include <WiFi.h>//este para esp32
#endif
//#include <Ethernet.h>//para arduino uno con ethernet
*/
#include <ESP8266WiFi.h>//este para esp8266
//#include <WiFi.h>//este para esp32
//**************************************************
/*#include <PubSubClient.h>
#include <SimpleDHT.h>
#include <RCSwitch.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include "sens_domo_mqtt.h"*/
/*
#include <SPI.h>
#include <SimpleDHT.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <PubSubClient.h>*/
#include "DomoEspManager.h"
#include "config_rf.h"
//DomoEspManager domoManager;
WifiManager wifi;
MqttManager mqtt;
MqttVarArray avars;
MqttVarManager vars;
MqttSensArray asens;
MqttSensManager sens;
WiFiClient EspClient;
PubSubClient clienteMqtt(EspClient);
void setup()
{
//domoManager.inicia(&clienteMqtt,&EspClient,&ConfiguracionActual);
}
void loop()
{
//domoManager.loop();
}

View File

@ -0,0 +1,347 @@
//#include <ESP8266WiFi.h>//este para esp8266
/*
#include <SimpleDHT.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
*/
#include "MqttSensManager.h"
#include "MqttVarManager.h"
#include "MqttUtiles.h"
MqttSensor::MqttSensor()
{
}
//*******************************************************************
MqttSensArray::MqttSensArray()
{
n=0;
}
MqttSensor* MqttSensArray:: Get(int i)
{
return &(sens[i]);
}
int MqttSensArray::Add(MqttSensor* var)
{
sens[n]=*var;
n++;
return n-1;
}
//*******************************************************************
MqttSensManager::MqttSensManager()
{
n_inter=0;
bloqueo_sens=false;
tiempo_sens=0;
incre_tsens=15*1000;//por defecto 15 segundos
n_inter=0;
pMqttSensManager=this;
}
void MqttSensManager::Config(MqttVarManager* var)
{
vars=var;
}
MqttSensor* MqttSensManager::Get(int i)
{
}
int MqttSensManager::Add(MqttSensor* var)
{
}
void MqttSensManager::inicia()
{
}
void MqttSensManager::inicia(int i)
{
}
void MqttSensManager::loop()
{
if(bloqueo_sens)
return;
procesaInterrupciones();
if(MqttUtiles::pasa_incre(&tiempo_sens, incre_tsens))
{
procesaSens();
}
}
void MqttSensManager::AddSensor(MqttSensor* sens)
{
}
void MqttSensManager::AddDin(int pin, char* topic)
{
MqttSensor s;
s.tipo=(int)MqttSensor::SENS_DIGI_IN;
s.pin=pin;
s.ivar=vars->AddVar((byte)(MqttVar::IN_VAR|MqttVar::ACCION_VAR),topic);
sens.Add(&s);
pinMode(s.pin, INPUT);
ConfiguraInterrupcion(n_inter++);
}
void MqttSensManager::AddDinAccion(int pin, char* topic)
{
MqttSensor s;
s.tipo=(int)MqttSensor::SENS_DIGI_IN_PULSANTE;
s.pin=pin;
s.ivar=vars->AddVar((byte)MqttVar::ACCION_VAR,topic);
sens.Add(&s);
pinMode(s.pin, INPUT);
ConfiguraInterrupcion(n_inter++);
}
void MqttSensManager::AddHDT22(int pin, char* topic)
{
char buffer_t[32];
MqttSensor s;
s.tipo=(int)MqttSensor::SENS_DHT22;
s.pin=pin;
s.ie.dht.p=&cdht;
sprintf(buffer_t, "%s/t", topic);
s.ivar=vars->AddVar((byte)MqttVar::IN_VAR| MqttVar::FLOAT_VAR,buffer_t);//variable temperatura
sprintf(buffer_t, "%s/h", topic);
s.ie.dht.ivarH=vars->AddVar((byte)MqttVar::IN_VAR| MqttVar::FLOAT_VAR,buffer_t);//variable humedad
sens.Add(&s);
}
void MqttSensManager::AddBMP180(int sda,int scl, char* topic)
{
/*
if(bmppillado)
return;
bmppillado=true;
*/
char buffer_t[32];
MqttSensor s;
s.tipo=(int)MqttSensor::SENS_BMP180;
s.pin=sda;
s.ie.bmp.p=bmp;
s.ie.bmp.pinScl=scl;
sprintf(buffer_t, "%s/t", topic);
s.ivar=vars->AddVar((byte)MqttVar::IN_VAR | MqttVar::FLOAT_VAR,buffer_t);//variable temperatura
sprintf(buffer_t, "%s/p", topic);
s.ie.bmp.ivarP=vars->AddVar((byte)MqttVar::IN_VAR,buffer_t);//variable presion
sprintf(buffer_t, "%s/a", topic);
s.ie.bmp.ivarA=vars->AddVar((byte)MqttVar::IN_VAR| MqttVar::FLOAT_VAR,buffer_t);//variable altura
sens.Add(&s);
//inicia------------------
Wire.begin( s.pin,s.ie.bmp.pinScl);
int i=0;
while(!bmp->begin(), i<300)
{
i++;
delay(10);
}
}
void MqttSensManager::procesaSens()
{
for(int i=0; i<sens.n; i++)
procesaSensor(i);
}
void MqttSensManager::procesaInterrupciones()
{
bool res=false;
for(int i=0; i<n_inter; i++)
{
MqttSensor* s=sens.Get(ind_interrup[i]);
if(s->ie.din.change)
{
noInterrupts();
s->ie.din.change=false;
interrupts();
//lee variable
MqttVar *v=vars->Get(s->ivar);
switch((int)s->tipo)
{
case((int)MqttSensor::SENS_DIGI_IN):
{
//lee y llama a cambio si es necesario
byte val=digitalRead(s->pin);
if(val!=v->val.i)
{
v->val.i=val;
vars->OnChange(s->ivar);
}
break;
}
case((int)MqttSensor::SENS_DIGI_IN_PULSANTE):
{
//lee y llama a cambio si es necesario
byte val=digitalRead(s->pin);
v->val.i=val;
vars->OnChange(s->ivar);
break;
}
default:
break;
}
}
}
}
void MqttSensManager::procesaSensor(int i)
{
MqttSensor *s=sens.Get(i);
MqttVar *v=vars->Get(s->ivar);
switch((int)s->tipo)
{
case((int)MqttSensor::SENS_DHT22)://pilla temperatura y humedad
{
MqttVar *vh=vars->Get(s->ie.dht.ivarH);
float t,h;
for(int i=0; i<4; i++)
{
if (s->ie.dht.p->read2(s->pin, &t, &h, NULL) != SimpleDHTErrSuccess)
{
delay(20);
continue;
}
v->val.f=t;
vh->val.f=h;
break;
}
break;
}
case((int)MqttSensor::SENS_BMP180)://pilla temperatura y humedad
{
MqttVar *vp=vars->Get(s->ie.bmp.ivarP);
MqttVar *va=vars->Get(s->ie.bmp.ivarA);
v->val.f=s->ie.bmp.p->readTemperature();
vp->val.i=s->ie.bmp.p->readPressure();//pascales;
va->val.f=s->ie.bmp.p->readAltitude();
}
default:
{
break;
}
}
}
//funciones auxiliares de interrupcion-------------------------------
void MqttSensManager::OnInterrupcion(int i)
{
MqttSensor* s=sens.Get(ind_interrup[i]);
s->ie.din.change=true;
}
void MqttSensManager::ConfiguraInterrupcion(int i)
{
int pin=sens.Get(ind_interrup[i])->pin;
switch(i)
{
case(0):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion0, CHANGE);
break;
case(1):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion1, CHANGE);
break;
case(2):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion2, CHANGE);
break;
case(3):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion3, CHANGE);
break;
case(4):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion4, CHANGE);
break;
case(5):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion5, CHANGE);
break;
case(6):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion6, CHANGE);
break;
case(7):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion7, CHANGE);
break;
case(8):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion8, CHANGE);
break;
case(9):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion9, CHANGE);
break;
case(10):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion10, CHANGE);
break;
case(11):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion11, CHANGE);
break;
case(12):
attachInterrupt(digitalPinToInterrupt(pin), MqttSensManagerInterrupcion12, CHANGE);
break;
}
}
//chapuza que no se como hacerlo de otra manera
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion0()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(0);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion1()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(1);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion2()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(2);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion3()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(3);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion4()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(4);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion5()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(5);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion6()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(6);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion7()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(7);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion8()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(8);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion9()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(9);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion10()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(10);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion11()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(11);
}
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion12()
{
MqttSensManager::pMqttSensManager->OnInterrupcion(12);
}

View File

@ -0,0 +1,178 @@
#ifndef MqttSensManagerDef
#define MqttSensManagerDef 1
/*
* cambiar en lugar de a topic a variable----------
SENS_DIGI_IN y SENS_ANALOG_IN
publican un topic (set) con el valor correspondiente
SENS_DIGI_OUT
escuchara los set de un topic y publicara el get
SENS_DHT22,//sensor temperatura y humedad
sensor dobles de tipo SENS_ANALOG_IN
publicaran set del topic asociado pñadiendo /t/set /h/set
para temperatura y humedad
SENS_BMP180,//sensor presion
sensor triple SENS_ANALOG_IN
ublicaran set del topic asociado pñadiendo /t/set /p/set /a/set
para temperatura, presion, altitud
*/
#include <SimpleDHT.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
#include <PubSubClient.h>
class PubSubClient;
class MqttVarManager;
struct DhtExt
{
byte ivarH;//puntero a variable humedad
SimpleDHT22 *p;
};
struct BmpExt
{
byte ivarP;
byte ivarA;
int pinScl;
Adafruit_BMP085 *p;
};
struct DinEx
{
volatile bool change;
};
union MqttInfEx//informacion extra segun sensor
{
DhtExt dht;
BmpExt bmp;
DinEx din;
};
class MqttSensor
{
public:
enum Tipo_sens//indica el tipo de sensor
{
SENS_NO_ASIG=0,//sensor sin asignar
SENS_DHT22,//sensor temperatura y humedad
SENS_BMP180,//sensor presion
SENS_ANALOG_IN,//sensor analogico in
SENS_DIGI_IN,//sensor digital in (algo con 2 estados)
SENS_DIGI_OUT,//sensor digital out
SENS_DIGI_IN_PULSANTE//pensado para pulsadores (Publicara un put)
//SENS_DIGI_IN_OUT//sensor doble de entrada y salida (dos pines que tienen que tener el mismo valor)
};
enum Tipo_flags//indica el tipo de sensor
{
FLAG_NEG=0x01,//indica que el resultado del sensor hay que negarlo (valor invertido)
FLAG_INMED=0x02//indica que es un sensor de actualizacion inmediata (interruptores ...) (TODO)
};
byte tipo;//tipo sensor
byte flags;//flags sensor
int pin;//pin de conexion scl para bmp
byte ivar;//indice a variable
MqttInfEx ie;//informacion extra
MqttSensor();
};
//array de sensores--------------------------------------------------------------
class MqttSensArray
{
public:
MqttSensor sens[12];//array de variables
int n;
MqttSensArray();
MqttSensor* Get(int i);
int Add(MqttSensor* var);
};
//array de sensores--------------------------------------------------------------
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion0();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion1();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion2();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion3();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion4();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion5();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion6();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion7();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion8();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion9();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion10();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion11();
ICACHE_RAM_ATTR void MqttSensManagerInterrupcion12();
class MqttSensManager
{
public:
static MqttSensManager* pMqttSensManager;
MqttSensArray sens;//array de variables
MqttVarManager* vars;
PubSubClient *client_qqtt;
SimpleDHT22 cdht;//clase para leer de dht
Adafruit_BMP085 *bmp;//clase bmp
bool bloqueo_sens;//bloquea todos los sensores (para poder editarlos)
int ind_interrup[13];
int n_inter;//numero de interrupciones
unsigned long tiempo_sens;
unsigned long incre_tsens;
MqttSensManager();
void Config(MqttVarManager* varTopics);
int Add(MqttSensor* var);
void inicia();
void loop();
int OnMqtt(char* topic, char* payload);//entra trama mqtt devuelve indice a sensor cambiado
void AddSensor(MqttSensor* sens);
//
//funcion add sensor
void AddHDT22(int pin, char* topic);
void AddBMP180(int sda,int scl, char* topic);
void AddDin(int pin, char* topic);//añade variable digital que se actualiza de manera instantanea
void AddDinAccion(int pin, char* topic);//variable que solo publica en el cambio
//funciones auxiliares------------
MqttSensor* Get(int i);
void inicia(int i);
void procesaSens();
void procesaInterrupciones();
void procesaSensor(int i);
//auxiliares de interrupciones-----------
void ConfiguraInterrupcion(int i);
void OnInterrupcion(int i);
};
/*
*/
#endif

111
DomoEsp_v01_/MqttUtiles.cpp Normal file
View File

@ -0,0 +1,111 @@
#include <SPI.h>
#include <PubSubClient.h>
#include <Wire.h>
#include "MqttUtiles.h"
//**************************************************************************************************************************************************
bool MqttUtiles::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;
}
bool MqttUtiles::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;
}
//**************************************************************************************************************************************************
WifiManager::WifiManager()
{
}
void WifiManager::inicia( WiFiClient *espclient,char *ssid, char* key)
{
espClient= espclient;
strcpy(nred, ssid);
strcpy(pass, key);
}
bool WifiManager::loop()
{
if((WiFi.status() == WL_CONNECTED))
return true;
WiFi.mode(WIFI_STA);
WiFi.begin(nred, pass);
for(int i=0; i<5 && WiFi.status() != WL_CONNECTED; i++)
{
delay(500);
}
return WiFi.status() == WL_CONNECTED;
}
//**************************************************************************************************************************************************
MqttManager::MqttManager()
{
}
void MqttManager::inicia(PubSubClient *mqttClient,char *ideEsp, char *host, int port, MqttReceiver* classReceiver)
{
strcpy(idEsp,ideEsp);
MqttManager::listener=classReceiver;
client_mqtt=mqttClient;
client_mqtt->setServer(host, port);
client_mqtt->setCallback(MqttManager::OnMqtt);
}
bool MqttManager::loop()
{
if(client_mqtt->loop())
return true;
if(client_mqtt->connect(idEsp))
{
subscribe_mqtt();
return true;
}
}
void MqttManager::subscribe_mqtt()
{
if(MqttManager::listener==NULL)
return;
MqttManager::listener->SubscribeMqtt(client_mqtt);
}
//auxiliar------------------
void MqttManager::OnMqtt(char* topic, byte* payload, unsigned int length)
{
if(MqttManager::listener==NULL)
return;
int i;
char buf[32];
i=31;
if(i>length)
i=length;
memcpy(buf, payload, i);
buf[i]=0;
MqttManager::listener->OnMqtt(topic, buf);
}

92
DomoEsp_v01_/MqttUtiles.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef MqttUtilesrDef
#define MqttUtilesDef 1
//#include <WiFi.h>//este para esp32
#include <ESP8266WiFi.h>//este para esp8266*/
class PubSubClient;
class WiFiClient;
#ifndef DO
#define D0 16
#endif
#ifndef D1
#define D1 5
#endif
#ifndef D2
#define D2 4
#endif
#ifndef D3
#define D3 0
#endif
#ifndef D4
#define D4 2
#endif
#ifndef D5
#define D5 14
#endif
#ifndef D6
#define D6 12
#endif
#ifndef D7
#define D7 13
#endif
#ifndef D8
#define D8 15
#endif
class MqttUtiles
{
public:
static bool pasa_incre( unsigned long *tt, unsigned long incre);
static bool pasa_incre( volatile unsigned long *tt, unsigned long incre);
};
class WifiManager
{
public:
char nred[32];
char pass[32];
WiFiClient *espClient;
WifiManager();
void inicia( WiFiClient *espClient, char *ssid, char* key);
bool loop();
};
class MqttReceiver
{
public:
virtual void OnMqtt(char* topic, char* payload)=0;
virtual void SubscribeMqtt(PubSubClient *client_mqtt){}
};
class MqttManager
{
public:
private:
static MqttReceiver* listener;
char idEsp[16];
public:
PubSubClient *client_mqtt;
MqttManager();
/*
WiFiClient espClient;//conexion a wifi
PubSubClient client_qqtt(espClient);//para conexion con mqtt
*/
void inicia(PubSubClient *mqttClient,char *ideEsp, char *host, int port, MqttReceiver* classReceiver);
bool loop();
void desconecta();
//auxiliar------------------
static void OnMqtt(char* topic, byte* payload, unsigned int length);
void subscribe_mqtt();
};
#endif

View File

@ -0,0 +1,220 @@
//#include <ESP8266WiFi.h>//este para esp8266
#include <SPI.h>
#include "MqttVarManager.h"
#include "MqttUtiles.h"
#include <cstring>
#include <PubSubClient.h>
MqttTopicAttay::MqttTopicAttay()
{
n=0;
nst=0;
}
char* MqttTopicAttay::Get(int i)
{
return &str[ind[i]];
}
int MqttTopicAttay::Get(char *topic)
{
for(int i=0; i<n; i++)
{
if(!strcmp(topic,Get(i)))
return i;
}
return -1;
}
int MqttTopicAttay::Add(char *topic)
{
int i=Get(topic);
if(i>=0)
return i;
i=n;
n=n+1;
ind[i]=nst;
nst=nst+strlen(topic)+1;
strcpy(Get(i), topic);
}
//*******************************************************************
MqttVar::MqttVar()
{
flags=0;
val.f=0;
topic=0;
}
//*******************************************************************
MqttVarArray::MqttVarArray()
{
n=0;
}
MqttVar* MqttVarArray:: Get(int i)
{
return &(data[i]);
}
MqttVar* MqttVarArray::GetVar(int itopic)
{
for(int i=0; i<n; i++)
{
if(data[i].topic==itopic)
return &(data[i]);
}
return NULL;
}
int MqttVarArray::Add(MqttVar* var)
{
data[n]=*var;
n++;
return n-1;
}
//*******************************************************************
MqttVarManager::MqttVarManager()
{
tiempo_var=0;
incre_tvar=30*1000;
}
void MqttVarManager::config(MqttVarArray *vArray, MqttTopicAttay* t)
{
vars=vArray;
topics=t;
}
int MqttVarManager::OnMqtt(char* topic, char* payload)
{
char buf[32];
int res=-1;
sprintf(buf, "%s",topic);
int nt=strlen(buf);
int ng=strlen("/get");
bool isGet=!strcmp("/get", &buf[nt-ng]);
buf[nt-ng]=0;
byte f=MqttVar::OUT_VAR;
if(isGet)
f=MqttVar::PRIV_VAR;
if(strcmp("/set", &buf[nt-ng]))
return res;//no es ni get ni set
//comprueba variables
MqttVar* v;
for(int i=0; i<vars->n; i++)
{
v=vars->Get(i);
if((v->flags & f) && !strcmp(topics->Get(v->topic),buf))
{
if(v->flags & MqttVar::FLOAT_VAR)
{
float ff=v->val.f;
v->val.f=atof(payload);
if(ff!=v->val.f)
res=i;
}
else
{
int ii=v->val.i;
v->val.i=atoi(payload);
if(ii!=v->val.i)
res=i;
}
break;//suponemos solo una variable con el mismo topic
}
}
return res;
}
void MqttVarManager::loop()
{
if(MqttUtiles::pasa_incre(&tiempo_var, incre_tvar))
{
PublicaVars();
}
}
void MqttVarManager::PublicaVars()
{
char buffer_t[32];
char buffer_p[24];
byte f=MqttVar::IN_VAR;
MqttVar* v;
for(int i=0; i<vars->n; i++)
{
v=vars->Get(i);
if(v->flags & MqttVar::ACCION_VAR)
continue;//las de accion solo en el onchange
if(v->flags & f)
{
sprintf(buffer_t, "%s/get",topics->Get(v->topic));
//Publica valor
if(v->flags & MqttVar::FLOAT_VAR)
dtostrf(v->val.f,3, 2, buffer_p);
else
sprintf(buffer_p, "%d", (int)v->val.i);
client_qqtt->publish(buffer_t, buffer_p);
}
}
}
void MqttVarManager::inicia(PubSubClient* client_mqtt)
{
client_qqtt=client_mqtt;
//suscribe a mqtt------------
char buffer_t[32];
MqttVar* v;
for(int i=0; i<vars->n; i++)
{
v=vars->Get(i);
if(v->flags & MqttVar::OUT_VAR)//suscribe al set
{
sprintf(buffer_t, "%s/set",topics->Get(v->topic));
client_qqtt->subscribe(buffer_t);
}
if(v->flags & MqttVar::PRIV_VAR)//suscribe al get
{
sprintf(buffer_t, "%s/set",topics->Get(v->topic));
client_qqtt->subscribe(buffer_t);
}
}
}
int MqttVarManager::AddVar(byte flags, char*topic)
{
MqttVar v;
v.flags=flags;
v.topic=topics->Add(topic);
return vars->Add(&v);
}
MqttVar* MqttVarManager::Get(int i)
{
return vars->Get(i);
}
void MqttVarManager::OnChange(int ivar)
{
MqttVar* v=vars->Get(ivar);
byte f= MqttVar::ACCION_VAR;
if(v->flags & f)
{
char buffer_t[32];
char buffer_p[24];
//if(v->flags & MqttVar::IN_VAR)
sprintf(buffer_t, "%s/get",topics->Get(v->topic));
//else
//sprintf(buffer_t, "%s/put",topics->Get(v->topic));
//Publica valor
if(v->flags & MqttVar::FLOAT_VAR)
dtostrf(v->val.f,3, 2, buffer_p);
else
sprintf(buffer_p, "%d", (int)v->val.i);
client_qqtt->publish(buffer_t, buffer_p);
}
}

View File

@ -0,0 +1,174 @@
/*#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif*/
#ifndef MqttvarManagerDef
#define MqttvarManagerDef 1
#define MAXTOPICVAR 24//maximo de caracteres de los topic de las variables
#define MAXTVARARRAY 64//maximo de variables que puede contener el amqttvarArray
class PubSubClient;
//array de topic
class MqttTopicAttay
{
public:
char str[1024];//topic de mqtt asociado
int ind[32];
int nst;
int n;
MqttTopicAttay();
char* Get(int i);
int Get(char *topic);
int Add(char *topic);
};
union MQTTvalor
{
float f;
byte i;
};
class MqttVar
{
public:
enum TipoFlags//indica el tipo de sensor
{
OUT_VAR=0x01,//variable de salida (acepta set)
IN_VAR=0x02,//variable de entrada (publica get)
PRIV_VAR=0x04,//variable privada de entrada (acepta get como si fueran set)
FLOAT_VAR=0x08,
ACCION_VAR=0x10,//variable de accion (publica en cada cambio)
};
public:
//generales---------------------------------------------------------------------
byte flags;
MQTTvalor val;//valor de la variable (tiene que ser union porque puede ser double)
byte topic;//topic de mqtt asociado
MqttVar();
};
//array de variables--------------------------------------------------------------
class MqttVarArray
{
public:
MqttVar data[64];//array de variables
int n;
MqttVarArray();
MqttVar* Get(int i);
MqttVar* GetVar(int itopic);
int Add(MqttVar* var);
};
//manager de variables------------------------------------------------------
class MqttVarManager
{
public:
MqttVarArray* vars;//variables mqtt
MqttTopicAttay* topics;
PubSubClient* client_qqtt;//cliente mqtt
unsigned long tiempo_var;
unsigned long incre_tvar;
MqttVarManager();
void config(MqttVarArray *vArray, MqttTopicAttay* t);
void inicia(PubSubClient* client_qqtt);//subscribe variables a mqtt
int OnMqtt(char* topic, char* payload);//entra trama mqtt devuelve indice a sensor cambiado
void loop();//publica datos variables
//funciones auxiliares----------------------------
MqttVar* Get(int i);
int AddVar(byte flags, char*topic);
void PublicaVars();
void OnChange(int ivar);
};
/*
//clase de relacciones/operaciones************************************************
class MqttOper
{
public:
byte x;//indice a variable 1
byte y;//indice a variable 2
byte oper;
MqttOper();
bool Test(MqttVarArray* vars);
};
//array de relacciones--------------------------------------------------------------
class MqttOperArray
{
public:
MqttOper data[32];
int n;
MqttVarArray();
MqttOper* Get(int i);
bool test(int *i);
int Add(MqttRelaccion* var);
};
class MqttCausa
{
public:
byte ini;//indice a primer oper
byte n;//numero de operadores totales
byte tipo;//tipo de causa (and or ...)
MqttCausa();
bool test(MqttOperArray *i);
};
class MqttAccion
{
public:
MQTTvalor val;
byte ia;//indice externo (dependiendo del tipo puede ser a una variable o topic o sensor ...)
byte tipo;//tipo de accion (and or ...)
MqttAccion();
bool test(MqttOperArray *i);
};
//falta acciones y efectos
//acciones tienen valor, tipo y ivar(indice a variable)
class MqttDesencadenadorManager
{
public:
MqttDesencadenadorManager();
};
/*
*/
#endif

42
DomoEsp_v01_/config_rf.h Normal file
View File

@ -0,0 +1,42 @@
//parametros configurables*************************************************
class ActualDomoConfig: public DomoConfig
{
public:
ActualDomoConfig()
{
strcpy(ssidWifi,"192.168.2.50");
strcpy(keyWifi,"Ardileorca1234.");
strcpy(ideEsp,"Esp8266_002");
strcpy(hostMQTT,"192.168.2.50");
portMQTT=1883;
}
virtual void ConfigSens(MqttSensManager* sens)
{
}
};
#define ID_ESP "Esp8266_002"//indica id de esp (ha de ser unico por instalacion)
const char *topic_id="casa/Desp/";
const int seg_espera=30;//intervalo entre muestras de sensores
//parametros wifi---------------------------------------
const char* ssid = "Idhun";//nombre wifi
const char* password = "Ardileorca1234.";//key wifi
//paremetros mqtt---------------------------------------
const char* mqtt_server = "192.168.2.50";//servidor mqtt
//const char* mqtt_server = "192.168.1.61";//servidor mqtt
//const char* mqtt_server = "192.168.1.20";//servidor mqtt
const int mqtt_puerto= 1883;//puerto servidor mqtt
const bool fuerza_graba=true;
ActualDomoConfig ConfiguracionActual;

View File

@ -0,0 +1,907 @@
#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 || (temperature==255 && humidity==255))
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;
}
//**************************************************************

View File

@ -0,0 +1,907 @@
#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;
}
//**************************************************************

View File

@ -0,0 +1,219 @@
/*#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif*/
//clase sensor mqtt------------------------------------
#define DEBUG_PS 1//si 1 se envia log a puerto serie si no 0
#define MAX_SENS_MQTT 32
#define MAX_INTERRUP_SENS_MQTT 12 //ojo si se cambia hay que hacer mas funciones de interrupcion
#define MAX_RF_IN_SENS_MQTT 16
#define VERSION_SENS_MQTT 102
#include <EEPROM.h>
#include <PubSubClient.h>
#include <SimpleDHT.h>
#include <RCSwitch.h>
#include <Wire.h>
#include <Adafruit_BMP085.h>
class PubSubClient;
class LiquidCrystal;
void conecta_serie(int veloc);
template <class Carg1>
void envia_serie(Carg1 s)
{
if(DEBUG_PS)
Serial.print(s);
};
template <class Carg2>
void envia_serieln(Carg2 s)
{
if(DEBUG_PS)
Serial.println(s);
};
bool pasa_incre( unsigned long *tt, unsigned long incre);
bool pasa_incre( volatile unsigned long *tt, unsigned long incre);
ICACHE_RAM_ATTR void interrupcion1();
ICACHE_RAM_ATTR void interrupcion2();
ICACHE_RAM_ATTR void interrupcion3();
ICACHE_RAM_ATTR void interrupcion4();
ICACHE_RAM_ATTR void interrupcion5();
ICACHE_RAM_ATTR void interrupcion6();
ICACHE_RAM_ATTR void interrupcion7();
ICACHE_RAM_ATTR void interrupcion8();
ICACHE_RAM_ATTR void interrupcion9();
ICACHE_RAM_ATTR void interrupcion10();
ICACHE_RAM_ATTR void interrupcion11();
ICACHE_RAM_ATTR void interrupcion12();
//**************************************************************************************************************************************************
class Ceprom_manager
{
public:
int nb;
Ceprom_manager();
void leeb(byte *p);//lee un byte y deja en p
void grabab(byte p);//graba en eprom un byte
void graba_st(char *st);
void fin_grabacion();//hace efectivos los cambios en la eprom
void cursor(int pos=0);//mueve cursor a posicion indicada
template <class Cgeneg>
void get(Cgeneg* dout)//lee entero
{
byte *b=(byte)dout;
for(int i=sizeof(Cgeneg); i>0;i--)
leeb(&b[i]);
};
template <class Cgenes>
void set(Cgenes* dout)//lee entero
{
byte *b=(byte*)dout;
for(int i=sizeof(Cgenes); i>0;i--)
grabab(b[i]);
};
};
/*
* calse sensor individual de domotica, esta clase administra sensores particulares
*
* Sensor dht22 (sensor out)
* lectura de temperatura y humedad
* tipo: SENS_DHT22
* val: no usado
* pin: pin digital donde se conecta el sensor
* val_old:no usado
* retard:no usado
* id:no usado
* pun: se almacena el puntero a la clase dht
*
* Sensor bmp180
* lectura de temperatura presion y altitud varimetrica
* tipo: SENS_BMP180
* val: no usado
* pin: pin digital donde se conecta el sensor
* val_old:no usado
* retard:no usado
* id:no usado
* pun: se almacena el puntero de la clase bmp
*
* Sensor de entrada analogico
* lectura de 0 a 100 de sensor analogico
* tipo: SENS_ANALOG_IN
* val: si es 0 es directa si es uno es indirecta (la señal de salida es directa o inversamente proporcional a el valor analogico)
* pin: pin analogico donde se conecta el sensor
* val_old:no usado
* retard:no usado
* id:no usado
* pun: no usado
*
* Sensor de entrada digital
* el sensor de entrada digital funciona por interrucciones, el valor se actualiza inmediatamente
* tipo: SENS_DIGI_IN
* val:valor actual del sensor
* pin: pin digital al que esta conectado
* val_old: guarda el valor anterior
* retard: usado para cambiar automaticamente el valor al anterior
* id:no usado
* pun: no usado
* Sensor de entrada y salida digital (dos pines uno de entrada y otro de salida que tiene que tener el mismo valor)
* el sensor de entrada digital funciona por interrucciones, el valor se actualiza inmediatamente
* tipo: SENS_DIGI_IN_OUT
* val:valor actual del sensor
* pin: pin digital de salida (out)
* val_old:no usado
* retard:no usado
* id:pin digital de entrada (pin digital de entrada)
* pun: no usado
*/
class Csens_mqtt
{
public:
//generales--------------------
byte tipo;//tipo sensor
byte val;//se usa para guradar valor en algunos sensores y flags en otros//byte
int pin;//pin de conexion scl para bmp
char topic[8];//topic de mqtt que se anadira
//-----------------------------
//especificas
byte val_old;//byte
volatile unsigned long t;
unsigned long retard;
long id; //pin sda para bmp
void *pun;
//c y d----------------------
Csens_mqtt();
~Csens_mqtt();
bool envia_mqtt(PubSubClient *client_qqtt, char *top, bool envia);//envia estado del sensor por mqtt
//bool recive_mqtt(PubSubClient *client_qqtt, char *top);//recive estado de sensor por mqtt
//bool inicia();//inicia sensor (previamente ya seteado)
bool set(char *conf);//rellena sensor segun trama de configuracion
bool get(char *conf);//anade a la trama la configuracion correspondiente a este sensor
enum Tipo_sens//indica el tipo de sensor
{
SENS_NO_ASIG=0,//sensor sin asignar
SENS_DHT22,//sensor temperatura y humedad
SENS_BMP180,//sensor presion
SENS_ANALOG_IN,//sensor analogico in
SENS_DIGI_IN,//sensor digital in
SENS_DIGI_OUT,//sensor digital out
SENS_DIGI_IN_OUT,//sensor doble de entrada y salida (dos pines que tienen que tener el mismo valor)
SENS_RF_OUT,//sensor transmisor de rf
SENS_RF_IN,//sensor receptor de rf
SENS_RF_DATA_IN//dato a recivir por rf
};
};
//clase manager de sensores mqtt-----------------------
class Csens_domo_mqtt
{
public:
SimpleDHT22 cdht;//clase para leer de dht
Adafruit_BMP085 bmp;//clase bmp
PubSubClient *client_qqtt;
bool bmppillado;//indica si el bmp esta asignado o no
RCSwitch rf;
bool bloqueo_sens;//bloquea todos los sensores (para poder editarlos)
byte rf_in_pillado;//indica si rf in esta asignado
bool rf_out_pillado;//indica si rf_out esta asignado
byte ind_interrup[MAX_INTERRUP_SENS_MQTT];//array de interrupciones (indices a sensor)
int n,//numero de sensores
n_inter,//numero de interrupciones
flags;
unsigned long t_inter, t_rev_interrup;
byte ind_rf_in[MAX_RF_IN_SENS_MQTT];
int n_rf_in;
char top[16];//topic_id_sensor
Csens_mqtt sen[MAX_SENS_MQTT];
Csens_domo_mqtt();//constructor
//funciones-------------------------------
bool inicia(int i);//inicia el sensor iesimo
bool conf();//configura de eprom
void envia_comunes();//envia por mqtt la info de sensores comunes
void revisa_interrupciones();//revisa sensores con interrupciones
void revisa_rf();//revisa entradas de rf
bool graba_conf();//graba configuracion en eprom
void para_sens();//desconfigura todos los sensores (a nivel de hardware)
void del(int i);//borra el sensor iesimo
void subscribe_mqtt();//pone en suspcripcion de los sensores que sean necesarios
bool on_mqtt(char* topic, char* payload);//recibe traza mqtt
void on_interrupcion(int i);//ejecuta interrupcion iesima
void atachea(int i);//habilita interrupcion iesima
};
#ifndef PCLASE_SENS_DOMO
#define PCLASE_SENS_DOMO
static void *pclase_sens_domo_mq;
#endif