make-all / tuya-local

Local support for Tuya devices in Home Assistant
MIT License
1.39k stars 534 forks source link

Request support for Mellerware City Move vacuum #584

Closed antonio1475 closed 1 year ago

antonio1475 commented 1 year ago

Log Message

No logs at all for tuya-local even when enabling Debugging mode :/ 

Information about DPS mappings

{
  "result": {
    "category": "sd",
    "functions": [
      {
        "code": "power",
        "dp_id": 1,
        "type": "Boolean",
        "values": "{}"
      },
      {
        "code": "cleanmode",
        "dp_id": 102,
        "type": "Enum",
        "values": "{\"range\":[\"clean_auto\",\"clean_random\",\"clean_wall\",\"clean_spot\",\"clean_sroom\",\"find_sta\",\"null\"]}"
      },
      {
        "code": "fanstatus",
        "dp_id": 104,
        "type": "Enum",
        "values": "{\"range\":[\"FANHALTING\",\"FANNORAM\",\"FANMAX\"]}"
      },
      {
        "code": "movedirect",
        "dp_id": 105,
        "type": "Enum",
        "values": "{\"range\":[\"MoveForward\",\"MoveBackward\",\"MoveLeft\",\"MoveRight\",\"stop\"]}"
      },
      {
        "code": "CleanSwtich",
        "dp_id": 112,
        "type": "Enum",
        "values": "{\"range\":[\"0\",\"1\"]}"
      },
      {
        "code": "ResetBrush",
        "dp_id": 113,
        "type": "Boolean",
        "values": "{}"
      },
      {
        "code": "ResetRollbrush",
        "dp_id": 114,
        "type": "Boolean",
        "values": "{}"
      },
      {
        "code": "ResetHepa",
        "dp_id": 115,
        "type": "Boolean",
        "values": "{}"
      },
      {
        "code": "FindRobot",
        "dp_id": 116,
        "type": "Boolean",
        "values": "{}"
      },
      {
        "code": "time",
        "dp_id": 117,
        "type": "Enum",
        "values": "{\"range\":[\"clean_auto\",\"clean_random\",\"clean_wall\",\"clean_spot\",\"find_sta\"]}"
      }
    ],
    "status": [
      {
        "code": "power",
        "dp_id": 1,
        "type": "Boolean",
        "values": "{}"
      },
      {
        "code": "cleanarea",
        "dp_id": 14,
        "type": "Integer",
        "values": "{\"unit\":\"㎡\",\"min\":0,\"max\":10000,\"scale\":1,\"step\":1}"
      },
      {
        "code": "fault",
        "dp_id": 17,
        "type": "Bitmap",
        "values": "{\"label\":[\"FAULT_CLIFF\",\"FAULT_IMP\",\"FAULT_WHL\",\"FAULT_BRUSH\",\"FAULT_FAN\",\"FAULT_ROLLBRUSH\",\"FAULT_LOWPOWER\",\"FAULT_GIVEUP\",\"FAULT_NODUST\",\"FAULT_NONE\"],\"maxlen\":10}"
      },
      {
        "code": "workstatus",
        "dp_id": 101,
        "type": "Enum",
        "values": "{\"range\":[\"SLEEP\",\"HALTING\",\"CLEANING\",\"CLEAN_COMP\",\"FIND_STA\",\"CHARGING_STA\",\"CHARGING_DC\",\"CHARG_COMP\"]}"
      },
      {
        "code": "cleanmode",
        "dp_id": 102,
        "type": "Enum",
        "values": "{\"range\":[\"clean_auto\",\"clean_random\",\"clean_wall\",\"clean_spot\",\"clean_sroom\",\"find_sta\",\"null\"]}"
      },
      {
        "code": "fanstatus",
        "dp_id": 104,
        "type": "Enum",
        "values": "{\"range\":[\"FANHALTING\",\"FANNORAM\",\"FANMAX\"]}"
      },
      {
        "code": "movedirect",
        "dp_id": 105,
        "type": "Enum",
        "values": "{\"range\":[\"MoveForward\",\"MoveBackward\",\"MoveLeft\",\"MoveRight\",\"stop\"]}"
      },
      {
        "code": "cleantime",
        "dp_id": 107,
        "type": "Integer",
        "values": "{\"unit\":\"min\",\"min\":0,\"max\":300,\"scale\":0,\"step\":1}"
      },
      {
        "code": "electricity",
        "dp_id": 108,
        "type": "Integer",
        "values": "{\"unit\":\"\",\"min\":0,\"max\":100,\"scale\":1,\"step\":1}"
      },
      {
        "code": "MaterialLife_Brush",
        "dp_id": 109,
        "type": "Integer",
        "values": "{\"unit\":\"%\",\"min\":0,\"max\":100,\"scale\":0,\"step\":1}"
      },
      {
        "code": "MaterialLife_Rollbru",
        "dp_id": 110,
        "type": "Integer",
        "values": "{\"unit\":\"%\",\"min\":0,\"max\":100,\"scale\":0,\"step\":1}"
      },
      {
        "code": "MaterialLife_HEPA",
        "dp_id": 111,
        "type": "Integer",
        "values": "{\"unit\":\"%\",\"min\":0,\"max\":100,\"scale\":0,\"step\":1}"
      },
      {
        "code": "CleanSwtich",
        "dp_id": 112,
        "type": "Enum",
        "values": "{\"range\":[\"0\",\"1\"]}"
      },
      {
        "code": "time",
        "dp_id": 117,
        "type": "Enum",
        "values": "{\"range\":[\"clean_auto\",\"clean_random\",\"clean_wall\",\"clean_spot\",\"find_sta\"]}"
      },
      {
        "code": "RobotModel",
        "dp_id": 118,
        "type": "Integer",
        "values": "{\"unit\":\"\",\"min\":0,\"max\":65535,\"scale\":1,\"step\":1}"
      },
      {
        "code": "DataSample",
        "dp_id": 119,
        "type": "Integer",
        "values": "{\"unit\":\"\",\"min\":0,\"max\":999999999,\"scale\":1,\"step\":1}"
      }
    ]
  },
  "success": true,
  "t": 1680353624182,
  "tid": "3c0c7457d08c11ed94b47648064b5440"
}

