From 601d4b2c54c74972364b0b83c50954d1fe46fcfa Mon Sep 17 00:00:00 2001 From: Felix-Pi <49276377+Felix-Pi@users.noreply.github.com> Date: Tue, 9 Aug 2022 16:46:07 +0200 Subject: [PATCH 1/2] Implemented SocketDevice --- tinytuya/Contrib/SocketDevice.py | 100 +++++++++++++++++++++++++++++++ tinytuya/Contrib/__init__.py | 3 +- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tinytuya/Contrib/SocketDevice.py diff --git a/tinytuya/Contrib/SocketDevice.py b/tinytuya/Contrib/SocketDevice.py new file mode 100644 index 00000000..2d800743 --- /dev/null +++ b/tinytuya/Contrib/SocketDevice.py @@ -0,0 +1,100 @@ +# TinyTuya Outlet Device +# -*- coding: utf-8 -*- +""" + Python module to interface with Tuya Socket Devices + + Author: Felix Pieschka + For more information see https://github.com/Felix-Pi + + Local Control Classes + SocketDevice(dev_id, address, local_key=None, dev_type='default', version=3.3) + + Functions + SocketDevice: + get_energy_consumption() + get_current() + get_power() + get_get_voltage() + Inherited + json = status() # returns json payload + set_version(version) # 3.1 [default] or 3.3 + set_socketPersistent(False/True) # False [default] or True + set_socketNODELAY(False/True) # False or True [default] + set_socketRetryLimit(integer) # retry count limit [default 5] + set_socketTimeout(timeout) # set connection timeout in seconds [default 5] + set_dpsUsed(dps_to_request) # add data points (DPS) to request + add_dps_to_request(index) # add data point (DPS) index set to None + set_retry(retry=True) # retry if response payload is truncated + set_status(on, switch=1, nowait) # Set status of switch to 'on' or 'off' (bool) + set_value(index, value, nowait) # Set int value of any index. + heartbeat(nowait) # Send heartbeat to device + updatedps(index=[1], nowait) # Send updatedps command to device + turn_on(switch=1, nowait) # Turn on device / switch # + turn_off(switch=1, nowait) # Turn off + set_timer(num_secs, nowait) # Set timer for num_secs + set_debug(toggle, color) # Activate verbose debugging output + set_sendWait(num_secs) # Time to wait after sending commands before pulling response + detect_available_dps() # Return list of DPS available from device + generate_payload(command, data) # Generate TuyaMessage payload for command with data + send(payload) # Send payload to device (do not wait for response) + receive() +""" + +from ..core import Device + + +class SocketDevice(Device): + """ + Represents a Tuya based Socket + + Args: + dev_id (str): The device id. + address (str): The network address. + local_key (str, optional): The encryption key. Defaults to None. + version (float, optional): Tuya Device Version (look at Device.set_version) + """ + + DPS_STATE = '1' + DPS_CURRENT = '18' + DPS_POWER = '19' + DPS_VOLTAGE = '20' + + def __init__(self, dev_id, address, local_key="", dev_type="default", version=None): + super(SocketDevice, self).__init__(dev_id, address, local_key, dev_type) + + if version is not None: + self.set_version(version) + + def get_energy_consumption(self): + data = self.status() + return {**self.get_current(data), **self.get_power(data), **self.get_voltage(data)} + + def get_current(self, status_data=None): + if status_data is None: + status_data = self.status() + + current = status_data['dps'][self.DPS_CURRENT] + + return {'current_raw': current, + 'current_fmt': str(current) + ' mA', } + + def get_power(self, status_data=None): + if status_data is None: + status_data = self.status() + + power = status_data['dps'][self.DPS_POWER] / 10 + + return {'power_raw': power, + 'power_fmt': str(power) + ' W', } + + def get_voltage(self, status_data=None): + if status_data is None: + status_data = self.status() + + voltage = status_data['dps'][self.DPS_VOLTAGE] / 10 + + return {'voltage_raw': voltage, + 'voltage_fmt': str(voltage) + ' V'} + + def get_state(self): + return {'on': self.status()['dps'][self.DPS_STATE]} diff --git a/tinytuya/Contrib/__init__.py b/tinytuya/Contrib/__init__.py index b07ef986..260adb40 100644 --- a/tinytuya/Contrib/__init__.py +++ b/tinytuya/Contrib/__init__.py @@ -1,5 +1,6 @@ from .ThermostatDevice import ThermostatDevice from .IRRemoteControlDevice import IRRemoteControlDevice +from .SocketDevice import SocketDevice -DeviceTypes = ["ThermostatDevice", "IRRemoteControlDevice"] +DeviceTypes = ["ThermostatDevice", "IRRemoteControlDevice", "SocketDevice"] From ecf5d03e64838e60adaf95767958ef0307f78aec Mon Sep 17 00:00:00 2001 From: Felix-Pi <49276377+Felix-Pi@users.noreply.github.com> Date: Tue, 9 Aug 2022 17:01:51 +0200 Subject: [PATCH 2/2] Updated readme --- tinytuya/Contrib/README.md | 15 +++++++++++++++ tinytuya/Contrib/SocketDevice.py | 1 + 2 files changed, 16 insertions(+) diff --git a/tinytuya/Contrib/README.md b/tinytuya/Contrib/README.md index daf86d75..9d098e06 100644 --- a/tinytuya/Contrib/README.md +++ b/tinytuya/Contrib/README.md @@ -34,6 +34,21 @@ In addition to the built-in `OutletDevice`, `BulbDevice` and `CoverDevice` devic ir.send_button(button) ``` +### SocketDevice + +* SocketDevice - A community-contributed Python module to add support for Tuya WiFi smart sockets +* Author: [Felix Pieschka](https://github.com/Felix-Pi) + + ```python + # Example usage of community contributed device modules + from tinytuya.Contrib import SocketDevice + + socket = SocketDevice('abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc', version=3.3) + + print(socket.get_energy_consumption()) + print(socket.get_state()) + ``` + ## Submit Your Device * We welcome new device modules! diff --git a/tinytuya/Contrib/SocketDevice.py b/tinytuya/Contrib/SocketDevice.py index 2d800743..83289ef6 100644 --- a/tinytuya/Contrib/SocketDevice.py +++ b/tinytuya/Contrib/SocketDevice.py @@ -15,6 +15,7 @@ get_current() get_power() get_get_voltage() + get_state() Inherited json = status() # returns json payload set_version(version) # 3.1 [default] or 3.3