python-broadlink icon indicating copy to clipboard operation
python-broadlink copied to clipboard

Add support for the FastCon technology

Open felipediel opened this issue 3 years ago • 15 comments

Proposed change

Add support for the FastCon technology. SP4 devices can now communicate with sub-devices.

Credits

@stevendodd helped us integrate the S3 hub recently. It's the same protocol.

Type of change

  • [ ] Dependency upgrade
  • [ ] Bugfix (non-breaking change which fixes an issue)
  • [ ] New device
  • [ ] New product id (the device is already supported with a different id)
  • [x] New feature (which adds functionality to an existing device)
  • [ ] Breaking change (fix/feature causing existing functionality to break)
  • [ ] Code quality improvements to existing code or addition of tests
  • [ ] Documentation

Additional information

  • This PR fixes issue: fixes https://github.com/mjg59/python-broadlink/issues/645
  • This PR is related to:
  • Link to documentation pull request:

Checklist

  • [ ] The code change is tested and works locally.
  • [x] The code has been formatted using Black.
  • [x] The code follows the Zen of Python.
  • [x] I am creating the Pull Request against the correct branch.
  • [ ] Documentation added/updated.

felipediel avatar Mar 19 '22 22:03 felipediel

How to test

Build the environment

Linux

python3 -m venv venv
source venv/bin/activate
pip3 install git+https://github.com/felipediel/python-broadlink.git@fastcon

WIndows

python3 -m venv venv
source venv/Scripts/activate
pip3 install git+https://github.com/felipediel/python-broadlink.git@fastcon

Run the code

python3

The Python Interpreter is open. Let's write some code and check the response.

>>> import broadlink as blk
>>> device = blk.hello("192.168.0.16")  # Example IP address
>>> device.auth()
>>> subdevices = device.get_subdevices()
>>> did = subdevices[0].get("did")
>>> device.get_state(did)
>>> device.set_state(did, pwr=1)
>>> device.set_state(did, pwr=0)

felipediel avatar Mar 19 '22 23:03 felipediel

Hi @felipediel , when running: did = subdevices[0].get("did") I get an error Traceback (most recent call last): File "", line 1, in IndexError: list index out of range

OMVMMG avatar Mar 22 '22 12:03 OMVMMG

Thank you! I forgot to mention, you need to have a sub-device connected to the device to test.

felipediel avatar Mar 22 '22 15:03 felipediel

I have 2 devices and one of them must be connecting as a sub-device as it doesn't respond to ping but I can control it thorugh Home Assistant and the Broadlink app, which woulod indicate it's part of the FastCon mesh. However, in the Broadlink app it doesn't specifically appear as a sub-device.

OMVMMG avatar Mar 23 '22 10:03 OMVMMG

@OMVMMG what type of sub devices do you have?

If you would like to test with: https://hub.docker.com/r/stevendodd/s3-rest-api or https://github.com/stevendodd/python-broadlink/tree/Add_S3_REST_API perhaps we can get more information

Instructions here: https://community.home-assistant.io/t/broadlink-s3-hub-support/319832/18?u=stevendodd

Noticed you are potentially using an SP4 device .. I'm not sure how that works but you might just be able to add the device ID into the Python library under an S3 hub for testing

stevendodd avatar Mar 23 '22 12:03 stevendodd

I have 2 devices and one of them must be connecting as a sub-device as it doesn't respond to ping but I can control it thorugh Home Assistant and the Broadlink app, which woulod indicate it's part of the FastCon mesh. However, in the Broadlink app it doesn't specifically appear as a sub-device.

If you can control it with Home Assistant, it's not a subdevice, we don't support this feature yet.

felipediel avatar Mar 23 '22 14:03 felipediel

If you can control it with Home Assistant, it's not a subdevice, we don't support this feature yet.

I can control one of them, as soon as I integrate the second device I lose control of the other.

OMVMMG avatar Mar 24 '22 11:03 OMVMMG

Are you using the process I described to create a Docker image?

stevendodd avatar Mar 24 '22 11:03 stevendodd

@felipediel hi I have four devices SP4L-EU, one main and three others are connected through it. I was unable to get a list of subdevices, I am attaching the logs that I could get

state = {"count": step, "index": index}
print(state) # {'count': 5, 'index': 0}
packet = self._encode(14, state)
print(packet) # bytearray(b'!\x00\xa5\xa5ZZ\xa1\xc7\x0e\x0b\x15\x00\x00\x00{"count":5,"index":0}')
resp = self.send_packet(0x6A, packet)
print(resp) # b'Z\xa5\xaaUZ\xa5\xaaU\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\xe9\x00\x00\x8ba\xee\x03m\x94e8\x00\xb0C\xa0\x01\x00\x00\x00\x96\xcf\x00\x00\xfe\x10X\x995\xd2\xbcp\xe7\xe9\x8b\x1b\xc2\x95F\xd9\xec3\x07\x11\xe5\xf2\xc2\x93\x7fn \x02(\xb1\x1d@AM\x8c\xe7\xbf\x82\xf5h\x85heZ\xaa\xdd\x9b\x92^\x9dB5\xb7\xaf\x18\xddu\xa6\xb7Ez\x843E'
e.check_error(resp[0x22:0x24])
resp = self._decode(resp)
print(resp) # {'status': 0, 'total': 0, 'index': 0, 'list': []}

Is there anything else I can help?

ovionlogis avatar Mar 24 '22 17:03 ovionlogis

Thank you! Maybe the communication is a bit different. I will do some research.

If anyone can make it work, please let me know.

felipediel avatar Mar 25 '22 19:03 felipediel

We are making progress here: home-assistant/core/pull/69338. Everyone with subdevices is welcome to help capture and decode this packet:

import socket

def discover(ip_addr):
    conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    conn.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    conn.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    conn.settimeout(10)
    packet = bytearray(0x30)
    packet[0x26] = 6
    checksum = sum(packet, 0xBEAF) & 0xFFFF
    packet[0x20:0x22] = checksum.to_bytes(2, "little")
    conn.sendto(packet, (ip_addr, 80))
    resp = conn.recvfrom(1024)
    conn.close()
    return resp

resp = discover("192.168.0.16")  # Example device IP address
print(resp)

unknown_bytes = resp[0x80:]
print(unknown_bytes)

So the mission is to capture and understand the unknown bytes. This part of the packet contains the MAC address and product id (2 bytes) of the subdevices.

felipediel avatar Apr 05 '22 22:04 felipediel

@felipediel are you wanting someone to try and connect directly to a sub device? I don't think that's possible; I have to talk via the hub. The hub then sends UDP traffic to each sub device via a broadcast message.

Screenshot (Feb 10, 2022 6_44_53 PM)

stevendodd avatar Apr 06 '22 18:04 stevendodd

No, it's via hub, the devices can work as hubs too. They have subdevices that can be discovered with the function above.

felipediel avatar Apr 06 '22 18:04 felipediel

192.168.1.99 = S3 Hub

Stevens-MacBook-Pro:python-broadlink steve$ python3 test.py (b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc6\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00D\x12e|M\xa6c\x01\xa8\xc0o\x029\xae\x0b\xec42573\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00', ('192.168.1.99', 80)) ()

stevendodd avatar Apr 06 '22 18:04 stevendodd

Would it help if we specify the DID (device unique identifier) in the integration? We can get the DID from Device Info from the Broadlink App.

TanTrungNguyen avatar Apr 10 '23 18:04 TanTrungNguyen