Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Device Type - Robot Mower #134

Closed
Whytey opened this issue May 21, 2022 · 7 comments
Closed

New Device Type - Robot Mower #134

Whytey opened this issue May 21, 2022 · 7 comments
Labels
documentation Improvements or additions to documentation tuya_device Support for specific Tuya Devices

Comments

@Whytey
Copy link
Contributor

Whytey commented May 21, 2022

Hi,

I have a Tuya Robot Mower and am hoping to create a Home-Assistant integration for it.

I originally intended to use the tuya-iot-python-sdk module but it was very limited in what functionality it would provide.

Using tinytuya, I get more data and avoid the round-trip to the cloud! Whilst I can set some values against the device I haven't found the magic required to command the mower to start

d.status()
{'dps': {'6': 100, '101': 'STANDBY', '102': 0, '103': 'MOWER_LEAN', '104': True, '105': 3, '106': 1111, '114': 'AutoMode'}}
dps read/write values comment
6 r 0-100 Battery
101 r (??) STANDBY/MOWING/CHARGING/EMERGENCY/LOCKED/PAUSED/PARK/CHARGING_WITH_TASK_SUSPEND/FIXED_MOWING Provides state - can't seem to command state using this
102 ?? ?? Unknown
103 r MOWER_LEAN/MOWER_EMERGENCY/MOWER_UI_LOCKED Provides sub-states for when the mower is in EMERGENCY
104 r/w True/False Should we work in the rain?
105 r/w/ 1-12 How many hours to run for when started manually
106 ?? ?? Unknown
114 ?? ?? Unknown

I also seem to get additional dpcode's report unsolicited:

