atxbyea / samsungrac

Home Assistant Climate Device for controlling (not only) Samsung AC
60 stars 18 forks source link

GET https://IP:8888/devices returns two separate AC devices #32

Open tanus10 opened 3 years ago

tanus10 commented 3 years ago

Problem For certain AC models Samsung is selling, "GET https://IP:8888/devices" returns two separate AC devices values.

Background I have a Samsung AC set, one main AC with WIFI, and the other just connected to the main AC. So one can install two AC's in different rooms with merit of installing only one heat exchanger outside. Smartthings natively supports such configuration too.

10165396_h

(sold as one product with two separate remotes for each AC, but only one outside heat exchanger unit to save energy and space)

Details

# curl -s -k -H "Content-Type: application/json" -H "Authorization: Bearer xxxxxxxx" --cert /root/ac/cert.pem --insecure -X GET https://192.168.45.232:8888/devices
{"Devices":[
{"Alarms":[{"alarmType":"Device","code":"ErrorCode_OFF","id":"0","triggeredTime":"2021-08-12T01:15:15"},{"alarmType":"Device","code":"FilterAlarm_OFF","id":"1","triggeredTime":"2021-08-12T01:15:15"}],"ConfigurationLink":{"href":"/devices/1/configuration"},"EnergyConsumption":{"saveLocation":"/files/usage.db"},"InformationLink":{"href":"/devices/1/information"},"Mode":{"modes":["Auto"],"options":["Comode_Off","Sleep_0","Autoclean_Off","Light_Off","Volume_100","RacOptionCode_0","FilterCleanAlarm_0","AI_Enable","ArtificialWork_Off","DisplayArtificial_Off"],"supportedModes":["Cool","Dry","Wind","CoolClean","DryClean","Auto"]},"Operation":{"power":"Off"},"Temperatures":[{"current":29.0,"desired":26.0,"id":"0","maximum":30,"minimum":16,"unit":"Celsius"}],"Wind":{"direction":"Fix","speedLevel":0},"connected":true,"description":"FAC_BORA_RAC_17K","id":"1","name":"Room Air Conditioner","resources":["Alarms","Configuration","Diagnosis","EnergyConsumption","Humidity","Information","Mode","Operation","Sensors","Temperatures","Wind"],"type":"Air_Conditioner","uuid":"C0972775-XXXX-0000-0000-000000000001"},
{"Alarms":[{"alarmType":"Device","code":"","id":"0","triggeredTime":"2021-08-12T01:15:16"},{"alarmType":"Device","code":"FilterAlarm_OFF","id":"1","triggeredTime":"2021-08-12T01:15:16"},{"alarmType":"Device","code":"AC_V_0002_OFF","id":"2","triggeredTime":"2021-08-12T01:15:16"}],"ConfigurationLink":{"href":"/devices/0/configuration"},"Diagnosis":{"diagnosisStart":"Ready"},"EnergyConsumption":{"cumulativeConsumption":100.0,"instantaneousPower":0.0,"saveLocation":"/files/usage.db","usageThreshold":0.0},"Humidity":{"current":0.0,"unit":"Percentage"},"InformationLink":{"href":"/devices/0/information"},"Mode":{"modes":["Wind"],"options":["Operation_Family","Comode_Off","Sleep_0","Autoclean_Off","FilterCleanAlarm_0","Panel_Close","Light_Off","Smarton_LockOff","Weather_Off","Volume_33","OptionCode_797","UpdateAllow_NotAllowed","WattNotice_0","RacInfo_First","ModelInfo_16K_BORA_VENT3","Blooming_0","UsagesDB_ok","EnergySaveIcon_Off","Dehumidification_0","AirMonitoring_Off","AI_Enable","ArtificialWork_Off","DisplayArtificial_Off"],"supportedModes":["Cool","Dry","Wind","CoolClean","DryClean","Auto"]},"Operation":{"power":"Off"},"Sensors":[{"id":"0","type":"CleanLevel","values":[2.0]},{"id":"1","type":"Odor","values":[0.0]},{"id":"2","type":"Dust","values":[9.0,0.0]},{"id":"3","type":"FineDust","values":[9.0,0.0]}],"Temperatures":[{"current":30.0,"desired":24.0,"id":"0","maximum":30,"minimum":18,"unit":"Celsius"}],"Wind":{"direction":"Off","speedLevel":3},"connected":true,"description":"FAC_BORA_17K","id":"0","name":"Stand Air Conditioner","resources":["Alarms","Configuration","Diagnosis","EnergyConsumption","Humidity","Information","Mode","Operation","Sensors","Temperatures","Wind"],"type":"Air_Conditioner","uuid":"C0972775-XXXX-0000-0000-000000000000"}]}

