tplinkrouterc6u 4.1.1__tar.gz → 4.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/PKG-INFO +3 -1
  2. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/README.md +2 -0
  3. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/setup.py +1 -1
  4. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/test/test_client.py +4 -1
  5. tplinkrouterc6u-4.2.0/test/test_client_c1200.py +141 -0
  6. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u/client.py +78 -3
  7. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u/dataclass.py +0 -1
  8. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u.egg-info/PKG-INFO +3 -1
  9. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u.egg-info/SOURCES.txt +1 -0
  10. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/LICENSE +0 -0
  11. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/setup.cfg +0 -0
  12. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/test/__init__.py +0 -0
  13. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/test/test_client_deco.py +0 -0
  14. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/test/test_client_mr.py +0 -0
  15. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u/__init__.py +0 -0
  16. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u/encryption.py +0 -0
  17. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u/enum.py +0 -0
  18. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u/exception.py +0 -0
  19. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u.egg-info/dependency_links.txt +0 -0
  20. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u.egg-info/requires.txt +0 -0
  21. {tplinkrouterc6u-4.1.1 → tplinkrouterc6u-4.2.0}/tplinkrouterc6u.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tplinkrouterc6u
3
- Version: 4.1.1
3
+ Version: 4.2.0
4
4
  Summary: TP-Link Router API
5
5
  Home-page: https://github.com/AlexandrErohin/TP-Link-Archer-C6U
6
6
  Author: Alex Erohin
@@ -227,6 +227,7 @@ or you have TP-link C1200 V2 or similar router you need to get web encrypted pas
227
227
  - Archer AX10 v1.0
228
228
  - Archer AX12 v1.0
229
229
  - Archer AX20 v1.0
230
+ - Archer AX20 v3.0
230
231
  - Archer AX21 v1.20
231
232
  - Archer AX23 v1.0
232
233
  - Archer AX50 v1.0
@@ -237,6 +238,7 @@ or you have TP-link C1200 V2 or similar router you need to get web encrypted pas
237
238
  - Archer AX73 V1
238
239
  - Archer AX75 V1
239
240
  - Archer AXE75 V1
241
+ - Archer AXE16000
240
242
  - Archer AX3000 V1
241
243
  - Archer AX6000 V1
242
244
  - Archer AX11000 V1
@@ -206,6 +206,7 @@ or you have TP-link C1200 V2 or similar router you need to get web encrypted pas
206
206
  - Archer AX10 v1.0
207
207
  - Archer AX12 v1.0
208
208
  - Archer AX20 v1.0
209
+ - Archer AX20 v3.0
209
210
  - Archer AX21 v1.20
210
211
  - Archer AX23 v1.0
211
212
  - Archer AX50 v1.0
@@ -216,6 +217,7 @@ or you have TP-link C1200 V2 or similar router you need to get web encrypted pas
216
217
  - Archer AX73 V1
217
218
  - Archer AX75 V1
218
219
  - Archer AXE75 V1
220
+ - Archer AXE16000
219
221
  - Archer AX3000 V1
220
222
  - Archer AX6000 V1
221
223
  - Archer AX11000 V1
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="tplinkrouterc6u",
8
- version="4.1.1",
8
+ version="4.2.0",
9
9
  author="Alex Erohin",
10
10
  author_email="alexanderErohin@yandex.ru",
11
11
  description="TP-Link Router API",
