jasonacox / tinytuya

Python API for Tuya WiFi smart devices using a direct local area network (LAN) connection or the cloud (TuyaCloud API).
MIT License
868 stars 157 forks source link

How to set up alarms [ TinyTuya Server ] #436

Open JRB202 opened 6 months ago

JRB202 commented 6 months ago

How could I use Tinytuya to send this command in order to set the value for over current alarm to this device :

https://www.amazon.fr/gp/product/B09FPD3LMZ/

From devices.json : "category": "dlq", "product_name": "breaker", "product_id": "hz2o2tnezttmmx15", "biz_type": 18, "model": "ZC01W",

It is apparently a device22

The hhttp request to send is : POST: /v1.0/electric-energy/{device_id}/actions/current-limit

Tua doc Source : See : https://developer.tuya.com/en/docs/cloud/c8a3368324?id=Kbhjkflky2j9s

jasonacox commented 6 months ago

Hi @JRB202 , What DPS values did you get from it when you ran the wizard (python -m tinytuya wizard)? I recommend looking at each of those and use the iot.tuya.com portal to investigate them. You can then manipulate those values with tinytuya's set_value(index, value, nowait) function.

JRB202 commented 6 months ago

Hi Jason, The problem is that DPS integer and value available from tinytuya server are not including all the entries available in dps mapping also returned by same tinytuya server command /status/ tinytuya :

Some of the most interesting code values, IDs are missing (Present in Mapping but not in returned data) : Example : code Phase_a, ID 6 containing voltage, current and load current values code alarm_set_1, ID 17 containing Alarm parameters (Low and high voltage threshold, max load and current values , ... code alarm_set_2, ID 18 also containing rest of Alarm parameters.

So no way to get and set values for alarm_set_1 and alarm_set_2 using /set//code/value tinytuya server command

That's why I am sadly turning to a direct access to tuya API as temporary workaround. Then I am currently working on an intermediary solution based on tinytuya to get and send values using tuya API I am currently prototyping a temporary solution using : https://github.com/jasonacox/tinytuya/blob/master/examples/cloud.py waiting for a fix to this tinytuya discrepancies between Code Values and mappings

Related hardware : (Open DIN switch) https://www.amazon.fr/gp/product/B09FPD3LMZ/

From devices.json : "category": "dlq", "product_name": "breaker", "product_id": "hz2o2tnezttmmx15", "biz_type": 18, "model": "ZC01W", See below for detailed results of /status/ for

Dps ID value available from /status/ :

dps 1 9 11 12 13 14 15 16 19 21

dps_mapping 1
code "total_forward_energy" type "Integer" values {…} 6
code "phase_a" type "Raw" values {} 9
code "fault" type "Bitmap" values {…} 11
code "switch_prepayment" type "Boolean" values {} 12
code "energy_reset" type "Enum" values {…} 13
code "balance_energy" type "Integer" values {…} 14
code "charge_energy" type "Integer" values {…} 15
code "leakage_current" type "Integer" values {…} 16
code "switch" type "Boolean" values {} 17
code "alarm_set_1" type "Raw" values {} 18
code "alarm_set_2" type "Raw" values {} 19
code "breaker_number" type "String" values '{"maxlen":255}' 21
code "leakagecurr_test" type "Boolean" values {}

jasonacox commented 6 months ago

Thanks, @JRB202 . I didn't realize this was related to the tinytuya server prototype. It was more of an experiment I set up to help test the tinytuya library. I'm happy that you are using it! I know it is missing a lot. Can you give me a screenshot of what you are seeing from the server and suggest what we should see?

JRB202 commented 6 months ago

Last finding about this subject :

Finding 1) This python3 code based cloud.py example is giving good mappings and values for the same device :

import tinytuya tinytuya.set_debug(False)

c = tinytuya.Cloud( apiRegion=APIREGION, apiKey=APIKEY, apiSecret=APISECRET, apiDeviceID=APIDEVICEID)

id = APIDEVICEID

Display Properties of Device

