Implementing custom Nexa 433mhz component with Homeeasy library

I am having lots of trouble with getting remote transmitter and reciever (rc_switch) to work with my Nexa wireless relays (EYCR-2300), using those RF Transmitter Reciever cheap modules. The readings from the remote (NEYCT-705) is unreliable and I just haven´t got any of the codes to work. When reading other issues it looks like others too are having trouble getting Nexa/Proove/Anslut 433mhz to work.

However, on my Arduino I have had great success with sending codes with the Homeeasyhacking library that I found here, using the AM-HRR3 reciever test sketch.

The reciever picks up everything correctly and I can use the information from that with homeeasy lib to send on/off commands flawlessly.

The information from the reciever to use with homeeasy library comes as:
sender: 30144518 (my remote ID)
recipient: 0 (0 to 15 depending on which unit to turn on/off. My remote can handle 16 units)
command: true/false depending if I press on or off button on the remote.

So I just have to pass the ID of my remote control, the number of the wall socket (0-15) and a true or false command to turn on or off. A click with my other, Anslut remote control and the reciever instantly picks up that ID as well. Just change the ID in the Arduino sketch and I control the Anslut sockets just as easy.

So my question is; how big of a task would it be to try and learn to make a custom component out of this for a newcomer? It would be so beautiful to set up a switch in esphome with the ID of the remote control, the number of the socket to control, and an on/off command and let the already working homeeasy library take care of the rest regarding pulses, protocols and what not. If it is possible at all, what tips can you give?

You can see how it looks like in my basic Arduino project here:

Hello @Ubiquitous-X

Have you done any progress on this issue?

I have Chacon DIO plugs which are also using the Nexa 433.92MHz protocol and I can see the data using a rtl-sdr dongle and rtl_433:

time      : 2022-11-01 15:47:41
model     : Nexa-Security House Code: XXXXXXX
Channel   : 3            State     : OFF           Unit      : 3             Group     : 0

Where XXXXXXX is the the remote ID

I wanted to use ESPHome to send the signals but I am not sure what to send, which rc_remote command to use and what to send. When I try my sniffer does see some signals but does not recognize as Nexa signals.

If you have any idea or pointers that would be welcomed.

I got a good starting point for receiving/sending nexa signals here: https://community.home-assistant.io/t/nexa-433mhz-using-sonoff-rf-bridge-modified-with-the-direct-hack-and-esphome/323261

I have made a few changes to make it behave on never esphome versions
without "default_transition_length: 0ms " it will flood the transmitter until crash, and I added in a switch and the right wait time (10ms) , below is a version with those changes made that should work for you to send and receive nexa signals

or if you dont get along with the esphome 433mhz implementation you can try this one I made a while back, not much interest in it but give it a try if you like: https://community.home-assistant.io/t/alternative-433-control-rc-sw-new-remote-switch-dimmer-support-optional-rfm69/330794

good luck!

1 more thing please tell me you are not using the green xy-mk-5v receiver if so GET A BETTER ONE!!

esphome:
  name: nexa_bridge
  platform: ESP8266
  board: esp01_1m
  platformio_options:
   board_build.f_cpu: 160000000L

wifi:
  output_power: 8.5 #8.5-20 will run 10-15c cooler with these settings, remove is you have disconnects.
  power_save_mode: NONE #HIGH NONE LIGHT
  fast_connect: true 
  ssid: "xxx"
  password: "xxxxx"


captive_portal:

# Enable logging
logger:
  baud_rate: 0 

# Enable Home Assistant API
api:

ota:
    safe_mode: True




remote_receiver:
   pin:
     number: 3
   dump:
   - nexa
   filter: 50us
   tolerance: 50%
   idle: 7ms


# Example configuration entry
remote_transmitter:
  pin: 1
  carrier_duty_percent: 100%
  
  
  

switch:

- platform: template
  name: "tx_test"
  optimistic: true 
  turn_on_action:
    - remote_transmitter.transmit_nexa:
        device: 0x38DDB4A
        state: 0
        group: 0
        channel: 15
        level: 0
        repeat:
          times: 10
          wait_time: 10ms 
  turn_off_action:
    - remote_transmitter.transmit_nexa:
        device: 0x38DDB4A
        state: 1
        group: 0
        channel: 15
        level: 0
        repeat:
          times: 10
          wait_time: 10ms 


