-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
[iaqualink] Add Support for AWS MQTT based IAqualink devices, such as Zodiac Hydroxinator #17671
base: main
Are you sure you want to change the base?
Conversation
f91ecad
to
f112a3f
Compare
</properties> | ||
<dependencies> | ||
<dependency> | ||
<groupId>software.amazon.awssdk.iotdevicesdk</groupId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe you can join @clinique to get rid of this SDK. For details see: #16893 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did actually have a look at using an alternative MQTT client, because it was originally such as pita to get the CRT working. The challenges that I had were:
- Should support MQTTv5
- Should work over Websockets
- Should support AWS Signature V4 authentication
I'm sure that it's possible, but I doubt that it's simple. I would also question the longevity and applicability of what we were to build, given that AWS appear happy to build their own custom clients and protocol. We'd need to maintain a parallel pure-Java implementation.
I am sympathetic to the arguments regarding packaging the CRT, however given that AWS have such a strong position in IOT I would expect many bindings to have to interface with AWS, and hence wonder if a better solution would be to create a CRT OSGi for all bindings to use (instead of package themselves)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alternative client to use would be the Paho MQTT client. It does look like it supports MQTTv5 over websockets, although not everything that AWS requires, for example: eclipse-paho/paho.mqtt.java#830, eclipse-paho/paho.mqtt.java#858 etc.
It should be coming, but it's not there yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I searched a long time but found no alternative to get logged in with HiveMQ. There are very rare informations available when you try to escape AWS SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PAHO client seems abandoned. So there does not seem to be an alternative. I'm no expert in OSGI packages and if it would be usefull to add this SDK as OSGI package. Maybe @wborn can give some guidance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding support for forward slashes to the hivemq client would probably be best, but i can't asses how much work that or even if that is possible at all. Maybe create an issue for the specific hivemq here: https://github.com/hivemq/hivemq-mqtt-client
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can get all the tokens, the problem I have is constructing the signed URL to connect to the broker (over wss). This is for a sigV4 URL, you may be using another approach like mtls etc?
It's a customAuthorizer :
MqttClientConnection connection = AwsIotMqttConnectionBuilder.newDefaultBuilder()
.withClientId("WX/USER/%s/%s/%s".formatted(userId, MQTT_USERNAME, productUuid))
.withEndpoint(endpoint).withUsername(MQTT_USERNAME).withCleanSession(false).withKeepAliveSecs(300)
.withConnectionEventCallbacks(this).withWebsockets(true)
.withWebsocketHandshakeTransform(handshakeArgs -> {
HttpRequest httpRequest = handshakeArgs.getHttpRequest();
httpRequest.addHeader("x-amz-customauthorizer-name", AUTHORIZER_NAME);
httpRequest.addHeader("x-amz-customauthorizer-signature", tok[2]);
httpRequest.addHeader("jwt", tok[0] + "." + tok[1]);
handshakeArgs.complete(httpRequest);
}).build();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@clinique That is certainly different to my case; I do not have all those fields (such as a username).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lsiepel I've spent a little more time on this and my conclusion is that we have a few choices:
- Ship the AWS SDK in the bundle. Possibly it can be shaved down a bit when shading, although given that much of it is JNI I'm not expecting much.
- Ship the AWS SDK as a shared bundle.
- Go with Hive: this means that we'd need to get a change into Hive, which unfortunately is down to an issue with the JDK URLEncoder, which doesn't escape forward slashes (or + signs). No chance of getting this changed there, and I'm afraid that Hive may be reluctant to deviate from it's behaviour. Seems some people say that escaping isn't required and others (e.g. Amazon) say that it is. The problem arises due to the signature calculation which is based on the URI. Whilst Hive allows you to pass a String, it puts in into a URI object (then gets it back out), which means that you cannot provide a raw querystring. Pre-encoded query string is decoded hivemq/hivemq-mqtt-client#643
- Go with Paho: Whilst I have it working, it comes with 2 caveats: 1. It relies on a commit which whilst is about 4 years old, does not yet appear in an official release. 2. Paho seems somewhat abandoned, hence the first problem.
I also had a quick look to see if I could find any other suitable libraries. There is nothing in Java, the only thing close I found was https://github.com/davidepianca98/KMQTT/ which is Kotlin. Personally I'd love to see Kotlin shipped with openHAB, however that's another very heavy bundle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like @wborn's advice regarding the SDK. wdyt about adding it as a OSGi bundle?
Thanks @jpg0 ! Nice to have someone else help out with this binding ! Question for you, is only a subset of iAqualink devices available via MQTT, or have they enabled this across all iAqualink products? The REST API the binding currently uses is kinda rough, was always hoping they would replace it with something a little more thought through. |
@digitaldan I don't know, but it wouldn't surprise me if it has enabled across all. I don't believe that the latest Android app supports the REST API (well, except for the initial connection, like this implementation), unlike if you visit the web app, which only supports the REST API. Do you have an iaqualink device to test with? If you use the new handler and point it to a new but different device then it should work, but not create any channels - however if you set logging to debug you'll get a dump of the JSON properties of the device, indicating that it is supported. |
Thanks, I will try and test that out this weekend with my aqualink controller and see if we can consolidate to a single Mqtt handler. |
Great! It should be fairly straightforward to add support for other channels, although I've implemented it in quite a different way to the V1 binding. Potential channels are defined via JsonPath expressions (in Channels.java) which are checked when the device JSON is retrieved. Seemed simpler (and more change-tolerant) than trying to map the JSON to POJOs. |
f112a3f
to
09b1483
Compare
09b1483
to
14037a4
Compare
Just added support for "boost_time" |
@digitaldan Did you ever have a chance to test this out? |
…oxinator Signed-off-by: Jonathan Gilbert <[email protected]>
14037a4
to
b5c0d21
Compare
Sorry, i have not yet, slipped my mind. I'll try and find some time this week to test it out. |
Hi @jpg0 I gave this a try, but am getting the following error. I'm guessing this may be b/c mqtt is not yet enabled for iaqualink controllers? (i replaced my ids with xxxxxx)
|
I'm confused as to where the |
Yeah, i created a new V2 thing, but that line was probably from the the other thing and was mixed in the logging, if i pause my original thing, and just run the new v2 one:
|
Hmm, not sure, but that may well be the case. Do you use the iaqualink mobile app? That works for me and I studied the traffic to determine what it was doing (aws mqtt in my case). Not sure if the mobile app can also fall back to rest/http though. |
How did you observe the network traffic? I tired MITMProxy, but it looks like they may be using certificate pinning, so i can't see the traffic from the app. |
I used mitmproxy, using the app in an emulator with proxy enabled and
mitmproxy certs installed. Seemed fine using the installed certs when I
tried it.
…On Sat, 28 Dec 2024, 10:05 am Dan Cunningham, ***@***.***> wrote:
How did you observe the network traffic? I tired MITMProxy, but it looks
like they may be using certificate pinning, so i can't see the traffic from
the app.
—
Reply to this email directly, view it on GitHub
<#17671 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAFNH5RPOWHVQWKQNNGCSWT2HXMK3AVCNFSM6AAAAABQ27AI6WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNRUGA4DCNBWGI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
was this the android app then ? I was trying on my iPhone. I'll try using the android version and see if that makes a difference. |
Yes, Android |
Initial login and device lookup happens over rest, then switches to an MQTTv5 client to interact with an AWS IOT Shadow Device service. Tested with Zodiac Hydroxinator only.
Due to being completely different to the existing implementation it is build as a distinct handler.
Note that this requires the AWS IOT SDK, which includes the AWS CRT native library. This appears to work fine, although only with a minimum of GLIBC 2.32. The openHAB Debian docker container packages Debian 11 which uses 2.31, so you must use Debian 12, which is currently already committed to 4.3.x anyway. (If you want to use on openHAB 4.2.x it works fine, even on docker, but requires a later Debian image, otherwise it crashes the JVM.)