Weather station middleware

In this post we are describing a  middleware communicating with a USB weather station and transferring the information to the cloud. Applications of the specific project can be found in many fields, such as remote weather monitoring, surveillance systems, smart home or any Internet of Thing integration. Due to the protocols simplicity any sensor or system capable to access the web server can post weather data into our server.

wsThe middleware communicates with WH3081 or WH3080 like Weather Station, through the USB port, and acquires the stored weather data. After processing the received measurements the information passed to a simple bash script that posts the data to a webserver. Data are posted using a REST API and on the other side, a PHP code running on the server is responsible to validate and store the information in the database.  Finally, information can be accessed from anywhere, either using a plot library or acquired the raw measurements.

The driver application is written in C and is responsible to communicate with the USB interface and decode the weather data according to WH308x protocol:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include "hidapi.h"
#include <time.h>
#include <unistd.h>

using namespace std;

float intTemp = 0;
float extTemp = 0;
float intHum = 0;
float extHum = 0;
float windSpeed = 0;
float windDir = 0;
float windGust = 0;
float pressure = 0;
float rain = 0;
float light = 0;
float uv = 0;

void parseWeatherData(unsigned char* buffer){

	if (buffer[15] & 0x40){
		printf("Error communicating with weather station\n");		
		return;
	}

	intHum = buffer[1];
	intTemp = (short int)(buffer[2] + buffer[3] * 256) / 10.0;
	extHum = buffer[4];
	extTemp = (short int)(buffer[5] + buffer[6] * 256) / 10.0;
	pressure = (buffer[7] + buffer[8] * 256) / 10.0;
	windSpeed = 3.6 * buffer[9] / 10.0;
	windGust = 3.6 * buffer[10] / 10.0;
	windDir = buffer[12] * 22.5;
	rain = buffer[13]* 0.33;
	if (buffer[16] != 0xFF && buffer[17] != 0xFF && buffer[18] != 0xFF)
		light = (buffer[16] + buffer[17] * 256 + buffer[18] * 65536) / 10.0;
	else
		light = 0;
	uv = buffer[19];

//	printf("Inside Temperature  %3.2f C\n"
//               "Outside Temperature %3.2f C\n"
//               "Inside Humidity     %3.2f %\n"
//               "Ouside Humidity     %3.2f %\n"
//               "Wind Speed          %3.2f Km/h\n"
//               "Wind Direction      %3.2f\n"
//               "Wind Gust           %3.2f Km/h\n"
//               "Atm. Pressure       %3.2f kPa\n"
//               "Cum. Rain           %3.2f mm\n"
//               "Light intesity      %3.2f Lux\n",
//		intTemp,extTemp,intHum,extHum,windSpeed,windDir,windGust,pressure,rain,light);
        printf("ws1=%3.2f&"
               "ws2=%3.2f&"
               "ws3=%3.2f&"
               "ws4=%3.2f&"
               "ws5=%3.2f&"
               "ws6=%3.2f&"
               "ws7=%3.2f&"
               "ws8=%3.2f&"
               "ws9=%3.2f&"
               "ws0=%3.2f",
                intTemp,extTemp,intHum,extHum,windSpeed,windDir,windGust,pressure,rain,light);

}

int readAddress(hid_device *handle, unsigned short int address, unsigned char* buffer){
int cnt = 0;

	buffer[0] = 0xA1;
	buffer[1] = address / 256;
	buffer[2] = (address % 256 );
	buffer[3] = 0x20;
	buffer[4] = 0xA1;
	buffer[5] = address / 256;
	buffer[6] = (address % 256 );
	buffer[7] = 0x20;
	buffer[8] = 0x00;

	if (hid_write(handle, buffer, 8) < 0){
		printf("Error writting hid\n");	
		return -1;
	}	

	cnt =+ hid_read_timeout(handle, &buffer[0], 8, 200);
	cnt =+ hid_read_timeout(handle, &buffer[8], 8, 200);
	cnt =+ hid_read_timeout(handle, &buffer[16], 8, 200);
	cnt =+ hid_read_timeout(handle, &buffer[24], 8, 200);
#ifdef DEBUG
	printf("%4.0d: %2.2X %2.2X %2.2X %2.2X - %2.2X %2.2X %2.2X %2.2X \n", 
		address, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]);
	printf("%4.0d: %2.2X %2.2X %2.2X %2.2X - %2.2X %2.2X %2.2X %2.2X \n", 
		address, buffer[8], buffer[9], buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], buffer[15]);
	printf("%4.0d: %2.2X %2.2X %2.2X %2.2X - %2.2X %2.2X %2.2X %2.2X \n", 
		address, buffer[16], buffer[17], buffer[18], buffer[19], buffer[20], buffer[21], buffer[22], buffer[23]);
	printf("%4.0d: %2.2X %2.2X %2.2X %2.2X - %2.2X %2.2X %2.2X %2.2X \n", 
		address, buffer[24], buffer[25], buffer[26], buffer[27], buffer[28], buffer[29], buffer[30], buffer[31]);
