eeroctl 1.1.1__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.
- eeroctl-1.1.1/LICENSE +21 -0
- eeroctl-1.1.1/PKG-INFO +113 -0
- eeroctl-1.1.1/README.md +76 -0
- eeroctl-1.1.1/pyproject.toml +105 -0
- eeroctl-1.1.1/setup.cfg +4 -0
- eeroctl-1.1.1/src/eero_cli/__init__.py +11 -0
- eeroctl-1.1.1/src/eero_cli/commands/__init__.py +32 -0
- eeroctl-1.1.1/src/eero_cli/commands/activity.py +215 -0
- eeroctl-1.1.1/src/eero_cli/commands/auth.py +467 -0
- eeroctl-1.1.1/src/eero_cli/commands/completion.py +142 -0
- eeroctl-1.1.1/src/eero_cli/commands/device.py +472 -0
- eeroctl-1.1.1/src/eero_cli/commands/eero/__init__.py +12 -0
- eeroctl-1.1.1/src/eero_cli/commands/eero/base.py +214 -0
- eeroctl-1.1.1/src/eero_cli/commands/eero/led.py +154 -0
- eeroctl-1.1.1/src/eero_cli/commands/eero/nightlight.py +235 -0
- eeroctl-1.1.1/src/eero_cli/commands/eero/updates.py +82 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/__init__.py +18 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/advanced.py +191 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/backup.py +162 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/base.py +321 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/dhcp.py +118 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/dns.py +197 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/forwards.py +115 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/guest.py +162 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/security.py +162 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/speedtest.py +99 -0
- eeroctl-1.1.1/src/eero_cli/commands/network/sqm.py +194 -0
- eeroctl-1.1.1/src/eero_cli/commands/profile.py +636 -0
- eeroctl-1.1.1/src/eero_cli/commands/troubleshoot.py +293 -0
- eeroctl-1.1.1/src/eero_cli/context.py +254 -0
- eeroctl-1.1.1/src/eero_cli/errors.py +156 -0
- eeroctl-1.1.1/src/eero_cli/exit_codes.py +68 -0
- eeroctl-1.1.1/src/eero_cli/formatting.py +1130 -0
- eeroctl-1.1.1/src/eero_cli/main.py +148 -0
- eeroctl-1.1.1/src/eero_cli/output.py +739 -0
- eeroctl-1.1.1/src/eero_cli/safety.py +259 -0
- eeroctl-1.1.1/src/eero_cli/utils.py +181 -0
- eeroctl-1.1.1/src/eeroctl/__init__.py +11 -0
- eeroctl-1.1.1/src/eeroctl/commands/__init__.py +32 -0
- eeroctl-1.1.1/src/eeroctl/commands/activity.py +215 -0
- eeroctl-1.1.1/src/eeroctl/commands/auth.py +467 -0
- eeroctl-1.1.1/src/eeroctl/commands/completion.py +142 -0
- eeroctl-1.1.1/src/eeroctl/commands/device.py +472 -0
- eeroctl-1.1.1/src/eeroctl/commands/eero/__init__.py +12 -0
- eeroctl-1.1.1/src/eeroctl/commands/eero/base.py +214 -0
- eeroctl-1.1.1/src/eeroctl/commands/eero/led.py +154 -0
- eeroctl-1.1.1/src/eeroctl/commands/eero/nightlight.py +235 -0
- eeroctl-1.1.1/src/eeroctl/commands/eero/updates.py +82 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/__init__.py +18 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/advanced.py +191 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/backup.py +162 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/base.py +321 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/dhcp.py +118 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/dns.py +197 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/forwards.py +115 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/guest.py +162 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/security.py +162 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/speedtest.py +99 -0
- eeroctl-1.1.1/src/eeroctl/commands/network/sqm.py +194 -0
- eeroctl-1.1.1/src/eeroctl/commands/profile.py +636 -0
- eeroctl-1.1.1/src/eeroctl/commands/troubleshoot.py +293 -0
- eeroctl-1.1.1/src/eeroctl/context.py +254 -0
- eeroctl-1.1.1/src/eeroctl/errors.py +156 -0
- eeroctl-1.1.1/src/eeroctl/exit_codes.py +68 -0
- eeroctl-1.1.1/src/eeroctl/formatting.py +1130 -0
- eeroctl-1.1.1/src/eeroctl/main.py +148 -0
- eeroctl-1.1.1/src/eeroctl/output.py +739 -0
- eeroctl-1.1.1/src/eeroctl/safety.py +259 -0
- eeroctl-1.1.1/src/eeroctl/utils.py +181 -0
- eeroctl-1.1.1/src/eeroctl.egg-info/PKG-INFO +113 -0
- eeroctl-1.1.1/src/eeroctl.egg-info/SOURCES.txt +73 -0
- eeroctl-1.1.1/src/eeroctl.egg-info/dependency_links.txt +1 -0
- eeroctl-1.1.1/src/eeroctl.egg-info/entry_points.txt +2 -0
- eeroctl-1.1.1/src/eeroctl.egg-info/requires.txt +13 -0
- eeroctl-1.1.1/src/eeroctl.egg-info/top_level.txt +2 -0
eeroctl-1.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Eero CLI Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
eeroctl-1.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eeroctl
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Summary: Command-line interface for Eero network management
|
|
5
|
+
Author: Eero CLI Contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/fulviofreitas/eeroctl
|
|
8
|
+
Project-URL: Issues, https://github.com/fulviofreitas/eeroctl/issues
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
11
|
+
Classifier: Intended Audience :: System Administrators
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Home Automation
|
|
18
|
+
Classifier: Topic :: System :: Networking
|
|
19
|
+
Classifier: Environment :: Console
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: eero-api>=1.3.1
|
|
25
|
+
Requires-Dist: rich>=13.0.0
|
|
26
|
+
Requires-Dist: click>=8.0.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# 🌐 eeroctl
|
|
39
|
+
|
|
40
|
+
[](https://github.com/fulviofreitas/eeroctl/actions/workflows/ci.yml)
|
|
41
|
+
[](https://pypi.org/project/eeroctl/)
|
|
42
|
+
[](https://github.com/fulviofreitas/homebrew-eeroctl)
|
|
43
|
+
|
|
44
|
+
> Manage your Eero mesh Wi-Fi from the terminal ✨
|
|
45
|
+
|
|
46
|
+
## ⚡ Features
|
|
47
|
+
|
|
48
|
+
- 🧭 **Intuitive commands** — noun-first structure (`eero network list`)
|
|
49
|
+
- 📊 **Multiple formats** — table, JSON, YAML, text
|
|
50
|
+
- 🛡️ **Safety rails** — confirmation for destructive actions
|
|
51
|
+
- 🔧 **Script-friendly** — non-interactive mode + machine-readable output
|
|
52
|
+
- 🐚 **Shell completion** — bash, zsh, fish
|
|
53
|
+
|
|
54
|
+
## 📦 Install
|
|
55
|
+
|
|
56
|
+
### Homebrew
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
brew install fulviofreitas/eeroctl/eeroctl
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### PyPI
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install eeroctl
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
<details>
|
|
69
|
+
<summary>From source</summary>
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git clone https://github.com/fulviofreitas/eeroctl.git
|
|
73
|
+
cd eeroctl
|
|
74
|
+
uv sync && source .venv/bin/activate
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Or with pip:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
81
|
+
pip install -e .
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
</details>
|
|
85
|
+
|
|
86
|
+
## 🚀 Quick Start
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
eero auth login # Authenticate
|
|
90
|
+
eero network list # List networks
|
|
91
|
+
eero device list # Connected devices
|
|
92
|
+
eero eero list # Mesh nodes
|
|
93
|
+
eero troubleshoot speedtest --force
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 📖 Documentation
|
|
97
|
+
|
|
98
|
+
Full documentation lives in the **[Wiki](https://github.com/fulviofreitas/eeroctl/wiki)**:
|
|
99
|
+
|
|
100
|
+
| 📚 Guide | Description |
|
|
101
|
+
|----------|-------------|
|
|
102
|
+
| [CLI Reference](https://github.com/fulviofreitas/eeroctl/wiki/CLI-Reference) | Commands, flags & exit codes |
|
|
103
|
+
| [Usage Examples](https://github.com/fulviofreitas/eeroctl/wiki/Usage-Examples) | Practical examples |
|
|
104
|
+
| [Configuration](https://github.com/fulviofreitas/eeroctl/wiki/Configuration) | Auth storage & env vars |
|
|
105
|
+
| [Troubleshooting](https://github.com/fulviofreitas/eeroctl/wiki/Troubleshooting) | Common issues |
|
|
106
|
+
|
|
107
|
+
## 🔗 Dependencies
|
|
108
|
+
|
|
109
|
+
Built on [eero-api](https://github.com/fulviofreitas/eero-api) for API communication.
|
|
110
|
+
|
|
111
|
+
## 📄 License
|
|
112
|
+
|
|
113
|
+
MIT — see [LICENSE](LICENSE)
|
eeroctl-1.1.1/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# 🌐 eeroctl
|
|
2
|
+
|
|
3
|
+
[](https://github.com/fulviofreitas/eeroctl/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/eeroctl/)
|
|
5
|
+
[](https://github.com/fulviofreitas/homebrew-eeroctl)
|
|
6
|
+
|
|
7
|
+
> Manage your Eero mesh Wi-Fi from the terminal ✨
|
|
8
|
+
|
|
9
|
+
## ⚡ Features
|
|
10
|
+
|
|
11
|
+
- 🧭 **Intuitive commands** — noun-first structure (`eero network list`)
|
|
12
|
+
- 📊 **Multiple formats** — table, JSON, YAML, text
|
|
13
|
+
- 🛡️ **Safety rails** — confirmation for destructive actions
|
|
14
|
+
- 🔧 **Script-friendly** — non-interactive mode + machine-readable output
|
|
15
|
+
- 🐚 **Shell completion** — bash, zsh, fish
|
|
16
|
+
|
|
17
|
+
## 📦 Install
|
|
18
|
+
|
|
19
|
+
### Homebrew
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
brew install fulviofreitas/eeroctl/eeroctl
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### PyPI
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install eeroctl
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
<details>
|
|
32
|
+
<summary>From source</summary>
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git clone https://github.com/fulviofreitas/eeroctl.git
|
|
36
|
+
cd eeroctl
|
|
37
|
+
uv sync && source .venv/bin/activate
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or with pip:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
44
|
+
pip install -e .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
## 🚀 Quick Start
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
eero auth login # Authenticate
|
|
53
|
+
eero network list # List networks
|
|
54
|
+
eero device list # Connected devices
|
|
55
|
+
eero eero list # Mesh nodes
|
|
56
|
+
eero troubleshoot speedtest --force
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## 📖 Documentation
|
|
60
|
+
|
|
61
|
+
Full documentation lives in the **[Wiki](https://github.com/fulviofreitas/eeroctl/wiki)**:
|
|
62
|
+
|
|
63
|
+
| 📚 Guide | Description |
|
|
64
|
+
|----------|-------------|
|
|
65
|
+
| [CLI Reference](https://github.com/fulviofreitas/eeroctl/wiki/CLI-Reference) | Commands, flags & exit codes |
|
|
66
|
+
| [Usage Examples](https://github.com/fulviofreitas/eeroctl/wiki/Usage-Examples) | Practical examples |
|
|
67
|
+
| [Configuration](https://github.com/fulviofreitas/eeroctl/wiki/Configuration) | Auth storage & env vars |
|
|
68
|
+
| [Troubleshooting](https://github.com/fulviofreitas/eeroctl/wiki/Troubleshooting) | Common issues |
|
|
69
|
+
|
|
70
|
+
## 🔗 Dependencies
|
|
71
|
+
|
|
72
|
+
Built on [eero-api](https://github.com/fulviofreitas/eero-api) for API communication.
|
|
73
|
+
|
|
74
|
+
## 📄 License
|
|
75
|
+
|
|
76
|
+
MIT — see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "eeroctl"
|
|
7
|
+
version = "1.1.1"
|
|
8
|
+
description = "Command-line interface for Eero network management"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Eero CLI Contributors"},
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: End Users/Desktop",
|
|
18
|
+
"Intended Audience :: System Administrators",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Home Automation",
|
|
25
|
+
"Topic :: System :: Networking",
|
|
26
|
+
"Environment :: Console",
|
|
27
|
+
"Typing :: Typed",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"eero-api>=1.3.1",
|
|
31
|
+
"rich>=13.0.0",
|
|
32
|
+
"click>=8.0.0",
|
|
33
|
+
"pyyaml>=6.0.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
dev = [
|
|
38
|
+
"pytest>=7.0.0",
|
|
39
|
+
"pytest-asyncio>=0.21.0",
|
|
40
|
+
"pytest-cov>=4.0.0",
|
|
41
|
+
"black>=23.0.0",
|
|
42
|
+
"isort>=5.12.0",
|
|
43
|
+
"mypy>=1.0.0",
|
|
44
|
+
"ruff>=0.1.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Repository = "https://github.com/fulviofreitas/eeroctl"
|
|
49
|
+
Issues = "https://github.com/fulviofreitas/eeroctl/issues"
|
|
50
|
+
|
|
51
|
+
[project.scripts]
|
|
52
|
+
eero = "eeroctl.main:cli"
|
|
53
|
+
|
|
54
|
+
[tool.setuptools.packages.find]
|
|
55
|
+
where = ["src"]
|
|
56
|
+
|
|
57
|
+
[tool.black]
|
|
58
|
+
line-length = 100
|
|
59
|
+
target-version = ["py312"]
|
|
60
|
+
|
|
61
|
+
[tool.isort]
|
|
62
|
+
profile = "black"
|
|
63
|
+
line_length = 100
|
|
64
|
+
|
|
65
|
+
[tool.mypy]
|
|
66
|
+
python_version = "3.12"
|
|
67
|
+
warn_return_any = false
|
|
68
|
+
warn_unused_configs = true
|
|
69
|
+
ignore_missing_imports = true
|
|
70
|
+
check_untyped_defs = false
|
|
71
|
+
disallow_untyped_defs = false
|
|
72
|
+
no_implicit_optional = false
|
|
73
|
+
|
|
74
|
+
[tool.ruff]
|
|
75
|
+
line-length = 100
|
|
76
|
+
target-version = "py312"
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint]
|
|
79
|
+
select = ["E", "F", "B", "W", "I"]
|
|
80
|
+
ignore = [
|
|
81
|
+
"E501", # Line too long - handled by black
|
|
82
|
+
"B904", # raise-without-from-inside-except - existing code pattern
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
[tool.pytest.ini_options]
|
|
86
|
+
testpaths = ["tests"]
|
|
87
|
+
asyncio_mode = "auto"
|
|
88
|
+
|
|
89
|
+
# =============================================================================
|
|
90
|
+
# Bandit Security Scanner Configuration
|
|
91
|
+
# =============================================================================
|
|
92
|
+
# Bandit is a tool designed to find common security issues in Python code.
|
|
93
|
+
# https://bandit.readthedocs.io/
|
|
94
|
+
# =============================================================================
|
|
95
|
+
[tool.bandit]
|
|
96
|
+
# Directories to scan
|
|
97
|
+
targets = ["src"]
|
|
98
|
+
# Exclude test files from security scanning
|
|
99
|
+
exclude_dirs = ["tests", ".venv", "build", "dist"]
|
|
100
|
+
# Skip specific tests if needed (uncomment to skip)
|
|
101
|
+
# skips = ["B101"] # Example: skip assert_used checks
|
|
102
|
+
# Confidence level: LOW, MEDIUM, HIGH
|
|
103
|
+
# confidence_level = "MEDIUM"
|
|
104
|
+
# Severity level: LOW, MEDIUM, HIGH
|
|
105
|
+
# severity_level = "MEDIUM"
|
eeroctl-1.1.1/setup.cfg
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""New command structure for the Eero CLI.
|
|
2
|
+
|
|
3
|
+
This package contains the new noun-first command tree:
|
|
4
|
+
- auth: Authentication management
|
|
5
|
+
- network: Network configuration and settings
|
|
6
|
+
- eero: Mesh node management
|
|
7
|
+
- device: Connected device management
|
|
8
|
+
- profile: Profile/parental controls management
|
|
9
|
+
- activity: Network activity data (Eero Plus)
|
|
10
|
+
- troubleshoot: Diagnostics and troubleshooting
|
|
11
|
+
- completion: Shell completion
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .activity import activity_group
|
|
15
|
+
from .auth import auth_group
|
|
16
|
+
from .completion import completion_group
|
|
17
|
+
from .device import device_group
|
|
18
|
+
from .eero import eero_group
|
|
19
|
+
from .network import network_group
|
|
20
|
+
from .profile import profile_group
|
|
21
|
+
from .troubleshoot import troubleshoot_group
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"auth_group",
|
|
25
|
+
"network_group",
|
|
26
|
+
"eero_group",
|
|
27
|
+
"device_group",
|
|
28
|
+
"profile_group",
|
|
29
|
+
"activity_group",
|
|
30
|
+
"troubleshoot_group",
|
|
31
|
+
"completion_group",
|
|
32
|
+
]
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""Activity commands for the Eero CLI (Eero Plus feature).
|
|
2
|
+
|
|
3
|
+
Commands:
|
|
4
|
+
- eero activity summary: Network activity summary
|
|
5
|
+
- eero activity clients: Per-client activity
|
|
6
|
+
- eero activity history: Historical activity
|
|
7
|
+
- eero activity categories: Activity by category
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
from eero import EeroClient
|
|
14
|
+
from rich.panel import Panel
|
|
15
|
+
from rich.table import Table
|
|
16
|
+
|
|
17
|
+
from ..context import ensure_cli_context, get_cli_context
|
|
18
|
+
from ..errors import is_premium_error
|
|
19
|
+
from ..exit_codes import ExitCode
|
|
20
|
+
from ..utils import with_client
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _format_bytes(bytes_val: int) -> str:
|
|
24
|
+
"""Format bytes into human-readable format."""
|
|
25
|
+
if bytes_val < 1024:
|
|
26
|
+
return f"{bytes_val} B"
|
|
27
|
+
elif bytes_val < 1024 * 1024:
|
|
28
|
+
return f"{bytes_val / 1024:.1f} KB"
|
|
29
|
+
elif bytes_val < 1024 * 1024 * 1024:
|
|
30
|
+
return f"{bytes_val / (1024 * 1024):.1f} MB"
|
|
31
|
+
else:
|
|
32
|
+
return f"{bytes_val / (1024 * 1024 * 1024):.2f} GB"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@click.group(name="activity")
|
|
36
|
+
@click.pass_context
|
|
37
|
+
def activity_group(ctx: click.Context) -> None:
|
|
38
|
+
"""View network activity data (Eero Plus feature).
|
|
39
|
+
|
|
40
|
+
\b
|
|
41
|
+
Commands:
|
|
42
|
+
summary - Network activity summary
|
|
43
|
+
clients - Per-client activity
|
|
44
|
+
history - Historical activity
|
|
45
|
+
categories - Activity by category
|
|
46
|
+
|
|
47
|
+
\b
|
|
48
|
+
Note: Requires an active Eero Plus subscription.
|
|
49
|
+
|
|
50
|
+
\b
|
|
51
|
+
Examples:
|
|
52
|
+
eero activity summary
|
|
53
|
+
eero activity clients
|
|
54
|
+
eero activity history --period week
|
|
55
|
+
"""
|
|
56
|
+
ensure_cli_context(ctx)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@activity_group.command(name="summary")
|
|
60
|
+
@click.pass_context
|
|
61
|
+
@with_client
|
|
62
|
+
async def activity_summary(ctx: click.Context, client: EeroClient) -> None:
|
|
63
|
+
"""Show network activity summary."""
|
|
64
|
+
cli_ctx = get_cli_context(ctx)
|
|
65
|
+
console = cli_ctx.console
|
|
66
|
+
|
|
67
|
+
with cli_ctx.status("Getting network activity..."):
|
|
68
|
+
try:
|
|
69
|
+
activity_data = await client.get_activity(cli_ctx.network_id)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
if is_premium_error(e):
|
|
72
|
+
console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
|
|
73
|
+
sys.exit(ExitCode.PREMIUM_REQUIRED)
|
|
74
|
+
raise
|
|
75
|
+
|
|
76
|
+
if cli_ctx.is_structured_output():
|
|
77
|
+
cli_ctx.render_structured(activity_data, "eero.activity.summary/v1")
|
|
78
|
+
else:
|
|
79
|
+
upload = activity_data.get("upload_bytes", 0)
|
|
80
|
+
download = activity_data.get("download_bytes", 0)
|
|
81
|
+
total = upload + download
|
|
82
|
+
|
|
83
|
+
content = (
|
|
84
|
+
f"[bold cyan]Download:[/bold cyan] {_format_bytes(download)}\n"
|
|
85
|
+
f"[bold cyan]Upload:[/bold cyan] {_format_bytes(upload)}\n"
|
|
86
|
+
f"[bold cyan]Total:[/bold cyan] {_format_bytes(total)}"
|
|
87
|
+
)
|
|
88
|
+
console.print(Panel(content, title="Network Activity Summary", border_style="blue"))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@activity_group.command(name="clients")
|
|
92
|
+
@click.pass_context
|
|
93
|
+
@with_client
|
|
94
|
+
async def activity_clients(ctx: click.Context, client: EeroClient) -> None:
|
|
95
|
+
"""Show per-client activity data."""
|
|
96
|
+
cli_ctx = get_cli_context(ctx)
|
|
97
|
+
console = cli_ctx.console
|
|
98
|
+
|
|
99
|
+
with cli_ctx.status("Getting client activity..."):
|
|
100
|
+
try:
|
|
101
|
+
clients_data = await client.get_activity_clients(cli_ctx.network_id)
|
|
102
|
+
except Exception as e:
|
|
103
|
+
if is_premium_error(e):
|
|
104
|
+
console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
|
|
105
|
+
sys.exit(ExitCode.PREMIUM_REQUIRED)
|
|
106
|
+
raise
|
|
107
|
+
|
|
108
|
+
if cli_ctx.is_structured_output():
|
|
109
|
+
cli_ctx.render_structured(clients_data, "eero.activity.clients/v1")
|
|
110
|
+
else:
|
|
111
|
+
if not clients_data:
|
|
112
|
+
console.print("[yellow]No client activity data available[/yellow]")
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
table = Table(title="Client Activity")
|
|
116
|
+
table.add_column("Device", style="cyan")
|
|
117
|
+
table.add_column("Download", justify="right")
|
|
118
|
+
table.add_column("Upload", justify="right")
|
|
119
|
+
table.add_column("Total", justify="right")
|
|
120
|
+
|
|
121
|
+
for client_info in clients_data:
|
|
122
|
+
name = (
|
|
123
|
+
client_info.get("display_name")
|
|
124
|
+
or client_info.get("hostname")
|
|
125
|
+
or client_info.get("mac", "Unknown")
|
|
126
|
+
)
|
|
127
|
+
download = client_info.get("download_bytes", 0)
|
|
128
|
+
upload = client_info.get("upload_bytes", 0)
|
|
129
|
+
total = download + upload
|
|
130
|
+
|
|
131
|
+
table.add_row(
|
|
132
|
+
name, _format_bytes(download), _format_bytes(upload), _format_bytes(total)
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
console.print(table)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@activity_group.command(name="history")
|
|
139
|
+
@click.option(
|
|
140
|
+
"--period",
|
|
141
|
+
type=click.Choice(["hour", "day", "week", "month"]),
|
|
142
|
+
default="day",
|
|
143
|
+
help="Time period (default: day)",
|
|
144
|
+
)
|
|
145
|
+
@click.pass_context
|
|
146
|
+
@with_client
|
|
147
|
+
async def activity_history(ctx: click.Context, client: EeroClient, period: str) -> None:
|
|
148
|
+
"""Show historical activity data.
|
|
149
|
+
|
|
150
|
+
\b
|
|
151
|
+
Options:
|
|
152
|
+
--period Time period: hour, day, week, month
|
|
153
|
+
"""
|
|
154
|
+
cli_ctx = get_cli_context(ctx)
|
|
155
|
+
console = cli_ctx.console
|
|
156
|
+
|
|
157
|
+
with cli_ctx.status(f"Getting activity history ({period})..."):
|
|
158
|
+
try:
|
|
159
|
+
history_data = await client.get_activity_history(cli_ctx.network_id, period)
|
|
160
|
+
except Exception as e:
|
|
161
|
+
if is_premium_error(e):
|
|
162
|
+
console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
|
|
163
|
+
sys.exit(ExitCode.PREMIUM_REQUIRED)
|
|
164
|
+
raise
|
|
165
|
+
|
|
166
|
+
if cli_ctx.is_structured_output():
|
|
167
|
+
cli_ctx.render_structured(history_data, "eero.activity.history/v1")
|
|
168
|
+
else:
|
|
169
|
+
total_download = history_data.get("total_download_bytes", 0)
|
|
170
|
+
total_upload = history_data.get("total_upload_bytes", 0)
|
|
171
|
+
data_points = history_data.get("data_points", [])
|
|
172
|
+
|
|
173
|
+
content = (
|
|
174
|
+
f"[bold]Period:[/bold] {period}\n"
|
|
175
|
+
f"[bold cyan]Total Download:[/bold cyan] {_format_bytes(total_download)}\n"
|
|
176
|
+
f"[bold cyan]Total Upload:[/bold cyan] {_format_bytes(total_upload)}\n"
|
|
177
|
+
f"[bold]Data Points:[/bold] {len(data_points)}"
|
|
178
|
+
)
|
|
179
|
+
console.print(Panel(content, title=f"Activity History ({period})", border_style="blue"))
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@activity_group.command(name="categories")
|
|
183
|
+
@click.pass_context
|
|
184
|
+
@with_client
|
|
185
|
+
async def activity_categories(ctx: click.Context, client: EeroClient) -> None:
|
|
186
|
+
"""Show activity grouped by category."""
|
|
187
|
+
cli_ctx = get_cli_context(ctx)
|
|
188
|
+
console = cli_ctx.console
|
|
189
|
+
|
|
190
|
+
with cli_ctx.status("Getting activity categories..."):
|
|
191
|
+
try:
|
|
192
|
+
categories_data = await client.get_activity_categories(cli_ctx.network_id)
|
|
193
|
+
except Exception as e:
|
|
194
|
+
if is_premium_error(e):
|
|
195
|
+
console.print("[yellow]This feature requires Eero Plus subscription[/yellow]")
|
|
196
|
+
sys.exit(ExitCode.PREMIUM_REQUIRED)
|
|
197
|
+
raise
|
|
198
|
+
|
|
199
|
+
if cli_ctx.is_structured_output():
|
|
200
|
+
cli_ctx.render_structured(categories_data, "eero.activity.categories/v1")
|
|
201
|
+
else:
|
|
202
|
+
if not categories_data:
|
|
203
|
+
console.print("[yellow]No category data available[/yellow]")
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
table = Table(title="Activity by Category")
|
|
207
|
+
table.add_column("Category", style="cyan")
|
|
208
|
+
table.add_column("Usage", justify="right")
|
|
209
|
+
|
|
210
|
+
for category in categories_data:
|
|
211
|
+
name = category.get("name", "Unknown")
|
|
212
|
+
usage = category.get("bytes", 0)
|
|
213
|
+
table.add_row(name, _format_bytes(usage))
|
|
214
|
+
|
|
215
|
+
console.print(table)
|