If you see the returned JSON above carefully, there are two different sets of device values. device/0 and device/1. Which is actually correct behavior, since it's Dual AC-set model. (You can use 'GET https://IP:8888/devices/0' or 'GET https://IP:8888/devices/1' to have just one set of device status values returned)

The problem is that in Homeassistant, climate_ip attributes are populated by the result of 'GET https://IP:8888/devices' call which contains TWO sets of almost identical JSON values. HOMEASSISTANT is parsing it only once. so Guess which values HOMEASSISTANT is using then? Always the first device's.

Example When I turn on device 0. the default device for climate_ip, HOMEASSISTANT populates attributes with device 1 values which is, for some reason, returned sequentially ahead of device 0. Since device 1 is not turned on, HOMEASSISTANT think the climate device is still Power off, Mode off and so on.

Digging I have tried to put '/0' in the end of

  status:
    type: 'json_status'
    connection:
      params: { method : 'GET', url: 'https://__CLIMATE_IP_HOST__:8888/devices' }

so it would look like,

      params: { method : 'GET', url: 'https://__CLIMATE_IP_HOST__:8888/devices/0' }

in samsungrac.yaml without success. It produces bellow error in HOMEASSISTANT.

2021-08-12 08:19:39 ERROR (MainThread) [homeassistant.components.climate] climate_ip: Error on device update!
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 432, in _async_add_entity
    await entity.async_device_update(warning=False)
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 601, in async_device_update
    await task
  File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/climate_ip/climate.py", line 261, in update
    self.rac.update_state()
  File "/config/custom_components/climate_ip/controller_yaml.py", line 222, in update_state
    op.update_state(device_state, debug)
  File "/config/custom_components/climate_ip/properties.py", line 233, in update_state
    v = self.status_template.render(device_state=device_state)
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 1304, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 455, in getitem
    return obj[argument]
jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'Devices'

I think it would solve the problem, if only I could put "/0" or "/1" at the end of
params: { method : 'GET', url: 'https://__CLIMATE_IP_HOST__:8888/devices' } to params: { method : 'GET', url: 'https://__CLIMATE_IP_HOST__:8888/devices/0' }

or '/1' then modify all /0 in samsungrac.yaml to /1. Actually, in this way I can separately control both AC's, with two different yamls. I have confirmed that with the same IP and port, '/devices/0' and '/devices/1' are what differentiates two AC's, only tried on/off operation, but I am sure others work too.

I do not have the expertise to find what is causing "jinja2.exceptions.UndefinedError: 'dict object' has no attribute 'Devices'" when I put /0 at the end of json_status params. Please help.

By the way, I think even Google nests and Alexa devices are currently supporting only the first device in this kind configuration.

Update

'GET https://192.168.1.132:8888/devices' gets, {"Devices":[{"Alarms":[{"alarmType":"Device","code........

'GET https://192.168.1.132:8888/devices/0' gets, {"Device":{"Alarms":[{"alarmType":"Device","code.....

Note the beginning of the returned JSON, "Devices:[" and "Device:" The structural difference is causing the error on HA run, I guess. How can I fix this?

atxbyea commented 3 years ago

Hopefully someone else can come along and try to make this work, since I don't have a dual unit nor enough python skills to make it work it would have to be someone else investigating it

jeongheon81 commented 2 years ago

In my case, the main AC listed in "Devices[1]" but the configuration path is "/devices/0". And sub AC listed in "Devices[0]" but the configuration path is "/devices/1".

I have create two configuration yaml with simple find and replace from 'samsungrac.yaml'. 'climate_ip_samsungrac_dual_main.yaml' : "Devices.0" => "Devices.1" 'climate_ip_samsungrac_dual_sub.yaml' : "devices/0" => "devices/1"

And create two climate devices in the configuration.yaml with same ip address and token. (config_file is different.)