IoT (Internet of Things) Tutorial

IoT (Internet of Things) Tutorial

Introduction

        I was searching online for tutorials about IoT software development  and most of the blogs or links gave very minimal information about the end to end implementation of IoT. Hence I decided to come up with this blog post.
        In this tutorial I will be using RabbitMQ as message broker. The reason I have chosen RabbitMQ as message broker is because we have a RabbitMQ cluster in Production that processes more than a million messages in a minute. I will be sending and receiving messages using the MQTT Protocol with a Simple MQTT Paho Client. I will also be using a Simple AMQP Client to receive and send messages which will give an end to end software implementation of IoT. You may be wondering what the abbreviations MQTT and AMQP mean and also what Paho means. To understand these please read on as I have explained them in very simple terms.

So there are 2 Applications required to get the end to end functionality:
  1. Simple MQTT Client using Paho
  2. Simple AMQP Client.

IoT (Internet of Things)

        IoT (Internet of Things) is a network of things. A thing is any physical device with an On and Off switch. This includes everything from cellphones to sensors to refrigerators to heaters to lights to anything that you can see around you. These things need to have embedded software and network connectivity which will enable them to connect to each other and exchange data. In this way the things will be able to inter-operate within the existing internet infrastructure. But you must be wondering how is a huge maze of things that communicate with each other be of any use to me. Consider your alarm clock tells your water heater to switch on when it rings or the printer in your home or office knew that it is down on supplies and automatically orders it or the air conditioner automatically switches ON some time before you reach home or lights switch OFF automatically after you leave your home. The possibilities are endless and this will simplify our lives and bring in a lot of efficiency in our lives. IoT can also be applied in a very large scale like for traffic management, setting up smart cities, smart buildings, monitoring and improving the efficiency of power and electricity usage and so on. This is a broad overview of IoT, but in this tutorial I will be focusing on the software development side of IoT.

For physical devices to communicate with each other, they require a messaging protocol preferably with small code footprint and also one that can work with limited network bandwidth. Here are a few examples of IoT messaging protocols:
  1. MQ Telemetry Transport or Message Queue Telemetry Transport(MQTT)
  2. Advanced Message Queuing Protocol (AMQP), 
  3. Streaming Text Oriented Messaging Protocol (STOMP) 
  4. The IETF Constrained Application Protocol
  5. Web Application Messaging Protocol (WAMP)
Among these the most popular and most widely used protocol in IoT is MQTT Protocol. Many times MQTT Protocol is referred to as the protocol of IoT.

MQTT Protocol

        MQTT (MQ Telemetry Transport or Message Queue Telemetry Transport) is an ISO standard  publish-subscribe-based messaging protocol. It works on top of the TCP/IP protocol. It is designed for connections with remote locations where a "small code footprint" is required or the network bandwidth is limited. The publish-subscribe messaging pattern requires a message broker. MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport.

More details about MQTT can be read from MQTT GitHub Website.

Here are a few message brokers that support MQTT protocol:
  1. mosquitto
  2. RabbitMQ
  3. HiveMQ
  4. mosca
  5. Apache ActiveMQ
A comparison of the MQTT Brokers can be found at: MQTT GihHub server support website.

Important points about MQTT Protocol

Publish and Subscribe

The MQTT protocol is based on the principle of publishing messages and subscribing to topics, or "pub/sub". Multiple clients connect to a broker and subscribe to topics that they are interested in. Clients also connect to the broker and publish messages to topics. Many clients may subscribe to the same topics and do with the information as they please. The broker and MQTT act as a simple, common interface for everything to connect to.

Topics and Subscriptions

Messages in MQTT are published on topics. There is no need to configure a topic, publishing on it is enough. Clients can receive messages by creating subscriptions. A subscription may be to an explicit topic or to multiple topics.

Quality of Service (QoS)

