Raspberry PI Weather App (no hardware sensor)

Introduction

 
Weather demo hardware
 
Figure 1: Weather Demo Device
 

Introduction

 
In this article, we will look into building a sample Weather App using Raspberry PI, Mono C# and RaspberryPi.Net (Mono.NET interface to the GPIO pins).
 
Note: Consider this one as a starting point in getting your hands wet in writing a C# code snippet and running them the same on the PI. Hence we don’t make use of a hardware sensor but instead, make use of web service to get the weather information.
 
The following is the list of things that are required for this demo Weather App:
  1. Raspberry PI (Model A, B or B+).
  2. Ethernet or USB WiFi Adapter.
  3. A Desktop/Laptop installed with MonoDevelop IDE.
  4. One LED and a 330 ohm 1/4 watt resistor.
  5. HDMI to DVI cable or HDMI cable depending on whether you are connecting PI to your computer monitor or HDMI TV.
Please Note: The following code is being reused and modified to work:
 
https://github.com/raharrison/GoogleAPI/tree/master/GoogleWeather
 
Background
 
If you are a beginner to Raspberry PI, please have a look into an excellent article by Guruprasad.K.Basavaraju which helped me understand the basics.
 
The first thing one has to do is register yourself and get the API Key from the following link:
 
We will be making an HTTP Web Request to the following formatted URL and get the weather information. Please note that this API is free for personal and non-commercial use with a "fairuse" of 250 daily accesses.
 
HTTP Web Request
 
Link
 
The key thing here is the API Key and the city for which you are interested in getting the weather information.
 
HTTP Web Response
 
The following is the HTTP Response consisting of forecast and weather conditions. We will be only concentrating on reading the current weather conditions.
 
Hide Copy Code
  1. <xml_api_reply version="1">  
  2.     <weather module_id="0" tab_id="0">  
  3.         <current_conditions>  
  4.             <!-- Some inner tags containing data of current weather -->  
  5.             <condition data="Sunny" />  
  6.             <temp_f data="32" />  
  7.             <temp_c data="0" />  
  8.             <humidity data="Humidity: 0%" />  
  9.             <icon data="/images/weather/sunny.gif" />  
  10.             <wind_condition data="Wind: SE at 9 mph" /> </current_conditions>  
  11.     </weather>  
  12. </xml_api_reply>  
Let us write some code in fetching the weather condition. The following is the code snippet of a WeatherEntity for holding the weather info.
  1. public class WeatherEntity  
  2. {  
  3.     public string City  
  4.     {  
  5.         get;  
  6.         set;  
  7.     }  
  8.     public string Condition  
  9.     {  
  10.         get;  
  11.         set;  
  12.     }  
  13.     public string TempInFahrenheit  
  14.     {  
  15.         get;  
  16.         set;  
  17.     }  
  18.     public string TempInCentigrade  
  19.     {  
  20.         get;  
  21.         set;  
  22.     }  
  23.     public string Humidity  
  24.     {  
  25.         get;  
  26.         set;  
  27.     }  
  28.     public string Wind  
  29.     {  
  30.         get;  
  31.         set;  
  32.     }  
  33.     public string Day  
  34.     {  
  35.         get;  
  36.         set;  
  37.     }  
  38.     public string High  
  39.     {  
  40.         get;  
  41.         set;  
  42.     }  
  43.     public string Low  
  44.     {  
  45.         get;  
  46.         set;  
  47.     }  
  48. }  
Here is the code snippet to get the weather condition. The code is self-explanatory where we are loading the XML response to XmlTextReader and then loading the same to XmlDocument so that we can select the nodes that we are interested in.
  1. public static WeatherEntity GetWeatherCondition(string apiKey, string city)  
  2. {  
  3.     var weatherEntity = new WeatherEntity();  
  4.     using(var weatherXmlReader = new XmlTextReader(string.Format("http://api.previmeteo.com/{0}/ig/api?weather={1}", apiKey, city)))  
  5.     {  
  6.         var doc = new XmlDocument();  
  7.         doc.Load(weatherXmlReader);  
  8.         if(doc.SelectSingleNode("xml_api_reply/weather/problem_cause") != null)  
  9.         {  
  10.             weatherEntity = null;  
  11.         }  
  12.         else  
  13.         {  
  14.             weatherEntity.City = doc.SelectSingleNode("/xml_api_reply/weather/forecast_information/city")  
  15.                 .Attributes["data"].InnerText;  
  16.             weatherEntity.Condition = doc.SelectSingleNode("/xml_api_reply/weather/current_conditions/condition")  
  17.                 .Attributes["data"].InnerText;  
  18.             weatherEntity.TempInCentigrade = doc.SelectSingleNode("/xml_api_reply/weather/current_conditions/temp_c")  
  19.                 .Attributes["data"].InnerText;  
  20.             weatherEntity.TempInFahrenheit = doc.SelectSingleNode("/xml_api_reply/weather/current_conditions/temp_f")  
  21.                 .Attributes["data"].InnerText;  
  22.             weatherEntity.Humidity = doc.SelectSingleNode("/xml_api_reply/weather/current_conditions/humidity")  
  23.                 .Attributes["data"].InnerText;  
  24.             weatherEntity.Wind = doc.SelectSingleNode("/xml_api_reply/weather/current_conditions/wind_condition")  
  25.                 .Attributes["data"].InnerText;  
  26.         }  
  27.     }  
  28.     return weatherEntity;  
  29. }  
