The Creek: Flood Event Web Page

In the previous post I talked about scanning through the Elkhorn Creek MySql database and finding flood events.  This is a very IO intensive task and as such is slower than crap.  It takes something like 20 seconds on the Raspberry Pi and as such is not very ideal for an interactive application.  So to make this better, I will create code that runs once per minute and then creates the “floods.html” with all a table of all of the floods and links to the charts.  It will also recreate the chart for any flood event that is in the database but doesn’t have a chart.

After the “ProcessEvents” run method has done its thing, there is a table in the database called “floodevents” that will have columns for the start,end and maxdepth of all of the floods.   To make things easy I would like a directory full of PNG files with the charts of the floods.  Each PNG file will contain one flood event and be named by the date of the flood.  To do this I create a function called “createCharts” that will:

  • [Line 71] Iterate through the list of events
  • [Lines ] Create a string that represents the filename
  • [lines] If that filename doesn’t exist (for some reason it was never created or it was deleted) or the flood isn’t over (and the chart needs to be redrawn) then:
  • [Lines 77-88] Create the chart of the flood

After this function has been run, there will be a directory full of charts.  I can then copy this directory to the Tomcat web apps directory

Screen Shot 2016-05-04 at 8.50.28 AM

As long as you know all of the floods, and you have created PNGs of the flood events you might as well also create and cache the HTML of the flood events.  This is simply done in the ProcessEvents object with the method “createHtml”.  This method take a filename  that will be the name of the HTML table file, then creates an HTML table, iterates through each of the events printing one row per flood event.

 

Screen Shot 2016-05-04 at 9.02.50 AM

As always you can get of all this code on the IOT Expert github site.

Index Description
The Creek: IOT for the Elkhorn Creek Introduction
The Creek: Solution Architecture 1.0 Overall architecture
The Creek: Creek Board 1.1 Eagle layout of the board
The Creek: Creek Board 1.0 – RCCA A discussion of the errors in the 1.0 board
The Creek: CYPI, a Raspberry Pi to Arduino Bridge PSoC4 <--> Raspberry Pi Bridge Board
The Creek: PSoC4 Creator Schematic and Firmware Firmware to interface with the temperature and pressure sensors
The Creek: Testing the Firmware Using tools to verify that the PSoC 4 Firmware is working correctly
The Creek: Testing the Bootloader Make sure that you can load new firmware into the PSoC
The Creek: Software Architecture All of the Raspberry Pi software connections
The Creek: Install MySql Instruction to configure MySql
The Creek: Install Tomcat Instruction to configure Tomcat JSP Server
The Creek: Data Collection Java (Part 1) The Java program that reads the I2C and saves it in the database
The Creek: Data Collection Java (Part 2) The Java program that reads the I2C and saves it in the database
The Creek: Create the Chart with JFreeChart Using open source Java charting software to create plots of the Creek Depth
The Creek: Flood Event Data Processor A batch program to create analyze the database and create a table of flood events
The Creek: Flood Event Web Page A batch program to create the flood event web page
The Creek: Creek Server 1.1 Updates to all of the back off server programs to integrate charts
The Creek: JSP Web Page for www.elkhorn-creek.org The JSP program to make the table and display the website
The Creek: Raspberry Pi Clock Stretching Sorting out a bug in the system having to do with the Broadcomm Raspberry Pi Master not functioning well with clock stretching
The Creek: Creek Server 1.2 Caching the web pages to make them faster

 

The Creek: Flood Event Data Processor

In the previous post I talked about using JFreeChart to create a plot of the last 8 hours.  I have never been satisfied with only 8 hours but had never spent the time to fix it.  To make matters worse I also wanted to have a website where I could see a list of the the flood events as well as plots of that data.  Well, this week I am going remedy this annoyance, and while I am at it, I am going to fix a bunch of things that I left hanging.

The Elkhorn Creek can do some crazy things.  Here is a plot that I made while I was working on these changes.  This was a spring flood that lasted 304 hours aka 12.6 days:

