speedport-api-expanded 0.7.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.
- speedport_api_expanded-0.7.0/LICENSE +22 -0
- speedport_api_expanded-0.7.0/PKG-INFO +188 -0
- speedport_api_expanded-0.7.0/README.md +144 -0
- speedport_api_expanded-0.7.0/setup.cfg +4 -0
- speedport_api_expanded-0.7.0/setup.py +48 -0
- speedport_api_expanded-0.7.0/speedport/__init__.py +3 -0
- speedport_api_expanded-0.7.0/speedport/__main__.py +239 -0
- speedport_api_expanded-0.7.0/speedport/api.py +186 -0
- speedport_api_expanded-0.7.0/speedport/call.py +46 -0
- speedport_api_expanded-0.7.0/speedport/connection.py +159 -0
- speedport_api_expanded-0.7.0/speedport/const.py +2 -0
- speedport_api_expanded-0.7.0/speedport/device.py +87 -0
- speedport_api_expanded-0.7.0/speedport/exceptions.py +10 -0
- speedport_api_expanded-0.7.0/speedport/speedport.py +253 -0
- speedport_api_expanded-0.7.0/speedport_api_expanded.egg-info/PKG-INFO +188 -0
- speedport_api_expanded-0.7.0/speedport_api_expanded.egg-info/SOURCES.txt +19 -0
- speedport_api_expanded-0.7.0/speedport_api_expanded.egg-info/dependency_links.txt +1 -0
- speedport_api_expanded-0.7.0/speedport_api_expanded.egg-info/entry_points.txt +2 -0
- speedport_api_expanded-0.7.0/speedport_api_expanded.egg-info/requires.txt +2 -0
- speedport_api_expanded-0.7.0/speedport_api_expanded.egg-info/top_level.txt +1 -0
- speedport_api_expanded-0.7.0/tests/test_compatibility.py +84 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Andre Basche
|
|
4
|
+
Copyright (c) 2026 Diego Guillen-Rosaperez
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: speedport-api-expanded
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Control Telekom Speedport routers with Python
|
|
5
|
+
Home-page: https://github.com/kplrm/speedport-api-expanded
|
|
6
|
+
Author: Andre Basche, Diego Guillen-Rosaperez
|
|
7
|
+
Maintainer: Diego Guillen-Rosaperez
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: GitHub, https://github.com/kplrm/speedport-api-expanded
|
|
10
|
+
Project-URL: PyPI, https://pypi.org/project/speedport-api-expanded/
|
|
11
|
+
Project-URL: Upstream, https://github.com/Andre0512/speedport-api
|
|
12
|
+
Platform: any
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Natural Language :: English
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Requires-Python: >=3.8
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: aiohttp>=3.8
|
|
30
|
+
Requires-Dist: pycryptodome>=3.18
|
|
31
|
+
Dynamic: author
|
|
32
|
+
Dynamic: classifier
|
|
33
|
+
Dynamic: description
|
|
34
|
+
Dynamic: description-content-type
|
|
35
|
+
Dynamic: home-page
|
|
36
|
+
Dynamic: license
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
Dynamic: maintainer
|
|
39
|
+
Dynamic: platform
|
|
40
|
+
Dynamic: project-url
|
|
41
|
+
Dynamic: requires-dist
|
|
42
|
+
Dynamic: requires-python
|
|
43
|
+
Dynamic: summary
|
|
44
|
+
|
|
45
|
+
**This python package is unofficial and is not related in any way to Telekom. It was developed by reversed engineered http requests and can stop working at anytime!**
|
|
46
|
+
|
|
47
|
+
## Speedport-API
|
|
48
|
+
[](https://pypi.org/project/speedport-api-expanded/)
|
|
49
|
+
[](https://pypi.org/project/speedport-api-expanded/)
|
|
50
|
+
[](https://www.python.org/)
|
|
51
|
+
[](https://github.com/kplrm/speedport-api-expanded/blob/main/LICENSE)
|
|
52
|
+
[](https://pypistats.org/packages/speedport-api-expanded)
|
|
53
|
+
|
|
54
|
+
Control Telekom Speedport routers with Python!
|
|
55
|
+
|
|
56
|
+
### Installation
|
|
57
|
+
```commandline
|
|
58
|
+
pip install speedport-api-expanded
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For this fork's changes, install from a checkout with `python -m pip install -e .`
|
|
62
|
+
or download a wheel from [GitHub releases](https://github.com/kplrm/speedport-api-expanded/releases).
|
|
63
|
+
The Python import remains `from speedport import Speedport`.
|
|
64
|
+
See [local development and adding features](docs/development.md),
|
|
65
|
+
[contribution guidelines](CONTRIBUTING.md), and [contributors](CONTRIBUTORS.md).
|
|
66
|
+
Store local router credentials in an
|
|
67
|
+
ignored `.env` copied from [.env.example](.env.example); see the guide for loading it.
|
|
68
|
+
|
|
69
|
+
### Supported Devices
|
|
70
|
+
* Speedport Smart 4
|
|
71
|
+
|
|
72
|
+
### Commandline tool
|
|
73
|
+
With this shipped commandline tool can a speedport in your network be controlled.
|
|
74
|
+
|
|
75
|
+
#### Turn wifi off
|
|
76
|
+
```commandline
|
|
77
|
+
$ speedport wifi off
|
|
78
|
+
Turn off wifi...
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
#### Turn guest wifi on
|
|
82
|
+
```commandline
|
|
83
|
+
$ speedport guest-wifi on
|
|
84
|
+
Turn on guest wifi...
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Reconnect for new ip address
|
|
88
|
+
```commandline
|
|
89
|
+
$ speedport reconnect
|
|
90
|
+
123.45.67.89 / 5403:f3:35aa:12f:7287:41cf:fb1c:3c83
|
|
91
|
+
Reconnect with internet provider...
|
|
92
|
+
123.45.67.12 / 5403:f3:35fe:12f:7287:41cf:fb1c:3c83
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### Query IPv4 and IPv6 information
|
|
96
|
+
```commandline
|
|
97
|
+
speedport --host 192.168.2.1 ip-info
|
|
98
|
+
speedport --host 192.168.2.1 --batch ip-info
|
|
99
|
+
```
|
|
100
|
+
Prints addresses, gateways, primary/secondary DNS servers, and IPv6 prefixes.
|
|
101
|
+
Batch output uses tab-separated field/value pairs. A password is prompted for
|
|
102
|
+
unless `SPEEDPORT_PASSWORD` is set.
|
|
103
|
+
|
|
104
|
+
To print only the public IPv4 address, without a label or table:
|
|
105
|
+
```commandline
|
|
106
|
+
python -m speedport --host 192.168.2.1 ip-info --ipv4
|
|
107
|
+
93.218.250.118
|
|
108
|
+
```
|
|
109
|
+
If no public IPv4 address is available, the command exits with an error.
|
|
110
|
+
|
|
111
|
+
#### Enable wps connect
|
|
112
|
+
```commandline
|
|
113
|
+
$ speedport wps
|
|
114
|
+
Enable wps connect...
|
|
115
|
+
wps connect enabled for 113s...
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
#### Reboot device
|
|
119
|
+
```commandline
|
|
120
|
+
$ speedport reboot
|
|
121
|
+
Reboot speedport...
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Print devices
|
|
125
|
+
```commandline
|
|
126
|
+
$ speedport devices
|
|
127
|
+
+-------------+---------------------+-------+-----------+
|
|
128
|
+
| ipv4 | name | type | connected |
|
|
129
|
+
+-------------+---------------------+-------+-----------+
|
|
130
|
+
| 10.5.12.32 | Google-Home-Mini-1 | wlan | 1 |
|
|
131
|
+
| 10.5.12.157 | PC10-5-12-157 | lan | 0 |
|
|
132
|
+
| 10.5.12.227 | andre-xps | wlan5 | 1 |
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
#### Print calls
|
|
137
|
+
```commandline
|
|
138
|
+
$ speedport calls
|
|
139
|
+
+-------------+--------+----------+---------------------+
|
|
140
|
+
| number | type | duration | date |
|
|
141
|
+
+-------------+--------+----------+---------------------+
|
|
142
|
+
| 01578212345 | missed | 0 | 2024-04-04 09:34:35 |
|
|
143
|
+
| 026361245 | taken | 1337 | 2024-04-06 05:12:53 |
|
|
144
|
+
| 7866 | dialed | 20 | 2024-04-06 18:39:00 |
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Library
|
|
148
|
+
|
|
149
|
+
#### IP information example
|
|
150
|
+
```python
|
|
151
|
+
import asyncio
|
|
152
|
+
import os
|
|
153
|
+
from speedport import Speedport
|
|
154
|
+
|
|
155
|
+
async def ip_info():
|
|
156
|
+
async with Speedport(
|
|
157
|
+
os.environ.get("SPEEDPORT_HOST", "192.168.2.1"),
|
|
158
|
+
os.environ["SPEEDPORT_PASSWORD"],
|
|
159
|
+
) as router:
|
|
160
|
+
info = await router.ip_info
|
|
161
|
+
print(info["public_ip_v4"], info["public_ip_v6"])
|
|
162
|
+
print(info) # All fields, including DNS servers and IPv6 prefixes.
|
|
163
|
+
|
|
164
|
+
asyncio.run(ip_info())
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
#### Reconnect example
|
|
168
|
+
```python
|
|
169
|
+
import asyncio
|
|
170
|
+
from speedport import Speedport
|
|
171
|
+
|
|
172
|
+
async def reconnect():
|
|
173
|
+
speedport = Speedport("192.168.1.1")
|
|
174
|
+
await speedport.login("password123")
|
|
175
|
+
await speedport.reconnect()
|
|
176
|
+
|
|
177
|
+
asyncio.run(reconnect())
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### Devices example
|
|
181
|
+
```python
|
|
182
|
+
import asyncio
|
|
183
|
+
from speedport import Speedport
|
|
184
|
+
|
|
185
|
+
devices = asyncio.run(Speedport().devices)
|
|
186
|
+
for device in devices:
|
|
187
|
+
print(device.ipv4, device.connected)
|
|
188
|
+
```
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
**This python package is unofficial and is not related in any way to Telekom. It was developed by reversed engineered http requests and can stop working at anytime!**
|
|
2
|
+
|
|
3
|
+
## Speedport-API
|
|
4
|
+
[](https://pypi.org/project/speedport-api-expanded/)
|
|
5
|
+
[](https://pypi.org/project/speedport-api-expanded/)
|
|
6
|
+
[](https://www.python.org/)
|
|
7
|
+
[](https://github.com/kplrm/speedport-api-expanded/blob/main/LICENSE)
|
|
8
|
+
[](https://pypistats.org/packages/speedport-api-expanded)
|
|
9
|
+
|
|
10
|
+
Control Telekom Speedport routers with Python!
|
|
11
|
+
|
|
12
|
+
### Installation
|
|
13
|
+
```commandline
|
|
14
|
+
pip install speedport-api-expanded
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For this fork's changes, install from a checkout with `python -m pip install -e .`
|
|
18
|
+
or download a wheel from [GitHub releases](https://github.com/kplrm/speedport-api-expanded/releases).
|
|
19
|
+
The Python import remains `from speedport import Speedport`.
|
|
20
|
+
See [local development and adding features](docs/development.md),
|
|
21
|
+
[contribution guidelines](CONTRIBUTING.md), and [contributors](CONTRIBUTORS.md).
|
|
22
|
+
Store local router credentials in an
|
|
23
|
+
ignored `.env` copied from [.env.example](.env.example); see the guide for loading it.
|
|
24
|
+
|
|
25
|
+
### Supported Devices
|
|
26
|
+
* Speedport Smart 4
|
|
27
|
+
|
|
28
|
+
### Commandline tool
|
|
29
|
+
With this shipped commandline tool can a speedport in your network be controlled.
|
|
30
|
+
|
|
31
|
+
#### Turn wifi off
|
|
32
|
+
```commandline
|
|
33
|
+
$ speedport wifi off
|
|
34
|
+
Turn off wifi...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Turn guest wifi on
|
|
38
|
+
```commandline
|
|
39
|
+
$ speedport guest-wifi on
|
|
40
|
+
Turn on guest wifi...
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Reconnect for new ip address
|
|
44
|
+
```commandline
|
|
45
|
+
$ speedport reconnect
|
|
46
|
+
123.45.67.89 / 5403:f3:35aa:12f:7287:41cf:fb1c:3c83
|
|
47
|
+
Reconnect with internet provider...
|
|
48
|
+
123.45.67.12 / 5403:f3:35fe:12f:7287:41cf:fb1c:3c83
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Query IPv4 and IPv6 information
|
|
52
|
+
```commandline
|
|
53
|
+
speedport --host 192.168.2.1 ip-info
|
|
54
|
+
speedport --host 192.168.2.1 --batch ip-info
|
|
55
|
+
```
|
|
56
|
+
Prints addresses, gateways, primary/secondary DNS servers, and IPv6 prefixes.
|
|
57
|
+
Batch output uses tab-separated field/value pairs. A password is prompted for
|
|
58
|
+
unless `SPEEDPORT_PASSWORD` is set.
|
|
59
|
+
|
|
60
|
+
To print only the public IPv4 address, without a label or table:
|
|
61
|
+
```commandline
|
|
62
|
+
python -m speedport --host 192.168.2.1 ip-info --ipv4
|
|
63
|
+
93.218.250.118
|
|
64
|
+
```
|
|
65
|
+
If no public IPv4 address is available, the command exits with an error.
|
|
66
|
+
|
|
67
|
+
#### Enable wps connect
|
|
68
|
+
```commandline
|
|
69
|
+
$ speedport wps
|
|
70
|
+
Enable wps connect...
|
|
71
|
+
wps connect enabled for 113s...
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### Reboot device
|
|
75
|
+
```commandline
|
|
76
|
+
$ speedport reboot
|
|
77
|
+
Reboot speedport...
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### Print devices
|
|
81
|
+
```commandline
|
|
82
|
+
$ speedport devices
|
|
83
|
+
+-------------+---------------------+-------+-----------+
|
|
84
|
+
| ipv4 | name | type | connected |
|
|
85
|
+
+-------------+---------------------+-------+-----------+
|
|
86
|
+
| 10.5.12.32 | Google-Home-Mini-1 | wlan | 1 |
|
|
87
|
+
| 10.5.12.157 | PC10-5-12-157 | lan | 0 |
|
|
88
|
+
| 10.5.12.227 | andre-xps | wlan5 | 1 |
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
#### Print calls
|
|
93
|
+
```commandline
|
|
94
|
+
$ speedport calls
|
|
95
|
+
+-------------+--------+----------+---------------------+
|
|
96
|
+
| number | type | duration | date |
|
|
97
|
+
+-------------+--------+----------+---------------------+
|
|
98
|
+
| 01578212345 | missed | 0 | 2024-04-04 09:34:35 |
|
|
99
|
+
| 026361245 | taken | 1337 | 2024-04-06 05:12:53 |
|
|
100
|
+
| 7866 | dialed | 20 | 2024-04-06 18:39:00 |
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Library
|
|
104
|
+
|
|
105
|
+
#### IP information example
|
|
106
|
+
```python
|
|
107
|
+
import asyncio
|
|
108
|
+
import os
|
|
109
|
+
from speedport import Speedport
|
|
110
|
+
|
|
111
|
+
async def ip_info():
|
|
112
|
+
async with Speedport(
|
|
113
|
+
os.environ.get("SPEEDPORT_HOST", "192.168.2.1"),
|
|
114
|
+
os.environ["SPEEDPORT_PASSWORD"],
|
|
115
|
+
) as router:
|
|
116
|
+
info = await router.ip_info
|
|
117
|
+
print(info["public_ip_v4"], info["public_ip_v6"])
|
|
118
|
+
print(info) # All fields, including DNS servers and IPv6 prefixes.
|
|
119
|
+
|
|
120
|
+
asyncio.run(ip_info())
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### Reconnect example
|
|
124
|
+
```python
|
|
125
|
+
import asyncio
|
|
126
|
+
from speedport import Speedport
|
|
127
|
+
|
|
128
|
+
async def reconnect():
|
|
129
|
+
speedport = Speedport("192.168.1.1")
|
|
130
|
+
await speedport.login("password123")
|
|
131
|
+
await speedport.reconnect()
|
|
132
|
+
|
|
133
|
+
asyncio.run(reconnect())
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Devices example
|
|
137
|
+
```python
|
|
138
|
+
import asyncio
|
|
139
|
+
from speedport import Speedport
|
|
140
|
+
|
|
141
|
+
devices = asyncio.run(Speedport().devices)
|
|
142
|
+
for device in devices:
|
|
143
|
+
print(device.ipv4, device.connected)
|
|
144
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
from setuptools import setup, find_packages
|
|
4
|
+
|
|
5
|
+
with open("README.md", "r", encoding="utf-8") as f:
|
|
6
|
+
long_description = f.read()
|
|
7
|
+
|
|
8
|
+
setup(
|
|
9
|
+
name="speedport-api-expanded",
|
|
10
|
+
version="0.7.0",
|
|
11
|
+
author="Andre Basche, Diego Guillen-Rosaperez",
|
|
12
|
+
maintainer="Diego Guillen-Rosaperez",
|
|
13
|
+
description="Control Telekom Speedport routers with Python",
|
|
14
|
+
long_description=long_description,
|
|
15
|
+
long_description_content_type="text/markdown",
|
|
16
|
+
url="https://github.com/kplrm/speedport-api-expanded",
|
|
17
|
+
project_urls={
|
|
18
|
+
"GitHub": "https://github.com/kplrm/speedport-api-expanded",
|
|
19
|
+
"PyPI": "https://pypi.org/project/speedport-api-expanded/",
|
|
20
|
+
"Upstream": "https://github.com/Andre0512/speedport-api",
|
|
21
|
+
},
|
|
22
|
+
license="MIT",
|
|
23
|
+
platforms="any",
|
|
24
|
+
packages=find_packages(),
|
|
25
|
+
include_package_data=True,
|
|
26
|
+
python_requires=">=3.8",
|
|
27
|
+
install_requires=["aiohttp>=3.8", "pycryptodome>=3.18"],
|
|
28
|
+
classifiers=[
|
|
29
|
+
"Development Status :: 4 - Beta",
|
|
30
|
+
"Environment :: Console",
|
|
31
|
+
"License :: OSI Approved :: MIT License",
|
|
32
|
+
"Natural Language :: English",
|
|
33
|
+
"Operating System :: OS Independent",
|
|
34
|
+
"Programming Language :: Python :: 3.8",
|
|
35
|
+
"Programming Language :: Python :: 3.9",
|
|
36
|
+
"Programming Language :: Python :: 3.10",
|
|
37
|
+
"Programming Language :: Python :: 3.11",
|
|
38
|
+
"Programming Language :: Python :: 3.12",
|
|
39
|
+
"Programming Language :: Python :: 3.13",
|
|
40
|
+
"Programming Language :: Python :: 3.14",
|
|
41
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
42
|
+
],
|
|
43
|
+
entry_points={
|
|
44
|
+
"console_scripts": [
|
|
45
|
+
"speedport = speedport.__main__:start",
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
)
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import asyncio
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
from getpass import getpass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
if __name__ == "__main__":
|
|
13
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
14
|
+
|
|
15
|
+
from speedport.speedport import Speedport
|
|
16
|
+
|
|
17
|
+
_LOGGER = logging.getLogger("speedport")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def set_logger(args):
|
|
21
|
+
logging.getLogger("aiohttp").setLevel(logging.WARNING)
|
|
22
|
+
if args["debug"]:
|
|
23
|
+
_LOGGER.setLevel(logging.DEBUG)
|
|
24
|
+
formatter = logging.Formatter("%(levelname)s - %(message)s")
|
|
25
|
+
elif args["quiet"]:
|
|
26
|
+
_LOGGER.setLevel(logging.WARNING)
|
|
27
|
+
formatter = logging.Formatter("%(message)s")
|
|
28
|
+
else:
|
|
29
|
+
_LOGGER.setLevel(logging.INFO)
|
|
30
|
+
formatter = logging.Formatter("%(message)s")
|
|
31
|
+
console_handler = logging.StreamHandler(sys.stdout)
|
|
32
|
+
console_handler.setFormatter(formatter)
|
|
33
|
+
_LOGGER.addHandler(console_handler)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def data_table(data, keys):
|
|
37
|
+
columns = {}
|
|
38
|
+
for key in keys:
|
|
39
|
+
columns[key] = max([len(str(d[key])) for d in data] + [len(key)])
|
|
40
|
+
line = (
|
|
41
|
+
"+-"
|
|
42
|
+
+ "-+-".join([f"{'-' * length}" for key, length in columns.items()])
|
|
43
|
+
+ "-+\n"
|
|
44
|
+
)
|
|
45
|
+
text = (
|
|
46
|
+
f"{line}| "
|
|
47
|
+
+ " | ".join([f"{key:<{length}}" for key, length in columns.items()])
|
|
48
|
+
+ f" |\n{line}"
|
|
49
|
+
)
|
|
50
|
+
for d in data:
|
|
51
|
+
text += (
|
|
52
|
+
"| "
|
|
53
|
+
+ " | ".join(
|
|
54
|
+
[f"{str(d[key]):<{length}}" for key, length in columns.items()]
|
|
55
|
+
)
|
|
56
|
+
+ " |\n"
|
|
57
|
+
)
|
|
58
|
+
return text + line
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def batch_output(devices):
|
|
62
|
+
for device in devices.values():
|
|
63
|
+
print(
|
|
64
|
+
int(device.connected),
|
|
65
|
+
device.ipv4,
|
|
66
|
+
device.type,
|
|
67
|
+
device.name,
|
|
68
|
+
sep="\t",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_arguments():
|
|
73
|
+
"""Get parsed arguments."""
|
|
74
|
+
parser = argparse.ArgumentParser(description="Speedport: Command Line Utility")
|
|
75
|
+
parser.add_argument(
|
|
76
|
+
"-H",
|
|
77
|
+
"--host",
|
|
78
|
+
help="ip address or hostname of Speedport webinterface",
|
|
79
|
+
default=os.environ.get("SPEEDPORT_HOST", "speedport.ip"),
|
|
80
|
+
)
|
|
81
|
+
parser.add_argument(
|
|
82
|
+
"-s", "--https", help="use https connection", action="store_true"
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"-p",
|
|
86
|
+
"--password",
|
|
87
|
+
help="password of Speedport webinterface (default: SPEEDPORT_PASSWORD)",
|
|
88
|
+
default=os.environ.get("SPEEDPORT_PASSWORD"),
|
|
89
|
+
)
|
|
90
|
+
parser.add_argument(
|
|
91
|
+
"-d", "--debug", help="enable debug logging", action="store_true"
|
|
92
|
+
)
|
|
93
|
+
parser.add_argument("-q", "--quiet", help="output only errors", action="store_true")
|
|
94
|
+
parser.add_argument(
|
|
95
|
+
"-b", "--batch", help="print output for batch processing", action="store_true"
|
|
96
|
+
)
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"-t", "--table", help="print output as table (default)", action="store_true"
|
|
99
|
+
)
|
|
100
|
+
subparser = parser.add_subparsers(
|
|
101
|
+
title="commands", metavar="COMMAND", required=True
|
|
102
|
+
)
|
|
103
|
+
for network in ["", "guest-", "office-"]:
|
|
104
|
+
wifi = subparser.add_parser(f"{network}wifi", help=f"Turn on/off {network}wifi")
|
|
105
|
+
wifi.add_argument(
|
|
106
|
+
f"{network}wifi", choices=["on", "off"], help=f"Turn on/off {network}wifi"
|
|
107
|
+
)
|
|
108
|
+
reconnect = subparser.add_parser(
|
|
109
|
+
"reconnect", help="Reconnect internet and receive new ip"
|
|
110
|
+
)
|
|
111
|
+
reconnect.set_defaults(reconnect=True)
|
|
112
|
+
reboot = subparser.add_parser("reboot", help="Reboot device")
|
|
113
|
+
reboot.set_defaults(reboot=True)
|
|
114
|
+
wps = subparser.add_parser("wps", help="Turn on wps for 2 minutes")
|
|
115
|
+
wps.set_defaults(wps=True)
|
|
116
|
+
devices = subparser.add_parser("devices", help="Output devices")
|
|
117
|
+
devices.set_defaults(devices=True)
|
|
118
|
+
calls = subparser.add_parser("calls", help="Output calls")
|
|
119
|
+
calls.set_defaults(calls=True)
|
|
120
|
+
ip_info = subparser.add_parser("ip-info", help="Output IPv4 and IPv6 information")
|
|
121
|
+
ip_info.set_defaults(ip_info=True)
|
|
122
|
+
ip_info.add_argument(
|
|
123
|
+
"--ipv4", help="Print only the public IPv4 address", action="store_true"
|
|
124
|
+
)
|
|
125
|
+
return vars(parser.parse_args())
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
async def check_args(speedport, args):
|
|
129
|
+
if args.get("ip_info"):
|
|
130
|
+
info = await speedport.ip_info
|
|
131
|
+
if args.get("ipv4"):
|
|
132
|
+
address = info.get("public_ip_v4")
|
|
133
|
+
if not address:
|
|
134
|
+
raise SystemExit("Router did not report a public IPv4 address")
|
|
135
|
+
print(address)
|
|
136
|
+
elif args.get("batch"):
|
|
137
|
+
for key, value in info.items():
|
|
138
|
+
print(key, value, sep="\t")
|
|
139
|
+
else:
|
|
140
|
+
print(
|
|
141
|
+
data_table(
|
|
142
|
+
[{"field": key, "value": value} for key, value in info.items()],
|
|
143
|
+
["field", "value"],
|
|
144
|
+
)
|
|
145
|
+
)
|
|
146
|
+
if args.get("wps"):
|
|
147
|
+
await wps_enable(args, speedport)
|
|
148
|
+
if args.get("reconnect"):
|
|
149
|
+
await reconnect(args, speedport)
|
|
150
|
+
if args.get("reboot"):
|
|
151
|
+
await speedport.reboot()
|
|
152
|
+
if args.get("devices"):
|
|
153
|
+
if args.get("batch"):
|
|
154
|
+
batch_output(await speedport.devices)
|
|
155
|
+
else:
|
|
156
|
+
print(
|
|
157
|
+
data_table(
|
|
158
|
+
(await speedport.devices).values(),
|
|
159
|
+
["ipv4", "name", "type", "connected"],
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
if args.get("calls"):
|
|
163
|
+
if args.get("batch"):
|
|
164
|
+
batch_output(await speedport.devices)
|
|
165
|
+
else:
|
|
166
|
+
print(
|
|
167
|
+
data_table(
|
|
168
|
+
await speedport.calls,
|
|
169
|
+
["number", "type", "duration", "date"],
|
|
170
|
+
)
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
async def check_wifi_args(speedport, args):
|
|
175
|
+
if args.get("wifi") and args["wifi"] == "on":
|
|
176
|
+
await speedport.wifi_on()
|
|
177
|
+
elif args.get("wifi") and args["wifi"] == "off":
|
|
178
|
+
await speedport.wifi_off()
|
|
179
|
+
if args.get("guest-wifi") and args["guest-wifi"] == "on":
|
|
180
|
+
await speedport.wifi_guest_on()
|
|
181
|
+
elif args.get("guest-wifi") and args["guest-wifi"] == "off":
|
|
182
|
+
await speedport.wifi_guest_off()
|
|
183
|
+
if args.get("office-wifi") and args["office-wifi"] == "on":
|
|
184
|
+
await speedport.wifi_office_on()
|
|
185
|
+
elif args.get("office-wifi") and args["office-wifi"] == "off":
|
|
186
|
+
await speedport.wifi_office_off()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
async def main():
|
|
190
|
+
args = get_arguments()
|
|
191
|
+
set_logger(args)
|
|
192
|
+
password = ""
|
|
193
|
+
if not args.get("devices"):
|
|
194
|
+
if not (password := args["password"]):
|
|
195
|
+
password = getpass("Password of Speedports webinterface: ")
|
|
196
|
+
async with Speedport(args["host"], password, args.get("https")) as speedport:
|
|
197
|
+
await check_wifi_args(speedport, args)
|
|
198
|
+
await check_args(speedport, args)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
async def reconnect(args, speedport):
|
|
202
|
+
if not args.get("quiet"):
|
|
203
|
+
await speedport.update_ip_data()
|
|
204
|
+
_LOGGER.info(f"{speedport.public_ip_v4} / {speedport.public_ip_v6}")
|
|
205
|
+
await speedport.reconnect()
|
|
206
|
+
if not args.get("quiet"):
|
|
207
|
+
for i in range(240):
|
|
208
|
+
await speedport.update_ip_data()
|
|
209
|
+
if await speedport.online_status == "online":
|
|
210
|
+
_LOGGER.info(f"{speedport.public_ip_v4} / {speedport.public_ip_v6}")
|
|
211
|
+
break
|
|
212
|
+
await asyncio.sleep(0.5)
|
|
213
|
+
print(f"Connecting.{'.' * (i % 3)} ", end="\r", flush=True)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
async def wps_enable(args, speedport):
|
|
217
|
+
await speedport.wps_on()
|
|
218
|
+
if not args.get("quiet"):
|
|
219
|
+
event = time.time()
|
|
220
|
+
next_time = event
|
|
221
|
+
while await speedport.wps_state == 1:
|
|
222
|
+
await asyncio.sleep(next_time - time.time())
|
|
223
|
+
next_time = time.time() + 1
|
|
224
|
+
print(
|
|
225
|
+
f"wps connect enabled for {120 - int(time.time() - event)}s...",
|
|
226
|
+
end="\r",
|
|
227
|
+
flush=True,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def start():
|
|
232
|
+
try:
|
|
233
|
+
asyncio.run(main())
|
|
234
|
+
except KeyboardInterrupt:
|
|
235
|
+
print("Aborted.")
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
if __name__ == "__main__":
|
|
239
|
+
start()
|