Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20c781c750 | ||
|
|
d206ae4390 |
@@ -2,3 +2,4 @@ __pycache__/
|
||||
*.pyc
|
||||
dist/
|
||||
.DS_Store
|
||||
.data/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# PIGWay Agent Console Plugin
|
||||
# PIGWay Raspberry Pi Console Plugin
|
||||
|
||||
独立维护的树莓派接入插件:连接现有 PIGWay Device Agent,不在树莓派安装新进程。设备 API、状态转换、配置字段、服务/进程监控、硬件界面及其翻译均由本仓库维护。
|
||||
独立维护的树莓派接入插件:连接现有 PIGWay Raspberry Pi Agent,不在树莓派安装新进程。设备 API、状态转换、配置字段、服务/进程监控、硬件界面及其翻译均由本仓库维护。
|
||||
|
||||
依赖 Python 标准库;接入 Console JSON-RPC v1 与可信前端扩展 `console-ui-v1`。插件 ID 保持 `pigway-agent`,已有设备可直接继续使用。
|
||||
|
||||
@@ -8,11 +8,19 @@
|
||||
|
||||
```sh
|
||||
mkdir -p dist
|
||||
python3 package.py plugin dist/pigway-agent-1.0.0.zip
|
||||
python3 package.py plugin dist/pigway-agent-1.1.0.zip
|
||||
```
|
||||
|
||||
在控制中心的机器管理页面安装 ZIP,再启用。开发时可用 `PIGWAY_ADAPTER_PATH=/absolute/path/pigway-console-adapter-agent/plugin` 加载源码;Docker 推荐使用持久化数据卷中的安装包。
|
||||
在控制中心的机器管理页面安装 ZIP,再启用。开发时可用 `PIGWAY_ADAPTER_PATH=/absolute/path/pigway-console-adapter-raspberry-pi/plugin` 加载源码;Docker 推荐使用持久化数据卷中的安装包。
|
||||
|
||||
包根目录只有 manifest、worker 与 ui;打包工具、文档和 Git 元数据不进入插件包。前端扩展通过 Console 的共享状态、请求、翻译与基础显示函数接入,不注入额外安装步骤。只应安装可信插件:前端模块与主页面共享 JavaScript 执行环境,加载失败、同步异常及 Promise 拒绝可降级,但不能隔离死循环或恶意代码;后端独立进程的隔离也不是安全沙箱。
|
||||
|
||||
正式仓库:https://tea.pigway.com/way/pigway-console-adapter-agent 。首次独立版本为 v1.0.0,需要 Console v2.0.0。与 Console 的集成回归使用后者 tests 下的模拟 Agent,不操作真实设备。
|
||||
正式仓库:https://tea.pigway.com/way/pigway-console-adapter-raspberry-pi 。首次独立版本为 v1.0.0,需要 Console v2.0.0。与 Console 的集成回归使用后者 tests 下的模拟 Agent,不操作真实设备。
|
||||
|
||||
## Naming and compatibility
|
||||
|
||||
This project targets Raspberry Pi. Other Linux platforms are not covered by its support claim and may have separately maintained adapters. Repository naming does not change the existing `pigway-agent` adapter ID or `pigway-pi-control` service, configuration and API identifiers.
|
||||
|
||||
## v1.1.0 历史指标
|
||||
|
||||
将现有 Agent API 的内存/磁盘字节数、开机时长与链路速度补充到标准 metrics,Console v2.1.0 可直接统一记录历史。不需要更新或新增树莓派进程。现有设备端没有上传下载流量计数,因此本版没有实际流量曲线;链路速度仅代表协商速率。
|
||||
|
||||
+5
-4
@@ -1,7 +1,7 @@
|
||||
7d856a7ec552a841097cd14f2f3e357efcd05c13f70eb98a415789e615f6fbf2 .gitignore
|
||||
f577e72ab33e2cc2dcb2fde5f598adab9dd0ae0602cef517c8281eb39bf00eb6 README.md
|
||||
3cfd361f7663a9a9c93b507d17bb1c7e98003d61316826f0a4ba4a93594f72d4 .gitignore
|
||||
2a476aea1b4fcaf43ace0a7f297e4f5c3cd5014b79992bb5bedf84faa194071f README.md
|
||||
d081c599d821149853368b1a8637c57a16995344406ff5ec9d7619b66e0479b3 package.py
|
||||
b7c560b9f529ef8dcdf74f1bc74a36745fc005c2432ff80325e1c9e87573e7b2 plugin/manifest.json
|
||||
cf40d1302a8398497e4d6724ec0a22b24420e32ed2697ba3f4d039d193cf38ea plugin/manifest.json
|
||||
e5c04001dbd8ed8bba614f7b341237fc6487a9a8fe2f28ccb6f59278725b0a69 plugin/ui/config.js
|
||||
c98f34119436e3020ef20b325f91617943aefe662119cf76738e0226c2e91cbb plugin/ui/device.js
|
||||
89b9d7994e7477e18c3f43e6f0975e04d5106056ba581b2964db0f39183d6f8a plugin/ui/hardware.js
|
||||
@@ -11,4 +11,5 @@ fadb6bf24d6fcf569fc4157847a3585a1008aad99ce5a0e2b87c9c0658f6d225 plugin/ui/over
|
||||
5d967b5d4e62eed7022bc04fe29e4ed670f2e288cf20adae0c25233f94a29079 plugin/ui/services.js
|
||||
56e67d2839cbb865133e3b5f796a07f36595c0f6c30480f8e2fac79e7d51e03f plugin/ui/styles.css
|
||||
0b79b9c5b5f23727164e05b127caca72255416309166ba200ccbd15a9667473c plugin/ui/translations.js
|
||||
c12c7b8a3c2fdb5eaef8ca535fcae04d960d4c89c86740529166f3e25cd8c7c9 plugin/worker.py
|
||||
0c37e4604a30c13923b45316d21c841164c48e8b632c3a3f8febd778b434c2f8 plugin/worker.py
|
||||
9ffd557bb01ccda24970af1cfc5ec395721d5b1e613bfc013feb27d074582b7e tests/test_metrics.py
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "pigway-agent",
|
||||
"name": "PIGWay Agent",
|
||||
"version": "1.0.0",
|
||||
"name": "PIGWay Raspberry Pi Agent",
|
||||
"version": "1.1.0",
|
||||
"protocol_version": 1,
|
||||
"entrypoint": "worker.py",
|
||||
"runtime": "python3",
|
||||
|
||||
+10
-2
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Official Agent adapter. This process alone knows Agent endpoints/authentication."""
|
||||
"""Official Raspberry Pi adapter. This process alone knows Agent endpoints/authentication."""
|
||||
import concurrent.futures
|
||||
import json
|
||||
import sys
|
||||
@@ -61,11 +61,19 @@ def collect(device):
|
||||
raise AdapterError('INVALID_RESPONSE')
|
||||
metrics = []
|
||||
units = {'cpu_percent': 'percent', 'memory_percent': 'percent', 'disk_percent': 'percent',
|
||||
'temperature_c': 'celsius', 'cpu_freq_mhz': 'megahertz'}
|
||||
'temperature_c': 'celsius', 'cpu_freq_mhz': 'megahertz',
|
||||
'memory_total_bytes': 'bytes', 'memory_used_bytes': 'bytes',
|
||||
'disk_total_bytes': 'bytes', 'disk_used_bytes': 'bytes'}
|
||||
for key, unit in units.items():
|
||||
number = value['system'].get(key)
|
||||
if isinstance(number, (int, float)) and not isinstance(number, bool):
|
||||
metrics.append({'resource_id': 'host', 'key': key, 'value': number, 'unit': unit})
|
||||
uptime = value.get('uptime_seconds')
|
||||
if isinstance(uptime, (int, float)) and not isinstance(uptime, bool):
|
||||
metrics.append({'resource_id': 'host', 'key': 'uptime_seconds', 'value': uptime, 'unit': 'seconds'})
|
||||
speed = value.get('network', {}).get('link_speed_mbps')
|
||||
if isinstance(speed, (int, float)) and not isinstance(speed, bool):
|
||||
metrics.append({'resource_id': 'host', 'key': 'network_link_speed_mbps', 'value': speed, 'unit': 'megabits_per_second'})
|
||||
return {'schema_version': 1, 'observed_at': value.get('timestamp'),
|
||||
'identity': {'reported_name': value['machine'].get('name'), 'category': 'host',
|
||||
'details': value.get('device', {})},
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'plugin'))
|
||||
import worker
|
||||
|
||||
|
||||
class MetricsTests(unittest.TestCase):
|
||||
def test_existing_agent_fields_become_standard_history_metrics(self):
|
||||
value = {'timestamp': 123, 'machine': {'name':'Pi'}, 'system': {
|
||||
'cpu_percent': 10, 'memory_total_bytes': 8000, 'memory_used_bytes': 4000,
|
||||
'disk_total_bytes': 16000, 'disk_used_bytes': 5000},
|
||||
'uptime_seconds': 1000, 'network': {'link_speed_mbps':1000},
|
||||
'display': {'alerts': []}}
|
||||
with patch.object(worker,'request',return_value=value): result=worker.collect({})
|
||||
values = {m['key']:m['value'] for m in result['metrics']}
|
||||
self.assertEqual(values['memory_used_bytes'],4000)
|
||||
self.assertEqual(values['uptime_seconds'],1000)
|
||||
self.assertEqual(values['network_link_speed_mbps'],1000)
|
||||
self.assertNotIn('network_rx_bytes_per_second',values)
|
||||
self.assertTrue(result['alerts_complete'])
|
||||
|
||||
def test_absent_or_boolean_fields_not_invented(self):
|
||||
value={'system': {'cpu_percent': True}, 'machine':{}, 'network': {'link_speed_mbps': None}}
|
||||
with patch.object(worker,'request',return_value=value): result=worker.collect({})
|
||||
self.assertEqual(result['metrics'],[])
|
||||
|
||||
if __name__=='__main__': unittest.main()
|
||||
Reference in New Issue
Block a user