2015-03-04-18-35-40

As there are more than 1M records in my database I knew that the Raspberry Pi didn’t have the horsepower to scan the data and create the charts in real time.  The first step was to create a table to hold statistics about the events.  I decided to store a timestamp for the start and end as well as the maximum depth.  Here is the table description:

Screen Shot 2016-04-17 at 8.27.59 AM

The next step was to create a java program called “ProcessEvents.java” that would analyze the raw data in the creekdata table using the “known” events from the floodevents table.  The first thing that I did was create a helper class called StartEnd that hold one record from the floodevents table.  The lowest “id” in the floodevents table is 1 so the 0 default for id represents a record that is not yet in the database.

Screen Shot 2016-04-17 at 8.46.28 AM

The program works by implementing the following algorithm.

  1. Line 52: set a flag that you have not found an event
  2. Line 53: scan the floodevent database
  3. Line 58: If you didn’t find an event or there is an event ongoing (it has a start but no end)
  4. Line 60: If there has never been an event then start scanning for a “start” the creekdatase from the start (all data)
  5. Line 63: If there has been an event, then start scanning for a “start” the creekdata after the end of the current event
  6. Line 66: If you don’t find a “start” then there are no more events (or you didnt find one at all) so stop scanning
  7. Line 71: Now that you have a start, look for an “end”
  8. Line 75: If you found a new event then save it in the database
  9. Line 79: If you are in the middle of an event update the database

Screen Shot 2016-04-17 at 8.49.00 AM

Once all of the events have been found and put into the floodevents database the last step is to look at all of the events and fix the “max” depth column [Line 84]

Screen Shot 2016-04-17 at 9.02.47 AM

The “findStart” function returns a timestamp for the start of the next event.  If it doesn’t find one then it return null.  The function looks through all of the creek data starting from the beginning [line 149] or after a time [line 151].  My program has a little bit of hysteresis in that it “starts” a flood when it get to 2.0 feet and it “ends” a flood when it gets below 0.75 feet.  If there is a little bit of noise around the upper trip point or the lower trip point it won’t turn on/off.

Screen Shot 2016-04-17 at 9.29.35 AM

The “findEnd” function returns a timestamp for the end of the current event.  If it doesn’t find one then it return null.

Screen Shot 2016-04-17 at 9.30.40 AM

The “calcAndInsertMaxDepth” function:

  • Sets up a query to scans all of the events in the floodevents database [line 253]
  • Loop through all of the events [line 259]
  • Foreach event find the maximum depth [line 265]
  • Update the table with the current maximum depth [line 266]

Screen Shot 2016-04-17 at 9.04.39 AM

The “getMaxDepthFunction” function uses a feature of mysql that allows you to perform a function during a query.  In this case it looks for all of the data between a start and end and calculates the “max(depth)”.  This query will return only one resultset.  I get the maximum depth value from the result set using the “rs.getFloat(“max(depth)”)”

Screen Shot 2016-04-17 at 9.05.59 AM

The “depthUpdate” function takes in an “id” of one of the events and a calculated “maxDepth” then updates the “max” field for that id in the floodevents database.

Screen Shot 2016-04-17 at 9.07.06 AM

All of this code is available on the iotexpert github site in the java program “ProcessEvents.java” which is in the “getCreek/src” directory.

In the next post I will talk about all of the modifications to the chart creation program that I made to support creating the flood events charts.

