Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for legacy Nexa Bridge (aka Bridge1) #15

Closed
biodland opened this issue Feb 11, 2023 · 60 comments
Closed

Support for legacy Nexa Bridge (aka Bridge1) #15

biodland opened this issue Feb 11, 2023 · 60 comments
Labels
1.6.x Non-X Bridge enhancement New feature or request help wanted Extra attention is needed investigation Needs investigation

Comments

@biodland
Copy link

Trying to add this to my Nexa bridge, but seems to not be working.
Getting invalid authentication.

Have probed the device with Postman and in Chrome and the API's are exposed.
Been looking briefly into code and seems like the issue lies in the basicauth part, as per documentation of Nexa API it states the requirement of digest auth.

https://nexa.se/docs/

general
For the local connection, the auth is a simple HTTP Digest Auth. Username and password is nexa. Always use the prefix /v1 before any API-call. For example, http://192.168.1.12/v1/nodes.

And doing a simple test in postman shows that using basicauth will not work, and changing to digestauth works.
If this is a difference between Nexa Bridge X and the older Nexa Bridge I'm not aware. Could not find a simple way to use digestauth in the same modules. And due to lack of python experience this gets overwhelming fast. :)

image
image
image

@andersevenrud
Copy link
Owner

Thanks for trying it out! You might actually be the first :)

If this is a difference between Nexa Bridge X and the older Nexa Bridge I'm not aware

This might be the case, because this integration works great on my bridge. I'm going to look into this today.

Would you mind sharing some data from the /v1/info endpoint ? It might have some personal stuff in there so make sure to remove that before pasting.l

@biodland
Copy link
Author

biodland commented Feb 11, 2023

{
    "systemType": "Bridge1",
    "builddate": "2020-02-04T12:50:18CET",
    "gitversion": "8a57926552033f755c83e3e9e97419edf3eaf6a7",
    "version": "1.6.7",
    "gwid": "4b0783",
    "sunrise": "08:26",
    "sunset": "17:20",
    "location": {
        "ip": "1.2.3.4",
        "lat": 1.0,
        "lon": 1.0,
        "manualOverride": true
    },
    "currentTime": "2023-02-11T12:57:33+0100",
    "name": "Nexa Bridge",
    "externalIp": "1.2.3.4",
    "remoteSupportPort": 0,
    "internalIp": "10.0.0.226",
    "zwaveRole": "Primary",
    "zwaveOnOtherNetwork": false,
    "ok433": true,
    "zwaveOK": true,
    "cloudOK": true,
    "cloudLatency": 36,
    "upgraded": false
}

@andersevenrud
Copy link
Owner

Ah. This integration was made for the "Bridge 2" aka "Bridge X".

I don't think the "Bridge 1" responds with the same data from the API, which seems to be the case by briefly looking at one of your screenshots.

Might be possible to add support though, but then we need to dig some more in order to make things compatible (and I don't have one of these).

@andersevenrud
Copy link
Owner

which seems to be the case by briefly looking at one of your screenshots.

Maybe you could share all the data from the nodes endpoint ? Also does it have /v1/energy ?

@andersevenrud andersevenrud changed the title Not able to add device - Invalid Authentication Support for legacy Nexa Bridge (aka Bridge1) Feb 11, 2023
@biodland
Copy link
Author

v1_energy.txt
v1_info.txt
v1_nodes.txt
v1_rooms.txt
v1_scenarios.txt

@biodland
Copy link
Author

Added the API end points, seems like most of the api endpoints listed on the nexa official site is available. What I could not find was an automations endpoint, not sure how implemented that is yet.

Since all the information on that page is swedish notes. :)

@andersevenrud
Copy link
Owner

Thanks!

I looked through and it seems that the node data is mostly compatible, however it does not contain the current value(s).

Maybe it's possible to get that from /v1/nodes/<node id>.

If so then I think I can make reading sensor data work for the legacy bridge in this integration 🤞

@biodland
Copy link
Author

biodland commented Feb 11, 2023

This is the result for Node Id it /1

{
    "includedSecurely": false,
    "id": 1,
    "type": "ZWave",
    "hideInApp": false,
    "ignoreInRoomAction": false,
    "broken": false,
    "locked": false,
    "name": "",
    "roomId": 1,
    "groupNode": 0,
    "prio": 0,
    "favorite": false,
    "capabilities": [],
    "zwaveInfo": {
        "basic": 2,
        "generic": 2,
        "specific": 1
    },
    "lastEvents": {},
    "failed": false
}

