Airtouch 4 integration (AUS)

Hi @mihailescu2m. Did you get a chance to look into the non-updating temperature sensors I mentioned previously? It looks like it’s only the ITC room sensors, not the overall system sensor, and only seems to occur when the system is off. The problem I’ve got is, with the system set on Economy, the main system sensor reports the ITC that’s furthest away from the set point, so if it was last on Heat but then the rooms start to get warm, it will choose the coldest room rather than the hottest. If I could run the automations based on the individual ITC temperatures instead, this wouldn’t matter.

Not sure if the behaviour is determined by the AC itself or the AirTouch but my Panasonic definitely just keeps running the indoor unit through the spills once it’s got to temperature. What brand AC do you have?

Thank you for this! I implemented your Zones card :slight_smile:

Hey wuism, I saw you’ve got vents working with “90%” displaying. May I bother you to post up a config to help? I just can’t seem to figure this bit out :frowning:

Could you not just create a generic thermostat integration? Just read the whole thread and realised how this integration works now…

Sorry, do not have an Airtouch system, but I am looking at buying one. What exactly does the system expose to HA? How much fine tuning can be done? Any recommendations on spill zone for install?

Noob Tutorial/Help;

Hey everyone, just sharing my experience getting this into my own setup.

AirTouch 4 with only the tablet temperature sensor. No temp sensors in any other rooms (aka the ITC things) but each room has its own controllable damper / vent.

@LonePurpleWolf I tried as hard as I can to use your official integration (then attempted to use the forked version for damper control) but as a novice, none of the steps made sense to me. I don’t have enough experience unfortunetly to get it to work with my limited experience.

I ended up using @mihailescu2m (GitHub - mihailescu2m/hass-airtouch4-platform: Airtouch4 integration for Home Assistant ) which actually gave me everything I needed including damper / vent control per room.

This is what I finally got working.

Code for the top card;

type: custom:simple-thermostat
entity: climate.midea_carrier
unit: C
step_size: '1'
header:
  name: Smart Touch 4
layout:
  mode:
    icons: true
    headings: false
    names: true
  step: column
decimals: '0'

Code for the bottom card;