MQTT defines three levels of Quality of Service (QoS). The QoS defines how hard the broker/client will try to ensure that a message is received. Messages may be sent at any QoS level, and clients may attempt to subscribe to topics at any QoS level. This means that the client chooses the maximum QoS it will receive. For example, if a message is published at QoS 2 and a client is subscribed with QoS 0, the message will be delivered to that client with QoS 0. If a second client is also subscribed to the same topic, but with QoS 2, then it will receive the same message but with QoS 2. For a second example, if a client is subscribed with QoS 2 and a message is published on QoS 0, the client will receive it on QoS 0.

Higher levels of QoS are more reliable, but involve higher latency and have higher bandwidth requirements.

0: The broker/client will deliver the message once, with no confirmation.

1: The broker/client will deliver the message at least once, with confirmation required.

2: The broker/client will deliver the message exactly once by using a four step handshake.

Requirements to Run the Application:

  1. RabbitMQ
  2. Java
  3. Maven
  4. IDE of your choice
RabbitMQ should be setup and running in your machine. To setup, run and test if the RabbitMQ setup is working fine, please refer to my post on: RabbitMQ Setup.

Enable support for MQTT Protocol in RabbitMQ by enabling rabbitmq_mqtt plugin using the command:
D:\Programs\RabbitMQ Server\rabbitmq_server-3.6.14\sbin>rabbitmq-plugins.bat enable rabbitmq_mqtt
Details about RabbitMQ MQTT Adapter can be read from: RabbitMQ Website.

Application 1: Simple MQTT Client using Paho

        Ideally this code would run on a physical device like a cellphone or a sensor or any other thing that is part of the Internet of Things.

Eclipse Paho Java Client

The Paho Java Client is an MQTT client library written in Java for developing applications that run on the JVM or other Java compatible platforms such as Android. The Paho project has been created to provide reliable open-source implementations of open and standard messaging protocols aimed at new, existing, and emerging applications for Machine-to-Machine (M2M) and Internet of Things (IoT). Paho reflects the inherent physical and cost constraints of device connectivity. For more details about Paho please check: Paho Website.

The MQTT Client can be coded in few simple steps.

Step 1: Paho Dependency to be added in pom.xml. 

Here is the dependency:
    <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.0</version>
        </dependency>