Product ID

"model": "CITY MOVE",
"product_id": "sayafukjeqp9kupy",
"product_name": "City Move",

Information about how the device functions

Instructions Manual: https://cdn.shopify.com/s/files/1/0281/0619/5026/files/MANUAL_Mellerware_City_Move_86e3a112-11a8-4837-b7a4-8ecfc848d7f5.pdf?v=1607113247

Local Tuya configuration (vacuum worked great with this config, but migrating to tuya-local so vacuum deleted from localtuya before adding to tuya-local too): image image

make-all commented 1 year ago

Maybe try selecting 3.4 as the protocol when adding the device to see if something appears in the log then. 3.4 devices seem to have problems being detected by the auto setting sometimes. Since you previously used the device with localtuya, the device must be on WiFi and should be able to be connected.

antonio1475 commented 1 year ago

@make-all I should have clarified that with protocol 3.3, it connects but it's "recognized" as a simple_switch. I have tried again with protocol 3.4 (and all. Auto IP or Auto protocol never works for me) and for this device, no logs are generated.

I would be happy to work on a custom yaml on my own and then share it, but I have added a mellerware_city_move_vacuum.yaml to /config/custom_components/tuya_local/devices/, restarted HA and I must be doing it wrong since it doesn't show up at all (only simple_switch):

name: Mellerware City Move vacuum
products:
  - id: sayafukjeqp9kupy
    name: City Move
