一、背景
最近接触了一下PCDN,大家对PCDN的态度各有千秋,我这里不对这个技术做评价。在开启了路由器的UPnP后,HomeAssistant里面自动出现了“UPnP/IGD”这个插件,添加了以后发现可以显示上传和下载速度,单位也可以选择B或者是bit,这就很方便了,可以使用一个卡片来显示网速,但是我想一直显示,那我就得一直开着HA的网页在桌面上,于是我有了制作一个显示网速硬件的想法。
技术定位:初级
所需软硬件:
必须:HomeAssistant、ESPHome、esp8266、lcd1602。
非必须:PCF8574 lcd转iic转接板、烧录器
整体思路:
主要利用ESPHome中的“Home Assistant Sensor”,把HA中的实体当作传感器使用,再利用自带的显示组件自定义显示信息在显示到屏幕上,理论上可以使用任何显示设备显示任何传感器信息。在这里我只做了网速显示的例子,其他显示设备或者数据都是大同小异,但是需要注意的是,一开始我的思路是使用文本传感器,我单纯的认为显示屏显示的都是字符,所以使用了文本传感器“Text Sensor”,编译时候才发现无法对字符串进行格式化,后改用上述的“Home Assistant Sensor”,采集的数据变成浮点型才可以格式化输出。
二、操作步骤
2.1 开发前的准备工作
- 请安装好HomeAssistant、ESPHome。安装过程不再赘述,只要可以正常运行即可。注意在编译固件的时候,ESPHome需要良好的公网现下载所需依赖,否则会编译很长时间。
- 确认好esp8266的管脚,此例子使用的是PCF8574转接过的1602,所以需要使用iic进行通信,请查阅芯片手册确认可以进行iic通信的引脚。我使用的是esp-12f,接到了默认的iic引脚上,即: sda--->GPIO2、scl--->GPIO14,检查好供电,然后调整lcd电位器。在没有进行通信的情况下lcd会第一行全显示,第二行不显示。
2.2 HA设置
路由器需要开启UPnP,不同品牌开启方式不一样,这有个比较全的教程只看开启UPnP的部分就行:路由器配置NAT/UPNP/DMZ方法。开启后,不出意外HA设备与集成页面就会自动弹出,直接配置就行。没有的话,搜索upnp。我配置好了,就不删除再演示了😜
添加好后,可以手动修改传感器名称和单位,用自己喜欢的即可。,单位这里不懂的去补一下课,网速、带宽之类的都学一下。我需要的是网速所以使用的是MB/s。
在这个界面,我们可以获取到两个接下来需要使用的东西,左键单击其中一个传感器,然后点击设置,里面就会有实体ID。旁边的按钮就是复制,多贴心。
2.3 ESPHome部分
新建设备部分不赘述,先直接看主要代码:
i2c:
sda: GPIO2
scl: GPIO14
sensor:
- platform: homeassistant
name: "up_speed"
id: up
entity_id: sensor.miwifi_router_upload_speed
- platform: homeassistant
name: "down_speed"
id: down
entity_id: sensor.miwifi_router_download_speed
display:
- platform: lcd_pcf8574
dimensions: 16x2
address: 0x27
update_interval: 5s
id: lcd
user_characters:
- position: 0
data:
- 0b00100
- 0b01110
- 0b10101
- 0b00100
- 0b00100
- 0b00100
- 0b00100
- 0b00000
- position: 7
data:
- 0b00100
- 0b00100
- 0b00100
- 0b00100
- 0b10101
- 0b01110
- 0b00100
- 0b00000
lambda: |-
it.printf(0,0,"\x08 %3.7f MB/s", id(up).state);
it.printf(0,1,"\x07 %2.7f MB/s",id(down).state);
- 先定义i2c引脚,注意引脚名称要按照所选的开发板或者模块来写,nodemcu开发板用的就是D1、D2这样的。
- 添加传感器,一个数据一个传感器,entity_id就是实体ID,从HA粘过来就行。然后id是自己起的名,别重复或者别用关键字就行。
- 添加显示部,这个取决于使用什么显示设备,我只说我用的这种需要改的地方。dimensions:填显示字符大小 一行中显示的字符数 x 有几行。address:填地址,这个模块默认地址就是0x27,通过短接模块上的地址触点可以改地址。update_interval:屏幕刷新时间:不是必须有的,默认是1s,但是HA里这个数据采集的非常慢,没必要刷新那么快。实测采集速度为30秒,暂时我还没找到加快采集速度的办法。user_characters:用户自定义的字符,用这个工具可以自定义lcd字符。我这里自定义了两个分别是↑↓,表示上传和下载。
- 最后的lambda是用来实现打印的,注意,官方示例中有两个函数,一个是简单显示字符串的print函数和高级功能的printf函数,我一开始没有注意到这两个函数的区别,导致函数参数未能识别编译报错。简单说一下printf函数:
display: - platform: lcd_gpio # or lcd_pcf8574 # ... lambda: |- // Print 0 at the top left it.print("0"); // Print 1 at the second row and second column. it.print(1, 1, "1"); // Let's write a sensor value (let's assume it's 42.1) it.printf("%.1f", id(my_sensor).state); // Result: "42.1" (the dot will appear on the segment showing "2") // Print a right-padded sensor value with 0 digits after the decimal it.printf("Sensor value: %8.0f", id(my_sensor).state); // Result: "Sensor value: 42" // Print the current time it.strftime("It is %H:%M on %d.%m.%Y", id(my_time).now()); // Result for 10:06 on august 21st 2018 -> "It is 10:06 on 21.08.2018" # (Optional) For displaying time: time: - platform: homeassistant id: my_time
官方说明是这样的,有函数复用。简单说,可以直接用""来显示字符串,从初始位置开始,但是要想指定位置,就得在前面加上两个位置信息,第一个是一行中的位置,第二个是第几行,ps:官方给的例子稀碎,用俩1,我一开始以为第一个参数是行,结果两行内容显示在一起了(arduino中就是这样)。然后就是格式化输出,eg.%2.3f 意味着整数部分有两位,小数部分有3位,格式化输出数据有四舍五入功能,后边跟着的参数就是需要格式化显示的内容。
it.printf(0,0,"\x08 %3.7f MB/s", id(up).state);意识是在第一个字符,第一行,显示
↑xx.xxxxxxx MB/s,用 id(up).state的值格式化后给xx.xxxxxxx。\x08是我自定义的第一个字符,\x07是第二个。
烧录之后添加到HA,这个也是自动能识别的。最终效果就在最上边。可以根据自己的需求改一下最后两条打印语句。
三、总结
这个项目没有什么难度,实验室嫖回来一堆lcd1602,也是淘汰的东西了,现在没几个人做项目会首选lcd1602,也算废物利用。再就是这个项目唯一的缺点就是采集数据太慢,30s采集一次。做个外壳包装一下应该会有点复古风,有时间我试着用数码管做一下。