Index Description
The Creek: IOT for the Elkhorn Creek Introduction
The Creek: Solution Architecture 1.0 Overall architecture
The Creek: Creek Board 1.1 Eagle layout of the board
The Creek: Creek Board 1.0 – RCCA A discussion of the errors in the 1.0 board
The Creek: CYPI, a Raspberry Pi to Arduino Bridge PSoC4 <--> Raspberry Pi Bridge Board
The Creek: PSoC4 Creator Schematic and Firmware Firmware to interface with the temperature and pressure sensors
The Creek: Testing the Firmware Using tools to verify that the PSoC 4 Firmware is working correctly
The Creek: Testing the Bootloader Make sure that you can load new firmware into the PSoC
The Creek: Software Architecture All of the Raspberry Pi software connections
The Creek: Install MySql Instruction to configure MySql
The Creek: Install Tomcat Instruction to configure Tomcat JSP Server
The Creek: Data Collection Java (Part 1) The Java program that reads the I2C and saves it in the database
The Creek: Data Collection Java (Part 2) The Java program that reads the I2C and saves it in the database
The Creek: Create the Chart with JFreeChart Using open source Java charting software to create plots of the Creek Depth
The Creek: Flood Event Data Processor A batch program to create analyze the database and create a table of flood events
The Creek: Flood Event Web Page A batch program to create the flood event web page
The Creek: Creek Server 1.1 Updates to all of the back off server programs to integrate charts
The Creek: JSP Web Page for www.elkhorn-creek.org The JSP program to make the table and display the website
The Creek: Raspberry Pi Clock Stretching Sorting out a bug in the system having to do with the Broadcomm Raspberry Pi Master not functioning well with clock stretching
The Creek: Creek Server 1.2 Caching the web pages to make them faster

 

RADIUS + Meraki + Beef Brisket

Last weekend was one of those times I felt like jabbing an icepick in my ear.  My “simple” project of cooking a beef brisket turned into a cascading series of pain.  What do brisket and IOT have to do with each other?  Here is the story:  A beef brisket needs to be smoked for no less than 12-15 hours.  This is a total PITA without some computer help as by far the most important variable in doing this right is the temperature of the Pit.  To solve this, I use the Cyber-Q from BBQ Guru.

CyberQ

This little box has

  1. 4x thermocouple based temperature probes (one for the “pit” and 3 for the BBQ)
  2. A Fan controlled by a PID
  3. WIFI with a build-in web server

This box turns your smoker into an IOT device.  What it really means is that you can pay very little attention to your smoker and it will stay within a few degrees of the target.  Which is awesome.  It can also be attached to your network so that you can monitor it from wherever you are (assuming you are willing to poke a hole in your firewall).

On Saturday I get up at 4:00AM to start the Brisket, but when I plug in the Cyber-Q the damn thing won’t attach to my freaking WIFI network.  With this box, this happens to me approximately 50% of the time.  I start and stop it a half a dozen times with the hope that it will attach, but to no avail which causes me nothing but frustration.  The WIFI at my house is protected using WPA2 Personal and all I can figure is that the Microchip WIFI  chipset in the Cyber-q is flaky but I suppose that it could also be the Meraki AP.

To attempt to fix the problem I decide to create an open WIFI network and attach the Cyber-Q to it.  That works fine, but now I have an open network which is mostly OK since I live out in the country, but it is still annoying.  When I created the new SSID I noticed that Meraki allows for MAC based access control using a RADIUS server.

Screen Shot 2016-07-18 at 8.30.07 AM

That is cool now all I have to do is figure out how to build a RADIUS server.  Actually, I need to start by figuring out what RADIUS server is.

It turns out that RADIUS stands for Remote Authentication Dial In User Server.  The “Dial In” part of the name gives you the hint that it has been around for a long time.   Basically a RADIUS server was built to perform three functions, Authentication, Authorization and Accounting in dial up networks.  When someone dialed in the RADIUS server validated the password, gave them access to the network and then kept track of their usage.  Since the days of dial-up, RADIUS servers have undergone the out of control process of creeping functionality and they now support a frightening number of possible setups.

My fist step in this journey was to look around on the internet and find a suitable RADIUS server.  FreeRadius seems to be the most popular tool around and it runs on my mac server.  When I looked on their website, there was no prebuilt version… go fish.  I started the process of getting Free Radius to build, but when I was looking around for a solution to one of the install problem I found “HomeBrew” which claims to be the missing package manager for Mac.  To install Brew you just need to run

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Screen Shot 2016-07-18 at 10.16.43 AM