primary_entity:
  entity: vacuum
  dps:
    - id: 1
      type: boolean
      name: power
    - id: 101
      type: string
      name: status
      mapping:
        - dps_val: STANDBY
          value: STANDBY
        - dps_val: CLEANING
          value: CLEANING
        - dps_val: CHARGING
          value: CHARGING
        - dps_val: CHARG_COMP
          value: CHARG_COMP
        - dps_val: HALTING
          value: HALTING
        - dps_val: FIND_STA
          value: FIND_STA
    - id: 102
      type: string
      name: command
      mapping:
        - dps_val: clean_auto
          value: clean_auto
        - dps_val: clean_random
          value: clean_random
        - dps_val: clean_wall
          value: clean_wall
        - dps_val: clean_spot
          value: clean_spot
        - dps_val: find_sta
          value: find_sta
    - id: 104
      type: string
      name: command
      mapping:
        - dps_val: FANHALTING
          value: FANHALTING
        - dps_val: FANNORAM
          value: FANNORAM
        - dps_val: FANMAX
          value: FANMAX

Any guidance towards being able to work on a yaml file or whatever is needed is much appreciated. Thank you!

make-all commented 1 year ago

When it shows up as "simple_switch", there should be a warning level log message output (unless it is a perfect match for simple switch, which basically means it is only exposing a switch). The log message will show exactly what is received from the device, without which I don't know why the config above would not be working.

antonio1475 commented 1 year ago

I was able to force logs by deleting the simple_switch.yaml.

This error originated from a custom integration.

Logger: custom_components.tuya_local.config_flow
Source: custom_components/tuya_local/config_flow.py:46
Integration: Tuya Local (documentation, issues)
First occurred: 14:12:25 (2 occurrences)
Last logged: 14:12:25

Device matches None with quality of 0%. DPS: {"updated_at": 1680437543.1548753, "1": true}
Report this to https://github.com/make-all/tuya-local/issues/

It seems it's only exposing 1 DP at least at config. Isn't that weird? Tuya API Explorer DPS are exposed (OP) and it worked with local tuya.

Screenshot from Tuya regarding Instruction Mode. DP Instruction or Standard Instruction (like all my other devices) doesn't seem to make a difference either. image

Additional info:

I was also using vaccum card to make it fully work, using the localtuya.set_dp service.

              - type: custom:popup-card
                entity: vacuum.mellerware_city_move_vacuum
                card:
                    type: custom:vacuum-card
                    entity: vacuum.mellerware_city_move_vacuum
                    image: default
                    actions:
                      start:
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 102
                          value: clean_auto
                      pause:
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 1
                          value: pause
                      stop:
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 1
                          value: stop
                      locate:
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 116
                          value: true
                      return_to_base:
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 102
                          value: find_sta
                    stats:
                      cleaning:
                        - value_template: >-
                            {{ (states.vacuum.mellerware_city_move_vacuum.attributes.clean_area |
                            float(0) / 10) | round(1) }}
                          unit: m²
                          subtitle: Cleaned area
                        - attribute: clean_time
                          unit: minutes
                          subtitle: Cleaning time
                        - subtitle: Mode
                          value_template: >-
                            {% set mode =
                            states.vacuum.mellerware_city_move_vacuum.attributes.cleaning_mode %} {%
                            if mode == 'clean_auto' %} Auto {% elif mode == 'clean_random' %} Random
                            {% elif mode == 'clean_wall' %} Wall {% elif mode == 'clean_spot' %}
                            Spot {% else %} ' ' {% endif %}
                    shortcuts:
                      - name: Auto
                        icon: mdi:refresh-auto
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 102
                          value: clean_auto
                      - name: Random
                        icon: mdi:arrow-all
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 102
                          value: clean_random
                      - name: Edge
                        icon: mdi:border-radius
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 102
                          value: clean_wall
                      - name: Spot
                        icon: mdi:target
                        service: localtuya.set_dp
                        service_data:
                          device_id: bf4acxxxxxxxxxxx5d54w8l
                          dp: 102
                          value: clean_spot

Should I go back to local-tuya for this vacuum?

make-all commented 1 year ago