output:
  - platform: template
    id: tilda_slinga_output
    type: binary
    write_action:
      - if:
          condition:
            light.is_on: tilda_slinga_light
          then:
            - remote_transmitter.transmit_nexa:
                device: 0x38DDB4A
                state: 1
                group: 0
                channel: 15
                level: 0
                repeat:
                  times: 10
                  wait_time: 10ms              
          else:
            - remote_transmitter.transmit_nexa:
                device: 0x38DDB4A
                state: 0
                group: 0
                channel: 15
                level: 0
                repeat:
                  times: 10
                  wait_time: 10ms 


  - platform: template
    id: vardagsrum_dimable_slinga_output
    type: float

    write_action:
      - if:
          condition:
            lambda: return (state > 0);
          then:       
            - remote_transmitter.transmit_nexa:
                device: 0x19A5470
                state: 2
                group: 0
                channel: 0
                level: !lambda return state*15;
                repeat:
                  times: 10
                  wait_time: 10ms 
          else:             
            - remote_transmitter.transmit_nexa:
                device: 0x19A5470
                state: 0
                group: 0
                channel: 0
                level: 0
                repeat:
                  times: 10
                  wait_time: 10ms 






 
light:
  - platform: binary
    name: "Tilda Slinga"
    id: tilda_slinga_light
    output: tilda_slinga_output

  - platform: monochromatic
    name: "Vardagsrum Slinga"
    default_transition_length: 0ms 
    id: vardagsrum_dimable_slinga_light
    output: vardagsrum_dimable_slinga_output
 

Ahah I missed the remote_transmitter.transmit_nexa :smiley:

But no luck… I do not get rtl_433 recognizing the signal as Nexa-Security like it does with my remote.

What I detect:

time      : 2022-11-01 17:27:12
model     : Nexa-Security House Code: 9821046
Channel   : 3            State     : ON            Unit      : 1             Group     : 0

I am using:

remote_transmitter:
  pin: GPIO32
  carrier_duty_percent: 100%

# Individual switches
switch:
  - platform: template
    name: "Chacon 1 on"
    optimistic: true 
    turn_on_action:
      - remote_transmitter.transmit_nexa:
          device: 0x9821046
          state: 1
          group: 0
          channel: 3
          level: 1
          repeat:
            times: 10
            wait_time: 10ms 
    turn_off_action:
      - remote_transmitter.transmit_nexa:
          device: 0x9821046
          state: 0
          group: 0
          channel: 3
          level: 1
          repeat:
            times: 10
            wait_time: 10ms 
            

I tried with level: 0 I am not sure how to tell which unit to use

I will post here if I ever make any progress :slight_smile:

level are for dimmer, leave at 0 for switches.
rtl_433 might have a really narrow tolerance for reception try " wait_time: 10400us "
260*40=10400 us

or look again above again I added in a link to something I made a while back

I had a few minutes to spare so here are a minimal nexa send code for esphome that rlt can pick up

433_switch_control.yaml

esphome:
  name: 433_switch_control_test
  platform: ESP8266
  board: esp01_1m
  includes:
    - 433_switch_main.h



wifi:
  fast_connect: true 
  ssid: "xxxxxx"
  password: "xxxx"


captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
    safe_mode: True

      
switch:

- platform: custom
  lambda: |-
    auto test0 = new New_remote_switch(9821046,0);
    auto test1 = new New_remote_switch(9821046,1);
    auto test2 = new New_remote_switch(9821046,2);
    App.register_component(test0);
    App.register_component(test1);
    App.register_component(test2);   
    return {test0,test1,test2};   
  switches:
    - name: "test0_"
    - name: "test1_"
    - name: "test2_"

text_sensor:
- platform: custom
  lambda: |-
    auto last_sent_received = new Last_sent_received();
    App.register_component(last_sent_received);
    return {last_sent_received};

  text_sensors:
    name: "last sent"    

433_switch_main.h
just change the _tx_pin below to whatever you need


#include "esphome.h"
#define _tx_pin 1		//set tx pin here 




unsigned long send_NRS_adress[4] = {0};
char send_NRS_unit[4] = {0};
char send_NRS_state[4] = {0};
int send_NRS_dimmer[4] = {0};



//-------------------------------------------------------------------------------------------------------------
class New_remote_switch : public Component, public Switch {
  public:
    int counter = 0;
    uint32_t  adress;
    uint8_t  unit;

    New_remote_switch(uint32_t  adress_, uint8_t unit_) {
      adress = adress_;
      unit = unit_;
    }


    void write_state(bool state) override {
								
      extern unsigned long send_NRS_adress[4];
      extern char send_NRS_unit[4];
      extern char send_NRS_state[4];
	  for (int i = 0; i <= 3; i++)
	  {
	if(send_NRS_adress[i]==0)
	{
      send_NRS_adress[i] = adress;
      send_NRS_unit[i] = unit;
      send_NRS_state[i] = state;
break;	  
	}		

	  }
	  
	  
	  
      publish_state(state);
	  
    }
};



//-----------------------NewRemoteSwitch---------------https://github.com/1technophile/NewRemoteSwitch


unsigned int pulselength;
bool invertedSignal;
uint8_t _repeats=4;
unsigned int _periodusec=260;
unsigned long _address;

