前言
最近入手了一台斐讯 K3 路由器, 可是博通的芯片发热太严重, 想要随时了解路由器的温度, 于是自己动手实现了一组程序来将路由器温度通过 MQTT 加入 Homeassistant 及 Homekit.
准备
- 已经获取 root 权限的 K3 路由器
- 部署好 HomeAssistant 的内网服务器
- 部署好 Node.js 的内网服务器
前置知识
- 基本的 Shell 编程
- 基本的 HTTP 及 web 服务器知识
- 基本的 MQTT 原理
- 基础 JavaScript 编程
软件结构
最早的想法是直接在路由器上通过 Python 获取数据及通过 MQTT 发送至 HASS 服务器, 但是一个是 opkg 的源太慢了, 另一个是不想给路由器增加额外负担(万一加了测温软件温度涨几度就尴尬了), 最终采用了如下的软件结构
- 路由器 —> Node.js Server —> Homeassistant
其中路由器到 Node.js 通过简单的 HTTP, 将温度数据通过 JSON 发送过来.
Node.js 通过 Express.js 实现 web 服务器用于接受路由器数据,mqtt 包实现 mqtt 通讯, 发送给 Homeassistant.
服务器端 Shell 程序
温度获取
首先第一步是获取路由器的温度数据:
- CPU
cat /proc/dmu/temperature #CPU 温度
wl -i eth1 phy_tempsense #2.4GHz 无线芯片温度
wl -i eth2 phy_tempsense #5GHz 无线芯片温度
运行结果如下:
需要注意的是这里有一个坑,CPU 温度的文件中又不符合 UTF- 8 的字符, 直接用 curl 发的话会导致错误, 这里我们直接用 cut 进行处理, 这里暂时不考虑温度为或 3 位的情况(事实上不太可能发生)
cat /proc/dmu/temperature|cut -c19-20
同理我们对另外两项数据也进行处理
wl -i eth1 phy_tempsense|cut -c0-2
wl -i eth2 phy_tempsense|cut -c0-2
发送温度数据
HTTP 数据约定
GET Method
数据位于 data 参数下, 内容封装于 JSON 中, 格式如下
{“type”:”data”,”CPU”:61,”W24G”:51,”W5G”:65}
curl 实现
这里我们通过 curl 来发送数据, 这里是用 GET 方法, 为了以后增加控制信息方便, 数据包格式如下
{"type":"data","CPU":61,"W24G":51,"W5G":65}
经过 url encode 的结果为
%7B%22type%22:%22data%22,%22CPU%22:61,%22W24G%22:51,%22W5G%22:65%7D
我的 Node.js 服务器地址是 192.168.2.103
, 端口3000
所以我们的 url 是
url="http://192.168.2.103:3000/?data=%7B%22type%22:%22data%22,%22CPU%22:$cpu,%22W24G%22:$w24,%22W5G%22:$w5%7D"
增加无限循环后的完整程序
#!/bin/sh
echo "run.."
while true
do
cpu=$(cat /proc/dmu/temperature|cut -c19-20)
w24=$(wl -i eth1 phy_tempsense|cut -c0-2)
w5=$(wl -i eth2 phy_tempsense|cut -c0-2)
url="http://192.168.2.103:3000/?data=%7B%22type%22:%22data%22,%22CPU%22:$cpu,%22W24G%22:$w24,%22W5G%22:$w5%7D"
curl $url
sleep 60 #设置 1 分钟的查询周期
continue
done
echo "end.."
为了让程序不断运行, 推荐用
screen
来管理
Node 端程序
HTTP 服务器
这里我们基本使用了模版提供的功能, 由于我们这里只对数据进行透明传输, 所以 JSON 不需要反序列化
router.get('/', function(req, res, next) {
var data = req.query.data
res.render('index', { title: 'Express'});
});
MQTT 客户端
MQTT 数据约定
我们的数据分别放在三个 Topic 下
homeassistant/sensor/K3/CPU/state
homeassistant/sensor/K3/24G/state
homeassistant/sensor/K3/5G/state
MQTT 实现
Node 端程序为了方便, 我们直接通过 webstorm 创建 Express.js 程序模版, 我们的程序之间放在 router/index.js
下
记得用 npm 安装 mqtt 包npm install mqtt
首先我们需要初始化 mqtt, 填入你的 MQTT 服务器账号密码(如果未设置匿名)
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://192.168.2.103',{
username: 'homeassistant',
password: 'password',
clientId: 'K3Server'
}); // 连接到服务端
client.subscribe('presence');
注意,mqtt 中客户端 id 不可重复, 后来者将踢出原先的客户端
Node 完整程序
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
var data = req.query.data
client.publish('homeassistant/sensor/K3/CPU/state', data, { qos: 0, retain: true});
client.publish('homeassistant/sensor/K3/24G/state', data, { qos: 0, retain: true});
client.publish('homeassistant/sensor/K3/5G/state', data, { qos: 0, retain: true});
res.render('index', { title: 'Express'});
});
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://192.168.2.103',{
username: 'homeassistant',
password: 'hello',
clientId: 'K3Server'
}); // 连接到服务端
client.subscribe('presence');
module.exports = router;
HomeAssistant 配置
我们这里使用 HA 自带的 MQTT 代理, 配置如下
# Sensors
sensor:
- platform: mqtt
name: 'K3_CPU'
state_topic: 'homeassistant/sensor/K3/CPU/state'
unit_of_measurement: '°C'
value_template: '{{value_json.CPU}}'
- platform: mqtt
name: 'K3_24'
state_topic: 'homeassistant/sensor/K3/24G/state'
unit_of_measurement: '°C'
value_template: '{{value_json.W24G}}'
- platform: mqtt
name: 'K3_5'
state_topic: 'homeassistant/sensor/K3/5G/state'
unit_of_measurement: '°C'
value_template: '{{value_json.W5G}}'
效果