@@ -425,7 +425,8 @@ class TestTPLinkClient(unittest.TestCase):
425
425
  response_game_accelerator = '''
426
426
  {
427
427
  "data": [
428
- {"mac": "06:82:9d:2b:8f:c6", "deviceTag":"2.4G", "isGuest":false, "ip":"192.168.1.186", "deviceName":"name1"},
428
+ {"mac": "06:82:9d:2b:8f:c6", "deviceTag":"2.4G", "isGuest":false, "ip":"192.168.1.186", "deviceName":"name1",
429
+ "uploadSpeed":12, "downloadSpeed":77},
429
430
  {"mac": "fb:90:b8:2a:8a:b1", "deviceTag":"iot_2.4G", "isGuest":false, "ip":"192.168.1.187", "deviceName":"name2"},
430
431
  {"mac": "54:b3:a2:f7:be:ea", "deviceTag":"iot_5G", "isGuest":false, "ip":"192.168.1.188", "deviceName":"name3"},
431
432
  {"mac": "3c:ae:e1:83:94:9d", "deviceTag":"iot_6G", "isGuest":false, "ip":"192.168.1.189", "deviceName":"name4"}
@@ -524,6 +525,8 @@ class TestTPLinkClient(unittest.TestCase):
524
525
  self.assertEqual(status.devices[2].hostname, 'UNKNOWN')
525
526
  self.assertEqual(status.devices[2].packets_sent, 450333)
526
527
  self.assertEqual(status.devices[2].packets_received, 4867482)
528
+ self.assertEqual(status.devices[2].up_speed, 12)
529
+ self.assertEqual(status.devices[2].down_speed, 77)
527
530
  self.assertIsInstance(status.devices[3], Device)
528
531
  self.assertEqual(status.devices[3].type, Connection.IOT_2G)
529
532
  self.assertEqual(status.devices[3].macaddr, 'FB-90-B8-2A-8A-B1')
@@ -0,0 +1,141 @@
1
+ import unittest
2
+ import json
3
+ from tplinkrouterc6u import (
4
+ TplinkC1200Router,
5
+ Connection,
6
+ ClientException
7
+ )
8
+
9
+ class TestTPLinkC1200Client(unittest.TestCase):
10
+
11
+ def test_set_led_on(self) -> None:
12
+
13
+ response_led_general_read = '''
14
+ {
15
+ "enable": "off",
16
+ "time_set": "yes",
17
+ "ledpm_support": "yes"
18
+ }
19
+ '''
20
+
21
+ response_led_general_write = '''
22
+ {
23
+ "enable": "on",
24
+ "time_set": "yes",
25
+ "ledpm_support": "yes"
26
+ }
27
+ '''
28
+
29
+ class TPLinkRouterTest(TplinkC1200Router):
30
+ def request(self, path: str, data: str,
31
+ ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
32
+ if path == 'admin/ledgeneral?form=setting&operation=read':
33
+ return json.loads(response_led_general_read)
34
+ if path == 'admin/ledgeneral?form=setting&operation=write':
35
+ self.captured_path = path
36
+ return json.loads(response_led_general_write)
37
+ raise ClientException()
38
+
39
+ client = TPLinkRouterTest('', '')
40
+
41
+ client.set_led(True)
42
+
43
+ expected_path = "admin/ledgeneral?form=setting&operation=write"
44
+
45
+ self.assertEqual(client.captured_path, expected_path)
46
+
47
+ def test_set_led_off(self) -> None:
48
+
49
+ response_led_general_read = '''
50
+ {
51
+ "enable": "on",
52
+ "time_set": "yes",
53
+ "ledpm_support": "yes"
54
+ }
55
+ '''
56
+
57
+ response_led_general_write = '''
58
+ {
59
+ "enable": "off",
60
+ "time_set": "yes",
61
+ "ledpm_support": "yes"
62
+ }
63
+ '''
64
+
65
+ class TPLinkRouterTest(TplinkC1200Router):
66
+ def request(self, path: str, data: str,
67
+ ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
68
+ if path == 'admin/ledgeneral?form=setting&operation=read':
69
+ return json.loads(response_led_general_read)
70
+ elif path == 'admin/ledgeneral?form=setting&operation=write':
71
+ self.captured_path = path
72
+ return json.loads(response_led_general_write)
73
+ raise ClientException()
74
+
75
+ client = TPLinkRouterTest('', '')
76
+
77
+ client.set_led(False)
78
+
79
+ expected_path = "admin/ledgeneral?form=setting&operation=write"
80
+
81
+ self.assertEqual(client.captured_path, expected_path)
82
+
83
+ def test_led_status(self) -> None:
84
+
85
+ response_led_general_read = '''
86
+ {
87
+ "enable": "on",
88
+ "time_set": "yes",
89
+ "ledpm_support": "yes"
90
+ }
91
+ '''
92
+
93
+ class TPLinkRouterTest(TplinkC1200Router):
94
+ def request(self, path: str, data: str,
95
+ ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
96
+ if path == 'admin/ledgeneral?form=setting&operation=read':
97
+ return json.loads(response_led_general_read)
98
+ raise ClientException()
99
+
100
+ client = TPLinkRouterTest('', '')
101
+
102
+ led_status = client.get_led()
103
+ self.assertTrue(led_status)
104
+
105
+
106
+ def test_set_wifi(self) -> None:
107
+
108
+ class TPLinkRouterTest(TplinkC1200Router):
109
+ def request(self, path: str, data: str,
110
+ ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
111
+
112
+ self.captured_path = path
113
+ self.captured_data = data
114
+
115
+ client = TPLinkRouterTest('', '')
116
+ client.set_wifi(
117
+ Connection.HOST_5G,
118
+ enable=True,
119
+ ssid="TestSSID",
120
+ hidden="no",
121
+ encryption="WPA3-PSK",
122
+ psk_version="2",
123
+ psk_cipher="AES",
124
+ psk_key="testkey123",
125
+ hwmode="11ac",
126
+ htmode="VHT20",
127
+ channel=36,
128
+ txpower="20",
129
+ disabled_all="no"
130
+ )
131
+
132
+ expected_data = ("operation=write&enable=on&ssid=TestSSID&hidden=no&encryption=WPA3-PSK&"
133
+ "psk_version=2&psk_cipher=AES&psk_key=testkey123&hwmode=11ac&"
134
+ "htmode=VHT20&channel=36&txpower=20&disabled_all=no")
135
+ expected_path = f"admin/wireless?form=wireless_5g&{expected_data}"
136
+
137
+ self.assertEqual(client.captured_path, expected_path)
138
+ self.assertEqual(client.captured_data, expected_data)
139
+
140
+ if __name__ == '__main__':
141
+ unittest.main()
@@ -317,6 +317,7 @@ class TplinkBaseRouter(AbstractRouter, TplinkRequest):
317
317
 
318
318
  def get_status(self) -> Status:
319
319
  data = self.request('admin/status?form=all&operation=read', 'operation=read')
320
+
320
321
  status = Status()
321
322
  status._wan_macaddr = macaddress.EUI48(data['wan_macaddr']) if 'wan_macaddr' in data else None
322
323
  status._lan_macaddr = macaddress.EUI48(data['lan_macaddr'])
@@ -386,6 +387,9 @@ class TplinkBaseRouter(AbstractRouter, TplinkRequest):
386
387
  status.iot_clients_total = 0
387
388
  status.iot_clients_total += 1
388
389
 
390
+ devices[item['mac']].down_speed = item.get('downloadSpeed')
391
+ devices[item['mac']].up_speed = item.get('uploadSpeed')
392
+
389
393
  for item in self.request('admin/wireless?form=statistics', 'operation=load'):
390
394
  if item['mac'] not in devices:
391
395
  status.wifi_clients_total += 1
@@ -576,9 +580,9 @@ class TPLinkDecoClient(TplinkEncryption, AbstractRouter):
576
580
 
577
581
  ip = item['ip'] if item.get('ip') else '0.0.0.0'
578
582
  device = Device(conn,
579
- macaddress.EUI48(item['mac']),
580
- ipaddress.IPv4Address(ip),
581
- base64.b64decode(item['name']).decode())
583
+ macaddress.EUI48(item['mac']),
584
+ ipaddress.IPv4Address(ip),
585
+ base64.b64decode(item['name']).decode())
582
586
  device.down_speed = item.get('down_speed')
583
587
  device.up_speed = item.get('up_speed')
584
588
  devices.append(device)
@@ -706,6 +710,77 @@ class TplinkC1200Router(TplinkBaseRouter):
706
710
  self._logger.error(error)
707
711
  raise ClientException(error)
708
712
 
713
+ def set_led(self, enable: bool) -> None:
714
+ current_state = (self.request('admin/ledgeneral?form=setting&operation=read', 'operation=read')
715
+ .get('enable', 'off') == 'on')
716
+ if current_state != enable:
717
+ self.request('admin/ledgeneral?form=setting&operation=write', 'operation=write')
718
+
719
+ def get_led(self) -> bool:
720
+
721
+ data = self.request('admin/ledgeneral?form=setting&operation=read', 'operation=read')
722
+ led_status = data.get('enable') if 'enable' in data else None
723
+ if led_status == 'on':
724
+ return True
725
+ elif led_status == 'off':
726
+ return False
727
+ else:
728
+ return None
729
+
730
+ def set_wifi(self, wifi: Connection, enable: bool = None, ssid: str = None, hidden: str = None,
731
+ encryption: str = None, psk_version: str = None, psk_cipher: str = None, psk_key: str = None,
732
+ hwmode: str = None, htmode: str = None, channel: int = None, txpower: str = None,
733
+ disabled_all: str = None) -> None:
734
+ values = {
735
+ Connection.HOST_2G: 'wireless_2g',
736
+ Connection.HOST_5G: 'wireless_5g',
737
+ Connection.HOST_6G: 'wireless_6g',
738
+ Connection.GUEST_2G: 'guest_2g',
739
+ Connection.GUEST_5G: 'guest_5g',
740
+ Connection.GUEST_6G: 'guest_6g',
741
+ Connection.IOT_2G: 'iot_2g',
742
+ Connection.IOT_5G: 'iot_5g',
743
+ Connection.IOT_6G: 'iot_6g',
744
+ }
745
+
746
+ value = values.get(wifi)
747
+ if not value:
748
+ raise ValueError(f"Invalid Wi-Fi connection type: {wifi}")
749
+
750
+ if enable is None and ssid is None and hidden is None and encryption is None and psk_version is None and psk_cipher is None and psk_key is None and hwmode is None and htmode is None and channel is None and txpower is None and disabled_all is None:
751
+ raise ValueError("At least one wireless setting must be provided")
752
+
753
+ data = "operation=write"
754
+
755
+ if enable is not None:
756
+ data += f"&enable={'on' if enable else 'off'}"
757
+ if ssid is not None:
758
+ data += f"&ssid={ssid}"
759
+ if hidden is not None:
760
+ data += f"&hidden={hidden}"
761
+ if encryption is not None:
762
+ data += f"&encryption={encryption}"
763
+ if psk_version is not None:
764
+ data += f"&psk_version={psk_version}"
765
+ if psk_cipher is not None:
766
+ data += f"&psk_cipher={psk_cipher}"
767
+ if psk_key is not None:
768
+ data += f"&psk_key={psk_key}"
769
+ if hwmode is not None:
770
+ data += f"&hwmode={hwmode}"
771
+ if htmode is not None:
772
+ data += f"&htmode={htmode}"
773
+ if channel is not None:
774
+ data += f"&channel={channel}"
775
+ if txpower is not None:
776
+ data += f"&txpower={txpower}"
777
+ if disabled_all is not None:
778
+ data += f"&disabled_all={disabled_all}"
779
+
780
+ path = f"admin/wireless?form={value}&{data}"
781
+
782
+ self.request(path, data)
783
+
709
784
 
710
785
  class TPLinkMRClient(AbstractRouter):
711
786
  REQUEST_RETRIES = 3
@@ -11,7 +11,6 @@ class Firmware:
11
11
  self.model = model
12
12
  self.firmware_version = firmware
13
13
 
14
-
15
14
  @dataclass
16
15
  class Device:
17
16
  def __init__(self, type: Connection, macaddr: macaddress, ipaddr: ipaddress, hostname: str) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tplinkrouterc6u
3
- Version: 4.1.1
3
+ Version: 4.2.0
4
4
  Summary: TP-Link Router API
5
5
  Home-page: https://github.com/AlexandrErohin/TP-Link-Archer-C6U
6
6
  Author: Alex Erohin
@@ -227,6 +227,7 @@ or you have TP-link C1200 V2 or similar router you need to get web encrypted pas
227
227
  - Archer AX10 v1.0
228
228
  - Archer AX12 v1.0
229
229
  - Archer AX20 v1.0
230
+ - Archer AX20 v3.0
230
231
  - Archer AX21 v1.20
231
232
  - Archer AX23 v1.0
232
233
  - Archer AX50 v1.0
@@ -237,6 +238,7 @@ or you have TP-link C1200 V2 or similar router you need to get web encrypted pas
237
238
  - Archer AX73 V1
238
239
  - Archer AX75 V1
239
240
  - Archer AXE75 V1
241
+ - Archer AXE16000
240
242
  - Archer AX3000 V1
241
243
  - Archer AX6000 V1
242
244
  - Archer AX11000 V1
@@ -3,6 +3,7 @@ README.md
3
3
  setup.py
4
4
  test/__init__.py
5
5
  test/test_client.py
6
+ test/test_client_c1200.py
6
7
  test/test_client_deco.py
7
8
  test/test_client_mr.py
8
9
  tplinkrouterc6u/__init__.py
File without changes