tinytuya
                                
                                 tinytuya copied to clipboard
                                
                                    tinytuya copied to clipboard
                            
                            
                            
                        Smart Energy meter
Hello, I have 2 smart energy meter, the first one has a firmware version 1.0.2 and the second is in 1.1.17. The first one is working fine and I can get the current and power with tinytuya.
The second one return with tinytuya import tinytuya
PLUGID = 'nzexeqam9qulajbf' PLUGIP = '192.168.0.94' PLUGKEY = 'XXXXXXX' PLUGVERS = '3.3'
d = tinytuya.OutletDevice(PLUGID, PLUGIP, PLUGKEY) d.set_version(3.3) data = d.status() print('set_status() result %r' % data)
set_status() result {'dps': {'1': 133, '10': 0, '16': True, '18': '111111111111'}}
Field '1' correspond to the total energy consumption but I can not see the real time power or the current consumption.
It seems to be linked to a newer firmware. Do you plan a new upgrade to this firmware?
Hi @dpoitou-tlse - It looks like tinytuya is communicating with your device, but the DPS indexes are new or unique to this energy meter.  I don't think this is a firmware issue.  It could require a different command to get the full DPS payload.
What results from the device do you get with python -m tinytuya wizard?
Also, try something like this to see if the meter is sending back data over time (let it run for several loops):
import tinytuya
d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
d.set_version(3.3)
d.set_socketPersistent(True)
print(" > Send Request for Status < ")
payload = d.generate_payload(tinytuya.DP_QUERY)
d.send(payload)
print(" > Begin Monitor Loop <")
while(True):
    # See if any data is available
    data = d.receive()
    print('Received Payload: %r' % data)
    # Send keyalive heartbeat
    print(" > Send Heartbeat Ping < ")
    payload = d.generate_payload(tinytuya.HEART_BEAT)
    d.send(payload)
You could also add this as part of the loop after you try that:
    print(" > Send Request for Status < ")
    payload = d.generate_payload(tinytuya.DP_QUERY)
    d.send(payload)
    # See if any data is available
    data = d.receive()
    print('Received Payload: %r' % data)
    # the UPDATEDPS command request DPS index updates - depending on what index you need, add them here
    print(" > Send DPS Update Request < ")
    payload = d.generate_payload(tinytuya.UPDATEDPS,['18','19','20'])
    d.send(payload)
    
    # See if any data is available
    data = d.receive()
    print('Received Payload: %r' % data)
Hello, Thanks o lot for your response.
Hi @dpoitou-tlse https://github.com/dpoitou-tlse - It looks like tinytuya is communicating with your device, but the DPS indexes are new or unique to this energy meter. I don't think this is a firmware issue. It could require a different command to get the full DPS payload.
I have no idea but the real time value of power and current are available in smart life app. The 2 energy meter that I have are the same, i.e. the name are ZMAi-90 one the 2 modules
That is the reason why I suspected a firmware issue as the one for the « piscine » is not responding...
What results from the device do you get with python -m tinytuya wizard?
    "name": "Compteur piscine",
    "id": "bfb9b29bca25f99a69aqla",
    "key": « XXXXXX »
