diff --git a/RELEASE.md b/RELEASE.md index 94c18aac..01124a29 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,9 @@ # RELEASE NOTES +## v1.6.7 - Unreleased + +* Added DoorbellDevice by @JonesMeUp in https://github.com/jasonacox/tinytuya/issues/162 + ## v1.6.6 - Updated Payload Dictionary and Command List * PyPI 1.6.6 diff --git a/examples/Contrib/DoorbellDevice-example.py b/examples/Contrib/DoorbellDevice-example.py new file mode 100644 index 00000000..969f547a --- /dev/null +++ b/examples/Contrib/DoorbellDevice-example.py @@ -0,0 +1,35 @@ +# TinyTuya IRRemoteControlDevice Example +# -*- coding: utf-8 -*- +""" + Python module to interface with Tuya WiFi smart devices + + Author: JonesMeUp + Tested: LSC-Bell 8S(AKV300_8M) + Note: Without hack the device can't be used offline. + With hack the DoorbellDevice is useless. + + For more information see https://github.com/jasonacox/tinytuya + https://github.com/jasonacox/tinytuya/issues/162 + +""" +import tinytuya +from tinytuya.Contrib import DoorbellDevice + +d = DoorbellDevice('abcdefghijklmnop123456', '192.168.178.25', + '1234567890123abc', 'device22') +d.set_version(3.3) +d.set_socketPersistent(True) # Keep socket connection open between commands + +d.set_volume(3) +d.set_motion_area(0, 5, 50, 50) +d.set_motion_area_switch(True) + +print(" > Begin Monitor Loop <") +while(True): + # See if any data is available + data = d.receive() + print('Data: %r' % data) + # Send keyalive heartbeat + print(" > Send Heartbeat Ping < ") + payload = d.generate_payload(tinytuya.HEART_BEAT) + d.send(payload) \ No newline at end of file diff --git a/tinytuya/Contrib/DoorbellDevice.py b/tinytuya/Contrib/DoorbellDevice.py new file mode 100644 index 00000000..b9df5d7a --- /dev/null +++ b/tinytuya/Contrib/DoorbellDevice.py @@ -0,0 +1,120 @@ +# TinyTuya Doorbell Device +# -*- coding: utf-8 -*- +""" + Python module to interface with Tuya WiFi smart devices + + Author: JonesMeUp + Tested: LSC-Bell 8S(AKV300_8M) + Note: Without hack the device can't be used offline. + With hack the DoorbellDevice is useless. + + For more information see https://github.com/jasonacox/tinytuya + https://github.com/jasonacox/tinytuya/issues/162 + +Offline Device + This DoorbellDevice works only if the device is online. Most stay + offline to preserve the battery. + + Local Control Classes + DoorbellDevice(dev_id, address, local_key=None, dev_type='default') + + Functions + DoorbellDevice: + set_basic_indicator(bool): + set_volume(1-10): + set_motion_area(x,y,lenX, lenY) + set_motion_area_switch(bool) +""" + +from ..core import Device + +class DoorbellDevice(Device): + """ + Represents a Tuya based Video-Doorbell. + + Args: + dev_id (str): The device id. + address (str): The network address. + local_key (str, optional): The encryption key. Defaults to None. + """ + DPS_2_STATE = { + "101": "basic_indicator", # Boolean (status indicator) + "103": "basic_flip", # Boolean (flip video vertically) + "104": "basic_osd", # Boolean (timestap on video) + "106": "motion_sensitivity", # Enum ["0","1","2"] (low, medium, high) + "108": "basic_nightvision", # Enum ["0","1","2"] (auto, off, on) + "109": "sd_storge", # String ["maxlen":255] (capacity|used|free) e.g: '258048|50176|207872' + "110": "sd_status", # Integer ["min":1,"max": 5,"scale":1,"step":1] + "111": "sd_format", # Boolean + "115": "movement_detect_pic", # Raw + "117": "sd_format_state", # Integer ["min":-20000,"max":20000,"scale":1,"step":1] + "134": "motion_switch", # Boolean (alarm on motion detection) + "136": "doorbell_active", # String ["maxlen":255] (doorbell was pressed) + "150": "record_switch", # Boolean (false = no recording) + "151": "record_mode", # Enum ["1","2"] (1=on event, 2=always) + "154": "doorbell_pic", # Raw (picture of the device) + "155": "doorbell_ring_exist", # Enum ["0","1"] + "156": "chime_ring_tune", # Enum ["1","2","3","4"] + "157": "chime_ring_volume", # Integer ["min":0,"max":100,"scale":1,"step":1] (chime is an extrenal gong [433MhZ]) + "160": "basic_device_volume", # Integer ["min":1,"max": 10,"scale":0,"step":1] + "165": "chime_settings", # Enum ["0","2","3"] + "168": "motion_area_switch", # Boolean (false = use full area) + "169": "motion_area", # String ["maxlen":255] (x, y, xlen, ylen) + "185": "alarm_message", # String + } + DPS_2_FUNC = { + "101": "basic_indicator", # Boolean + "103": "basic_flip", # Boolean + "104": "basic_osd", # Boolean + "106": "motion_sensitivity", # Enum ["0","1","2"] + "108": "basic_nightvision", # Enum ["0","1","2"] + "111": "sd_format", # Boolean + "134": "motion_switch", # Boolean + "150": "record_switch", # Boolean + "151": "record_mode", # Enum ["1","2"] + "155": "doorbell_ring_exist", # Enum ["0","1"] + "156": "chime_ring_tune", # Enum ["1","2","3","4"] + "157": "chime_ring_volume", # Integer ["min":0,"max":100,"scale":1,"step":1] + "160": "basic_device_volume", # Integer ["min":1,"max": 10,"scale":0,"step":1] + "165": "chime_settings", # Enum ["0","2","3"] + "168": "motion_area_switch", # Boolean + "169": "motion_area", # String ["maxlen":255] + } + + def __init__(self, dev_id, address, local_key="", dev_type="default"): + super(DoorbellDevice, self).__init__(dev_id, address, local_key, dev_type) + + def set_basic_indicator(self, val=True, nowait=False): + """ Set the basic incicator """ + self.set_value(101, bool(val), nowait) + + def set_volume(self, vol=10, nowait=False): + """ Set the doorbell volume """ + if vol < 3: + vol = 3 # Nothing to hear below 3 + if vol > 10: + vol = 10 + self.set_value(160, int(vol), nowait) + + def set_motion_area(self, x=0,y=0,xlen=50, ylen=100, nowait=False): + """ set the area of motion detection [%] """ + if x < 0: x = 0 + if y < 0: y = 0 + if x > 100: x = 100 + if y > 100: y = 100 + if xlen < 0: xlen = 0 + if ylen < 0: ylen = 0 + if xlen > 100: xlen = 100 + if ylen > 100: ylen = 100 + if x+xlen >100: + x = 25 + xlen = 75 + if y+ylen >100: + y = 25 + ylen = 75 + data = '{"num":1,"region0":{"x":'+str(x)+',"y":'+str(y)+',"xlen":'+str(xlen)+',"ylen":'+str(ylen)+'}}' + self.set_value(169, data, nowait) + + def set_motion_area_switch(self, useArea=False, nowait=False): + """ use the area of motion detection on/off """ + self.set_value(168, bool(useArea), nowait) diff --git a/tinytuya/Contrib/README.md b/tinytuya/Contrib/README.md index 9d098e06..f4f9974b 100644 --- a/tinytuya/Contrib/README.md +++ b/tinytuya/Contrib/README.md @@ -43,12 +43,42 @@ In addition to the built-in `OutletDevice`, `BulbDevice` and `CoverDevice` devic # Example usage of community contributed device modules from tinytuya.Contrib import SocketDevice - socket = SocketDevice('abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc', version=3.3) + socket = SocketDevice('abcdefghijklmnop123456', '172.28.321.475', '', version=3.3) print(socket.get_energy_consumption()) print(socket.get_state()) ``` - + +### DoorbellDevice + +* DoorbellDevice - A community-contributed Python module to add support for Tuya WiFi doorbells. +* Author: [JonesMeUp](https://github.com/jonesMeUp) +* Note: Most doorbells will not stay online (to preserve battery) so controlling them locally is difficult. + + ```python + import tinytuya + from tinytuya.Contrib import DoorbellDevice + + d = DoorbellDevice('abcdefghijklmnop123456', '192.168.178.25', + '1234567890123abc', 'device22') + d.set_version(3.3) + d.set_socketPersistent(True) # Keep socket connection open between commands + + d.set_volume(3) + d.set_motion_area(0, 5, 50, 50) + d.set_motion_area_switch(True) + + print(" > Begin Monitor Loop <") + while(True): + # See if any data is available + data = d.receive() + print('Data: %r' % data) + # Send keyalive heartbeat + print(" > Send Heartbeat Ping < ") + payload = d.generate_payload(tinytuya.HEART_BEAT) + d.send(payload) + ``` + ## Submit Your Device * We welcome new device modules! diff --git a/tinytuya/Contrib/__init__.py b/tinytuya/Contrib/__init__.py index 260adb40..047b1db7 100644 --- a/tinytuya/Contrib/__init__.py +++ b/tinytuya/Contrib/__init__.py @@ -2,5 +2,6 @@ from .ThermostatDevice import ThermostatDevice from .IRRemoteControlDevice import IRRemoteControlDevice from .SocketDevice import SocketDevice +from .DoorbellDevice import DoorbellDevice -DeviceTypes = ["ThermostatDevice", "IRRemoteControlDevice", "SocketDevice"] +DeviceTypes = ["ThermostatDevice", "IRRemoteControlDevice", "SocketDevice", "DoorbellDevice"]