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

Control functions have stopped responding to input #19

Open
Dazzzwaa opened this issue Feb 21, 2024 · 191 comments
Open

Control functions have stopped responding to input #19

Dazzzwaa opened this issue Feb 21, 2024 · 191 comments

Comments

@Dazzzwaa
Copy link

Dazzzwaa commented Feb 21, 2024

Hi,
last week i have noticed the integration has stopped responding to input the magiqtouch display wont update to the value i set in Home assistant, however if i set it on magiqtouch controll it will update on Home assistant
image
image

see below information from the log
This error originated from a custom integration.

Logger: magiqtouch
Source: custom_components/magiqtouch/magiqtouch.py:274
Integration: Seeley MagIQtouch (documentation, issues)
First occurred: 8:40:15 PM (3 occurrences)
Last logged: 8:51:34 PM

Failed to set value properly:

@DeltaTangoLima
Copy link

Came here to open an issue for the very same thing - identical experience, and log entry. Definitely happened in the past week or so.

@AlexPotterOnGit
Copy link

+1 with the same issue

@roelfdiedericks
Copy link

+1 same issue with the same error log

@jmot205
Copy link

jmot205 commented Feb 24, 2024

+1 same issue encountered here

@jmot205
Copy link

jmot205 commented Feb 24, 2024

For additional context I have tried deleting and re-adding the HA air con entity and also confirmed that the air con system is still able to be controlled remotely through the Seeley Magiqtouch app.

@andrewleech
Copy link
Owner

Oh that really sucks. I noticed my control widget wasn't working the other day and just assumed I probably needed to restart something... It looks like the magiqtouch app protocol must have actually changed a bit.

It's probably going to be quite a while before I can get to fixing this, I've only recently joined the "2 under 2" club and don't have much time for projects

@jmot205
Copy link

jmot205 commented Feb 24, 2024

Just sniffed the MagIQTouch app, and in addition to the host
tgjgb3bcf3.execute-api.ap-southeast-2.amazonaws.com
(which is in the ha_magiqtouch integration code) it is also hitting
xs5z2412cf.execute-api.ap-southeast-2.amazonaws.com

Could it potentially just be an updated API URL? Not sure why it'd still be hitting the previous one though.

The error message in this post makes it sound like it just can't hit the tgjgb3bcf3 endpoint.

@andrewleech
Copy link
Owner

Nice one @jmot205 . I've decompiled a copy of old and newest app, hopefully that'll give me a more direct answer as to what's going on... though I'm coding from phone with Acode app and SSH to my Linux box, so it's just little bits here and there :-)

@andrewleech
Copy link
Owner

andrewleech commented Feb 26, 2024

Actually it's bad news on the decompile. Previously the app code was written with dotnet & xamarin which is easy to decompile.

The brand new one has been rewritten from scratch, with that new url reported now locked inside a C / binary library which is much harder to inspect.

Oh, the new url is actually a websocket.
While I haven't decompiled the binary library, just listing strings from it is quite interesting.
wss://xs5z2412cf.execute-api.ap-southeast-2.amazo naws.com/prod
The app is now written with flutter and aws-amplify

    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "analytics": {
        "plugins": {
            "awsPinpointAnalyticsPlugin": {
                "pinpointAnalytics": {
                    "appId": "b9c0364dab934e9aa7708a0b03417db1",
                    "region": "ap-southeast-2"
                },
                "pinpointTargeting": {
                    "region": "ap-southeast-2"
                }
            }
        }
    },
    "auth": {
        "plugins": {
            "awsCognitoAuthPlugin": {
                "UserAgent": "aws-amplify-cli/0.1.0",
                "Version": "0.1.0",
                "IdentityManager": {
                    "Default": {}
                },
                "CredentialsProvider": {
                    "CognitoIdentity": {
                        "Default": {
                            "PoolId": "ap-southeast-2:87af6d7b-28ef-4014-88f1-67b19c361221",
                            "Region": "ap-southeast-2"
                        }
                    }
                },
                "CognitoUserPool": {
                    "Default": {
                        "PoolId": "ap-southeast-2_uw5VVNlib",
                        "AppClientId": "afh7fftbb0fg2rnagdbgd9b7b",
                        "Region": "ap-southeast-2"
                    }
                },
                "Auth": {
                    "Default": {
                        "authenticationFlowType": "USER_SRP_AUTH",
                        "socialProviders": [],
                        "usernameAttributes": [],
                        "signupAttributes": [
                            "NAME",
                            "FAMILY_NAME",
                            "EMAIL",
                            "PHONE_NUMBER"
                        ],
                        "passwordProtectionSettings": {
                            "passwordPolicyMinLength": 6,
                            "passwordPolicyCharacters": []
                        },
                        "mfaConfiguration": "OFF",
                        "mfaTypes": [],
                        "verificationMechanisms": [
                            "EMAIL"
                        ]
                    }
                },
                "PinpointAnalytics": {
                    "Default": {
                        "AppId": "b9c0364dab934e9aa7708a0b03417db1",
                        "Region": "ap-southeast-2"
                    }
                },
                "PinpointTargeting": {
                    "Default": {
                        "Region": "ap-southeast-2"
                    }
                }
            }
        }
    },
    "api": {
        "plugins": {
            "awsAPIPlugin": {
                "apiGateway": {
                    "endpointType": "REST",
                    "endpoint": "https://tgjgb3bcf3.execute-api.ap-southeast-2.amazonaws.com/prod",
                    "region": "ap-southeast-2",
                    "authorizationType": "NONE"
                }
            }
        }
    }

