节点
Ecowitt气象站的Node.js/TypeScript客户端——地方民意调查+推取,一个统一的传感器模型.
事件驱动库——不是UI.
安装
npm install @apocaliss92/nodewitt
运输
实施了两种运输方式:本地输入客户端和HTTP推收器(内部)
node:http 接收网关“ 自定义”的服务器 x-www-form-urlencoded 上传和
将它们解码为相同的SI正态读取. 都暴露在单曲背后 Ecowitt
外表,使它们合为一体 Sensor 带有已键入事件流的模型.
使用量
这个 Ecowitt 外观是唯一的公共入口. 选择运输工具 Ecowitt.createLocal
(打开HTTP的网关)或 Ecowitt.createListener (接收网关的上传),那么
用同样的生命周期驱动它: start() 编号 : stop(),订阅 on(...) 编号 : off(...) 编号 :
once(...),并读取时点快照 getStation() (或 getSensors()) (中文(简体) ).
stop()实值 终端:它撕裂了运输,并清除了所有的听众,以及实例 无法重新启动 。 创建新Ecowitt通过createLocal编号 :createListener继续.
地方民意调查
import { Ecowitt } from '@apocaliss92/nodewitt';
const client = Ecowitt.createLocal({
host: '192.168.20.181',
// port: 80, // gateway HTTP port (default 80)
// password: 'secret', // newer firmware
// pollIntervalMs: 60000, // live-data poll interval (default 60000)
// mappingIntervalMs: 600000 // sensor-map refresh interval (default 600000)
});
client.on('update', (sensors) => {
for (const s of sensors) {
console.log(s.id, s.quantity, s.value, s.unit, s.battery ?? '', s.batteryUnit ?? '');
}
});
client.on('sensorChanged', (s) => console.log('changed', s.id, s.value));
client.on('snapshot', (snap) => console.log('sensors:', snap.sensors.length));
client.on('error', (err) => console.error('ecowitt error', err.message));
await client.start();
// ... later
console.log(client.getStation().sensors.length);
await client.stop();
推动收听器
import { Ecowitt } from '@apocaliss92/nodewitt';
const client = Ecowitt.createListener({ port: 4199 }); // port: 0 for an ephemeral port
client.on('update', (sensors) => console.log('push update', sensors.length));
await client.start();
console.log('listening on', client.getAddress()); // point the gateway "Customized" upload here
// ... later
await client.stop();
活动
| 事件 | 有效载数 | 何时 |
|---|---|---|
update | Sensor[] | 值或电池在最新摄入量上发生变化的传感器 |
sensorChanged | Sensor | 一个传感器被改变(每个被改变的传感器一次接收) |
snapshot | StationSnapshot | 每一次摄入后 整个车站的快照 |
error | Error | 运输/解码器出错(从未投入消费者) |
rawFrame | RawFrame | 用于诊断的原始、未解码的运输框架(poll活数据/推取形式) |
统一 Sensor
| 字段 | 含义 |
|---|---|
id | 站内稳定身份 |
hardwareId? | 传感器硬件代号(只投出) |
model? 编号 : channel? | 传感器模型符号/通道 (1.8) |
quantity | temperature | humidity | pressure | wind_speed |.. |
value 编号 : unit 编号 : raw | SI 值, SI 单位, 原始字符串 |
battery? 编号 : batteryUnit? | 电池电位- '%' (解码百分比)或 'V' (拉电压) |
signal? | 信号强度(波浪,已知时) |
lastUpdated | 时代小米 |
两种传动都集中在这个模型上:通过硬件 id(在电池之间稳定)进行传票键传感器
互换; 按键通过 PASSKEY +频道. 值在内部是 SI , 保留了原始字符串 .
电池的表面与运输产生的电池(百分比或电压)完全相同——从未重新被解码.
诊断垃圾堆
createDumper 附上a 只读 现场诊断记录器 Ecowitt 客户端。 节点
没有发布命令——只发布倾卸器 观察 事件流加传感器快照——这样它就可以
永远不要改变网关。 它记录了车站在运营期间暴露的情况(传感器模型,
信道、测量键、电池编码和可选的生框)和导出a
匿名 DeviceDump JSON在共享的跨图书馆堆放格式.
import { Ecowitt, createDumper } from '@apocaliss92/nodewitt';
const client = Ecowitt.createLocal({ host: '192.168.20.181' });
const dumper = createDumper(client, { captureRawFrames: true });
await client.start();
dumper.start();
// ...let the station report for a while (one or more poll ticks)...
dumper.stop();
const json = dumper.exportJson(); // anonymized, share-safe JSON
await client.stop();
输出为 匿名: 网关 mac 编号 : PASSKEY / SSID / IP / 主机 / 纬度/经度
并用 [redacted]抓获时和抓获时均对活框进行擦拭
导出,所以 PASSKEY 或者说 mac 在民意测验/推力框中 从未到达JSON.
共享垃圾堆以扩展传感器表
条目 observations.properties 带有 无空 unmapped 数组 命名节点
尚未确认:
model:<img>——感应模型符号(如:全新的wh99)没有出现在协议表中.key:<rawKey>- 测量/推出键(如新的六分位码或固件字段),用于classifyKey无法映射 .battery:<rawKey>——一个电池键,其编码无一能解码.
在 GitHub 问题上附加匿名的 JSON 使维护者可以将新的传感器类型折叠成
protocol/sensor-models.ts 编号 : protocol/hex-ids.ts 编号 : protocol/battery.ts。 。 。 .
说明:
captureRawFrames(默认关闭)需要表面未知的原始测量键 和不可解密的电池。 这个Station放弃任何无法分类的读取, 因此这些密钥只能是 在原始民意测验/推力框中出现——当这面旗帜是时,倾卸者才会捕捉到(并修改) 继续 还没画好的..模式 信号没有它.
承认
局部层端口 alexlenk/ ecowitt 当地语 (麻省理工学院).
推力层是Ecowitt记录的推力协议的独立实施,基于
灰尘/ 皮克威特 财务报告和审定财务报表
护身符/ 护身符 ecowit (Apache-2.0) 作为
协议参考。 见 LICENSE。 。 。 .
许可证
麻省理工学院.