Fujitsu Air Conditioning integration - Airstage dongle

Latest version of file which includes tweaks for swing control as as posted by @mow
Also added tip to use capitals for the MAC address

To-do: (volunteers?)

  • !secrets for IP address and MAC address (but not sure if this will make it simpler or not as additional file)
  • change swing control options from On/Off to being ‘On’ or ‘Position 1…4’ (need volunteer as I don’t have a device with swing control)
# Integration for Fujitsu wi-fi adapters that use Airstage app (n.b. will NOT work with the older/discontinued adapters that use FGLair app)
# See the HA Community thread https://community.home-assistant.io/t/fujitsu-air-conditioning-integration-airstage-dongle/589679
#
# 1) Install 'Climate Template' via the HACS integration manager https://github.com/jcwillox/hass-template-climate
# 2) Using 'Studio Code Server' from the HA add-ons store is useful
# 3) Use seach&replace funcitonality is useful!
# 4) Save this file as e.g. 'upstairs_aircon.yaml'. 
# 5) Place this file in the same folder as your configuration.yaml
# 6) Search & replace all '192.168.1.188' with the IP address of your aircon (assign a static IP to this device)
# 7) Search & replace all 'E8FB1CFF5FF5' with the MAC address of your aircon (use CAPITALS and do not put any : in the address)
# 8) Search & replace all instances of 'upstairs' with what you want to name the new aircon device (n.b. needs to be in lower case except where indicated)
# 9) Have a look through at # out sections to see if you want to enable
# 10) Add the following lines to your configuration.yaml (ensure it refers to the correct filename & you remove the #'s')
###############
#homeassistant:
#  packages:
#    pack_1: !include upstairs_aircon.yaml 
###############
#
# ***you will need to do a 'proper'' restart of HA rather than just a quick reload ***
#
# **swing mode is not tested as my device does not have that function** (please report back in the thread if it works)
# 
# Thanks to all the people in the aforemetnioned thread including @pietervanh @ravenland

rest_command:
  upstairs_aircon_setmode:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: >
      {% set aircomodes = {"auto": '"iu_op_mode":"0"',"cool": '"iu_op_mode":"1"',"dry": '"iu_op_mode":"2"',"fan_only": '"iu_op_mode":"3"',"heat": '"iu_op_mode":"4"',"off": '"iu_onoff":"0"'} %}
      {% set opmode = aircomodes.get(hvac_mode, 0) %}
      {"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{ {{opmode}} }} 
  upstairs_aircon_settemp:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: >
      {% set setroomtemp = (target_temp | float   * 10) | int %}
      {"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_set_tmp":"{{ setroomtemp }}"}}
  upstairs_aircon_set_fan_speed:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: >
      {% set fanspds = {"auto": 0, "Quiet": 2,"low": 5,"medium": 8,"high": 11} %}
      {% set spd = fanspds.get(fan_mode, 0) %}
      {"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_fan_spd":"{{ spd }}"}}

# enable if your device has a swing mode
#  upstairs_aircon_set_swing_mode:
#    url: http://192.168.1.188/SetParam
#    method: POST
#    payload: >
#      {% set mode = {"off": 0, "on": 1} %}
#      {% set swing = mode.get(swing_mode, 0) %}
#      {"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_af_swg_vrt":"{{ swing }}"}}
    
# not all units especially ducted have powerful mode. Powerful runs for a short period then stops
  upstairs_aircon_pwrfull_on:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_powerfull":"1"}}'
  upstairs_aircon_pwrfull_off:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_powerfull":"0"}}'

# these aren't used by the template but included for completion
  upstairs_aircon_on:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_onoff":"1"}}'
  upstairs_aircon_off:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_onoff":"0"}}'
  upstairs_aircon_eco_on:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_economy":"1"}}'
  upstairs_aircon_eco_off:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_economy":"0"}}'
  upstairs_aircon_fanctrl_on:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_fan_ctrl":"1"}}'
  upstairs_aircon_fanctrl_off:
    url: http://192.168.1.188/SetParam
    method: POST
    payload: '{"device_id":"E8FB1CFF5FF5","device_sub_id":0,"req_id":"","modified_by":"","set_level":"02","value":{"iu_fan_ctrl":"0"}}'

