tplinkrouterc6u 5.12.3__tar.gz → 5.13.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 (48) hide show
  1. {tplinkrouterc6u-5.12.3/tplinkrouterc6u.egg-info → tplinkrouterc6u-5.13.0}/PKG-INFO +12 -2
  2. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/README.md +11 -1
  3. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/setup.py +1 -1
  4. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_c6u.py +53 -20
  5. tplinkrouterc6u-5.13.0/test/test_client_c6u_v1_11.py +95 -0
  6. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_ex.py +80 -0
  7. tplinkrouterc6u-5.13.0/test/test_client_r.py +633 -0
  8. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_xdr.py +5 -0
  9. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/__init__.py +2 -1
  10. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/c6u.py +99 -1
  11. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/ex.py +10 -12
  12. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/mr.py +1 -1
  13. tplinkrouterc6u-5.13.0/tplinkrouterc6u/client/r.py +198 -0
  14. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/xdr.py +10 -1
  15. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/provider.py +4 -1
  16. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0/tplinkrouterc6u.egg-info}/PKG-INFO +12 -2
  17. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u.egg-info/SOURCES.txt +3 -0
  18. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/LICENSE +0 -0
  19. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/setup.cfg +0 -0
  20. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/__init__.py +0 -0
  21. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_c1200.py +0 -0
  22. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_c80.py +0 -0
  23. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_deco.py +0 -0
  24. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_mr.py +0 -0
  25. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_mr_200.py +0 -0
  26. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_re330.py +0 -0
  27. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_vr400v2.py +0 -0
  28. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/test/test_client_wdr.py +0 -0
  29. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/__init__.py +0 -0
  30. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/c1200.py +0 -0
  31. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/c5400x.py +0 -0
  32. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/c80.py +0 -0
  33. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/deco.py +0 -0
  34. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/mr200.py +0 -0
  35. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/re330.py +0 -0
  36. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/vr.py +0 -0
  37. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/vr400v2.py +0 -0
  38. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client/wdr.py +0 -0
  39. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/client_abstract.py +0 -0
  40. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/common/__init__.py +0 -0
  41. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/common/dataclass.py +0 -0
  42. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/common/encryption.py +0 -0
  43. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/common/exception.py +0 -0
  44. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/common/helper.py +0 -0
  45. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u/common/package_enum.py +0 -0
  46. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u.egg-info/dependency_links.txt +0 -0
  47. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u.egg-info/requires.txt +0 -0
  48. {tplinkrouterc6u-5.12.3 → tplinkrouterc6u-5.13.0}/tplinkrouterc6u.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tplinkrouterc6u
3
- Version: 5.12.3
3
+ Version: 5.13.0
4
4
  Summary: TP-Link Router API (supports also Mercusys Router)
5
5
  Home-page: https://github.com/AlexandrErohin/TP-Link-Archer-C6U
6
6
  Author: Alex Erohin
