First time sending message from HA to MySensors



  • Hi,

    I have been using MySensors with Home Assistant successfully for a few months now. I feel like I have a pretty good grasp on how to get the sensor (Arduino) to report a value to Home Assistant (RPi) over MQTT.

    The next step I'm trying to do is getting the sensor to do something based on a switch in Home Assistant.

    Basically what I want to do is use the Arduino to transmit a code via RF to control a Watts Clever RF power relay. I've already got the Arduino doing this based on a motion sensor but the only MySensor integration is reporting to HA what the status of the relay is.

    I've tried re purposing the relay actuator code for my use but the code is a bit beyond my Arduino coding knowledge. I just want to send a message from Home Assistant which is read by the Arduino and code is then run based on what that message says (eg on, off).

    Is there a tutorial or similar that anyone can link me to? My googling only results in complicated examples for particular things. I just need the bare bones so I can add what I want.

    I know this would not work because I made most of it up, but this is the type of thing I think I'm looking for:

    void receive(const MyMessage &message) {
        if (message.type == V_STATUS) {   // check for switch status
    status=message;    // This is where I start making up stuff to convey my intent
    if status == 'on'
    {
     mySwitch.send("110011110011000101010101");    \\Send RF code
     digitalWrite(13,HIGH);
     delay(500);
     digitalWrite(13,LOW);
     delay(1000);
      Serial.println("on");
      }
    else {
    mySwitch.send("110011110011000101011101");   \\Send RF code
     digitalWrite(13,HIGH);
     delay(500);
     digitalWrite(13,LOW);
     delay(1000);
      Serial.println("off");
    }
    }
    

    Also, what would I actually add to Home Assistant to make a switch (or button) send a line of MQTT to the sensor, and what would that line be?

    Sorry if this is a difficult and vague question to answer. I'm not expecting someone to explain how the whole thing works or write my code for me but any similar examples or links to tutorials would be very helpful.

    Thanks.

    Ps, just for reference here is my working code as it currently stands:

    
    // Enable debug prints
    //#define MY_DEBUG
    #define MY_CONTROLLER_IP_ADDRESS 192, 168, 1, 141
    #define MY_PORT 1883
    #define MY_MQTT_CLIENT_ID "mysensors-1"
    #define MY_MQTT_PUBLISH_TOPIC_PREFIX "mygateway1-out"
    #define MY_MQTT_SUBSCRIBE_TOPIC_PREFIX "mygateway1-in"
    // Enable and select radio type attached
    #define MY_RADIO_NRF24
    //#define MY_RADIO_RFM69
    
    
    //RF Codes here
    //Shed Lights attached to WATTS CLEVER 13578589
    #define shedlighton "110011110011000101011101"
    #define shedlightoff "110011110011000101010101"
    
    #include <MySensors.h>
    #include <RCSwitch.h>
    #include <SPI.h>
    unsigned long SLEEP_TIME = 12000; // Sleep time between reports (in milliseconds)
    #define DIGITAL_INPUT_SENSOR 3   // The digital input you attached your motion sensor.  (Only 2 and 3 generates interrupt!)
    
    #define CHILD_ID 1
    
    // Initialize motion message
    MyMessage msgtrip(CHILD_ID, V_TRIPPED);
    MyMessage msglight(CHILD_ID, V_LIGHT);
    MyMessage msgrain(CHILD_ID, V_TEXT);
    
    RCSwitch mySwitch = RCSwitch();
    
    long previousTime = 0;        
    long interval = 5000;   
    int recentmotion = 0;
    unsigned long currentTime = 0;
    unsigned long differentTime = 0;
    
    const int sensorMin = 0;     // sensor minimum
    const int sensorMax = 1024;  // sensor maximum
    
    void setup()
    {
    	pinMode(DIGITAL_INPUT_SENSOR, INPUT);      // sets the motion sensor digital pin as input
    	// Transmitter is connected to Arduino Pin #10 
    	mySwitch.enableTransmit(4);
    
     // Optional set pulse length.
     mySwitch.setPulseLength(321);
    }
    
    void presentation()
    {
    	// Send the sketch version information to the gateway and Controller
    	sendSketchInfo("Motion Sensor Plus", "1.0");
    
    	// Register all sensors to gw (they will be created as child devices)
    	present(1, S_MOTION);
    }
    
    void loop()
    {
              Serial.println(millis());
    if(millis() > 20000 && digitalRead(DIGITAL_INPUT_SENSOR) == LOW){
      if(millis() > differentTime){
        recentmotion = 0;
               send(msglight.set("Off"));
            previousTime = currentTime; 
              Serial.print("recentmotion=");
              Serial.println(recentmotion);
      }
    }
      if(recentmotion == 0) {
       
     mySwitch.send(shedlightoff);
     digitalWrite(13,HIGH);
     delay(500);
     digitalWrite(13,LOW);
     delay(1000);
      Serial.println("off");
      }
    	// Read digital motion value
    	bool tripped = digitalRead(DIGITAL_INPUT_SENSOR) == HIGH;
    
    	Serial.println(tripped);
    	send(msgtrip.set(tripped?"1":"0"));  // Send tripped value to gw
      if(digitalRead(DIGITAL_INPUT_SENSOR) == HIGH){
          Serial.println("on");
       mySwitch.send(shedlighton);
     digitalWrite(13,HIGH);
     delay(500);
     digitalWrite(13,LOW);
     delay(2000); 
           recentmotion = 1;
           send(msglight.set("On"));
            differentTime = millis() + 20;
            Serial.print("differentTime=");
                    Serial.println(differentTime);
          Serial.print("recentmotion=");
                    Serial.println(recentmotion);
      }
    // rain sensor
    
    
    // read the sensor on analog A0:
      int sensorReading = analogRead(A0);
      // map the sensor range (four options):
      // ex: 'long int map(long int, long int, long int, long int, long int)'
      int range = map(sensorReading, sensorMin, sensorMax, 0, 3);
      
      // range value:
      switch (range) {
     case 0:    // Sensor getting wet
        Serial.println("Flood");
        send(msgrain.set("Yes, heavy rain"));
        break;
     case 1:    // Sensor getting wet
        Serial.println("Rain Warning");
        send(msgrain.set("Light rain detected"));
        break;
     case 2:    // Sensor dry - To shut this up delete the " Serial.println("Not Raining"); " below.
        Serial.println("Not Raining");
        send(msgrain.set("No, it's not raining"));
        break;
      }
    
    
    	// Sleep until interrupt comes in on motion sensor. Send update every two minute.
    	sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), CHANGE, SLEEP_TIME);
    }
    

  • Plugin Developer

    @adamp237

    It sounds as you currently only have one arduino that acts both as a gateway and motion sensor and you don't have any other devices talking to the gateway via nrf radio. If so it's OK to have the gateway sleeping as long as you don't plan to send messages to it. But if you plan to send messages to the arduino via mqtt from home assistant and/or connect other arduino via radio to the gateway, the gateway is not allowed to sleep. You can use wait instead to suspend execution.

    This is the most basic switch example controlling a relay:

    #include <MySensor.h>
    #include <SPI.h>
    
    #define SN "Relay"
    #define SV "1.0"
    #define CHILD_ID 1
    #define RELAY_PIN 3
    
    bool initialValueSent = false;
    MyMessage msgRelay(CHILD_ID, V_STATUS);
    
    void setup()
    {
      digitalWrite(RELAY_PIN, 0);
      // Initialize the digital pin as an output.
      pinMode(RELAY_PIN, OUTPUT);
    }
    
    void presentation() {
      sendSketchInfo(SN, SV);
      present(CHILD_ID, S_BINARY);
    }
    
    void loop()
    {
      if (!initialValueSent) {
        Serial.println("Sending initial value");
        send(msgRelay.set(0));
        Serial.println("Requesting initial value from controller");
        request(CHILD_ID, V_STATUS);
        wait(2000, C_SET, V_STATUS);
      }
    }
    
    void receive(const MyMessage &message)
    {
      if (message.type == V_STATUS) {
        if (!initialValueSent) {
          Serial.println("Receiving initial value from controller");
          initialValueSent = true;
        }
         // Change relay state.
         digitalWrite(RELAY_PIN, message.getInt() ? 1 : 0);
         send(msgRelay.set(message.getInt() ? 1 : 0));
      }
    }
    

    Are you using the mysensors component in home assistant or are you defining your sensor yourself directly using the mqtt component and mqtt sensor platform? If you're using the mysensors component you don't need to change anything in the home assistant configuration, you just need to present the mysensors switch properly to home assistant and home assistant will add it as a switch entity automatically.


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.