diff --git a/Makefile b/Makefile
index 62130ec..ef954d8 100755
--- a/Makefile
+++ b/Makefile
@@ -3,8 +3,8 @@
all: 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: wh1080_rf.o bcm2835.o bmp280.o wunderground.o mqtt.o
+ $(CC) -lm -lconfig -lmosquitto wh1080_rf.o bcm2835.o bmp280.o wunderground.o mqtt.o -o wh1080_rf
wh1080_rf.o: wh1080_rf.c
$(CC) $(CFLAGS) wh1080_rf.c
@@ -12,8 +12,8 @@
bcm2835.o: bcm2835.c
$(CC) $(CFLAGS) bcm2835.c
-bmp085.o: bmp085.c
- $(CC) $(CFLAGS) bmp085.c
+bmp280.o: bmp280.c
+ $(CC) $(CFLAGS) bmp280.c
wunderground.o: wunderground.c
$(CC) $(CFLAGS) wunderground.c
@@ -22,7 +22,7 @@
$(CC) $(CFLAGS) mqtt.c
clean:
- rm -f wh1080_rf.o bcm2835.o bmp085.o wunderground.o mqtt.o wh1080_rf
+ rm -f wh1080_rf.o bcm2835.o bmp280.o wunderground.o mqtt.o wh1080_rf
install: wh1080_rf
install wh1080_rf /usr/local/sbin/wh1080_rf
diff --git a/bmp085.c b/bmp085.c
deleted file mode 100755
index 384a5ee..0000000
--- a/bmp085.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * pcf8563_i2c_rtc.c - example of accessing a PCF8563 via the BSC0 (I2C) peripheral on a BCM2835 (Raspberry Pi)
- *
- * Copyright 2012 Kevin Sangeelee.
- * Released as GPLv2, see
- *
- * This is intended as an example of using Raspberry Pi hardware registers to drive an RTC chip. Use at your own risk or
- * not at all. As far as possible, I've omitted anything that doesn't relate to the RTC or the Raspi registers. There are more
- * conventional ways of doing this using kernel drivers, though these are harder to follow.
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "bcm2835.h"
-
-
-////////////////
-// main()
-////////////////
-
-char eeprom[22] = { 0, 0, };
-short ac1, ac2, ac3, b1, b2, mb, mc, md;
-unsigned short ac4, ac5, ac6;
-
-float temperature_deg_c;
-float pressure_hpa;
-
-int read_bmp085(float altitude) {
-
- if(map_peripheral(&gpio) == -1) {
- printf("Failed to map the physical GPIO registers into the virtual memory space.\n");
- return -1;
- }
- //if(map_peripheral(&bsc0) == -1) {
- if(map_peripheral(&bsc1) == -1) {
- printf("Failed to map the physical BSC1 (I2C) registers into the virtual memory space.\n");
- return -1;
- }
-
- /* BSC0 is on GPIO 0 & 1 */
- *gpio.addr &= ~0x3f; // Mask out bits 0-5 of FSEL0 (i.e. force to zero)
- *gpio.addr |= 0x24; // Set bits 0-5 of FSEL0 to binary '100100'
-
- // Read eeprom data if the array is empty
- // I2C Device Address 0x77 (hardwired into the chip, 0xEE & 0xEF)
- if((unsigned short)*eeprom == 0) {
-
- // Device 0x77, register 0xaa, read into buf, 22 bytes
- i2c_read(0x77, 0xaa, eeprom, 22);
-
- ac1 = (short)eeprom[0] << 8 | eeprom[1];
- ac2 = (short)eeprom[2] << 8 | eeprom[3];
- ac3 = (short)eeprom[4] << 8 | eeprom[5];
- ac4 = (unsigned short)eeprom[6] << 8 | eeprom[7];
- ac5 = (unsigned short)eeprom[8] << 8 | eeprom[9];
- ac6 = (unsigned short)eeprom[10] << 8 | eeprom[11];
- b1 = (short)eeprom[12] << 8 | eeprom[13];
- b2 = (short)eeprom[14] << 8 | eeprom[15];
- mb = (short)eeprom[16] << 8 | eeprom[17];
- mc = (short)eeprom[18] << 8 | eeprom[19];
- md = (short)eeprom[20] << 8 | eeprom[21];
-
- // Test values
- //ac1 = 408, ac2 = -72, ac3 = -14383, ac4 = 32741, ac5 = 32757, ac6 = 23153;
- //b1 = 6190, b2 = 4, mb = -32768, mc = -8711, md = 2868;
- // Also include 'ut = 27898' , 'up = 23843', and 'oss = 0'
- //printf("%d %d %d %d %d %d\n", ac1, ac2, ac3, ac4, ac5, ac6);
- //printf("%d %d %d %d %d\n", b1, b2, mb, mc, md);
- }
-
-
- char ut_buf[2];
- char up_buf[2];
-
- char cmd_ut = 0x2e;
- char cmd_up[] = {0x34, 0x74, 0xb4, 0xf4};
- int oss_delay[] = {4500, 7500, 13500, 25500};
- int oss = 1; // This is an index into the above array
-
- /*
- * Get Uncompensated Temperature from BMP085
- */
- i2c_write(0x77, 0xf4, &cmd_ut, 1);
- usleep(4500); // just wait the maximum possible time for conversion
- i2c_read(0x77, 0xf6, ut_buf, 2);
-
- long ut = (long)ut_buf[0] << 8 | ut_buf[1];
-
- // Temperature compensation algorithm (derived from datasheet)
- long x1 = ((ut - ac6) * ac5) >> 15;
- long x2 = (mc * (1 << 11)) / (x1 + md);
- long b5 = x1 + x2;
- long t = (b5 + 8) >> 4;
-
- temperature_deg_c = (float)t / 10;
- printf("Temperature: %0.1fC\n", temperature_deg_c);
-
- int idx;
- float p0 = 0;
-
- for(idx=0; idx < 2; idx++) {
- /*
- * Get Uncompensated Pressure from BMP085, based on the OverSampling Setting
- * of (0, 1, 2, or 3). This determines accuracy, conversion delay, and power consumption.
- */
- i2c_write(0x77, 0xf4, &cmd_up[oss], 1);
- usleep(oss_delay[oss]); // wait according to the chosen oss mode
- i2c_read(0x77, 0xf6, up_buf, 3);
-
- long up = (((long)up_buf[0] << 16) | ((long)up_buf[1] << 8) | up_buf[2]) >> (8 - oss);
-
- // Pressure compensation algorithm (derived from datasheet)
- long b6 = b5 - 4000;
- x1 = (b2 * (b6 * b6 >> 12)) >> 11;
- x2 = ac2 * b6 >> 11;
- long x3 = x1 + x2;
- long b3 = (((ac1 * 4 + x3) << oss) + 2) >> 2;
- x1 = ac3 * b6 >> 13;
- x2 = (b1 * (b6 * b6 >> 12)) >> 16;
- x3 = ((x1 + x2) + 2) >> 2;
- unsigned long b4 = ac4 * (unsigned long)(x3 + 32768) >>15;
- unsigned long b7 = ((unsigned long)up - b3) * (50000 >> oss);
- long p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
- x1 = (p >> 8) * (p >> 8);
- x1 = (x1 * 3038) >> 16;
- x2 = (-7357 * p) >> 16;
- p = p + (x1 + x2 + 3791) / 16;
-
- p0 += (float)p / powf(1.0f - (altitude / 44330), 5.255f);
-
- usleep(100000);
- }
- p0 /= 2;
- pressure_hpa = p0 / 100;
- printf("Pressure p0 (sea level): %0.1f hPa\n", pressure_hpa);
-
- unmap_peripheral(&gpio);
- unmap_peripheral(&bsc0);
-
- return 0;
-}
diff --git a/bmp280.c b/bmp280.c
new file mode 100755
index 0000000..399f13b
--- /dev/null
+++ b/bmp280.c
@@ -0,0 +1,18 @@
+#include
+#include
+#include
+
+float pressure_hpa;
+
+int read_bmp280(float altitude) {
+ FILE * fp;
+ float station_pressure, sea_level_pressure;
+ fp = fopen("/sys/bus/iio/devices/iio:device0/in_pressure_input", "r");
+ fscanf(fp, "%f", &station_pressure);
+ fclose(fp);
+ sea_level_pressure = station_pressure / powf(1.0f - (altitude / 44330), 5.255f);
+ printf("Sea level pressure: %.4f\n", sea_level_pressure);
+ pressure_hpa = sea_level_pressure * 10;
+
+ return 0;
+}
diff --git a/mqtt.c b/mqtt.c
index 92b71bb..8b39b08 100644
--- a/mqtt.c
+++ b/mqtt.c
@@ -60,7 +60,7 @@
)
{
char * msg;
- int msglen = asprintf(&msg, "{\"temp\": %.1f, \"humidity\": %.1f, \"windAveMs\": %.1f, \"windGustMs\": %.1f, \"windDir\": \"%s\", \"totalRain\": %.f, \"pressure\": %.f}",
+ int msglen = asprintf(&msg, "{\"temp\": %.1f, \"humidity\": %.1f, \"windAveMs\": %.1f, \"windGustMs\": %.1f, \"windDir\": \"%s\", \"totalRain\": %.f, \"pressure\": %.1f}",
TemperatureC, Humidity, WindAveMs, WindGustMs, WindDirection, TotalRainMm, PressureHpa);
if (msglen < 0) {
return false;
diff --git a/wh1080_rf.c b/wh1080_rf.c
index ced35a9..5a9f7dc 100755
--- a/wh1080_rf.c
+++ b/wh1080_rf.c
@@ -181,7 +181,7 @@
}
// pressure function and value
-extern int read_bmp085(float altitude);
+extern int read_bmp280(float altitude);
extern float pressure_hpa;
#define CONFIG_FILE "/etc/wh1080.conf"
@@ -192,46 +192,75 @@
//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;
+ // Read configuration file
+ config_t cfg;
+ config_setting_t *mqtt_settings, *bmp280_settings, *wu_settings;
+ const char *mqtt_host;
+ int mqtt_port;
+ const char *mqtt_topic;
+ const char *mqtt_user;
+ const char *mqtt_pass;
+ double altitude;
+ const char *wu_stationId, *wu_password;
- 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);
- }
+ 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);
+ // BMP280 options
+ bmp280_settings = config_lookup(&cfg, "bmp280");
+ if (!bmp280_settings) {
+ printf("No settings for BMP280 pressure sensor, disabling.\n");
+ } else {
+ if (!config_setting_lookup_float(bmp280_settings, "altitude", &altitude)) {
+ printf("No alititude provided, setting to 0 metres above sea level.\n");
+ altitude = 0.0f;
+ }
+ }
+
+ // MQTT options
+ mqtt_settings = config_lookup(&cfg, "mqtt");
+ if (!mqtt_settings) {
+ printf("No settings for MQTT found, disabling.\n");
+ } else {
+ if (!(config_setting_lookup_string(mqtt_settings, "host", &mqtt_host) &&
+ config_setting_lookup_int(mqtt_settings, "port", &mqtt_port) &&
+ config_setting_lookup_string(mqtt_settings, "topic", &mqtt_topic))) {
+ printf("MQTT requires host, port and topic.\n");
+ config_destroy(&cfg);
+ exit(-1);
+ }
+ if (!config_setting_lookup_string(mqtt_settings, "user", &mqtt_user)) {
+ mqtt_user = NULL;
+ }
+ if (!config_setting_lookup_string(mqtt_settings, "pass", &mqtt_pass)) {
+ mqtt_pass = NULL;
+ }
+ // Attempt to initialize MQTT as a client
+ if (!MQTT_init(mqtt_host, mqtt_port, mqtt_user, mqtt_pass, mqtt_topic)) {
+ printf("Unable to initialize MQTT.\n");
+ config_destroy(&cfg);
+ exit(-1);
+ }
+ }
+
+ // WUnderground options
+ wu_settings = config_lookup(&cfg, "wunderground");;
+ if (!wu_settings) {
+ printf("No settings for WUnderground found, disabling.\n");
+ } else {
+ if (!(config_setting_lookup_string(wu_settings, "station", &wu_stationId) &&
+ config_setting_lookup_string(wu_settings, "password", &wu_password))) {
+ printf("WUnderground requires station ID and password.\n");
+ config_destroy(&cfg);
+ exit(-1);
+ }
+ // initialize weather underground module
+ WUnderground_Init(wu_stationId, wu_password);
}
uint8_t packet_sig = 0xfa;
@@ -474,11 +503,11 @@
// at this point, we can do other stuff that requires the RT scheduler
- #ifdef USE_BMP085
- read_bmp085(ALTITUDE_M); // read pressure, calculate for the given altitude
- #endif
+ if (bmp280_settings) {
+ read_bmp280(altitude); // read pressure, calculate for the given altitude
+ }
- calculate_values(bytes, pressure_hpa);
+ calculate_values(bytes, pressure_hpa, (wu_settings != NULL), (mqtt_settings != NULL));
// Wait for remainder of 47 seconds in standard scheduler until we can expect the next read
scheduler_standard();
@@ -495,7 +524,6 @@
}
count = 0;
-
// LED off
*(gpio.addr + (0x28 >> 2)) = 1 << 22;
}
@@ -507,6 +535,7 @@
// Currenty unreachable
close(fd);
config_destroy(&cfg);
+ // Todo: clean up MQTT, WUnderground
unmap_peripheral(&gpio);
unmap_peripheral(&timer_arm);
@@ -516,7 +545,7 @@
char *direction_name[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
-void calculate_values(unsigned char *buf, float pressure_hpa) {
+void calculate_values(unsigned char *buf, float pressure_hpa, bool send_wu, bool send_mqtt) {
unsigned short device_id = ((unsigned short)buf[0] << 4) | (buf[1] >> 4);
unsigned short temperature_raw = (((unsigned short)buf[1] & 0x0f) << 8) | buf[2];
@@ -544,13 +573,18 @@
printf("Wind speed: %0.2f m/s, Gust Speed %0.2f m/s, %s\n", wind_avg_ms, wind_gust_ms, direction_str);
printf("Wind speed: %0.1f mph, Gust Speed %0.1f mph, %s\n", wind_avg_mph, wind_gust_mph, direction_str);
printf("Total rain: %0.1f mm\n", rain);
- printf("Pressure (sea level): %0.1f hpa\n", pressure_hpa);
+ printf("Pressure (sea level): %0.1f hpa\n", pressure_hpa);
- // submit observation to weather underground
- WUnderground_Observation(temperature, humidity, wind_avg_mph, wind_gust_mph, direction_str, rain, pressure_hpa);
+ if (send_wu) {
+ // 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);
+ if (send_mqtt) {
+ // publish to MQTT
+ MQTT_observation(temperature, humidity, wind_avg_ms, wind_gust_ms, direction_str, rain, pressure_hpa);
+ }
}
/*
diff --git a/wh1080_rf.h b/wh1080_rf.h
index 3371cff..4f0303d 100755
--- a/wh1080_rf.h
+++ b/wh1080_rf.h
@@ -1,8 +1,7 @@
+#define _GNU_SOURCE
-//#define USE_BMP085
-//#define ALTITUDE_M 210.0f
-#define ALTITUDE_M 6.0f
+#include
void scheduler_realtime();
void scheduler_standard();
-void calculate_values(unsigned char *buf, float pressure_hpa);
+void calculate_values(unsigned char *buf, float pressure_hpa, bool send_wu, bool send_mqtt);
diff --git a/wunderground.c b/wunderground.c
index 59125d3..695d911 100644
--- a/wunderground.c
+++ b/wunderground.c
@@ -25,16 +25,9 @@
#include
#include "wunderground.h"
-// file that contains weather underground station ID (first line) and
-// password (second line)
-#define CREDENTIALS "/etc/wunderground/creds.txt"
-
// API url
#define WUURL "http://rtupdate.wunderground.com/weatherstation/updateweatherstation.php"
-// maximum lengths of station id and password
-#define STATIONIDLENGTH 50
-#define PASSWORDLENGTH 50
// maximum command length
#define CMDLENGTH 1024
@@ -55,9 +48,7 @@
#define PI 3.14159265359
// module variables
-static char gStationId[STATIONIDLENGTH];
-static char gPassword[PASSWORDLENGTH];
-
+char *gStationId, *gPassword;
static int CurrentDay = -1;
static double RainatStartofDay = 0.0;
@@ -192,19 +183,14 @@
// initializes the module
void WUnderground_Init
(
- void
+ const char *stationId,
+ const char *password
)
{
int i;
- // read in credentials
- FILE *fp = fopen(CREDENTIALS, "r");
- fgets(gStationId, STATIONIDLENGTH, fp);
- strtok(gStationId, "\n");
- fgets(gPassword, PASSWORDLENGTH, fp);
- strtok(gPassword, "\n");
- fclose(fp);
-
+ gStationId = strdup(stationId);
+ gPassword = strdup(password);
// no rain data
for (i = 0; i < SAMPLESPERHOUR; i++) RainSamples[i] = 0.0;
// no wind vectors
@@ -215,6 +201,15 @@
}
}
+void WUnderground_Destroy() {
+ if (gStationId) {
+ free(gStationId);
+ }
+ if (gPassword) {
+ free(gPassword);
+ }
+}
+
// submits an observation
void WUnderground_Observation
(
diff --git a/wunderground.h b/wunderground.h
index f8971af..46476db 100644
--- a/wunderground.h
+++ b/wunderground.h
@@ -8,7 +8,8 @@
// initializes the module
extern void WUnderground_Init
(
- void
+ const char *stationId,
+ const char *password
);
// submits an observation