Skip to content

Commit

Permalink
Add support for Wyze Locks including locking and unlocking
Browse files Browse the repository at this point in the history
See: SecKatie/ha-wyzeapi#135

Thank to [KevinVoell](https://github.com/KevinVoell) for providing direction on how to implement signing code.
  • Loading branch information
Joshua Mulliken committed Apr 24, 2021
1 parent 93f4bc8 commit 6225075
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 3 deletions.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[metadata]
# replace with your username:
name = wyzeapy
version = 0.0.15
version = 0.0.16
author = Mulliken LLC
author_email = [email protected]
description = Python client for private Wyze API
Expand Down
71 changes: 69 additions & 2 deletions src/wyzeapy/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import time
import uuid
from enum import Enum
from typing import List
from typing import List, Dict

import requests

Expand Down Expand Up @@ -55,6 +55,10 @@ class ResponseCodes(Enum):
ACCESS_TOKEN_ERROR = "2001"


class ResponseCodesLock(Enum):
SUCCESS = 0


SWITCHABLE_DEVICES = [DeviceTypes.LIGHT, DeviceTypes.MESH_LIGHT, DeviceTypes.PLUG]


Expand Down Expand Up @@ -137,6 +141,51 @@ def check_for_errors(response_json):
else:
raise UnknownApiError(response_json)

@staticmethod
def check_for_errors_lock(response_json):
if response_json['ErrNo'] != ResponseCodes.SUCCESS.value:
if response_json['code'] == ResponseCodes.PARAMETER_ERROR.value:
raise ParameterError
elif response_json['code'] == ResponseCodes.ACCESS_TOKEN_ERROR.value:
raise AccessTokenError
else:
raise UnknownApiError(response_json)

app_key = "275965684684dbdaf29a0ed9"
app_secret = "4deekof1ba311c5c33a9cb8e12787e8c"

def postMethod(self, str, str2, map):
str4 = str
str3 = str2
map2 = map

return self.getTransferParam(map2, str3, str4, "post")

def getTransferParam(self, map, str4, str2, str3):
map["accessToken"] = self.access_token
map["key"] = self.app_key
map["timestamp"] = str(datetime.datetime.now().timestamp()).split(".")[0] + "000"
map["sign"] = self.getSignStr(str4, str3, map)
import json
print(json.dumps(map))
return map

def getSignStr(self, str, str2, map: Dict):
string_buf = str2 + str
for entry in sorted(map.keys()):
print(entry)
print(map[entry])
string_buf += entry + "=" + map[entry] + "&"

string_buf = string_buf[:-1]
print(string_buf)
string_buf += self.app_secret
import urllib.parse
urlencoded = urllib.parse.quote_plus(string_buf)
sign_str = hashlib.md5(urlencoded.encode()).hexdigest()
print(sign_str)
return sign_str

def get_object_list(self):
payload = {
"phone_system_type": PHONE_SYSTEM_TYPE,
Expand Down Expand Up @@ -316,4 +365,22 @@ def get_event_list(self, device: Device, count: int) -> dict:

self.check_for_errors(response_json)

return response_json
return response_json

def lock_control(self, device: Device, action: str):
sb2 = "https://yd-saas-toc.wyzecam.com/openapi/lock/v1/control"
str3 = "/openapi/lock/v1/control"

uuid = device.mac.split(".")[2]

hash_map = {
"uuid": uuid,
"action": action # "remoteLock" or "remoteUnlock"
}

payload = self.postMethod(sb2, str3, hash_map)

url = "https://yd-saas-toc.wyzecam.com/openapi/lock/v1/control"

response_json = requests.post(url, json=payload).json()
print(response_json)
8 changes: 8 additions & 0 deletions src/wyzeapy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ def turn_on(self, device: Device, extra_pids=None):
plist.extend(extra_pids)

self.client.run_action_list(device, plist)
elif device_type in [
DeviceTypes.LOCK
]:
self.client.lock_control(device, "remoteLock")
else:
raise ActionNotSupported(device_type.value)

Expand Down Expand Up @@ -148,6 +152,10 @@ def turn_off(self, device: Device, extra_pids=None):
plist.extend(extra_pids)

self.client.run_action_list(device, plist)
elif device_type in [
DeviceTypes.LOCK
]:
self.client.lock_control(device, "remoteUnlock")
else:
raise ActionNotSupported(device_type.value)

Expand Down

0 comments on commit 6225075

Please sign in to comment.