WASHING MACHINE+ HA + PHOTON + MQTT = unknown sensor


#1

as been checked (in my capacity) for I don’t know how many times.
CASE: I have a particle photon with a photoresistor connected between two pins, which publishes the value of the resistance placed in front of the “end” light of a washing machine under my own WIFI. The part of Particle works, so much so that with IFTT I can start Pushbullet when the light comes on with the message “the washing machine has run out”.
I therefore created a mqtt sensor on Hassio, with also the states of unavailability (AFAIK)

[code]
 sensor:
  - platform: mqtt
    name: "Lavatrice"
    state_topic: "tele/LAVATRICE/status"
    icon: mdi:washing-machine   
    payload_available: "online"
    payload_not_available: "offline"
[/code]

and…

nothing, mosquitto refuses -o, better, truncates-the connection with

[Code]
1556805730: New client connected from 192.168.0.15 as WASHING MACHINE (c1, k15, u'MQTT ').
1556805744: Socket error on client WASHING MACHINE, disconnecting.
[/ Code]

and the sensor remains in “unknown”

This is the Photon code. I’m sure I made a trivial mistake (or maybe not, I’m not very well on MQTT) but I don’t see it.
Thank you in advance.

[code]
#include "MQTT.h"
 // Lavatrice


int photoresistor = A0; // This is where your photoresistor is plugged in. The other side goes to the "power" pin (below).

int power = A5; // This is the other end of your photoresistor. The other side is plugged into the "photoresistor" pin (above).

int analogvalue;

void callback(char* topic, byte* payload, unsigned int length);


  
   byte server[] = { 192,168,0,xx };   //IP del HA+raspi
   MQTT client(server, 1883, callback);

// receive message              UNUSED BUT I HAVE NOT REMOVED IT FOR POSSIBLE UPGRADES
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;

    if (!strcmp(p, "RED"))
        RGB.color(255, 0, 0);
    else if (!strcmp(p, "GREEN"))
        RGB.color(0, 255, 0);
    else if (!strcmp(p, "BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);
}


void setup() {
    
 
    pinMode(photoresistor,INPUT);  //  photoresistor pin  input (reading the photoresistor)
    pinMode(power,OUTPUT); //  pin powering the photoresistor is output (sending out consistent power)
    digitalWrite(power,HIGH);

 
    Spark.variable("analogvalue", &analogvalue, INT); //variable to be published on cloud particle


  
    
    
    RGB.control(true);  //led control
    // connect to the server
    client.connect("LAVATRICE", "MQTTUSER", "MQTTpwd");  //login to broker

    // publish/subscribe
    if (client.isConnected()) {
        client.publish("tele/LAVATRICE/status","CONNESSA");  //I don't already see this: it should put the sensor as CONNECTed as soon as the connection is made.
    }
}

void loop() {
    
    analogvalue = analogRead(photoresistor);  //reads the resistor
    if (client.isConnected())          //if it is still connected to the MQTT ...
  {
    delay(10000);                      //...after ten sec...
    RGB.color(0, 255, 0);          // ... the LED turns green

    if (analogvalue>3750)       //.....e if the light is on ...
    {
    Spark.publish("analogvalue");         //....publicishes the value of the resistor in the cloud ...
    client.publish("tele/LAVATRICE/status","FINITO");    // ...and"FINITO" on MQTTT...
    delay(300000);                     // ...and wait 5 minutes before the next reading
    }
    
    else 
    {
    Spark.publish("analogvalue");     //... otherwise it only publishes the value of the resistance in the cloud (AS IF!)
    delay(20000);                          // ...and wait only 20 seconds
    }



   
    client.loop();      // I found this, I suppose it's the keepalive
 }
        
    else            // Instead, if it's not connected to the broker ....
    {
        RGB.color(255, 0, 0);   //....the LED turns red ...
        client.publish("tele/LAVATRICE/status","DISCONNESSA");  //.....for security post the disconnection even if it will never arrive ...
    if (analogvalue>3750)           //...e if the LED is on ...
    {
    Spark.publish("analogvalue");   //.... posts the value on the cloud ...
    delay(300000);       // ...and waits 5 minutes before the next reading
    }
    else 
    {
    Spark.publish("analogvalue"); //... otherwise only publish the value of the resistance in the cloud
    delay(20000);             // ...and wait only 20 seconds
    }    
        
        //(sorry for the rubberducking).
    }
    
             }


[/code]

The problem is that the sensor on HASSIO does not even present the “online” and “offline” payloads.
I’m afraid I got something wrong between PHOTON and MQTT, but …
Again, thanks.


#2

Some points

  • you should avoid using delay() with multi second periods since that renders the device rather sluggish in regards to responsiveness.
  • A photoresistor should typically be part of a voltage divider and not merely a series resistor.
  • you are still using the outdate Spark.xxxx() functions - Nowadays it would be Particle.xxxx()
  • for Spark.variable() it should now be Particle.variable("analogvalue", analogvalue).
  • Particle.publish() (e.g. Particle.publish("analogvalue", NULL, PRIVATE); should provide a scope (since you don’t have one I’d deduce you are still targeting a rather old device OS version)
  • your code indentation doesn’t make reading your code easy, so there may be some logical not-yet-found issues too

#3

Thanks for the tips.
The Cloud spark-particle part is so far working, so I think the fault is in the MQTT part.
Anyway, I’ll try changing the cloud part too :slight_smile:
I have read and reread nearly everything I could find about it.
Am I losing the “socket” part? :confused:


#4

After reformattig your code (and slightly cleaning it up - but not yet removed the delay() calls) I found at least one more puzzling part

cleaned up code
#include "MQTT.h"

const char   *id        = "LAVATRICE";
const char   *user      = "MQTTUSER";
const char   *pwd       = "MQTTpwd";
const char   *topic     = "tele/LAVATRICE/status";
const uint8_t server[]  = { 192, 168,   0,   0};        // IP del HA+raspi

const int photoresistor = A0;                           // photoresistor in here plugged in ... 
const int power         = A5;                           // ... the other side goes to the "power" pin
int analogvalue;

void callback(char*, uint8_t*, unsigned int);
MQTT client((char*)server, 1883, callback);             // poor implementation requires a non-const char* as domain parameter - should be const!!!

void setup() {
  pinMode(photoresistor,INPUT);                         // photoresistor pin  input (reading the photoresistor)
  pinMode(power,OUTPUT);                                // pin powering the photoresistor is output (sending out consistent power)
  digitalWrite(power,HIGH);

  Particle.variable("analogvalue", analogvalue);        // variable to be published on cloud particle
  
  RGB.control(true);  //led control

  client.connect(id, user, pwd);                        // login to broker

  // publish/subscribe
  if (client.isConnected()) {
    client.publish(topic, "CONNESSA");                  // I don't already see this: it should put the sensor as CONNECTed as soon as the connection is made.
  }
}

void loop() {
  analogvalue = analogRead(photoresistor);              // reads the resistor
  if (client.isConnected()) {                           // if it is still connected to the MQTT ...
    delay(10000);                                       // ... after ten sec ...
    RGB.color(0, 255, 0);                               // ... the LED turns green

    if (analogvalue>3750) {                             // ... e if the light is on ...
      Particle.publish("analogvalue", NULL, PRIVATE);   // ... publicishes the value of the resistor in the cloud ...
      client.publish(topic, "FINITO");                  // ... and"FINITO" on MQTTT ...
      delay(300000);                                    // ... and wait 5 minutes before the next reading
    }
    else {
      Particle.publish("analogvalue", NULL, PRIVATE);   // ... otherwise it only publishes the value of the resistance in the cloud (AS IF!)
      delay(20000);                                     // ... and wait only 20 seconds
    }
    client.loop();                                      // I found this, I suppose it's the keepalive
  }
  else {                                                // Instead, if it's not connected to the broker ...
    RGB.color(255, 0, 0);                               // ... the LED turns red ...
    client.publish(topic, "DISCONNESSA");               // ... for security post the disconnection even if it will never arrive ...
    if (analogvalue > 3750) {                           // ... e if the LED is on ...
      Particle.publish("analogvalue", NULL, PRIVATE);   // ... posts the value on the cloud ...
      delay(300000);                                    // ... and waits 5 minutes before the next reading
    }
    else {
      Particle.publish("analogvalue", NULL, PRIVATE);   // ... otherwise only publish the value of the resistance in the cloud
      delay(20000);                                     // ... and wait only 20 seconds
    }    
    // (sorry for the rubberducking).
  }
}

// receive message              UNUSED BUT I HAVE NOT REMOVED IT FOR POSSIBLE UPGRADES
void callback(char* topic, byte* payload, unsigned int length) {
  char p[length + 1];
  memcpy(p, payload, length);
  p[length] = NULL;

  if (!strcmp(p, "RED"))
    RGB.color(255, 0, 0);
  else if (!strcmp(p, "GREEN"))
    RGB.color(0, 255, 0);
  else if (!strcmp(p, "BLUE"))
    RGB.color(0, 0, 255);
  else
    RGB.color(255, 255, 255);
}

The else block (for if (client.isConnected())) does call client.publish(topic, "DISCONNESSA"); which doesn’t make sense.
If the client is not connected, how would it then use that client to publish?
Also wouldn’t it be logical to attempt to reconnect once the lack of connectivity has become known?


#5

Yes, I know it is puzzling. The “hail mary” publish is just a “I know it won’t work, but maybe I can see if sometimes there’s a false disconnection”; really, I can’t understand why it does disconnect on MQTT.
Yes again, the attempt of reconnection has sense IN the loop. I moved the code a bit, I think (I SEE now) I put the connect in the wrong place.

I have to check if when the first disconnection is recoverable, is then more stable. As you pointed, as it is, it’s a one-shot :confused:

Again, I can’t understand why I can’t get into the MQTT. Am I losing part of the mandatory configuration?

(again, thank you for the cleaning :slight_smile: )


#6

You can try this
https://go.particle.io/shared_apps/5cd2d52d2327c10017875b60


#7

ASAP.
I’ll let you know the results
Thank you in advance.


#8

Ok, yesterday I was eventually at home, and I tried the code you kindly provided.
I changed only id, user, pwd and server IP.

Nothing.
Red Led after some blinking cyan and blue.
Checking and rechecking, Mosquitto’s log does not even show the connection attempt.
Thank you for now, I’ll try tweaking around mosquitto itself (that works with tasmotadmin, though) and maybe the router’s log.
Or maybe with another photon/core, to exclude an hardware fault.

Again, thank you for the help.


#9

I think there was just a minor bug in the typecast here

MQTT client((char*)server, 1883, callback);  

it should rather be

MQTT client((uint8_t*)server, 1883, callback);  

Have a try with this
https://go.particle.io/shared_apps/5ce2d70886cf77000a9edc8f
For testing I have reduced the 5 minute delay time to 30sec in line 11

const uint32_t wait[]     = { 20000, 30000 }; // delay for LED should be 20000, 300000