type: custom:button-card
custom_fields:
  column1: Area
  column2: Vent
  column3: Vent Control
  column4: Zone On/Off
  masterlabel: Master
  bed_2label: Bed 2
  bed_3_4label: Bed 3 & 4
  kitchenlabel: Kitchen
  studylabel: Study
  theatrelabel: Theatre
  mastertemp: '[[[ return `${states["fan.master"].attributes.percentage} %` ]]]'
  bed_2temp: '[[[ return `${states["fan.bed_2"].attributes.percentage} %` ]]]'
  bed_3_4temp: '[[[ return `${states["fan.bed_3_4"].attributes.percentage} %` ]]]'
  kitchentemp: '[[[ return `${states["fan.kitchen"].attributes.percentage} %` ]]]'
  studytemp: '[[[ return `${states["fan.study"].attributes.percentage} %` ]]]'
  theatretemp: '[[[ return `${states["fan.theatre"].attributes.percentage} %` ]]]'
  masterslider:
    card:
      entity: fan.master
      full_row: true
      hide_state: true
      show_icon: false
      type: custom:slider-entity-row
      entities: fan.master
      attribute: percentage
      min: 0
      max: 100
      step: 5
      hide_when_off: true
  bed_2slider:
    card:
      entity: fan.bed_2
      full_row: true
      hide_state: true
      show_icon: false
      entities: fan.bed_2
      type: custom:slider-entity-row
      min: 0
      max: 100
      step: 5
      hide_when_off: true
  bed_3_4slider:
    card:
      entity: fan.bed_3_4
      full_row: true
      hide_state: true
      show_icon: false
      type: custom:slider-entity-row
      min: 0
      max: 100
      step: 5
      hide_when_off: true
  kitchenslider:
    card:
      entity: fan.kitchen
      full_row: true
      hide_state: true
      show_icon: false
      type: custom:slider-entity-row
      min: 0
      max: 100
      step: 5
      hide_when_off: true
  studyslider:
    card:
      entity: fan.study
      full_row: true
      hide_state: true
      show_icon: false
      type: custom:slider-entity-row
      min: 0
      max: 100
      step: 5
      hide_when_off: true
  theatreslider:
    card:
      entity: fan.theatre
      full_row: true
      show_icon: false
      type: custom:slider-entity-row
      min: 0
      max: 100
      step: 5
      hide_when_off: true
  masterbutton:
    card:
      entity: climate.master
      show_state: false
      show_name: false
      show_icon: true
      icon: mdi:power
      color: darkgreen
      size: 25px
      right: 10px
      type: custom:button-card
      state:
        - value: 'off'
          color: grey
      tap_action:
        action: call-service
        service: >-
          [[[ if (states["fan.master"].state != "off") return "fan.turn_off";
          else return "fan.turn_on" ]]]
        service_data:
          entity_id: fan.master
  bed_2button:
    card:
      entity: climate.bed_2
      show_state: false
      show_name: false
      show_icon: true
      icon: mdi:power
      color: darkgreen
      size: 25px
      type: custom:button-card
      state:
        - value: 'off'
          color: grey
      tap_action:
        action: call-service
        service: >-
          [[[ if (states["fan.bed_2"].state != "off") return "fan.turn_off";
          else return "fan.turn_on" ]]]
        service_data:
          entity_id: fan.bed_2
  bed_3_4button:
    card:
      entity: fan.bed_3_4
      show_state: false
      show_name: false
      show_icon: true
      icon: mdi:power
      color: darkgreen
      size: 25px
      type: custom:button-card
      state:
        - value: 'off'
          color: grey
      tap_action:
        action: call-service
        service: >-
          [[[ if (states["fan.bed_3_4"].state != "off") return "fan.turn_off";
          else return "fan.turn_on" ]]]
        service_data:
          entity_id: fan.bed_3_4
  kitchenbutton:
    card:
      entity: climate.kitchen
      show_state: false
      show_name: false
      show_icon: true
      icon: mdi:power
      color: darkgreen
      size: 25px
      type: custom:button-card
      state:
        - value: 'off'
          color: grey
      tap_action:
        action: call-service
        service: >-
          [[[ if (states["fan.kitchen"].state != "off") return "fan.turn_off";
          else return "fan.turn_on" ]]]
        service_data:
          entity_id: fan.kitchen
  studybutton:
    card:
      entity: climate.study
      show_state: false
      show_name: false
      show_icon: true
      icon: mdi:power
      color: darkgreen
      size: 25px
      type: custom:button-card
      state:
        - value: 'off'
          color: grey
      tap_action:
        action: call-service
        service: >-
          [[[ if (states["fan.study"].state != "off") return "fan.turn_off";
          else return "fan.turn_on" ]]]
        service_data:
          entity_id: fan.study
  theatrebutton:
    card:
      entity: climate.theatre
      show_state: false
      show_name: false
      show_icon: true
      icon: mdi:power
      color: darkgreen
      size: 25px
      type: custom:button-card
      state:
        - value: 'off'
          color: grey
      tap_action:
        action: call-service
        service: >-
          [[[ if (states["fan.theatre"].state != "off") return "fan.turn_off";
          else return "fan.turn_on" ]]]
        service_data:
          entity_id: fan.theatre
styles:
  card:
    - padding: 2%
    - font-size: 15px
  custom_fields:
    column1:
      - justify-self: start
      - padding-left: 30%
    column2:
      - justify-self: start
      - padding-left: 30%
    column3: null
    column4: null
    masterlabel:
      - justify-self: start
      - padding-left: 30%
    bed_2label:
      - justify-self: start
      - padding-left: 30%
    bed_3_4label:
      - justify-self: left
      - padding-left: 30%
    kitchenlabel:
      - justify-self: left
      - padding-left: 30%
    studylabel:
      - justify-self: left
      - padding-left: 30%
    theatrelabel:
      - justify-self: left
      - padding-left: 30%
    mastertemp:
      - justify-self: left
      - padding-left: 30%
    bed_2temp:
      - justify-self: start
      - padding-left: 30%
    bed_3_4temp:
      - justify-self: start
      - padding-left: 30%
    kitchentemp:
      - justify-self: start
      - padding-left: 30%
    studytemp:
      - justify-self: start
      - padding-left: 30%
    theatretemp:
      - justify-self: start
      - padding-left: 30%
    masterslider: null
    bed_2slider: null
    bed_3_4slider: null
    kitchenslider: null
    studyslider: null
    theatreslider: null
    masterbutton:
      - padding-left: 25%
      - padding-right: 25%
    bed_2button:
      - padding-left: 25%
      - padding-right: 25%
    bed_3_4button:
      - padding-left: 25%
      - padding-right: 25%
    kitchenbutton:
      - padding-left: 25%
      - padding-right: 25%
    studybutton:
      - padding-left: 25%
      - padding-right: 25%
    theatrebutton:
      - padding-left: 25%
      - padding-right: 25%
  grid:
    - grid-template-areas: >-
        "column1 column2 column3 column4" "masterlabel mastertemp masterslider
        masterbutton" "bed_2label bed_2temp bed_2slider bed_2button"
        "bed_3_4label bed_3_4temp bed_3_4slider bed_3_4button" "kitchenlabel
        kitchentemp kitchenslider kitchenbutton" "studylabel studytemp
        studyslider studybutton" "theatrelabel theatretemp theatreslider
        theatrebutton"
    - grid-template-rows: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr
    - grid-template-columns: 1fr 1fr 1fr 1fr
  img_cell:
    - justify-content: start
    - align-items: start
    - margin: none
