element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
IoT: In the Cloud
  • Challenges & Projects
  • Project14
  • IoT: In the Cloud
  • More
  • Cancel
IoT: In the Cloud
Blog Arduino MKR 10xx, ETH Shield and Amazon Web Services: Safe MQTT with SSL and Certificate
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join IoT: In the Cloud to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 8 Sep 2019 3:02 PM Date Created
  • Views 3137 views
  • Likes 5 likes
  • Comments 2 comments
  • p14 mkr 1010
  • ardino_mkr
  • aws
  • iot
  • arduino
Related
Recommended

Arduino MKR 10xx, ETH Shield and Amazon Web Services: Safe MQTT with SSL and Certificate

Jan Cumps
Jan Cumps
8 Sep 2019

We'll connect an Arduino MKR to AWS IoT with an Ethernet cable and the MKR ETH shield.

I've done this before on a MKR1010 with WiFi. This post uses the same example, with a wired Ethernet solution.

image

With this example, you can safely connect to AWS and interact with their MQTT service.

 

What do you need?

 

  • An Arduino MKR Arduino MKR. Any will do, MKR1000, 1010, .....
  • An Arduino MKR ETH shieldArduino MKR ETH shield mounted on it
  • An internet connected Ethernet cable plugged into the shield.

 

For the setup of AWS, I'd like to point you to my previous AWS + WiFi blog. All provisionings are the same.

If you've built that example, you can reuse the same AWS "SECRET_BROKER" and "SECRET_CERTIFICATE".

If not, check the post and get your Arduino MKR set up as a thing".

 

Sketch Differences between WiFi and Wired Ethernet example

 

There's not that much to change. Where I used the WiFI Arduino libraries in the previous post, this time I use the Ethernet libraries.

 

The connection object is different:

 

EthernetClient client;

 

But the SSL library accept it just the same as a WiFI connection (hooray for C++).

 

BearSSLClient sslClient(client); // Used for SSL/TLS connection

 

The biggest change was in the getTime() method in the WiFi example. A reasonable exact time is needed to validate the certificates.

In the WiFi example, the sketch uses the WiFi lib's getTime() command. But the Ethernet library doesn't have such a function.

Fortunately for us, there's an UdpNtpClient example for Ethernet. A sketch that gets the current time from the time.nist.gov NTP server.

I used the core of that example to retrieve the time. I've also copied the Ethernet connectivity approach from it.

 

image

 

In the code below, you can see the full sketch, with connection to Amazon Web Services and the time server.

The example posts an MQTT message every 5 seconds (to arduino/outgoing) and also subscribes to a topic (arduino/incoming).

 

/*
  AWS IoT ETH


  This sketch securely connects to an AWS IoT using MQTT over Ethernet.
  It uses a private key stored in the ATECC508A and a public
  certificate for SSL/TLS authetication.


  It publishes a message every 5 seconds to arduino/outgoing
  topic and subscribes to messages on the arduino/incoming
  topic.
*/

#include <ArduinoBearSSL.h>
//#include <ArduinoECCX08.h>
#include <ArduinoMqttClient.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

#include "arduino_secrets.h"

/////// Enter your sensitive data in arduino_secrets.h
const char broker[]      = SECRET_BROKER;
const char* certificate  = SECRET_CERTIFICATE;

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

// time service
unsigned int localPort = 8888;       // local port to listen for UDP packets
const char timeServer[] = "time.nist.gov"; // time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
// A UDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
BearSSLClient sslClient(client); // Used for SSL/TLS connection, integrates with ECC508
MqttClient    mqttClient(sslClient);

unsigned long lastMillis = 0;

void setup() {
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);
  
  Ethernet.init(5);   // MKR ETH shield

  Serial.begin(115200);
  while (!Serial);
    
  // start Ethernet and UDP
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // Check for Ethernet hardware present
    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    } else if (Ethernet.linkStatus() == LinkOFF) {
      Serial.println("Ethernet cable is not connected.");
    }
    // no point in carrying on, so do nothing forevermore:
    while (true) {
      delay(1);
    }
  }

  Udp.begin(localPort);  

  // Set a callback to get the current time
  // used to validate the servers certificate
  ArduinoBearSSL.onGetTime(getTime);

  // Set the ECCX08 slot to use for the private key
  // and the accompanying public certificate for it
  sslClient.setEccSlot(0, certificate);

  // Optional, set the client id used for MQTT,
  // each device that is connected to the broker
  // must have a unique client id. The MQTTClient will generate
  // a client id for you based on the millis() value if not set
  //
  // mqttClient.setId("clientId");

  // Set the message callback, this function is
  // called when the MQTTClient receives a message
  mqttClient.onMessage(onMessageReceived);
}

