[Solved] Can connect using PubSubClient.h but fails with Losant.h

I am working with an Arduiono Board and an Ethernet Shield.

I followed the “Can’t connect to Losant” topic - using a modified version of the sketch described using PubSubClient.h I succeed in connecting to Losant:


> #include <SPI.h>
> #include <Ethernet.h>
> #include <PubSubClient.h>

> #define MQTT_MAX_TRANSFER_SIZE 80  //this was done as a result of troubleshooting

> byte mac[] = {  0x00, 0x21, 0x5C, 0xD7, 0x78, 0xEF };

> void callback(char* topic, byte* payload, unsigned int length) {
>   Serial.print("Command received.");
> }

> EthernetClient client;

> PubSubClient pclient("broker.losant.com", 1883, callback, client);


> void setup() {
>   Serial.begin(9600);

>   // disable SD SPI
>   pinMode(4,OUTPUT);
>   digitalWrite(4,HIGH);

>   Serial.print(F("Starting ethernet..."));
>   if(!Ethernet.begin(mac)) Serial.println(F("failed"));
>   else {
>       Serial.println(Ethernet.localIP());
>       Serial.println(Ethernet.gatewayIP());
>   }
>    if(pclient.connect("removed for security", "removed for security", "removed for security")) {
>     Serial.println("Connected to Losant");
>   }
>   else {
>     Serial.println("Failed to connect.");
>     Serial.println(pclient.state());
>   }
> }

> void loop() {
> }

I double check this by looking on the Serial monitor - I see “Connected to Losant” -
and on the Losant Application Communication log I see “Connection Succeeded” & “Authentication Succeeded”

