Rollease Acmeda Automate Pulse hub integration

@fantangelo, thanks for the dump - I’ve worked it out. The room/scene/roller ID’s are not stings so I’ve changed how they’re parsed. I’ve just committed an update to the aiopulse API if you can give the demo one more go. If this works for you I’ll update the Home Assistant integration.

@stavroz, can you run the demo on another machine and provide the debug dumps? Any OS with python 3 should be fine.

I have re-run the following in hass.io terminal and then tried to re-add the integration but I still get the same error.

curl https://codeload.github.com/atmurray/home-assistant/tar.gz/acmeda | tar -xz --strip=3 home-assistant-acmeda/homeassistant/components/acmeda

Not sure how to run the aiopulse demo?
thanks

@atmurray I have run the new demo file. See output below.
The app nows exits after the third roller (there are nine on the hub).

$ python3 demo.py

discover
Starting hub discovery
DEBUG:aiopulse.transport:Connection established
DEBUG:aiopulse.transport:UDP datagram received
INFO:aiopulse.hub:192.168.0.8: Discovered hub on port 12414
DEBUG:aiopulse.transport:UDP datagram received
DEBUG:aiopulse.transport:Connection established
INFO:aiopulse.hub:192.168.0.8: Handshake complete
DEBUG:aiopulse.hub:192.168.0.8: Disconnecting
DEBUG:aiopulse.transport:Socket closed
DEBUG:aiopulse.transport:192.168.0.8: TCP buffer cleared.
DEBUG:aiopulse.transport:192.168.0.8: TCP connection closed.
INFO:aiopulse.hub:192.168.0.8: Disconnected
Hub added to prompt
INFO:aiopulse.hub:192.168.0.43: Discovered hub on port 12414
DEBUG:aiopulse.transport:Connection established
INFO:aiopulse.hub:192.168.0.43: Handshake complete
DEBUG:aiopulse.hub:192.168.0.43: Disconnecting
DEBUG:aiopulse.transport:Socket closed
DEBUG:aiopulse.transport:192.168.0.43: TCP buffer cleared.
DEBUG:aiopulse.transport:192.168.0.43: TCP connection closed.
INFO:aiopulse.hub:192.168.0.43: Disconnected
Hub added to prompt
INFO:aiopulse.hub:Discovery complete
DEBUG:aiopulse.transport:UDP connection closed
DEBUG:aiopulse.transport:Socket closed
connect
INFO:aiopulse.hub:192.168.0.8: Connecting
INFO:aiopulse.hub:192.168.0.43: Connecting
DEBUG:aiopulse.transport:Connection established
INFO:aiopulse.hub:192.168.0.8: Handshake complete
DEBUG:aiopulse.hub:192.168.0.8: Hub update command sent
DEBUG:aiopulse.hub:192.168.0.8: Starting response parser
DEBUG:aiopulse.transport:Connection established
WARNING:aiopulse.hub:192.168.0.8: Received unknown response type: b’61000091’, trying to decode anyway. Message: b’06536d6172745f4964315f793a4f001600030000000000000053020800303030303030333954020800303430323030313355020800303048464c50423156020c0046304645364235454342384157020b0031
39322e3136382e302e38ff2b’
INFO:aiopulse.hub:192.168.0.8: Parsing hub info
DEBUG:aiopulse.hub:192.168.0.8: Received response: b’03000091’ acknowledge content: b’’
DEBUG:aiopulse.hub:192.168.0.8: Received response: b’01000091’ scene list content: b’\x06Smart_Id1_y:\xaf\x00\x01\x01\x05\x00\x00\x00\x00\x00\x00\x00\x10\x00\x01\x00\x06\x00\x02\x08\x008CA6\x04\x0c7(\x0f\x00\x01\x00\x05\x0e\x00\x05\x00Seven\x00\x02\x08\x007265\x04\r\x02\x11\x0f
x00\x01\x00\x01\x0e\x00\x05\x00Three\x00\x02\x08\x0096EA\x04\r\x07\x1b\x0f\x00\x01\x00\x03\x0e\x00\x07\x00Bedroom\x00\x02\x08\x006FD2\x06\x0c*\r\x0f\x00\x01\x00\n\x0e\x00\x05\x00South\x00\x02\x08\x006063\x06\x0c,\x0f\x0f\x00\x01\x00\x06\x0e\x00\x04\x00East\x00\x02\x08\x00E044\t
x10)\x0e\x0f\x00\x01\x00\x0b\x0e\x00\x06\x00Office\xff\x03’
INFO:aiopulse.hub:192.168.0.8: Parsing room list
Hub updated
INFO:aiopulse.hub:192.168.0.43: Handshake completeDEBUG:aiopulse.hub:192.168.0.43: Hub update command sentDEBUG:aiopulse.hub:192.168.0.43: Starting response parser
DEBUG:aiopulse.hub:192.168.0.8: Received response: b’04000091’ 04000091 content: b’\x06Smart_Id1_y:c\x02!\x01\x06\x00\x00\x00\x00\x00\x00\x00\x10\x00\x01\x00\t\x01\x01\x06\x00e7\xdfJ\x00\x01\x00\x02\x08\x006063\x06\x0c,\x0f\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 1\x02\x01\x02
x001\x02x\x02\x06\x00534001\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x14\x00\x01\x01\x06\x00X6\xcc\xf8\x00\x01\x00\x02\x08\x006063\x06\x0c,\x0f\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 2\x02\x01\x02\x001\x02x\x02\x06\x00534002\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x14\x00\x01\x
01\x06\x00\x9e\x05\x8a}\x00\x01\x00\x02\x08\x007265\x04\r\x02\x11\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 3\x02\x01\x02\x001\x02x\x02\x06\x00534003\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x11\xb4\x01\x01\x06\x00\xe1\xe23\x07\x00\x01\x00\x02\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 4\x02\x01\x02\x001\x02x\x02\x06\x00534004\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x0f\x00\x01\x01\x06\x00\x17\xb5\x06\t\x00\x01\x00\x02\x08\x006FD2\x06\x0c*\r\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 5\x02\x01\x02\x001\x02x\x02\x06\x00534005\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x0f\xb4\x01\x01\x06\x00\x18,8\x04\x00\x01\x00\x02\x08\x006FD2\x06\x0c*\r\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 6\x02\x01\x02\x001\x02x\x02\x06\x00534006\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x0f\x00\x01\x01\x06\x00\xfb\xd9&\x1b
\x00\x01\x00\x02\x08\x008CA6\x04\x0c7(\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 7\x02\x01\x02\x001\x02x\x02\x06\x00534007\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x0f\xb4\x01\x01\x06\x00k\xb4\xa5u\x00\x01\x00\x02\x08\x006FD2\x06\x0c*\r\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 8\x02\x01\x02\x001\x02x\x02\x06\x00534008\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x0f\x00\x01\x01\x06\x00\xa2\xc1;*\x00\x01\x00\x02\x08\x0096EA\x04\r\x07\x1b\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 0\x02\x01\x02\x001\x02x\x02\x06\x00534009\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x14\x00\xff\xcd’INFO:aiopulse.hub:192.168.0.8: Parsing roller listHub updatedDEBUG:aiopulse.hub:192.168.0.43: Received response: b’62000091’ 62000091 content: b’\x06Smart_Id1_y:P\x00\x16\x00\x03\x00\x00\x00\x00\x00\x00\x00S\x02\x08\x0000000039T\x02\x08\x0004020013U\x02\x08\x0000HFLPB1V\x02\x0c\x00F0FE6B3E40B4W\x02\x0c\x00192.168.0.43\xff5’INFO:aiopulse.hub:192.168.0.43: Parsing hub infoDEBUG:aiopulse.hub:192.168.0.43: Received response: b’03000091’ acknowledge content: b’‘DEBUG:aiopulse.hub:192.168.0.43: Received response: b’57000091’ roller name change content: b’\x06Smart_Id1_y:E\x00\x01\x01\x05\x00\x00\x00\x00\x00\x00\x00\x10\x00\x01\x00\x02\x00\x02\x08\x00E044\t\x10)\x0e\x0f\x00\x01\x00\x0b\x0e\x00\x06\x00Office\x00\x02\x08\x006063\x06\x0c,\x0f\x0f\x00\x01\x00\x06\x0e\x00\x04\x00East\xff\xa6’INFO:aiopulse.hub:192.168.0.43: Parsing room listHub updatedDEBUG:aiopulse.hub:192.168.0.43: Received response: b’65000091’ timer list content: b’\x06Smart_Id1_y:S\x00!\x01\x06\x00\x00\x00\x00\x00\x00\x00\x10\x00\x01\x00\x01\x01\x01\x06\x00ss\xf1Q\x00\x01\x00\x02\x08\x00E044\t\x10)\x0e\x0f\x00\x01\x00\x04\x0e\x00\x07\x00SHADE 9\x02\x01\x02\x001\x02x\x02\x06\x00779001\x03\x01\x01\x00\x19\x04\x01\x03\x00\x03\x18\xb4\xffm’INFO:aiopulse.hub:192.168.0.43: Parsing roller list
Hub updated
DEBUG:aiopulse.hub:192.168.0.8: Received response: b’03000091’ acknowledge content: b’\x06Smart_Id1_y:\xca\x013\x01\n\x00\x00\x00\x00\x00\x00\x00\x10\x00\x01\x00\n\x10\x02\x08\x00477C\x14\t)\x0e\x0f\x00\x01\x00\x02\x0e\x00\t\x00East Open\x13\x02\x01\x00\x04R\x02\x02\x001]\x10\x02\x08\x0068BB\x14\t,\x15\x0f\x00\x01\x00\x02\x0e\x00\n\x00South Open\x13\x02\x01\x00\x04R\x02\x02\x001]\x10\x02\x08\x004CC5\x19\x0e!\x03\x0f\x00\x01\x00\x02\x0e\x00\x0c\x00Office Opens\x13\x02\x01\x00\x00R\x02\x02\x001]R\x02\x02\x00h\x13\x10\x02\x08\x0023AB\x19\x0e!“\x0f\x00\x01\x00\x00\x0e\x00\r\x00Office Closes\x13\x02\x01\x00\x00R\x02\x02\x001]R\x02\x02\x00h\x13\x10\x02\x08\x00B71C\x1b\x0b\x06#\x0f\x00\x01\x00\x02\x0e\x00\n\x00Three Open\x13\x02\x01\x00\x01R\x02\x02\x001]\x10\x02\x08\x008922\x1c\x0e\x13,\x0f\x00\x01\x00\x02\x0e\x00\t\x00Four Open\x13\x02\x01\x00\x01R\x02\x02\x001]\x10\x02\x08\x0018D2\x1c\x0e\x16\x11\x0f\x00\x01\x00\x02\x0e\x00\n\x00Seven Open\x13\x02\x01\x00\x01R\x02\x02\x001]\x10\x02\x08\x00604D\x1e\x0f\x0e0\x0f\x00\x01\x00\x02\x0e\x00\n\x00Eight Open\x13\x02\x01\x00\x01R\x02\x02\x001]\x10\x02\x08\x00BD62\x0f\t\x10”\x0f\x00\x01\x00\x00\x0e\x00\x0b\x00Eight Close\x13\x02\x01\x00\x01R\x02\x02\x001]\x10\x02\x08\x002654\t\r$\x0b\x0f\x00\x01\x00\x04\x0e\x00\t\x00Not Sunny\x13\x02\x01\x00\x05R\x02\x02\x001]R\x02\x02\x00h\x13\xff\xad’
INFO:aiopulse.hub:192.168.0.8: Parsing scene list
Hub updated
WARNING:aiopulse.hub:192.168.0.8: Received unknown response type: b’4e000091’, trying to decode anyway. Message: b’06536d6172745f4964315f793a3c0033010b0000000000000010000100011002080046373632091034280f000100000e000b004561737420436c6f736573130201000452020200315dff01’
INFO:aiopulse.hub:192.168.0.8: Parsing scene list
Hub updated
DEBUG:aiopulse.hub:192.168.0.43: Received response: b’01000091’ scene list content: b’\x06Smart_Id1_y:\xa5\x003\x01\n\x00\x00\x00\x00\x00\x00\x00\x10\x00\x01\x00\x03\x10\x02\x08\x0023AB\x19\x0e!“\x0f\x00\x01\x00\x00\x0e\x00\r\x00Office Closes\x13\x02\x01\x00\x01R\x02\x02\x001]R\x02\x02\x00h\x13\x10\x02\x08\x004CC5\x19\x0e!\x03\x0f\x00\x01\x00\x02\x0e\x00\x0c\x00Office Opens\x13\x02\x01\x00\x01R\x02\x02\x001]R\x02\x02\x00h\x13\x10\x02\x08\x002654\t\r$\x0b\x0f\x00\x01\x00\x04\x0e\x00\t\x00Not Sunny\x13\x02\x01\x00\x00R\x02\x02\x001]R\x02\x02\x00h\x13\xff\xda’
INFO:aiopulse.hub:192.168.0.43: Parsing scene list
Hub updated
WARNING:aiopulse.hub:192.168.0.8: Received unknown response type: b’76000091’, trying to decode anyway. Message: b’06536d6172745f4964315f793a640041010f00000000000000100001000120020800344643451408382e0f000100030e0016004f666669636520636c6f736573206174206e6967687421020100013b020100153c02010037220204007f0000003d020100001002080032334142190e2122ffac’
INFO:aiopulse.hub:192.168.0.8: Parsing timer list
WARNING:aiopulse.hub:192.168.0.43: Received unknown response type: b’76000091’, trying to decode anyway. Message: b’06536d6172745f4964315f793a640041010f00000000000000100001000120020800344643451408382e0f000100030e0016004f666669636520636c6f736573206174206e6967687421020100013b020100153c02010037220204007f0000003d020100001002080032334142190e2122ffac’
INFO:aiopulse.hub:192.168.0.43: Parsing timer list
DEBUG:aiopulse.hub:192.168.0.43: Received response: b’03000016’ ping content: b’’
DEBUG:aiopulse.hub:192.168.0.43: Received hub ping response
DEBUG:aiopulse.hub:192.168.0.8: Received response: b’03000016’ ping content: b’’
DEBUG:aiopulse.hub:192.168.0.8: Received hub ping response
list
Listing hubs…
Hub 1: Name: WXSPONEFLS
Roller 1: Name: SHADE 1 ID: 1100767770469 Serial: 534001 Room: East Type: 4 Closed %: 20 Battery %: 100 Flags: 00000000
Roller 2: Name: SHADE 2 ID: 1103685760600 Serial: 534002 Room: East Type: 4 Closed %: 20 Battery %: 100 Flags: 00000000
Roller 3: Name: SHADE 3 ID: 1101617825182 Serial: 534003 Room: Three Type: 4 Closed %: 17 Battery %: 100 Flags: 10110100
ERROR:asyncio:Future exception was never retrieved
future: <Future finished exception=AttributeError(”‘NoneType’ object has no attribute ‘name’")>
Traceback (most recent call last):
File “/usr/lib/python3.8/concurrent/futures/thread.py”, line 57, in run
result = self.fn(*self.args, **self.kwargs)
File “/usr/lib/python3.8/cmd.py”, line 138, in cmdloop
stop = self.onecmd(line)
File “/usr/lib/python3.8/cmd.py”, line 217, in onecmd
return func(arg)
File “demo.py”, line 114, in do_list
print(“Roller {}: {}”.format(rid, roller))
File “/config/custom_components/aiopulse/elements.py”, line 34, in str
self.room.name,
AttributeError: ‘NoneType’ object has no attribute ‘name’
custom_components $
*1 [bash] Sat 04-18 10:42

ok, I have installed and run the demo program. There are no errors and it discovers the hub but not the devices.

➜  aiopulse python3 demo.py
> discover
Starting hub discovery
> DEBUG:aiopulse.transport:Connection established
DEBUG:aiopulse.transport:UDP datagram received
INFO:aiopulse.hub:192.168.1.167: Discovered hub on port 12414
DEBUG:aiopulse.transport:Connection established
INFO:aiopulse.hub:192.168.1.167: Handshake complete
DEBUG:aiopulse.hub:192.168.1.167: Disconnecting
DEBUG:aiopulse.transport:Socket closed
DEBUG:aiopulse.transport:192.168.1.167: TCP buffer cleared.
DEBUG:aiopulse.transport:192.168.1.167: TCP connection closed.
INFO:aiopulse.hub:192.168.1.167: Disconnected
Hub added to prompt
INFO:aiopulse.hub:Discovery complete
DEBUG:aiopulse.transport:UDP connection closed
DEBUG:aiopulse.transport:Socket closed
list
Listing hubs...
Hub 1: Name: QCNMNHJYHW
> Traceback (most recent call last):
  File "demo.py", line 189, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.8/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 603, in run_until_complete
    self.run_forever()
  File "/usr/lib/python3.8/asyncio/base_events.py", line 570, in run_forever
    self._run_once()
  File "/usr/lib/python3.8/asyncio/base_events.py", line 1823, in _run_once
    event_list = self._selector.select(timeout)
  File "/usr/lib/python3.8/selectors.py", line 468, in select
    fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3.8/concurrent/futures/thread.py", line 40, in _python_exit
    t.join()
  File "/usr/lib/python3.8/threading.py", line 1011, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.8/threading.py", line 1027, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

@fantangelo you need to use the “connect” command to discover the blinds

Not sure why but ‘connect’ just gave me a bunch of errors when I was trying it before but it is working now. Not sure if a restart of hassio made a difference.
thanks for the tip.

@gregbm: That’s great, I was able to reproduce the issue - you have a roller that is not in any room. I’ve re-created your full setup and was able to get everything to parse OK. Can you check-out the latest and give the demo yet another go?

Also, noting that you’ve already posted it publically here, are you happy for me to use all your output to create unit tests that I’ll check-in? I don’t believe there is anything personally identifying (just the private IP addresses of your hub along with room/scene/roller names).

It’d be great if someone could help prepare the branding for the integration as per the information in the following:

Similarly, improving the documentation for the integration would be greatly appreciated too:

Neither of these contributions require any coding skills.

The latest version works - thanks

Go ahead and use the output, As you say there is nothing personal there.

Hi,
The demo program discovers the hub and devices but the integration to HA is still giving me the same errors and not finding any devices:

2020-04-19 06:39:39 ERROR (MainThread) [root] 192.168.1.167: Exception raised when parsing response: b'000000037100009106536d6172745f4964315f793a5f0033010a0000000000000010000100021002080062643731606b26610f000100020e0007004d6f726e696e671302010007520202006f941002080062643731a21d8b8a0f000100010e0007004576656e696e671302010007520202006f94ffe5'
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/aiopulse/hub.py", line 510, in response_parse
    self.rec_message(message)
  File "/usr/local/lib/python3.7/site-packages/aiopulse/hub.py", line 441, in rec_message
    self.msgmap[mtype].execute(self, message[ptr:])
  File "/usr/local/lib/python3.7/site-packages/aiopulse/hub.py", line 400, in execute
    self.function(target, message)
  File "/usr/local/lib/python3.7/site-packages/aiopulse/hub.py", line 266, in response_scenelist
    scene_id, ptr = utils.unpack_string(message, ptr)
  File "/usr/local/lib/python3.7/site-packages/aiopulse/utils.py", line 28, in unpack_string
    str_new.decode("utf-8"),
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa2 in position 4: invalid start byte

Gents, I just pushed a new commit of the integration to my fork. Suggest using the instructions on the other thread to install it as a custom component to give it a go. You may need to upgrade to a fairly recent build of Home Assistant (I’m on 0.108.5).

Let me know how you go.

The integration is working now. Thanks for your work! :+1:
I have two feature requests.

I only need to send a command to my shades twice a day, once in the morning based on sunrise to open, then in the evening to close based on sunset. I don’t really need to know if someone manually uses the remote to open/close the shades. So, is it possible to minimize the polling that is done to determine the current state? For example, by using a ‘scan_interval’ setting? I am concerned about unnecessary WIFI traffic when my system is already fairly congested as is. I would set the scan interval to, let’s say, once an hour.

Secondly, is there a way to open/close all shades with one cover.open call?

Also, is the discovery of hubs and devices only run once when the integration is added or is it run on every HA restart?

Thanks again for your work.

@atmurray I still get an error trying to install the integration. I upgraded to hassio 0.108.6 and HassOS 3.13.

Error log is:

2020-04-19 10:22:40 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 418, in start
    resp = await task
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_app.py", line 458, in _handle
    resp = await handler(request)
  File "/usr/local/lib/python3.7/site-packages/aiohttp/web_middlewares.py", line 119, in impl
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/real_ip.py", line 39, in real_ip_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 72, in ban_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 127, in auth_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 123, in handle
    result = await result
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 163, in post
    return await super().post(request, flow_id)
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 50, in wrapper
    result = await method(view, request, *args, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 92, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 130, in async_configure
    result = await self._async_handle_step(flow, cur_step["step_id"], user_input)
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 168, in _async_handle_step
    f"Handler {flow.__class__.__name__} doesn't support step {step_id}"
homeassistant.data_entry_flow.UnknownStep: Handler AcmedaFlowHandler doesn't support step init 

I dont know even linux very well, I think im missing something…

Glad it works!

is it possible to minimize the polling that is done to determine the current state? For example, by using a ‘scan_interval’ setting? I am concerned about unnecessary WIFI traffic when my system is already fairly congested as is. I would set the scan interval to, let’s say, once an hour.

The way I developed the API is asynchronous and doesn’t rely on polling at all. Essentially, the hub tells the API and therefore Home Assistant when a blind changes position. The only exception to this is that the API does periodically (every 30 seconds) send a short “poll” message (a couple of dozen bytes in total) in order to keep the connection to the hub alive. This mimics the way the hub communicates with the smart phone app and the Acmeda cloud service. As such, load on your WiFi network won’t be more than what these already create.

is there a way to open/close all shades with one cover.open call?

Despite creating this integration, I’m in no way a Home Assistant expert. However, I think this sort of thing should be able to be configured within Home Assistant itself. Have you considered configuring an automation or script to do this? I could look at exposing the configured Hub scenes in Home Assistant, but this seems to waste the power of Home Assistant itself.

is the discovery of hubs and devices only run once when the integration is added or is it run on every HA restart?

Discovery only runs the one time you “add” the integration (you can re-add the integration to add multiple hubs). You can actually manually add hubs to Home Assistant using the configuration script if for some reason discovery doesn’t work or you prefer not to run it.

@gregbm

I still get an error trying to install the integration.

I could be wrong but it looks like your install isn’t upgrading correctly. Either way, just for you I’ve had a go at backporting the integration, give the following a try:

curl https://codeload.github.com/atmurray/home-assistant/tar.gz/acmeda-backport | tar -xz --strip=3 home-assistant-acmeda-backport/homeassistant/components/acmeda

@stavroz, looks like you haven’t installed the API.

You can do this from PyPi:

pip install aiopulse

Or from within the aiopulse code in the directory that contains setup.py:

pip install .

Or by manually installing the dependancies:

pip install asyncio async_timeout

Thanks for your detailed reply. Congrats on creating this integration!
I will use it and report back any problems or issues.

@atmurray
The backport worked for me. Thanks for your excellent support with this.

One issue is that the Current Position is the opposite of what the app says. When the Shade is closed the current position says 0% whereas the app says 100%

A question - does the battery level work? Mine all say 100%.

fyi, all of my battery sensors show as unknown even after several restarts.

@fantangelo - Yes you can do this with Cover Groups - https://www.home-assistant.io/integrations/cover.group/