@@ -56,6 +56,7 @@ Python package for API access and management for TP-Link and Mercusys Routers. S
56
56
  ```python
57
57
  from tplinkrouterc6u import (
58
58
  TplinkRouterProvider,
59
+ TplinkRouterV1_11,
59
60
  TplinkRouter,
60
61
  TplinkC1200Router,
61
62
  TplinkC5400XRouter,
@@ -66,6 +67,7 @@ from tplinkrouterc6u import (
66
67
  TPLinkVR400v2Client,
67
68
  TPLinkEXClient, # Class for EX series routers which supports old firmwares with AES cipher CBC mode
68
69
  TPLinkEXClientGCM, # Class for EX series routers which supports AES cipher GCM mode
70
+ TPLinkRClient,
69
71
  TPLinkXDRClient,
70
72
  TPLinkDecoClient,
71
73
  TplinkC80Router,
@@ -83,7 +85,7 @@ router = TplinkRouterProvider.get_client('http://192.168.0.1', 'password')
83
85
  # If you have the TP-link C5400X or similar, you can use the TplinkC5400XRouter class instead of the TplinkRouter class.
84
86
  # Remember that the password for this router is different, here you need to use the web encrypted password.
85
87
  # To get web encrypted password, read Web Encrypted Password section
86
- # router = TplinkC5400XRouter('http://192.168.0.1','WebEncryptedPassword', Logger('test'))
88
+ # router = TplinkC5400XRouter('http://192.168.0.1','WebEncryptedPassword', logger: Logger('test'))
87
89
 
88
90
  try:
89
91
  router.authorize() # authorizing
@@ -372,6 +374,7 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
372
374
  - Deco P7
373
375
  - Deco X20
374
376
  - Deco X50 v1.3
377
+ - Deco X50-5G 1.20
375
378
  - Deco X55 1.0
376
379
  - Deco X60 V3
377
380
  - Deco X90
@@ -379,7 +382,10 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
379
382
  - Deco XE75PRO (v3.0)
380
383
  - EX511 v2.0
381
384
  - HX510 v1.0
385
+ - M8550 v1
386
+ - NE200-Outdoor v1.0
382
387
  - NX510v v1.0
388
+ - NX600 v2.0
383
389
  - TD-W9960 (v1, V1.20)
384
390
  - TL-MR100 v2.0
385
391
  - TL-MR105
@@ -388,10 +394,13 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
388
394
  - TL-MR150 v2
389
395
  - TL-MR6400 (v5, v5.3)
390
396
  - TL-MR6500v
397
+ - TL-R470GP-AC 4.0
398
+ - TL-R488GPM-AC 2.0
391
399
  - TL-WA1201 3.0
392
400
  - TL-WA3001 v1.0
393
401
  - TL-XDR3010 V2
394
402
  - TL-WDR3600 V1
403
+ - TL-XDR5410 1.0
395
404
  - TL-XDR6088 v1.0.30
396
405
  - VX420-G2h v1.1
397
406
  - VX800v v1
@@ -403,6 +412,7 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
403
412
  - AC10 1.20
404
413
  - MR47BE v1.0
405
414
  - MR50G 1.0
415
+ - ME30 1.0
406
416
  - H60XR 1.0
407
417
  - H47BE 2.0
408
418
  - Halo H80X 1.0
@@ -23,6 +23,7 @@ Python package for API access and management for TP-Link and Mercusys Routers. S
23
23
  ```python
