deiger / AirCon

Scripts for controlling Air Conditioners, e.g. with HiSense modules.
GNU General Public License v3.0
198 stars 55 forks source link

AEH-W4G2 #160

Open jcbshw opened 2 years ago

jcbshw commented 2 years ago

Stumbled upon this looking to connect my new Hisense AC to home assistant. It has the W4G2 wifi module and uses the ConnectLife app. Nothing really comes up for this module when googling. I have attempted adding it to the other apps but the WiFi network is HIS-####### not HiSmart-####### or the other variations it is looking for.

Anything I can do to look at having support for this AC added?

EDIT: looks like the url the AC communicates with is ac-eu-link.hijuconn.com

Lineflyer commented 6 months ago

@Samorja Its purely NodeRed. At this moment I can not share it as I would need to duplicate it and remove all personal information.

However what I purely did was making use of the Oauth2 library using their example on this page: https://flows.nodered.org/node/node-red-contrib-oauth2

Afterwards you can send requests as documented on the above mentioned swagger page.

Monacoslo commented 6 months ago

Is this about HomeAssistant integration?

Netesfiu commented 5 months ago

While waiting for ConnectLife to release documentation and provide a system to allow creating one own's clientId and clientSecret, I managed to reverse-engineer the OAuth workflow for regenerating the bearer token when this has expired.

Information needed:

clientId: this is visible on Swagger UI page clientSecret: this is visible in the source code on the Swagger UI page (starts with 07swf...) access_token: this is returned after login on the Authorization URL. To get this, open the Network tab on Chrome's developer tools and before opening the Authorization URL. After successful Authentication, the Network tab should display the JSON for the request made to https://oauth-gateway.hijuconn.com/oauth/token expires_in: this values should always be 1440 seconds. The value is returned in the Network tab as described above refresh_token: the value is returned in the Network tab as described above.

Once you have the refresh_token, you can request new tokens when the previous if the token has expired by making further requests to https://oauth-gateway.hijuconn.com/oauth/token

Here's a very basic cURL request for this:

curl -X POST https://oauth-gateway.hijuconn.com/oauth/token \
    -d "grant_type=refresh_token" \
    -d "refresh_token=YOUR_REFRESH_TOKEN" \
    -d "client_id=YOUR_CLIENT_ID" \
    -d "client_secret=YOUR_CLIENT_SECRET" \
    -H "Content-Type: application/x-www-form-urlencoded"

Values YOUR_REFRESH_TOKEN, YOUR_CLIENT_ID and YOUR_CLIENT_SECRET would need to be replaced.

Can you please give us an example for the correct log entry? I've only managed to find the accessToken, but not the refreshToken. Using your cURL request returns the following error for me:

{"resultCode":1,"error":600906,"error_description":"Illegal app"}

image

apphancer commented 5 months ago

@Netesfiu here's the steps:

  1. Head to https://api.connectlife.io/swagger/index.html
  2. Open your browser's Dev Tools
  3. Click on the Authorize button on top of the webpage. In the dialog that opens, do not change any details and click on Authorize
  4. In the the new tab that opens, enter your own credentials and click on Sign In
  5. The tab will close and in the network section of the Dev Tools for the https://api.connectlife.io/swagger/index.html, you should see a new request (name: token; url: https://oauth-gateway.hijuconn.com/oauth/token)
  6. If you click on this request, then click on the Preview or the Response tab, you should get the JSON response which contains your access and refresh tokens.
image

Now, you should be able to use your access token to make requests to the other API endpoints. Your access token, however, will expire after 1440 seconds. Once it has expired, you can request a new one by making a request to the https://oauth-gateway.hijuconn.com/oauth/token endpoint to request new access and refresh tokens. For this, you will need to make a request like the one in the example I've posted earlier making sure to replace YOUR_REFRESH_TOKEN, YOUR_CLIENT_ID, YOUR_CLIENT_SECRET accordingly.

bilan commented 5 months ago

This is my solution to getting access token to connectlife API: https://github.com/Bilan/connectlife-api-connector/blob/main/app/Services/ConnectlifeApiService.php

grzech1991 commented 5 months ago

Are you thinking about a homebridge plugin?