Here is the full pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.aj.mqttclient</groupId>
    <artifactId>MQTTClient</artifactId>
    <version>1.0.0</version>


    <properties>
        <jdk.version>1.8</jdk.version>
        <logback.version>1.1.3</logback.version>
        <jcl.slf4j.version>1.7.12</jcl.slf4j.version>
        <packaging>jar</packaging>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${jcl.slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <createDependencyReducedPom>true</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.aj.mqttclient.MQTTClient</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project> 
If you observe the pom.xml, I have added logging related dependencies to it.

Step 2: Add logback configuration in logback.xml

Basic file based and console based logging configuration is added in logback.xml.
Please Note: Please change the log file location, mentioned in the logback.xml, as per your requirements.
In this file, I have used the log file location as: D:/projects/Logs/mqttclient.log 
Here is the logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <Pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>D:/projects/Logs/mqttclient.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover. Make sure the path matches the one in the file element or else
             the rollover logs are placed in the working directory. -->
            <fileNamePattern>D:/projects/Logs/mqttclient.%d.%i.log.gz</fileNamePattern>
            <!-- keep 30 days' worth of history -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>

        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.aj.mqttclient" level="info"
            additivity="false">
        <appender-ref ref="consoleAppender" />
        <appender-ref ref="FILE" />
    </logger>

    <root level="error">
        <appender-ref ref="consoleAppender" />
        <appender-ref ref="FILE"/>
    </root>
</configuration>

Step 3: Add MQTT Client Java class with main method

This is a Paho Java MQTT Client class.

Here is MQTTClient.java:

package com.aj.mqttclient;

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class MQTTClient {

    private static final Logger logger = LoggerFactory.getLogger(MQTTClient.class);

    public static void main(String[] args) {
        MqttClient mqttClient;
        String tmpDir = System.getProperty("java.io.tmpdir");
        String subscribeTopicName = "echo";
        String publishTopicName = "thing";
        String payload;
        MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(tmpDir);
        try {
            mqttClient = new MqttClient("tcp://localhost:1883", "thing1", dataStore);
            MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
            mqttConnectOptions.setUserName("/:guest");
            mqttConnectOptions.setPassword("guest".toCharArray());
            mqttConnectOptions.setCleanSession(false);
            mqttClient.connect(mqttConnectOptions);
            logger.info("Connected to Broker");
            mqttClient.subscribe(subscribeTopicName);
            logger.info(mqttClient.getClientId() + " subscribed to topic: {}", subscribeTopicName);
            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable throwable) {
                    logger.info("Connection lost to MQTT Broker");
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    logger.info("-------------------------------------------------");
                    logger.info("| Received ");
                    logger.info("| Topic: {}", topic);
                    logger.info("| Message: {}", new String(message.getPayload()));
                    logger.info("| QoS: {}", message.getQos());
                    logger.info("-------------------------------------------------");

                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                    logger.info("Delivery Complete");
                }
            });
            MqttMessage message = new MqttMessage();
            for (int i = 1; i < 6; i++) {
                payload = "Message " + i + " from Thing";
                message.setPayload(payload
                        .getBytes());
                logger.info("Set Payload: {}", payload);
                logger.info(mqttClient.getClientId() + " published to topic: {}", publishTopicName);
                //Qos 1
                mqttClient.publish(publishTopicName, message);
            }
        } catch (MqttException me) {
            logger.error("reason: {}", me.getReasonCode());
            logger.error("msg: {}", me.getMessage());
            logger.error("loc: {} ", me.getLocalizedMessage());
            logger.error("cause: {}", me.getCause());
            logger.error("excep: {}", me);
            me.printStackTrace();
        }
    }
}
In this class you can observe the following:
1. Create a new MQTT client and name it with a clientID as thing1. The server URI to conect to RabbitMQ is tcp://localhost:1883. Code for this is:
mqttClient = new MqttClient("tcp://localhost:1883", "thing1", dataStore);
2. RabbitMQ is a multi-tenant system at the core and every connection belongs to a virtual host. Hence we will be using the default virtual host / in RabbitMQ, default username: guest and default password: guest to connect to RabbitMQ. These need to be mentioned in MqttConnectOptions. Here is the code for this:
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setUserName("/:guest");
mqttConnectOptions.setPassword("guest".toCharArray());
3. Connect to MQTT Broker: RabbitMQ. Here is the code for this:
mqttClient.connect(mqttConnectOptions);
4. I am using the MQTT Client to both send and receive messages. I am subscribing to a topic named as echo. Here is the code to subscribe to a topic:
mqttClient.subscribe(subscribeTopicName);
5. I am publishing to a topic named as thing. I am publishing 5 messages to it using a for loop. Here is the code for this:
mqttClient.publish(publishTopicName, message);
6. There is standard callback code that I am setting to the MQTT Client to detect events like connectionLost, messageArrived and deliveryComplete. Here is the code for this:
mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable throwable) {
                    logger.info("Connection lost to MQTT Broker");
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    logger.info("-------------------------------------------------");
                    logger.info("| Received ");
                    logger.info("| Topic: {}", topic);
                    logger.info("| Message: {}", new String(message.getPayload()));
                    logger.info("| QoS: {}", message.getQos());
                    logger.info("-------------------------------------------------");

                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                    logger.info("Delivery Complete");
                }
            });

Application 2: Simple Java AMQP Client

        Ideally this code would run where ever RabbitMQ is running. RabbitMQ speaks multiple protocols. This tutorial uses AMQP, which is an open, general-purpose protocol for messaging. The Advanced Message Queuing Protocol (AMQP) is an open standard application layer protocol for message-oriented middleware. The defining features of AMQP are message orientation, queuing, routing (including point-to-point and publish-and-subscribe), reliability and security.

The AMQP Client can be coded in few simple steps.

Step 1: AMQP Client Dependency to be added in pom.xml. 

Here is the dependency:
    <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.0.0</version>
        </dependency>

