Fujitsu Air Conditioning integration - Airstage dongle

‘’'After a week week of struggling (I am pretty new to HA) I managed to make some nice cards for my 5 Fujitu’s. And got it all working (inlcuding set fan speed / operation mode)

I used two HACS integrations:
Button-card and Multiple Entity Row card.

Since I rent out this house I have put some extra’s in it like When the requested temp (from the remote controller get’s lower than the change temp slider it turn bold and red.

I made some automations as well: If my shelly door/window sensor stay open for >120 secs. the Livingroom airco turns off. The same counts for all the bedroom aircons.

Personally I really like the tap buttons for the OP Mode, however I can’t get the icons lit up in yellow as soon as one is tapped (and active). It should adjust to yellow regarding the value of iu_op_mode eventually. Maybe someone know how to do tis?

Here’s my yaml for one of them (Sorry I don’t know how to insert it as a copy field):

type: entities
title: Airco Bedroom 2
state_color: true
entities:

  • type: custom:button-card
    entity: script.airco_bedroom2_toggle
    tap_action:
    action: call-service
    service: script.turn_on
    service_data:
    entity_id: script.airco_bedroom2_toggle
    show_icon: false
    show_name: true
    name: |
    [[[
    if (states[‘binary_sensor.airco_bedroom2_powered’].state === ‘on’) return ‘Powered on - Turn Off’;
    else return ‘Powered off - Turn On’;
    ]]]
    styles:
    card:
    - background-color: |
    [[[
    if (states[‘binary_sensor.airco_bedroom2_powered’].state === ‘on’) return ‘#90EE90’;
    else return ‘#FF7F7F’;
    ]]]
    name:
    - font-weight: bold
  • entity: sensor.requested_temp_airco_bedroom2
    name: Requested Temperature
    icon: mdi:remote
    state_color: true
    style: |
    :host {
    font-weight: {% if states(‘sensor.requested_temp_airco_bedroom2’) | float < states(‘input_number.setaircotempbedroom2’) | float %} bold {% else %} normal {% endif %};
    color: {% if states(‘sensor.requested_temp_airco_bedroom2’) | float < states(‘input_number.setaircotempbedroom2’) | float %} red {% else %} inherit {% endif %};
    }
  • entity: input_number.setaircotempbedroom2
    name: Change temperature
  • type: custom:multiple-entity-row
    entity: sensor.operational_mode_airco_bedroom1_friendlyname
    name: ’ ’
    icon: mdi:cog-outline
    state_icon:
    ‘0’: mdi:auto-mode
    ‘1’: mdi:snowflake
    ‘2’: mdi:water-off-outline
    ‘3’: mdi:fan
    ‘4’: mdi:radiator
    entities:
    • icon: mdi:auto-mode
      tap_action:
      action: call-service
      service: input_number.set_value
      service_data:
      entity_id: input_number.setaircooperationalmodebedroom2
      value: 0
    • icon: mdi:snowflake
      tap_action:
      action: call-service
      service: input_number.set_value
      service_data:
      entity_id: input_number.setaircooperationalmodebedroom2
      value: 1
    • icon: mdi:water-off-outline
      tap_action:
      action: call-service
      service: input_number.set_value
      service_data:
      entity_id: input_number.setaircooperationalmodebedroom2
      value: 2
    • icon: mdi:fan
      tap_action:
      action: call-service
      service: input_number.set_value
      service_data:
      entity_id: input_number.setaircooperationalmodebedroom2
      value: 3
    • icon: mdi:radiator
      tap_action:
      action: call-service
      service: input_number.set_value
      service_data:
      entity_id: input_number.setaircooperationalmodebedroom2
      value: 4

I hope you guy;s like it and can do somthing with it :slight_smile:

Regards, Mark’’’

This is what the built-in (I think) Lovelace thermostat card looks like with the climate code that has been put up in recent posts.

If you click the three dots in top right you get the ‘full’ HVAC options including fan control etc.

One more feature idea.

The climate integration in home assistant supports preset_mode like for example eco.

Unfortunately the HACS integration Climate Template does not support it. There is an one year old open feature request. Maybe someone here is able to add this feature to the HACS integration.

1 Like

Looking at the code of the HACS Climate Template…

  1. It should be relatively easy to replicate the preset_mode functionality from existing similar code

  2. I wonder if a dedicated Fujitsu HACS integration plugin can be made by altering the original HACS Climate Template integration - configuration.yaml would just need to have the IP/MAC/NAME +/- optional features to enable/disable settings… I may look at the practicalities of doing this…

3 Likes

I’ve had a nose around the AirStage API today and it’s using Google Firebase for it’s comms, and Android Keystore (presumably for user creds).

I can see the api keys/ids that it uses, but the APK is heavily obfuscated for “sub-URLs” to (for example) iterate devices etc, so I can’t see those or where it’s hiding tokens. Dumping the app log shows function names which are not visible in the code browser due to the obfuscation :\

Looks like Firebase is ultimately MQTT-esque on that side, as I can see references to “TopicBindingName” etc.

Hi,

I have made a home assistant integration for Fujitsu Airstage Airconditioners, if any one want to try it out.

Please let me know if any issues here:

8 Likes

Daniel! You’re the hero we’ve been waiting for! :smiling_face_with_three_hearts:

2 Likes

Appears to work flawlessly on my system. Case closed everyone, shut down the thread, send Daniel some beers.

That’s awesome! Good to hear!

@edmooredop Did you go for local connection or via cloud?

Local. That approach with the various REST calls we got working over the rest of this thread was working fine for me so saw no reason to involve the cloud now.

Allright :+1:
Let me know if you stumble upon any issues!

1 Like

This is great work @danielkaldheim

I am having some trouble with the integration.
I am using local mode (briefly tried Cloud with same issue). The model number of my Airstage adapter is UTY-TFSXJ3 for a ducted unit.

The integration partially works in that it shows the room/outdoor temperatures and the current settings for ‘Ecomony mode’ and ‘Energy saving fan’.

However:

  1. The climate controls are ‘unavailable’

  2. The ‘Ecomony mode’ and ‘Energy saving fan’ settings don’t reflect changes I make in the app (until I reload the integration). I suspect the temperatures don’t update but can’t confirm this (as it takes a long time for temperature to change!)

I wonder if it isn’t updating as the aircon unit itself doesn’t have all the functionality of a normal split unit (e.g. doesn’t have a ‘swing mode’)

When I try and change the A/C mode I see a ‘failed to call service climate.set_hvac_mode 65535’ in the UI
I have enabled debug logging but there is nothing in there even though there are errors in the UI:

2023-08-15 07:51:24.901 DEBUG (MainThread) [custom_components.fujitsu_airstage] Finished fetching Fujitsu Airstage data in 4.149 seconds (success: True)
2023-08-15 07:51:39.212 DEBUG (MainThread) [custom_components.fujitsu_airstage.climate] ON
2023-08-15 07:51:45.538 DEBUG (MainThread) [custom_components.fujitsu_airstage] Finished fetching Fujitsu Airstage data in 5.550 seconds (success: True)

I have included the output of a CURL command to see if this helps the debug

curl -vv -X POST --data '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"03","list":["iu_set_tmp","iu_indoor_tmp","iu_outdoor_tmp","iu_onoff","iu_economy","iu_fan_ctrl","iu_powerful","ou_low_noise","iu_op_mode","iu_fan_spd","iu_af_swg_vrt","iu_onoff","iu_af_swg_vrt"]}' 'http://192.168.1.59/GetParam'

Note: Unnecessary use of -X or --request, POST is already inferred.

* Trying 192.168.1.59:80...

* Connected to 192.168.1.59 (192.168.1.59) port 80 (#0)

> POST /GetParam HTTP/1.1

> Host: 192.168.1.59

> User-Agent: curl/7.81.0

> Accept: */*

> Content-Length: 283

> Content-Type: application/x-www-form-urlencoded

>

* Mark bundle as not supporting multiuse

< HTTP/1.1 200 OK

< Content-Type: application/json

< Content-Length: 409

<

* Connection #0 to host 192.168.1.59 left intact

{"value":{"iu_set_tmp":"220","iu_indoor_tmp":"7250","iu_outdoor_tmp":"6500","iu_onoff":"1","iu_economy":"0","iu_fan_ctrl":"1","iu_powerful":"65535","ou_low_noise":"0","iu_op_mode":"4","iu_fan_spd":"0","iu_af_swg_vrt":"65535","iu_onoff":"1","iu_af_swg_vrt":"65535"},"read_res":"ack","device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"03","cause":"","result":"OK","error":""}

I suspect the issue is relating to the lack of some functions on ducted A/C. Note the JSON output “iu_af_swg_vrt”:“65535” especially the number 65535 which is the same as referenced in the UI error message above. I think the integration is baulking at the fact that some features are not available. Note also “iu_powerful”:“65535”

Does the integration setup routine need to be able to disable features that are not available with tick-boxes e.g. be able to disable powerful and the swing control.

update: I think the integration updates some of the modes (e.g. choose heating) as it is reflected in the App but the HA UI remains ‘unavailable’

In case it’s useful the unit I’m using that works fine is the ASYG07KMCE.

That’s a standard split unit with swing control

Mine is a ARXG18KLLAP which is a ducted unit and uses a slightly different Airstage adapter

1 Like

Hi,

Thank you for sharing, and I think you are right. I can add a check for params resulting with “65535” and enable / disable function based on this.

I made this integration based on the unit I’m having access to, so your CURL is appreciated!

If you want you could add this to configuration.yaml for more debug info:

logger:
  default: info
  logs:
    fujitsu_airstage: debug
    pyairstage: debug

I’m using three sets of param list for getting the information needed for the integration. Some of these are probably redundant.

This one fetches the model for example: “ASYG12KMCEN”. This has failed in another case, and I’m looking into this.

 modelInfo = await self.get_parameters(
            [
                "iu_model",
            ],
        )
        acInfo = await self.get_parameters(
            [
                "iu_wifi_led",
                "iu_af_inc_hrz",
                "iu_af_inc_vrt",
                "iu_indoor_tmp",
                "iu_outdoor_tmp",
                "iu_hmn_det",
                "iu_main_ver",
                "iu_eep_ver",
                "iu_has_upd_main",
                "iu_has_upd_eep",
                "iu_fld_set80",
            ],
        )
        modeInfo = await self.get_parameters(
            [
                "iu_onoff",
                "iu_op_mode",
                "iu_fan_spd",
                "iu_set_tmp",
                "iu_af_dir_vrt",
                "iu_af_swg_vrt",
                "iu_af_dir_hrz",
                "iu_af_swg_hrz",
                "ou_low_noise",
                "iu_fan_ctrl",
                "iu_hmn_det_auto_save",
                "iu_min_heat",
                "iu_powerful",
                "iu_economy",
                "iu_err_code",
                "iu_demand",
                "iu_fltr_sign_reset",
            ],
        )

It would be interesting to get your results from this curl (the same as modeInfo used in my integration):

curl -vv -X POST --data '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"03","list":["iu_onoff","iu_op_mode","iu_fan_spd","iu_set_tmp","iu_af_dir_vrt","iu_af_swg_vrt","iu_af_dir_hrz","iu_af_swg_hrz","ou_low_noise","iu_fan_ctrl","iu_hmn_det_auto_save","iu_min_heat","iu_powerful","iu_economy","iu_err_code","iu_demand","iu_fltr_sign_reset"]}' 'http://192.168.1.59/GetParam'

There’s a delay (120 seconds) for every background refresh from the unit. This was set to not flood the cloud service. So when theres a change done by the app, it can take up to two minutes before it’s reflected in the integration.

I can lower this when on local connection, and maybe add a configuration settings where you can set the sync interval.

Thanks for the reply.

Happy to test out some code edits as I appreciate that it is difficult if you don’t have access.

(alternatively I could send you my Airstage login details for you to work against with a temporary password if that is more useful)

Here is the output of the requested curl command:

curl -vv -X POST --data '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"03","list":["iu_onoff","iu_op_mode","iu_fan_spd","iu_set_tmp","iu_af_dir_vrt","iu_af_swg_vrt","iu_af_dir_hrz","iu_af_swg_hrz","ou_low_noise","iu_fan_ctrl","iu_hmn_det_auto_save","iu_min_heat","iu_powerful","iu_economy","iu_err_code","iu_demand","iu_fltr_sign_reset"]}' 'http://192.168.1.59/GetParam'

Note: Unnecessary use of -X or --request, POST is already inferred.

* Trying 192.168.1.59:80...

* Connected to 192.168.1.59 (192.168.1.59) port 80 (#0)

> POST /GetParam HTTP/1.1

> Host: 192.168.1.59

> User-Agent: curl/7.81.0

> Accept: */*

> Content-Length: 355

> Content-Type: application/x-www-form-urlencoded

>

* Mark bundle as not supporting multiuse

< HTTP/1.1 200 OK

< Content-Type: application/json

< Content-Length: 507

<

* Connection #0 to host 192.168.1.59 left intact

{"value":{"iu_onoff":"1","iu_op_mode":"1","iu_fan_spd":"0","iu_set_tmp":"220","iu_af_dir_vrt":"65535","iu_af_swg_vrt":"65535","iu_af_dir_hrz":"65535","iu_af_swg_hrz":"65535","ou_low_noise":"0","iu_fan_ctrl":"1","iu_hmn_det_auto_save":"65535","iu_min_heat":"0","iu_powerful":"65535","iu_economy":"0","iu_err_code":"0","iu_demand":"0","iu_fltr_sign_reset":"65535"},"read_res":"ack","device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"03","cause":"","result":"OK","error":""}

I think a locally configurable poll interval would be good for the local API.

Interestingly, the app when connected to the cloud seems to update very quickly. Not sure if this is just rapid polling or some kind of push.

Issue should be have fixed now in version 1.0.6!

1 Like