1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#!/usr/bin/env python3
"""Wrapper functions for dealing with TPLink devices. Based on code
written by Lubomir Stroetmann and Copyright 2016 softScheck GmbH which
was covered by the Apache 2.0 license:
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Modifications by Scott Gasch Copyright 2020-2022 also released under
the Apache 2.0 license as required by the license (see above).
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import json
import logging
import os
import re
import subprocess
import sys
from struct import pack
from typing import Dict, Optional
import logging_utils
from decorator_utils import timeout
logger = logging.getLogger(__name__)
@timeout(10.0, use_signals=False, error_message="Timed out waiting for tplink.py")
def tplink_command(command: str) -> bool:
result = os.system(command)
signal = result & 0xFF
if signal != 0:
msg = f'{command} died with signal {signal}'
logger.warning(msg)
logging_utils.hlog(msg)
return False
else:
exit_value = result >> 8
if exit_value != 0:
msg = f'{command} failed, exited {exit_value}'
logger.warning(msg)
logging_utils.hlog(msg)
return False
logger.debug('%s succeeded.', command)
return True
@timeout(10.0, use_signals=False, error_message="Timed out waiting for tplink.py")
def tplink_get_info(cmd: str) -> Optional[Dict]:
logger.debug('Getting tplink device status via "%s"', cmd)
try:
out = subprocess.getoutput(cmd)
logger.debug('RAW OUT> %s', out)
out = re.sub("Sent:.*\n", "", out)
out = re.sub("Received: *", "", out)
info = json.loads(out)["system"]["get_sysinfo"]
logger.debug("%s", json.dumps(info, indent=4, sort_keys=True))
return info
except Exception as e:
logger.exception(e)
print(out, file=sys.stderr)
return None
def encrypt(string: str) -> bytes:
"""Encryption and Decryption of TP-Link Smart Home Protocol.
XOR Autokey Cipher with starting key = 171
>>> " ".join(hex(b).replace('0x', '') for b in encrypt('{"system":{"get_sysinfo":{}}}'))
'0 0 0 1d d0 f2 81 f8 8b ff 9a f7 d5 ef 94 b6 d1 b4 c0 9f ec 95 e6 8f e1 87 e8 ca f0 8b f6 8b f6'
"""
key = 171
result = pack(">I", len(string))
for i in string:
a = key ^ ord(i)
key = a
result += bytes([a])
return result
def decrypt(string: bytes) -> str:
"""Opposite of encrypt (above).
>>> b = encrypt('hi, mom')
>>> s = decrypt(b[4:])
>>> s
'hi, mom'
"""
key = 171
result = ""
for i in string:
a = key ^ i
key = i
result += chr(a)
return result
if __name__ == '__main__':
import doctest
doctest.testmod()
|