Nicla Vision to HiveMQ

Hello,

I am trying to publish messages to my Hive MQ Cloud from a Nicla Vision Board. As I am new to Arduino, this may be the reason I cannot seem to get this. I am having issues incorporating the root certificate into my sketch. Does anyone know how to do this? I am trying to use ChatGPT to assist me and it is telling me to do wifiClient.setCACert(root_ca); however, ‘class WiFiSSLClient’ has no member named ‘setCACert’

#include <WiFiNINA.h>
#include <WiFiSSLClient.h>
#include <PubSubClient.h>
#include "arduino_secrets.h"


///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;    // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

const char* mqtt_Server = "#";
const char* mqtt_User = "#";
const char* mqtt_Password = "#";
int mqtt_Port = 8883;
const char* mqtt_topic = "testTopic";
int status = WL_IDLE_STATUS;
char server[] = "example.com"; 
static const char *root_ca PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
")EOF";


WiFiSSLClient wifiClient;
PubSubClient mqttClient(wifiClient);

void connectToWiFi(){
// check for the WiFi module:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }
  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // wait 3 seconds for connection:
    delay(3000);
  }
  Serial.println("Connected to wifi");
  
}

void connectToMQTT(){
    //connect to MQTT broker

  mqttClient.setServer(mqtt_Server, mqtt_Port);
  while (!mqttClient.connected()) {
    Serial.print("Connecting to MQTT broker...");
    String clientId = "001";
    if (mqttClient.connect(clientId.c_str(), mqtt_User, mqtt_Password)) {
      Serial.println("connected");
      
      //mqttClient.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      //Serial.println(mqttClient.connectErrorString(mqttClient.state()));
      Serial.println(" try again in 5 seconds");
      delay(5000);
    } 
  }
}

void makeHTTPRequest() {
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (wifiClient.connect(server, 80)) {
    Serial.println("Connected to server");
    delay(3000);
    // Make a HTTP request
    wifiClient.println("GET /index.html HTTP/1.1");
    wifiClient.print("Host: ");
    wifiClient.println(server);
    wifiClient.println("Connection: close");
    wifiClient.println();
  }
}

void reconnect() {
  //mqttClient.setBufferSize(255);
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    String clientId = "001";
    if (mqttClient.connect(clientId.c_str(), mqtt_User, mqtt_Password)) {
      Serial.println("\nConnected to MQTT broker!");
      //client.subscribe(mqttTopic);
    } else {
      Serial.print(".");
      delay(1000);
    }
  }
}


void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  connectToWiFi();
  makeHTTPRequest();
  wifiClient.setCACert(root_ca);
  mqttClient.setServer(mqtt_Server, mqtt_Port);
  connectToMQTT();  
  
}

void loop() {
  if(!mqttClient.connected()) {
    reconnect();
  }
  mqttClient.loop();
  if(mqttClient.connected()){
    mqttClient.publish(mqtt_topic, "hello world");
  }
  delay(1000);
}

Hello @LaurenMcGarry ,

Thank you for the interest in MQTT and HiveMQ, and welcome to the community!

When accessing your HiveMQ Cloud instance and managing a cluster, there is a ‘Getting Started’ option at the upper right of the Cluster Details page.

When selecting this option, various installation and connection guidelines for devices are available, including Arduino/ESP8266, which may be helpful here.

If possible, please provide a link to the documentation or MQTT details for the Nicla Vision Board device, as well - this will allow us to review connection requirements in comparison with HiveMQ Cloud.

Best,
Aaron from the HiveMQ Team

Hello @AaronTLFranz,

Thanks for the reply. I had come across this, but at the time was not sure if it could be used with the Nicla Sense as the wifi library used was for ESP8266. I am unsure on how to get any MQTT details for this board, sorry, but here is data sheet for the board: https://docs.arduino.cc/static/0b75723ee8acb19cabf18a2af4de2889/ABX00051-datasheet.pdf

I will have another go with the arduino getting started and see if i can use some of that sketch, however, I am a bit confused over TLS/ ra cert. To confirm, using the free hive mq cloud pathway, I think I saw that I needed to include the RA cert, is that right?

