Hyundai-Kia-Connect / kia_uvo

A Home Assistant HACS integration that supports Kia Connect(Uvo) and Hyundai Bluelink. The integration supports the EU, Canada and the USA.
MIT License
413 stars 85 forks source link

Failed to call service number/set_value Duplicate request - Duplicate request #498

Open dc911x opened 1 year ago

dc911x commented 1 year ago

Region and Brand of car EU - Ioniq 5

Version of the integration Version 2.048

Describe the bug

When using the slider for the 2nd time after first sliding AC or DC in my lovelace dashboard I'm getting the error: Failed to call service number/set_value Duplicate request - Duplicate request

example both AC and DC are set to 100% and I want to change them back to 80%

edit: After testing a bit the charging levels were set but it required multiple attempts and the slider is stuck many times: afbeelding

Debug logs if an error occurred

File "/usr/local/lib/python3.10/site-packages/hyundai_kia_connect_api/KiaUvoApiEU.py", line 544, in _get_forced_vehicle_state_check_response_for_errors(response)
File "/usr/local/lib/python3.10/site-packages/hyundai_kia_connect_api/KiaUvoApiEU.py", line 71, in _check_response_for_errorsraise error_code_mapping[response["resCode"]](response["resMsg"])
hyundai_kia_connect_api.exceptions.DuplicateRequestError: Duplicate request - Duplicate request

To Reproduce

Slide the AC and then DC charge limit slider without waiting a bit (or vice versa)

Expected behavior

Setting the sliders and after a delay set the charge levels, atm it seems it wants to set the charge right away causing the 2nd slider to error out.

Screenshots

If applicable, add screenshots to help explain your problem. afbeelding afbeelding Additional context

This is all extra context not sure how valuable this will be:

A while back I made my own sliders to set the charging limits, I should check GitHub more then I would have seen you guys did it better with no button, extra automation and script needed like in my case.

I made 2 helpers in home assistant

input_number.ioniq5_ac_limit
input_number.ioniq5_dc_limit

Then made a script that sets sends the charging limit to the car, since trying to integrate this in the lovelace card didn't work...

alias: Set Charging Limits
sequence:
  - service: kia_uvo.set_charge_limits
    data:
      device_id: xxx
      dc_limit: "{{ states('input_number.ioniq5_dc_limit') | int(0) }}"
      ac_limit: "{{ states('input_number.ioniq5_ac_limit') | int(0) }}"
mode: single
icon: mdi:home-lightning-bolt-outline

note: script still works, I just needed to add the device_id since now we have multi vehicle support.

But now my sliders were out of sync if I changed the charging limit using the bluelink app or the car's build-in settings so I also made this automation:

alias: "[Ioniq 5] Update AC/DC target capacity of charge"
description: >-
  Updates the (helper) slider so the dashboard is always in sync even when I
  change the target capacity of charge in the car itself or the bluelink app.
trigger:
  - platform: state
    entity_id:
      - sensor.ioniq_5_target_capacity_of_charge_dc
      - sensor.ioniq_5_target_capacity_of_charge_ac
condition: []
action:
  - service: input_number.set_value
    data:
      value: "{{ (states('sensor.ioniq_5_target_capacity_of_charge_ac') | int) }}"
    target:
      entity_id: input_number.ioniq5_ac_limit
  - service: input_number.set_value
    data:
      value: "{{ (states('sensor.ioniq_5_target_capacity_of_charge_dc') | int) }}"
    target:
      entity_id: input_number.ioniq5_dc_limit
mode: single

Both sensor.ioniq_5_target_capacity_of_charge_dc or sensor.ioniq_5_target_capacity_of_charge_ac don't exist any more so useless automation...


For those curious about the "Consumption" in the card, I should update it using the new "sensor.ioniq_5_monthly_energy_consumption" because I think my formule is wrong somewhere anyway:

  - platform: template
    sensors: 
      ioniq_5_battery_capacity:
        value_template: "72.6"
        unit_of_measurement: "kWh"
      ev_mileage_since_last_charge:
        value_template: "{{ states('sensor.ioniq_5_odometer') | int(0) - states('input_number.ev_mileage_since_last_charge_base') | int }}"
      ioniq_5_battery_capacity_remaining:
        value_template: "{{ ((states('sensor.ioniq_5_battery_capacity') | float * states('sensor.ioniq_5_ev_battery_level') | float ) / 100) | round(1) }}"
        unit_of_measurement: "kWh"
      ev_comsumption:
        value_template: "{{ (states('sensor.ev_mileage_since_last_charge') | float / ((states('sensor.ioniq_5_battery_capacity') | float - states('sensor.ioniq_5_battery_capacity_remaining') | float ))) | round(1) }}"
        unit_of_measurement: "km/kWh"