For id 1017

{
    "id": 1017,
    "type": "NexaSwitch",
    "hideInApp": false,
    "ignoreInRoomAction": false,
    "broken": false,
    "locked": false,
    "name": "Utelys terasse",
    "roomId": 1,
    "groupNode": 0,
    "prio": 0,
    "favorite": false,
    "capabilities": [
        "switchBinary"
    ],
    "lastEvents": {
        "switchBinary": {
            "value": false,
            "sourceNode": 1017,
            "fromWS": false,
            "time": "2023-02-11T08:28:00+0100",
            "name": "switchBinary"
        },
        "methodCall": {
            "cap": "switchBinary",
            "value": false,
            "targetNode": 1017,
            "targetRoomId": 0,
            "method": "setValue",
            "sourceNode": 1017,
            "fromWS": false,
            "time": "2023-02-03T20:49:42+0100",
            "name": "methodCall"
        }
    }
}

@andersevenrud
Copy link
Owner

Sweet! That's basically all that's needed to make this work.

I'm going to set up a dummy API to simulate a classic bridge and then update the integration.

If you want to I can drop some development builds into this issue for you to test when I have something worked out.

@biodland
Copy link
Author

Sounds good. :)

@andersevenrud
Copy link
Owner

I think I have something ready for testing now.

Added a "legacy bridge" checkbox in the configuration box that changes the behaviour of this integration slightly to work with your device.

nexa_bridge_x.zip

@andersevenrud
Copy link
Owner

andersevenrud commented Feb 11, 2023

I wonder if your device also broadcasts updates via a websocket. Currently I have it disabled because I was unsure.

Would you be able to run https://github.com/vi/websocata and connect to the socket at ws://<bridge-ip>:8887 to see if you get any connection and data when one of your connected devices updates (like pressing a switch).

If this is the same as on Bridge2 I can simply just re-enable.

@andersevenrud andersevenrud added enhancement New feature or request help wanted Extra attention is needed investigation Needs investigation labels Feb 11, 2023
@biodland
Copy link
Author

Did a test with an websocket test app on the google play store. And got some good news. :) if it is implemented same as Bridge2 i dont know.

Screenshot_20230211_192133

@andersevenrud
Copy link
Owner

Fett! This looks promising.

Could you paste in the full text here ? I need to see the entire message(s).

@biodland
Copy link
Author

power:{"scale":2,"meterType":"Electric","value":0.0,"electricScale":"W","sourceNode":2,"fromWS":false,"time":"2023-02-11T19:21:24+0100","name":"power"}

This was the complete message when i tutned off my light.

@andersevenrud
Copy link
Owner

Hm. This doesn't look like a message from the actual switch, but some kind of power metering.

The bridge can spit out quite a few messages in a row (my assumption is that metering gets triggered when a switch state is modified and the "power" comes right after the value we want), and I don't know if your app is capable of capturing that 🤔

@biodland
Copy link
Author

Might be correct. Will check on the computer soon.

@andersevenrud
Copy link
Owner

In hindsight, I think that the message you gave was enough to work with. So I've created a new release that's ready for testing:

nexa_bridge_x.zip

@andersevenrud
Copy link
Owner

was enough to work with

Would still love to see some though 😊

@biodland
Copy link
Author

image

@andersevenrud
Copy link
Owner

Looks like my changes should take care of the differences in your data :)

@biodland
Copy link
Author

biodland commented Feb 11, 2023

2023-02-11 22:52:26.421 WARNING (MainThread) [homeassistant.config_entries] Config entry 'Nexa Bridge' for nexa_bridge_x integration not ready yet: 'prevValue'; Retrying in background
2023-02-11 22:52:33.748 ERROR (MainThread) [custom_components.nexa_bridge_x.nexa] Unexpected error fetching Nexa Bridge X Coordinator data: 'prevValue'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 239, in _async_refresh
    self.data = await self._async_update_data()
  File "/config/custom_components/nexa_bridge_x/nexa.py", line 624, in _async_update_data
    list(map(lambda n: NexaNode(n, self.legacy), nodes)),
  File "/config/custom_components/nexa_bridge_x/nexa.py", line 624, in <lambda>
    list(map(lambda n: NexaNode(n, self.legacy), nodes)),
  File "/config/custom_components/nexa_bridge_x/nexa.py", line 456, in __init__
    legacy and data["value"] or data["prevValue"],