I have made a preliminary config. It would be useful to get the diagnositcs after running it, to see what data is actually coming back from the device with usage.

antonio1475 commented 1 year ago

It works! ❤️ Thank you so much - Local Tuya is now gone! 😄

image

image

Default statuses are Error and empty Fan speed: image

After a command, Status field (DP 101?) starts reporting back, but Entity status remains as ERROR. Fan speed doesn't. imageimage

It works great as-is, but

My feedback for improvements:

  1. The general status is always ERROR, but the "Status:" field changes between cleaning, paused, returning, CHARGING_STA, etc. 1.1 After pressing the physical button a few times (not always reproduceable), it changed to always Docked with a button to START CLEANING (even when it's already cleaning), except for when it's Returning to base. I don't understand where this status is coming from. image image

If I make DP 101 the main one and reload, it will recognize Cleaning (but then the device won't be recognized if being newly added because it's looking for DP 1?): image

I really don't know how to consistently get this status field. It doesn't work (ERROR) most of the time.

1.2 I would suggest capitalizing the Status' field values (eg. Cleaning) 1.2 CHARGING_STA is not being mapped to "charging". It seems that when there are multiple dps_val in brackets [] they aren't being recognized? Changing it to:

        - dps_val: CHARGING_STA
          value: Charging

works though. Are lists in brackets supported? I didn't find another device example. The same happens in the other cases (CHARG_COMP instead Standy for [null,SLEEP,CHARG_COMP] image

  1. "Scheduled task" (using DPS 117) should be "Mode". 2.1 Can Mode be added next to Fan speed in the more-info dialog?
  2. Fan speed isn't polled / doesn't report unless manually changed in HA, but Mode ('Scheduled task' select) does automatically.

The 3 Remaining sensors (material life) do work but after Reload remain Unknown until they change again.

Again, I'm aware that this is a minor, Spanish-branded device, and it's working great already, so thank you again!

antonio1475 commented 1 year ago

Oh, adding the logs as you requested home-assistant_tuya_local_2023-04-22T14-26-01.690Z.log config_entry-tuya_local-9fbe7a26cb268e2b97cf7a7f59f83329.json (1).txt

make-all commented 1 year ago
  1. support for arrays as dps_val was added recently for a different purpose, but it seems it is not working in this context, so I have separated these out again. I think these were the cause of the false Error state detection, and things should work better with that fixed. Status values are named to be consistent with other supported vacuums, so I won't change them now - probably this will be sorted by translations for the common vacuum statuses in a coming HA release.
  2. I'm not sure this is correct. Mode is already covered by dp 102, and dp 117 seemed to be a duplicate of that, with the name "time" in your original report. My guess that "time" means it is a scheduled mode may be incorrect, but it is also unlikely to be simply a duplicate of the dp 102 mode. Maybe moving it from a separate select into a read-only attribute of the vacuum would be better until its purpose is better understood.
  3. I can try forcing polling on the missing dps - so far this has only been tried for smartplugs, and there is some possibility that it can cause problems, but worth a try.
antonio1475 commented 1 year ago

I see... thank you.

DP 117 is called Time in the API logs, but Clean Mode in Debug Device (Tuya Cloud), same as 102. However, 102 changes including NILL when paused and findsta when returning to dock, while 117 only changes/stays with the last actual clean mode. 117 doesn't seem actually related to timing.

I scheduled a cleaning in the app and this showed up in Tuya Cloud device logs, but that DPS ("Timing" doesn't exist/show in the dropdown. It's not 117 either. image I think this (Timing/Schedule) is to be disregarded for HA, since the app has various options for it that don't appear to have linked DPS.

I re-added the device with your latest commit and:

  1. Program & Time appear as attributes, as expected.
  2. Entity status is still ERROR.
  3. force: true doesn't seem to poll Fan Speed or the Materials life. However, although Fan speed is not polled when the vacuum starts, it updates if it's changed via the app :+1:
  4. Mode selection is gone. I see that you added 117 both as Program and as Time attributes, but removed 102/117 as Mode Select in config, so mode select is not possible. Adding it back at the end but with 102 works wonders and updates automatically:
  - entity: select
    name: Clean mode
    icon: "mdi:form-dropdown"
    category: config
    dps:
      - id: 102
        type: string
        name: option
        optional: true
        mapping:
          - dps_val: clean_auto
            value: Auto
          - dps_val: clean_random
            value: Random
          - dps_val: clean_wall
            value: Wall follow
          - dps_val: clean_spot
            value: Clean spot
          - dps_val: clean_sroom
            value: Clean room
          - dps_val: find_sta
            value: Return to base

At this point everything is great except the entity status being ERROR most of the time (which doesn't show in the logs either...), which kind of impacts the vacuum card, but it's not a big deal since the Status field (attribute) can be used for the important stuff, and the HA Vacuum services work.

You've done so much more than I thought possible, thank you so much. I wouldn't want you wasting more time on this, just maybe add back the Mode selection :smile:

Thanks again!

antonio1475 commented 1 year ago

Hi again 😄

I might have "fixed" it (at least for my device):

I edited vacuum.py around line 105 (property state) from:

    @property
    def state(self):
        """Return the state of the vacuum cleaner."""
        status = self.status
        if self._error_dps and self._error_dps.get_value(self._device) != 0:
            return STATE_ERROR
        elif status in [SERVICE_RETURN_TO_BASE, "returning"]:
            return STATE_RETURNING
        elif status in ["standby", "charging"]:
            return STATE_DOCKED
        elif self._power_dps and not self._power_dps.get_value(self._device):
            return STATE_DOCKED
        elif self._active_dps and not self._active_dps.get_value(self._device):
            return STATE_DOCKED
        else:
            return STATE_CLEANING

to:

    @property
    def state(self):
        """Return the state of the vacuum cleaner."""
        status = self.status
        if status in ["standby"]:
            return STATE_IDLE
        elif status in ["paused"]:
            return STATE_PAUSED
        elif status in ["cleaning", "cleaning_complete"]:
            return STATE_CLEANING
        elif status in [SERVICE_RETURN_TO_BASE, "returning"]:
            return STATE_RETURNING
        elif status in ["charging", "charged"]:
            return STATE_DOCKED
        else:
            return STATE_ERROR

I also imported STATE_PAUSED and STATE_IDLE at the top of the file from (homeassistant.components.vacuum import), after looking at the HA Vacuum Valid States to make use of them (eg. now when pausing, the option is "Resume Cleaning" instead of "Start Cleaning").

I know that this might not be valid for all vacuums, but just sharing what I did in case you want to look at it.

image image image

Thank you so much for everything 😃

antonio1475 commented 1 year ago

Hi. I don't mean to bother, but just fyi, with the changes in the tuya-local 2023.4.2:

  1. Status is no longer Error, but it stays as Docked. No Cleaning nor Paused, so the entity button doesn't change, battery icon is always charging, vacuum-card doesn't work, etc. Maybe because vacuum.py is using power and active dps to report Docked and it's not very compatible with my device.
  2. Mode selection is still missing - it was removed in some commit ago.

Anyway I'll leave my 2 working files here compared to tuya-local 2023.4.2 (original on left):

  1. vacuum.py: https://www.textcompare.org/yaml/?id=644f8683a443163b1ce2718c
  2. mellerware: https://www.textcompare.org/yaml/?id=644f8769a443163b1ce271ac

For now I'll just replace them every update, takes only a minute.

Thanks again! Best regards 😄

make-all commented 1 year ago

Mode selection is available using the "vacuum.send_command" service. Some third party vacuum cards have a fixed list of commands they recognise and put buttons on the card for, but you should be able to add buttons to the UI for any command.

For status, I will look at the logic. But it might help to get a snapshot of the dps when the vacuum is operating so I can understand what is going wrong here.