Objective: The Objective of this exercise is to integrate Spring Boot, Pi4J, MySQL database on to Raspberry Pi by creating a simple Web application to toggle (ON or OFF) the LED on Raspberry Pi based on the REST URL hit on the browser and to persist the LED information (i.e blink status, blink datetimestamp, blink counter, JSON format) to MySQL database. Also we can view the LED information that is persisted in the MySQL database. Also the LED information is published to a topic on MQTT Broker, which can accessed by any MQTT client subscribed for that topic.
YouTube Video:
The YouTube Video for this tutorial is available at this link and also can be found at the end of the tutorial.
GitHub Source:
https://github.com/agilerules/IOT/tree/master/iotled-mqtt
Task details:
Once the application is successfully setup (as per the instructions below) and MySQL database and table are configured, here is what you see as the output.
1. Every time once the URL http://<raspberryIp>:9999 is hit (or refreshed), it will Hello World!!! as shown in the below screen shot.
2. Every time once the URL http://<raspberryIp>:9999/light is hit (or refreshed) then the LED on the Raspberry Pi will toggle (on or off) and you should see the LED Status (ON/OFF), time and the blink counter on the browser output. Notice that the blink counter will increase by 1 for every hit.
Now refresh he browser again, where you see that the status is OFF (and also the LED on the Raspberry Pi will be OFF) now and the counter is increased to 2.
Now refresh he browser again, where you see that the status is ON (and also the LED on the Raspberry Pi will be ON) now and the counter is increased to 3.
For every refresh that is made above, there will be an entry in the MySQL database in the table led_details for the transactions made in the above steps, which can be validated by invoking the MySQL PhpMyAdmin screen installed on Raspberry Pi (as instructed in the blog).
http://<raspberryIp>/phpmyadmin/
3. Every time once the URL http://<raspberryIp>:9999/display is hit (or refreshed) then it fetches the top 10 records persisted in the MySQL database table led_details.
4. MQTT Testing: Open a new terminal window of Raspberry Pi using SSH and subscribe for the MQTT topic using the following command:
mosquitto_sub -d -v -t iot/led
The concept here is the that we are trying to subscribe to the MQTT Topic using MQTT client (mosquitto_sub).
5. Now every time you hit the browser with the URL http://<raspberryIp>:9999/light, you will notice that the LED information is published on the screen (as highlighted in red). The reason here is that we have the logic in the code to publish the LED information to a particular topic (here iot/led) on MQTT Broker, which can be viewed from any MQTT Client, subscribed to the same topic.
mosquitto_sub -d -v -t iot/led
The concept here is the that we are trying to subscribe to the MQTT Topic using MQTT client (mosquitto_sub).
5. Now every time you hit the browser with the URL http://<raspberryIp>:9999/light, you will notice that the LED information is published on the screen (as highlighted in red). The reason here is that we have the logic in the code to publish the LED information to a particular topic (here iot/led) on MQTT Broker, which can be viewed from any MQTT Client, subscribed to the same topic.
Dependencies:
Software:
- Spring Boot with Tomcat Embedded
- Pi4j
- Java
- Maven (Please find my blog here on how to install Maven on Raspberry Pi)
- MySQL & PhpMyAdmin (Please find my blog here on how to install MySQL and PhpMyAdmin on Raspberry Pi)
- MQTT Broker (Please find my blog here on how to install MQTT Broker on Raspberry Pi).
Hardware:
- Raspberry Pi (installed with Java, Maven)
- 3 Jumper wires
- LED
- 220 Ohm Resistor
- Breadboard
- GPIO Ribbon Cable
Steps:
1. MySQL database has to be installed first on the Raspberry Pi and have to create the table led_details to capture the LED information. Please follow the instructions provided in the blog on how to install MySQL database on Raspberry Pi, create a database and the table.
CREATE DATABASE agilerulesdb;
USE agilerulesdb;
CREATE USER ‘admin’@’localhost’ IDENTIFIED BY ‘password’;
GRANT ALL PRIVILEGES ON agilerulesdb.* TO 'admin'@'localhost';
--Relogin with the new user "admin" that is created and execute the following scripts
mysql -u admin -p
use agilerulesdb;
CREATE TABLE led_details
(
ID int NOT NULL AUTO_INCREMENT,
BlinkStatus varchar(3),
DateTimeStamp DATETIME,
BlinkCounter INT,
JsonPayload varchar(255),
PRIMARY KEY (ID)
);
Note: You can change the database name, user id and password in the above list, as per you convenience.
2. Install MQTT Broker on the Raspberry Pi and test the installation with the MQTT Client using the instructions provided in the blog. We are going to the use the MQTT Broker URL to publish the LED information, which will be explained further down in the tutorial.
3. Complete the following Wiring process of Raspberry Pi, LED, Resistor and with few jumper wires as shown in the below diagram.
Wiring Diagram:
Bread Board Wiring |
Bread Board Wiring |
- A wire from Pin 6 to Ground ( - on Breadboard)
- A wire from Pint 12 (GPIO_1) to + line on Breadboard
- Fix the LED and the long end of LED Anode (+) to be connected to Resistor (Yellow side on top of Resistor)
- Other end of Resistor (i.e the red colour on top) to the + line of Breadboard
- LED Cathode (-) to – line of Breadboard
4. Now connect to Raspberry Pi using Putty with your Raspberry Pi Credentials and by-default, you will in the path /home/pi.
5. For proper organization purpose, I created folders (using mkdir command) \projects. But this is not mandatory. You can even skip this step and move to next step.
5. For proper organization purpose, I created folders (using mkdir command) \projects. But this is not mandatory. You can even skip this step and move to next step.
mkdir projects
6. From the \projects folder, execute the following command to Git clone the code to your local raspberry Pi.
git clone https://github.com/agilerules/IOT.git
git clone https://github.com/agilerules/IOT.git
7. Once the git clone is complete, you will see IOT folder created in \projects folder. Now go to IOT folder (using the command cd IOT) and you will see the folder iotled-mqtt inside this folder IOT.
8. Move to this iotled-mqtt folder (using the command cd iotled-mqtt).
9. Now execute the following command to start the maven build. (Incase if mvn command is not recognized then it means that maven is not installed on your Raspberry Pi. Please follow my blog on how to install Maven on Raspberry Pi.
8. Move to this iotled-mqtt folder (using the command cd iotled-mqtt).
9. Now execute the following command to start the maven build. (Incase if mvn command is not recognized then it means that maven is not installed on your Raspberry Pi. Please follow my blog on how to install Maven on Raspberry Pi.
12. Now come back to previous folder (i.e to iotled-mqtt) and run the following command and you should see the Spring in your screen as shown in the below screen shot, which indicates that Spring Boot is working fine.
13. You should finally see the message saying “Started Application...”. Also you can see that the REST end points / and /light are loaded and Tomcat Started on port 9999.
14. Now go to browser and hit the below URL where replace <raspberryIp> with your Raspberry pi IP address.
http://<raspberryIp>:9999/
15. Similarly once you hit the below URL (multiple times), the LED connected to Raspberry Pi should toggle (On or Off) and you should see the LED Status (ON/OFF), time and the blink counter. Notice that the blink counter will increase by 1 for every hit.
http://<raspberryIp>:9999/light
Now refresh the browser again, where you see that the status is OFF now and the counter is increased to 2.
Now refresh the browser again, where you see that the status is ON now and the counter is increased to 3.
Now refresh the browser again, where you see that the status is OFF now and the counter is increased to 2.
Now refresh the browser again, where you see that the status is ON now and the counter is increased to 3.
16. Once you hit the below URL http:// <raspberryIp>:9999/display, it will fetch the top 10 records persisted in the MySQL database table led_details.
17. Here is the source code explanation below:
The complete project structure is available here:
17. Here is the source code explanation below:
The complete project structure is available here:
a) Pom.xml
The below are two library dependencies that we need for this application: spring-boot-starter-web - This is for Spring boot to enable the Web application with embedded Tomcat. This would need the following parent Spring Boot starter package to be defined in <parent> node. <artifactId>spring-boot-starter-parent</artifactId>
The below are two library dependencies that we need for this application: spring-boot-starter-web - This is for Spring boot to enable the Web application with embedded Tomcat. This would need the following parent Spring Boot starter package to be defined in <parent> node. <artifactId>spring-boot-starter-parent</artifactId>
pi4j-core – This is for Pi4J to communicate with Raspberry Pi GPIO pins.
spring-boot-starter-data-jpa: This is required for Spring Data JPA communication.
mysql-connector-java: This is driver class required to connect to MySQL database
gson: This is required to convert Java Objects into their JSON representation and viceverza.
Junit: This required for JUnit testing
b) Application.java
spring-boot-starter-data-jpa: This is required for Spring Data JPA communication.
mysql-connector-java: This is driver class required to connect to MySQL database
gson: This is required to convert Java Objects into their JSON representation and viceverza.
Junit: This required for JUnit testing
This is simple Spring Boot code with @SpringBootApplication annotation and SpringApplication.run() method with the arguments (class, args) inside main() method.
@SpringBootApplication:
The @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes.
@SpringBootApplication is a convenience annotation that adds all of the following:
@Configuration tags the class as a source of bean definitions for the application context.
@EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviours such as setting up a DispatcherServlet.
@ComponentScan tells Spring to look for other components, configurations, and services in the the hello package, allowing it to find the HelloController.
Did you notice that there wasn’t a single line of XML? No web.xml file either. This web application is 100% pure Java and you didn’t have to deal with configuring any plumbing or infrastructure.
The run() method returns an ApplicationContext and this application then retrieves all the beans that were created either by your app or were automatically added thanks to Spring Boot. It sorts them and prints them out.
c) LEDModel.java
This class is the JPA Model class to capture the LED information like blinkStatus (ON/OFF), dateTimeStamp (the blink time stamp), blinkCounter (the count of blinks), jsonPayload( all the other fields represented in json format). It holds the private variables with respective getters and setters. Here is the explanation for the JPA Annotations used in this class:
@Entity:
This class is the JPA Model class to capture the LED information like blinkStatus (ON/OFF), dateTimeStamp (the blink time stamp), blinkCounter (the count of blinks), jsonPayload( all the other fields represented in json format). It holds the private variables with respective getters and setters. Here is the explanation for the JPA Annotations used in this class:
@Entity:
The @Entity annotation indicates that the JavaBean is a persistent entity. JPA would automatically pick up this class for Persistence.
@Table(name = "led_details")
@Table annotation explicitly configures which table the entity is mapped to. Here the (name = "led_details") denotes that this bean is mapped to the database table name led_details. Note that led_details is a MySQL table name, which holds the LED information.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
@Id annotation denotes that the this field below this definition is primary key field in the database
@GeneratedValue(strategy = GenerationType.AUTO) - denotes that we are going to use Auto increment field for the primary key and that's is depicted with the strategy as GenerationType.AUTO
@Column(name = "ID") - denotes the Field name defined in the database table. Similar to this we have other @Column fields defined.
d) MqttPublishSubscribeUtility.java
This class is the utility class which implements MQTT protocol to publish the LED information on a topic. To give some overview on MQTT, it is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol, designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium.
This utility class has a method named mqttConnect()which connect to MQTT broker that is installed on Raspberry Pi whose broker URL is defined in the properties file named mqtt.properties, which is available in the src/main/resources folder.
Here are the entries for mqtt.properties file:
src/main/resources/mqtt.properties
mqttConnect() method:
It makes use of Eclipse Paho API’s to connect to MQTT broker:
f) LedController.java:
@RestController:
Spring 4.0 introduced @RestController, a specialized version of the controller which is a convenience annotation that does nothing more than add the @Controller and @ResponseBody annotations. By annotating the controller class with @RestController annotation, you no longer need to add @ResponseBody to all the request mapping methods. The @ResponseBody annotation is active by default.
@Table(name = "led_details")
@Table annotation explicitly configures which table the entity is mapped to. Here the (name = "led_details") denotes that this bean is mapped to the database table name led_details. Note that led_details is a MySQL table name, which holds the LED information.
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "ID")
@Id annotation denotes that the this field below this definition is primary key field in the database
@GeneratedValue(strategy = GenerationType.AUTO) - denotes that we are going to use Auto increment field for the primary key and that's is depicted with the strategy as GenerationType.AUTO
@Column(name = "ID") - denotes the Field name defined in the database table. Similar to this we have other @Column fields defined.
d) MqttPublishSubscribeUtility.java
This class is the utility class which implements MQTT protocol to publish the LED information on a topic. To give some overview on MQTT, it is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol, designed as an extremely lightweight publish/subscribe messaging transport. It is useful for connections with remote locations where a small code footprint is required and/or network bandwidth is at a premium.
This utility class has a method named mqttConnect()which connect to MQTT broker that is installed on Raspberry Pi whose broker URL is defined in the properties file named mqtt.properties, which is available in the src/main/resources folder.
Here are the entries for mqtt.properties file:
src/main/resources/mqtt.properties
mqttConnect() method:
It makes use of Eclipse Paho API’s to connect to MQTT broker:
Here are the steps at high level:
1. Initialize the MqttClient along with the Borker URL, Client Id and persistence object
2. Initialize the MqttConnectOptions and setCleanSession() to true.
3. Invoke the connect() method on MqttClient.
MqttClient sampleClient = new MqttClient(props.getProperty("BROKER_URL"), props.getProperty("CLIENT_ID"),persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
sampleClient.connect(connOpts);
This method will inturn invoke the mqttConnect() method described above to connect to MQTT broker and will publish the MqttMessage payload to the topic named iot/led (defined in the mqtt.properties file). It accepts the JsonObject as payload input from which the LED parameters defined in the LEDModel.java are set.
Here are the steps involved:
1. Initialize the MqttClient by calling the method mqttConnect().
2. Initialize the MqttMessage object with payload as input
3. Set QOS (Quality Of Service) parameter as 2 (defined in mqtt.properties) for the message. The highest QoS is 2, it guarantees that each message is delivered exactly once. It is the safest and also the slowest quality of service level. The other two QOS values are 1 (which means the message is delivered atleast once) and 0 (which means the message is delivered atmost once)
4. Invoke the setCallback() method to callback listener to use the events that happen asynchronously
5. Finally publish the MQTT message on the topic named iot/led, defined in the mqtt.properties file.
MqttClient sampleClient = mqttConnect();
MqttMessage message = new MqttMessage(payload.toString().getBytes(Charset.forName("UTF-8")));
if(props.getProperty("QOS")!=null){ message.setQos(Integer.parseInt(props.getProperty("QOS")));
}
sampleClient.setCallback(new SimpleCallback());
sampleClient.publish(props.getProperty("TOPIC_NAME"), message);
e) LedDAORepository.java:
This is DAO repository that extends JPARespository interface provided by Spring. This class has one findBy method (called findTop10ByOrderByIdDesc ) which will fetch the top 10 records from the database table led_details order by the column ID descending. @Transactional annotation defines the scope of the database transaction.
This is DAO repository that extends JPARespository interface provided by Spring. This class has one findBy method (called findTop10ByOrderByIdDesc ) which will fetch the top 10 records from the database table led_details order by the column ID descending. @Transactional annotation defines the scope of the database transaction.
f) LedController.java:
@RestController:
Spring 4.0 introduced @RestController, a specialized version of the controller which is a convenience annotation that does nothing more than add the @Controller and @ResponseBody annotations. By annotating the controller class with @RestController annotation, you no longer need to add @ResponseBody to all the request mapping methods. The @ResponseBody annotation is active by default.
@RequestMapping maps / to the index() method and returns “Hello World!!”
@RequestMapping maps /light to the light() method which uses the Pi4j API’s to toggle LED on or off and returns the response with the Light Status as ON/OFF, Time, blink counter information.
@RequestMapping maps /display to the display() method to fetch the top 10 records persisted in the MySQL database table led_details.
Explanation of Request Mapping /:
This method will return Hello World!!! as shown in the below screen shot.
@RequestMapping maps /light to the light() method which uses the Pi4j API’s to toggle LED on or off and returns the response with the Light Status as ON/OFF, Time, blink counter information.
@RequestMapping maps /display to the display() method to fetch the top 10 records persisted in the MySQL database table led_details.
Explanation of Request Mapping /:
This method will return Hello World!!! as shown in the below screen shot.
@RequestMapping("/")
public String greeting(){
return "Hello World!!";
}
Explanation of Request Mapping /light:
This method uses the Pi4j API’s to toggle LED on or off and returns the response with the Light Status as ON/OFF, Time, blink counter information.
Here are the steps at high level:
1. Initialize the Pi4J API GPIOController using GPIOFactory’s getInstance() method
2. Invoke the method provisionDigitialoutputPin() method to provision the pin GPIO_01 as the Ouput pin and default the Pin state to LOW (which means, it will be in off state by-defualt) and “My LED” is the user defined name for the LED. Set the BlinkStatus on ledModel instance to OFF (as it is in OFF state for the first time).
3. Now toggle the pin (ON/OFF) by invoking the toggle() method.
if(pin==null){
System.out.println("Entering for the first time..");
GpioController gpio = GpioFactory.getInstance();
pin = gpio.provisionDigitalOutputPin(RaspiPin.GPIO_01,"My LED",PinState.LOW);
ledModel.setBlinkStatus("OFF");
}
pin.toggle();
4. Have a blink counter logic to increment the counter for every refresh and set the value to blinkConter() method of ledModel.
blinkCounter++;
ledModel.setBlinkCounter(blinkCounter);
5.Set the current date time stamp using setDateTimeStamp() method.
ledModel.setDateTimeStamp(new Date().toString());
6. Using gson API’s, create a JsonObject and add the LED parameters using addProperty() method. Note that getId() method will fetch the MySQL’s Auto Increment number from the table led_details.
JsonObject payload = new JsonObject();
payload.addProperty("Id", ledModel.getId());
payload.addProperty("blinkStatus", ledModel.getBlinkStatus());
payload.addProperty("dateTimeStamp", ledModel.getDateTimeStamp());
payload.addProperty("blinkCounter", ledModel.getBlinkCounter());ledModel.setJsonPayload(payload.toString());
7. Invoke the mqttConnectNPublishNSubscribe() method to connect to MQTT broker and publish the message payload to a topic.
mqttPublishSubscribeUtility.mqttConnectNPublishNSubscribe(payload)
8.Finally, persist the LED information to MySQL database using LedDAORepository instance, which is auto wired using Spring’s @AutoWired annotation.
ledDAORepository.save(ledModel);
ledModel.setDateTimeStamp(new Date().toString());
6. Using gson API’s, create a JsonObject and add the LED parameters using addProperty() method. Note that getId() method will fetch the MySQL’s Auto Increment number from the table led_details.
JsonObject payload = new JsonObject();
payload.addProperty("Id", ledModel.getId());
payload.addProperty("blinkStatus", ledModel.getBlinkStatus());
payload.addProperty("dateTimeStamp", ledModel.getDateTimeStamp());
payload.addProperty("blinkCounter", ledModel.getBlinkCounter());ledModel.setJsonPayload(payload.toString());
7. Invoke the mqttConnectNPublishNSubscribe() method to connect to MQTT broker and publish the message payload to a topic.
mqttPublishSubscribeUtility.mqttConnectNPublishNSubscribe(payload)
8.Finally, persist the LED information to MySQL database using LedDAORepository instance, which is auto wired using Spring’s @AutoWired annotation.
ledDAORepository.save(ledModel);
Explanation of Request Mapping /display:
This method will display the top 10 records persisted in the MySQL database table led_details.
Source Code Explanation:
Here are the steps at high level:
1. Initialize the StringBuffer Object
2. Invoke the method findTop10ByOrderByIdDesc() will fetch the top 10 records from MySQL database table led_details, order by primary key field Id and fetch them in descending order, which will basically return the List.
3. Iterate the List to fetch the values and append them to String Buffer object that is created in the first step and finally return this StringBuffer instance.
StringBuffer strBuffer = new StringBuffer();
List<LedModel> ledModels = ledDAORepository.findTop10ByOrderByIdDesc();
for (LedModel ledModel : ledModels){
strBuffer.append("<html><body>");
strBuffer.append("Id="+ledModel.getId()+" |BlinkStatus="+ledModel.getBlinkStatus()+" |DateTimeStamp="+ledModel.getDateTimeStamp()+"|Json Payload="+ledModel.getJsonPayload());
strBuffer.append(System.getProperty("line.separator"));
strBuffer.append("<br>");
strBuffer.append("</body></html>");
}
return strBuffer;
}
server.port = 9999
The above entry indicates the embedded Tomcat in Spring Boot to use the port 9999 (rather than the default 8080 port).
That’s it. Hope this tutorial is useful for you.
No comments:
Post a Comment