show_icon: false

For any newbies also looking to do this you will also need to install ‘slider-entity-row’ from the HACS store.

GLHF

seems like you figured it out? still need the config?

Yeah, working great now. All good thank you :slight_smile:

Would anyone be against me taking the latest code and creating a PR for the master branch of HA? (i would only touch the changes requested by HA, not planning on coding anything else)

Anyone else finding that @mihailescu2m updated AirTouch integration does not load initially on restart of home assistant. If I disable and re-enable the integration starts working no issue.

Looking through the logs it appears to be timing out. Did attempt to adjust the time out in the code but didn’t seem to make a difference (I might be doing it wrong though)

I am having the same issues as @salty2011 ans @Brett.Grivell .

  1. Temperature sensors will not update until a command (for example damper change) is sent, then all temps are updated

  2. The integration does not load correctly on restart. It appears the integration also fails after 4-5hrs which can be solved by disabling and re-enabling the integration

For issue 1, it appears group climate entities update correctly (I.e the status of my main unit, and main temperature), however it is the individual AC units. I had a look at the difference in code (airtouch.py) between these two different entities and noticed a few difference such as forces int conversion, however, I do not have enough experience to troubleshoot the issue further.

Does anyone have any experience troubleshooting integrations into HASS? Happy to try to assist/test but this is a bit out of my depth.

As issue 2 was not present for me in @LonePurpleWolf integration, I can only assume this would be solvable also with the correct expertise!

I can’t say I’ve noticed any issues with the integration failing and my system has been up for almost a month now.

I think the non-updating zone temperature sensors is related to when the system is turned off. Not sure if it’s fixable in code, but I worked around it by just turning one of my zones off / on (or on / off) every 15 mins in an Automation.

alias: AC Force Update
description: ''
trigger:
  - platform: time_pattern
    minutes: /15
condition: []
action:
  - service: script.force_ac_temperatures_to_update
mode: single
alias: Force AC Temperatures To Update
sequence:
  - service: climate.turn_off
    target:
      entity_id: climate.landing
  - delay: 2
  - service: climate.turn_off
    target:
      entity_id: climate.landing
mode: single

Note: both actions are turn_off as that seems to behave as a toggle and turn_on doesn’t do anything

This seems to work pretty well for me.

1 Like

Thanks for the suggestion @Brett.Grivell, I have concerns with doing this as my understanding is that this will cause the damper motor to close/open every 15mins causing unnecessary wear on the system? (Please correct me if I am wrong).

Interesting to hear you have no issues with the integration failing. I will have to look into it deeper on my end with a fresh HA installation to confirm it’s not a conflict on my side.

Cheers

You’re likely right, but I figured that the AT4 seems to take several seconds before sending commands to the AC system so hopefully it wasn’t actually sending the command before it was reset (not sure if there’s any way to confirm without getting in the roof).

I forgot to mention that I have no issues with it connecting automatically on startup either, so maybe it is disconnecting but successfully re-connecting??

Hey @jlich

The integrations failing of HASS restart has been solved for me. I moved my HASS setup from a RPI3 with sdcard to a NUC using nvme. This seems to have fixed this a many other issues I was having.

Thought will have to say I am not getting the temperature issue mentioned by @Brett.Grivell.

Three errors when calling climate.turn_off (it does turn off the zone / AC unit though - although not consistently)

Logger: homeassistant.components.airtouch4
Source: components/airtouch4/__init__.py:65
Integration: AirTouch 4 (documentation, issues)
First occurred: January 5, 2022, 4:20:59 AM (19 occurrences)
Last logged: 6:03:20 PM

Unexpected error fetching airtouch4 data: 'AirTouchAc' object has no attribute 'StartGroupNumber'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 187, in _async_refresh
    self.data = await self._async_update_data()
  File "/usr/src/homeassistant/homeassistant/components/airtouch4/__init__.py", line 65, in _async_update_data
    await self.airtouch.UpdateInfo()
  File "/usr/local/lib/python3.9/site-packages/airtouch4pyapi/airtouch.py", line 85, in UpdateInfo
    if(ac.StartGroupNumber == 0 and ac.GroupCount == 0):