After that I can use brew to install FreeRadius using the following command:

brew install freeradius-server

Screen Shot 2016-07-18 at 10.18.56 AM

After running the brew command you will have a built version of FreeRadius in /usr/local/Cellar/freeradius-server/3.0.11

So how does it work?  When a device tries to attach to the network, the Meraki will query the Radius server to see if their is a user/password combination that matches the mac address of the device.  To make this work I just add a username/password to the …/freeradius-server/3.0.11/etc/raddb/users file so that it looks like this:

001ec020425a Cleartext-Password := “001ec020425a”

The “001ec020425a” is just the MAC address of the Cyber-q.

The next step is to tell the Mac OS-X to start the Radius server when it boots.  To do this you need to create  “plist” file with the right stuff in it to make the Launchd start the daemon when the Mac boots.  There is a tutorial on the web here.

The first step is to create a file called org.freeradius.radius-server.plist and put it into the directory /Library/LaunchDaemons.  The file just contains instructions to the launchd to start the radiusd (daemon) when the mac starts.  Here is the file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.freeradius.radius-server</string>
<key>Program</key>
<string>/usr/local/Cellar/freeradius-server/3.0.11/bin/radiusd</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

After that you need to run:

  • sudo launchctl load org.freeradius.radius-server

Then

  • sudo launchtl start org.freeradius.radius-server

Now that I have a radiusd running I need to tell the Meraki about it.  To do that I change the SSID setup

Screen Shot 2016-07-18 at 10.22.42 AM

There are a few problems with this setup.

  1. The devices that are attached to the open WIFI broadcast in the open
  2. It is easy enough to change the MAC address of device and then hack your way onto the network.
  3. Any broadcast packets from the private network  are broadcast in the open on the WIFI network

But none of these problems are serious enough given that I am in “gun range” of anyone who is within “hacking range.”

The Creek: Create the Chart with JFreeChart

It is almost always better to see data in a plot than as raw values.  I knew that I wanted to be able to see the Elkhorn Creek Water Level.

creekdepth

The charting software that I am using has been done and re-done several times (including as I prepared this post).  I was committed to using Java and I wanted to find a toolkit for building charts.  After searching around on the internet a bit, I settled on JFreeChart which is an open source Java based plotting package.  I like to contribute to the good work of people so I bought the developers guide for $65 and it was well worth it.

I knew that creating a chart would take a bit of CPU and that the Raspberry Pi was a bit under powered as far as that goes.  This lead me to create a batch program which I run via crontab directly after I have collected the data (once per minute).  It appears to the web user that the chart is “fresh”, but really it is up to 1 minute old.

The “makeChart” program is broken up into the following parts

  • Setup the global settings
  • Read and process the command line arguments
  • Read in x-y data from the MySql Database
  • Make the chart

Setup the global settings

The first block of code (lines 2-16) just imports the different classes that I use in this program.  To make the org.jfree stuff work you need to have jcommon-1.0.16.jar and jfreechart-1.0.13.jar in your class path.  You can download them from the source forge project directory https://sourceforge.net/projects/jfreechart/files/

The second block of code (lines 20-26) setup global configuration variables which I declare as “final” so that I know that they are immutable.  It probably would have been better to make the filename be configurable with the command line arguments, but that is something for another day.  Publishing the MySql User and Password would be a problem except, that user can only access the MySql database from inside my network.

The last block of code (lines 32-40) just prints out the command like usage if they program is run with the “-help” argument.

Screen Shot 2016-04-15 at 12.21.46 PM

Read and process the command line arguments

The next step is setting up the Start date/time and the number of hours.  Java has a cool class called “LocalDateTime” which I use to represent the starting time of the data.  There is an absolutely mind boggling number of issues when you deal with dates and times.  I was to far down the road, but if I had it to do over again I would have used Joda Time.