rest:
  - resource: http://192.168.1.188/GetParam
    scan_interval: 60
    payload: '{"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_fan_ctrl","iu_powerful","ou_low_noise","iu_op_mode","iu_fan_spd","iu_af_swg_vrt"]}'
    sensor:
      - name: "Temp Outside upstairs Aircon"
        value_template: "{{ (((value_json['value']['iu_outdoor_tmp'] | float  / 100 ) - 32 ) * 5/9) | round(2) }}"
        unit_of_measurement: "°C"
      - name: "Temp Inside upstairs Aircon"
        value_template: "{{ (((value_json['value']['iu_indoor_tmp'] | float  / 100 ) - 32 ) * 5/9) | round(2) }}"
        unit_of_measurement: "°C"
      - name: "Requested Temp upstairs Aircon"
        value_template: "{{ (value_json['value']['iu_set_tmp'] | float / 10 )| round(2) }}"
        unit_of_measurement: "°C"
      - name: "Mode upstairs Aircon"
        value_template: >
          {% set mapper ={'0': 'auto','1': 'cool','2': 'dry','3': 'fan_only','4': 'heat'} %}
          {% set state =  value_json['value']['iu_op_mode'] %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
      - name: "Fan Speed Upstairs Aircon"
        value_template: >
          {% set mapper ={'0': 'auto','2': 'Quiet','5': 'low','8': 'medium','11': 'high'} %}
          {% set state =  value_json['value']['iu_fan_spd'] %}
          {{ mapper[state] if state in mapper else 'Unknown' }}
    binary_sensor:
      - name: "Power Status upstairs Aircon"
        value_template: "{{ (value_json['value']['iu_onoff']) }}"

# enable if your device has a swing mode
#      - name: "Swing Mode Upstairs Aircon"
#        value_template: >
#          {% set mapper ={'0': 'off','1': 'on'} %}
#          {% set state =  value_json['value']['iu_af_swg_vrt'] %}
#          {{ mapper[state] if state in mapper else 'Unknown' }}



climate:
  - platform: climate_template
# the name: can have capital letters if desired
    name: Upstairs Aircon
    modes: 
      - "auto"
      - "dry"
      - "off"
      - "cool"
      - "fan_only"
      - "heat"
    fan_modes:
      - "auto"
      - "Quiet"
      - "low"
      - "medium"
      - "high"

# enable if your device has a swing mode
#    swing_modes:
#      - "on"
#      - "off"

    min_temp: 15
    max_temp: 30

    current_temperature_template: "{{ states('sensor.temp_inside_upstairs_aircon') }}"

    hvac_mode_template: >
      {% if is_state('binary_sensor.power_status_upstairs_aircon', 'off') %}
        off
      {% else %}
        {{ states('sensor.mode_upstairs_aircon') }}
      {% endif %}
    
    target_temperature_template: "{{ states('sensor.requested_temp_upstairs_aircon') }}"
    
    fan_mode_template: "{{ states('sensor.fan_speed_upstairs_aircon') }}"

# enable if your device has a swing mode
#    swing_mode_template: "{{ states('binary_sensor.swing_mode_upstairs_aircon') }}"

    set_hvac_mode:
      - service: rest_command.upstairs_aircon_on
      - delay: 1
      - service: rest_command.upstairs_aircon_setmode
        data:
          hvac_mode: "{{ hvac_mode }}"
      - delay: 2
      - service: homeassistant.update_entity
        entity_id: sensor.mode_upstairs_aircon

    set_temperature:
      - service: rest_command.upstairs_aircon_settemp
        data:
          target_temp: "{{ temperature }}"
      - delay: 2
      - service: homeassistant.update_entity
        entity_id: sensor.requested_temp_upstairs_aircon

    set_fan_mode:
      - service: rest_command.upstairs_aircon_set_fan_speed
        data:
          fan_mode: "{{ fan_mode }}"
      - delay: 2
      - service: homeassistant.update_entity
        entity_id: sensor.fan_speed_upstairs_aircon

# enable if your device has a swing mode
#    set_swing_mode:
#      - service: rest_command.upstairs_aircon_set_swing_mode
#        data:
#          swing_mode: "{{ swing_mode }}"
#      - delay: 2
#      - service: homeassistant.update_entity
#        entity_id: binary_sensor.swing_mode_upstairs_aircon