and ... [Compteur piscine] - 192.168.0.94 - No Response
The other one gives [Compteur PAC] - 192.168.0.40 - On - DPS: {'1': True, '2': 0, '4': 233, '5': 301, '6': 2389}
I tried your python example but it seems that it is not working...
Also, try something like this to see if the meter is sending back data over time (let it run for several loops):
import tinytuya
d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY') d.set_version(3.3) d.set_socketPersistent(True)
print(" > Send Request for Status < ") payload = d.generate_payload(tinytuya.DP_QUERY) d.send(payload) 11 print(" > Send Request for Status < ") 12 payload = d.generate_payload(tinytuya.DP_QUERY) ---> 13 d.send(payload) 14 15 print(" > Begin Monitor Loop <")
AttributeError: 'OutletDevice' object has no attribute 'send'
print(" > Begin Monitor Loop <") while(True): # See if any data is available data = d.receive()
AttributeError                            Traceback (most recent call last)
AttributeError: 'OutletDevice' object has no attribute 'receive'
print('Received Payload: %r' % data) # Send keyalive heartbeat print(" > Send Heartbeat Ping < ") payload = d.generate_payload(tinytuya.HEART_BEAT) d.send(payload)You could also add this as part of the loop after you try that:
print(" > Send Request for Status < ") payload = d.generate_payload(tinytuya.DP_QUERY) d.send(payload) # See if any data is available data = d.receive() print('Received Payload: %r' % data) # the UPDATEDPS command request DPS index updates - depending on what index you need, add them here print(" > Send DPS Update Request < ") payload = d.generate_payload(tinytuya.UPDATEDPS,['18','19','20']) d.send(payload) # See if any data is available data = d.receive() print('Received Payload: %r' % data)
Tanks for your help
Damien
Correct, while the 2 energy meter devices seem to be the same, the firmware does tell us that they are different and possibly slightly different models. Does it show a firmware update is available?
The "No response" from the wizard is concerning.  Does that always happen?   That can be caused by having the SmartLife app open when you try to run the wizard.  Many Tuya devices will not allow more than one thing to connect to it at a time.  The SmartLIfe app will always work because it uses the TuyaCloud to get that information.  In your prior example, you show a response of set_status() result {'dps': {'1': 133, '10': 0, '16': True, '18': '111111111111'}} which indicates it does communicate unless I misunderstood.
For the loop test - you need update to the latest version of tinytuya which is 1.2.6.
python -m pip install --upgrade tinytuya
Try the loop test to see what additional information you can get. If nothing, try adding debug - add this after import:
tinytuya.set_debug(True)
Hello, I retested the wizard and I got a response [Compteur piscine] - 192.168.0.93 - Off - DPS: {u'1': 4009, u'10': 0, u'18': u'111111111111', u'16': True}
The loop test works with the update and gives
Send Request for Status < Begin Monitor Loop < Received Payload: {'dps': {'1': 4012, '10': 0, '16': True, '18': '111111111111'}} Send Heartbeat Ping < Send Request for Status < Received Payload: {'dps': {'1': 4012, '10': 0, '16': True, '18': '111111111111'}} Send DPS Update Request < Received Payload: {'dps': {'6': 'CWAAAPkAAC0='}, 't': 1623960544} Received Payload: None Send Heartbeat Ping < Send Request for Status < Received Payload: {'dps': {'1': 4012, '10': 0, '16': True, '18': '111111111111'}} Send DPS Update Request < Received Payload: {'dps': {'1': 4013}, 't': 1623960549} Received Payload: None Send Heartbeat Ping < Send Request for Status < Received Payload: {'dps': {'1': 4013, '10': 0, '16': True, '18': '111111111111'}} Send DPS Update Request < Received Payload: {'dps': {'6': 'CWIAAPsAAC0='}, 't': 1623960559} Received Payload: None Send Heartbeat Ping < Send Request for Status < Received Payload: {'dps': {'1': 4013, '10': 0, '16': True, '18': '111111111111'}} Send DPS Update Request < Received Payload: None Received Payload: {'dps': {'6': 'CWQAAP4AAC4='}, 't': 1623960574} Send Heartbeat Ping < Send Request for Status < Received Payload: {'dps': {'1': 4013, '10': 0, '16': True, '18': '111111111111'}} Send DPS Update Request < Received Payload: None Received Payload: None Send Heartbeat Ping < Send Request for Status < Received Payload: {'dps': {'1': 4013, '10': 0, '16': True, '18': '111111111111'}} Send DPS Update Request < Received Payload: {'dps': {'6': 'CV4AAPoAAC0='}, 't': 1623960589}
I understate that I can get only the energy consumption but not the real time power…
Maybe I need to buy another one to get the informations that I cant but how to know if I would have the correct firmware...
Le 16 juin 2021 à 04:50, Jason Cox @.***> a écrit :
Correct, while the 2 energy meter devices seem to be the same, the firmware does tell us that they are different and possibly slightly different models. Does it show a firmware update is available?
The "No response" from the wizard is concerning. Does that always happen? That can be caused by having the SmartLife app open when you try to run the wizard. Many Tuya devices will not allow more than one thing to connect to it at a time. The SmartLIfe app will always work because it uses the TuyaCloud to get that information. In your prior example, you show a response of set_status() result {'dps': {'1': 133, '10': 0, '16': True, '18': '111111111111'}} which indicates it does communicate unless I misunderstood.
For the loop test - you need update to the latest version of tinytuya https://pypi.org/project/tinytuya/ which is 1.2.6.
python -m pip install --upgrade tinytuya Try the loop test to see what additional information you can get. If nothing, try adding debug - add this after import:
tinytuya.set_debug(True) — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jasonacox/tinytuya/issues/55#issuecomment-861995589, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANELQPGLCFYMVK4XRA2B4MLTTAGNZANCNFSM46VJAIUA.
I would ask the seller/manufacturer if they intend to fix the firmware or if they can provide the mapping for these DPS data points. The DPS values they are using aren't standard for Tuya devices. I suspect that there may be something in DPS index 6. The changing values there may actually be encoded power data:
{'dps': {'6': 'CWAAAPkAAC0='}, 't': 1623960544}
{'dps': {'6': 'CWIAAPsAAC0='}, 't': 1623960559}
{'dps': {'6': 'CWQAAP4AAC4='}, 't': 1623960574}
{'dps': {'6': 'CV4AAPoAAC0='}, 't': 1623960589}
It just seems very strange that they would send it that way. Those 12 characters could be a base64 encoding of two or four integer values. Looking at one of them, I don't know that it helps:
import base64
# Take one of the DPS values 
text = 'CV4AAPoAAC0='
field = text.encode('ascii')
print("input text = %s" % text)
# Decode base64
z =base64.b64decode(field)
print("decoded = %r" % z)
# Convert to binary - 64 bits
zbin = "".join(["{:08b}".format(x) for x in z])
print("%s converts to %s" % (text, zbin))
# Assume 2 int values are in the 64 bits
a = zbin[:32]
b = zbin[32:]
print("----- 2 values -----")
print("a = %s (%d)" % (a,int(a, 2)))
print("b = %s (%d)" % (b,int(b, 2)))
# Assume 4 int vlaues are in the 64 bits
a = zbin[:16]
b = zbin[16:32]
c = zbin[32:48]
d = zbin[48:64]
print("----- 4 values -----")
print("a = %s (%d)" % (a,int(a, 2)))
print("b = %s (%d)" % (b,int(b, 2)))
print("c = %s (%d)" % (c,int(c, 2)))
print("d = %s (%d)" % (d,int(d, 2)))
output:
input text = CV4AAPoAAC0=
decoded = b'\t^\x00\x00\xfa\x00\x00-'
CV4AAPoAAC0= converts to 0000100101011110000000000000000011111010000000000000000000101101
----- 2 values -----
a = 00001001010111100000000000000000 (157155328)
b = 11111010000000000000000000101101 (4194304045)
----- 4 values -----
a = 0000100101011110 (2398)
b = 0000000000000000 (0)
c = 1111101000000000 (64000)
d = 0000000000101101 (45)
Hello I tried to buy another one form Amazon, even if I paid it 2 times more than the previous one from aliexpress the result is the same.
The return for the wizard is [WiFi Smart Meter 2] - 192.168.0.139 - Off - DPS: {u'1': 11, u'10': 0, u'18': u'111111111111', u'16': True}
And the firmware version is the same (1.1.71)
I don’t know how to use the converted 64bits text. It could correspond also to some alarms included in the energy meter.
The best way to make it working would be to get an answer from the manufacturer I think…
Best regards
Le 20 juin 2021 à 08:28, Jason Cox @.***> a écrit :
I would ask the seller/manufacturer if they intend to fix the firmware or if they can provide the mapping for these DPS data points. The DPS values they are using aren't standard for Tuya devices. I suspect that there may be something in DPS index 6. The changing values there may actually be encoded power data:
{'dps': {'6': 'CWAAAPkAAC0='}, 't': 1623960544} {'dps': {'6': 'CWIAAPsAAC0='}, 't': 1623960559} {'dps': {'6': 'CWQAAP4AAC4='}, 't': 1623960574} {'dps': {'6': 'CV4AAPoAAC0='}, 't': 1623960589} It just seems very strange that they would send it that way. Those 12 characters could be a base64 encoding of two integer values. Looking at one of them, I don't know that it helps:
import base64
Take one of the DPS values
text = 'CV4AAPoAAC0=' field = text.encode('ascii') print("input text = %s" % text)
Decode base64
z =base64.b64decode(field) print("decoded = %r" % z)
Convert to binary - 64 bits
zbin = "".join(["{:08b}".format(x) for x in z]) print("%s converts to %s" % (text, zbin))
Assume 2 int values are in the 64 bits
a = zbin[:32] b = zbin[32:] print("a = %s (%d)" % (a,int(a, 2))) print("b = %s (%d)" % (b,int(b, 2))) output:
input text = CV4AAPoAAC0= decoded = b'\t^\x00\x00\xfa\x00\x00-' CV4AAPoAAC0= converts to 0000100101011110000000000000000011111010000000000000000000101101 a = 00001001010111100000000000000000 (157155328) b = 11111010000000000000000000101101 (4194304045)
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jasonacox/tinytuya/issues/55#issuecomment-864506722, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANELQPCQR7QONLZSZENVHXTTTWDCHANCNFSM46VJAIUA.
The 4 values interpretation seems a possiblity, as 2398 is likely to be a voltage (239.8V). The encoding seems similar to this device: https://github.com/home-assistant/core/pull/63519
I tried to add local support for the above device based on tinytuya, but also wasn't getting the relevant fields for realtime measurements, useful to know that it can be explicitly requested with the UPDATEDPS command.
Hi, I have the same circuit breaker (Smart Electric Meter). My output:
Received Payload: {'dps': {'1': 1182, '10': 0, '16': True, '18': '111111111111'}} --> 11,82 kwh total energy used since start --> 16:true --> switch is On
input text = CQYAB/oAAXQ= decoded = b'\t\x06\x00\x07\xfa\x00\x01t' CQYAB/oAAXQ= converts to 0000100100000110000000000000011111111010000000000000000101110100 ----- 2 values ----- a = 00001001000001100000000000000111 (151388167) b = 11111010000000000000000101110100 (4194304372) ----- 4 values ----- a = 0000100100000110 (2310) b = 0000000000000111 (7) c = 1111101000000000 (64000) d = 0000000101110100 (372)
--> a= Voltage *10 --> b=? --> c=? --> d= Current usage in Watt
Trough the api explorer on iot.tuya.com I get the follow result from this device { "result": [ { "code": "forward_energy_total", "value": 1182 }, { "code": "phase_a", "value": "{"electricCurrent":2.03,"power":0.372,"voltage":230.1}" }, { "code": "fault", "value": 0 }, { "code": "switch", "value": true }, { "code": "alarm_set_2", "value": "[{"alarmCode":"overcurrent","doAction":false,"threshold":"20"},{"alarmCode":"ammeter_overvoltage","doAction":false,"threshold":"264"},{"alarmCode":"under_voltage","doAction":false,"threshold":"150"}]" }, { "code": "meter_id", "value": "111111111111" } ], "success": true, "t": 1642688146838 } Hope this helps
If you look at the code for decoding raw ElectricityTypeData the current and power are 3 bytes each. So V = 0000100100000110 = 2310 /10.0 => 231.0V I = 000000000000011111111010 = 2042 mA P = 000000000000000101110100 = 372 W
Great find @make-all ! So the story looks like this: Payload = Voltage (2 bytes) + Current (3 bytes) + Power (3 bytes).
@Utopia69 You could use this code:
import base64
# Take one of the DPS values 
text = 'CQYAB/oAAXQ=='
field = text.encode('ascii')
print("input text = %s" % text)
# Decode base64
z =base64.b64decode(field)
print("decoded = %r" % z)
# Convert to binary - 64 bits
zbin = "".join(["{:08b}".format(x) for x in z])
print("%s converts to %s" % (text, zbin))
# Assume 3 int values are in the 64 bits
a = zbin[:16]
b = zbin[16:40]
c = zbin[40:64]
print("----- 3 values -----")
print("V = %s = %0.1f V" % (a,int(a, 2)/10.0))
print("I = %s = %d mA" % (b,int(a, 2)))
print("P = %s = %d W" % (c,int(c, 2)))
Output:
input text = CQYAB/oAAXQ==
decoded = b'\t\x06\x00\x07\xfa\x00\x01t'
CQYAB/oAAXQ== converts to 0000100100000110000000000000011111111010000000000000000101110100
----- 3 values -----
V = 0000100100000110 = 231.0 V
I = 000000000000011111111010 = 2310 mA
P = 000000000000000101110100 = 372 W
I ran the same for one of @dpoitou-tlse examples:
input text = CV4AAPoAAC0=
decoded = b'\t^\x00\x00\xfa\x00\x00-'
CV4AAPoAAC0= converts to 0000100101011110000000000000000011111010000000000000000000101101
----- 3 values -----
V = 0000100101011110 = 239.8 V
I = 000000000000000011111010 = 2398 mA
P = 000000000000000000101101 = 45 W
If this seems right, we can add a helper function to TinyTuya to convert the 64-bit payload to the 3 values (V, I and P). Let me know...
I own a Hiking DDS-238-4 W with the Tuya firmware. I use it with the LocalTuya integration. I can use the data from DPS1 and 16 for total energy and controlling the relay but I need help in reading the Voltage, Current and Power. I can read DPS6 but the data is encoded as in the example above. I wanted to make templates for these but I am lost with converting your code to jinja. If someone who is knowledgeable enough could do this and share it that would be great. Thank you!
Hi jasonacox thanks a lot for your help! Sorry for the long delay I made a pause on my smart home projet in 2022...
I used your code and it works very well thanks!
I opened a new topic to decode a flood sensor here : https://github.com/jasonacox/tinytuya/discussions/338
Regards