RF Converter V3.0 custom integration

Recently, I’ve created custom integration for RF Converter V3.0 WiFi to Remote.

Click here to download

Feel free to give me any feedback.
Thank you.

2 Likes

Thanks! Great job!..

The RF Converter module does not respond to sending a packet from Home Assistant.

reload_remote - retrieves the data correctly:

{"ecostar": {"ip": "192.168.2.28", "mac": "08:3a:8d:ee:2a:4f", "type": "1", "project": "13", "frequency": "43392", "id": "1726589522", "key": {"garaz": "32", "wjazdowa": "64"}}}

send_command - it’s visible that the packet was sent to the RF module, but the LED on the RF, which signals task execution, does not react (192.168.1.101 is my Home Assistant).

root@router:/tmp/home/root# cat /proc/net/nf_conntrack | grep 192.168.2.28
ipv4     2 tcp      6 1085 ESTABLISHED src=192.168.2.28 dst=47.254.152.213 sport=30327 dport=8950 src=47.254.152.213 dst=10.100.0.2 sport=8950 dport=30327 [ASSURED] mark=0 use=2
ipv4     2 udp      17 28 src=192.168.1.101 dst=192.168.2.28 sport=39109 dport=26258 [UNREPLIED] src=192.168.2.28 dst=192.168.1.101 sport=26258 dport=39109 mark=0 use=2

Where else can I look for a solution to the problem?

Sorry for the late response. Since the RF converter communicates on layer 2, it needs to be on the same network as the Home Assistant. I guess 192.168.1.101 and 192.168.2.28 are on different subnets, so they won’t be able to communicate each other.

Thanks for the response. I switched to the same network, but the converter still doesn’t respond to the command.
I’m attaching the packet send and receive capture from Wireshark.

First, please ensure that Smartmate app is working correctly. Next, how did you capture packets with Wireshark? Normally, Layer 2 packets cannot be captured because they are only passed through a switch hub. Lastly, please post the binary of the captured packet, and I’ll check for any issues. Thank you.

Yes, the Smartmate app is working correctly. The gate opens, and the green LED lights up on the RF Converter V3.0 device.

I suspect that the data being sent is incorrect or the checksum is off.
When sending the packet through this integration, the blue Wi-Fi LED on the RF Converter V3.0 blinks, but the green LED, which indicates the signal being sent to the gate, remains red.
Thank you for your help.

No.     Time           Source                Destination           Protocol Length Info
   1078 6.663952       192.168.2.30          192.168.2.28          UDP      85     26258 → 26258 Len=43

Frame 1078: 85 bytes on wire (680 bits), 85 bytes captured (680 bits) on interface \Device\NPF_{0F4E7421-ABE4-4575-85A5-6F700304567D}, id 0
Ethernet II, Src: Intel_de:65:4d (04:e8:b9:de:65:4d), Dst: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
    Destination: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Intel_de:65:4d (04:e8:b9:de:65:4d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 6]
Internet Protocol Version 4, Src: 192.168.2.30, Dst: 192.168.2.28
User Datagram Protocol, Src Port: 26258, Dst Port: 26258
Data (43 bytes)

0000  fe 01 01 0d 04 e8 b9 de 65 4d 08 3a 8d ee 2a 4f   ........eM.:..*O
0010  00 00 00 00 00 00 00 00 02 01 00 0c 66 e9 aa 52   ............f..R
0020  00 00 00 00 a9 80 40 00 00 75 ef                  [email protected].

No.     Time           Source                Destination           Protocol Length Info
   1082 6.685618       192.168.2.28          192.168.2.30          UDP      73     26258 → 26258 Len=31

Frame 1082: 73 bytes on wire (584 bits), 73 bytes captured (584 bits) on interface \Device\NPF_{0F4E7421-ABE4-4575-85A5-6F700304567D}, id 0
Ethernet II, Src: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f), Dst: Intel_de:65:4d (04:e8:b9:de:65:4d)
    Destination: Intel_de:65:4d (04:e8:b9:de:65:4d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 6]
Internet Protocol Version 4, Src: 192.168.2.28, Dst: 192.168.2.30
User Datagram Protocol, Src Port: 26258, Dst Port: 26258
Data (31 bytes)

