Skip to content

Commit

Permalink
Adding support for Presence Detector Device like https://www.amazon.c…
Browse files Browse the repository at this point in the history
  • Loading branch information
mrioan authored and Mario committed Jan 29, 2024
1 parent 9036e93 commit d45473d
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 1 deletion.
133 changes: 133 additions & 0 deletions tinytuya/Contrib/PresenceDetectorDevice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
from tinytuya.core import Device
import time
import json

class PresenceDetectorDevice(Device):
"""
Represents a Tuya-based Presence Detector.
"""

DPS_KEY = "dps"
PRESENCE_KEY = "1"
SENSITIVITY_KEY = "2"
NEAR_DETECTION_KEY = "3"
FAR_DETECTION_KEY = "4"
AUTO_DETECT_RESULT_KEY = "6"
TARGET_DISTANCE_KEY = "9"
DETECTION_DELAY_KEY = "101"
FADING_TIME_KEY = "102"
LIGHT_SENSE_KEY = "104"

def __init__(self, *args, **kwargs):
# set the default version to 3.3 as there are no 3.1 devices
if 'version' not in kwargs or not kwargs['version']:
kwargs['version'] = 3.3
super(PresenceDetectorDevice, self).__init__(*args, **kwargs)

def status_json(self):
"""Wrapper around status() that replace DPS indices with human readable labels."""
status = self.status()
if "Error" in status:
return status
dps = status[self.DPS_KEY]
json_string = json.dumps({
"Presence": dps[self.PRESENCE_KEY],
"Sensitivity": dps[self.SENSITIVITY_KEY],
"Near detection": dps[self.NEAR_DETECTION_KEY],
"Far detection": dps[self.FAR_DETECTION_KEY],
"Checking result": dps[self.AUTO_DETECT_RESULT_KEY],
"Target distance": dps[self.TARGET_DISTANCE_KEY],
"Detection delay": dps[self.DETECTION_DELAY_KEY],
"Fading time": dps[self.FADING_TIME_KEY],
"Light sense": dps[self.LIGHT_SENSE_KEY]
})
return json_string

def status(self):
"""In some cases the status json we received is not the standard one with all the proper keys. We will re-try 5 to get the expected one"""
status = super().status()
if "Error" in status:
return status
dps = status[self.DPS_KEY]
retry = 5
while(retry > 0 and not self.PRESENCE_KEY in dps):
retry = retry - 1
status = super().status()
dps = status[self.DPS_KEY]
time.sleep(5)
return status

def get_presence_state(self):
"""Get the presence state of the Presence Detector.
Returns:
str: Presence state ("none" or "presence").
"""
status = self.status()
if "Error" in status:
return status
return status[self.DPS_KEY][self.PRESENCE_KEY]

def get_sensitivity(self):
"""Get the sensitivity level of the Presence Detector.
Returns:
int: Sensitivity level (0 to 9).
"""
status = self.status()
if "Error" in status:
return satus
return status[self.DPS_KEY][self.SENSITIVITY_KEY]

def set_sensitivity(self, sensitivity):
self.set_value(self.SENSITIVITY_KEY, sensitivity)

def get_near_detection(self):
"""Get the near detection distance of the Presence Detector.
Returns:
int: Near detection distance in meters.
"""
status = self.status()
if "Error" in status:
return satus
return status[self.DPS_KEY][self.NEAR_DETECTION_KEY]

def set_near_detection(self, distance):
self.set_value(self.NEAR_DETECTION_KEY, distance)

def get_far_detection(self):
"""Get the far detection distance of the Presence Detector.
Returns:
int: Far detection distance in meters.
"""
status = self.status()
if "Error" in status:
return satus
return status[self.DPS_KEY][self.FAR_DETECTION_KEY]

def set_far_detection(self, distance):
self.set_value(self.FAR_DETECTION_KEY, distance)

def get_checking_result(self):
"""Get the checking result of the Presence Detector.
Returns:
str: Checking result (one of ["checking", "check_success", "check_failure", "others", "comm_fault", "radar_fault"]).
"""
status = self.status()
if "Error" in status:
return satus
return status[self.DPS_KEY][self.AUTO_DETECT_RESULT_KEY]

def get_target_distance(self):
"""Get the closest target distance of the Presence Detector.
Returns:
int: Closest target distance in meters.
"""
status = self.status()
if "Error" in status:
return satus
return status[self.DPS_KEY][self.TARGET_DISTANCE_KEY]
46 changes: 46 additions & 0 deletions tinytuya/Contrib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,52 @@ In addition to the built-in `OutletDevice`, `BulbDevice` and `CoverDevice` devic
device.set_target_water_temp(28)
```

### PresenceDetectorDevice

* PresenceDetectorDevice - A community-contributed Python module to add support for Tuya WiFi smart presence detector device
* Author: [Mario Antollini](https://github.com/mrioan)
* Tested: [MmWave Human Presence Sensor](https://www.amazon.com/gp/product/B0BZCRNY14)

```python
from tinytuya.Contrib import PresenceDetectorDevice
from tinytuya import core
import time
import logging
import requests

log = logging.getLogger(__name__)
device_id = 'XXXX'
device_ip = 'YYYY'
local_key = 'ZZZZ'
iftt_url = "https://maker.ifttt.com/trigger/{webhook_name_here}/json/with/key/{key_here}"

def main():
setup()
run()

def setup():
global device
device = PresenceDetectorDevice(device_id, address=device_ip, local_key=local_key)
device.set_version(3.3)

def run():
log.info(" >>>> Begin Monitor Loop <<<< ")
while(True):
presence = device.get_presence_state()
if (presence == 'presence'):
log.info('ALERT! Presence detected!')
presence_detected_steps()
else:
log.debug('no presence, sleep...')
time.sleep(20)

def presence_detected_steps():
requests.post(iftt_url, json={})

if __name__ == "__main__":
main()
```

## Submit Your Device

* We welcome new device modules!
Expand Down
3 changes: 2 additions & 1 deletion tinytuya/Contrib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
from .ClimateDevice import ClimateDevice
from .AtorchTemperatureControllerDevice import AtorchTemperatureControllerDevice
from .InverterHeatPumpDevice import InverterHeatPumpDevice, TemperatureUnit, InverterHeatPumpMode, InverterHeatPumpFault
from .PresenceDetectorDevice import PresenceDetectorDevice

DeviceTypes = ["ThermostatDevice", "IRRemoteControlDevice", "SocketDevice", "DoorbellDevice", "ClimateDevice", "AtorchTemperatureControllerDevice", "InverterHeatPumpDevice"]
DeviceTypes = ["ThermostatDevice", "IRRemoteControlDevice", "SocketDevice", "DoorbellDevice", "ClimateDevice", "AtorchTemperatureControllerDevice", "InverterHeatPumpDevice", "PresenceDetectorDevice"]

0 comments on commit d45473d

Please sign in to comment.