If there is only 1 argument then there are two possibilities

Lines 44-60: The user did 1 command line argument

  • They typed in a number of hours.  On line 47 if the argv[0] string converts to an Integer with no Exception being thrown then I assume that is a number of hours from the current time
  • They typed in a date in the form of “yyyy-MM-dd” or “yyyy-MM-dd hh:mm:ss” or “yyyy-MM-dd hh:mm”.  If they typed 1 argument and it isn’t an integer then I called the “convertStringDateTime” function to try to parse the string.

Lines 65-80: The users did 2 command line arguments

  • The first argument has to be a date and I covert it to the LocalDateTime class using the same “convertStringDateTime” function (line 67)
  • The second argument has to be an integer number of hours and I just use the “Integer(String)” to convert it to a number.

If any of these steps fail, then the program exits.

If there are 0 arguments (line 82-85) then set the date to the current date/time and the hours to the global constant runTimeDefault

Screen Shot 2016-04-15 at 11.10.14 AM

The next block of code takes the command line argument and trys to turn it into a date/time.  To do this I use the DateTimeFormatter class.  Basically I try three different date/time formats to see if I can find one that works.  If there is nothing that works I throw an Exception.

Screen Shot 2016-04-15 at 11.11.08 AM

Read in x-y data from the MySql Database

This function sets up the SQL statement to read the data into a JDBCXYDataset class (from jfree.org) .  The JDBCDataset class can be passed to the charting program to create the plot of the data.  The function is pretty simple, it just takes the input date/time and number of hours.  Then creates an end date/time and embeds that information into the SQL statement.  Finally it runs the MySql query and returns the data.

Screen Shot 2016-04-15 at 11.11.18 AM

Create the chart

The last step is to call the JFreeChart class to build the chart which is done on line 88-96.  Once the chart is created, I setup the axis to have a range of 0.0 –> maxDepthChart (If the water is 23 feet deep then my floor is just getting covered )  (lines 98-101).  And finally create the PNG file (line 103).

Screen Shot 2016-04-15 at 11.10.47 AM

Index Description
The Creek: IOT for the Elkhorn Creek Introduction
The Creek: Solution Architecture 1.0 Overall architecture
The Creek: Creek Board 1.1 Eagle layout of the board
The Creek: Creek Board 1.0 – RCCA A discussion of the errors in the 1.0 board
The Creek: CYPI, a Raspberry Pi to Arduino Bridge PSoC4 <--> Raspberry Pi Bridge Board
The Creek: PSoC4 Creator Schematic and Firmware Firmware to interface with the temperature and pressure sensors
The Creek: Testing the Firmware Using tools to verify that the PSoC 4 Firmware is working correctly
The Creek: Testing the Bootloader Make sure that you can load new firmware into the PSoC
The Creek: Software Architecture All of the Raspberry Pi software connections
The Creek: Install MySql Instruction to configure MySql
The Creek: Install Tomcat Instruction to configure Tomcat JSP Server
The Creek: Data Collection Java (Part 1) The Java program that reads the I2C and saves it in the database
The Creek: Data Collection Java (Part 2) The Java program that reads the I2C and saves it in the database
The Creek: Create the Chart with JFreeChart Using open source Java charting software to create plots of the Creek Depth
The Creek: Flood Event Data Processor A batch program to create analyze the database and create a table of flood events
The Creek: Flood Event Web Page A batch program to create the flood event web page
The Creek: Creek Server 1.1 Updates to all of the back off server programs to integrate charts
The Creek: JSP Web Page for www.elkhorn-creek.org The JSP program to make the table and display the website
The Creek: Raspberry Pi Clock Stretching Sorting out a bug in the system having to do with the Broadcomm Raspberry Pi Master not functioning well with clock stretching
The Creek: Creek Server 1.2 Caching the web pages to make them faster

 

The Creek: Install Tomcat