void loop() {

  if (!mqttClient.connected()) {
    // MQTT client is disconnected, connect
    connectMQTT();
  }

  // poll for new MQTT messages and send keep alives
  mqttClient.poll();


  // publish a message roughly every 5 seconds.
  if (millis() - lastMillis > 5000) {
    lastMillis = millis();

    publishMessage();
  }
}

unsigned long getTime() {
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  unsigned long epoch = 0UL;

  // wait to see if a reply is available
  delay(1000);
  if (Udp.parsePacket()) {
    // We've received a packet, read the data from it
    Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer

    // the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, extract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    Serial.print("Seconds since Jan 1 1900 = ");
    Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    epoch = secsSince1900 - seventyYears;
    Serial.println(epoch);    
  }
  return epoch;
}

// send an NTP request to the time server at the given address
void sendNTPpacket(const char * address) {
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(address, 123); // NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

void connectMQTT() {
  Serial.print("Attempting to MQTT broker: ");
  Serial.print(broker);
  Serial.println(" ");

  while (!mqttClient.connect(broker, 8883)) {
    // failed, retry
    Serial.print(".");
    delay(5000);
  }
  Serial.println();

  Serial.println("You're connected to the MQTT broker");
  Serial.println();

  // subscribe to a topic
  mqttClient.subscribe("arduino/incoming");
}

void publishMessage() {
  Serial.println("Publishing message");

  // send message, the Print interface can be used to set the message contents
  mqttClient.beginMessage("arduino/outgoing");
  mqttClient.print("{\n\"message\": \"hello\",\n\"testdata\": ");
  mqttClient.print(millis());
  mqttClient.print("\n}");
  mqttClient.endMessage();
}

void onMessageReceived(int messageSize) {
  // we received a message, print out the topic and contents
  Serial.print("Received a message with topic '");
  Serial.print(mqttClient.messageTopic());
  Serial.print("', length ");
  Serial.print(messageSize);
  Serial.println(" bytes:");

  // use the Stream interface to print the contents
  while (mqttClient.available()) {
    Serial.print((char)mqttClient.read());
  }
  Serial.println();
  Serial.println();
}

 

 

Watch your AWS budget. The example sends a message every 5 seconds. It's advised to not leave it running for long time, or to lower the frequency of messages to AWS significantly.

 

image

 

You can use the same content for the arduino_secrets.h file as in the previous blog.

Delete the WiFi settings. They are not needed in a wired setup.

Good luck!

 

 

related blog posts
Manage Arduino MKR WIFI 1010 Battery Life in the Cloud - How Long until the Next Recharge?
Arduino MKR WIFI 1010 and Amazon Web Services: Safe MQTT with SSL and Certificate
Project14 | IoT in the Cloud: Make Use of a Wireless Technology and a Cloud Provider!
Keithley DMM6500: Measure Amp-Hours of an Arduino MKR WIFI 1010
Manage Arduino MKR WIFI 1010 Battery Life in the Cloud - AWS, Graphs and Alerts
Arduino MKR 10xx, ETH Shield and Amazon Web Services: Safe MQTT with SSL and Certificate
  • Sign in to reply
  • Jan Cumps
    Jan Cumps over 5 years ago in reply to tdp1985

    Thomas, I do not know if it's possible to use TLS without certificates. I only used it in situations with certificates.

    It may be possible to work without, but then my understanding of SSL\TLS is wrong ...

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • tdp1985
    tdp1985 over 5 years ago

    Dear Jan,

    Thank you very much for this article.

     

    I use the same hardware as you : Arduino Mkr Zero + Mkr Eth shield.

    I would like to connect to a MQTT server that support TLS or SSL, no certificate needed but just Login / Password.

     

    So I stuck on this part of your code :   sslClient.setEccSlot(0, certificate); 

     

     

    With a MQTT client on computer I use theses setting :

    Connectivity : Websockets

    Enable user authentification: User / password

    TLS/SSL Mode : Certificates and keys provided externally

    Protocol : TLSv1.2

     

    Do you know how is it possible to modify your code to connect to these kind of MQTT with TLS server ?

     

    Thank you very much.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube