Home Assistant/MySensors quirks



  • I just deployed my Remote Solar (with battery) Moisture Sensor. Once I got all of the subtilties nailed down, two lines of code, read and send, bloomed into over 300 lines!

    There were three Home Assistant (HA) related gotchas.

    Gotcha 1. getting data from HA.

    If you have everything coded right, HA will know about your Arduino, but you have to send a datum for each sensor (child_ids) to get HA to know about the sensors. I do this in setup

    But for reasons beyond my understanding, HA won't send anything other than binary. To get around this I send text. That is, the MyMessage is of type V_TEXT and the presentation() is S_INFO

    #define CHILD_ID_SAMPLE_INTERVAL 0
    MyMessage msgSampleInterval(CHILD_ID_SAMPLE_INTERVAL, V_TEXT);
    volatile unsigned long SamplePeriod = 20000; // ms to sleep between sensor reads
    volatile bool SamplePeriodReceived = false;
    
    void presentation(){
      present(CHILD_ID_SAMPLE_INTERVAL,S_INFO,varName); // sensor 0
      wait(REGISTERING_VARIABLES_WAIT);
    }  
    
    void setup(){
      send(msgSampleInterval.set(SamplePeriod));
        wait(MESSAGE_WAIT);
    }
    void loop(){
    
      // read data
      // send data
    
      if (SamplePeriodReceived) {
        SamplePeriodReceived = false;
        // do something with datum that came from HA
      }
      smartSleep(SamplePeriod);
    }
    void receive(const MyMessage &message){
        switch( message.getSensor() ) {
          case CHILD_ID_SAMPLE_INTERVAL:
            // MQTT topic: mysensors-in/177/0/0/0/47
            SamplePeriod = message.getLong();
            SamplePeriodReceived = true;
            break;
    }
    
    

    What's going on?

    • Basic MyMessage, but of type V_TEXT
    • The two variables need to volatile because they can be changed at any time by the background process receive(). This variable must be kept up-to-date.
    • present() is of type S_INFO (see below for varname)
    • Send an initial value in setup() so that HA knows about the variable
    • In loop(), check periodically to see if a datum came in. This is done because you want to keep the receive() routine as short as possible. Also, no sends and no print statements, no long loops, etc. in receive(). Anything you can do in loop(), do it in loop().

    The data is sent from HA as text. Doesn't matter, the message.getTYPE(); will convert it for you.

    Gotcha 2. I use an MQTT gateway. I have a wait() after every send(). I'm not sure why; my guess is that if you send to fast, the data gets overrun. For sending messages, I use 300mSec. For presentation is use 4000 mSec!!!!

    Gotch 3. Beauteous! I got it all working. Time to turn MY_DEBUG off. To ensure it is off:

      #ifdef MY_DEBUG
        #undef MY_DEBUG
      #endif
    

    It stopped working and, because MY_DEBUG was off, I couldn't figure out why. I put it back in, worked fine. It dawned on me that those debug statements took time. I added 200mSec, yes, a full half second! (Lieutenant Commander Data: 0.68 seconds sir. For an android, that is nearly an eternity.)

    Do not use delay(), that stops all processing. wait() will allow the background process to function, such as receiving data. The syntax for wait() is bool wait(unsigned long ms, uint8_t cmd, uint8_t msgtype); which will wait for the first condition to be true, but I am unable to find the cmd or msgtype. To wait for those would be much more elegant.

    • below varname

    varname This is the name that HA uses in automations, scripts, etc. The problem comes when you have two Arduinos that run the same code. HA appends an arbitrary number to the end of the variable name. This leaves you to root around HA to find out what that was. I programatically append the node number to my varname. varname must be of type string (an array of characters the byte after the last character set to 0) as opposed to type String. Using type String is not advised as it is very easy to add to the String so much that it wipes out memory beyond its bounds. A real bugger to debug, especially if it occurs in receive().

    • HA script to change interval period to 4001 mSec (assumes varname is "int177"
    sequence:
      - target:
          entity_id: text.int177
        data:
          value: "4001"
        action: text.set_value
    alias: moisture sensor 177 Sample Period 4001 HA
    mode: single
    description: Send text to change sample period to 4001
    

Log in to reply
 

Suggested Topics

  • 1
  • 3
  • 5
  • 3
  • 11
  • 3

22
Online

11.5k
Users

11.1k
Topics

112.8k
Posts