KeyError: 'prevValue'

@biodland
Copy link
Author

Trying to add the comment as code, but it does remove linebreaks. Dont understand what I'm doing wrong x)

@andersevenrud
Copy link
Owner

That was a silly mistake on my end... Fixed here hopefully:

nexa_bridge_x.zip

Trying to add the comment as code, but it does remove linebreaks. Dont understand what I'm doing wrong x)

You need three of those tickmarks and a newline, then end with a newline and three ticks :) I think you can click on edit on your last comment (that I edited) to see.

@andersevenrud
Copy link
Owner

Really appreciate it :)

I was doing some reverse-engineering by using the Web UI that's accessible on the Bridge to when you access the IP directly. Maybe that's possible on the Bridge1 as well ? It had basic features for controls.

Dimmer Z-Wave device is also added as a light sensor

This is actually intentional. I wonder if I should add a config option for it. I just found it handy to have a sensor in addition to a control.

No way to control the dim %

That's def not intentional. I have a couple of dimmers at home, and they only appear as a light because they don't have the "binary" capability, only "level" (i.e.: 0-100%). Theoretically that should not have any issues, but I'm going to do some investigation on my end.

@andersevenrud
Copy link
Owner

Theoretically that should not have any issues, but I'm going to do some investigation on my end.

Tested by forcing my dimmers to become switches as well, and I got both 🤔

Is it somewhere in the "Entities" tab disguised as something else perhaps ?

@biodland
Copy link
Author

I exported the postman collection.

NexaBridge.postman_collection.zip

I see how it was now, it added the "lights" under an other group. Which only was acceptable under the right page to show. Still new to this.
image

@andersevenrud
Copy link
Owner

I see how it was now, it added the "lights" under an other group. Which only was acceptable under the right page to show. Still new to this.

Ah, I see. It took me a while to get to grips with this as well :)

@andersevenrud
Copy link
Owner

Also, I see now that I should disable the power meter stuff so that "Nexa Bridge" card doesn't just display garbage. I tried infer the stuff from the logs you shared, but obviously I missed something there :)

@andersevenrud
Copy link
Owner

Here's without that stuff. NB: Might have to remove the entities manually now that they have data on them (and might just show unavailable from now on).

nexa_bridge_x.zip

Looking forward to what you find out with the controls 😁

@andersevenrud
Copy link
Owner

Actually, I maybe think what's needed here.

The node_call method on line 344 (nexa.py) sends the command with "capability". I suspect this might need to be "name" because this has been the case elsewhere. Unless the actual endpoint does not actually exists that is.

@andersevenrud
Copy link
Owner

andersevenrud commented Feb 12, 2023

Meanwhile I've been trying to find some information about this on the web, but there's basically zero. Even for the X bridge (which is why I even started writing a document about all of this).

I'm kind of bummed about that, but figure the solution for this gotta be simple considering how similar the APIs are.

I suspect this might need to be "name" because this has been the case elsewhere

Or maybe even "cap" which is used some places in the new API. It's very inconsistent.

One thing I noticed is that methodCall thing that's on your nodes, which is not on Bridge2. That has the cap on it.

Really hope it's that simple. Or even that the endpoint is called methodCall instead of call, or a combination of all of this 😅

. I was doing some reverse-engineering by using the Web UI that's accessible on the Bridge to when you access the IP directly. Maybe that's possible on the Bridge1 as well ? It had basic features for controls.

Is this available on your device btw ? If so you can open the browser dev tools to capture network calls to easily see how it's done. If you don't know how to work with this tool I can help out (on discord or something like that even),

@biodland
Copy link
Author

Sorry for the late reply. A session in Discord or similar would probably be great at some time.

Opening up the web page locally and clicking the actions. It uses the call endpoint (which is also mentioned in the API doc from Nexa).

/v1/nodes/[nodeId]/call

With the payload of what capability to set value to.

{"cap":"switchBinary","method":"turnOn"} for a switch

Funny story tho, dimming units does not appear to work from the web interface. The button on WebUI does nothing at all. Power On and off does work and calls the above.

dimming switch has the following body for setting dimming level.

{"cap": "switchLevel","value": 0.6}

@andersevenrud
Copy link
Owner

With the payload of what capability to set value to.

Ah, so there's some kind of special case for buttons here in the old API. That's so weird.

