embedded-lab-control 0.2.0__py3-none-any.whl
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.
- embedded_lab_control-0.2.0.dist-info/METADATA +855 -0
- embedded_lab_control-0.2.0.dist-info/RECORD +64 -0
- embedded_lab_control-0.2.0.dist-info/WHEEL +5 -0
- embedded_lab_control-0.2.0.dist-info/entry_points.txt +2 -0
- embedded_lab_control-0.2.0.dist-info/licenses/LICENSE +21 -0
- embedded_lab_control-0.2.0.dist-info/top_level.txt +1 -0
- labctl/__init__.py +8 -0
- labctl/actuators/__init__.py +56 -0
- labctl/actuators/base.py +183 -0
- labctl/actuators/lcus1.py +232 -0
- labctl/actuators/mock.py +81 -0
- labctl/actuators/runtime.py +1178 -0
- labctl/cli.py +7485 -0
- labctl/core/__init__.py +36 -0
- labctl/core/admin_files.py +388 -0
- labctl/core/audit.py +269 -0
- labctl/core/claim_keepalive.py +342 -0
- labctl/core/config.py +1068 -0
- labctl/core/database.py +880 -0
- labctl/core/images.py +503 -0
- labctl/core/manager.py +2815 -0
- labctl/core/models.py +815 -0
- labctl/core/safe_open.py +109 -0
- labctl/extras.py +128 -0
- labctl/health/__init__.py +43 -0
- labctl/health/alerts.py +275 -0
- labctl/health/checks.py +533 -0
- labctl/health/daemon.py +397 -0
- labctl/mcp_server.py +5254 -0
- labctl/power/__init__.py +13 -0
- labctl/power/base.py +145 -0
- labctl/power/kasa.py +446 -0
- labctl/power/shelly.py +89 -0
- labctl/power/tasmota.py +95 -0
- labctl/sdwire/__init__.py +10 -0
- labctl/sdwire/controller.py +1116 -0
- labctl/sdwire/power_guard.py +190 -0
- labctl/serial/__init__.py +18 -0
- labctl/serial/boot_test.py +342 -0
- labctl/serial/capture.py +430 -0
- labctl/serial/keys.py +89 -0
- labctl/serial/proxy.py +802 -0
- labctl/serial/ser2net.py +338 -0
- labctl/serial/udev.py +273 -0
- labctl/services.py +210 -0
- labctl/web/__init__.py +9 -0
- labctl/web/activity_broadcaster.py +204 -0
- labctl/web/api.py +1003 -0
- labctl/web/app.py +202 -0
- labctl/web/auth.py +97 -0
- labctl/web/claims.py +232 -0
- labctl/web/static/css/style.css +477 -0
- labctl/web/static/js/app.js +76 -0
- labctl/web/templates/activity.html +202 -0
- labctl/web/templates/base.html +49 -0
- labctl/web/templates/claim_refused.html +38 -0
- labctl/web/templates/console.html +237 -0
- labctl/web/templates/dashboard.html +100 -0
- labctl/web/templates/login.html +25 -0
- labctl/web/templates/sbc_detail.html +306 -0
- labctl/web/templates/settings.html +78 -0
- labctl/web/templates/status_history.html +65 -0
- labctl/web/views.py +496 -0
- labctl/web/websocket.py +208 -0
labctl/power/tasmota.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tasmota power controller.
|
|
3
|
+
|
|
4
|
+
Controls Tasmota-flashed smart plugs via HTTP API.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import requests
|
|
11
|
+
|
|
12
|
+
from labctl.power.base import PowerController, PowerState
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TasmotaController(PowerController):
|
|
18
|
+
"""
|
|
19
|
+
Power controller for Tasmota devices.
|
|
20
|
+
|
|
21
|
+
Uses Tasmota HTTP API:
|
|
22
|
+
- Power On: http://<ip>/cm?cmnd=Power<index>%20On
|
|
23
|
+
- Power Off: http://<ip>/cm?cmnd=Power<index>%20Off
|
|
24
|
+
- Status: http://<ip>/cm?cmnd=Power<index>
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def _command(self, cmnd: str) -> Optional[dict]:
|
|
28
|
+
"""
|
|
29
|
+
Send command to Tasmota device.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
cmnd: Command string (e.g., "Power1 On")
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
JSON response dict or None on error
|
|
36
|
+
"""
|
|
37
|
+
url = f"http://{self.address}/cm"
|
|
38
|
+
params = {"cmnd": cmnd}
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
response = requests.get(url, params=params, timeout=self.timeout)
|
|
42
|
+
response.raise_for_status()
|
|
43
|
+
return response.json()
|
|
44
|
+
except Exception as e:
|
|
45
|
+
logger.warning(
|
|
46
|
+
"Tasmota command '%s' failed for %s: %s", cmnd, self.address, e
|
|
47
|
+
)
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
def _power_key(self) -> str:
|
|
51
|
+
"""Get the power key for responses (POWER or POWER1, POWER2, etc.)."""
|
|
52
|
+
if self.plug_index == 1:
|
|
53
|
+
return "POWER"
|
|
54
|
+
return f"POWER{self.plug_index}"
|
|
55
|
+
|
|
56
|
+
def power_on(self) -> bool:
|
|
57
|
+
"""Turn power on."""
|
|
58
|
+
cmnd = f"Power{self.plug_index} On"
|
|
59
|
+
result = self._command(cmnd)
|
|
60
|
+
|
|
61
|
+
if result is None:
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
# Tasmota returns {"POWER": "ON"} or {"POWER1": "ON"}
|
|
65
|
+
power_key = self._power_key()
|
|
66
|
+
return result.get(power_key, "").upper() == "ON"
|
|
67
|
+
|
|
68
|
+
def power_off(self) -> bool:
|
|
69
|
+
"""Turn power off."""
|
|
70
|
+
cmnd = f"Power{self.plug_index} Off"
|
|
71
|
+
result = self._command(cmnd)
|
|
72
|
+
|
|
73
|
+
if result is None:
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
power_key = self._power_key()
|
|
77
|
+
return result.get(power_key, "").upper() == "OFF"
|
|
78
|
+
|
|
79
|
+
def get_state(self) -> PowerState:
|
|
80
|
+
"""Get current power state."""
|
|
81
|
+
cmnd = f"Power{self.plug_index}"
|
|
82
|
+
result = self._command(cmnd)
|
|
83
|
+
|
|
84
|
+
if result is None:
|
|
85
|
+
return PowerState.UNKNOWN
|
|
86
|
+
|
|
87
|
+
power_key = self._power_key()
|
|
88
|
+
state = result.get(power_key, "").upper()
|
|
89
|
+
|
|
90
|
+
if state == "ON":
|
|
91
|
+
return PowerState.ON
|
|
92
|
+
elif state == "OFF":
|
|
93
|
+
return PowerState.OFF
|
|
94
|
+
else:
|
|
95
|
+
return PowerState.UNKNOWN
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SDWire SD card multiplexer support for lab controller.
|
|
3
|
+
|
|
4
|
+
Controls SDWireC devices to switch SD cards between DUT (target SBC)
|
|
5
|
+
and host (dev machine) for automated flashing.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from labctl.sdwire.controller import SDWireController
|
|
9
|
+
|
|
10
|
+
__all__ = ["SDWireController"]
|