bilan commented 5 months ago

I use Home Assistant so no plan for other platforms but it should be easy to integrate because I use MQTT and http api is also exposed.

djm193 commented 5 months ago

I use Home Assistant so no plan for other platforms but it should be easy to integrate because I use MQTT and http api is also exposed.

Are you saying you could create a Home Assistant integration in order to use the AC with home assistant? This would be super nice!

bilan commented 5 months ago

Home Assistant integration, I mean add-on is ready to go here: https://github.com/Bilan/connectlife-api-connector

kctje commented 5 months ago

it's working already
https://github.com/Bilan/connectlife-api-connector

djm193 commented 5 months ago

Not sure what I am doing wrong. Installed the addon, configured with my mqtt credentials however it says „Establishing a connection to the MQTT broker failed: The configured broker responded with unauthorized.“

-----------------------------------------------------------

Add-on: Connectlife API proxy / MQTT Add-on Integrates Connectlife AC devices with Home Assistant via MQTT and provides an HTTP API

Add-on version: 1.0.11 You are running the latest version of this add-on. System: Home Assistant OS 11.5 (aarch64 / raspberrypi4-64) Home Assistant Core: 2024.2.1 Home Assistant Supervisor: 2024.01.1

Please, share the above information when

bilan commented 5 months ago

Wrong credentials to MQTT server. You can try removing mqtt credentails, then addon will try to fetch it by supervisor API.

ekashuba commented 5 months ago

Home Assistant integration, I mean add-on is ready to go here: https://github.com/Bilan/connectlife-api-connector

Thank you, Bilan. I've been using Node-Red to make all of my calls to the Connectlife API's but this will make things much easier so thanks for putting this together!

Is there a way to set my region? I'm in the US and when my thermostats are updated both the target and current values are displayed correctly (for me that's in Fahrenheit) but if I try to change the temp using one of these new thermostats it ends up setting the target temp to 32. I looked at the logs during the discovery process and I can see that the min_temp is 16.0 and the max_temp is 32.0 so when I try to set it to 70F I can see how that would be outside of its range.

bilan commented 5 months ago

Glad you like it :)

I just updated the code to support Fahrenheit. Update to v1.0.12 and select correct temperature_unit in Add-on Configuration section.

ekashuba commented 5 months ago

Glad you like it :)

I just updated the code to support Fahrenheit. Update to v1.0.12 and select correct temperature_unit in Add-on Configuration section.

That works perfectly. Thanks!

aguedob commented 5 months ago

Home Assistant integration, I mean add-on is ready to go here: https://github.com/Bilan/connectlife-api-connector

Works like a charm! Thank you!

delumerlino commented 5 months ago

Glad you like it :)

I just updated the code to support Fahrenheit. Update to v1.0.12 and select correct temperature_unit in Add-on Configuration section.

Thank you, works like a charm!!! 😍

vpaulos commented 5 months ago

