AWS IOT activate a Relay via mqtt and ArduinoYun

Hi,

I created a project with an ArduinoYUN and Temp sensor. Every 5 seconds the sensor send info to AWS IOT platform.

Now I wold like to Publish a topic to Another YUN and this activate a relay. Does anybody how to do it?

This is the scketck for the sensor Arduino:

#include <aws_iot_mqtt.h>
#include <aws_iot_version.h>
#include "aws_iot_config.h"
aws_iot_mqtt_client myClient; // init iot_mqtt_client
char msg[32]; // read-write buffer
int cnt = 0; // loop counts
int rc = -100; // return value placeholder
bool success_connect = false; // whether it is connected

#include <ArduinoJson.h>
char data[80];
StaticJsonBuffer<200> jsonBuffer;
#include <Process.h>
Process date;                 // process used to get the date
#include "DHT.h" //cargamos la librería DHT
#define DHTPIN 2 //Seleccionamos el pin en el que se conectará el sensor
#define DHTTYPE DHT22 //Se selecciona el DHT22(hay otros DHT)
DHT dht(DHTPIN, DHTTYPE); //Se inicia una variable que será usada por Arduino para comunicarse con el sensor
const int moisturePin = A1;    // Grove Moisture sensor connected to A1 on the Grove Shield
const int ledPin = 2;
int moisturValue = 0;  // variable to store the Moisture Sensor
const int lightPin = A2; //variable to store the Light Sensor



// Basic callback function that prints out the message
void msg_callback(char* src, int len) {
  Serial.println("CALLBACK:");
  int i;
  for(i = 0; i < len; i++) {
    Serial.print(src[i]);
  }
  Serial.println("");
}


