General Mysensors 433 mhz switch

I am trying to create a general mysensors switchtype to switch my 433 mhz switches.
right now i have to program every switch i use directly on the arduino and then mysensors sees it as a switch and then i can use it in HA.

the GPIO_rf switch is the way I want to use the mysensors switch.

so i tried to make something which functions that way.

in the config i have put:

switch:
  platform: mysensor_rf
  rfswitches:
    livingroom:
      nodeid: 2 # nodeid from mysensors
      type: kaku  # switchtyp could be kaku, elro, action, blokker and more in the future
      code: P01 # switchcode
    diningroom:
      nodeid: 2
      type: elro
      code: A31
    bedroom:
      nodeid: 3
      type: action
      code: B03

and then i created a new componend based on the GPIO-rf switch.

"""
Allows to configure a switch using a 433MHz module via Mysensors.

"""

import logging

from homeassistant.components.switch import SwitchDevice
#from homeassistant.components import mysensors

_LOGGER = logging.getLogger(__name__)


def setup_platform(hass, config, add_devices_callback, discovery_info=None):
    """Find and return switches controlled by a RF device via Mysensors."""
    
    rfswitches = config.get('rfswitches', {})
    rfdevices = []
    for dev_name, properties in rfswitches.items():
        if not properties.get('nodeid'):
            _LOGGER.error("%s: node id not specified", dev_name)
            continue
        if not properties.get('type'):
            _LOGGER.error("%s: switch type not specified", dev_name)
            continue
        if not properties.get('code'):
            _LOGGER.error("%s: code not specified", dev_name)
            continue
        if properties.get('type')=="elro":
            rfchildid=203
        if properties.get('type')=="action":
            rfchildid=204
        if properties.get('type')=="blokker":
            rfchildid=205
        if properties.get('type')=="kaku":
            rfchildid=206
       
        rfdevices.append(
            MysensorRFSwitch(
                hass,
                properties.get('name', dev_name),
                properties.get('nodeid'),
                rfchildid,
                properties.get('code')))

    add_devices_callback(rfdevices)


class MysensorRFSwitch(SwitchDevice):
    """Representation of a Mysensor RF switch."""

    def __init__(self, hass, name, nodeid, childid, code):
        """Initialize the switch."""
        self._hass = hass
        self._name = name
        self._state = False
        self._nodeid = nodeid
        self._childid = childid
        self._code_on = code + "t"
        self._code_off = code + "f"

    @property
    def name(self):
        """Return the name of the switch."""
        return self._name

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state

    def _send_code(self, code):
        """Send the code with a specified pulselength."""
        code=str(self._nodeid)+";"+str(self._childid)+";1;0;23;"+code
        _LOGGER.info('Sending code: %s', code)
        #res = self._rfdevice.tx_code(code, protocol, pulselength)
        res=False #sending isnt implemented yet so Always false
        #if not res:
            #_LOGGER.error('Sending code %s failed', code)
        return True #res (to avoid errors set to yes)

    def turn_on(self):
        """Turn the switch on."""
        if self._send_code(self._code_on):
            self._state = True
            self.update_ha_state()

    def turn_off(self):
        """Turn the switch off."""
        if self._send_code(self._code_off):
            self._state = False
            self.update_ha_state()

so far, so good.
i get switches in the frontend and the code i like to send to the arduino’s nicely shows up in the log.

and now i am stuck.
I am not expirienced enough to go on and implement this part in the mysensorspart, which is needed to send the code to the gateway.

so i need someone to help me now (i hope there is someone)

As there already is a service for setting and sending an IR code for a mysensors switch, I suggest using that service in your custom platform. Configuration would take the entity_id of the mysensors IR switch to know which node and child to send the code to. You basically make a shadow switch for the mysensors IR switch but have regular on/off behavior and customizable code via configuration.

Look at how the template switch is written. Your platform will be somewhat similar but simpler as it will be more specific.

Actually, I think we should change the template switch and remove the requirement for a state feedback, and let it switch optimistically. Then you could use the template switch for your use case, and wouldn’t need a custom platform.

1 Like

there are several options to chose from to get to a result.

  • change the mysensors switch
  • change the template switch
  • change the input_boolean

I am just trying around, because i see there is the possibility. and there must be others who are interested to (there is the same option with PI but that isnt as flexibel and more expensive)

but i am only capable till a certain level.

thats why i didnt start changing the mysensor switch, because thats to complex for me right now.

Finally, I made it!!
I made a copy from the templateswitch and then i edited the parts which were annoying me.
i named it Template2.

"""
Support for switches which integrates with other components.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.template/
"""
import logging

from homeassistant.components.switch import ENTITY_ID_FORMAT, SwitchDevice
from homeassistant.const import (
    ATTR_FRIENDLY_NAME, STATE_OFF, STATE_ON,
    ATTR_ENTITY_ID, MATCH_ALL)