#endif
	return cnt;
}

int main(int argc, char *argv[]){

hid_device *handle;
unsigned char buffer[64];
unsigned int offset, updCount, lastAddress;
int i;

	updCount = 0;

	handle = hid_open(0x1941, 0x8021, NULL);
	if (handle <= 0){
		printf("Error opening HID device\n");
		hid_close(handle);
		return 1;
	}

	hid_set_nonblocking(handle, 0);

	if (readAddress(handle, 0, buffer) < 0){
		hid_close(handle);
		printf("Error reading HID device\n");
		return 1;
	}
	
	if (buffer[0] != 0x55 || buffer[1] != 0xAA || buffer[2] != 0xFF || buffer[3] != 0xFF){
		printf("Error reading data header %X %X %X %X\n", 
                        buffer[0], buffer[1], buffer[2], buffer[3]);
		return 1;
	}
		
	lastAddress = buffer[31] * 256 + buffer[30];
//	printf ("Weather address: %X\n", lastAddress);

	readAddress(handle, lastAddress, buffer);

	parseWeatherData(buffer);

	hid_close(handle);

	return 0;

}

Then a simple bash script can used to POST the data to web sever:

#!/bin/bash
# Update Weather data on server

MY_SERVER="www.test.gr"

###########################################################

#Weather address: 7248
#Inside Temperature  31.70 C
#Outside Temperature 29.30 C
#Inside Humidity     32.00 %
#Ouside Humidity     41.00 %
#Wind Speed          5.80 Km/h
#Wind Direction      270.00
#Wind Gust           7.80 Km/h
#Atm. Pressure       1009.00 kPa
#Cum. Rain           0.00 mm
#Light intesity      105082.50 Lux

res=$(/home/user/./ws-weather)

# Update DB
wsr=`curl -X POST -H "User-Agent: Mozilla/5.0" -H "Accept: text/html" -H "Content-Type: text/html" --connect-timeout 3 ${MY_SERVER}/UpdateWeather.php?${res}`

echo $wsr

On the server side, the appropriate page should exist in order to receive the REST request:

&lt;?php
$url = $_SERVER['QUERY_STRING'];
$servername = "localhost";
$username = "my_username";
$password = "my_password";
$dbname = "my_db";

	
	function updWeather() {
	
	   parse_str($GLOBALS['url']);

	   if ($ws1 != '' &amp;&amp; $ws2 != '' &amp;&amp; $ws3 != '' &amp;&amp; $ws4 != '' &amp;&amp; $ws5 != '' &amp;&amp; 
	       $ws6 != '' &amp;&amp; $ws7 != '' &amp;&amp; $ws8 != '' &amp;&amp; $ws9 != '' &amp;&amp; $ws0 != '') {
	              
	       mysqli_query( $GLOBALS['conn'], "INSERT INTO `weather` (`in_temp`, `out_temp`, `in_hum`, `out_hum`, `wind_speed`, `wind_dir`, `wind_gust`, `pressure`, `rain`, `light`) VALUES ('$ws1', '$ws2', '$ws3', '$ws4', '$ws5', '$ws6', '$ws7', '$ws8', '$ws9', '$ws0')");
	      
	   }
	}


	// Create connection
	$conn = mysqli_connect($servername, $username, $password, $dbname);
	   
	// Check connection
	if (!$conn) {
	   die("Connection failed: " . mysqli_connect_error()); 
	}
	
	updWeather();
	
	$conn-&gt;close();
?&gt;

The complete source code can be found under the following GitHub repository: https://github.com/johnkok/weather_station