Here is the full pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.aj.amqpclient</groupId>
    <artifactId>AMQPClient</artifactId>
    <version>1.0.0</version>


    <properties>
        <jdk.version>1.8</jdk.version>
        <logback.version>1.1.3</logback.version>
        <jcl.slf4j.version>1.7.12</jcl.slf4j.version>
        <packaging>jar</packaging>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${jcl.slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>

        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.0.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <createDependencyReducedPom>true</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.aj.amqpclient.AMQPClient</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
If you observe the pom.xml, I have added logging related dependencies to it.

Step 2: Add logback configuration in logback.xml

Basic file based and console based logging configuration is added in logback.xml.
Please Note: Please change the log file location, mentioned in the logback.xml, as per your requirements.
In this file, I have used the log file location as: D:/projects/Logs/amqpclient.log 
Here is the logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">

    <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <charset>UTF-8</charset>
            <Pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>D:/projects/Logs/amqpclient.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- daily rollover. Make sure the path matches the one in the file element or else
             the rollover logs are placed in the working directory. -->
            <fileNamePattern>D:/projects/Logs/amqpclient.%d.%i.log.gz</fileNamePattern>
            <!-- keep 30 days' worth of history -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>

        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d %-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="com.aj.amqpclient" level="info"
            additivity="false">
        <appender-ref ref="consoleAppender" />
        <appender-ref ref="FILE" />
    </logger>

    <root level="error">
        <appender-ref ref="consoleAppender" />
        <appender-ref ref="FILE"/>
    </root>
</configuration>

Step 3: Add AMQP Client Java class with main method

Here is AMQPClient.java:

package com.aj.amqpclient;

import com.rabbitmq.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.TimeoutException;


public class AMQPClient {

    private static final Logger logger = LoggerFactory.getLogger(AMQPClient.class);
    public static final String QUEUE_NAME = "mqttserver";

    public static void main(String[] args) throws IOException, InterruptedException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        String message;
        String sendTopicName = "echo";
        String receiveTopicName = "thing";
        factory.setHost("localhost");
        factory.setPort(5672);
        factory.setVirtualHost("/");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        channel.queueBind(QUEUE_NAME, "amq.topic", receiveTopicName);
        logger.info(" [*] Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                logger.info(" [x] Received '" + message + "'");
            }
        };
        channel.basicConsume(QUEUE_NAME, true, consumer);
        Thread.sleep(15000);
        for (int i = 1; i < 6; i++) {
            message = "Message " + i + " from AMQP Client!";
            channel.basicPublish("amq.topic", sendTopicName, null, message.getBytes("UTF-8"));
            logger.info(" [x] Sent '" + message + "'");
        }
    }
}
In this class you can observe the following:
1. A queue is the name for a post box which lives inside RabbitMQ. Although messages flow through RabbitMQ and your applications, they can only be stored inside a queue. It is a message buffer that RabbitMQ keeps on behalf of the consumer. So we need to name a queue for MQTT messages. Here is the code for this:
public static final String QUEUE_NAME = "mqttserver";
2. The connection abstracts the socket connection, and takes care of protocol version negotiation and authentication and so on for us. Here we connect to a broker on the local machine - hence the localhost. Here is the code for this:
factory.setHost("localhost");
factory.setPort(5672);
factory.setVirtualHost("/");
Connection connection = factory.newConnection();
3. Next we create a channel, which is where most of the API for getting things done resides. Here is the code for this:
Channel channel = connection.createChannel();
4. I am using the AMQP Client to both send and receive messages. To send and receive messages, we must declare a queue; then we can publish to and subscribe to messages on the queue. Here is the code for declaring a queue:
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
5. I am subscribing to a topic named as thing. Here is the code to consume messages:
channel.queueBind(QUEUE_NAME, "amq.topic", receiveTopicName);
        logger.info(" [*] Waiting for messages. To exit press CTRL+C");

        Consumer consumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
                    throws IOException {
                String message = new String(body, "UTF-8");
                logger.info(" [x] Received '" + message + "'");
            }
        };
        channel.basicConsume(QUEUE_NAME, true, consumer);