Thanks,
Lauren

Hello @LaurenMcGarry

In addition to what my colleague Aaron has already provided and based on the documentation that you have shared, I believe will be better if you start your project by using OpenMV instead of Arduino. They have a lot of scripts examples (Board Control, Sensors, Audio, WiFi, Bluetooth, Low-Power) for Nicla Vision Board. An MQTT publish sample is also available, I could not find any sample using MQTT TLS (which is required to connect to the HiveMQ Cloud) but you can use it to connect to our public broker (The Free Public MQTT Broker by HiveMQ - Check out our MQTT Demo), it is a good way to start your project.

Kind regards,
Diego from HiveMQ Team

Hi @Diego,

Thanks, however in regards to your suggestion to using OpenMV, I have successfully used wifi and MQTT (over 1883 to another platform) using examples provided by Arduino on the Nicla vision. The issue lies with TLS, and if there is no examples using TLS in OpenMV, I do not know why I would try to use this.

I have tried the public broker (changed the server and port, and removed username and password references) and it looks like my script is publishing to it no problem.

Lauren

Hello @LaurenMcGarry ,

In reply to your previous inquiry about the server certificate, we do offer a server CA available here. This .pem file can be utilized in TLS connection to your HiveMQ Cloud instance.

Best,
Aaron from HiveMQ Team

Hi @AaronTLFranz,

Thanks, but as you can see I already have the certificate in the sketch.

Lauren

Hello @LaurenMcGarry ,

Understood - in that case, could I have you clarify the current questions that you have? It looks like we were asking previously if, using the free HiveMQ Cloud instance via TLS, the RA cert is required. The CA cert provided above has historically been the only requirement for Arduino devices to connect via TLS, using the server CA for authentication.

If the question is regarding TLS configuration within the code utilized, please include the error message provided when attempting to connect, as well.

Best,
Aaron from HiveMQ Team

Hi @AaronTLFranz ,

Yes it is regarding how I declare the certificate in the WIFI instance. After some WiFi library confusion, I am using the Wifi library that comes with the Nicla Sense board. Within this library there is ‘WiFiSSLClient’, which seems to be the only header available that would work with this certificate. The code for this script is as follows:

#ifndef WIFISSLCLIENT_H
#define WIFISSLCLIENT_H

#include "WiFi.h"
#include "MbedSSLClient.h"

extern const char CA_CERTIFICATES[];

namespace arduino {

class WiFiSSLClient : public arduino::MbedSSLClient {
  NetworkInterface *getNetwork() {
    return WiFi.getNetwork();
  }
};

My updated sketch is:

#include <WiFi.h>
#include <WiFiSSLClient.h>
#include <PubSubClient.h>
#include "arduino_secrets.h"


///////sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;    // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)

const char* mqtt_Server = "#";
const char* mqtt_User = "#";
const char* mqtt_Password = "#";
int mqtt_Port = 8883;
const char* mqtt_topic = "testTopic";
int status = WL_IDLE_STATUS;
char server[] = "example.com"; 
const char *root_ca = R"EOF(v 
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
")EOF";

//WiFiClient wifiClient;
WiFiSSLClient wifiClient(root_ca);
PubSubClient mqttClient(wifiClient);

void connectToWiFi(){
// check for the WiFi module:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }
  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // wait 3 seconds for connection:
    delay(3000);
  }
  Serial.println("Connected to wifi");
  
}

void connectToMQTT(){
    //connect to MQTT broker

  mqttClient.setServer(mqtt_Server, mqtt_Port);
  while (!mqttClient.connected()) {
    Serial.print("Connecting to MQTT broker...");
    String clientId = "001";
    if (mqttClient.connect(clientId.c_str(), mqtt_User, mqtt_Password)) {
      Serial.println("connected");
      
      //mqttClient.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    } 
  }
}

void makeHTTPRequest() {
  Serial.println("\nStarting connection to server...");
  // if you get a connection, report back via serial:
  if (wifiClient.connect(server, 80)) {
    Serial.println("Connected to server");
    delay(3000);
    // Make a HTTP request
    wifiClient.println("GET /index.html HTTP/1.1");
    wifiClient.print("Host: ");
    wifiClient.println(server);
    wifiClient.println("Connection: close");
    wifiClient.println();
  }
}

void reconnect() {
  //mqttClient.setBufferSize(255);
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    String clientId = "001";
    if (mqttClient.connect(clientId.c_str(), mqtt_User, mqtt_Password)) {
      Serial.println("\nConnected to MQTT broker!");
      //client.subscribe(mqttTopic);
    } else {
      Serial.print(".");
      delay(1000);
    }
  }
}