0000  fe 02 01 0d 08 3a 8d ee 2a 4f 04 e8 b9 de 65 4d   .....:..*O....eM
0010  00 00 00 00 00 00 00 00 02 01 00 00 00 e6 ef      ...............

No.     Time           Source                Destination           Protocol Length Info
   1101 7.074682       192.168.2.28          192.168.2.30          UDP      74     26258 → 26259 Len=32

Frame 1101: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface \Device\NPF_{0F4E7421-ABE4-4575-85A5-6F700304567D}, id 0
Ethernet II, Src: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f), Dst: Intel_de:65:4d (04:e8:b9:de:65:4d)
    Destination: Intel_de:65:4d (04:e8:b9:de:65:4d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 6]
Internet Protocol Version 4, Src: 192.168.2.28, Dst: 192.168.2.30
User Datagram Protocol, Src Port: 26258, Dst Port: 26259
Data (32 bytes)

0000  fe 01 01 0d 08 3a 8d ee 2a 4f 04 e8 b9 de 65 4d   .....:..*O....eM
0010  00 00 00 00 00 00 00 00 21 01 00 01 00 00 08 ef   ........!.......

No.     Time           Source                Destination           Protocol Length Info
   1123 7.574880       192.168.2.28          192.168.2.30          UDP      74     26258 → 26259 Len=32