6. I am publishing to a topic named as echo. I am publishing 5 messages to it using a for loop. Here is the code for this:
for (int i = 1; i < 6; i++) {
            message = "Message " + i + " from AMQP Client!";
            channel.basicPublish("amq.topic", sendTopicName, null, message.getBytes("UTF-8"));
            logger.info(" [x] Sent '" + message + "'");
        }
7. One very important thing to note is that in both publish and subscribe I use amq.topic. The RabbitMQ MQTT plugin builds on top of RabbitMQ core protocol's entities: exchanges and queues. Messages published to MQTT topics use a topic exchange: amq.topic by default internally.

8. If you observe the code, I am using Thread.sleep(15000); so that I publish messages from the AMQP Client only 15 seconds after starting it.

For more details about a generic Java AMQP Client, check: RabbitMQ Website.

Project Setup:

For Java Setup, please refer to:  Java Setup
For Maven Setup, please refer to: Maven Setup
For Git and Project Setup, please refer to: Git and Project Setup

Run Application:

1. Start RabbitMQ

To start RabbitMQ use the command:
D:\Programs\RabbitMQ Server\rabbitmq_server-3.6.14\sbin>rabbitmq-server.bat start

2. Start AMQP Client by right clicking on the file in your IDE and running the main method (or) build a jar using the maven command:
mvn clean install
Then run the JAR by using the following command in the target folder in the Project folder location:
java -jar AMQPClient-1.0.0.jar

3. Start MQTT Client by right clicking on the file in your IDE and running the main method (or) build a jar using the maven command:
mvn clean install
Then run the JAR by using the following command in the target folder in the Project folder location:
java -jar MQTTClient-1.0.0.jar

Results

1. The AMQP Client has subscribed to the topic thing. Hence it will receive the 5 messages sent by the MQTT Client on thing. At the same time the AMQP Client publishes messages to the topic echo.

2. At the same time the MQTT Client has subscribed to the topic echo. Hence it will receive the 5 messages sent by the AMQP Client on the topic echo. This can be observed in the following 2 screenshots:

3. Open the RabbitMQ Console using the link: http://localhost:15672/mgmt
    Username: guest
    Password: guest
    In the tab Overview, you can observe the messages sent and received through RabbitMQ in a      graphical format.
    
    In the tab Connections, you can observe 2 connections; one from the MQTT Client and the other from the AMQP Client

    In the tab Queues, you can observe 2 queues; one of the MQTT Client named as: mqtt-subscription-thing1qos1 and the other from the AMQP Client named as: mqttserver
 In the tab Admin->Virtual Hosts, you can see the default virtual host named as / to which default user guest has access.

Conclusion and GitHub link: 

    This tutorial gives an overview of end to end software development of IoT based applications using MQTT Protocol. To get your application to Production grade, you may have to think of security related aspects like HTTP Authentication to all clients accessing the MQTT broker, consumption and usage of messages received by MQTT broker, a generic application to send messages to MQTT broker instead of the Simple AMQP client that I have used and so on.
You can check the GitHub code for the MQTT Client used in this post by going to the link: MQTT Client.
You can check the GitHub code for the AMQP Client used in this post by going to the link: AMQP Client.
    Learn the most popular and trending technologies like Machine Learning, Angular 5, Internet of Things (IoT), Akka HTTP, Play Framework, Dropwizard, Docker, Elastic Stack, Spring Boot and Flask in simple steps by reading my most popular blog posts at Software Developer Central.
    If you like my post, please feel free to share it using the share button just below this paragraph or next to the heading of the post. You can also tweet with #SoftwareDeveloperCentral on Twitter. To get a notification on my latest posts or to keep the conversation going, you can follow me on Twitter. Please leave a note below if you have any questions or comments.

Comments

Post a Comment

Popular Posts

REST API using Play Framework with Java

Asynchronous Processing (@Async) in Spring Boot

Elasticsearch, Logstash, Kibana Tutorial: Load MySQL Data into Elasticsearch