For this I use 2 input helpers:

input_number.ev_mileage_since_last_charge_base
ev_total_mileage_since_last_charge

and this automation:

alias: "[Ioniq 5] Update EV Mileage Stats"
description: Updates mileage stats after EV charger is connected
trigger:
  - platform: state
    entity_id: binary_sensor.ioniq_5_plugged_in
    from: "off"
    to: "on"
condition: []
action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.ev_total_mileage_since_last_charge
      value: "{{states('sensor.ev_mileage_since_last_charge') | float }}"
  - service: input_number.set_value
    data_template:
      entity_id: input_number.ev_mileage_since_last_charge_base
      value: "{{states('sensor.ioniq_5_odometer') | float }}"
mode: single

And maybe this can help some others too, below are sensors I needed to change to make my dashboard card work again:

binary_sensor.ioniq_5_plugged_in TO binary_sensor.ioniq_5_ev_battery_plug binary_sensor.ioniq_5_charging TO binary_sensor.ioniq_5_ev_battery_charge sensor.ioniq_5_range_by_evTO sensor.ioniq_5_ev_range sensor.ioniq_5_last_update TO sensor.ioniq_5_last_updated_at sensor.ioniq_5_ev_battery TO ensor.ioniq_5_ev_battery_level

cdnninja commented 1 year ago

Thanks for this. Yes this new feature currently calls the car to update the level right away which can cause problems. Let me play around with how I can delay the call to see if a second change is about to be done. I would assume a 30 second delay or so wouldn't be an issue.

If missing sensors let us know in a new issue and we can fix it up. Being almost a full re-write some haven't been mapped. I also don't have an EV so makes some of this a challenge.

dc911x commented 1 year ago

Thanks for this. Yes this new feature currently calls the car to update the level right away which can cause problems. Let me play around with how I can delay the call to see if a second change is about to be done. I would assume a 30 second delay or so wouldn't be an issue.

If missing sensors let us know in a new issue and we can fix it up. Being almost a full re-write some haven't been mapped. I also don't have an EV so makes some of this a challenge.

You guys are doing great work!

30seconds delay shouldn't be a problem, mostly you change one or change both of them pretty fast after. I'm glad I could throw away that ugly button and not mess with the card to make it nice. It's a great new feature.

4homeassistant commented 1 year ago

@cdnninja, I am facing the same issue when trying press the lock and unlock switch too quick (since the cached state often does not necessarily represent the real state until a deep refresh happened). When I open the doors and lock it 15 seconds later it works but the state does not update. Should I open a separate issue?

Logger: homeassistant.components.websocket_api.http.connection
Source: custom_components/kia_uvo/coordinator.py:165
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 19:00:23 (2 occurrences)
Last logged: 19:00:28

[547094956640] Duplicate request - Duplicate request
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 200, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1755, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1792, in _execute_service
    await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)(
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service
    await service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 678, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 958, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 715, in _handle_entity_call
    await result
  File "/config/custom_components/kia_uvo/lock.py", line 51, in async_lock
    await self.coordinator.async_lock_vehicle(self.vehicle.id)
  File "/config/custom_components/kia_uvo/coordinator.py", line 165, in async_lock_vehicle
    await self.hass.async_add_executor_job(self.vehicle_manager.lock, vehicle_id)
  File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.10/site-packages/hyundai_kia_connect_api/VehicleManager.py", line 129, in lock
    return self.api.lock_action(
  File "/usr/local/lib/python3.10/site-packages/hyundai_kia_connect_api/KiaUvoApiEU.py", line 723, in lock_action
    _check_response_for_errors(response)
  File "/usr/local/lib/python3.10/site-packages/hyundai_kia_connect_api/KiaUvoApiEU.py", line 91, in _check_response_for_errors
    raise error_code_mapping[response["resCode"]](response["resMsg"])
hyundai_kia_connect_api.exceptions.DuplicateRequestError: Duplicate request - Duplicate request

Followed by non-availability of all devices entities of the corresponding account. A reload of the integration recovers it.

Logger: custom_components.kia_uvo.coordinator
Source: helpers/update_coordinator.py:201
Integration: Hyundai / Kia Connect (documentation, issues)
First occurred: 19:02:40 (1 occurrences)
Last logged: 19:02:40

Error fetching kia_uvo data: Error communicating with API: Request timeout. - Request timeout.
rolandsteinmeyer commented 1 year ago

Maybe it would also be better to present input_select.car_ac_charginglimit instead of number.car_ac_charginglimit ?

input_select ist triggered once after finishing selecting the new value.

number ist triggered every time you press the up/down arrow if you put it in a standard entitiy card, so if you click twice to change from 80% to 100% the second change errors out.

This would also play better with mushroom cards, since there is no mushroom card for number, but there is a mushroom card for input_select.