Funny story tho, dimming units does not appear to work from the web interface. The button on WebUI does nothing at all. Power On and off does work and calls the above.

Hm. Does this work from the Nexa app ?

@biodland
Copy link
Author

Yes. It works from the app. And it works if I use postman with the payload mentioned aboved with "cap" set to switchLevel and with a value between 0 and 1 (0-100%) :)

@biodland
Copy link
Author

Just a side note, it also works from Google Home (I have tried to use Google Home) as well, but due to the high delay I want to use something not cloud based, therefor HA

@andersevenrud
Copy link
Owner

Yes. It works from the app. And it works if I use postman with the payload mentioned aboved with "cap" set to switchLevel and with a value between 0 and 1 (0-100%) :)

So only not from the web UI. Now that's a fun one :D Hopefully this means that it works from HA.

Well, then I think there's only one thing left to fix on my end and I can make a proper release. I'll fix that right after I finish work :)

@biodland
Copy link
Author

Perfect! Will hopefully be available to do a test in the evening if you get a RC ready.

@andersevenrud
Copy link
Owner

Here's a release with the methodCall stuff implemented:

nexa_bridge_x.zip

@biodland
Copy link
Author

Retrying setup: 'NexaEnergy' object has no attribute 'populate_legac'

Seems like something not working. Tried to just change it to populate_legacy and got a different error then.

2023-02-13 17:00:21.880 ERROR (MainThread) [custom_components.nexa_bridge_x.nexa] Unexpected error fetching Nexa Bridge X Coordinator data: name 'current' is not defined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 239, in _async_refresh
    self.data = await self._async_update_data()
  File "/config/custom_components/nexa_bridge_x/nexa.py", line 630, in _async_update_data
    NexaEnergy(energy, energy_nodes, self.legacy)
  File "/config/custom_components/nexa_bridge_x/nexa.py", line 422, in __init__
    self.populate_legac(data)
  File "/config/custom_components/nexa_bridge_x/nexa.py", line 431, in populate_legacy
    self.total_kilowatt_hours = current["kWh"]
NameError: name 'current' is not defined

@andersevenrud
Copy link
Owner

Oh.... looks like I forgot to commit something on my home computer yesterday. I'm on the go 😅

This should fix that:

nexa_bridge_x.zip

@biodland
Copy link
Author

Well. It is working, not 100% reliable. Some calls not going through, and with a high latency. Will try to dig into this further once I get home. Sitting at work and remoting to home computer.

@andersevenrud
Copy link
Owner

Might be worth looking into increasing the poll interval defined in the const file if it's a case of too many open connections on the bridge / congestion.

I'm contemplating increasing it in general because theoretically the websocket should broadcast all of the required updates.

@andersevenrud
Copy link
Owner

andersevenrud commented Feb 13, 2023

I'm just wondering about one thing (relating to the methodCall differences)... do the Nexa and Zwave switches behave the same ? I see you have both. Do the switches on/off use the turnOn/turnOff in both cases in the Web UI ?

@andersevenrud
Copy link
Owner

andersevenrud commented Feb 13, 2023

I'm just wondering about one thing (relating to the methodCall differences)

Ignore this. It actually works on Bridge2 as well (backward compatible) :)

@biodland
Copy link
Author

biodland commented Feb 13, 2023

Nexa dimmer and Z-wave dimmer works the same in HA. Works on first try, but trying to do successive changes makes the device go unavailable before coming back to life.

Could perhaps give you some access, can be found on discord

@andersevenrud
Copy link
Owner

After inspecting Mr @biodland's instance I've come to the following conclusion:

  • Bridge1 seems to sometimes get unresponsive. Nothing I can do about that, really.
  • The default request timeout is 5 seconds. This is not enough in some scenarios
  • I've implemented things as they should be generally

And at the same time:

  • I can increase the polling timers because the websocket should cover frequent updates in real-time.

@andersevenrud
Copy link
Owner

All of this has now been released: https://github.com/andersevenrud/ha-nexa-bridge-x/releases/tag/v1.1.0

Thank you so much for your time digging into this!

Integration for the Bridge1 is pretty much complete with exception of this: #19 🎉

If you experience some issues following this release, feel free to open a new issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.6.x Non-X Bridge enhancement New feature or request help wanted Extra attention is needed investigation Needs investigation
Projects
None yet
Development

No branches or pull requests

2 participants