自从我
第一次发布具有RS485 / ModBus接口
SDM-220的电表以来,已经过去了将近一年的时间,然后
第二篇文章介绍了如何从中收集数据和处理统计信息。 这是第三次,希望是最后一次。 她将介绍如何将计数器与
OpenHab集成。 结果终于对我完全没问题。

因此,首次尝试使用外部云服务
ThingSpeak从计数器收集统计信息。 作为轮询计数器的本地服务器,我们使用了瘦客户机(小型计算机),在USB记忆棒上安装了
Ubuntu Server 。 这是第一个错误-闪存驱动器在3个月后“死”了(我以为是事故)。 没有得出任何结论,我在2个月内(正常)杀死了第二个闪存驱动器。 在第三个版本中,带有2.5英寸螺钉的USB口袋已被用作存储设备。
ThingSpeak服务本身允许进行一些处理,但不能提供足够的数据处理灵活性。 例如,每天的数据收集为每小时的数据总和。 如果某些数据包没有到达服务器上,或者我在测试期间发送了一些数据,则发生错误。 认为有必要参照一天中的时间保持两次汇率结算的想法并没有增加乐观情绪。
总的来说,我决定学习
OpenHab 。
第一项任务:从计数器获取原始数据。
说明中详细介绍了OpenHab本身的安装。 安装后,需要通过
Paper UI→Bindings 面板安装
ModBus绑定 -binding-modbus1-1.9.0。通过USB-RS485适配器轮询Modus总线,因此您需要确保适配器在系统中,并将openhab用户访问权限添加到端口:
lsusb Bus 002 Device 002: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC ls /dev/ttyUSB* /dev/ttyUSB0 sudo adduser openhab dialout sudo adduser openhab tty
然后,建议配置Java的权限(在OpenHab安装说明中也对此进行了详细说明):
sudo vi /etc/default/openhab2 EXTRA_JAVA_OPTS="-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0"
完成这些操作后,您需要配置
services / modbus.cfg配置文件:
sudo vi /etc/openhab2/services/modbus.cfg # poll=30000 # , . start - . connection (9600,8,n,1), . # - 0x00 serial.slave1.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave1.type=input serial.slave1.start=0 serial.slave1.length=2 serial.slave1.valuetype=float32 # - 0x06 serial.slave2.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave2.type=input serial.slave2.start=6 serial.slave2.length=2 serial.slave2.valuetype=float32 # - 0x0C serial.slave3.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave3.type=input serial.slave3.start=12 serial.slave3.length=2 serial.slave3.valuetype=float32 # ( ) - 0x156 serial.slave4.connection=/dev/ttyUSB0:9600:8:none:1:rtu:2000:1000:none:none serial.slave4.type=input serial.slave4.start=342 serial.slave4.length=2 serial.slave4.valuetype=float32
然后,您需要在
items / sdm220.items文件中创建数据
项 :
sudo vi /etc/openhab2/items/sdm220.items # Group gSDM220 # , , energy - Number sdm220_voltage " [%.1f ]" <energy> (gSDM220) {modbus="slave1:0"} Number sdm220_current " [%.2f ]" <energy> (gSDM220) {modbus="slave2:0"} Number sdm220_actpower " [%.1f ]" <energy> (gSDM220) {modbus="slave3:0"} Number sdm220_actcounter " [%.1f *]" <energy> (gSDM220) {modbus="slave4:0"}
仍然需要将当前读数添加到仪表板上。 为此,请编辑
sitemaps / default.sitemap文件:
sudo vi /etc/openhab2/sitemaps/default.sitemap sitemap default label="alk0v SmartHome (default sitemap)" { Frame label="" { Text item=sdm220_voltage Text item=sdm220_current Text item=sdm220_actpower Text item=sdm220_actcounter } }
原则上,这足以查看当前的电表读数:

任务二:配置HabPanel并可视化读数
OpenHab支持多个控制面板。 从表面上看,我最喜欢
HabPanel 。 通过
Paper UI→用户界面,安装
HabPanel -
ui-habpanel-2.0.0 。
要绘制图形,您还需要将数据存储在某处。 OpenHab对数据库使用术语“
持久性 ”。 我想使用MySQL数据库,社区讨论了该数据库的许多问题,最后我找到了一条对我也有用的
指令 。
因此,请安装MySQL Persistence(persistence-mysql-1.9.0)。
安装MySQL:
sudo apt-get install mysql-server sudo mysql -u root -p
设置基地:
CREATE DATABASE OpenHAB; CREATE USER 'openhab'@'localhost' IDENTIFIED BY 'YOURPASSWORD'; GRANT ALL PRIVILEGES ON OpenHAB.* TO 'openhab'@'localhost'; quit
重新启动openhab:
sudo service openhab2 stop sudo service openhab2 start
编辑
服务/ mysql.cfg :
# the database url like 'jdbc:mysql://<host>:<port>/<database>' (without quotes) url=jdbc:mysql://localhost:3306/openhab # the database user user=openhab # the database password password=YOURPASSWORD
编辑
persistence / mysql.persist 。 默认情况下,每次更改时,所有Items的值都会输入到数据库中:
Strategies { // if no strategy is specified for an item entry below, the default list will be used everyMinute : "0 * * * * ?" every5Minutes : "0 */5 * * * ?" everyHour : "0 0 * * * ?" everyDay : "0 0 0 * * ?" default = everyChange } Items { // persist all items once a day and on every change and restore them from the db at startup * : strategy = default, restoreOnStartup }
如果正确配置了所有内容,则每个项目的“项目”表和“项目XX”表应出现在数据库中。
mysql> use openhab; Database changed mysql> show tables; +
现在,您可以将美丽带到HabPanel。
添加一个仪表板,向其中添加新的小部件。 要显示值,请使用
Dummy小部件来显示图表
-Chart 。 这里的一切都很直观。 我使用两个不同的Y标尺推导了一张图上的功率和电压参数。
指定mysql作为数据源:

设置电压轴的阈值:

添加项,指示它们的线的颜色和类型,电压指示辅助轴:

我们得到结果:)

