Posted in Information Technology

Internet of Things (IoT) with Redis, NodeMCU and Spring boot

https://medium.com/@dinethchalitha/internet-of-things-iot-with-redis-nodemcu-and-spring-boot-3d3291484b11

If things connected with network it doesn’t mean it’s “smart”.Truly smart devices provide valuable services, are trusted, and are easy to use. This Make your life easier by implementing your own IoT solution as smart way.

Redis is an open source in memory database,cache and message broker. Redis supports various types of data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries.

Most Off other database require considerable amount of resources for handle millions of transactions.Also it may be difficult to handle real-time analytics.
Redis use minimum amount of resources and it has in built data structures, modules are advantage in delivering reliable IoT solutions.

NodeMCU is an open source IoT platform.The NodeMCU development board is a powerful solution to program micro-controllers. This is a cute module with a micro-controller, integrated Wi-Fi receiver, and transmitter.

Let’s start implement a scenario using a smart database and a cute module. 🙂

This is a very simple scenario. If you are not familiar with nodemcu/esp8266 you can refer this (https://www.instructables.com/id/Quick-Start-to-Nodemcu-ESP8266-on-Arduino-IDE/).

Scenario —

Here NodeMCU board connected with DHT11 sensor, redis db and home wifi network. Basically sensor send the data to NodeMCU and it directly update the redis cache via TCP call.Here redis db is available in another host (PC).After Spring boot app read the data from redis cache and those data will expose as a rest service.

High level architecture.

Hardware implementation

required resources

  • NodeMCU development board.
  • DHT11 sensor module.
  • breadboard and jumping wires(optional).
Hardware deployment diagram
  • Pin 1 goes into +3v.
  • Pin 2 of the DHT11 goes into Digital Pin D4.
  • Pin 3 of the DHT11 goes into Ground Pin (GND).
Hardware implementation

Arduino Code has implemented following functions.

  • Connect with WiFi connection.
  • Connect with redis Connection.
  • Reading data from DHT11 Sensor.
  • Get current time using NTPClient.
  • Send the data to redis cache.

Arduino full source code.

//network SSID (name)
#define WIFI_SSID "DCB"
#define WIFI_PASS "dcbdcb123bcd"
//redis config
#define REDISHOST "192.168.8.101"
#define REDISPORT 6379
#include <ESP8266WiFi.h>
#include <DHT.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
DHT dht;
#define NTP_OFFSET   60*60*5// In seconds
#define NTP_INTERVAL 60 * 1000    // In miliseconds
#define NTP_ADDRESS  "www.sltime.org"
WiFiClient redis;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, NTP_OFFSET,  NTP_INTERVAL);
String dayStamp;
String timeStamp;
String formattedTime;
String formattedDate;
float humidity;
float temperature;
String key;
String sensorData;
void setup() {
  Serial.begin(115200);
  
  Serial.println("Serial initialized.");
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  
  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion 
    delay(500);
    Serial.println("Waiting for connection"); 
  }
  Serial.println("");
  Serial.print("WiFi (");
  Serial.print(WiFi.macAddress());
  Serial.print(") connected with IP ");
  Serial.println(WiFi.localIP());
  Serial.print("DNS0 : ");
  Serial.println(WiFi.dnsIP(0));
  Serial.print("DNS1 : ");
  Serial.println(WiFi.dnsIP(1));
//set the DHT11 output datapin 
  dht.setup(D4);
  timeClient.begin();
  timeClient.setTimeOffset(3600); 
}
void loop() {
  timeClient.update();
  formattedTime = timeClient.getFormattedTime();
  formattedDate = timeClient.getFormattedDate();
//Extract Time and Date
  int splitT = formattedDate.indexOf("T");
  dayStamp = formattedDate.substring(0, splitT);
  timeStamp = formattedDate.substring(splitT+1, formattedDate.length()-1);
if (!redis.connected()) {
      Serial.print("Redis not connected, connecting...");
      if (!redis.connect(REDISHOST,REDISPORT)) {
        Serial.print  ("Redis connection failed...");
        Serial.println("Waiting for next read");
        return; 
      } else
        Serial.println("OK");
    }
humidity = dht.getHumidity();/* Get humidity value */
    temperature = dht.getTemperature();
    key = "DHT11:AreaX1";
    sensorData= "DATE: "+dayStamp+" TIME:"+timeStamp+" humidity:"+String(humidity)+" temperature:"+String(temperature);
    
    Serial.print("Time Formatted : ");
    Serial.println(formattedTime);
//
redis.print(
      String("*3\r\n")
      +"$5\r\n"+"LPUSH\r\n"
      +"$"+key.length()+"\r\n"+key+"\r\n"
      +"$"+sensorData.length()+"\r\n"+sensorData+"\r\n"
    );
    
  while (redis.available() != 0)
    Serial.print((char)redis.read());
    delay(10000);/* Delay of amount equal to sampling period */
}

Redis Database setup

Download redis — https://redis.io/download

wget http://download.redis.io/redis-stable.tar.gz
tar xvzf redis-stable.tar.gz
cd redis-stable
make

Now, copy redis-server,redis-client from the redis-stable/src and paste it into two different directories.

Start the redis-server

./redis-server

Next, navigate to redis-client directory and connect to redis server with running the following command.

./redis-client

After entering the monitor command, you can monitor the redis operation.

Spring App

This service will handle post requests for /getSensorData , optionally with a reqData parameter will use to query the latest number of data from redis cache . The post request should return the required number of data as a json response to client.

Here, I used the Jedis client to connect with redis database.

@Controller
@RequestMapping("/")
public class WebController {
@Autowired
private RedisUtil util;
private JedisPool jedisPool = null;
@RequestMapping(value = "/getSensorData", method = RequestMethod.POST)
    public @ResponseBody List<String> findValue(@RequestBody SensorData sensorData,@RequestParam("reqData") int reqData) {
        List<String>  retrieveMap=null;
        jedisPool = util.getJedisPool();
        try (Jedis jedis = jedisPool.getResource()) {
           String key=getListKey(sensorData.getSensorType(),sensorData.getSensorLocation());
           retrieveMap = jedis.lrange(key, 0, reqData);
        }
        return retrieveMap;
    }
private String getListKey(String sensorType,String location){
        return sensorType+":"+location;
    }
}

Sample request .

POST /getSensorData?reqData=3 HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
 "sensorType":"DHT11",
 "sensorLocation":"AreaX1"
}

Response related to above request.

[
    "DATE: 2018-08-18 TIME:17:19:46 humidity:93.00 temperature:28.00",
    "DATE: 2018-08-18 TIME:17:19:36 humidity:92.00 temperature:28.00",
    "DATE: 2018-08-18 TIME:17:19:26 humidity:92.00 temperature:28.00",
    "DATE: 2018-08-18 TIME:17:19:16 humidity:93.00 temperature:28.00"
]

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s