Frame 1123: 74 bytes on wire (592 bits), 74 bytes captured (592 bits) on interface \Device\NPF_{0F4E7421-ABE4-4575-85A5-6F700304567D}, id 0
Ethernet II, Src: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f), Dst: Intel_de:65:4d (04:e8:b9:de:65:4d)
    Destination: Intel_de:65:4d (04:e8:b9:de:65:4d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
    [Stream index: 6]
Internet Protocol Version 4, Src: 192.168.2.28, Dst: 192.168.2.30
User Datagram Protocol, Src Port: 26258, Dst Port: 26259
Data (32 bytes)

0000  fe 01 01 0d 08 3a 8d ee 2a 4f 04 e8 b9 de 65 4d   .....:..*O....eM
0010  00 00 00 00 00 00 00 00 21 01 00 01 00 00 08 ef   ........!.......

No.     Time           Source                Destination           Protocol Length Info
   2067 11.646526      Intel_de:65:4d        Espressif_ee:2a:4f    ARP      42     Who has 192.168.2.28? Tell 192.168.2.30

Frame 2067: 42 bytes on wire (336 bits), 42 bytes captured (336 bits) on interface \Device\NPF_{0F4E7421-ABE4-4575-85A5-6F700304567D}, id 0
Ethernet II, Src: Intel_de:65:4d (04:e8:b9:de:65:4d), Dst: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
    Destination: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Intel_de:65:4d (04:e8:b9:de:65:4d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: ARP (0x0806)
    [Stream index: 6]
Address Resolution Protocol (request)
    Hardware type: Ethernet (1)
    Protocol type: IPv4 (0x0800)
    Hardware size: 6
    Protocol size: 4
    Opcode: request (1)
    Sender MAC address: Intel_de:65:4d (04:e8:b9:de:65:4d)
    Sender IP address: 192.168.2.30
    Target MAC address: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
    Target IP address: 192.168.2.28

No.     Time           Source                Destination           Protocol Length Info
   2068 11.647935      Espressif_ee:2a:4f    Intel_de:65:4d        ARP      42     192.168.2.28 is at 08:3a:8d:ee:2a:4f

Frame 2068: 42 bytes on wire (336 bits), 42 bytes captured (336 bits) on interface \Device\NPF_{0F4E7421-ABE4-4575-85A5-6F700304567D}, id 0
Ethernet II, Src: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f), Dst: Intel_de:65:4d (04:e8:b9:de:65:4d)
    Destination: Intel_de:65:4d (04:e8:b9:de:65:4d)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: ARP (0x0806)
    [Stream index: 6]
Address Resolution Protocol (reply)
    Hardware type: Ethernet (1)
    Protocol type: IPv4 (0x0800)
    Hardware size: 6
    Protocol size: 4
    Opcode: reply (2)
    Sender MAC address: Espressif_ee:2a:4f (08:3a:8d:ee:2a:4f)
    Sender IP address: 192.168.2.28
    Target MAC address: Intel_de:65:4d (04:e8:b9:de:65:4d)
    Target IP address: 192.168.2.30

Thank you for the detailed post. The packets were sent from 192.168.2.30 to 192.168.2.28 four times, and they’re not same. Could you please specify in more detail how you called send_command each time? and how your remote controllers are registered in Safemate app?

Hi, this doesn’t work. It can retrieve all the data, but when sending a command, nothing happens. Have you tested this yourself ?

2024-11-27 00:40:16.659 WARNING (SyncWorker_20) [custom_components.rf_converter] Remote [SOMMER]/[key1] not found

2024-11-27 00:51:19.382 WARNING (SyncWorker_14) [custom_components.rf_converter] Remote [SOMMER]/[key] not found
2024-11-27 00:51:22.548 WARNING (SyncWorker_5) [custom_components.rf_converter] Remote [SOMMER]/[key] not found

Tried to test as seperate python file too without success…Any idea ? Data is fetched correctly, but i think there is some logical issue with how UDP packet is built…

import requests
import socket
import uuid
import json


class rf_converter:
    def __init__(self):
        self.remote_data = {}
        self.sequence = 0

    def GetRemote(self, requesturlbase, account, security_code, headers):
        try:
            # Fetch device data
            device_response = requests.post(
                requesturlbase + 'get_all_device_data.php',
                data={'account': account, 'security_code': security_code},
                headers=headers
            )
            device_response.raise_for_status()
            devices = device_response.json()
            self.remote_data = {}

            if devices['result'] == 0:
                # Process devices
                for device in devices['message']:
                    mac = device['mac']
                    remote_response = requests.post(
                        requesturlbase + 'get_remote_controller.php',
                        data={'mac': mac, 'security_code': security_code},
                        headers=headers
                    )
                    remote_response.raise_for_status()

                    # Log the JSON response from the remote controller API
                    remotes = remote_response.json()
                    print(f"Remote response for MAC {mac}: {json.dumps(remotes, indent=4)}")

                    if remotes['result'] == 0:
                        for remote in remotes['message']:
                            r_name = remote['r_name']
                            self.remote_data[r_name] = {
                                'ip': device['ip'],
                                'mac': mac,
                                'type': device['type'],
                                'project': device['project'],
                                'frequency': remote['frequency'],
                                'id': remote['id'],
                                'key': {key['k_name']: key['value'] for key in remote['key']}
                            }
            return devices['result']
        except Exception as e:
            print(f"Error in GetRemote: {e}")
            return -1

    def Checksum(self, crc_data, length):
        checksum = 0
        for byte in crc_data[:length]:
            checksum ^= byte
            for _ in range(8):
                if checksum & 1:
                    checksum = (checksum >> 1) ^ 0x8C
                else:
                    checksum >>= 1
        return checksum

    def PacketBuilder(self, device_type, device_project, sender, receiver, remote_id, frequency, key_value, sequence, remote_name=None, key_name=None):
        try:
            packet = bytearray()
            packet.append(0xFE)  # Start of packet
            packet.append(1 if key_value is not None else 2)  # Command type
            packet.append(int(device_type) & 0xFF)
            packet.append(int(device_project) & 0xFF)
            packet.extend(bytes.fromhex(sender.replace(':', '')))
            packet.extend(bytes.fromhex(receiver.replace(':', '')))
            packet.extend(b'\x00' * 8)  # Reserved bytes

            if key_value is None:
                packet.extend(b'\x21\x01\x00\x00')  # General command
            else:
                packet.extend(b'\x02\x01\x00\x0C')  # Key-specific command
                packet.extend((int(remote_id) & 0xFFFFFFFF).to_bytes(4, 'big'))
                packet.extend(b'\x00' * 4)  # Reserved
                packet.extend((int(frequency) & 0xFFFF).to_bytes(2, 'big'))
                packet.append(int(key_value) & 0xFF)
                packet.append(0x00)  # Key terminator

            # Add remote name and key name
            if remote_name:
                remote_name_bytes = remote_name.encode('utf-8')[:16]
                packet.extend(remote_name_bytes.ljust(16, b'\x00'))
            if key_name:
                key_name_bytes = key_name.encode('utf-8')[:16]
                packet.extend(key_name_bytes.ljust(16, b'\x00'))

            packet.append(sequence & 0xFF)
            packet.append(self.Checksum(packet, len(packet)))
            packet.append(0xEF)  # End of packet

            print(f"Composed UDP Packet: {packet.hex()}")
            return packet
        except Exception as e:
            print(f"Error in PacketBuilder: {e}")
            return None

    def CreatePacket(self, remote, key):
        try:
            if remote in self.remote_data:
                remote_info = self.remote_data[remote]
                if key in remote_info['key'] or key == '':
                    packet = self.PacketBuilder(
                        remote_info['type'],
                        remote_info['project'],
                        f'{uuid.getnode():x}',
                        remote_info['mac'],
                        remote_info['id'],
                        remote_info['frequency'],
                        None if key == '' else remote_info['key'][key],
                        self.sequence,
                        remote_name=remote,
                        key_name=key if key else None
                    )
                    self.sequence = (self.sequence + 1) & 0xFF
                    return remote_info['ip'], packet
            return None, None
        except Exception as e:
            print(f"Error in CreatePacket: {e}")
            return None, None

    def SendCommand(self, remote, key):
        try:
            ip, packet = self.CreatePacket(remote, key)
            if ip and packet:
                with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
                    sock.sendto(packet, (ip, 26258))
                print(f"Command sent to {remote} with key {key}.")
                return True
            print(f"Failed to create packet for remote: {remote}, key: {key}")
            return False
        except Exception as e:
            print(f"Error in SendCommand: {e}")
            return False


# Example Usage
if __name__ == '__main__':
    converter = rf_converter()

    # Configuration
    request_url = 'http://47.254.152.213/yetcloud_release/'
    account = 'xxxx'
    security_code = 'DSKWIJAKZXLQPSZMANXVTBFGYHPNVCRE'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Connection': 'keep-alive',
        'Accept': '*/*',
        'User-Agent': 'Custom-Agent'
    }

    # Fetch remote data
    if converter.GetRemote(request_url, account, security_code, headers) == 0:
        print("Remote data fetched successfully.")
    else:
        print("Failed to fetch remote data.")

    # Send command
    if converter.SendCommand('Sommer', 'key1'):
        print("Command sent successfully.")
    else:
        print("Failed to send command.")

