Jorge
Created March 13, 2019 © GPL3+

Maintenance Buttler

Let your maintenance bot tell you what's going on with your equipment.

IntermediateFull instructions provided10 hours42
Maintenance Buttler

Things used in this project

Hardware components

Raspberry Pi Zero Wireless
Raspberry Pi Zero Wireless
×1
Automation HAT
Pimoroni Automation HAT
×1
pt100 4-20 ma transmitter
×1
PT100 RTD
×1
drok current to voltage converter
×1
drok 0-10V 4-20ma simulator
×1
Water Level Sensor switch
×1
SORACOM Air Global IoT SIM
SORACOM Air Global IoT SIM
×1

Software apps and online services

AWS IoT
Amazon Web Services AWS IoT
SORACOM Funnel
SORACOM Funnel
SORACOM Air IoT Connectivity Platform
SORACOM Air IoT Connectivity Platform
AWS Lambda
Amazon Web Services AWS Lambda
AWS DynamoDB
Amazon Web Services AWS DynamoDB
AWS Lex Bot
Python

Story

Read more

Schematics

Connection Diagram of Simulator

This is how I connected things to the RPI automation HAT to control and acquire the signals

Connection Diagram

This is how wired the simulator to the raspberrry pi automation hat

Code

lexResponses.js

JavaScript
module.exports.delegate=function(sessionAttributes,slots){
    return{
        sessionAttributes,
        dialogAction:{
            type:"Delegate",
            slots,
        },
    };
}

module.exports.close = function(sessionAttributes, fulfillmentState, message){
    return {
        sessionAttributes,
        dialogAction:{
            type:"Close",
          fulfillmentState,
          message,
        },
    };
}

dispatch.js

JavaScript
This is the dispatcher fo the lambda function
'use strict';

const SensorValue = require('./SensorValue');

module.exports = function(intentRequest,callback) {
  console.log(`dispatch userId=${intentRequest.userId}, intentName=${intentRequest.currentIntent.name}`);
  const intentName = intentRequest.currentIntent.name;// we get the intent that was called

 
  if (intentName === 'GetSensorValue') {// if the intent is GetSensorValue we call the function SensorValue
    console.log(intentName + ' was called');
      return SensorValue(intentRequest,callback);
    //return GetSensorValue(intentRequest);
  }

  if (intentName === 'GreetingIntent') {
    return greetUser(intentRequest);
  }

  throw new Error(`Intent with name ${intentName} not supported`);
};

handler.js

JavaScript
We call dispatch when entering the lambda function
'use strict';
const dispatch =require('./dispatch');

module.exports.intents =(event,context, callback)=>{
    try{
        console.log(`event.bot.name=${event.bot.name}`);
        dispatch(event,(response)=> callback(null,response));// this function is called..
    }catch(err){
        callback(err);
    }
    };

SensorValue.js

JavaScript
Code that fullfills the get sensor intent from lex querying the dynamodb to look for the sensor info
'use strict';
const lexResponses =require("./lexResponses")
const AWS =require("aws-sdk");
const ddb = new AWS.DynamoDB({apiVersion: '2012-08-10'});
const docClient = new AWS.DynamoDB.DocumentClient();