@andrewleech
Copy link
Owner

Ah, this integration is also still using ApiUrl = "https://57uh36mbv1.execute-api.ap-southeast-2.amazonaws.com/api/" for much of its functionality; this url appears to no longer exist! So it seems I'll need to find equivalent endpoints oh the newer web API to replace these

@jmot205
Copy link

jmot205 commented Feb 27, 2024

That's a frustrating outcome of them seemingly putting so much effort into re-writing their app - that it throws a spanner into the decompile process. Nice find on that printout - that's a lot of info.

Here's hoping that a drag-and-drop update of the ApiUrl is all it needs to come back to life.

@raym777
Copy link

raym777 commented Feb 28, 2024

Thanks for looking into this. I came here to report the issue but you guys are obviously all over it already :)

Hopefully not too difficult to get it back up and running.

@andrewleech
Copy link
Owner

andrewleech commented Feb 29, 2024

So I've been trying a lot of different things, working day and night ( coding from phone while rocking newborn to sleep :-D )

... and was starting to get quite pessimistic about ever getting it working again.

I tried just changing the old url to either of the new endpoints identifed previously, but they just throw an AWS authentication error. Stack overflow says that particular error means the url path is wrong / doesn't exist...

My initial attempts at decompiling went nowhere (as mentioned above) so I went back to trying to sniff the network traffic.

Turns out there's an awesome on-phone network analyser now called pcapdroid. It acts like a "fake vpn" to intercept traffic and show all the packets. It works great, can select just the magiqtouch app and it shows communications to that new endpoint.

These are all https (aka encrypted) however so don't show the full url path or the request contents. So not enough to figure out how to use it.

Luckily pcapdroid has an option to decrypt these, so I got all that set up and going, only to find the magiqtouch app no longer works, it can't communicate with the server and pcapdroid shows a common error being that the app is detecting / rejecting the proxy decode certificate.

One common workaround for this requires a rooted device. Thankfully I had an old phone in the cupboard that's got magisk root installed so I got that charged, installed everything and tried again with the root / system certificate stuff configured. Same failure :-(

Apparently when this fails it usually means the app itself is enforcing the certificate. 

So I tried a few tools & techniques to patch the app itself to disable this so called "cert pinning". Some methods made the app crash, some didn't. None of them let me decode the API calls unfortunately.

FWIW though one tool that's _very useful for unpacking, smali editing, rebuilding and signing apks is apk.sh

It was about here I was getting close to giving up.

Then I thought, if all the app communication is hidden inside a binary library, maybe I don't need to figure out how the API calls work, maybe I can just copy the binary library and figure out how to embed it into my package, then directly call the official apps' functions in it!

So I took another look at the binary library and quickly figured out this wouldn't work because it's not a normal linux-like shared library, it's a custom format "flutter app" thing.

And that started me down a path of figuring out what flutter is. Tldr it's a cross platform mobile app framework by Google that has its own programming language that compiles to a binary library. Hence all the app code is in a binary library. Unfortunately flutter apps are very hard to decompile, and it's only becoming harder in newer versions. And that cert pinning issue I ran into is standard practice in all flutter apps!

But thankfully flutter is popular enough that lots of people have figured out various ways to patch it / disable cert pinning in different versions of flutter as this kind of network inspection is crucial for a lot of security research.

I tried a couple of ways that crashed the app, before finally one that didn't crash.  And actually worked to disable cert pinning, so network inspection finally worked!

The tool used is reflutter.

It does require a separate inspection proxy that's listening on a different port than pcapdroid uses, so I've got a separate copy of mitmproxy running on my home computer.

After all that, I think a picture is worth a thousand words, so...
Screenshot_20240229-141409.png

PS. This doesn't mean I've fixed anything yet, but does mean I should be able to trace how the real app communicates with the server to copy it!

@DeltaTangoLima
Copy link

DeltaTangoLima commented Feb 29, 2024

@andrewleech I am in awe. I could barely write a Python hello world one-liner when our kid was newborn, let alone decompile an app and sniff its traffic with a MITM proxy.

Look - I'm an infrastructure guy, and totally a Python hack. Clearly you've done a lot of the heavy lifting already, and you seem like a guy that enjoys doing this stuff but, if I can help at all, please yell out mate.

@AlexPotterOnGit
Copy link

AlexPotterOnGit commented Feb 29, 2024

So I've been trying a lot of different things, working day and night ( coding from phone while rocking newborn to sleep :-D )

< snip >

PS. This doesn't mean I've fixed anything yet, but does mean I should be able to trace how the real app communicates with the server to copy it!

I was so enjoying just reading the story so even if we are not going to be lucky enough to get back control, not going to be disappointed. Thanks mate for your time and efforts.