void setup() 
 {
  // Start Serial for print-out and wait until it's ready
    Serial.begin(115200);
  while(!Serial);
  dht.begin(); //Se inicia el sensor
  Bridge.begin();        // initialize Bridge
  //
  char curr_version[80];
  snprintf_P(curr_version, 80, PSTR("AWS IoT SDK Version(dev) %d.%d.%d-%s\n"), VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
  Serial.println(curr_version);
  // Set up the client
  if((rc = myClient.setup(AWS_IOT_CLIENT_ID)) == 0) {
    // Load user configuration
    if((rc = myClient.config(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH, AWS_IOT_PRIVATE_KEY_PATH, AWS_IOT_CERTIFICATE_PATH)) == 0) {
      // Use default connect: 60 sec for keepalive
      if((rc = myClient.connect()) == 0) {
        success_connect = true;
        // Subscribe to "topic1"
        if((rc = myClient.subscribe("topic1", 1, msg_callback)) != 0) {
          Serial.println("Subscribe failed!");
          Serial.println(rc);
        }
      }
      else {
        Serial.println(F("Connect failed!"));
        Serial.println(rc);
      }
    }
    else {
      Serial.println(F("Config failed!"));
      Serial.println(rc);
    }
  }
  else {
    Serial.println(F("Setup failed!"));
    Serial.println(rc);
  }
  // Delay to make sure SUBACK is received, delay time could vary according to the server
  delay(2000);
}
void loop() {
  //Lectura Hora de Sistema
  date.begin("/bin/date");
  date.addParameter("+%d/%m/%Y %T");
  date.run();
  String timeString = date.readString();    
  
  
  //Lecturas de Sensores
  float humity = dht.readHumidity(); //Se lee la humedad
  int temperature = dht.readTemperature(); //Se lee la temperatura
  moisturValue = analogRead(moisturePin);//Se lee la humedad del suelo
  int lightValue = analogRead(lightPin); //Se lee la luz solar
    
  //Se imprimen las variables
     //sprintf(msg,"\"Temperature\": %d", temperature);
    Serial.print("moisture = " ); Serial.println(moisturValue); //Check the Value for with Dry sand and then with Wet Sand   
    Serial.print("light value = ");  Serial.println(lightValue);   
    Serial.print("Temperatura= ");Serial.println(temperature);
    Serial.print("Humedad= ");Serial.println(humity);
 
   //Creating the JSON payload  
 String temp = "\"Temperature\": " + String(temperature) ;
 String humi = ", \"Humity\": " + String(humity) ;
 String light = ", \"lightval\":" + String(lightValue) ;
 String soilMoist = ", \"moistval\":" + String(moisturValue) ;
 // Add both value together to send as one string. 
 String value = temp + humi + light +soilMoist;
 Serial.println(value);
 String payload = "{" + value + "}";
 payload.toCharArray(data, (payload.length() + 1));
  
  //Json File
  //Serial.print("\{");Serial.print("\"Id\":\"001\"\,");Serial.print("\"Date\":\"");Serial.print(timeString);Serial.print("\"\,"); Serial.print("\"Temperature\":\"");Serial.print(t);Serial.print("\"");Serial.println("\}");
  delay(10000); //Se espera 10 segundos para seguir leyendo //datos
 
 //Publish data to AWS IoT using  topic/plantdata,which in turn will fire the AWS IoT rule to write sensor data to Dynamo DB
 if(success_connect) {
    // Generate a new message in each loop and publish to "topic/plantdata" 

    if((rc = myClient.publish("topic1", data, strlen(data), 1, false)) != 0) {
      Serial.println("Publish failed!");
      Serial.println(rc);
    }
  
    // Get a chance to run a callback
    if((rc = myClient.yield()) != 0) {
      Serial.println("Yield failed!");
      Serial.println(rc);
    }
  
    // Done with the current loop
    sprintf(msg, "publish %d done", cnt++);
    Serial.println(msg);
  
    delay(10000);
  }

 // }//end if checking for time interval to post 
  delay(5000);
}

Thank you very much

Eduard

Hi, Can you please give some more detail on your setup? I do not understand the relay part. In general you have a mqtt broker and all the iot devices connect to that broker. In your case I would think that both your yuns will connect to the mqtt broker. Br, Martijn

Hi, I'm'using Amazon IOT as a broker, the problem is I have another arduino to control a pump, and I have no idea how to when AWS IOT sends a topic to this pump the pump starts

I did not have idea how to setup the YUn as a subscriber, process the data and the activates or not the pump.

For example, when the Sensor unit send a moisture value lower than 100, the aws console process this info and sends a topic called Relay1 with value 1. This activates the pump.

Many many thank's for your help.

Best

Eduard

Hi Eduard, I want to help you, but I do not understand your setup. Can you make a drawing of your setup and with the communication between them? Br, Martijn

Hi Martijn,

First of all thank’s for your help and patience.

See the drawing attached

Many thank’s

Now I understand the setup. And if I’m correct you do not understand how to subscribe, correct? Please check following tutorial:
http://www.martijnschut.nl/arduino-yun-mqtt-tutorial/

This should explain how to subscribe to a topic and sent the value to control the pump

Hi Martijn,

I read the article and still witout understand the language. I’m writting the scketch wit Arduino’s IDE, and with this script I could not configure the Arduino’s pump…

See attached the basic scketch that I use to configure the sensor to AmazonWS IOT…is it possible to modify this sketch to receive data from server and then activate a relay?

Many thank’s again for you patience

Eduard

arduino.txt (2.9 KB)

Hi,
I think that you can use the yun the best to its potential to use the mcu part to control the pump and the openwrt part to handle the mqtt messages. And the bridge between the both of them for communication.

This means a python script on the openwrt side which communicates via the yunbridge to the mcu where you can upload a sketch which reads the value on the bridge.

I can help you with this and I know that this is gonna work. If you want that all be controlled on the mcu/sketch side I cannot help you.

So can you login via ssh to the yun? If yes, I will help you with the steps for the python script.

Hi Martijn

As you can see I’m a newbye and I appreciate being advised for the people who controls the situation :wink:

Yes, I can acces ssh to the yun…I have full control.

If you come to Barcelona a paella is waiting you :wink:

Many thank’s again

Eduard

Excellent!

So we are going to do the next two steps:
1.) build python script to communicate with the broker
2.) Arduino sketch to control your pump (for now we will use the led on your arduino)
And we will use the arduino yun bridge for communication between the sketch (MCU) and openwrt (MPU).

Login via ssh to your yun and check if pip has been installed. Just run pip pn the command line. If not please follow: Using pip to install python packages on the Arduino Yún | Sam Brenner

Now we are going to install the python mqtt lib and an easy to use editor (nano).

opkg update
opkg install nano
pip install paho-mqtt

Now the lib has been installed we are going to make the python script. So execute: nano mqtt.py and paste and modify the followng code:

#!/usr/bin/python
import sys
import paho.mqtt.client as mqtt

sys.path.insert(0, '/usr/lib/python2.7/bridge/')

from bridgeclient import BridgeClient as bridgeclient

from tcp import TCPJSONClient
json = TCPJSONClient('127.0.0.1', 5700)

value = bridgeclient()


# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, rc):
    print("Connected with result code "+str(rc))
        # Subscribing in on_connect() means that if we lose the connection and
        # reconnect then subscriptions will be renewed.
    client.subscribe("arduino/led")

#subscribe to the right topic

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
        print(msg.topic+" "+str(msg.payload))
        json.send({'command':'put', 'key':'led', 'value':msg.payload})

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

# use the dns name or ip address from AWS IOT mqtt broker
client.connect("192.168.x.x", 1883, 60)

# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()

You can execute this python script: python mqtt.py

Now upload the arduino code:

#include <Bridge.h>
#include <stdio.h>
 