void _sendBit(boolean isBitOne) {
  if (isBitOne) {
    // Send '1'
    digitalWrite(_tx_pin, HIGH);
    delayMicroseconds(_periodusec);
    digitalWrite(_tx_pin, LOW);
    delayMicroseconds(_periodusec * 5);
    digitalWrite(_tx_pin, HIGH);
    delayMicroseconds(_periodusec);
    digitalWrite(_tx_pin, LOW);
    delayMicroseconds(_periodusec);
  } else {
    // Send '0'
    digitalWrite(_tx_pin, HIGH);
    delayMicroseconds(_periodusec);
    digitalWrite(_tx_pin, LOW);
    delayMicroseconds(_periodusec);
    digitalWrite(_tx_pin, HIGH);
    delayMicroseconds(_periodusec);
    digitalWrite(_tx_pin, LOW);
    delayMicroseconds(_periodusec * 5);
  }
}

void _sendAddress() {
  for (int8_t i=25; i>=0; i--) {
     _sendBit((_address >> i) & 1);
  }
}

void _sendUnit(uint8_t unit) {
  for (int8_t i = 3; i >= 0; i--) {
    _sendBit(unit & 1 << i);
  }
}

void _sendStopPulse() {
  digitalWrite(_tx_pin, HIGH);
  delayMicroseconds(_periodusec);
  digitalWrite(_tx_pin, LOW);
  delayMicroseconds(_periodusec * 40);
}

  void _sendStartPulse(){
  digitalWrite(_tx_pin, HIGH);
  delayMicroseconds(_periodusec);
  digitalWrite(_tx_pin, LOW);
  delayMicroseconds(_periodusec * 10 + (_periodusec >> 1)); // Actually 10.5T insteat of 10.44T. Close enough.
}
void sendUnit(uint8_t unit, boolean switchOn,unsigned long adress) {
  for (int8_t i = _repeats; i >= 0; i--) {
    _address=adress;
    _sendStartPulse();
    _sendAddress();
    // No group bit
    _sendBit(false);
    // Switch on | off
    _sendBit(switchOn);
    _sendUnit(unit);
    _sendStopPulse();
  }}
 
  void sendDim(uint8_t unit, uint8_t dimLevel,unsigned long adress) {
	for (int8_t i = _repeats; i >= 0; i--) {
		_address=adress;
		
		_sendStartPulse();

		_sendAddress();

		// No group bit
		_sendBit(false);
//if we have dimmlevel send state 2 =dimmer..		
if(dimLevel)
{
		// Switch type 'dim'
		digitalWrite(_tx_pin, HIGH);
		delayMicroseconds(_periodusec);
		digitalWrite(_tx_pin, LOW);
		delayMicroseconds(_periodusec);
		digitalWrite(_tx_pin, HIGH);
		delayMicroseconds(_periodusec);
		digitalWrite(_tx_pin, LOW);
		delayMicroseconds(_periodusec);
}
else// if no dimmlevel send state 0 = off, sending dimmer 0 and state 2 leaves my dimmer turned on, on the lowest level
{
_sendBit(0);	
	
}
		_sendUnit(unit);
//0-15 dimm
		for (int8_t j=3; j>=0; j--) {
		   _sendBit(dimLevel & 1<<j);
		}

		_sendStopPulse();
	}
}






class Last_sent_received : public PollingComponent, public TextSensor {
  public:



     Last_sent_received() : PollingComponent(50) {}

    void setup() override {


#if defined(ESP8266) // kill serial if rx/tx pins are used, like on esp01
if(_tx_pin==1||_tx_pin==3)
{
Serial.end();		
}
#endif
pinMode(_tx_pin,OUTPUT);

   	  
    }
    void update() override {

     


     

for (int i = 0; i <= 3; i++)
{
      if (send_NRS_adress[i])//we have data from NRS
      {
        if (send_NRS_state[i] == 2 ) {
          sendDim(send_NRS_unit[i], send_NRS_dimmer[i], send_NRS_adress[i]);
        }
        else {
			
			 sendUnit(send_NRS_unit[i], send_NRS_state[i], send_NRS_adress[i]);							

        }
        std::string my_data;
        my_data = "send address ";
        my_data += to_string(send_NRS_adress[i]);

        my_data += "unit ";
        my_data += to_string(send_NRS_unit[i]);

        my_data += "switchType ";
        my_data += to_string(send_NRS_state[i]);
        if (send_NRS_state[i] == 2)
        {
          my_data += " dimmer ";
          my_data += to_string(send_NRS_dimmer[i]);
        }
        publish_state(my_data);
        send_NRS_adress[i] = 0;
		break; // only send 1 signal per loop
      }
	  
}
 
	  
    }
};