I then switch to a sketch using the Losant.h library based on the arduino wifi example (again key details removed for security but exactly the same as those used successfully above


#include <SPI.h>
#include <Ethernet.h>
#include <Losant.h>

#define MQTT_MAX_TRANSFER_SIZE 80  //this was done as a result of troubleshooting

// ** Configure the Losant credentials to enable comms over mqtt **

const char* LOSANT_DEVICE_ID = "removed for security";
const char* LOSANT_ACCESS_KEY = "removed for security";
const char* LOSANT_ACCESS_SECRET = "removed for security";

byte mac[] = {  0x00, 0x21, 0x5C, 0xD7, 0x78, 0xEF };

const int BUTTON_PIN = 31;
const int LED_PIN = 12;

bool ledState = false;

EthernetClient client;

LosantDevice device(LOSANT_DEVICE_ID);

void toggle() {
  Serial.println("Toggling LED.");
  ledState = !ledState;
  digitalWrite(LED_PIN, ledState ? HIGH : LOW);
}

// Called whenever the device receives a command from the Losant platform.
void handleCommand(LosantCommand *command) {
  Serial.print("Command received: ");
  Serial.println(command->name);

  if(strcmp(command->name, "toggle") == 0) {
    toggle();
  }
}

void setup() {
  Serial.begin(9600);

  while(!Serial) { }
  pinMode(BUTTON_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  // disable SD SPI
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  Serial.print(F("Starting ethernet..."));
  if(!Ethernet.begin(mac)) Serial.println(F("failed"));
  else {
      Serial.println(Ethernet.localIP());
      Serial.println(Ethernet.gatewayIP());
  }
  // Register the command handler to be called when a command is received
  // from the Losant platform.
  device.onCommand(&handleCommand);

  connect();

}

void connect() {

  // Connect to Losant.
  Serial.println();
  Serial.print("Connecting to Losant...");

  device.connectSecure(client, LOSANT_ACCESS_KEY, LOSANT_ACCESS_SECRET);

  while(!device.connected()) {
    delay(500);
    Serial.println(device.mqttClient.state()); 
    Serial.print(".");
  }

  Serial.println("Connected!");
}



void buttonPressed() {
  Serial.println("Button Pressed!");

  // Losant uses a JSON protocol. Construct the simple state object.
  // { "button" : true }
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["button"] = true;

  // Send the state to Losant.
  device.sendState(root);
}

int buttonState = 0;

void loop() {

  bool toReconnect = false;

  if(!device.connected()) {
    Serial.println("Disconnected from Losant");
    Serial.println(device.mqttClient.state());
    toReconnect = true;
  }

  if(toReconnect) {
    connect();
  }

  device.loop();

  int currentRead = digitalRead(BUTTON_PIN);

  if(currentRead != buttonState) {
    buttonState = currentRead;
    if(buttonState) {
      buttonPressed();
    }
  }

  delay(100);
}

I get -4 returned from Serial.println(device.mqttClient.state()); and there is no activity shown in the communication log- it feels like I have done something daft - can you help?

I believe the issue is with using device.connectSecure since you’re using the standard Ethernet client. Please try changing that line to device.connect.

The pubsubclient example is using the address and port for the non-TLS MQTT endpoint, which should be the same as using device.connect.

What Arduino board are you using? We should check to see if it has a secure version of the Ethernet client.

2 Likes

Hi Brandon.

That indeed does the trick - it works now.

I am using a Genuino (European name for Arduino) Mega with a tinxi® W5100 Ethernet Shield Network Module Board for Arduino UNO R3 TF Mega 2560 TE146.

Would be good to get a secure version for sure - any advice you have much appreciated.

In the meantime thanks for your help and support.

As far as I can tell, there is not a version of the Ethernet shield that supports TLS, however the Arduino 101 WiFi shield does. TLS requires a decent amount of memory/CPU to perform, so it’s fairly common not to be supported on low-power devices. The Arduino 101 WiFi shield has a co-processor on the shield to help with the encryption.

The most common work-around in this scenario is to use a local gateway. The Arduino would connect over your private network to something like a Raspberry Pi or Intel Edison. The high-power device then has the secure connection to our platform. Typically one local gateway can easily handle 100’s of low-power devices connected to it.

Our platform has direct support for this concept through Gateways and Peripherals.

Hello Bradon, please can you and the Team help me out on this project am working on: I have this arduino relay battery monitoring sketch and i want to make it run on an arduino ethernet shield W5100 to send the battery voltages “RealB1V…ReamB4V” to my Losant page for remote moniroting. Can you or anyone in the team hep me re-write/insert the necessary losant code to achieve this please. This is the code:

/******************************************************
 * Written By: Usman Ali Butt                         *
 * Dated     : 26 june 2018                           *
 * Property off: www.microcontroller-project.com      *
 ******************************************************/

int Vdiv = A0; // Voltage divider at Analog channel A0

int B=4; //Relay control pins 
int B2=5;
int B3=6;
int B4=7;

float ratio = 3.6;  // Calculated from Vin / Vout


long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
     ADMUX = _BV(MUX5) | _BV(MUX0) ;
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  
 
  delay(2);                       // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);            // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
 
  uint8_t low  = ADCL;            // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH;            // unlocks both
 
  long result = (high<<8) | low;
 
  result = 1125300L / result;     // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result;                  // Vcc in millivolts
}


void setup() {
  Serial.begin(9600);      //Serial port initialized
  pinMode(B,OUTPUT);      //Relay controlling pins declared as output
  pinMode(B2,OUTPUT);
  pinMode(B3,OUTPUT);
  pinMode(B4,OUTPUT);
}

void loop() {

float  B1PV=0.0;
float  B2PV=0.0;
float  B3PV=0.0;
float  B4PV=0.0;

float RealB1V=0;
float RealB2V=0;
float RealB3V=0;
float RealB4V=0;

float vccValue=readVcc()/1000.0;        //Arduino operating voltage
                                            

                digitalWrite(B,HIGH);              //Open battery-1 relay
                delay(400);                         //Time for relay to make contact
                B1PV = analogRead(Vdiv);         // read the voltage on the divider 
                RealB1V= (B1PV * vccValue/1024) * ratio;
                digitalWrite(B,LOW);               
                delay(400);

                digitalWrite(B2,HIGH);              
                delay(400); 
                B2PV = analogRead(Vdiv);         // read the voltage on the divider                           
                RealB2V = (B2PV * vccValue/1024) * ratio;
                digitalWrite(B2,LOW);               
                delay(400);

                digitalWrite(B3,HIGH);              
                delay(400);     
                B3PV = analogRead(Vdiv);         // read the voltage on the divider                    
                RealB3V = (B3PV * vccValue/1024) * ratio;
                digitalWrite(B3,LOW);               
                delay(400);

                digitalWrite(B4,HIGH);              
                delay(400);  
                B4PV = analogRead(Vdiv);         // read the voltage on the divider                          
                RealB4V = (B4PV * vccValue/1024) * ratio;
                digitalWrite(B4,LOW);               
                delay(400);
              

Serial.println();
Serial.println(RealB1V); //Print battery voltage on arduino serial monitor
Serial.println(RealB2V);
Serial.println(RealB3V);
Serial.println(RealB4V);
  
}// end of loop