You must be probably wondering where I am using the LED and register.
 
It’s time to have a little understanding of the Raspberry PI GPIO (General Purpose Input/Output). The following picture shows the GPIO pins in the PI. We will be using the Ground and GPIO 17 (3V3 Power pins) with a register to glow an LED-based on specific criteria.
 
More information about the GPIO can be found here.
 
rpi gpio
 
 
You have to make use of two jumper wires and connect the same to “Ground” and Pin 17 of GPIO as in the following snapshot. It doesn’t have to be Pin 17 but we are using it for this demo app.
 
Note: Make sure you accidentally do no connect through the 5V Power.
 
The longer end of the LED has to be connected with the resistor which is in-turn connected with the GPIO Pin 17. Whereas the lower end of the LED has to be connected to “Ground” as shown below.
 
ledground
 
Now it’s the time to have a look into the code snippet which is responsible for taking the city name as input and further making a call to get the weather condition so that we can display the same on Console.
  1. public static void Main(string[] args)  
  2. {  
  3.     String apiKey = "<API_KEY>";  
  4.     GPIOFile led = null;  
  5.     Console.WriteLine("Enter city name: ");  
  6.     var city = Console.ReadLine();  
  7.     try  
  8.     {  
  9.         var weather = GetWeatherCondition(apiKey, city);  
  10.         if(weather != null)  
  11.         {  
  12.             Console.WriteLine("************************************************** ");  
  13.             Console.WriteLine("TempC: " + weather.TempInCentigrade);  
  14.             Console.WriteLine("TempF: " + weather.TempInFahrenheit);  
  15.             Console.WriteLine("Condition: " + weather.Condition);  
  16.             Console.WriteLine(weather.Humidity);  
  17.             Console.WriteLine(weather.Wind);  
  18.             Console.WriteLine("************************************************** ");  
  19.             // if the temperature is less than 5 deg, then glow an LED  
  20.             if(int.Parse(weather.TempInCentigrade) < 5)  
  21.             {  
  22.                 led = new GPIOFile(GPIOPins.V2_GPIO_17);  
  23.                 led.Write(PinState.High);  
  24.             }  
  25.         }  
  26.         else  
  27.         {  
  28.             Console.WriteLine("Problem in fetching in the weather information.");  
  29.         }  
  30.     }  
  31.     catch(Exception ex)  
  32.     {  
  33.         Console.WriteLine(ex.ToString());  
  34.     }  
  35.     Console.WriteLine("Press any key to exit!");  
  36.     Console.ReadLine();  
  37.     if(led != null) led.Write(PinState.Low);  
  38. }  
Let us take a look into how we glow the LED based on a specific temperature value. The following is the link to the library that we are making use of. You can download the same and compile and reference in your projects. It’s very easy to use library.
 
RaspberryPi.Net GitHub
 
As per the above code, if the temperature in centigrade is less than 5, then we are creating an instance of GPIOFile with the PIN as 17. With a single line of code, by making a call to write method of GPIOFile instance with a value as PinState.High will glow the LED on Pin 17 in our case.
 
Let us see how one can run the application on Raspberry PI. Firstly, you have to install mono on the PI. You need to run the following command on the Linux terminal. You can execute the same remotely by connecting to PI through SSH (use Putty app) or you can directly run the same on Raspberry PI.
 
sudo apt-get install mono-complete
 
Have a look into the following link to get started with Mono
 
Compile the Weather App source code so that you can upload the necessary executable to PI. I have used an FTP client tool named FileZilla and have connected to PI and uploaded the required executable.
 
Please make sure to run the Weather Demo app under “root” user as there are necessary permissions required for the GPIO library to access to path “/sys/class/gpio”.
 
pi@raspberry
 
Point of Interest
 
I am still a beginner to IoT and Raspberry Pi. Since when I got this little device, I started playing and learning a lot. Working with Mono C# is really cool. I am being a .NET Programmer and quickly started in writing a C# code to run on Linux.