Apache Tomcat is a web server that allows you to create dynamic web pages using “Java Server Pages” (JSP).   Basically, you can embed Java into your HTML to create dynamic web pages.  Instead of writing Java that spits out HTML (CGI style) you write HTML with the Java embedded into it to create the dynamic part of your web page.  I use this to read the creek depth and temperature and put it into an HTML table, this will be the subject of a future post.

It is straight forward to install Tomcat onto your Raspberry Pi.  You use your old friend “apt-get install” to load Tomcat from somewhere out in the cloud.

  • sudo apt-get update
  • sudo apt-get install tomcat7  –fix-missing [wordpress turns double dash into endash… so use double -]
  • sudo apt-get install tomcat7-docs tomcat7-admin tomcat7-examples

Once you have started Tomcat you will be able to load up the default web page into your browser.  In my case it is “http://iotexpert:8080”.  The “8080” refers to the default port that Tomcat runs on.  If your install went OK, you should see the welcome screen:

Screen Shot 2016-04-03 at 10.29.35 AM

After you have it working, you will need to configure the Administration and Manager users.  To do this edit the “/etc/tomcat7/tomcat-users.xml” file and add a user.  I call my administration user “root” and gave it the excellent password “secret”.

Screen Shot 2016-04-03 at 11.35.34 AM

After you have made the changes you should restart Tomcat using “sudo service tomcat7 restart”.  Then when you click on the “manager web app” you will see this screen:

Screen Shot 2016-04-03 at 11.33.12 AM

And the Virtual Host Manager.

Screen Shot 2016-04-03 at 12.14.54 PM

At this point the Raspberry Pi has all of the required tools to make the Creek Server work.  In the next few posts Ill talk about the different programs that read the data, store it into the database and create the web pages.

Index Description
The Creek: IOT for the Elkhorn Creek Introduction
The Creek: Solution Architecture 1.0 Overall architecture
The Creek: Creek Board 1.1 Eagle layout of the board
The Creek: Creek Board 1.0 – RCCA A discussion of the errors in the 1.0 board
The Creek: CYPI, a Raspberry Pi to Arduino Bridge PSoC4 <--> Raspberry Pi Bridge Board
The Creek: PSoC4 Creator Schematic and Firmware Firmware to interface with the temperature and pressure sensors
The Creek: Testing the Firmware Using tools to verify that the PSoC 4 Firmware is working correctly
The Creek: Testing the Bootloader Make sure that you can load new firmware into the PSoC
The Creek: Software Architecture All of the Raspberry Pi software connections
The Creek: Install MySql Instruction to configure MySql
The Creek: Install Tomcat Instruction to configure Tomcat JSP Server
The Creek: Data Collection Java (Part 1) The Java program that reads the I2C and saves it in the database
The Creek: Data Collection Java (Part 2) The Java program that reads the I2C and saves it in the database
The Creek: Create the Chart with JFreeChart Using open source Java charting software to create plots of the Creek Depth
The Creek: Flood Event Data Processor A batch program to create analyze the database and create a table of flood events
The Creek: Flood Event Web Page A batch program to create the flood event web page
The Creek: Creek Server 1.1 Updates to all of the back off server programs to integrate charts
The Creek: JSP Web Page for www.elkhorn-creek.org The JSP program to make the table and display the website
The Creek: Raspberry Pi Clock Stretching Sorting out a bug in the system having to do with the Broadcomm Raspberry Pi Master not functioning well with clock stretching
The Creek: Creek Server 1.2 Caching the web pages to make them faster

 

The Creek: Collect Data (Part 2)

In the last post I went through all of the setup work for the I2CDB program.  Now I will give you the main course.  My program is divided into five functions

  • main: a simple function that loads the configuration file, attaches to the I2C bus, reads the data from the I2C slave and saves it into the database.
  • getI2CBus: uses the Pi4J library to attach to the I2C Master and initialize the two gobal variables bus1 and bus2.
  • readProperties: reads the “config.properties” file containing the global configuration (like the database name, userid and password) as well as the I2C registers, addresses and names.
  • insertStringDatabase: run the MySql insert function.
  • i2readVariables: read the data from the I2C, setup the insert string, and call the insert function.  This (long) function is where all of the action is at.

