Domotique/WifiControlSensor/MQTT.ino

225 lines
7.0 KiB
Arduino
Raw Permalink Normal View History

2016-10-28 18:04:30 +02:00
#ifndef CONFIG_DISABLE_MQTT
2016-04-08 01:03:57 +02:00
#include <stdarg.h>
#include "utils.h"
2016-04-14 01:15:42 +02:00
#include "MQTT.h"
2016-11-20 18:08:15 +01:00
#include "sensors.h"
2016-04-14 01:15:42 +02:00
2016-03-14 01:47:43 +01:00
Adafruit_MQTT_Client *mqtt;
Adafruit_MQTT_Publish *mqtt_temp;
2016-03-16 00:54:13 +01:00
Adafruit_MQTT_Publish *mqtt_pressure;
2016-04-07 02:04:38 +02:00
Adafruit_MQTT_Publish *mqtt_dht_temp;
Adafruit_MQTT_Publish *mqtt_dht_humidity;
2016-06-18 02:24:00 +02:00
Adafruit_MQTT_Publish *mqtt_ip;
2016-09-28 13:45:01 +02:00
Adafruit_MQTT_Publish *mqttGpio[MAXSUBSCRIPTIONS] = {};
2016-09-28 14:08:43 +02:00
Adafruit_MQTT_Publish *mqttPwm[MAXSUBSCRIPTIONS] = {};
2016-11-20 18:08:15 +01:00
Adafruit_MQTT_Publish **gpioSensorsMqtt;
2016-03-14 01:47:43 +01:00
#define FEED_MAX_SIZE 96
2016-03-21 00:56:27 +01:00
//FEED have the following formats /feeds/USER/DEVICE_NAME/....
2016-11-20 18:08:15 +01:00
#define GPIO_FEED_FORMAT "/feeds/%s/%s/%s/%s"
2016-09-28 13:45:01 +02:00
#define TEMPERATURE_FEED_FORMAT "/feeds/%s/%s/temperature"
#define PRESSURE_FEED_FORMAT "/feeds/%s/%s/pressure"
#define TEMPERATURE_DHT_FEED_FORMAT "/feeds/%s/%s/dht/temperature"
#define HUMIDITY_DHT_FEED_FORMAT "/feeds/%s/%s/dht/humidity"
#define GPIO_FEED_FORMAT "/feeds/%s/%s/gpio/%d"
#define GPIO_SET_FEED_FORMAT "/feeds/%s/%s/gpio/%d/set"
2016-09-28 14:08:43 +02:00
#define PWM_FEED_FORMAT "/feeds/%s/%s/gpio/%d"
#define PWM_SET_FEED_FORMAT "/feeds/%s/%s/gpio/%d/set"
2016-09-28 13:45:01 +02:00
#define IP_FEED_FORMAT "/feeds/%s/%s/configuration/ip/addr"
2016-04-07 02:04:38 +02:00
2016-03-22 20:01:05 +01:00
// Should have less that MAXSUBSCRIPTIONS elements
// MAXSUBSCRIPTIONS is defined is Adafruit_mqtt.h
const int gpioWatched[] = CONFIG_MQTT_CONTROLLED_GPIO;
2016-09-28 14:08:43 +02:00
const int pwmWatched[] = CONFIG_CONTROLLED_PWM;
2016-03-21 00:56:27 +01:00
char *mqttId;
2016-03-14 01:47:43 +01:00
bool isMqttConfigured = false;
2016-09-15 22:43:00 +02:00
bool useMqtts = false;
2016-11-20 18:08:15 +01:00
void initGpioSensorsMqtt(char *user, char *hostname){
uint i;
gpioSensorsMqtt = new Adafruit_MQTT_Publish *[NB_ELEMENTS(gpioSensors)];
for(i = 0; i < NB_ELEMENTS(gpioSensors); i++){
gpioSensorsMqtt[i] = MqttCreatePublisher(GPIO_FEED_FORMAT, user, hostname,
gpioSensors[i]->sensorName, gpioSensors[i]->measureName);
}
}
2016-04-14 01:15:42 +02:00
2016-09-27 23:51:01 +02:00
int MqttSetup(char *server, char *user, char *passwd, int port, char *hostname) {
mqttId = hostname;
2016-09-15 22:43:00 +02:00
useMqtts = (port == 8883);
2016-04-14 01:15:42 +02:00
isMqttConfigured = server[0] != '\0';
2016-04-14 01:15:42 +02:00
if(!isMqttConfigured)
return 0;
#ifndef CONFIG_DISABLE_SSL
2016-09-15 22:43:00 +02:00
if(useMqtts)
mqtt = new Adafruit_MQTT_Client(new WiFiClientSecure(), server, port, user, passwd);
else
#endif
2016-09-15 22:43:00 +02:00
mqtt = new Adafruit_MQTT_Client(new WiFiClient(), server, port, user, passwd);
2016-09-27 23:51:01 +02:00
mqtt_dht_temp = MqttCreatePublisher(TEMPERATURE_DHT_FEED_FORMAT, user, mqttId);
mqtt_dht_humidity = MqttCreatePublisher(HUMIDITY_DHT_FEED_FORMAT, user, mqttId);
mqtt_temp = MqttCreatePublisher(TEMPERATURE_FEED_FORMAT, user, mqttId);
mqtt_pressure = MqttCreatePublisher(PRESSURE_FEED_FORMAT, user, mqttId);
mqtt_ip = MqttCreatePublisher(IP_FEED_FORMAT, user, mqttId);
2016-09-28 14:08:43 +02:00
if( NB_ELEMENTS(gpioWatched) + NB_ELEMENTS(pwmWatched) > MAXSUBSCRIPTIONS){
SKETCH_DEBUG_PRINTF("Too much gpio/pwm to control\n Nb gpio %d Nb pwm %d Max is %d",
NB_ELEMENTS(gpioWatched), NB_ELEMENTS(pwmWatched), MAXSUBSCRIPTIONS);
return -1;
}
2016-04-07 16:14:19 +02:00
for (uint i = 0 ; i < NB_ELEMENTS(gpioWatched) && i < MAXSUBSCRIPTIONS; i++) {
2016-09-27 23:44:52 +02:00
mqtt->subscribe(MqttCreateSubscribe(GPIO_SET_FEED_FORMAT, user, mqttId, gpioWatched[i]));
mqttGpio[i] = MqttCreatePublisher(GPIO_FEED_FORMAT, user, mqttId, gpioWatched[i]);
2016-03-22 20:01:05 +01:00
}
2016-09-28 14:08:43 +02:00
for (uint i = 0 ; i < NB_ELEMENTS(gpioWatched) && i < MAXSUBSCRIPTIONS; i++) {
mqtt->subscribe(MqttCreateSubscribe(PWM_SET_FEED_FORMAT, user, mqttId, pwmWatched[i]));
mqttPwm[i] = MqttCreatePublisher(PWM_FEED_FORMAT, user, mqttId, pwmWatched[i]);
}
2016-11-20 18:08:15 +01:00
initGpioSensorsMqtt(user, hostname);
2016-03-14 01:47:43 +01:00
return 0;
}
2016-04-08 01:03:57 +02:00
Adafruit_MQTT_Publish *MqttCreatePublisher(const char *fmt, ...){
2016-04-14 01:15:42 +02:00
char buf[FEED_MAX_SIZE];
2016-04-08 01:03:57 +02:00
va_list args;
va_start (args, fmt);
vsnprintf(buf, sizeof(buf), (const char *)fmt, args);
va_end(args);
2016-09-27 23:44:52 +02:00
return new Adafruit_MQTT_Publish(mqtt, strdup(buf));
2016-04-08 01:03:57 +02:00
}
2016-09-27 23:44:52 +02:00
Adafruit_MQTT_Subscribe *MqttCreateSubscribe(const char *fmt, ...){
char buf[FEED_MAX_SIZE];
va_list args;
va_start (args, fmt);
vsnprintf(buf, sizeof(buf), (const char *)fmt, args);
va_end(args);
return new Adafruit_MQTT_Subscribe(mqtt, strdup(buf));
}
2016-04-10 01:59:37 +02:00
int MqttIsConnected() {
2016-04-14 01:15:42 +02:00
return (isMqttConfigured) ? mqtt->connected() : 0;
2016-03-14 18:05:14 +01:00
}
2016-03-11 01:31:03 +01:00
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
int MqttConnect() {
2016-03-11 01:31:03 +01:00
int8_t ret;
2016-04-10 01:59:37 +02:00
if(!isMqttConfigured)
return -1;
2016-03-11 01:31:03 +01:00
// Stop if already connected.
2016-03-14 01:47:43 +01:00
if (mqtt->connected()) {
2016-03-11 01:31:03 +01:00
return 0;
}
uint8_t retries = 3;
2016-03-14 01:47:43 +01:00
while ((ret = mqtt->connect()) != 0) { // connect will return 0 for connected
SKETCH_DEBUG_PRINTLN(mqtt->connectErrorString(ret));
SKETCH_DEBUG_PRINTLN("Retrying MQTT connection ...");
2016-03-14 01:47:43 +01:00
mqtt->disconnect();
2016-03-11 01:31:03 +01:00
delay(100); // wait
retries--;
if (retries == 0) {
return -1;
}
}
return 0;
}
2016-03-22 20:01:05 +01:00
template<typename T> int MqttPublish(Adafruit_MQTT_Publish *publisher, T value){
2016-11-20 00:23:16 +01:00
if (MqttConnect() == 0) {
publisher->publish(value);
return 0;
2016-03-22 20:01:05 +01:00
}
return -1;
2016-03-22 20:01:05 +01:00
}
int MqttPublishBMP180(double temp, double pressure) {
return MqttPublish(mqtt_temp, temp) + MqttPublish(mqtt_pressure, pressure);
2016-06-04 18:45:11 +02:00
}
int MqttPublishIP(const String &ip) {
return MqttPublish(mqtt_ip, ip.c_str());
}
int MqttPublishDHT(float temp, float humidity) {
return MqttPublish(mqtt_dht_temp, temp) + MqttPublish(mqtt_dht_humidity, humidity);
2016-04-07 02:04:38 +02:00
}
2016-11-20 18:08:15 +01:00
int MqttPublishGPIO(){
if (MqttConnect() == 0){
uint i;
for (i = 0; i < NB_ELEMENTS(gpioSensors); i++) {
gpioSensorsMqtt[i]->publish(gpioSensors[i]->lastMeasure);
}
return 0;
}
return -1;
}
2016-09-28 14:08:43 +02:00
int getGpioFromSubscription(Adafruit_MQTT_Subscribe *subscription, const char *pattern) {
char *temp = strstr(subscription->topic, pattern);
if (!temp)
2016-03-22 20:01:05 +01:00
return -1;
2016-09-28 14:08:43 +02:00
String gpioStr(temp + strlen(pattern));
2016-03-22 20:01:05 +01:00
int idx = gpioStr.indexOf("/");
2016-03-23 00:34:50 +01:00
int gpio = gpioStr.substring(0, idx).toInt();
if (gpio >= 0 && gpio < 32 )
2016-03-22 20:01:05 +01:00
return gpio;
else
return -1;
}
void MqttNofity(int gpio, int value){
2016-09-28 14:08:43 +02:00
int watchIdx = findIndex(gpio, gpioWatched);
if (watchIdx >= 0 && isMqttConfigured) {
2016-09-28 14:08:43 +02:00
mqttGpio[watchIdx]->publish(value);
}
}
void MqttChangeGpioValue(int gpio, int value) {
pinMode(gpio, OUTPUT);
digitalWrite(gpio, value);
MqttNofity(gpio, value);
}
2016-09-28 14:08:43 +02:00
void MqttChangePWMValue(int gpio, int value) {
analogWrite(gpio, value);
MqttNofity(gpio, value);
2016-03-22 20:01:05 +01:00
}
void MqttCheckSubscription() {
if (MqttConnect() == 0) {
2016-03-22 20:01:05 +01:00
Adafruit_MQTT_Subscribe *subscription;
2016-04-10 00:37:41 +02:00
while ((subscription = mqtt->readSubscription(0))) {
2016-09-28 14:08:43 +02:00
int gpio = getGpioFromSubscription(subscription, "/gpio/");
if (gpio > 0 && findIndex(gpio, gpioWatched) >= 0) {
SKETCH_DEBUG_PRINTF("Got Subscription for GPIO %d\n", gpio);
2016-03-22 20:01:05 +01:00
char *value = (char *) subscription->lastread;
SKETCH_DEBUG_PRINTF("Receive data: %s\n", value);
MqttChangeGpioValue(gpio, atoi(value));
2016-03-22 20:01:05 +01:00
}
2016-09-28 14:08:43 +02:00
gpio = getGpioFromSubscription(subscription, "/pwm/");
if (gpio > 0 && findIndex(gpio, pwmWatched) >= 0) {
SKETCH_DEBUG_PRINTF("Got Subscription for PWM %d\n", gpio);
char *value = (char *) subscription->lastread;
SKETCH_DEBUG_PRINTF("Receive data: %s\n", value);
MqttChangePWMValue(gpio, atoi(value));
}
2016-03-22 20:01:05 +01:00
}
}
}
2016-10-28 18:04:30 +02:00
#endif