C:\Kapi>python test.py
Remote response for MAC d8:3b:da:1c:03:e0: {
“result”: 0,
“message”: [
{
“mac”: “d8:3b:da:1c:03:e0”,
“r_order”: “1”,
“r_name”: “Sommer”,
“id”: “1732662252”,
“brand”: “10”,
“speed”: “0”,
“frequency”: “86880”,
“key”: [
{
“k_order”: “1”,
“k_name”: “key1”,
“image”: “14”,
“type”: “0”,
“value”: “32”
},
{
“k_order”: “2”,
“k_name”: “key2”,
“image”: “15”,
“type”: “0”,
“value”: “64”
},
{
“k_order”: “3”,
“k_name”: “key3”,
“image”: “16”,
“type”: “0”,
“value”: “128”
},
{
“k_order”: “4”,
“k_name”: “key4”,
“image”: “17”,
“type”: “0”,
“value”: “16”
}
]
}
]
}
Remote data fetched successfully.
Composed UDP Packet: fe01010f5414f377493ed83bda1c03e000000000000000000201000c674653ec0000000053602000536f6d6d6572000000000000000000006b6579310000000000000000000000000029ef
Command sent to Sommer with key key1.
Command sent successfully.

C:\Kapi>

Remote and Key are case sensitive. Please try sending command with remote name ‘Sommer’ instead of ‘SOMMER’.
And your seperated python file does not create correct packet. You added remote and key name into packet, and should not.

Hi tested sending a command using Sommer as the remote and key1 as the key. The command seems to be processed successfully, as there are no errors in the logs. However, the target device does not respond (e.g., no blinking or action).

Interestingly, when I use a random key instead of key1, the logs show the following error:

2024-12-09 00:47:33.513 WARNING (SyncWorker_16) [custom_components.rf_converter] Remote [Sommer]/[A] not found

This indicates that the system recognizes Sommer and key1 as valid inputs, but the device still fails to react.

Thank you for your comment.

  1. Make sure that the Home Assistant and RF Converter are within the same subnet for layer 2 communication.
  2. What type is your remote (Sommer and key1)? Are they built-in pre-configured ones or DIY learned keys? I have only tested DIY remote keys, and there’s a chance that built-in keys may not work.