OurWeather REST Interface to the Raspberry Pi Released
SwitchDoc Labs has now released a Python program (for the OurWeather REST Interface) that reads the OurWeather Weather Station and stores the data from the weather station in a MySQL database. It does this by making use of the REST interface of the OurWeather Weather Kit.
What is OurWeather?
OurWeather is an ESP8266 based connected weather station containing 7 different sensors that will teach about electronics, software and the weather. It contains all the sensors and wires to make a fully functional, WiFi weather station. No software programming is required, it works right out of the box. However, if you want to change the way OurWeather works, add your own software or do something entirely different, we have the Open Source software available. And what is one of the coolest features of OurWeather? Building the kit requires NO SOLDERING. It uses Grove Connectors. It is all plug and play based building, with a full step-by-step photograph based instruction manual. It is a safe and educational way to learn about weather, electronics and science topics. You can watch our successful kickstarter video here: https://youtu.be/pw6hSNSQnsM
See the Grove Connector Tutorial Here.
What is the REST Interface For OurWeather?
The OurWeather / WeatherPlus Advanced Usage Manual is now available for download on the OurWeather product page and the WeatherPlus product page.
This manual documents the REST interface present in OurWeather / WeatherPlus and tells how to program the WeatherPlus board using the Arduino IDE.
Example of REST Call
https://192.168.1.118/FullDataString
returns a JSON string:
{"FullDataString": "21.30,36.70,25.63,101714.00,620.44,0.00,0.00,0.00,0.70,0.00,0.00,0.00,0.00,0.00,0.00,0,04/24/2016 11:56:10,SwitchDoc Labs", "id": "1", "name": "OurWeather", "connected": true}
The values in the FullDataString are all in metric.
- Outdoor Temperature
- Outdoor Humidity
- Indoor Temperature
- Barometric Pressure
- Altitude
- Current Wind Speed
- Current Wind Gust
- Current Wind Direction
- Rain Total
- Wind Speed Minimum
- Wind Speed Maximum
- Window Gust Minimum
- Window Gust Maximum
- Wind Direction Minimum
- Wind Direction Maximum
- Is Display English Or Metric
- Current Date/Time on OurWeather
- OurWeather Station Name
- Current Air Quality Sensor Reading
- Current Air Quality Qualitative Reading
SDL_Pi_DataLogger
The DataLogger consists of a Raspberry Pi 3 running the DataLogging Python Software, MySQL, MatPlotLib and an Apache Webserver.
The DataLogging software is available on github.com (SDL_Pi_DataLogger). The DataLogger software, hardware and installation tutorial is here.
Reading from the OurWeather REST Interface from the Raspberry Pi
The code for reading from the OurWeather REST interface is very straight forward on the Raspberry Pi.
The steps are:
1) Set up your URI (URL) call: https://192.168.1.140/FullDataString
2) Read the JSON data from OurWeather using the function “fetchJSONData” shown below
3) Parse the data as shown in the DataLogger example
4) Store it in the MySQL database
5) Analyze the data
Here is the read and database code from SDL_Pi_DataLogger (OURWEATHERFunctions.py):
# set up your OurWeather IP Address here uri = 'https://192.168.1.140/FullDataString' path = '/' # fetch the JSON data from the OurWeather device def fetchJSONData(uri, path): target = urlparse(uri+path) method = 'GET' body = '' h = http.Http() # If you need authentication some example: #if auth: # h.add_credentials(auth.user, auth.password) response, content = h.request( target.geturl(), method, body, headers) # assume that content is a json reply # parse content with the json module data = json.loads(content) return data headers = { 'Accept': 'application/json', 'Content-Type': 'application/json; charset=UTF-8' } def readOURWEATHERData(password): print('readOURWEATHERData - The time is: %s' % datetime.now()) data = fetchJSONData(uri, path) # pre split weather data preSplitData = data['FullDataString'] WData = preSplitData.split(",") print Data if (len(WData) < 18): # we have a bad read # try again later print "bad read from OurWeather" return 0 if (len(WData) == 18): # Version does not have air quality WData.append(0) WData.append(4) # open database con = mdb.connect('localhost', 'root', password, 'DataLogger' ) cur = con.cursor() # # Now put the data in MySQL # # Put record in MySQL print "writing SQLdata "; # write record deviceid = 0 query = 'INSERT INTO '+OURWEATHERtableName+('(timestamp, deviceid, Outdoor_Temperature , Outdoor_Humidity , Indoor_Temperature , Barometric_Pressure , Altitude , Current_Wind_Speed , Current_Wind_Gust , Current_Wind_Direction , Rain_Total , Wind_Speed_Minimum , Wind_Speed_Maximum , Wind_Gust_Minimum , Wind_Gust_Maximum , Wind_Direction_Minimum , Wind_Direction_Maximum , Display_English_Metrice , OurWeather_DateTime , OurWeather_Station_Name , Current_Air_Quality_Sensor , Current_Air_Quality_Qualitative ) VALUES(UTC_TIMESTAMP(), %i, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %.3f, %i, "%s" , "%s", %i, %i)' % ( int(data['id']), float(WData[0]), float(WData[1]), float(WData[2]), float(WData[3]), float(WData[4]), float(WData[5]), float(WData[6]), float(WData[7]), float(WData[8]), float(WData[9]), float(WData[10]), float(WData[11]), float(WData[12]), float(WData[13]), float(WData[14]), int(WData[15]), WData[16], WData[17], int(WData[18]), int(WData[19])) ) print("query=%s" % query) cur.execute(query) con.commit()
Drawing the Temperature and Humidity Graph in DataLogger
Once you have the weather data in a database, you can start to perform analysis on the data. This example uses MatPlotLib.
This graph was taken from our indoor testing OurWeather system inside the lab, so the temperature does not vary much.
Here is the temperature / humidity graphing code from SDL_Pi_DataLogger. The code goes through these four steps:
1) Open MySQL Database
2) Query data from MySQL database, storing in array
3) Build Graph with MatPlotLib
4) Copy resulting graph to /var/www/html to display on webpage
def buildOURWEATHERGraphTemperature(password, myGraphSampleCount): print('buildOURWEATHERGraph - The time is: %s' % datetime.now()) # open database con1 = mdb.connect('localhost', 'root', password, 'DataLogger' ) # now we have to get the data, stuff it in the graph mycursor = con1.cursor() print myGraphSampleCount query = '(SELECT timestamp, deviceid, Outdoor_Temperature, OutDoor_Humidity, OurWeather_Station_Name, id FROM '+OURWEATHERtableName+' ORDER BY id DESC LIMIT '+ str(myGraphSampleCount) + ') ORDER BY id ASC' print "query=", query try: mycursor.execute(query) result = mycursor.fetchall() except: e=sys.exc_info()[0] print "Error: %s" % e t = [] # time u = [] # Outdoor temperature v = [] # Outdoor humidity averageTemperature = 0.0 currentCount = 0 for record in result: t.append(record[0]) u.append(record[2]) v.append(record[3]) averageTemperature = averageTemperature+record[2] currentCount=currentCount+1 StationName = record[4] averageTemperature = averageTemperature/currentCount print ("count of t=",len(t)) fds = dates.date2num(t) # converted # matplotlib date format object hfmt = dates.DateFormatter('%H:%M:%S') #hfmt = dates.DateFormatter('%m/%d-%H') fig = pyplot.figure() fig.set_facecolor('white') ax = fig.add_subplot(111,axisbg = 'white') ax.vlines(fds, -200.0, 1000.0,colors='w') ax2 = fig.add_subplot(111,axisbg = 'white') ax.xaxis.set_major_formatter(hfmt) pyplot.xticks(rotation='45') pyplot.subplots_adjust(bottom=.3) pylab.plot(t, u, color='r',label="Outside Temp (C) ",linestyle="-",marker=".") pylab.xlabel("Time") pylab.ylabel("degrees C") pylab.legend(loc='upper left') pylab.axis([min(t), max(t), -20, 50]) ax2 = pylab.twinx() pylab.ylabel("% ") pylab.plot(t, v, color='b',label="Outside Hum %",linestyle="-",marker=".") pylab.axis([min(t), max(t), 0, 100]) pylab.legend(loc='lower left') pylab.figtext(.5, .05, ("%s Average Temperature %6.2f\n%s") %( StationName, averageTemperature, datetime.now()),fontsize=18,ha='center') pylab.grid(True) pyplot.show() pyplot.savefig("/var/www/html/OURWEATHERDataLoggerGraphTemperature.png", facecolor=fig.get_facecolor()) mycursor.close() con1.close() fig.clf() pyplot.close() pylab.close() gc.collect() print "------OURWEATHERGraphTemperature finished now"
Thanks for all the hard work on this project! I am trying to follow along, and I do believe I have everything installed correctly, and I can see the raw data from my OurWeather device in a browser. I modified the uri in ~/SDL_Pi_DataLogger/OURWEATHERFunctions.py but I don’t believe the database is getting any information. Any suggestions on what to check? Or did I miss a step? I see the database in MySQL and it appears to be built correctly.
Thanks again for such an awesome (and sometimes challenging) project!
Pete,
You have a password wrong or something like that with the MySQL database. One of the problems with running the tasks using apscheduler is that the tasks are run in threads and the exceptions just disappear rather than showing what is wrong. This is something that we need to look into. How to redirect those exceptions to the screen when running in a thread.
Here is what to do. Execute the read functions directly in the main thread:
In DataLogger.py, right after this:
if __name__ == '__main__':
scheduler = BackgroundScheduler()
Add the following statement:
OURWEATHERFunctions.readOURWEATHERData(password)
Execute DataLogger.py and you will see the exception and be able to figure out what is wrong.
Best,
SDL