I am sure that more could be done to handle exceptions, mostly do a few retrys, but I decided to just print out the error message.

main

This function is called when the i2cdb program is run by the “runi2c” shell script.  It simply

  • reads in the properties file
  • attaches to the Raspberry Pi i2c master
  • reads the i2c slave
  • saves the data into the MySql database
  • print out an error message if there is some exception

Screen Shot 2016-04-10 at 9.02.35 AM

readProperties

This function reads the “config.properties” file into the global class “prop”.  The Properties class handles key/value pairs and knows how to read a file of “key=value” lines.  You can make whatever keys you want, and they have whatever value you want.  Later in the program I use the Integer(String) constructor to convert the String “123” into the Integer 123.

Screen Shot 2016-04-10 at 9.10.21 AM

insertStringDatabase

This function handles the interface to MySql:

  • 159 Takes an input sql command formatted into a string like “insert into creekdata.creekdata (created_at,depth,temperature) values (“2016-04-10 13:16:43.261″,1.568,21.199991);”
  • 163-165 Makes a connection to the “dburl” that it gets from the config.properties file. The URL specifies, which protocol (jdbc), which port and IP address and what database.  e.g “dburl=jdbc:mysql://192.168.15.82/creekdata”
  • 167-169: Executes the insert command

Screen Shot 2016-04-10 at 9.10.30 AM

getI2CBus

The Broadcom 2835 ARM controller is the main chip that runs the Raspberry Pi.  It is essentially a cell phone MCU.  As with most MCUs it has fixed function serial communication blocks embedded into the chip.  In this case the RPi device driver enumerates the I2C blocks as “0” and “1”.  I have no idea what block 0 is attached to.  Block 1 is attached to the GPIO pins on the RPi.  The geti2C function makes a connection to the two controllers.  If you are unable to attach to either of the controllers then I throw an exception.  Hopefully this will future proof this code for updated version of the RPi.

Screen Shot 2016-04-10 at 9.02.45 AM

i2readVariables

Finally the function that does all of the work.  Big picture, this function:

  • iterates over all of the number of variables specified by “i2vars”
    • Figures out the I2C Bus, Address, Register Address and # of bytes
    • Reads the bytes into a “buffer”
    • Converts the buffer to the correct endian-ness
    • Converts the buffer to the correct type (uint8, int8, uint16, int16, float,double)
    • saves the name of the MySql column into the insertNames[] array
    • saves the value of the variable into the insertVals[] array
  • builds up a string with the MySQL “insert ….” command
  • run the insert

The start of the i2readVariables (I really should have called this i2cReadVariables) gets things going

  • I noticed that the I2C reads are not perfectly reliable and it sometimes takes several reads to get a successful read.  I believe that the Broadcom chip does not like to have its I2C clock stretched.  I use the variables I2CReadSuccess and I2CRetryCount to keep track of failures and to retry.
  • Lines 51-52 declare arrays to hold the names of the MySql Columns and the Values to insert.  I declare them as “Object” so that they can hold Integers or Floats.
  • Lines 56-60 look at the properties class to figure out the I2C Bus, I2C Slave Address, I2C Register #, the type of data, and the endinaness
  • Lines 63-68 set the nbytes variable to the right number of bytes to read.  One sin that I perform in this code is to embed the property name (uint8, …) into the code.  Even worse I duplicated the name a few places.
  • Line 70: declare a buffer of bytes to hold the data read from the I2C Slave

Screen Shot 2016-04-10 at 10.12.10 AM