第三项任务:每小时和每天计量用电量
显示状态随时间的变化是很好的,但是我还想获取一个小时,一天,一个月的消耗量统计信息。 也就是说,任务是定期执行一些计算。 这是OpenHab中的规则引擎出现的地方。
因此,我们配置
Rules 。
首先,您需要向
items / sdm220.items添加新项目:
Number sdm220_hourcounter (gSDM220) Number sdm220_daycounter (gSDM220)
然后创建
rules / energy.rules文件 ,您需要在其中指定2条规则:一条规则每小时执行一次,第二条规则每天执行一次。
rule "Energy by hour" when Time cron "0 0 * * * ?" then // . var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType // logInfo("TEST","sdm220_hourcounter = "+hour) // Item postUpdate(sdm220_hourcounter, hour) end rule "Energy by day" when Time cron "0 0 0 * * ?" then var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType postUpdate(sdm220_daycounter, day)
您可以使用OpenHab控制台进行调试。 标准用户名和密码:openhab / habopen。 您可以使用以下命令连接到它:
ssh -p 8101 openhab@localhost openhab> log:tail 19:22:00.012 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.526123046875 19:22:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.861083984375 19:22:09.462 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_current changed from 16.0433025360107421875 to 5.69449329376220703125 19:22:11.500 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actcounter changed from 2387.51904296875 to 2387.5458984375 19:22:13.532 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_voltage changed from 192.7679595947265625 to 200.4195098876953125 19:22:15.568 [INFO ] [marthome.event.ItemStateChangedEvent] - sdm220_actpower changed from 2271.8486328125 to 1132.8717041015625 19:23:00.014 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.515869140625 19:23:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8769531250
或者您可以查看日志文件:
tail -f /var/log/openhab2/openhab.log 2017-04-18 19:17:45.587 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'energy.rules' 2017-04-18 19:18:00.259 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.571044921875 2017-04-18 19:18:00.272 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.8330078125 2017-04-18 19:19:00.015 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.83789062500 2017-04-18 19:19:00.025 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.557861328125 2017-04-18 19:20:00.013 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_hourcounter_day = 0.55517578125 2017-04-18 19:20:00.024 [INFO ] [.eclipse.smarthome.model.script.TEST] - sdm220_daycounter = 10.859130859375
我计划将主电表更改为两价电表,根据该电表,在23:00至07:00范围内消耗的电以0.5的系数进行支付,因此我希望看到预期的效果并保持两价电表。 首先,我只是将其他时间条件添加到“项目和规则”中,并将白天和黑夜的读数添加到两个不同的表中。 数据库中的一切都很漂亮,但是在图表上显得笨拙,因为图表将最后两个值用一条直线连接起来:

为了使我感到美丽,我不得不打扰一下。
因此,用于两种关税的最终“规则”脚本如下所示:
rule "Energy by hour" when Time cron "0 0 * * * ?" then var hour = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1), "mysql":).state as DecimalType // if(now.getHourOfDay > 7 && now.getHourOfDay < 23) { logInfo("TEST","sdm220_hourcounter_day = "+hour) postUpdate(sdm220_hourcounter_day, hour) } else { // // primary key timestamp, if(now.getHourOfDay==7) { postUpdate(sdm220_hourcounter_night, hour) Thread::sleep(1000) postUpdate(sdm220_hourcounter_night, 0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_day, 0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_day, hour) } else if(now.getHourOfDay==23) { postUpdate(sdm220_hourcounter_day, hour) Thread::sleep(1000) postUpdate(sdm220_hourcounter_day,0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_night, 0) Thread::sleep(1000) postUpdate(sdm220_hourcounter_night, hour) } else { postUpdate(sdm220_hourcounter_night, hour) } } postUpdate(sdm220_hourcounter, hour) end rule "Energy by day" when Time cron "0 0 0 * * ?" then var day = sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType //night counter, 00:00..07:00 + 23:00..00:00 var day2 = sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusDays(1), "mysql":).state as DecimalType + sdm220_actcounter.state as DecimalType - sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType //day counter, 07:00..23:00 var day1 = sdm220_actcounter.historicState(now.minusHours(1),"mysql":).state as DecimalType - sdm220_actcounter.historicState(now.minusHours(17),"mysql":).state as DecimalType logInfo("TEST","sdm220_daycounter_day = "+day1) logInfo("TEST","sdm220_daycounter_night = "+day2) logInfo("TEST","sdm220_daycounter = "+day) postUpdate(sdm220_daycounter, day) postUpdate(sdm220_daycounter_day, day1) postUpdate(sdm220_daycounter_night, day2) end
在编辑脚本之前,添加必要的项目:
Number sdm220_hourcounter_day (gSDM220) Number sdm220_hourcounter_night (gSDM220) Number sdm220_daycounter_day (gSDM220) Number sdm220_daycounter_night (gSDM220)
现在,每小时和每天的流程图如下所示:

仅此而已。 还计划增加每天的电费和金钱消耗量,以计算夜间和夜间电费,并通过邮件发送生成报告。