24
24
  from tplinkrouterc6u import (
25
25
  TplinkRouterProvider,
26
+ TplinkRouterV1_11,
26
27
  TplinkRouter,
27
28
  TplinkC1200Router,
28
29
  TplinkC5400XRouter,
@@ -33,6 +34,7 @@ from tplinkrouterc6u import (
33
34
  TPLinkVR400v2Client,
34
35
  TPLinkEXClient, # Class for EX series routers which supports old firmwares with AES cipher CBC mode
35
36
  TPLinkEXClientGCM, # Class for EX series routers which supports AES cipher GCM mode
37
+ TPLinkRClient,
36
38
  TPLinkXDRClient,
37
39
  TPLinkDecoClient,
38
40
  TplinkC80Router,
@@ -50,7 +52,7 @@ router = TplinkRouterProvider.get_client('http://192.168.0.1', 'password')
50
52
  # If you have the TP-link C5400X or similar, you can use the TplinkC5400XRouter class instead of the TplinkRouter class.
51
53
  # Remember that the password for this router is different, here you need to use the web encrypted password.
52
54
  # To get web encrypted password, read Web Encrypted Password section
53
- # router = TplinkC5400XRouter('http://192.168.0.1','WebEncryptedPassword', Logger('test'))
55
+ # router = TplinkC5400XRouter('http://192.168.0.1','WebEncryptedPassword', logger: Logger('test'))
54
56
 
55
57
  try:
56
58
  router.authorize() # authorizing
@@ -339,6 +341,7 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
339
341
  - Deco P7
340
342
  - Deco X20
341
343
  - Deco X50 v1.3
344
+ - Deco X50-5G 1.20
342
345
  - Deco X55 1.0
343
346
  - Deco X60 V3
344
347
  - Deco X90
@@ -346,7 +349,10 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
346
349
  - Deco XE75PRO (v3.0)
347
350
  - EX511 v2.0
348
351
  - HX510 v1.0
352
+ - M8550 v1
353
+ - NE200-Outdoor v1.0
349
354
  - NX510v v1.0
355
+ - NX600 v2.0
350
356
  - TD-W9960 (v1, V1.20)
351
357
  - TL-MR100 v2.0
352
358
  - TL-MR105
@@ -355,10 +361,13 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
355
361
  - TL-MR150 v2
356
362
  - TL-MR6400 (v5, v5.3)
357
363
  - TL-MR6500v
364
+ - TL-R470GP-AC 4.0
365
+ - TL-R488GPM-AC 2.0
358
366
  - TL-WA1201 3.0
359
367
  - TL-WA3001 v1.0
360
368
  - TL-XDR3010 V2
361
369
  - TL-WDR3600 V1
370
+ - TL-XDR5410 1.0
362
371
  - TL-XDR6088 v1.0.30
363
372
  - VX420-G2h v1.1
364
373
  - VX800v v1
@@ -370,6 +379,7 @@ or you have TP-link C5400X or similar router you need to get web encrypted passw
370
379
  - AC10 1.20
371
380
  - MR47BE v1.0
372
381
  - MR50G 1.0
382
+ - ME30 1.0
373
383
  - H60XR 1.0
374
384
  - H47BE 2.0
375
385
  - Halo H80X 1.0
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="tplinkrouterc6u",
8
- version="5.12.3",
8
+ version="5.13.0",
9
9
  author="Alex Erohin",
10
10
  author_email="alexanderErohin@yandex.ru",
11
11
  description="TP-Link Router API (supports also Mercusys Router)",
@@ -14,6 +14,12 @@ from tplinkrouterc6u import (
14
14
 
15
15
 
16
16
  class TestTPLinkClient(TestCase):
17
+ router_class = TplinkRouter
18
+ game_accelerator_path = 'admin/smart_network?form=game_accelerator'
19
+ openvpn_config_path = 'admin/openvpn?form=config'
20
+ pptpd_config_path = 'admin/pptpd?form=config'
21
+ vpn_uses_data_param = True
22
+
17
23
  def test_get_status(self) -> None:
18
24
  response_status = '''
19
25
  {
@@ -211,7 +217,9 @@ class TestTPLinkClient(TestCase):
211
217
  }
212
218
  '''
213
219
 
214
- class TPLinkRouterTest(TplinkRouter):
220
+ router_class = self.router_class
221
+
222
+ class TPLinkRouterTest(router_class):
215
223
  def request(self, path: str, data: str,
216
224
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
217
225
  if path == 'admin/status?form=all&operation=read':
@@ -339,7 +347,9 @@ class TestTPLinkClient(TestCase):
339
347
  }
340
348
  '''
341
349
 
342
- class TPLinkRouterTest(TplinkRouter):
350
+ router_class = self.router_class
351
+
352
+ class TPLinkRouterTest(router_class):
343
353
  def request(self, path: str, data: str,
344
354
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
345
355
  if path == 'admin/status?form=all&operation=read':
@@ -484,12 +494,15 @@ class TestTPLinkClient(TestCase):
484
494
  }
485
495
  '''
486
496
 
487
- class TPLinkRouterTest(TplinkRouter):
497
+ router_class = self.router_class
498
+ game_accelerator_path = self.game_accelerator_path
499
+
500
+ class TPLinkRouterTest(router_class):
488
501
  def request(self, path: str, data: str,
489
502
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
490
503
  if path == 'admin/status?form=all&operation=read':
491
504
  return loads(response_status)['data']
492
- elif path == 'admin/smart_network?form=game_accelerator':
505
+ elif path == game_accelerator_path:
493
506
  return loads(response_game_accelerator)['data']
494
507
  elif path == 'admin/wireless?form=statistics':
495
508
  return loads(response_stats)['data']
@@ -508,7 +521,7 @@ class TestTPLinkClient(TestCase):
508
521
  self.assertEqual(status.wired_total, 2)
509
522
  self.assertEqual(status.wifi_clients_total, 2)
510
523
  self.assertEqual(status.guest_clients_total, 0)
511
- self.assertEqual(status.clients_total, 4)
524
+ self.assertEqual(status.clients_total, 7)
512
525
  self.assertEqual(status.iot_clients_total, 3)
513
526
  self.assertEqual(status.guest_2g_enable, True)
514
527
  self.assertEqual(status.guest_5g_enable, None)
@@ -618,7 +631,9 @@ class TestTPLinkClient(TestCase):
618
631
  }
619
632
  '''
620
633
 
621
- class TPLinkRouterTest(TplinkRouter):
634
+ router_class = self.router_class
635
+
636
+ class TPLinkRouterTest(router_class):
622
637
  def request(self, path: str, data: str,
623
638
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
624
639
  if path == 'admin/status?form=all&operation=read':
@@ -661,8 +676,9 @@ class TestTPLinkClient(TestCase):
661
676
  def test_set_wifi(self) -> None:
662
677
  check_url = ''
663
678
  check_data = ''
679
+ router_class = self.router_class
664
680
 
665
- class TPLinkRouterTest(TplinkRouter):
681
+ class TPLinkRouterTest(router_class):
666
682
  def request(self, path: str, data: str,
667
683
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
668
684
  nonlocal check_url, check_data
@@ -705,8 +721,9 @@ class TestTPLinkClient(TestCase):
705
721
 
706
722
  def test_get_ipv4_status_empty(self) -> None:
707
723
  response_network = '{"result": {}, "error_code": 0}'
724
+ router_class = self.router_class
708
725
 
709
- class TPLinkRouterTest(TplinkRouter):
726
+ class TPLinkRouterTest(router_class):
710
727
  def request(self, path: str, data: str,
711
728
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
712
729
  if path == 'admin/network?form=status_ipv4&operation=read':
@@ -750,8 +767,9 @@ class TestTPLinkClient(TestCase):
750
767
  "operator": "load"
751
768
  }
752
769
  '''
770
+ router_class = self.router_class
753
771
 
754
- class TPLinkRouterTest(TplinkRouter):
772
+ class TPLinkRouterTest(router_class):
755
773
  def request(self, path: str, data: str,
756
774
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
757
775
  if path == 'admin/status?form=all&operation=read':
@@ -800,8 +818,9 @@ class TestTPLinkClient(TestCase):
800
818
  }
801
819
  }
802
820
  '''
821
+ router_class = self.router_class
803
822
 
804
- class TPLinkRouterTest(TplinkRouter):
823
+ class TPLinkRouterTest(router_class):
805
824
  def request(self, path: str, data: str,
806
825
  ignore_response: bool = False, ignore_errors: bool = False) -> dict | None:
807
826
  if path == 'admin/status?form=all&operation=read':
@@ -871,7 +890,12 @@ class TestTPLinkClient(TestCase):
871
890
  "extra": "7450", "vpntype": "pptp", "key": "7450"}
872
891
  ]"""
873
892
 
874
- class TPLinkRouterTest(TplinkRouter):
893
+ router_class = self.router_class
894
+ openvpn_config_path = self.openvpn_config_path
895
+ pptpd_config_path = self.pptpd_config_path
896
+ vpn_uses_data_param = self.vpn_uses_data_param
897
+
898
+ class TPLinkRouterTest(router_class):
875
899
  def request(
876
900
  self,
877
901
  path: str,
@@ -879,14 +903,20 @@ class TestTPLinkClient(TestCase):
879
903
  ignore_response: bool = False,
880
904
  ignore_errors: bool = False,
881
905
  ) -> dict | None:
882
- if path == "admin/openvpn?form=config":
906
+ if path == openvpn_config_path:
883
907
  return loads(response_openvpn_read)
884
- if path == "admin/pptpd?form=config":
908
+ if path == pptpd_config_path:
885
909
  return loads(response_pptp_read)
886
- if path == "admin/vpnconn?form=config" and data == "operation=list&vpntype=openvpn":
887
- return loads(respone_vpnconn_openvpn)
888
- if path == "admin/vpnconn?form=config" and data == "operation=list&vpntype=pptp":
889
- return loads(respone_vpnconn_pptpvpn)
910
+ if vpn_uses_data_param:
911
+ if path == "admin/vpnconn?form=config" and data == "operation=list&vpntype=openvpn":
912
+ return loads(respone_vpnconn_openvpn)
913
+ if path == "admin/vpnconn?form=config" and data == "operation=list&vpntype=pptp":
914
+ return loads(respone_vpnconn_pptpvpn)
915
+ else:
916
+ if path == "admin/vpnconn?form=config&operation=list&vpntype=openvpn":
917
+ return loads(respone_vpnconn_openvpn)
918
+ if path == "admin/vpnconn?form=config&operation=list&vpntype=pptp":
919
+ return loads(respone_vpnconn_pptpvpn)
890
920
  raise ClientException()
891
921
 
892
922
  client = TPLinkRouterTest("", "")
@@ -910,7 +940,10 @@ class TestTPLinkClient(TestCase):
910
940
  }
911
941
  """
912
942
 
913
- class TPLinkRouterTest(TplinkRouter):
943
+ router_class = self.router_class
944
+ openvpn_config_path = self.openvpn_config_path
945
+
946
+ class TPLinkRouterTest(router_class):
914
947
  def request(
915
948
  self,
916
949
  path: str,
@@ -918,7 +951,7 @@ class TestTPLinkClient(TestCase):
918
951
  ignore_response: bool = False,
919
952
  ignore_errors: bool = False,
920
953
  ) -> dict | None:
921
- if path == "admin/openvpn?form=config" and data == "operation=read":
954
+ if path == openvpn_config_path and data == "operation=read":
922
955
  return loads(response_openvpn_read)
923
956
  self.captured_path = path
924
957
  self.captured_data = data
@@ -930,7 +963,7 @@ class TestTPLinkClient(TestCase):
930
963
  "operation=write&enabled=on"
931
964
  "&proto=udp&access=home&cert_exist=True&mask=255.255.255.0&port=1194&serverip=10.8.0.0"
932
965
  )
933
- self.assertEqual(client.captured_path, 'admin/openvpn?form=config')
966
+ self.assertEqual(client.captured_path, self.openvpn_config_path)
934
967
  self.assertEqual(client.captured_data, expected_data)
935
968
 
936
969
 
@@ -0,0 +1,95 @@
1
+ from unittest import main
2
+ from unittest.mock import patch, Mock
3
+ from test_client_c6u import TestTPLinkClient
4
+ from tplinkrouterc6u import TplinkRouterV1_11, ClientException
5
+
6
+
7
+ class TestTPLinkClientV1_11(TestTPLinkClient):
8
+ """Inherits all tests from TestTPLinkClient, using TplinkRouterV1_11."""
9
+
10
+ router_class = TplinkRouterV1_11
11
+ game_accelerator_path = 'admin/smart_network?form=game_accelerator&operation=loadDevice'
12
+ openvpn_config_path = 'admin/openvpn?form=config&operation=read'
13
+ pptpd_config_path = 'admin/pptpd?form=config&operation=read'
14
+ vpn_uses_data_param = False
15
+
16
+ # V1_11-specific tests only
17
+
18
+ def test_supports_password_too_long(self) -> None:
19
+ long_password = 'a' * 126
20
+ client = TplinkRouterV1_11('http://192.168.0.1', long_password)
21
+ self.assertFalse(client.supports())
22
+
23
+ @patch('tplinkrouterc6u.client.c6u.EncryptionWrapper.rsa_encrypt')
24
+ @patch('tplinkrouterc6u.client.c6u.post')
25
+ def test_authorize_success(self, mock_post: Mock, mock_rsa: Mock) -> None:
26
+ mock_rsa.return_value = 'encrypted_password_hex'
27
+
28
+ keys_response = Mock()
29
+ keys_response.json.return_value = {
30
+ 'success': True,
31
+ 'data': {
32
+ 'password': ['mock_nn_value', '010001']
33
+ }
34
+ }
35
+
36
+ login_response = Mock()
37
+ login_response.json.return_value = {
38
+ 'success': True,
39
+ 'data': {
40
+ 'stok': 'test_stok_12345'
41
+ }
42
+ }
43
+ login_response.headers = {'set-cookie': 'sysauth=test_sysauth_cookie; path=/'}
44
+
45
+ mock_post.side_effect = [keys_response, login_response]
46
+
47
+ client = TplinkRouterV1_11('http://192.168.0.1', 'testpassword')
48
+ client.authorize()
49
+
50
+ self.assertTrue(client._logged)
51
+ self.assertEqual(client._stok, 'test_stok_12345')
52
+ self.assertEqual(client._sysauth, 'test_sysauth_cookie')
53
+ self.assertEqual(mock_post.call_count, 2)
54
+
55
+ first_call = mock_post.call_args_list[0]
56
+ self.assertIn('login?form=keys', first_call[0][0])
57
+
58
+ second_call = mock_post.call_args_list[1]
59
+ self.assertIn('login?form=login', second_call[0][0])
60
+ login_data = second_call[1]['data']
61
+ self.assertTrue(login_data.startswith('operation=login&password='))
62
+
63
+ @patch('tplinkrouterc6u.client.c6u.EncryptionWrapper.rsa_encrypt')
64
+ @patch('tplinkrouterc6u.client.c6u.post')
65
+ def test_authorize_failure(self, mock_post: Mock, mock_rsa: Mock) -> None:
66
+ mock_rsa.return_value = 'encrypted_password_hex'
67
+
68
+ keys_response = Mock()
69
+ keys_response.json.return_value = {
70
+ 'success': True,
71
+ 'data': {
72
+ 'password': ['mock_nn_value', '010001']
73
+ }
74
+ }
75
+
76
+ login_response = Mock()
77
+ login_response.json.return_value = {
78
+ 'success': False,
79
+ 'data': {'errorcode': 'invalid password'}
80
+ }
81
+ login_response.headers = {}
82
+
83
+ mock_post.side_effect = [keys_response, login_response]
84
+
85
+ client = TplinkRouterV1_11('http://192.168.0.1', 'wrongpassword')
86
+
87
+ with self.assertRaises(ClientException) as context:
88
+ client.authorize()
89
+
90
+ self.assertIn('Login failed', str(context.exception))
91
+ self.assertFalse(client._logged)
92
+
93
+
94
+ if __name__ == '__main__':
95
+ main()
@@ -204,6 +204,86 @@ class TestTPLinkEXClient(TestCase):
204
204
  self.assertEqual(status.devices[1].packets_sent, None) # TODO
205
205
  self.assertEqual(status.devices[1].packets_received, None) # TODO
206
206
 
207
+ def test_get_status_NE200(self) -> None:
208
+ DEV2_ADT_LAN = ('{"data":[{"MACAddress":"a0:28:84:de:dd:5c","IPAddress":"192.168.4.1","stack":"1,0,0,0,0,0"}],'
209
+ '"operation":"gl","oid":"DEV2_ADT_LAN","success":true}')
210
+ DEV2_ADT_WAN = ('{"data":[{"enable":"1","MACAddr":"","connIPv4Address":"","connIPv4Gateway":""'
211
+ ',"stack":"1,0,0,0,0,0"}],"operation":"gl","oid":"DEV2_ADT_WAN","success":true}')
212
+ DEV2_ADT_WIFI_COMMON = ('{"data":[],"operation":"gl",'
213
+ '"oid":"DEV2_ADT_WIFI_COMMON","success":true}')
214
+ DEV2_HOST_ENTRY = ('{"data":[{"active":"1","X_TP_LanConnType":"1","physAddress":"66-E2-02-BD-B5-1B",'
215
+ '"IPAddress":"192.168.30.10","hostName":"host1","stack":"1,0,0,0,0,0"},'
216
+ '{"active":"1","X_TP_LanConnType":"1","physAddress":"F4-A3-86-2D-41-B5",'
217
+ '"IPAddress":"192.168.30.11","hostName":"host2","stack":"2,0,0,0,0,0"}],"operation":"gl",'
218
+ '"oid":"DEV2_HOST_ENTRY","success":true}')
219
+ DEV2_MEM_STATUS = ('{"data":{"total":"192780","free":"78400","stack":"0,0,0,0,0,0"},"operation":"go",'
220
+ '"oid":"DEV2_MEM_STATUS","success":true}')
221
+ DEV2_PROC_STATUS = ('{"data":{"CPUUsage":"69","stack":"0,0,0,0,0,0"},"operation":"go",'
222
+ '"oid":"DEV2_PROC_STATUS","success":true}')
223
+
224
+ class TPLinkEXClientTest(TPLinkEXClient):
225
+ self._token = True
226
+
227
+ def _request(self, url, method='POST', data_str=None, encrypt=False):
228
+ if 'DEV2_ADT_LAN' in data_str:
229
+ return 200, DEV2_ADT_LAN
230
+ elif 'DEV2_ADT_WAN' in data_str:
231
+ return 200, DEV2_ADT_WAN
232
+ elif 'DEV2_ADT_WIFI_COMMON' in data_str:
233
+ return 200, DEV2_ADT_WIFI_COMMON
234
+ elif 'DEV2_HOST_ENTRY' in data_str:
235
+ return 200, DEV2_HOST_ENTRY
236
+ elif 'DEV2_MEM_STATUS' in data_str:
237
+ return 200, DEV2_MEM_STATUS
238
+ elif 'DEV2_PROC_STATUS' in data_str:
239
+ return 200, DEV2_PROC_STATUS
240
+ raise ClientException()
241
+
242
+ client = TPLinkEXClientTest('', '')
243
+ status = client.get_status()
244
+
245
+ self.assertIsInstance(status, Status)
246
+ self.assertEqual(status.wan_macaddr, None)
247
+ self.assertEqual(status.lan_macaddr, 'A0-28-84-DE-DD-5C')
248
+ self.assertIsInstance(status.lan_macaddress, EUI48)
249
+ self.assertEqual(status.wan_ipv4_addr, None)
250
+ self.assertEqual(status.lan_ipv4_addr, '192.168.4.1')
251
+ self.assertEqual(status.wan_ipv4_gateway, None)
252
+ self.assertEqual(status.wired_total, 0)
253
+ self.assertEqual(status.wifi_clients_total, 2)
254
+ self.assertEqual(status.guest_clients_total, 0)
255
+ self.assertEqual(status.clients_total, 2)
256
+ self.assertEqual(status.guest_2g_enable, None)
257
+ self.assertEqual(status.guest_5g_enable, None)
258
+ self.assertEqual(status.iot_2g_enable, None)
259
+ self.assertEqual(status.iot_5g_enable, None)
260
+ self.assertEqual(status.wifi_2g_enable, None)
261
+ self.assertEqual(status.wifi_5g_enable, None)
262
+ self.assertEqual(status.wan_ipv4_uptime, None)
263
+ self.assertGreaterEqual(status.mem_usage, 0)
264
+ self.assertLessEqual(status.mem_usage, 1)
265
+ self.assertGreaterEqual(status.cpu_usage, 0)
266
+ self.assertLessEqual(status.cpu_usage, 1)
267
+ self.assertEqual(len(status.devices), 2)
268
+ self.assertIsInstance(status.devices[0], Device)
269
+ self.assertEqual(status.devices[0].type, Connection.HOST_2G)
270
+ self.assertEqual(status.devices[0].macaddr, '66-E2-02-BD-B5-1B')
271
+ self.assertIsInstance(status.devices[0].macaddress, EUI48)
272
+ self.assertEqual(status.devices[0].ipaddr, '192.168.30.10')
273
+ self.assertIsInstance(status.devices[0].ipaddress, IPv4Address)
274
+ self.assertEqual(status.devices[0].hostname, 'host1')
275
+ self.assertEqual(status.devices[0].packets_sent, None)
276
+ self.assertEqual(status.devices[0].packets_received, None)
277
+ self.assertIsInstance(status.devices[1], Device)
278
+ self.assertEqual(status.devices[1].type, Connection.HOST_2G)
279
+ self.assertEqual(status.devices[1].macaddr, 'F4-A3-86-2D-41-B5')
280
+ self.assertIsInstance(status.devices[1].macaddress, EUI48)
281
+ self.assertEqual(status.devices[1].ipaddr, '192.168.30.11')
282
+ self.assertIsInstance(status.devices[1].ipaddress, IPv4Address)
283
+ self.assertEqual(status.devices[1].hostname, 'host2')
284
+ self.assertEqual(status.devices[1].packets_sent, None) # TODO
285
+ self.assertEqual(status.devices[1].packets_received, None) # TODO
286
+
207
287
  def test_get_ipv4_reservations(self) -> None:
208
288
 
209
289
  response = ('{"data":[{"enable":"1","chaddr":"bf:75:44:4c:dc:9e","yiaddr":"192.168.8.21",'