@andrewleech
Copy link
Owner

@DeltaTangoLima Cheers yeah to be clear, this is my second son and he's healthy and doing well... so it's all coming a bit easier than with our first :-)

I find this kind of hacking around mentally invigorating, similar to exercise being physically energising. I also need something to keep me awake at times when holding bubs in the middle of the night, don't want to fall asleep and drop him!

@AlexPotterOnGit actually it's looking quite definite I'll be able to get it working! I've already replaced a couple of calls to the old / shut down API url. The new API url is definitely a websocket, I got communication with that started last night and have received "current state" over it just like the app does.

The app uses this websocket for both

  • getting current state updates without polling
  • Sending new settings

The format of the json data structures used for these is different to the old one though, so the dataclass structures here will need updating to suit.

I'm pretty sure my first round of fixes will break zone control because I don't have zones which in the new format seems to show as empty lists.... people with zones will have lists filled with "something new", we'll have to wait until someone with zones runs the new code (once it's written) to see what the format is.

@andrewleech
Copy link
Owner

andrewleech commented Feb 29, 2024

Oh wow, just found another use for chatgpt!
https://chat.openai.com/share/995ca6b7-6ac9-4fe8-8105-61c9039549b1

Neat, Gemini can do it too, question:

Can you write a python dataclass to match this json data: {"device":"606405ab6f38","timestamp":1709218416442,"online":true,"systemOn":false,"runningMode":"COOL","heaterFault":false,"coolerFault":false,"cooler":[{"brand":0,"name":"","runningState":"NOT_REQUIRED","zoneRunningState":"NOT_REQUIRED","zoneOn":null,"zoneType":"NONE","set_temp":18,"temperature_units":"c","actual_temp":22,"max_temp":28,"min_temp":18,"fan_speed":1,"max_fan_speed":10,"min_fan_speed":1,"control_mode":"FAN","control_mode_type":"MASTER","internal_temp":22,"external_temp":null,"programMode":"off","ProgramModeOverridden":false,"ProgramPeriodActive":false,"programOverrideDisabled":false}],"heater":[],"fan":{"cooler_available":true,"cooler_brand":0,"heater_available":false,"heater_brand":3,"heater_Fan_Speed":1,"cooler_Fan_Speed":1},"touchCount":206,"installed":{"evap":true,"faoc":false,"heater":false,"iaoc":false,"coolerType":0}}

Response:

Here's the Python dataclass that matches the provided JSON data:
from dataclasses import dataclass

@dataclass
class Cooler:
    brand: int
    name: str
    runningState: str
    zoneRunningState: str
    zoneOn: bool
    zoneType: str
    set_temp: float
    temperature_units: str
    actual_temp: float
    max_temp: float
    min_temp: float
    fan_speed: int
    max_fan_speed: int
    min_fan_speed: int
    control_mode: str
    control_mode_type: str
    internal_temp: float
    external_temp: float
    programMode: str
    ProgramModeOverridden: bool
    ProgramPeriodActive: bool
    programOverrideDisabled: bool

@dataclass
class Fan:
    cooler_available: bool
    cooler_brand: int
    heater_available: bool
    heater_brand: int
    heater_Fan_Speed: int
    cooler_Fan_Speed: int

@dataclass
class Installed:
    evap: bool
    faoc: bool
    heater: bool
    iaoc: bool
    coolerType: int

@dataclass
class DeviceData:
    device: str
    timestamp: int
    online: bool
    systemOn: bool
    runningMode: str
    heaterFault: bool
    coolerFault: bool
    cooler: list[Cooler]
    heater: list
    fan: Fan
    touchCount: int
    installed: Installed

This dataclass structure closely mirrors the JSON data, with each class representing a nested element and its corresponding attributes.

PS. This is the current state json that's reported over websocket

@DeltaTangoLima
Copy link

Oh wow, just found another use for chatgpt! https://chat.openai.com/share/995ca6b7-6ac9-4fe8-8105-61c9039549b1

Neat, Gemini can do it too, question:

Yep - done this a lot myself. genAI isn't going to kill development, for those devs that learn how to harness it properly. I use it to bootstrap about 80% of a new project, which means I can spend my time refining and tweaking the end product. Very useful!

@roelfdiedericks
Copy link

roelfdiedericks commented Mar 1, 2024

Considering the "strings" trail you found, I'm going to guess that they built the app with AWS Amplify, and more specifically the amplify_flutter library. https://pub.dev/publishers/aws-amplify.com/packages

https://aws-amplify.com

Authentication could pose a bit of a challenge, I suspect.

Edit: indeed, looks like they use Amazon Cognito, after some more strings-ing.

@andrewleech
Copy link
Owner

Authentication could pose a bit of a challenge, I suspect.

Heh, yeah the auth was a massive pain to get working when I started this integration a year or two ago, it took me ages to get the AWS cognitive auth library & dependences all going.

Thankfully, that all still works. I think one of the pool identifiers has changed, I copied that from the amplify json/string block.

I can login still just fine and use the API and websocket endpoints, the json used in the dataclass comment above was pulled by my code.

@roelfdiedericks
Copy link

Ah, ok, I didn't directly see that in the current integration.