dps purpose example
110 ?? 'status': [{'110': 'AIiIiIgBiIiIiAKIiIiIA4iIiIgEiIiIiAWIiIiIBoiIiIg='}]
111 ?? 'status': [{'111': 'Ylxw+RRiXG/nFGJVvhsUYlW9/wJiVb30AmJJefACYkl5zAJiSXm/AmJJWowCAAAAAAA='}]
112 Report of mower working time after work has completed 'status': [{'112': 'YoJb5wAAKK4BYoDkWAAAQOUBYn+SygAABUABYn5JAwAADcsBYn5ITQAAAEYBYn5IEQAAADwBYn5H4QAAADwBYn5HtQAAADwBYn5HigAAADwBYn5HYAAAADwB'}]
113 ??? 'status': [{'113': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='}]

When I queried the cloud for the functions available to this device category this is what was reported (though I am unsure how to map the 'code' here to a 'dps' ID):

/v1.0/iot-03/categories/gcj/functions:

[
    {
        "code": "mode",
        "desc": "mode",
        "name": "mode",
        "type": "Enum",
        "values": '{"range":["standby","random","smart","wall_follow","spiral","chargego"]}',
    },
    {
        "code": "battery_percentage",
        "desc": "battery percentage",
        "name": "battery percentage",
        "type": "Integer",
        "values": '{"unit":"%","min":0,"max":100,"scale":0,"step":1}',
    },
    {
        "code": "switch_go",
        "desc": "switch go",
        "name": "switch go",
        "type": "Boolean",
        "values": "{}",
    },
    {
        "code": "direction_control",
        "desc": "direction control",
        "name": "direction control",
        "type": "Enum",
        "values": '{"range":["forward","backward","turn_left","turn_right","stop"]}',
    },
    {
        "code": "switch",
        "desc": "switch",
        "name": "switch",
        "type": "Boolean",
        "values": "{}",
    },
]

I am at a loss for how to progress to issue commands to this device. I have tried using Wireshark and the android emulator without success but I am not very competent at the low level messaging stuff.

I am intending to issue a pull-request for the data I have discovered, should it help anyone else - I assume this would be welcome?

Thanks.

@jasonacox
Copy link
Owner

Here is what I would try to get the DPS values that control the action. First run a monitoring loop (see below) then use the local control (if the robot has one) or app to command the robot to start running. Watch the monitoring loop. Hopefully these state changes will show up in the monitoring loop.

import tinytuya

d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
d.set_version(3.3)
d.set_socketPersistent(True)

print(" > Send Initial Request for Status < ")
payload = d.generate_payload(tinytuya.DP_QUERY)
d.send(payload)

print(" > Begin Monitoring Loop <")
while(True):
    # See if any data is available
    data = d.receive()
    print('Received Payload: %r' % data)

    # Send keyalive heartbeat to stay connected
    print(" > Send Heartbeat Ping < ")
    payload = d.generate_payload(tinytuya.HEART_BEAT)
    d.send(payload)

And yes, please feel free to submit a pull request for the DPS values you discover! Thanks for opening thing. I had no idea there was a Tuya mower!

@Whytey
Copy link
Contributor Author

Whytey commented May 21, 2022

Thanks Jason, will work up the PR for the Mower type.

I have already trialled what you suggested using the Tuya app for control. Here is the output from a slightly modified monitoring loop (removes heartbeat noise and adds a timestamp):

2022/05/21-21:31:03 - Received Payload: {'dps': {'6': 100, '101': 'STANDBY', '102': 0, '103': 'MOWER_LEAN', '104': True, '105': 5, '106': 1111, '114': 'AutoMode'}}
2022/05/22-09:47:33 - Received Payload: {'dps': {'101': 'MOWING'}, 't': 1653176852}
2022/05/22-09:47:38 - Received Payload: {'dps': {'101': 'PAUSED'}, 't': 1653176857}
2022/05/22-09:47:40 - Received Payload: {'dps': {'101': 'STANDBY'}, 't': 1653176860}
2022/05/22-09:47:41 - Received Payload: {'dps': {'112': 'YooGswAAADwBYokDzAAAADwBYoghiAAAADwBYogGCAAAACICYogF6gAAADwBYogFvgAAADwBYodcxgAAcIQBYoYw5wAARlQBYoOE4gAAQxQBYoJb5wAAKK4B'}, 't': 1653176860}

Here we see that I :

  1. Command the mower to start (101)
  2. Command the mower to pause (101)
  3. Cancel the mowing session (101)
  4. Receive a job-report (112)

Maybe I am doing something completely wrong but I can't just ask it to start mowing by issuing something like:
d.set_value(101, "MOWING")

@jasonacox
Copy link
Owner

jasonacox commented May 22, 2022

Hi @Whytey - I suspect you may have done this already to get the original table you posted, but just in case it would be interesting to see the results from getdps():

import tinytuya

# Connect to Tuya Cloud using IoT Credentials - see tinytuya.json
c = tinytuya.Cloud(
        apiRegion="us", 
        apiKey="xxxxxxxxxxxxxxxxxxxx", 
        apiSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
        apiDeviceID="xxxxxxxxxxxxxxxxxxID")

# download DPS mapping from Tuya - DeviceID of Mower
print(c.getdps(apiDeviceID))

# these may also be interesting
print(c.getproperties(apiDeviceID))
print(c.getfunctions(apiDeviceID))

I have poked around the https://developer.tuya.com/ site to see if there is anything on robotic mowers. I found this: https://developer.tuya.com/en/demo/grass-mower and wonder if you can see your mower in the Tuya IoT platform and if it shows more details about controllable DPs.

@Whytey
Copy link
Contributor Author

Whytey commented May 22, 2022

Yeah, unfortunately, the cloud data is even more limited.

c.getdps(MOWER_DEVICE_ID)
{'result': {'category': 'gcj', 'functions': [{'code': 'battery_percentage', 'dp_id': 6, 'type': 'Integer', 'values': '{"unit":"%","min":0,"max":100,"scale":0,"step":1}'}], 'status': [{'code': 'battery_percentage', 'dp_id': 6, 'type': 'Integer', 'values': '{"unit":"%","min":0,"max":100,"scale":0,"step":1}'}]}, 'success': True, 't': 1653196496973, 'tid': '1eebdd4bd98e11eca914e276ec45657f'}

It was the same result when using the official tuya-iot-python-sdk to get this data.

I have noted the similarities with robot vacuums and reviewed that demo mower project but I am not sure how to proceed. I am actually thinking of poking Tuya support but I think they might not be interested in helping.

@Whytey
Copy link
Contributor Author

Whytey commented May 24, 2022

Hi @jasonacox . Success!!!!

I have finally been able to discover the secret sauce for being able to control the mower (plus determine what most of the other DPS codes were for). In case it helps yourself or others in the future, the Zigbee2MQTT provides the instructions for it- https://www.zigbee2mqtt.io/advanced/support-new-devices/03_find_tuya_data_points.html#_9-find-your-data-point .

In my case, I need to send DPS 115 with one of PauseWork/CancelWork/StartMowing/StartReturnStation values to the mower.

FYI, I am still planning to prepare a pull request for adding this data to tinytuya.
FYI, I should probably make you aware of my project which is leveraging your great work. https://github.com/Whytey/pymoebot

@jasonacox
Copy link
Owner

jasonacox commented May 27, 2022

Excellent work @Whytey !!! I suspect the Find your Data Point link will be a great reference for others too. Thanks for sharing!

Please do feel free to submit a PR for the data point. I'll add your project as a link.

Great job! 😀

@uzlonewolf
Copy link
Collaborator

uzlonewolf commented Jun 16, 2022

I suspect the Find your Data Point link will be a great reference for others too.

And I just discovered that you can get a list of all data points at once by opening DevTools after step 7 but before step 8 - once you click the "Device Logs" tab (step 8) the first "list" request will contain all the data points in the DevTools 'Preview' tab. It would have been nice if I had discovered this before looking up all 32 of my data points one at a time 🤣

@jasonacox jasonacox added the tuya_device Support for specific Tuya Devices label Aug 21, 2022
@jasonacox jasonacox added the documentation Improvements or additions to documentation label Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation tuya_device Support for specific Tuya Devices
Projects
None yet
Development

No branches or pull requests

3 participants