// Here we will hold the values coming from Python via Bridge.
char ledvalue[2];
 
void setup() {
  // Zero out the memory we're using for the Bridge.
  memset(ledvalue, 0, 2);
   
  // Initialize digital pins 13 as output.
  pinMode(13, OUTPUT); 
 
  // Start using the Bridge.
  Bridge.begin();
}
 
void loop() {
  
  
  // Write current value of D13 to the pin (basically turning it on or off).
  Bridge.get("led", ledvalue, 2);
  int ledD13 = atoi(ledvalue);
  digitalWrite(13, ledD13);
   
  delay(10);  
}

If you now publish ‘1’ or ‘0’ to your subscribed topic you can control the LED on your yun. This sketch can be the basis to control your pump.

Hi Martijn,

Sorry to not answer till today, but I was on a travel :-(

First, Many thank's for your help. I just installed the software in my Yun, and now I'm making the py files.

In the mqtt.py file, what I sould I modify?

1º The topic Arduino/led for my topic relay1? 2º The ip address from AWS IOT mqtt broker, I have no idea, do you know where it is?

did I have to modify anything else?

Thank you very much

Eduard

Hi Eduard,

Correct you should modify the mqtt.py file and both the topic and ip address should be modified.

I never worked with AWS IoT and now I see that they use a certificate.

You can read more about here:

https://www.hackster.io/mariocannistra/python-and-paho-for-mqtt-with-aws-iot-921e41

I will also make my own account and will help you further, this will only take more then a week due to holiday with my familiy.

Martijn

Hi Martijn,

I read the article and I saw that it’s for a Rasberry but I thing it’s the same code. See attached the subscriber and the publisher code files.

I was comparing with your code and basically i saw a difference with the way to connect with AWS.

Is it possible to use your code with the conncetion setup used in the project?

WOW many thank’s for your help and patience, but there is no place to learn this kind of thinks

Eduard

awsiotpub.py.txt (1.7 KB)

awsiotsub.py.txt (1.42 KB)

I just did a quick check. We need to update my code with the right credentials. See below. I got it working on ubunutu. But it should also work on your yun.

If you login to aws and choice the IoT service, you ca create your "own thing". Once created you can push the button "Connect device" (button below).

No you can download the appropriate certificates. Please also download the Root CA (save file). If you push next you will see the names which yu can use below.

Now you have them local, please upload them to your Yun. You need to upload the CA root, AWS_IOT_CERTIFICATE and AWS_IOT_PRIVATE_KEY certficates. Put them into your directory of your source code. Now I alreadt changed the source code for you. You only need to update CA root, private and CERT name in the source file.

#!/usr/bin/python
import sys
import paho.mqtt.client as mqtt

sys.path.insert(0, '/usr/lib/python2.7/bridge/')

from bridgeclient import BridgeClient as bridgeclient

from tcp import TCPJSONClient
json = TCPJSONClient('127.0.0.1', 5700)

value = bridgeclient()


# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, rc):
    print("Connected with result code "+str(rc))
        # Subscribing in on_connect() means that if we lose the connection and
        # reconnect then subscriptions will be renewed.
    client.subscribe("#")

#subscribe to the right topic

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
        print(msg.topic+" "+str(msg.payload))
        json.send({'command':'put', 'key':'led', 'value':msg.payload})

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

awshost = "[check the config].iot.eu-central-1.amazonaws.com"
awsport = 8883
clientId = "arduinoyun" #name of your device
thingName = "arduinoyun" #name of your device

caPath = "root-CA.crt" #name to the CA root, change the file to root-CA.crt
certPath = "xxxxxxxx-certificate.pem.crt" # AWS_IOT_CERTIFICATE_FILENAME, change xxxxx to the downloaded file
keyPath = "xxxxxxxx-private.pem.key" # AWS_IOT_PRIVATE_KEY_FILENAME, change xxxxx to the downloaded file

mqttc.tls_set(caPath, certfile=certPath, keyfile=keyPath, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)

mqttc.connect(awshost, awsport, keepalive=60)


# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
client.loop_forever()

Maybe you need to install SSL: pip install ssl

Run the file: python [yourname.py] Now you will get: Connection returned result: 0 The subscribed topic is '#' so the un will receive all the topics.

Good luck!

Hi Martijn

We are heading to the end of this :-), but I did the python.py file, and when I executed, i received this response (response attached)

You know why?

Many thank’s

Eduard

error.png

mqttc.tls_set(caPath, certfile=certPath, keyfile=keyPath, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)

mqttc.connect(awshost, awsport, keepalive=60)

--> change mqttc to client

client.tls_set(caPath, certfile=certPath, keyfile=keyPath, cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)

client.connect(awshost, awsport, keepalive=60)

Hi Martijn

I updated the filed but I had the same error, did you test it in an Arduino?

many thank's....

Eduard