Was about to start down this rabbithole....

image

@roelfdiedericks
Copy link

Clearly my reading skills lacked.

image

@roelfdiedericks
Copy link

I can login still just fine and use the API and websocket endpoints, the json used in the dataclass comment above was pulled by my code.

Pull your own PR already :)

@andrewleech
Copy link
Owner

It's taken a lot of re-writing, testing, then restructuring to try to get even basic communication working reliability over websocket and new API but the original support for evap cooling seems to be working well again for me now #21

I've just cleaned up and merged that to the main hacs branch so anyone should be able to upgrade to it if you have pre-release versions enabled in hacs.

This may work for heating but it's a guess so far.

This will not work for zones as my setup doesn't have any so the json doesn't include any details for this. I'll need to get json data dumped from someone's ha logs (with verbose logging enabled on this integration) to make any progress there.

@jmot205
Copy link

jmot205 commented Mar 11, 2024

Legend! Thanks for all that work - sorry to hear it was such a big chunk of effort. Hopefully they refrain from any more "useful" app re-writes in future...

I've updated to v3.0 and had no entities auto-detected so found I need to login to my account again. Unfortunately that doesn't work - I get a "failed to connect" error in the GUI, and the error log shows that it didn't resolve:

This error originated from a custom integration.

Logger: custom_components.magiqtouch.config_flow
Source: custom_components/magiqtouch/config_flow.py:42
integration: magiqtouch (documentation, issues)
First occurred: 10:37:47 (4 occurrences)
Last logged: 10:45:26