result = c.getproperties(id) print("Properties of device:\n", result)

Display DPS IDs of Device

result = c.getdps(id) print("DPS IDs of device:\n", result)

Display Status of Device

result = c.getstatus(id) print("Status of device:\n", result)

So, good new : tinytuya is clearly able to access to all DPS code and values !

Finding 2) I also se that tuya-raw.json file contains good mapping and all corresponding values for this device.

So there is clearly something in tinytuya server code which is abusively eliminating some of the DPS ID values (6 17 18) after reading of this tuya-raw.json correct file.

You can trust my own full support to help any one to dig into this issue.

jasonacox commented 6 months ago

Hi @JRB202 , the code you have is using the Tuya Cloud to get the DPS. The tinytuya server uses your local area network (talking to the device directly) to get the DPS. There are times that the devices don't send all their DPS values on the local network. Can you run a scan to see what is being picked up on the local network?

# If you haven't done so already, run wizard
python3 -m tinytuya wizard

# Scan
python3 -m tinytuya scan
JRB202 commented 6 months ago

Wizard already successfully run during installation process of this device. As already said : tuya-raw.json file generated by wizard contains good mappings and ALL CORRESPONDING VALUES for this device. So complete data is acquired by tinytuya from device using tuya cloud

But local acccess to device : d = tinytuya.OutletDevice(PLUGID, PLUGIP, PLUGKEY) data = d.status() print(data) do not return some of the mapping values :
codes 'alarm_set_1', 'alarm_set_2' (and 'phase_a' values are missing in d.status() values So the loss of these code values is located in this OutletDevice object code for this status method

Then I intentionally use cloud access as temporary workaround because local tinytuya server /status/ do not return values for : code 'alarm_set_1', 'alarm_set_2' (and 'phase_a') and I need to set up values for code 'alarm_set_1', 'alarm_set_2' and read phase_a to gain access to voltage, current and load values

JRB202 commented 6 months ago

Hi Jason,

I found a way to set locally and via Tuya cloud the alarms in this device using this code :

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

payload=d.generate_payload(tinytuya.CONTROL, {'17': Alarm1ValB64.decode('ascii'), '18': Alarm2ValB64.decode('ascii')}) print("Payload\n:", payload) result = d._send_receive(payload) print("Results\n:", result)

This confirm that : The loss of these 'alarm_set_1', 'alarm_set_2' and 'phase_a' code values by server /status/ command is located in OutletDevice object code for this status method. I will now try to examine this part of your code ...

JRB202 commented 6 months ago

Hi Jason,

After examination of Tinituya code, I think the problem comes from 'def detect_available_dps' method of tinytuya core.py This method is querying Device ports in a brute force way See 1618 line to 1646 For unknown reasons this device22 is not answering on all available ports and omit to respond at least on port 6 (phase_a), 17 and 18 ('alarm_set_1', 'alarm_set_2')

On the other way, the file tuya-raw.json as generated by wizard is containing all really available ports and correct values including Alarm definition ports (17 and 18 for this device) and port 6 phase_a which contains load, voltage and current real time values.

Conclusion : I suggest to change strategy in 'def detect_available_dps from brute force attempts to reading of a dictionnary of mappings for each device that must be stored in a file that can be generated with all correct mapping values during wizard execution while generating tuya-raw.json as wizard is already reading good mapping values.

This would make Tinytuya more resilient to different behaviors of tuya devices, as these devices mappings files would come directly from Tuya Cloud based device definitions while executing wizard.

JRB202 commented 6 months ago

After checks I see that devices.json contains all mappings. So tinytuya core.py def detect_available_dps function could be rewritten to just read this file to get good mappings.

jasonacox commented 6 months ago

That's a great suggestion! I would add that it could try to use the devices.json mapping first and if that doesn't exist, fall back to the forced detection method. Would you or someone else like to try to add this change to the code and submit a PR?

JRB202 commented 6 months ago

Jason, I do not feel comfortable with writing part of Tinytuya code But I am definitively ready to test any update in code especially in server code !