AttributeError: 'AirTouchAc' object has no attribute 'StartGroupNumber'
Logger: homeassistant.components.websocket_api.http.connection
Source: components/airtouch4/climate.py:138
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 6:00:23 PM (3 occurrences)
Last logged: 6:02:59 PM

[548176938176] 'AirTouchAc' object has no attribute 'PowerState'
[547908196720] 'AirTouchAc' object has no attribute 'PowerState'
[547873691536] 'AirTouchAc' object has no attribute 'PowerState'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 185, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1495, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1530, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 209, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 663, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 896, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 700, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/airtouch4/climate.py", line 335, in async_turn_off
    await self.coordinator.async_request_refresh()
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 141, in async_request_refresh
    await self._debounced_refresh.async_call()
  File "/usr/src/homeassistant/homeassistant/helpers/debounce.py", line 78, in async_call
    await task
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 165, in async_refresh
    await self._async_refresh(log_failures=True)
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 265, in _async_refresh
    update_callback()
  File "/usr/src/homeassistant/homeassistant/components/airtouch4/climate.py", line 97, in _handle_coordinator_update
    return super()._handle_coordinator_update()
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 325, in _handle_coordinator_update
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 505, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 538, in _async_write_ha_state
    state = self._stringify_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 511, in _stringify_state
    if (state := self.state) is None:
  File "/usr/src/homeassistant/homeassistant/components/climate/__init__.py", line 210, in state
    return self.hvac_mode
  File "/usr/src/homeassistant/homeassistant/components/airtouch4/climate.py", line 138, in hvac_mode
    is_off = self._unit.PowerState == "Off"
AttributeError: 'AirTouchAc' object has no attribute 'PowerState'
Logger: homeassistant.components.websocket_api.http.connection
Source: components/airtouch4/climate.py:147
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 8:43:53 AM (1 occurrences)
Last logged: 8:43:53 AM

[547904682400] 'AirTouchAc' object has no attribute 'ModeSupported'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 185, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1495, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1530, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 209, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 663, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 896, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 700, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/airtouch4/climate.py", line 191, in async_turn_off
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 505, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 535, in _async_write_ha_state
    attr = self.capability_attributes
  File "/usr/src/homeassistant/homeassistant/components/climate/__init__.py", line 226, in capability_attributes
    ATTR_HVAC_MODES: self.hvac_modes,
  File "/usr/src/homeassistant/homeassistant/components/airtouch4/climate.py", line 147, in hvac_modes
    airtouch_modes = self._airtouch.GetSupportedCoolingModesForAc(self._ac_number)
  File "/usr/local/lib/python3.9/site-packages/airtouch4pyapi/airtouch.py", line 163, in GetSupportedCoolingModesForAc
    return self.acs[acNumber].ModeSupported;
AttributeError: 'AirTouchAc' object has no attribute 'ModeSupported'
1 Like

I’m new to HA, but having successfully installed the AirTouch 4 integration by @mihailescu2m but am stuck configuring an automation.

I have the trigger working fine, but am struggling with the action(s).

I’d like the action to set zones to “Damper” mode and set the percentage to 100.

It’s probably simple, but I’ve never done anything with YAML before so any help would be appreciated.

Think this should do it for you.

service: fan.set_preset_mode
target:
  entity_id: fan.master
data:
  preset_mode: Damper
service: fan.set_percentage
data:
  percentage: 100
target:
  entity_id: fan.master

Hey @jlich. Not sure if you’re still looking into it, but I found a better workaround for the temperature sensors not updating when the system is turned off. Because climate.turn_on isn’t working for individual zones and climate.turn_off is behaving like a toggle, you needed to turn off / on or on / off to leave it in the same state. If you instead use fan.turn_off or fan.turn_on, they behave as expected, so you can target a particular zone that is already off or on respectively and it will still cause Home Assistant to update the zone temperatures. Hope that helps and solves the worry of the zone motor wear.

1 Like

Thanks @Brett.Grivell that worked, but need to put a 1 sec delay between the two actions. So that means 3 actions for each zone, so for my 6 zones means 18 actions in total.

I actually discovered I can achieve the same effect using two scenes activated my an automation. The first changes all zones to damper at once, the second changes them all too 100%. And a 1 second delay between activating each scene.

Thanks