USB gateway Arduino Mega: HA doesn't see switches and relays



  • Hi, I'm struigling with connecting MySensors to my Home Assistant (server on unRaid - docker).

    here is my sketch (4 relays but I've another sketch for 24 which will be used when everything will be working):

    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    // Set LOW transmit power level as default, if you have an amplified NRF-module and
    // power your radio separately with a good regulator you can turn up PA level. 
    //#define MY_RF24_PA_LEVEL RF24_PA_LOW
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    #define MY_BAUD_RATE 38400
    
    // Flash leds on rx/tx/err
    // #define MY_LEDS_BLINKING_FEATURE
    // Set blinking period
    // #define MY_DEFAULT_LED_BLINK_PERIOD 300
    
    // Inverses the behavior of leds
    // #define MY_WITH_LEDS_BLINKING_INVERSE
    
    // Enable inclusion mode
    #define MY_INCLUSION_MODE_FEATURE
    // Enable Inclusion mode button on gateway
    #define MY_INCLUSION_BUTTON_FEATURE
    
    // Inverses behavior of inclusion button (if using external pullup)
    //#define MY_INCLUSION_BUTTON_EXTERNAL_PULLUP
    
    // Set inclusion mode duration (in seconds)
    #define MY_INCLUSION_MODE_DURATION 60 
    // Digital pin used for inclusion mode button
    #define MY_INCLUSION_MODE_BUTTON_PIN  3 
    
    // Uncomment to override default HW configurations
    //#define MY_DEFAULT_ERR_LED_PIN 4  // Error led pin
    //#define MY_DEFAULT_RX_LED_PIN  6  // Receive led pin
    //#define MY_DEFAULT_TX_LED_PIN  5  // the PCB, on board LED
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <Bounce2.h>
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #define RELAY_1  14  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define RELAY_2  15
    #define RELAY_3  16
    #define RELAY_4  17
    
    #define NUMBER_OF_RELAYS 4 // Total number of attached relays
    
    #define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    
    #define BUTTON_PIN 5
    #define BUTTON2_PIN 6
    #define BUTTON3_PIN 7
    #define BUTTON4_PIN 8
    
    void before() { 
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);   
        // Set relay to last known state (using eeprom storage) 
        digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
      }
    }
    Bounce debouncer = Bounce();
    Bounce debouncer2 = Bounce();
    Bounce debouncer3 = Bounce();
    Bounce debouncer4 = Bounce();
    
    void setup() { 
      // Setup locally attached sensors
      delay(10000);
       // Setup the button.
      pinMode(BUTTON_PIN, INPUT_PULLUP);
      pinMode(BUTTON2_PIN, INPUT_PULLUP);
      pinMode(BUTTON3_PIN, INPUT_PULLUP);
      pinMode(BUTTON4_PIN, INPUT_PULLUP);
      // After setting up the button, setup debouncer.
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
      debouncer2.attach(BUTTON2_PIN);
      debouncer2.interval(5);
      debouncer3.attach(BUTTON3_PIN);
      debouncer3.interval(5);
      debouncer4.attach(BUTTON4_PIN);
      debouncer4.interval(5);
    
      //presentation();
    }
    void presentation()  
    {   
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Relay", "1.0");
    
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_LIGHT);
      }
    }
    MyMessage msg(1, V_LIGHT);
    MyMessage msg2(2, V_LIGHT);
    MyMessage msg3(3, V_LIGHT);
    MyMessage msg4(4, V_LIGHT);
    
    void loop() { 
      // Send locally attached sensor data here 
      if (debouncer.update()) {
        // Get the update value.
        int value = debouncer.read();
        // Send in the new value.
        if(value == LOW){
             saveState(1, !loadState(1));
             digitalWrite(RELAY_1, loadState(1)?RELAY_ON:RELAY_OFF);
             send(msg.set(loadState(1)));
             }
      }
      if (debouncer2.update()) {
          int value2 = debouncer2.read();
        if(value2 == LOW){
             saveState(2, !loadState(2));
             digitalWrite(RELAY_2, loadState(2)?RELAY_ON:RELAY_OFF);
             send(msg2.set(loadState(2)));
             }
      }
      if (debouncer3.update()) {
          int value3 = debouncer3.read();
        if(value3 == LOW){
             saveState(3, !loadState(3));
             digitalWrite(RELAY_3, loadState(3)?RELAY_ON:RELAY_OFF);
             send(msg3.set(loadState(3)));
             }
      }
      if (debouncer4.update()) {
          int value4 = debouncer4.read();
        if(value4 == LOW){
             saveState(4, !loadState(4));
             digitalWrite(RELAY_4, loadState(4)?RELAY_ON:RELAY_OFF);
             send(msg4.set(loadState(4)));
             }
      }
    }
    
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
         // Change relay state
         digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
         // Store state in eeprom
         saveState(message.sensor, message.getBool());
         // Write some debug info
         Serial.print("Incoming change for sensor:");
         Serial.print(message.sensor);
         Serial.print(", New status: ");
         Serial.println(message.getBool());
       } 
    }
    

    Home Assistant config:

    mysensors:
      gateways:
        - device: '/dev/ttyACM0'
          persistence_file: 'mysensors.json'
          baud_rate: 38400
          topic_in_prefix: 'mygateway1-out'
          topic_out_prefix: 'mygateway1-in' 
      optimistic: false
      persistence: true
      retain: true
      version: '2.0'
    

    mysensors.json generated by Home Assistant:

    {}
    

    when I'm connecting arduino to HA I'm getting this:

    2019-08-26 18:33:09 INFO (MainThread) [mysensors] Connected to Serial<id=0x14800ea0cf90, open=True>(port='/dev/ttyACM0', baudrate=38400, bytesize=8, parity='N', stopbits=1, timeout=0, xonxoff=False, rtscts=False, dsrdtr=False)
    2019-08-26 18:33:10 DEBUG (MainThread) [mysensors.handler] n:0 c:255 t:3 s:9 p:Starting gateway (R-NGA-, 2.0.0)
    2019-08-26 18:33:10 INFO (MainThread) [mysensors.handler] n:0 c:255 t:3 s:14 p:Gateway startup complete.
    2019-08-26 18:33:10 DEBUG (MainThread) [homeassistant.components.mysensors.gateway] Node update: node 0 child 255
    2019-08-26 18:33:15 DEBUG (SyncWorker_12) [mysensors.persistence] Saving sensors to persistence file /config/mysensors.json
    2019-08-26 18:33:20 DEBUG (MainThread) [mysensors.handler] n:0 c:255 t:3 s:9 p:No registration required
    2019-08-26 18:33:20 DEBUG (MainThread) [mysensors.handler] n:0 c:255 t:3 s:9 p:Init complete, id=0, parent=0, distance=0, registration=1
    

    any idea to make it work?


  • Admin

    @jan-kocon I am just learning Home Assistant myself so I'm no expert. One thing it looks like your relay code is missing is to send an initial relay value in the loop function of your code when the node first starts (which is required by Home Assistant). Here is the link for more info: https://www.home-assistant.io/components/mysensors/#presentation



  • @petewill I've uncommented "//presentation" part in the code

    ...
      debouncer4.attach(BUTTON4_PIN);
      debouncer4.interval(5);
    
      //presentation();
    }
    void presentation()  
    ...
    

    and I've got this in the log:

    2019-08-28 17:40:25 ERROR (MainThread) [mysensors.handler] Node 0 is unknown, will not add child 1
    2019-08-28 17:40:25 ERROR (MainThread) [mysensors.handler] Node 0 is unknown, will not add child 2
    2019-08-28 17:40:25 ERROR (MainThread) [mysensors.handler] Node 0 is unknown, will not add child 3
    2019-08-28 17:40:25 ERROR (MainThread) [mysensors.handler] Node 0 is unknown, will not add child 4
    

    Plus I've added those lines in void setup:

    // Make sure relays are off when starting up
      digitalWrite(RELAY_1, RELAY_OFF);
      digitalWrite(RELAY_2, RELAY_OFF);
      digitalWrite(RELAY_3, RELAY_OFF);
      digitalWrite(RELAY_4, RELAY_OFF);
      pinMode(RELAY_1, OUTPUT);
      pinMode(RELAY_2, OUTPUT);
      pinMode(RELAY_3, OUTPUT);
      pinMode(RELAY_4, OUTPUT);
    

    I've defined node in the code

    #define MY_NODE_ID 1
    

    and updated HA config

    mysensors:
      gateways:
        - device: '/dev/ttyACM0'
          persistence_file: 'mysensors.json'
          baud_rate: 115200
          topic_in_prefix: 'mygateway1-out'
          topic_out_prefix: 'mygateway1-in'
          nodes: 
            1:
              name: 'test'
      optimistic: true
      persistence: true
      retain: true
      version: '2.0'
    

    but unfortunatelly when I'm pressing any button on Arduino I'm getting this in log:

    2019-08-28 17:50:50 WARNING (MainThread) [mysensors] Node 0 is unknown
    2019-08-28 17:50:50 INFO (MainThread) [mysensors] Requesting new presentation for node 0
    

    And i have no idea what esle to do 😞


  • Admin

    @Jan-Kocon I would recommend starting with the relay example sketch that is in the presentation section of this site: https://www.home-assistant.io/components/mysensors/#presentation

    Once you have that working you can start integrating your existing sketch in to that one.

    One thing I notice with your existing sketch is you have a sensor type of "S_LIGHT" which doesn't exist. You need S_BINARY (https://www.mysensors.org/download/serial_api_20).
    You also need to send the initial value in the loop function like this:

      if (!initialValueSent) {
        Serial.println("Sending initial value");
        send(msg.set(state?RELAY_ON:RELAY_OFF));
        Serial.println("Requesting initial value from controller");
        request(CHILD_ID, V_STATUS);
        wait(2000, C_SET, V_STATUS);
      }```


  • @petewill I've tried that config earlier but no luck.

    I've added some changes in my Arduino code, here is actual code:

    // Override Setting for Manual Node ID to 2
    #define MY_NODE_ID 2
    
    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    
    // Enable and select radio type attached
    //#define MY_RADIO_NRF24
    
    // Enable serial gateway
    #define MY_GATEWAY_SERIAL
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    #include <SPI.h>
    #include <MySensors.h>  
    #include <Bounce2.h>
    
    // Enable repeater functionality for this node
    #define MY_REPEATER_FEATURE
    
    
    #define RELAY_1  14  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
    #define RELAY_2  15
    #define RELAY_3  16
    #define RELAY_4  17
    #define NUMBER_OF_RELAYS 4 // Total number of attached relays
    #define RELAY_ON 1  // GPIO value to write to turn on attached relay
    #define RELAY_OFF 0 // GPIO value to write to turn off attached relay
    
    #define BUTTON1_PIN 5
    #define BUTTON2_PIN 6
    #define BUTTON3_PIN 7
    #define BUTTON4_PIN 8
    
    bool initialValueSent = false;
    
    MyMessage msg1(1, V_LIGHT);
    MyMessage msg2(2, V_LIGHT);
    MyMessage msg3(3, V_LIGHT);
    MyMessage msg4(4, V_LIGHT);
    
    void before() { 
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
        // Then set relay pins in output mode
        pinMode(pin, OUTPUT);   
        // Set relay to last known state (using eeprom storage) 
        digitalWrite(pin, loadState(sensor)?RELAY_ON:RELAY_OFF);
      }
    }
    Bounce debouncer1 = Bounce();
    Bounce debouncer2 = Bounce();
    Bounce debouncer3 = Bounce();
    Bounce debouncer4 = Bounce();
    
    void setup() { 
      // Setup locally attached sensors
      delay(10000);
      
       // Setup the button.
      pinMode(BUTTON1_PIN, INPUT_PULLUP);
      pinMode(BUTTON2_PIN, INPUT_PULLUP);
      pinMode(BUTTON3_PIN, INPUT_PULLUP);
      pinMode(BUTTON4_PIN, INPUT_PULLUP);
      
      // After setting up the button, setup debouncer.
      debouncer1.attach(BUTTON1_PIN);
      debouncer1.interval(5);
      debouncer2.attach(BUTTON2_PIN);
      debouncer2.interval(5);
      debouncer3.attach(BUTTON3_PIN);
      debouncer3.interval(5);
      debouncer4.attach(BUTTON4_PIN);
      debouncer4.interval(5);
    
    }
    void presentation()  
    {   
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Relay", "1.0");
    
      for (int sensor=1, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_LIGHT);
      }
    }
    
    void loop() { 
      if (!initialValueSent) {
        Serial.println("Sending initial value");
        send(msg1.set(loadState(1)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg2.set(loadState(2)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg3.set(loadState(3)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg4.set(loadState(4)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        Serial.println("Sending initial value: Completed");
        wait(5000);
      }
      
      // Send locally attached sensor data here 
      if (debouncer1.update()) {
        // Get the update value.
        int value = debouncer1.read();
        // Send in the new value.
        if(value == LOW){
             saveState(1, !loadState(1));
             digitalWrite(RELAY_1, loadState(1)?RELAY_ON:RELAY_OFF);
             send(msg1.set(loadState(1)));
             }
      }
      if (debouncer2.update()) {
          int value2 = debouncer2.read();
        if(value2 == LOW){
             saveState(2, !loadState(2));
             digitalWrite(RELAY_2, loadState(2)?RELAY_ON:RELAY_OFF);
             send(msg2.set(loadState(2)));
             }
      }
      if (debouncer3.update()) {
          int value3 = debouncer3.read();
        if(value3 == LOW){
             saveState(3, !loadState(3));
             digitalWrite(RELAY_3, loadState(3)?RELAY_ON:RELAY_OFF);
             send(msg3.set(loadState(3)));
             }
      }
      if (debouncer4.update()) {
          int value4 = debouncer4.read();
        if(value4 == LOW){
             saveState(4, !loadState(4));
             digitalWrite(RELAY_4, loadState(4)?RELAY_ON:RELAY_OFF);
             send(msg4.set(loadState(4)));
             }
      }
    }
    
    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller. But we better check anyway.
      if (message.type==V_LIGHT) {
         // Change relay state
         digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
         // Store state in eeprom
         saveState(message.sensor, message.getBool());
         // Write some debug info
         Serial.print("Incoming change for sensor:");
         Serial.print(message.sensor);
         Serial.print(", New status: ");
         Serial.println(message.getBool());
       } 
    }
    

    and finally I can see my relays in GUI:
    alt text

    mysensor file:

    {
        "0": {
            "sensor_id": 0,
            "children": {
                "1": {
                    "id": 1,
                    "type": 3,
                    "description": "",
                    "values": {
                        "2": "1"
                    }
                },
                "2": {
                    "id": 2,
                    "type": 3,
                    "description": "",
                    "values": {
                        "2": "1"
                    }
                },
                "3": {
                    "id": 3,
                    "type": 3,
                    "description": "",
                    "values": {
                        "2": "1"
                    }
                },
                "4": {
                    "id": 4,
                    "type": 3,
                    "description": "",
                    "values": {
                        "2": "1"
                    }
                }
            },
            "type": 17,
            "sketch_name": "Relay",
            "sketch_version": "1.0",
            "battery_level": 0,
            "protocol_version": "2.3.1",
            "heartbeat": 0
        }
    }
    

    But it couldn't be to good...
    Home Assistant doesn't save changes in GUI so when I'm switch relay to off it will turn off the relay and it will stay off on device but after 2-3 seconds it's coming back on in GUI (on arduino it's still off). To trun it back on I have to turn on and turn off relay in GUI pretty fast before it will 'switch' back again.

    when I'm switching relay in GUI I'm getting this:

    2019-08-29 13:14:07 WARNING (MainThread) [mysensors.message] Error decoding message from gateway, bad data received: Incoming change for sensor:1, New status: 0
    2019-08-29 13:14:07 WARNING (MainThread) [mysensors] Not a valid message: not enough values to unpack (expected 5, got 0)
    

    and additionaly every few seconds I'm getting those lines in logs (even when it's iddle):

    2019-08-29 13:16:34 WARNING (MainThread) [mysensors.message] Error decoding message from gateway, bad data received: Sending initial value
    2019-08-29 13:16:34 WARNING (MainThread) [mysensors] Not a valid message: not enough values to unpack (expected 5, got 0)
    2019-08-29 13:16:34 DEBUG (MainThread) [homeassistant.components.mysensors.gateway] Node update: node 0 child 1
    2019-08-29 13:16:34 DEBUG (MainThread) [homeassistant.components.mysensors.device] Entity update: Relay 0 1: value_type 2, value = 1
    2019-08-29 13:16:35 DEBUG (MainThread) [homeassistant.components.mysensors.gateway] Node update: node 0 child 2
    2019-08-29 13:16:35 DEBUG (MainThread) [homeassistant.components.mysensors.device] Entity update: Relay 0 2: value_type 2, value = 1
    2019-08-29 13:16:36 DEBUG (MainThread) [homeassistant.components.mysensors.gateway] Node update: node 0 child 3
    2019-08-29 13:16:36 DEBUG (MainThread) [homeassistant.components.mysensors.device] Entity update: Relay 0 3: value_type 2, value = 1
    2019-08-29 13:16:37 DEBUG (MainThread) [homeassistant.components.mysensors.gateway] Node update: node 0 child 4
    2019-08-29 13:16:37 DEBUG (MainThread) [homeassistant.components.mysensors.device] Entity update: Relay 0 4: value_type 2, value = 1
    2019-08-29 13:16:37 DEBUG (SyncWorker_32) [mysensors.persistence] Saving sensors to persistence file /config/mysensors2.json
    2019-08-29 13:16:38 WARNING (MainThread) [mysensors.message] Error decoding message from gateway, bad data received: Sending initial value: Completed
    2019-08-29 13:16:38 WARNING (MainThread) [mysensors] Not a valid message: not enough values to unpack (expected 5, got 0)
    


  • Well... another update:

    I've deleted this part from code:

      if (!initialValueSent) {
        Serial.println("Sending initial value");
        send(msg1.set(loadState(1)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg2.set(loadState(2)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg3.set(loadState(3)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        send(msg4.set(loadState(4)?RELAY_OFF:RELAY_ON),true);
        wait(1000);
        Serial.println("Sending initial value: Completed");
        wait(5000);
      }
    

    and its working fine, I'm not getting update for intitial value and degub lines apears when I'm pressing buttons and they are working fine and I can see changes in HA.

    Still when I'm changing state on GUI it's coming back to previous state in GUI but it's holding new state on Arduino.
    Last problem with debug log:

    2019-08-29 15:43:56 WARNING (MainThread) [mysensors.message] Error decoding message from gateway, bad data received: Incoming change for sensor:3, New status: 1
    2019-08-29 15:43:56 WARNING (MainThread) [mysensors] Not a valid message: not enough values to unpack (expected 5, got 0)
    

    Any idea what to change in code?


  • Admin

    @Jan-Kocon I am experiencing the same thing with my devices (where the status doesn't stick but the relay stays on). I haven't had time to dig into it yet but I suspect this ultimately needs to be fixed in the Home Assistant integration. The example code on the Home Assistant site sends back the status after the relay has been updated. The MySensors RelayActuator sketch does not send back the status this way.

    It seems to me there are two workarounds for this.

    1. Set the "optimistic" setting in the home assistant configuration.yaml file to True
    2. Send the state back to Home Assistant after the relay has been changed. See these lines of code for in the example:
        // Change relay state
        state = (bool)message.getInt();
        digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
        send(msg.set(state?RELAY_ON:RELAY_OFF));```

  • Admin

    @Jan-Kocon I found the issue. Home Assistant doesn't request an Ack response for some reason. Here is a comparison of my current home automation controller (Vera) and Home Assistant. The top line is Vera (requesting an Ack response) and the bottom line is Home Assistant.
    https://www.mysensors.org/build/parser?log=19%3B0%3B1%3B1%3B2%3B1 19%3B0%3B1%3B0%3B2%3B0


 

276
Online

8.7k
Users

9.5k
Topics

99.9k
Posts