and how can I add this repo to HAOS? in addons - do not work (((

In ConnectlifeApiService.php line 80:

[Error]
Call to a member function body() on array

Exception trace: at /home/app/app/Services/ConnectlifeApiService.php:80 App\Services\ConnectlifeApiService->App\Services{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:397 Illuminate\Cache\Repository->remember() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php:429 Illuminate\Cache\CacheManager->call() at /home/app/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:355 Illuminate\Support\Facades\Facade::callStatic() at /home/app/app/Services/ConnectlifeApiService.php:59 App\Services\ConnectlifeApiService->getAccessToken() at /home/app/app/Services/ConnectlifeApiService.php:54 App\Services\ConnectlifeApiService->getTokenHeaders() at /home/app/app/Services/ConnectlifeApiService.php:167 App\Services\ConnectlifeApiService->App\Services{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:397 Illuminate\Cache\Repository->remember() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php:429 Illuminate\Cache\CacheManager->call() at /home/app/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:355 Illuminate\Support\Facades\Facade::callStatic() at /home/app/app/Services/ConnectlifeApiService.php:163 App\Services\ConnectlifeApiService->devices() at /home/app/app/Services/ConnectlifeApiService.php:143 App\Services\ConnectlifeApiService->status() at /home/app/app/Services/ConnectlifeApiService.php:127 App\Services\ConnectlifeApiService->getOnlineAcDevices() at /home/app/app/Services/MqttService.php:18 App\Services\MqttService->__construct() at n/a:n/a ReflectionClass->newInstanceArgs() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:952 Illuminate\Container\Container->build() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:795 Illuminate\Container\Container->resolve() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:957 Illuminate\Foundation\Application->resolve() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:731 Illuminate\Container\Container->make() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:942 Illuminate\Foundation\Application->make() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:181 Illuminate\Container\BoundMethod::addDependencyForCallParameter() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:124 Illuminate\Container\BoundMethod::getMethodDependencies() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:36 Illuminate\Container\BoundMethod::Illuminate\Container{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Util.php:41 Illuminate\Container\Util::unwrapIfClosure() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:93 Illuminate\Container\BoundMethod::callBoundMethod() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:35 Illuminate\Container\BoundMethod::call() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:662 Illuminate\Container\Container->call() at /home/app/vendor/laravel/framework/src/Illuminate/Console/Command.php:211 Illuminate\Console\Command->execute() at /home/app/vendor/symfony/console/Command/Command.php:326 Symfony\Component\Console\Command\Command->run() at /home/app/vendor/laravel/framework/src/Illuminate/Console/Command.php:180 Illuminate\Console\Command->run() at /home/app/vendor/symfony/console/Application.php:1096 Symfony\Component\Console\Application->doRunCommand() at /home/app/vendor/symfony/console/Application.php:324 Symfony\Component\Console\Application->doRun() at /home/app/vendor/symfony/console/Application.php:175 Symfony\Component\Console\Application->run() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:201 Illuminate\Foundation\Console\Kernel->handle() at /home/app/artisan:35

s6-rc: info: service legacy-services: stopping

vpaulos commented 5 months ago

and how can I add this repo to HAOS? in addons - do not work (((

In ConnectlifeApiService.php line 80:

[Error]
Call to a member function body() on array

Exception trace: at /home/app/app/Services/ConnectlifeApiService.php:80 App\Services\ConnectlifeApiService->App\Services{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:397 Illuminate\Cache\Repository->remember() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php:429 Illuminate\Cache\CacheManager->call() at /home/app/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:355 Illuminate\Support\Facades\Facade::callStatic() at /home/app/app/Services/ConnectlifeApiService.php:59 App\Services\ConnectlifeApiService->getAccessToken() at /home/app/app/Services/ConnectlifeApiService.php:54 App\Services\ConnectlifeApiService->getTokenHeaders() at /home/app/app/Services/ConnectlifeApiService.php:167 App\Services\ConnectlifeApiService->App\Services{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:397 Illuminate\Cache\Repository->remember() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php:429 Illuminate\Cache\CacheManager->call() at /home/app/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:355 Illuminate\Support\Facades\Facade::callStatic() at /home/app/app/Services/ConnectlifeApiService.php:163 App\Services\ConnectlifeApiService->devices() at /home/app/app/Services/ConnectlifeApiService.php:143 App\Services\ConnectlifeApiService->status() at /home/app/app/Services/ConnectlifeApiService.php:127 App\Services\ConnectlifeApiService->getOnlineAcDevices() at /home/app/app/Services/MqttService.php:18 App\Services\MqttService->__construct() at n/a:n/a ReflectionClass->newInstanceArgs() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:952 Illuminate\Container\Container->build() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:795 Illuminate\Container\Container->resolve() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:957 Illuminate\Foundation\Application->resolve() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:731 Illuminate\Container\Container->make() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:942 Illuminate\Foundation\Application->make() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:181 Illuminate\Container\BoundMethod::addDependencyForCallParameter() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:124 Illuminate\Container\BoundMethod::getMethodDependencies() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:36 Illuminate\Container\BoundMethod::Illuminate\Container{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Util.php:41 Illuminate\Container\Util::unwrapIfClosure() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:93 Illuminate\Container\BoundMethod::callBoundMethod() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:35 Illuminate\Container\BoundMethod::call() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:662 Illuminate\Container\Container->call() at /home/app/vendor/laravel/framework/src/Illuminate/Console/Command.php:211 Illuminate\Console\Command->execute() at /home/app/vendor/symfony/console/Command/Command.php:326 Symfony\Component\Console\Command\Command->run() at /home/app/vendor/laravel/framework/src/Illuminate/Console/Command.php:180 Illuminate\Console\Command->run() at /home/app/vendor/symfony/console/Application.php:1096 Symfony\Component\Console\Application->doRunCommand() at /home/app/vendor/symfony/console/Application.php:324 Symfony\Component\Console\Application->doRun() at /home/app/vendor/symfony/console/Application.php:175 Symfony\Component\Console\Application->run() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:201 Illuminate\Foundation\Console\Kernel->handle() at /home/app/artisan:35

s6-rc: info: service legacy-services: stopping

2024-02-21 17:01:57,883 WARN exited: mqtt (exit status 1; not expected) 2024-02-21 17:01:58,897 INFO spawned: 'mqtt' with pid 405 2024-02-21 17:01:59,900 INFO success: mqtt entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

In RequestException.php line 113:

Client error: GET https://api.connectlife.io/api/v1/appliance resulted in
a 404 Not Found response

2024-02-21 17:02:00,547 WARN exited: mqtt (exit status 1; not expected) 2024-02-21 17:02:01,558 INFO spawned: 'mqtt' with pid 408 2024-02-21 17:02:02,562 INFO success: mqtt entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

In RequestException.php line 113:

Client error: GET https://api.connectlife.io/api/v1/appliance resulted in
a 404 Not Found response

2024-02-21 17:02:03,166 WARN exited: mqtt (exit status 1; not expected)

delumerlino commented 5 months ago

and how can I add this repo to HAOS? in addons - do not work (((

In ConnectlifeApiService.php line 80:

[Error] Call to a member function body() on array

Exception trace: at /home/app/app/Services/ConnectlifeApiService.php:80 App\Services\ConnectlifeApiService->App\Services{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:397 Illuminate\Cache\Repository->remember() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php:429 Illuminate\Cache\CacheManager->call() at /home/app/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:355 Illuminate\Support\Facades\Facade::callStatic() at /home/app/app/Services/ConnectlifeApiService.php:59 App\Services\ConnectlifeApiService->getAccessToken() at /home/app/app/Services/ConnectlifeApiService.php:54 App\Services\ConnectlifeApiService->getTokenHeaders() at /home/app/app/Services/ConnectlifeApiService.php:167 App\Services\ConnectlifeApiService->App\Services{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/Repository.php:397 Illuminate\Cache\Repository->remember() at /home/app/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php:429 Illuminate\Cache\CacheManager->call() at /home/app/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:355 Illuminate\Support\Facades\Facade::callStatic() at /home/app/app/Services/ConnectlifeApiService.php:163 App\Services\ConnectlifeApiService->devices() at /home/app/app/Services/ConnectlifeApiService.php:143 App\Services\ConnectlifeApiService->status() at /home/app/app/Services/ConnectlifeApiService.php:127 App\Services\ConnectlifeApiService->getOnlineAcDevices() at /home/app/app/Services/MqttService.php:18 App\Services\MqttService->__construct() at n/a:n/a ReflectionClass->newInstanceArgs() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:952 Illuminate\Container\Container->build() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:795 Illuminate\Container\Container->resolve() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:957 Illuminate\Foundation\Application->resolve() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:731 Illuminate\Container\Container->make() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php:942 Illuminate\Foundation\Application->make() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:181 Illuminate\Container\BoundMethod::addDependencyForCallParameter() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:124 Illuminate\Container\BoundMethod::getMethodDependencies() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:36 Illuminate\Container\BoundMethod::Illuminate\Container{closure}() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Util.php:41 Illuminate\Container\Util::unwrapIfClosure() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:93 Illuminate\Container\BoundMethod::callBoundMethod() at /home/app/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:35 Illuminate\Container\BoundMethod::call() at /home/app/vendor/laravel/framework/src/Illuminate/Container/Container.php:662 Illuminate\Container\Container->call() at /home/app/vendor/laravel/framework/src/Illuminate/Console/Command.php:211 Illuminate\Console\Command->execute() at /home/app/vendor/symfony/console/Command/Command.php:326 Symfony\Component\Console\Command\Command->run() at /home/app/vendor/laravel/framework/src/Illuminate/Console/Command.php:180 Illuminate\Console\Command->run() at /home/app/vendor/symfony/console/Application.php:1096 Symfony\Component\Console\Application->doRunCommand() at /home/app/vendor/symfony/console/Application.php:324 Symfony\Component\Console\Application->doRun() at /home/app/vendor/symfony/console/Application.php:175 Symfony\Component\Console\Application->run() at /home/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:201 Illuminate\Foundation\Console\Kernel->handle() at /home/app/artisan:35

s6-rc: info: service legacy-services: stopping

2024-02-21 17:01:57,883 WARN exited: mqtt (exit status 1; not expected) 2024-02-21 17:01:58,897 INFO spawned: 'mqtt' with pid 405 2024-02-21 17:01:59,900 INFO success: mqtt entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

In RequestException.php line 113:

Client error: GET https://api.connectlife.io/api/v1/appliance resulted in a 404 Not Found response

2024-02-21 17:02:00,547 WARN exited: mqtt (exit status 1; not expected) 2024-02-21 17:02:01,558 INFO spawned: 'mqtt' with pid 408 2024-02-21 17:02:02,562 INFO success: mqtt entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

In RequestException.php line 113:

Client error: GET https://api.connectlife.io/api/v1/appliance resulted in a 404 Not Found response

2024-02-21 17:02:03,166 WARN exited: mqtt (exit status 1; not expected)

Connection to API is closed, see https://github.com/Bilan/connectlife-api-connector/issues/7

Lineflyer commented 5 months ago

I noticed the same in my custom Node-Red implementation. The appliance endpoint is just gone (404). :(

Monacoslo commented 5 months ago

I noticed the same in my custom Node-Red implementation. The appliance endpoint is just gone (404). :(

https://community.home-assistant.io/t/add-integration-for-hisense-devices-using-connectlife/459082/75

Due the abuse of unofficial API (Ip from Nyiregyhaza, Hungary was sending crazy amount of requests) they had to close it until they will make is as it should be.

apphancer commented 5 months ago

I've received a similar reply from customer support adding that "API is under the development". It could be a matter days, months or it could never materialise. As I need a way to control these appliances and as there is no certainty of when or even if the API will be publicly available, I've resorted at creating a Node Red instance with node-red-contrib-alexa-remote2-applestrudel which integrates with the Alexa Skill of Connectlife. My Node Red server exposes a /device endpoint which returns json data of the appliances statuses. I still need to create another endpoint to allow posting appliances settings but it shouldn't be too difficult to implement.

Monacoslo commented 5 months ago

According to my information public API is actually in the development, the one used in some integrations was unofficial one, for internal use only, but they still silently allowed community to use it for custom integrations until last "abuse".

But very likely now the publish of the official one will be even later (end of the year) since they will probably add additional security layers

BenJamesAndo commented 4 months ago

Has anyone attempted to reverse-engineer the serial commands from the AEH-W4G2? It would be nice to plug an ESP device into it and use ESPHome or Tasmota to control it all locally and skip the whole ConnectLife app.

EDIT Someone did do some work that might be a good starting point for reverse-engineering these Hisense units. https://community.home-assistant.io/t/aircon-international-hisense-mini-split-control/551716

pio2398 commented 1 month ago

I will post this comment also here. I apologize if anyone thinks this is SPAM.

AEH-W4G2 seem to base on RTL8710BL with UM3352EESA as RS485 convector. Source: https://fccid.io/2AGCCAEH-W4G2/Users-Manual/User-Manual-5281170

So maybe just flash custom firmware with this metod: https://docs.libretiny.eu/docs/platform/realtek-ambz/#wiring?

No extra hardware will be required in AC unit. No problem with power or case.

At the moment, I see only one problem. How access CEN and serial port of RTL8710BL. From the bottom of the PCB, test pins are available. Maybe serial and CEN is available via these test pins?

fccid got PCB scan/layout but I don't see connection to RTL8710BL.