module.exports = function(intentRequest,callback){
    // We get the slot information this will be the slot NAME not the slot type !!!!
    var sensor=intentRequest.currentIntent.slots.sensor;
    var sensorPlace= intentRequest.currentIntent.slots.place;
    var SensorResponse=0;
    console.log("called : "+sensor + "in " +sensorPlace);

    const source= intentRequest.invocationSource;
    console.log(source);

    if (source ==="DialogCodeHook"){
        callback(lexResponses.delegate(intentRequest.sessionAttributes, intentRequest.currentIntent.slots));
        return;
    }

    if(source==="FulfillmentCodeHook"){

                  console.log("is a fullfilment");
                  //---Code to extract from DynamoDB
                        var requestedtype=sensor;// type of sensor
                        var foundimei="";
                        var sensortype=""

                    //Query to find Sensor Imeis based on the place
                    var paramsSensor = {
                    TableName: 'devices',
                    KeyConditionExpression: "#ro = :roomname",
                    ExpressionAttributeNames: {
                          "#ro": "room"
                      },
                    ExpressionAttributeValues: {
                          ":roomname": sensorPlace,
                      }

                    };


                    /// queryyyy
                    //-- Function to Find imei based on the place
                    //-- We get the place from Lex Bot
                    docClient.query(paramsSensor, function(err, data) {
                    if (err) {
                      console.log("Error on lambda", err);
                    } else {

                      //console.log("Success", data.Items);
                      //console.log(typeof(data))
                      console.log(data)
                      console.log("Sensory Type: "+data.Items[0].type);//Type of Sensor


                      // Iterate over the array
                      data.Items.forEach(function(element, index, array) {
                      //console.log("Sensor types is : "+element.type+" With Imei : "+element.deviceid);
                      if(element.type=="multiple")
                      {
                        console.log("is Multiple");
                        console.log("Imei is "+element.deviceid);
                        foundimei=element.deviceid;
                        sensortype="multiple";
                      }else{
                        console.log("is single");
                        console.log("Imei is "+element.deviceid);
                        foundimei=element.deviceid;
                        sensortype="single";
                      }

                      });


                      //--Query to  get the sensor value
                      var paramsQuery = {
                        TableName: 'challenge6',
                        KeyConditionExpression: "#im = :imeinumber",
                        ExpressionAttributeNames: {
                            "#im": "imei"

                      },
                      ExpressionAttributeValues: {
                          ":imeinumber": foundimei

                      },
                      ScanIndexForward: false,
                      Limit:1

                  };

                    console.log("found imei = "+foundimei);
                    docClient.query(paramsQuery, function(err, data) {
                    if (err) {
                      console.log("Error on lambda", err);
                    } else {
                                var sensorkey="";
                                //console.log("Success", data.Items);
                                //console.log(typeof(data))
                                if(sensortype=="multiple"){
                                      console.log(data)
                                      data.Items.forEach(function(element, index, array) {
                                      //  console.log(Object.keys(data.Items.payloads[0]));
                                    //  if(Object.keys()==requestedtype)
                                      //    {
                                      console.log(element);
                                      Object.entries(element.payloads).forEach(entry => {
                                              let key = entry[0];

                                              let value = entry[1];
                                              //use key and value here
                                              console.log("key "+key);
                                              console.log("value "+ value);
                                              if(key==requestedtype)
                                              {
                                                SensorResponse=value;
                                                sensorkey=key;
                                              }

                                            });

                                      //   }
                                    });

                                    var sensorresponse="The "+sensorkey+" is "+SensorResponse;
                                      console.log("content response "+sensorresponse);
                                      callback(lexResponses.close(intentRequest.sessionAttributes,"Fulfilled",{contentType: "PlainText", content: sensorresponse}));
                                    }// End of sensor Multiple


                              }// End of else of query
                  });// en dof query to find value of temperature



                    }
                    });// en dof query for Sensor name to find imei



                  //-- End of code to extract from dynamoDB





    }//--- End of fullfilment
}

Python Code For automation Hat

Python
This will acquire the signals an convert them to send them to funnel in soracom
import sys, time, requests, json,random
from statistics import mean
import automationhat
time.sleep(0.1)



def Relay1_ON():
    automationhat.relay.one.on()

def Relay1_Off():
    automationhat.relay.one.off()

def Analog1():
    return (automationhat.analog.one.read()/0.02127-50)
def Analog2():
    return (automationhat.analog.two.read()*10)
def Analog3():
    average=[]
    for x in range(60):
        average.append(automationhat.analog.three.read())
    ##print("average is :")
    #print(average)
    print(max(average))
    print(min(average))
    return mean(average)

def Input1():
    if automationhat.input.one.read()==1 :
        return True
    else:
        return False


def SendFunnel(payload):
    headers = {'Content-Type': 'application/json'}

    print("- sending data to funnel")
    try:
            r = requests.post('http://funnel.soracom.io', data=json.dumps(payload), headers=headers, timeout=5)
            print(r)
    except requests.exceptions.ConnectTimeout:
            print('ERROR: connection timeout. Is 3G connection online?')

            #if r.status_code == 400:
            #    print('ERROR: failed to submit data. Did you configure Funnel for your SIM?')

Relay1_ON()
while True:
    print("Analog")
    ac=Analog3()
    print("------")
    temperature=Analog1()
    humidity=Analog2()
    TankLimit=Input1()
    print(temperature)
    print(humidity)
    print(TankLimit)
    print(ac)
    print("---------------")
    payload = {'temperature':temperature,"humidity":humidity,"overflow":TankLimit}

    SendFunnel(payload)
    ##print(payload)
    time.sleep(20)

Credits

Jorge

Jorge

3 projects • 8 followers
I am a EE that enjoys doing projects at home having fun with electronics. I like the world of Internet of things. www.seasluglabs.io

Comments