Help needed creating a custom Hub Component

I am trying to integrate my securifi Almond+ to HASS and learning python at the same time. The API uses Websockets

Is there a tutorial on how to create a basic hub component? I tried to use wink as an example and it looks like it relies on pywink. I had a look at it, but since it is very feature rich, I am slightly confused.

If someone could just provide a very simple example /pseudo code of how to set this up, that would be much appreciated.

Here’s my understanding.

  1. I need to create a pyalmond component that initiates and creates the websocket connection. This will be open on a single thread. I have this running partially.

  2. I will need to have a device component, let us say a switch, that will talk to the pyalmond component and get/set the state.

Any pointers/tips would be appreciated.

I think this would be better categorized in the Developer section. I can move it there if you like but I thought I’d ask you first.

Sure. Please do. You’re right, that seems like a better fit

My pleasure. I hope you don’t mind but I also modified the title a little so as to make more sense for your needs.

Sorry I can’t help you directly but I’m hoping this will result in getting you the right answers.

Maybe this helps.

Thanks. I did try using websocket client, but ws4py (https://ws4py.readthedocs.io) seems to work a bit better.

I can send and receive messages using that, but I am more interested in what I need to do to integrate with HomeAssistant and how that works.

Take a light for example. Here are the three things that I need to accomplish.

  1. Discover the lights. The API will allow me to get a list of devices, I can iterate through the list and fetch only the lights. Now how do I send this to HASS

  2. Communicate state changes - Since its a constant connection I can get the state changes. I am trying to understand if HASS polls for any state change or does my script have to push the state change to HASS.

I think these are pretty basic questions, but I am unable to get the answers I need to come up with something from scratch. Any pointers would be appreciated.

Home assistant is in the process of moving to async instead of using threads. By doing so it will probably start using aiohttp for all internet communication including web sockets. I don’t know when this is all going to happen, but I am pretty sure this will be the future proof way of doing this…

It has taken me hours of study and experimentation but I think I have this figured out. It wasn’t easy as I am new to python too.

My implementation uses telnet to listen and talk to the Lutron Caseta Pro hub, your implementation my use a built in protocol or stack. You need to study the python libraries for asyncio (asynciolib) and how to add to the event loop in HA with coroutines. zone.py in the components directory is a good place to study as, they are using the basic functionality. Once I have the bugs wrung out on my code I will make it available.

Thank you. This is what I was looking for. I’ll look at zone.py as well as your code when you release it.

Sorry about this but I have different answer now. After attempting to use the the event loop which utilizes asincio, appeared to be real stable, I had issues with future and exceptions. I have changed my methodology to a much simpler method. when using “hass.bus.listen_once(EVENT_HOMEASSISTANT_START, my_running_function)” I discovered that the function is started in i’s own thread so I just used a “while self.I_am_running” type loop with “time.sleep(self.interval)” in the loop to set my loop rate. Then a stop function which runs in a different thread can be used to turn off “self.I_am_running” which will stop the loop. This is simple but, I am finding that the timing in the loop stutters a bit since I run mine at 6 to 8 per second to read the switches. This is at least stable, handles the hub going offline and reconnecting and can be stopped and restarted.

If anyone has any input on dealing with this in the event loop using an outside socket handler (I am using telnetlib), I would like to hear it.

I too have a Almond+ and would like to use it as a bridge. I started googling and found this thread and another one you started https://community.home-assistant.io/t/newbie-hass-component/25826?u=penright. The other was newer but this had more activity. Which one?
I am a .NET guy, but can I speak other languages. :slight_smile: I am willing to help.

So I have two questions:
@kdvlr Where are you at on this project?
Anyone else interested?

I could not get around to creating a proper component, but ended up using command line sensors and switches. I have uploaded those very crude scripts into github here - https://github.com/kdvlr/almond-scripts/ That should get you started

So are you still using your Almond+ for home automation task?

Just started digging, but here is where I am at right now.
Somehow I find myself looking at …

As stupid as this sounds, I never really understood the HA architecture. Guess I still don’t. :slight_smile:
Anyway, we do not want to do a “component”, we want to do a “platform”.

Using Wink as an example …
Starting with the switch …
Here is the code …
https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/switch/wink.py
There are not that many lines. Just enough to wire the switch components properties to the Wink API.
Then the heavy lifting is in the Wink API …

So, I first step is to create a API. Is the Almond+ API same as the other Securfi products or do we need to drill down into Almond+

I need to get to my day job. Thoughts?

Thanks, quick question. I am trying to set up the environment to test. Is there a URL example I can test with from a browser so see if I am connected easily? If so what would the device list look like?

<Almond_IP:7681/root/?“MobileInternalIndex”:“device_list_231234”,“CommandType”:“DeviceList”

The easiest would be to use a websocket client for the browser. Search for websocket client for firefox or chrome.

Here are the steps

  1. Get the websocket client and add it to your browser.
  2. Go to ws://10.10.10.254:7681/root/frank . Replace the IP with your Almond IP if that is different. Change frank to your password
  3. It should respond back with something.
  4. Now type this as a test

Request
{
“MobileInternalIndex”:“3424324234”,
“CommandType”:“DeviceList”
}

  1. This should give you a list of all your devices.

Had to add an extension to my chrome browser. I used https://chrome.google.com/webstore/detail/smart-websocket-client/omalebghpgejjiaoknljcfmglgbpocdp?hl=en

Was able to see the response. All that worked. Next step is a hello world python program. I have a mac at home and I am not a mac person. That step may take longer than it should seem. At least now, thanks to you, I can verify that the A+ is responding.

@kdvlr Do you what does the request look like to turn on/off say a switch?
Looks like I set set the name https://wiki.securifi.com/index.php/Websockets_Documentation

FWI, I asked the same question on the Securifi form … https://forum.securifi.com/index.php/topic,6101.0.html

Here’s a sample I use to dim my lights.

This turns it off.

 ws.send(str('{ "MobileInternalIndex":"dim_lights_hass", "CommandType":"UpdateDeviceIndex", "ID":"45" "Index":"1","Value":"0" }'))

This sets it to 40%

    ws.send(str('{ "MobileInternalIndex":"dim_lights_hass", "CommandType":"UpdateDeviceIndex", "ID":"45" "Index":"1","Value":"40" }'))

Let me know if that works.

Thanks. How did you connect the dots on that looking at the API?
I guess whatever key/value you include gets updated?
So Value is the key and 0 or 40 is the value.

Here is one of my binary switches

"9": {
      "Data": {
        "ID": "9",
        "Name": "Power Strip 1",
        "FriendlyDeviceType": "BinarySwitch",
        "Type": "1",
        "Location": "Default",
        "LastActiveEpoch": "1521894543",
        "Model": "ZFM-80",
        "Version": "4",
        "Manufacturer": "Remotec"
      },
      "DeviceValues": {
        "1": {
          "Name": "SWITCH BINARY",
          "Value": "false",
          "Type": "1"
        }
      }

So I would expect

{"MobileInternalIndex":"123", "CommandType":"UpdateDeviceIndex", "ID":"9","Index":"1", "Value":"true"}

To turn it on. Do you agree?

Here is my response

{
  "MobileInternalIndex": "123",
  "CommandType": "UpdateDeviceIndex",
  "Success": "true"
}

Edit: I just remembered seeing it maybe unplug. I will test this when I get home. Stand by.