Could not connect: Cannot connect to host 57uh36mbv1.execute-api.ap-southeast-2.amazonaws.com:443 ssl:default [Name does not resolve] Traceback (most recent call last): File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1173, in _create_direct_connection hosts = await asyncio.shield(host_resolved) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 884, in _resolve_host addrs = await self._resolver.resolve(host, port, family=self._family) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/resolver.py", line 33, in resolve infos = await self._loop.getaddrinfo( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/base_events.py", line 899, in getaddrinfo return await self.run_in_executor( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 58, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/socket.py", line 963, in getaddrinfo for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socket.gaierror: [Errno -2] Name does not resolve The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/config/custom_components/magiqtouch/config_flow.py", line 37, in validate_input if not await hub.login(): ^^^^^^^^^^^^^^^^^ File "/config/custom_components/magiqtouch/magiqtouch.py", line 106, in login async with self._httpsession.get( File "/usr/local/lib/python3.12/site-packages/aiohttp/client.py", line 1194, in aenter self._resp = await self._coro ^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/client.py", line 578, in _request conn = await self._connector.connect( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 544, in connect proto = await self._create_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 911, in _create_connection _, proto = await self._create_direct_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1187, in _create_direct_connection raise ClientConnectorError(req.connection_key, exc) from exc aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host 57uh36mbv1.execute-api.ap-southeast-2.amazonaws.com:443 ssl:default [Name does not resolve]
Could not connect: Traceback (most recent call last): File "/config/custom_components/magiqtouch/config_flow.py", line 38, in validate_input raise InvalidAuth custom_components.magiqtouch.config_flow.InvalidAuth

@AlexPotterOnGit
Copy link

First of all - thank you for the efforts. And wanted to confirm I have the same issue:
Logger: homeassistant.setup
Source: setup.py:296
First occurred: 10:38:49 AM (1 occurrences)
Last logged: 10:38:49 AM

Setup failed for custom integration 'magiqtouch': Unable to import component: No module named 'mandate'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/setup.py", line 296, in _async_setup_component
component = await integration.async_get_component()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/loader.py", line 894, in async_get_component
comp = self.get_component()
^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/loader.py", line 921, in get_component
ComponentProtocol, importlib.import_module(self.pkg_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/importlib/init.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "", line 1387, in _gcd_import
File "", line 1360, in _find_and_load
File "", line 1331, in _find_and_load_unlocked
File "", line 935, in _load_unlocked
File "", line 995, in exec_module
File "", line 488, in _call_with_frames_removed
File "/config/custom_components/magiqtouch/init.py", line 15, in
from .magiqtouch import MagiQtouch_Driver
File "/config/custom_components/magiqtouch/magiqtouch.py", line 15, in
from mandate import Cognito
ModuleNotFoundError: No module named 'mandate'

@andrewleech
Copy link
Owner

andrewleech commented Mar 11, 2024

v3.0 is not the new work, that's the old version.

The new stuff just merged would need pre-release enabled I think to get installed.

Maybe the new stuff should be given a version number; it'd be good to know it works for someone else before I "formally" release it as such... though that really doesn't actually matter.

@jmot205
Copy link

jmot205 commented Mar 11, 2024

Ah sorry, thought that was the prerelease because I have beta enable and it just gives the options "v3.0" and "hacs". When selected, "hacs" just reverts to the 3.0 option.
Screenshot_20240311_112407_Home Assistant

@raym777
Copy link

raym777 commented Apr 24, 2024

and then, keep it selected on v4.0? ...

Try changing the selected version to hacs that's the development branch that has newer work on it.

Thanks for the reply.

Yeah I've tried that previously and just did it again ... the version updated ok in HACS:-
image

but... I've lost my climate controller entity. All I get is the internal temp sensor:-

image

I've tried removing the MagiqTouch integration in HA, re-adding it, restarting HA a couple of times as well but it never comes back.

There's this in the log which looks related:

image

@raym777
Copy link

raym777 commented Apr 25, 2024

Hi @andrewleech - I just updated again today to 8b00eb3 and the above problem is now resolved. My climate entity has returned! Whether intentional or not, many thanks and thank you for your continued effort on this integration. It's really appreciated.

@andrewleech
Copy link
Owner

Great, yeah I pushed a fix to the most recent issue last night but wanted to test one thing before posting about it here.

@TheOriginalMrWolf i think your latest exception should be fixed with this too.

@AschwinGehlen
Copy link

@andrewleech, looks like you have cracked it!

Just did a quick test and can now control both zones independently, set zones temps, turn zones on and off, turn master off (turns all zones off).

Can also now set the unit to Fan mode and adjust fan speed.

It is now working FAR better than the Seeley app.

Only one problem that I can see now is that the log file has gone crazy. Not sure if this is an issue but I have attached the logs from my testing so you can see if there are any issues. :) First one was me adjusting temperatures etc. The second one is me just starting the logs for a few seconds and stopping the logs so no changes.

Let me know if you want me to do some more testing.

home-assistant_magiqtouch_2024-04-25T03-34-33.668Z.log

home-assistant_magiqtouch_2024-04-25T03-32-06.778Z.log

@DuL90
Copy link

DuL90 commented Apr 26, 2024

@andrewleech looks like some good progress with the zones! I did some testing last night and found that the room zones are working as you would expect. They do however show up as either "off" or "auto", I would have thought they would show "off" or "heat"?? The thermostat control for all zones including the Common Zone all work as expected.

While the individual room zones are working the "Common Zone" is not functioning as it was previously. You can turn the heater on but this is not reflected in the state of the Common Zone entity as it says its off (when in reality its on), the "Preset" shows "None" and the "Fan Mode" shows 1. Using the Common Zone entity you cannot turn off the heater at all (the state is already off). You can turn on and off individual zones but if you have only one zone running and turn it off it will also turn off Common Zone. It should leave the Common Zone on. If you have more than one zone running and turn it off it turns just that zone off.

I've grabbed some further logs which hopefully may help. home-assistant_2024-04-26T03-56-36.597Z.log

Definately feels like you're getting close! Let me know if you need anything alse.

@andrewleech
Copy link
Owner

Thanks @AschwinGehlen and @DuL90 that's some helpful details. Curious that your common/master entity behaviours is different, I'll look at why that might be.

Shame about the reported mode being auto, my intention is for the button to be "auto" because there's no way to have a button just be "on". I thought it would have been working to report "on (heating)" etcetera as the current state though.

Maybe I should just add heat and cool mode buttons (as supported by the system) and use either of them as "zone on". Could even let any entity change the overall system mode, not sure if that would be more or less confusing.

@AschwinGehlen
Copy link

@andrewleech, having auto and off option works perfectly for my setup but I don’t have a hvac unit.

I would have thought having auto is how the system would normally run, that way the heater would cool or heat automatically.

Maybe we need Heat, Fan, hvac and off options?

Good thing with the way it is setup at the moment is I can now have the heater “on” but the zones are off. This means the heater will still report the current room temperature. If I turn the master off (heater fully off) then the heater no longer report the room temperature. I think the Seeley app also works like this.

There are two warnings in the logs that keep coming up:

Logger: magiqtouch
Source: custom_components/magiqtouch/magiqtouch.py:391
integration: Seeley MagIQtouch (documentation, issues)
First occurred: 1:07:39 PM (311 occurrences)
Last logged: 6:24:23 PM

And

Logger: magiqtouch
Source: custom_components/magiqtouch/climate.py:164
integration: Seeley MagIQtouch (documentation, issues)
First occurred: 1:07:39 PM (7184 occurrences)
Last logged: 6:24:23 PM

Let me know if you need more logs.

@andrewleech
Copy link
Owner

andrewleech commented May 4, 2024

New update pushed... I've removed the auto button on zone controls (I think) :-)
I did some tests and it looks like I should be able to change which buttons are available on-the-fly so now the zone controls should just have "off" and a single button that matches the master zone mode. Hopefully that works out well and helps make it clear what mode the system is currently in.

@AschwinGehlen one of those recurring messages is because the "verbose" configuration setting is enabled. The other was a development diagnostic message I still had in the code. I've now gone through and removed all the *extra" diag log messages I hopefully won't need anymore.

@AschwinGehlen
Copy link

@andrewleech awesome! I’ll download it tomorrow morning and have a play. Getting a bit late for me, need my beauty sleep. 🤣

@AshieSlashy
Copy link

Well done @andrewleech - you've done it - I can at last actually properly interact with my system... thank you!!

Only a couple of minor things that I've spotted so far -

  • When in fan-only mode, I can successfully set the fan speed but the 'master' unit fan mode reverts to 'temperature' (even though the fan is running at the selected speed). Error seen in log (repeating every minute):
homeassistant  | 2024-05-04 21:29:25.501 ERROR (MainThread) [magiqtouch] process_new_state failed
homeassistant  | Traceback (most recent call last):
homeassistant  |   File "/config/custom_components/magiqtouch/magiqtouch.py", line 288, in ws_handler
homeassistant  |     self.process_new_state(status)
homeassistant  |   File "/config/custom_components/magiqtouch/magiqtouch.py", line 388, in process_new_state
homeassistant  |     self.current_state.update(new_state)
homeassistant  |   File "/config/custom_components/magiqtouch/structures.py", line 455, in update
homeassistant  |     cu = current[i]
homeassistant  |          ~~~~~~~^^^
homeassistant  | IndexError: list index out of range

State (which shows the current fan speed of 3) at this point is:

homeassistant  | 2024-05-04 21:29:33.333 WARNING (MainThread) [magiqtouch] Current State: {"device": "90e202cadd0c", "timestamp": 1714822173247, "online": true, "systemOn": true, "runningMode": "HEATER_FAN", "heaterFault": false, "coolerFault": false, "cooler": [{"brand": 3, "name": "Family Room", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 20, "temperature_units": "c", "actual_temp": 20, "max_temp": 28, "min_temp": 19, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": null, "control_mode_type": "NONE", "internal_temp": 20, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": false}, {"brand": 3, "name": "Lounge / Dining", "runningState": "NOT_REQUIRED", "zoneRunningState": "NOT_REQUIRED", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 21, "temperature_units": "c", "actual_temp": 20, "max_temp": 28, "min_temp": 19, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": null, "control_mode_type": "NONE", "internal_temp": 20, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": false}, {"brand": 3, "name": "Master Bedroom", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 21, "temperature_units": "c", "actual_temp": 22, "max_temp": 28, "min_temp": 19, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": null, "control_mode_type": "NONE", "internal_temp": 22, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": false}, {"brand": 3, "name": "Spare Room", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 20, "temperature_units": "c", "actual_temp": 20, "max_temp": 28, "min_temp": 19, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": null, "control_mode_type": "NONE", "internal_temp": 20, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": false}, {"brand": 3, "name": "Mishy Bedroom", "runningState": "NOT_REQUIRED", "zoneRunningState": "NOT_REQUIRED", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 20, "temperature_units": "c", "actual_temp": 19, "max_temp": 28, "min_temp": 19, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": null, "control_mode_type": "NONE", "internal_temp": 19, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": false}], "heater": [{"brand": 3, "name": "Family Room", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 20, "temperature_units": "c", "actual_temp": 20, "max_temp": 23, "min_temp": 0, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": "TEMP", "control_mode_type": "NONE", "internal_temp": 20, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": true}, {"brand": 3, "name": "Lounge / Dining", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 21, "temperature_units": "c", "actual_temp": 20, "max_temp": 23, "min_temp": 0, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": "TEMP", "control_mode_type": "NONE", "internal_temp": 20, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": true}, {"brand": 3, "name": "Master Bedroom", "runningState": "NOT_REQUIRED", "zoneRunningState": "NOT_REQUIRED", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 21, "temperature_units": "c", "actual_temp": 22, "max_temp": 23, "min_temp": 0, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": "TEMP", "control_mode_type": "NONE", "internal_temp": 22, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": true}, {"brand": 3, "name": "Spare Room", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 20, "temperature_units": "c", "actual_temp": 20, "max_temp": 23, "min_temp": 0, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": "TEMP", "control_mode_type": "NONE", "internal_temp": 20, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": true}, {"brand": 3, "name": "Mishy Bedroom", "runningState": "REQUIRED_NOT_RUNNING", "zoneRunningState": "REQUIRED_NOT_RUNNING", "zoneOn": true, "zoneType": "INDIVIDUAL", "set_temp": 20, "temperature_units": "c", "actual_temp": 19, "max_temp": 23, "min_temp": 0, "fan_speed": 3, "max_fan_speed": 10, "min_fan_speed": 1, "control_mode": "TEMP", "control_mode_type": "NONE", "internal_temp": 19, "external_temp": null, "programMode": "off", "ProgramModeOverridden": false, "ProgramPeriodActive": false, "programOverrideDisabled": true}], "fan": {"cooler_available": false, "cooler_brand": 3, "heater_available": true, "heater_brand": 3, "heater_Fan_Speed": 3, "cooler_Fan_Speed": 3}, "touchCount": 187, "installed": {"evap": false, "faoc": false, "heater": true, "iaoc": true, "coolerType": 2}}
  • When in heating/cooling mode, the 'master' unit still shows fan speed options in fan mode, even though fan speed is not settable in heating/cooling (ie: if possible fan mode should only show temperature when heating/cooling... is that possible?).
  • MagiQtouch entities include one additional Internal Temperature sensor per 'master' unit and zones. This is super useful, except name and ID are generic (eg sensor.magiqtouch_internal_temperature_1). Is it possible, similar to the thermostat entities, to name and ID the sensors according to their MagiQtouch names?
  • And, finally for tonight, when the system is off, the individual thermostats allow the user to select the fan mode which then turns the system on again with the fan running at low speed. This isn't great as it affects all zones (in fan mode all dampers open and all zones receive air)

To be honest, these are only minor/trivial issues so I could well live with it as it is, however if you are possibly looking for things to do then these items would be great for you to look at! 😁

@AschwinGehlen
Copy link

AschwinGehlen commented May 4, 2024

@andrewleech did some testing this morning and everything is working perfectly with my system. No popup errors anymore when changing the temperature settings etc. Fan mode works, turning the zones off and on works perfectly.

Here are the latest logs, as you can see there are still a few errors that keep popping up in the logs but FAR less than what we had before.

For testing I enabled Debug Logging then reloaded the integration, then changed settings in the master entity followed by changing the zone settings.

home-assistant_magiqtouch_2024-05-04T22-32-49.198Z.log

@DuL90
Copy link

DuL90 commented May 5, 2024

@andrewleech Thanks for the update. I did a little testing last night and again this morning and found a few issues and odd behaviour. The entity for the Common Zone mostly works like previously described but it still does not turn off the heater. It also does not turn off the Cooler or the Fan if running in those modes. If you select Heat (or Cool or Fan) from the Common Zone entity the system will come on but the entity changes status to off after a few seconds (even thought the system is on). If other room zones are on the heater will completely turn off when the last room zone is switched off, the Common Zone should remain on but doesn't. I noticed the first internal temperature sensor is unavailable but all the other integration entities are available, including other temperature entities.

The individual room zones are now only showing "Off" or "Heat", whereas the Common Zone shows these as well as "Cool" and "Fan Only". This is perfect but it seems a different experience to the last point @AshieSlashy made above.

I noticed this week (and also occurs with this release) is if I put the system in "Program" mode (to run the timers) the individual room zone entities become unavailble along with the corresponding temperature entities. The Common Zone remains functional and now the first temperature entity comes back to life. Apart from the temperature entities this isn't really a problem, I just found this a little odd.

There seems to be a number of errors in the logs which I've attached: home-assistant_2024-05-04T23-39-53.390Z.log While grabbing the logs I also put it in "Program" mode in case that shows you anything interesting.

Hope that all makes sense.

@andrewleech
Copy link
Owner

Thanks for the detailed feedback everyone, that really helps

There's certainly still some gremlins; it actually doesn't quite work properly for me either. There's a common thread of settings going through, but then the UI reverting to old / previous setting. I've seen things like that with setting/changing fan mode myself lately.

I've never used Program mode myself, so don't know how it interacts with the remote interface at all. I do see an unexpected error reported in the logs that's possibly related, not sure how to fix it though.

The issues with temperature sensors is interesting too - the names of them should be easy to fix, not sure what would be causing missing entities though.

@AschwinGehlen
Copy link

@andrewleech funny thing is that it seems to be working perfectly on my system. So much so that it is FAR better than the Seeley app. Responds faster and actually connects to the system. 😁

@DuL90
Copy link

DuL90 commented May 11, 2024

@andrewleech The behaviour when in Program mode really isn't a problem as far as I'm concerned, I only mentioned it in case it was of some help. I'm using Program mode for the first time this year to manage timers for the heater but given there are only 4 time slots its not particularly helpful. Ideally I'll go back to using HA to schedule the heater so it really doesn't matter to me how the integration handles that mode (including the temp entities). Thanks again for all your efforts!

@raym777
Copy link

raym777 commented Jun 1, 2024

@andrewleech Just thought I post to say I've had great success for the past few weeks on the latest version. I use HA exclusively now to control my heating and it's working very reliably.

The only minor thing I've found is occasionally, the native HA thermostat dashboard card doesn't reflect state changes, or more accurately, takes a long time to update. For example, I have an automation which turns the thermostat off at night via service call and sometimes, the UI doesn't reflect the change despite the wall controller successfully being in the off position. After several minutes, it will eventually update but on at least one occasion, it did not and I had to switch the UI to "off" manually to get it back in sync.

Not a big deal but thought I'd mention it in case anyone else may be experiencing the same thing.

Thanks again for all your hard work!

@cat2devnull
Copy link

I've just fired this up again. Upgraded to 6bfa853.
It correctly shows temps, fan speed but the mode is always showing as off.
I can change the temp and the system updates correctly but not the mode.
If I try to change the mode it flips back off after a couple of seconds without any change on the actual unit.
home-assistant_magiqtouch_2024-06-01T05-53-15.106Z.log

@epetousis
Copy link
Contributor

@cat2devnull does the mode change send correctly if you try again/a few times? I also experienced the same as what you describe, but I was at least able to get the mode to change after a second attempt.

@cat2devnull
Copy link

does the mode change send correctly if you try again/a few times? I also experienced the same as what you describe, but I was at least able to get the mode to change after a second attempt.

@epetousis So you seem to be right. I can turn it on after a few attempts. Not sure on the reliability but it's low. The problem still remains that the HA interface always shows as off, even if the aircon is actually on. So although I can turn it on after a few attempts, I cannot then turn if off because HA thinks it's off.
So close and yet so far. :)

@andrewleech
Copy link
Owner

@cat2devnull it looks like the zone handling is getting confused by your system, I'll have to find some time to try manually feeding the state data from your logs through the code to see what's going wrong.

@cat2devnull
Copy link

@andrewleech Thanks for taking the time to look...

@andrewleech
Copy link
Owner

... and yes I can confirm that sometimes / often this HA module is failing to show settings that are changed from the control panel directly. I just had this myself, when I turned on my unit manually but HA still shows it off.
I can see in my HA logs that it's failing to get updates from magiqtouch. I'm doing something wrong with the websocket I think - it's supposed to push updates through to me, but isn't.

For context though I've only got evap air-conditioner and it's winter here, so it's very rare for me to have an opportunity to turn my unit on to test / work on any of this stuff. Hence development has become quite slow!

@TheOriginalMrWolf
Copy link

Is there anything I could do to help @andrewleech ?

@andrewleech
Copy link
Owner

Is there anything I could do to help?

Not sure. I got my patched copy of the official all running to get some more logs of its data, though it's not completely clear yet from that either.

I thought the websocket was being used to keep a connection to the server open so that manual changes made at the control panel could be pushed directly to remote clients like this. But the app looks like it opens new websockets regularly and just get a few quick messages though - maybe it's only really of benefit when a change is made and you're waiting for it to propagate to the unit.

I might have to update the code to essentially poll for remote charges once a minute or something by starting new websockets each time.

@AschwinGehlen
Copy link

@andrewleech the latest version is still working fine on my setup. Occasionally I make a change to the temperature and a few seconds later it reverts back to its previous state but the office app on the phone does the same.

As far as I am concerned it works better than the app so well done on all your work on this.

Can you upload the known working version bb8f4da as a non hacs version and upload it as version 4.1 or version 5? HACS constantly states that there is a version update to version 4 but v4 doesn’t work. 😁

Also let me know if you need more logs from my setup or even if you want me to arrange access to my setup for you to look at.

@TheOriginalMrWolf
Copy link

Hi @andrewleech - running in heating mode & trying to turn on one of the zones (spare room) fails.

Log attached.
Log-1.txt

Also, would be great if the names of the temp sensors could be picked up as well please (they are all just getting named to “MagiQtouch Internal Temperature”.

@TheOriginalMrWolf
Copy link

Hi @andrewleech - I hope you’re doing well.

I have noticed with the app on iOS that there is often considerable lag between making a setting change and seeing that change stably reflected in the app.

For instance, I can turn a zone off in the app and, if I wait a few seconds, I see that zone turn on again. Then, after another (often quite long) wait I finally see that zone turn off again and then stay there.

Gut feeling is that this is the result of ws connections being dropped and reestablished - almost as if the app is polling the server, but using ws connections instead of https.

Even if not that, it certainly doesn’t feel like a stable and performant long-held ws implementation…

I’m thinking of implementing an mitmproxy in my network to investigate further (as well as try to check out the control panel’s comms).

Have you tried mitmproxy for this before, or know of anyone who has?

Cheers!

@andrewleech
Copy link
Owner

andrewleech commented Jul 23, 2024

Hi @TheOriginalMrWolf yeah the current build here certainly has issues with the websocket which have rather confused me. At one point it had seemed quite stable.... I have a hunch they might have changed something on the server end :-/

I have used mitmproxy, that's been my primary method of determining how the oem app works to get all of this going. It was tricky to get working though, requiring patching the app itself to accept the mitmproxy cert to be able to inspect all the https traffic. This was possible on the android app (took a few goes with different tools though) but I doubt it can easily be done with an ios app.
mitmproxy itself didn't easily show the ws content annoyingly. I think it might be possible to dump it, but it's not exposed in the built in UI. I used a second mitm style proxy app on my phone itself to inspect the ws content, though it needed the mitmproxy / patched app to work as well.

Regarding the ws usage, I'm currently trying to maintain a single ws connection which is reused for everything, with it auto-reconnecting any time it closes.
I looked at the oem app dumps again recently however and it kinda looks like it is the one using the ws in a more polling style manner! It seems to be starting new websockets quite regularly, perhaps it starts a new one for each command, using the ws connection just for the "live-ish" updates from the server for when the command goes all the way through the system.

I can't quite tell how it's being used for background updates of commands that are set manually on the wall panel, not sure if it's starting new ws regularly to receive them, or keeping one open in the background.

I've made some changes to my module locally to try using the ws for shorter periods of time, starting new ones for each update, but haven't really had much chance to test and fix it (evap cooler in the middle of winter).

edit: maybe it is possible to get going on ios, I'm pretty sure this is what I used to get it working with the oem app: https://github.com/ptswarm/reFlutter

@TheOriginalMrWolf
Copy link

Thanks @andrewleech. It's been a while since I last used mitmproxy, so not sure what's changed, but in the past I was able to use mitmproxy to capture websocket traffic and then (along with the TLS keys) use Wireshark to decode the traffic (though I did have more control over both the environment and client).

I only have iDevices so based on your feedback I'm not too optimistic about what I can do with the app then. Will see if I have any luck with the control panel.

I have gas heater and inverter cooling so happy to do some testing for you if you'd like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests