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.
Files changed (75) hide show
  1. eeroctl-1.1.1/LICENSE +21 -0
  2. eeroctl-1.1.1/PKG-INFO +113 -0
  3. eeroctl-1.1.1/README.md +76 -0
  4. eeroctl-1.1.1/pyproject.toml +105 -0
  5. eeroctl-1.1.1/setup.cfg +4 -0
  6. eeroctl-1.1.1/src/eero_cli/__init__.py +11 -0
  7. eeroctl-1.1.1/src/eero_cli/commands/__init__.py +32 -0
  8. eeroctl-1.1.1/src/eero_cli/commands/activity.py +215 -0
  9. eeroctl-1.1.1/src/eero_cli/commands/auth.py +467 -0
  10. eeroctl-1.1.1/src/eero_cli/commands/completion.py +142 -0
  11. eeroctl-1.1.1/src/eero_cli/commands/device.py +472 -0
  12. eeroctl-1.1.1/src/eero_cli/commands/eero/__init__.py +12 -0
  13. eeroctl-1.1.1/src/eero_cli/commands/eero/base.py +214 -0
  14. eeroctl-1.1.1/src/eero_cli/commands/eero/led.py +154 -0
  15. eeroctl-1.1.1/src/eero_cli/commands/eero/nightlight.py +235 -0
  16. eeroctl-1.1.1/src/eero_cli/commands/eero/updates.py +82 -0
  17. eeroctl-1.1.1/src/eero_cli/commands/network/__init__.py +18 -0
  18. eeroctl-1.1.1/src/eero_cli/commands/network/advanced.py +191 -0
  19. eeroctl-1.1.1/src/eero_cli/commands/network/backup.py +162 -0
  20. eeroctl-1.1.1/src/eero_cli/commands/network/base.py +321 -0
  21. eeroctl-1.1.1/src/eero_cli/commands/network/dhcp.py +118 -0
  22. eeroctl-1.1.1/src/eero_cli/commands/network/dns.py +197 -0
  23. eeroctl-1.1.1/src/eero_cli/commands/network/forwards.py +115 -0
  24. eeroctl-1.1.1/src/eero_cli/commands/network/guest.py +162 -0
  25. eeroctl-1.1.1/src/eero_cli/commands/network/security.py +162 -0
  26. eeroctl-1.1.1/src/eero_cli/commands/network/speedtest.py +99 -0
  27. eeroctl-1.1.1/src/eero_cli/commands/network/sqm.py +194 -0
  28. eeroctl-1.1.1/src/eero_cli/commands/profile.py +636 -0
  29. eeroctl-1.1.1/src/eero_cli/commands/troubleshoot.py +293 -0
  30. eeroctl-1.1.1/src/eero_cli/context.py +254 -0
  31. eeroctl-1.1.1/src/eero_cli/errors.py +156 -0
  32. eeroctl-1.1.1/src/eero_cli/exit_codes.py +68 -0
  33. eeroctl-1.1.1/src/eero_cli/formatting.py +1130 -0
  34. eeroctl-1.1.1/src/eero_cli/main.py +148 -0
  35. eeroctl-1.1.1/src/eero_cli/output.py +739 -0
  36. eeroctl-1.1.1/src/eero_cli/safety.py +259 -0
  37. eeroctl-1.1.1/src/eero_cli/utils.py +181 -0
  38. eeroctl-1.1.1/src/eeroctl/__init__.py +11 -0
  39. eeroctl-1.1.1/src/eeroctl/commands/__init__.py +32 -0
  40. eeroctl-1.1.1/src/eeroctl/commands/activity.py +215 -0
  41. eeroctl-1.1.1/src/eeroctl/commands/auth.py +467 -0
  42. eeroctl-1.1.1/src/eeroctl/commands/completion.py +142 -0
  43. eeroctl-1.1.1/src/eeroctl/commands/device.py +472 -0
  44. eeroctl-1.1.1/src/eeroctl/commands/eero/__init__.py +12 -0
  45. eeroctl-1.1.1/src/eeroctl/commands/eero/base.py +214 -0
  46. eeroctl-1.1.1/src/eeroctl/commands/eero/led.py +154 -0
  47. eeroctl-1.1.1/src/eeroctl/commands/eero/nightlight.py +235 -0
  48. eeroctl-1.1.1/src/eeroctl/commands/eero/updates.py +82 -0
  49. eeroctl-1.1.1/src/eeroctl/commands/network/__init__.py +18 -0
  50. eeroctl-1.1.1/src/eeroctl/commands/network/advanced.py +191 -0
  51. eeroctl-1.1.1/src/eeroctl/commands/network/backup.py +162 -0
  52. eeroctl-1.1.1/src/eeroctl/commands/network/base.py +321 -0
  53. eeroctl-1.1.1/src/eeroctl/commands/network/dhcp.py +118 -0
  54. eeroctl-1.1.1/src/eeroctl/commands/network/dns.py +197 -0
  55. eeroctl-1.1.1/src/eeroctl/commands/network/forwards.py +115 -0
  56. eeroctl-1.1.1/src/eeroctl/commands/network/guest.py +162 -0
  57. eeroctl-1.1.1/src/eeroctl/commands/network/security.py +162 -0
  58. eeroctl-1.1.1/src/eeroctl/commands/network/speedtest.py +99 -0
  59. eeroctl-1.1.1/src/eeroctl/commands/network/sqm.py +194 -0
  60. eeroctl-1.1.1/src/eeroctl/commands/profile.py +636 -0
  61. eeroctl-1.1.1/src/eeroctl/commands/troubleshoot.py +293 -0
  62. eeroctl-1.1.1/src/eeroctl/context.py +254 -0
  63. eeroctl-1.1.1/src/eeroctl/errors.py +156 -0
  64. eeroctl-1.1.1/src/eeroctl/exit_codes.py +68 -0
  65. eeroctl-1.1.1/src/eeroctl/formatting.py +1130 -0
  66. eeroctl-1.1.1/src/eeroctl/main.py +148 -0
  67. eeroctl-1.1.1/src/eeroctl/output.py +739 -0
  68. eeroctl-1.1.1/src/eeroctl/safety.py +259 -0
  69. eeroctl-1.1.1/src/eeroctl/utils.py +181 -0
  70. eeroctl-1.1.1/src/eeroctl.egg-info/PKG-INFO +113 -0
  71. eeroctl-1.1.1/src/eeroctl.egg-info/SOURCES.txt +73 -0
  72. eeroctl-1.1.1/src/eeroctl.egg-info/dependency_links.txt +1 -0
  73. eeroctl-1.1.1/src/eeroctl.egg-info/entry_points.txt +2 -0
  74. eeroctl-1.1.1/src/eeroctl.egg-info/requires.txt +13 -0
  75. 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
+ [![CI](https://github.com/fulviofreitas/eeroctl/actions/workflows/ci.yml/badge.svg)](https://github.com/fulviofreitas/eeroctl/actions/workflows/ci.yml)
41
+ [![PyPI](https://img.shields.io/pypi/v/eeroctl)](https://pypi.org/project/eeroctl/)
42
+ [![Homebrew](https://img.shields.io/badge/homebrew-eeroctl-orange)](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)
@@ -0,0 +1,76 @@
1
+ # 🌐 eeroctl
2
+
3
+ [![CI](https://github.com/fulviofreitas/eeroctl/actions/workflows/ci.yml/badge.svg)](https://github.com/fulviofreitas/eeroctl/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/eeroctl)](https://pypi.org/project/eeroctl/)
5
+ [![Homebrew](https://img.shields.io/badge/homebrew-eeroctl-orange)](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"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,11 @@
1
+ """Command-line interface for Eero client.
2
+
3
+ This package provides the CLI for managing Eero networks.
4
+
5
+ Entry point: eero_cli.main:cli
6
+ """
7
+
8
+ from .main import cli, main
9
+
10
+ __version__ = "1.2.2"
11
+ __all__ = ["cli", "main", "__version__"]
@@ -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)