void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  connectToWiFi();
  makeHTTPRequest();
  mqttClient.setServer(mqtt_Server, mqtt_Port);
  connectToMQTT();  
  
}

void loop() {
  if(!mqttClient.connected()) {
    reconnect();
  }
  mqttClient.loop();
  if(mqttClient.connected()){
    mqttClient.publish(mqtt_topic, "hello world");
  }
  delay(1000);
}

My error message is:

C:\Users\3057166\OneDrive - Queen's University Belfast\Documents\Arduino\MQTT\15\MQTTwifiTest15\MQTTwifiTest15.ino:59:33: error: no matching function for call to 'arduino::WiFiSSLClient::WiFiSSLClient(const char*&)'
 WiFiSSLClient wifiClient(root_ca);
                                 ^
In file included from C:\Users\3057166\OneDrive - Queen's University Belfast\Documents\Arduino\MQTT\15\MQTTwifiTest15\MQTTwifiTest15.ino:5:0:
C:\Users\3057166\AppData\Local\Arduino15\packages\arduino\hardware\mbed_nicla\4.0.2\libraries\WiFi\src/WiFiSSLClient.h:30:7: note: candidate: arduino::WiFiSSLClient::WiFiSSLClient()
 class WiFiSSLClient : public arduino::MbedSSLClient {
       ^~~~~~~~~~~~~
C:\Users\3057166\AppData\Local\Arduino15\packages\arduino\hardware\mbed_nicla\4.0.2\libraries\WiFi\src/WiFiSSLClient.h:30:7: note:   candidate expects 0 arguments, 1 provided
C:\Users\3057166\AppData\Local\Arduino15\packages\arduino\hardware\mbed_nicla\4.0.2\libraries\WiFi\src/WiFiSSLClient.h:30:7: note: candidate: arduino::WiFiSSLClient::WiFiSSLClient(const arduino::WiFiSSLClient&)
C:\Users\3057166\AppData\Local\Arduino15\packages\arduino\hardware\mbed_nicla\4.0.2\libraries\WiFi\src/WiFiSSLClient.h:30:7: note:   no known conversion for argument 1 from 'const char*' to 'const arduino::WiFiSSLClient&'
C:\Users\3057166\AppData\Local\Arduino15\packages\arduino\hardware\mbed_nicla\4.0.2\libraries\WiFi\src/WiFiSSLClient.h:30:7: note: candidate: arduino::WiFiSSLClient::WiFiSSLClient(arduino::WiFiSSLClient&&)
C:\Users\3057166\AppData\Local\Arduino15\packages\arduino\hardware\mbed_nicla\4.0.2\libraries\WiFi\src/WiFiSSLClient.h:30:7: note:   no known conversion for argument 1 from 'const char*' to 'arduino::WiFiSSLClient&&'

exit status 1

Compilation error: no matching function for call to 'arduino::WiFiSSLClient::WiFiSSLClient(const char*&)'

Hello @LaurenMcGarry ,

Understood - thank you for the clarification!

Based on the details provided here, it looks like property being declared, the root_ca of wificlient, does not exist within the utilized library. Historically, users attempting to connect via SSL to their cloud instance have had the most success with the libraries

#include <WiFi.h>
#include <WiFiClientSecure.h>

These allow configuration of the root CA as expected above.

With the current configuration, it looks like the wifiClient(root_ca) does not exist within the library, or cannot be called as configured. Reviewing what I believe to be the correct library referenced above, it looks like this can only be called to connect, rather than pass and authenticate CA certs.

Best,
Aaron from the HiveMQ Team