The next block of code reads the I2C Slave.

  • Lines 71-81 attaches to the device on the correct I2C bus.  If there a problem it throws an exception which terminates this function.  Perhaps it would have been better to have a retry scheme, but I didn’t.
  • Lines 83-84: Setup the retry and success variables.  The retry scheme counts down from the hardcoded 20.  When I was running tests I noticed that it may fail 2-3-4 times.
  • Line 86: Sets up a loop that runs until
    • You have had a successful read as indicated by I2CReadSuccess == true
    • You have retried 20 times as indicated by I2CRetryCount == 0
  • Line 88: Reads the I2C Slave
  • Lines 91-97: If there is a failed read as indicated by an Exception being thrown, then sleep for 200ms and try again.
  • Lines 101-104: If you fall out of the loop and haven’t had a succesfull read then throw an exception and exit the read process

Screen Shot 2016-04-10 at 10.23.58 AM

The next block of code uses a cool class called “ByteBuffer” to help convert the individual bytes read from the I2C Slave into Java variables of the right type.

  • Line 106 takes the array of bytes and turns it into a ByteBuffer
  • Lines 108-111 look at the endian-ness setup in the config.properties and then convert the ByteBuffer to the correct endianness.  Originally I did this design using a PSoC3 which was Big Endian… but it now uses a PSoC4 which is little endian.
  • Lines 113-118 convert the ByteBuffer to a value of the right type as specified by the config.properties file.  One trick is that Java does not like unsigned so the bitwise “and” is used to convert the signed values to unsigned.
  • Line 119 saves the MySql column name of the variable

Screen Shot 2016-04-10 at 10.31.47 AM

The last block of code builds up the MySql String and then calls the insert function

  • Lines 122 & 126-129: If the user has specified that he wants a timestamp, then create that timestamp and add it to the MySql Insert statement
  • Line 124: setup the MySql Statement template
  • Lines 130-133 iterate through the column names and add them to the MySql Statement
  • Lines 135-139 if they have asked for a timestamp then add that value to the insert statement
  • Lines 141-143 iterate through all of the values and add them to the insert statement
  • Lines 144-147: finish the MySql Statement, print it out and run it.

Screen Shot 2016-04-10 at 10.37.34 AM

I like this program because I can create a new template file without having to change the program.  Basically I created a generic interface that can bridge from an I2CSlave that collects data and then write that data into the database.

In the next posts Ill show you the user interface web pages.

Index Description
The Creek: IOT for the Elkhorn Creek Introduction
The Creek: Solution Architecture 1.0 Overall architecture
The Creek: Creek Board 1.1 Eagle layout of the board
The Creek: Creek Board 1.0 – RCCA A discussion of the errors in the 1.0 board
The Creek: CYPI, a Raspberry Pi to Arduino Bridge PSoC4 <--> Raspberry Pi Bridge Board
The Creek: PSoC4 Creator Schematic and Firmware Firmware to interface with the temperature and pressure sensors
The Creek: Testing the Firmware Using tools to verify that the PSoC 4 Firmware is working correctly
The Creek: Testing the Bootloader Make sure that you can load new firmware into the PSoC
The Creek: Software Architecture All of the Raspberry Pi software connections
The Creek: Install MySql Instruction to configure MySql
The Creek: Install Tomcat Instruction to configure Tomcat JSP Server
The Creek: Data Collection Java (Part 1) The Java program that reads the I2C and saves it in the database
The Creek: Data Collection Java (Part 2) The Java program that reads the I2C and saves it in the database
The Creek: Create the Chart with JFreeChart Using open source Java charting software to create plots of the Creek Depth
The Creek: Flood Event Data Processor A batch program to create analyze the database and create a table of flood events
The Creek: Flood Event Web Page A batch program to create the flood event web page
The Creek: Creek Server 1.1 Updates to all of the back off server programs to integrate charts
The Creek: JSP Web Page for www.elkhorn-creek.org The JSP program to make the table and display the website
The Creek: Raspberry Pi Clock Stretching Sorting out a bug in the system having to do with the Broadcomm Raspberry Pi Master not functioning well with clock stretching
The Creek: Creek Server 1.2 Caching the web pages to make them faster