diff --git a/Makefile b/Makefile index 94122ee..0340402 100755 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ all: wh1080_rf -wh1080_rf: wh1080_rf.o bcm2835.o bmp085.o wunderground.o - $(CC) -lm wh1080_rf.o bcm2835.o bmp085.o wunderground.o -o wh1080_rf +wh1080_rf: wh1080_rf.o bcm2835.o bmp085.o wunderground.o mqtt.o + $(CC) -lm -lconfig -lmosquitto wh1080_rf.o bcm2835.o bmp085.o wunderground.o mqtt.o -o wh1080_rf wh1080_rf.o: wh1080_rf.c $(CC) $(CFLAGS) wh1080_rf.c @@ -18,5 +18,8 @@ wunderground.o: wunderground.c $(CC) $(CFLAGS) wunderground.c +mqtt.o: mqtt.c + $(CC) $(CFLAGS) mqtt.c + clean: - rm -f wh1080_rf.o bcm2835.o bmp085.o wunderground.o wh1080_rf + rm -f wh1080_rf.o bcm2835.o bmp085.o wunderground.o mqtt.o wh1080_rf diff --git a/mqtt.c b/mqtt.c new file mode 100644 index 0000000..e92b201 --- /dev/null +++ b/mqtt.c @@ -0,0 +1,77 @@ +/* Publish observations to a MQTT topic +*/ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +struct mosquitto *mosq = NULL; +char * publish_topic = NULL; + +bool MQTT_init(const char * hostname, int port, const char * username, const char * password, const char * topic) { + mosquitto_lib_init(); + mosq = mosquitto_new (NULL, true, NULL); + if (!mosq) { + fprintf (stderr, "Can't initialize Mosquitto library\n"); + return false; + } + if (username && password) { + mosquitto_username_pw_set (mosq, username, password); + } + + int ret = mosquitto_connect (mosq, hostname, port, 0); + if (ret) { + fprintf (stderr, "Can't connect to Mosquitto server\n"); + return false; + } + + publish_topic = strdup(topic); + + return true; +} + +void MQTT_destroy() { + if (mosq) { + mosquitto_disconnect (mosq); + mosquitto_destroy (mosq); + } + if (publish_topic) { + free(publish_topic); + } + mosquitto_lib_cleanup(); +} + +bool MQTT_observation + ( + double TemperatureC, // temperature in C + double Humidity, // as a percentage + double WindAveMs, + double WindGustMs, + char *WindDirection, // string "N", "NNE", "NE", "ENE", "E", etc. + double TotalRainMm, // total since battery change + double PressureHpa // pressure at sea level + ) +{ + char * msg; + int msglen = asprintf(&msg, "{\"temp\": %.1f, \"humidity\": %.1f, \"windAveMs\": %.1f, \"windGustMs\": %.1f, \"windDir\": \"%s\", \"totalRain\": %.f, \"pressure\": %.f}", + TemperatureC, Humidity, WindAveMs, WindGustMs, WindDirection, TotalRainMm, PressureHpa); + if (msglen < 0) { + return false; + } + int ret = mosquitto_publish (mosq, NULL, publish_topic, + msglen, msg, 0, false); + if (ret) + { + fprintf (stderr, "Can't publish to Mosquitto server\n"); + return false; + } + return true; +} + diff --git a/mqtt.h b/mqtt.h new file mode 100644 index 0000000..8a491cd --- /dev/null +++ b/mqtt.h @@ -0,0 +1,22 @@ +/* + */ + +#ifndef _MQTT_H_ +#define _MQTT_H_ + +#include + +extern bool MQTT_init(const char * hostname, int port, const char * username, const char * password, const char * topic); +extern bool MQTT_observation + ( + double TemperatureC, // temperature in C + double Humidity, // as a percentage + double WindAveMs, + double WindGustMs, + char *WindDirection, // string "N", "NNE", "NE", "ENE", "E", etc. + double TotalRainMm, // total since battery change + double PressureHpa // pressure at sea level + ); +extern void MQTT_destroy(); + +#endif diff --git a/wh1080_rf.c b/wh1080_rf.c index 95ef1db..ced35a9 100755 --- a/wh1080_rf.c +++ b/wh1080_rf.c @@ -46,11 +46,13 @@ #include #include #include +#include #include "wh1080_rf.h" #include "bcm2835.h" #include "rfm01.h" #include "wunderground.h" +#include "mqtt.h" uint16_t bw_scale[6] = {BW_67, BW_134, BW_200, BW_270, BW_340, BW_400}; @@ -182,14 +184,55 @@ extern int read_bmp085(float altitude); extern float pressure_hpa; +#define CONFIG_FILE "/etc/wh1080.conf" + int main(int argc, char *argv[]) { //unsigned char bytes2[] = {0xa1,0x82,0x0a,0x59,0x03,0x06,0x00,0x4e,0x06,0xc8}; //calculate_values(bytes2); //return -1; + // Read configuration file + config_t cfg; + config_setting_t *mqtt_setting; + const char *mqtt_host; + int mqtt_port; + const char * mqtt_topic; + const char * mqtt_user; + const char * mqtt_pass; + + config_init(&cfg); + if (!config_read_file(&cfg, CONFIG_FILE)) { + fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), + config_error_line(&cfg), config_error_text(&cfg)); + config_destroy(&cfg); + exit(-1); + } + + mqtt_setting = config_lookup(&cfg, "mqtt"); + if (!mqtt_setting) { + printf("Required settings for MQTT not found.\n"); + config_destroy(&cfg); + exit(-1); + } + if (!(config_setting_lookup_string(mqtt_setting, "host", &mqtt_host) && + config_setting_lookup_int(mqtt_setting, "port", &mqtt_port) && + config_setting_lookup_string(mqtt_setting, "topic", &mqtt_topic))) { + printf("MQTT requires host, port and topic.\n"); + config_destroy(&cfg); + exit(-1); + } + if (!config_setting_lookup_string(mqtt_setting, "user", &mqtt_user)) { + mqtt_user = NULL; + } + if (!config_setting_lookup_string(mqtt_setting, "pass", &mqtt_pass)) { + mqtt_pass = NULL; + } // initialize weather underground module WUnderground_Init(); + if (!MQTT_init(mqtt_host, mqtt_port, mqtt_user, mqtt_pass, mqtt_topic)) { + exit(-1); + } uint8_t packet_sig = 0xfa; @@ -463,6 +506,7 @@ // Currenty unreachable close(fd); + config_destroy(&cfg); unmap_peripheral(&gpio); unmap_peripheral(&timer_arm); @@ -504,6 +548,9 @@ // submit observation to weather underground WUnderground_Observation(temperature, humidity, wind_avg_mph, wind_gust_mph, direction_str, rain, pressure_hpa); + + // publish to MQTT + MQTT_observation(temperature, humidity, wind_avg_ms, wind_gust_ms, direction_str, rain, pressure_hpa); } /* diff --git a/wunderground.c b/wunderground.c index 9910780..59125d3 100644 --- a/wunderground.c +++ b/wunderground.c @@ -296,7 +296,7 @@ // get amount of rain in last hour in mm double RainLastHour = GetHourlyRainTotal(TotalRainMm); - sprintf(Cmd, "wget -b \"%s?action=updateraw&ID=%s&PASSWORD=%s&realtime=1&rtfreq=48&dateutc=%s&tempf=%.1f&humidity=%.2f&windspeedmph=%.2f&windgustmph=%.2f&baromin=%.4f&dewptf=%.1f&winddir=%.1f&dailyrainin=%.4f&rainin=%.4f\"", + sprintf(Cmd, "wget -b --quiet -o /dev/null \"%s?action=updateraw&ID=%s&PASSWORD=%s&realtime=1&rtfreq=48&dateutc=%s&tempf=%.1f&humidity=%.2f&windspeedmph=%.2f&windgustmph=%.2f&baromin=%.4f&dewptf=%.1f&winddir=%.1f&dailyrainin=%.4f&rainin=%.4f\"", WUURL, gStationId, gPassword,