from homeassistant.exceptions import TemplateError
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.script import Script
from homeassistant.helpers import template
from homeassistant.helpers.event import track_state_change
from homeassistant.util import slugify

CONF_SWITCHES = 'switches'

ON_ACTION = 'turn_on'
OFF_ACTION = 'turn_off'

_LOGGER = logging.getLogger(__name__)
_VALID_STATES = [STATE_ON, STATE_OFF, 'true', 'false']


# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the Template switch."""
    switches = []
    if config.get(CONF_SWITCHES) is None:
        _LOGGER.error("Missing configuration data for switch platform")
        return False

    for device, device_config in config[CONF_SWITCHES].items():

        if device != slugify(device):
            _LOGGER.error("Found invalid key for switch.template: %s. "
                          "Use %s instead", device, slugify(device))
            continue

        if not isinstance(device_config, dict):
            _LOGGER.error("Missing configuration data for switch %s", device)
            continue

        friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device)
        on_action = device_config.get(ON_ACTION)
        off_action = device_config.get(OFF_ACTION)

        if on_action is None or off_action is None:
            _LOGGER.error(
                "Missing action for switch %s", device)
            continue

        entity_ids = device_config.get(ATTR_ENTITY_ID, MATCH_ALL)

        switches.append(
            SwitchTemplate(
                hass,
                device,
                friendly_name,
                on_action,
                off_action,
                entity_ids)
            )
    if not switches:
        _LOGGER.error("No switches added")
        return False
    add_devices(switches)
    return True


class SwitchTemplate(SwitchDevice):
    """Representation of a Template switch."""

    # pylint: disable=too-many-arguments
    def __init__(self, hass, device_id, friendly_name,
                 on_action, off_action, entity_ids):
        """Initialize the Template switch."""
        self.hass = hass
        self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id,
                                            hass=hass)
        self._name = friendly_name
        #self._template = state_template
        self._on_script = Script(hass, on_action)
        self._off_script = Script(hass, off_action)
        self._state = False

    @property
    def name(self):
        """Return the name of the switch."""
        return self._name

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state

    @property
    def should_poll(self):
        """No polling needed."""
        return False

    def turn_on(self, **kwargs):
        """Fire the on action."""
        self._on_script.run()
        self._state = True
        self.update_ha_state()

    def turn_off(self, **kwargs):
        """Fire the off action."""
        self._off_script.run()
        self._state = False
        self.update_ha_state()

i made a sketch for the arduino which is actually a combination from some sketches which i found on several places.

#include <MySensor.h>  
#include <SPI.h>
#include <RemoteTransmitter.h>
 
#define TRANSMITTERPIN 6 
#define CHILD_ID_ELRO_SWITCH 4 
#define CHILD_ID_KAKU_SWITCH 5 
#define CHILD_ID_BLOKKER_SWITCH 6 
#define CHILD_ID_ACTION_SWITCH 7 
char Code1 = 'A';
int Code2 = 0;
boolean Code3;
char code[5]="A01t";
char oldCode[5]="A01t";

ElroTransmitter switchelroTransmitter = ElroTransmitter( TRANSMITTERPIN ); 
KaKuTransmitter switchkakuTransmitter = KaKuTransmitter( TRANSMITTERPIN ); 
BlokkerTransmitter switchblokkerTransmitter = BlokkerTransmitter( TRANSMITTERPIN ); 
ActionTransmitter switchactionTransmitter = ActionTransmitter( TRANSMITTERPIN ); 
MySensor gw;
 
MyMessage msg(0, V_LIGHT );
MyMessage msgCode(0, V_IR_SEND );
MyMessage msgCodeRec(0, V_IR_RECEIVE);

void setup() {
  gw.begin(incomingMessage); 
  gw.sendSketchInfo("Afstandbediening", "1.0");  
  gw.present( CHILD_ID_ELRO_SWITCH, S_IR ); 
  gw.present( CHILD_ID_KAKU_SWITCH, S_IR ); 
  gw.present( CHILD_ID_BLOKKER_SWITCH, S_IR ); 
  gw.present( CHILD_ID_ACTION_SWITCH, S_IR ); 
  gw.send(msg.setSensor(CHILD_ID_ELRO_SWITCH).set(false));
  gw.send(msg.setSensor(CHILD_ID_KAKU_SWITCH).set(false));
  gw.send(msg.setSensor(CHILD_ID_BLOKKER_SWITCH).set(false));
  gw.send(msg.setSensor(CHILD_ID_ACTION_SWITCH).set(false));
  gw.send(msgCode.setSensor(CHILD_ID_ELRO_SWITCH).set(code));
  gw.send(msgCode.setSensor(CHILD_ID_KAKU_SWITCH).set(code));
  gw.send(msgCode.setSensor(CHILD_ID_BLOKKER_SWITCH).set(code));
  gw.send(msgCode.setSensor(CHILD_ID_ACTION_SWITCH).set(code));
  gw.send(msgCodeRec.setSensor(CHILD_ID_ELRO_SWITCH).set(code));
  gw.send(msgCodeRec.setSensor(CHILD_ID_KAKU_SWITCH).set(code));
  gw.send(msgCodeRec.setSensor(CHILD_ID_BLOKKER_SWITCH).set(code));
  gw.send(msgCodeRec.setSensor(CHILD_ID_ACTION_SWITCH).set(code));
}

void loop() {
  gw.process();
}

void incomingMessage(const MyMessage &message) {
  Serial.println(message.sensor);
  if (message.type == V_IR_SEND) {
    String codestring = message.getString();
    codestring.toCharArray(code, sizeof(code));
    Code2=((code[1]-48)*10)+(code[2]-48);
    if(code[3]==char('t')){
      //Serial.println("switch on");
      Code3=true;
    } else {
      //Serial.println("switch off");
      Code3=false;
    }
    if (message.sensor==CHILD_ID_KAKU_SWITCH){
      switchkakuTransmitter.sendSignal(code[0] , Code2 ,Code3 ); 
    }
    if (message.sensor==CHILD_ID_ELRO_SWITCH){
      switchelroTransmitter.sendSignal(Code2 , code[0] ,Code3 ); 
    }
    if (message.sensor==CHILD_ID_BLOKKER_SWITCH){
      switchblokkerTransmitter.sendSignal(Code2 ,Code3 ); 
    }
    if (message.sensor==CHILD_ID_ACTION_SWITCH){
      switchactionTransmitter.sendSignal(Code2 , code[0] ,Code3 ); 
    }
  }
}

and then in de configuration.yaml

# switch 4 => ELRO, switch 5 => KAKU, switch 6 => Blokker, switch 7 Action
# ELROcode => (A/E) buttoncode, (01/31) dipswitchcode, (t or f) ON or OFF example: A15t 
# KAKUcode => (A/P) groupcode(dipswitch), (01/16) buttoncode, (t or f) ON or OFF example: M03f 
# Blokkercode => (A) to keep the code unified, (01/16) buttoncode, (t or f) ON or OFF example: A07t
# Actioncode =>  (A/D) buttoncode, (01/?) dipswitchcode, (t or f) ON or OFF example: A04f 
switch:
  platform: template2
  switches:
    diningroom:
      friendly_name: diningroom
      turn_on:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_5  # switch 5 for KAKUswitches
        data:
          V_IR_SEND: 'A01t' 
      turn_off:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_5  # switch 5 for KAKUswitches
        data:
          V_IR_SEND: 'A01f'
    livingroom:
      friendly_name: livingroom
      turn_on:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_4 # switch 4 for ELROswitches
        data:
          V_IR_SEND: 'A02t'
      turn_off:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_4 # switch 4 for ELROswitches
        data:
          V_IR_SEND: 'A02f' 
    bedroom:
      friendly_name: bedroom
      turn_on:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_6 # switch 6 for BLOKKERswitches
        data:
          V_IR_SEND: 'A07t'
      turn_off:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_6 # switch 6 for BLOKKERswitches
        data:
          V_IR_SEND: 'A07f'
    outside:
      friendly_name: outside
      turn_on:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_7 # switch 7 for ACTIONswitches
        data:
          V_IR_SEND: 'A04t'
      turn_off:
        service: switch.mysensors_send_ir_code
        entity_id: switch.remote_2_7 # switch 7 for ACTIONswitches
        data:
          V_IR_SEND: 'A04f'

in the part customize:

    switch.remote_2_4:
      hidden: true
    switch.remote_2_5:
      hidden: true
    switch.remote_2_6:
      hidden: true
    switch.remote_2_7:
      hidden: true
    sensor.remote_2_4:
      hidden: true
    sensor.remote_2_5:
      hidden: true
    sensor.remote_2_6:
      hidden: true
    sensor.remote_2_7:
      hidden: true

probably it can be made more perfect,
and it it al lot of code for the configuration, which would be easier to read if it was simplefied, but it works.
now i can go on implementing mor switches around the house (a have around 50 old ones lying around)
I can put an arduino in every room where it is needed and change all the hardware i want without reprogramming all the time.

1 Like

What do you mean by “in the part customize:”

is that a custom file or something else?

Would also like to add this feature to HA.

what i mean with the part customize is the customize section in the configuration.yaml

dont forget that this is created with the Mysensors 1.5
if you have 2.0 running the sketch must be rewritten.

How do you rewrite the script for 2.0? (sorry im really noob at this) :sweat:

i would advice you to read up at mysensors.

in this part it says that it is backwards compatible, so it should work like it is.

but if you want to rewrite (which i will do in the future) here is info over that:

you might also be interested in parts from this:

1 Like