本帖最后由 bugensui 于 2023-11-8 17:32 编辑
一直想把家里的电力数据做数字化部署,并且接入到ha里,可以方便查看,观望了小半年,终于在10月底动手了,我把步骤分享出来,供大家参考,如果有错误,希望家友指正下,非常感谢!
免责声明:涉及到强电箱接线,一定要请专业的电工师傅操作!涉及到强电箱接线,一定要请专业的电工师傅操作!涉及到强电箱接线,一定要请专业的电工师傅操作!(重要的事情做3遍)
改造最终效果(见末尾图片,见图一、图二):
备注:我是10月下旬改造的,现在是11月,所以上月的电量和电费数据,以及今年的电量是不准的,上月的电量(比如缺少21天的电量)和今年的电量(比如缺少9个月+21天电量),我是通过国家电网查询到完整数据,计算后,追加到相关传感器里的,这个后面会讲。ui界面用了一个fold-entity-row的卡片,可以实现折叠功能,显示核心数据,隐藏非重要数据,如果有需要就点开,代码如下。
type: entities
title: 家庭电表
entities:
- entity: sensor.jin_ri_dian_liang
- entity: sensor.zuo_ri_dian_liang
- entity: sensor.ben_yue_dian_liang
- entity: sensor.jin_nian_dian_liang
- entity: sensor.jin_ri_dian_fei
- entity: sensor.zuo_ri_dian_fei
- entity: sensor.ben_yue_dian_fei
- entity: sensor.esp_current
- entity: sensor.esp_power
- type: custom:fold-entity-row
head:
type: section
label: 更多数据
open: false
padding: 0
entities:
- entity: sensor.esp_voltage
- entity: sensor.esp_power_factor
- entity: sensor.shang_yue_dian_liang
- entity: sensor.shang_yue_dian_fei
- entity: sensor.qu_nian_dian_liang
- entity: sensor.dang_qian_jie_ti_qing_kuang
state_color: false
show_header_toggle: true
关于设备:
智能电表我是在海鲜市场买的,卖家也是论坛里的,设备的型号应该是:PZEM-004T,是培正的电表模块,采用开合式电流互感器,这种比较方便安装,直接把互感器套在入户进火线上,然后给设备接零火供电,接线有要求的,具体你们自己可以问卖家,设备刷的是esphome,可以很方便的接入ha,断网可用,长期稳定。我买的是成品,设备是卖家焊接好,刷好固件,我只是负责给设备接好线,给设备配好网,这样就可以直接在ha里发现了。
esphome ota升级代码
代码里有个button按钮,会生成1个清空总电量的按钮,按下后,总电量就清空了,可以做为调试用,前几天可以观察下数据,比如跟国家电网每天的数据差异大不大,后期方便找规律要来修正电表,电表都有误差,我现在每天误差0.1度。
name: esp_meter
friendly_name: esp_meter
esp8266:
board: esp01_1m
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "D2*************"
ota:
password: "123456***"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp_meter"
password: ""
captive_portal:
web_server:
port: 80
uart:
rx_pin: GPIO03
tx_pin: GPIO01
baud_rate: 9600
id: mod_uart
modbus:
send_wait_time: 50ms
uart_id: mod_uart
id: mod_bus
button:
- platform: template
name: "kWh reset"
on_press:
then:
- delay: 5s
- pzemac.reset_energy: pzemac_1
sensor:
- platform: uptime
id: uptime_s
update_interval: 5s
- platform: pzemac
id: pzemac_1
energy:
name: "Energy"
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: "energy"
state_class: "total_increasing"
accuracy_decimals: 3
voltage:
name: "Voltage"
current:
name: "Current"
power:
name: "Power"
power_factor:
name: "power_factor"
frequency:
name: "Frequency"
address: 1
modbus_id: mod_bus
update_interval: 5s
- platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
name: "WiFi Signal dB"
id: wifi_signal_db
update_interval: 60s
entity_category: "diagnostic"
- platform: copy # Reports the WiFi signal strength in %
source_id: wifi_signal_db
name: "WiFi Signal"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "Signal %"
entity_category: "diagnostic"
text_sensor:
- platform: version
name: version
- platform: wifi_info
ip_address:
name: "esp_meter ip"
ssid:
name: ssid
- platform: template
name: "Uptime"
lambda: |-
int seconds = (id(uptime_s).state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
icon: mdi:clock-start
update_interval: 5s
binary_sensor:
- platform: status
name: "esp_meter Status"
接入ha(见图3)
电表配网后,ha会自动发现该设备,设备里会有这几个传感器,(总电量、电流、电压、功率、功率因素、开启时长、频率),其他的传感器是没有的(如:本月电量、今日电量等),需要我们自己配置,设备只会递增式的呈现总电量,截取昨日,今日,本月,上月等这些,需要辅助元素,对我们最重要的,就是这个总电量实体。
分隔电量(呈现今日电量,昨日电量、本月电量、上月电量、今年电量、去年电量等)
这个需要借助(创建辅助元素-仪表统计),举例:今日电量,填入如下信息,名称:今日电量、输入传感器:选择总电量实体,计量复位时间:每日。其他的不填默认就好,记住定期重置要选中,另外本月电量和今年电量也是按照这种方法,复位时间选每月、每年。按照此方法,就可以生成3个实体,今日电量、本月电量、今年电量,并且这3个实体会出现在电表的传感器列表实体里。
刚刚获得的今日、本月、今年电量实体属性里,有个last_period值,代表着上一期的值,即昨天、上月、去年电量,我们用辅助元素就可以直接创建这3个实体。(创建辅助元素-Template—Template sensor),举例创建昨日电量,name:昨日电量,State template填模板数据{{ state_attr('sensor.jin_ri_dian_liang','last_period')}},Unit of measurement填kWh,Device class填Energy,State class填Total increasing,然后提交就行了,其中sensor.jin_ri_dian_liang是代表刚刚上面创建的今日电量实体名称,其他2个上月和今年也是用这个方法,这样就得到了昨天电量,上月电量,去年电量。
追加数据(主要是今年电量和本月电量)
比如我是10月22日开始接入电表的,这样本月电量就缺少了21天,今年电量就缺少了9个月+21天,我们自己去国家电网,把这部分数据算出来+加上当前电表的电量,比如本月国家电网上,21天的总电量是100度,今天电表走了3度,那本月电量就是103度,我们需要把103追加到辅助元素创建的实体(本月电量里),需要用到(开发者工具-服务-仪表统计: 校准),目标选中:本月电量实体,下面的值填103。今年电量的修正,也是这样。
当前阶梯
这个是我用辅助元素里创建的(今年电量)实体的数字做判断的,判断现在处于第几阶梯电量,每个地方可能阶梯不一样,大家根据自己的实际情况修改。用(创建辅助元素-Template—Template sensor)创建1个当前阶梯的实体,平时也可以知道处于第几电价,后面的计算,也会用到这个值,代码如下。
{% if states("sensor.jin_nian_dian_liang") | float <= 2760 %}
1
{% elif states("sensor.jin_nian_dian_liang") | float >2760 and states("sensor.jin_nian_dian_liang") | float <= 4800 %}
2
{% elif states("sensor.jin_nian_dian_liang") | float > 4800 %}
3
{% endif %}
实时电价
根据上面创建的当前阶梯,结合时间,可以创建1个实时电价的的实体,可以后期接入能源面板显示电费和后面计算使用,其中sensor.dang_qian_jie_ti_2是上面创建的当前阶梯的实体名称,创建实时电价的步骤,用(创建辅助元素-Template—Template sensor)创建1个实时电价的实体,模板代码如下,单位填CNY/kWh,这样就创建了1个实时电价的传感器实体。注意写准确;阶梯1,阶梯2,阶梯3分别对应的峰电和谷电单价。
{% if now().strftime("%H")| int >= 8 and now().strftime("%H")|int < 22 and states("sensor.dang_qian_jie_ti_2")=="1" %}
0.568
{%elif now().strftime("%H")| int >= 8 and now().strftime("%H")|int < 22 and states("sensor.dang_qian_jie_ti_2")=="2" %}
0.618
{%elif now().strftime("%H")| int >= 8 and now().strftime("%H")|int < 22 and states("sensor.dang_qian_jie_ti_2")=="3" %}
0.868
{% elif states("sensor.dang_qian_jie_ti_2")=="1"%}
0.288
{% elif states("sensor.dang_qian_jie_ti_2")=="2" %}
0.338
{% elif states("sensor.dang_qian_jie_ti_2")=="3" %}
0.588
{% endif %}
接入能源(见图4):
消耗电能:选择总电量实体。选择实时电价实体:在下拉框里选择上面创建的实时电价实体,保存,数据会延后显示,可能会延后2个小时,这样就会实时计算电费了。
注意:有的时候,接入的电表不能在能源面板里找到这个总电量实体,可能是总电量实体的某些参数不符合ha规范,我的就不行,后面找了个简单的办法,用辅助元素转换下就行,(创建辅助元素-Template—Template sensor)名称:智能电表总电量,模板函数填:{{ states('总电量实体名')}},单位:kWh,设备类别:Energy,状态类别:Total increasing,提交保存。这样就复刻了1个标准规范的总电量的替身,用这个新实体,就可以接入能源了。
计算电费:
其实电费计算,还是比较复杂的,并不简单,有6种可能性,阶梯1峰电*对应电价,阶梯1谷电*对应电价,阶梯2峰电*对应电价,阶梯2谷电*对应电价,阶梯3峰电*对应电价,阶梯3谷电*对应电价,要想算的准确,就必须把这些属性,全部暴露出来,计算,才能用模板工具,创建传感器实体,这样才能在ha的前端ui卡片上显示。不然只能在能源面板里看,接下来,我们需要暴露(阶梯1峰电量、阶梯1谷电量、阶梯2峰电量、阶梯2谷电量、阶梯3峰电量、阶梯3谷电量),并且是需要,按天,月,年,甚至周,季度,规律性生成数据,这个需要用到ha的仪表统计代码和自动化代码,这个后面讲,获得对应数据后,就可以计算出电费。
电费计算思路:比如计算今日电费,今日电费=(今日阶梯1峰电量*阶梯1峰电价)+(今日阶梯1谷电量*阶梯1谷电价)+(今日阶梯2峰电量*阶梯2峰电价)+(今日阶梯2谷电量*阶梯2谷电价)+(今日阶梯3峰电量*阶梯3峰电价)+(今日阶梯3谷电量*阶梯3谷电价)。本月电费和今年电费也是用这个思路,另外昨日电费,上月电费,去年电费,在(今日、本月、去年电量)的实体属性里提取last_period值,last_period代表上一期的值,就可以生成(昨日,上月,去年的电费),用模板创建传感器实体即可。
分隔电量(阶梯1峰电量、阶梯1谷电量、阶梯2峰电量、阶梯2谷电量、阶梯3峰电量、阶梯3谷电量,按天,月,年)
configuration.yaml加入以下代码,source:填总电量实体,tariffs对应的会按照今日、本月、今年,分别会生成6个实体属性(阶梯1峰电量、阶梯1谷电量、阶梯2峰电量、阶梯2谷电量、阶梯3峰电量、阶梯3谷电量),这样ha就可以按照规则统计细分电量。
# #统计每日、月、年用电量。
utility_meter:
daily_use:
source: sensor.esp_energy
cycle: daily
name: 日用电
unique_id: daily_use
tariffs:
- peak
- offpeak
- peak2
- offpeak2
- peak3
- offpeak3
monthly_use:
source: sensor.esp_energy
cycle: monthly
name: 月用电
unique_id: monthly_use
tariffs:
- peak
- offpeak
- peak2
- offpeak2
- peak3
- offpeak3
yearly_use:
source: sensor.esp_energy
cycle: yearly
name: 年用电
unique_id: yearly_use
tariffs:
- peak
- offpeak
- peak2
- offpeak2
- peak3
- offpeak3
# #统计每日、月、年用电量。
自动化生成各阶梯的峰电量和谷电量
需要3个自动化,我不知道怎么把3个自动化合成1个,就用3个自动化了。代码如下;自动化的意思是,到8点,到22点,到阶梯2,阶梯3后,相关的操作,为日用的,月用电,年用电写入对应的数据,代码里会用到前面创建的当前阶梯实体,和日用电,月用电,年用电选择器。
alias: 峰谷1
description: ""
trigger:
- platform: time
at: "08:00:00"
condition: []
action:
- choose:
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "2"
sequence:
- service: select.select_option
data:
option: peak2
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "3"
sequence:
- service: select.select_option
data:
option: peak3
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
default:
- service: select.select_option
data:
option: peak
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
mode: single
alias: 峰谷2
description: ""
trigger:
- platform: time
at: "22:00:00"
condition: []
action:
- choose:
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "2"
sequence:
- service: select.select_option
data:
option: offpeak2
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "3"
sequence:
- service: select.select_option
data:
option: offpeak3
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
default:
- service: select.select_option
data:
option: offpeak
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
mode: single
alias: 峰谷
description: ""
trigger:
- platform: state
entity_id:
- sensor.dang_qian_jie_ti_2
from: "1"
to: "2"
- platform: state
entity_id:
- sensor.dang_qian_jie_ti_2
from: "2"
to: "3"
condition: []
action:
- choose:
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "2"
- condition: time
after: "08:00:00"
before: "22:00:00"
sequence:
- service: select.select_option
data:
option: peak2
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "3"
- condition: time
after: "08:00:00"
before: "22:00:00"
sequence:
- service: select.select_option
data:
option: peak3
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "2"
- condition: time
after: "22:00:00"
before: "08:00:00"
sequence:
- service: select.select_option
data:
option: offpeak2
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
- conditions:
- condition: state
entity_id: sensor.dang_qian_jie_ti_2
state: "3"
- condition: time
after: "22:00:00"
before: "08:00:00"
sequence:
- service: select.select_option
data:
option: offpeak3
target:
entity_id:
- select.daily_use
- select.monthly_use
- select.yearly_use
mode: single
计算今日电费/本月电费/今年电费
这里仅举例今日电费计算,这样需要用到辅助元素,创建传感器,(创建辅助元素-Template—Template sensor)名称:今日电费,模板函数代码如下,单位填;RMB,其他留空,按照这个方法,就可以得到今日电费、本月电费、今年电费。
注意: 部分数据可能要在经历1个周期后,才能正常,比如月用电细分数据(月用电阶梯1峰电、谷电电量,月用电阶梯2峰电、谷电电量,月用电阶梯3峰电、谷电电量)、年用电细分数据,这里指的是细分数据,不是月总量和年总量,总量不受影响
{% if is_number(states('sensor.daily_use_peak')) and is_number(states('sensor.daily_use_offpeak')) and is_number(states('sensor.daily_use_peak2')) and is_number(states('sensor.daily_use_offpeak2')) and is_number(states('sensor.daily_use_peak3')) and is_number(states('sensor.daily_use_offpeak3'))%}
{{((states("sensor.daily_use_peak") | float *0.568)+(states("sensor.daily_use_offpeak") | float * 0.288)+(states("sensor.daily_use_peak2") | float * 0.618)+(states("sensor.daily_use_offpeak2") | float * 0.338)+(states("sensor.daily_use_peak3") | float * 0.868)+(states("sensor.daily_use_offpeak3") | float * 0.588))| round(3)}}
{% else %}
None
{% endif %}
计算昨日电费/上月电费/去年电费
前面创建的日用的,月用电、年月电的实体属性里有个last_period值,last_period代表上一期的值,通过这个,就可以计算出昨日电费、上月电费、去年电费等,举例昨日电费、(创建辅助元素-Template—Template sensor)名称:昨日电费,模板函数代码如下,单位填RMB。
{% if is_number(state_attr('sensor.daily_use_peak','last_period')) and is_number(state_attr('sensor.daily_use_offpeak','last_period')) and is_number(state_attr('sensor.daily_use_peak2','last_period')) and is_number(state_attr('sensor.daily_use_offpeak2','last_period')) and is_number(state_attr('sensor.daily_use_peak3','last_period')) and is_number(state_attr('sensor.daily_use_offpeak3','last_period'))%}
{{((state_attr('sensor.daily_use_peak','last_period') | float * 0.568)+(state_attr('sensor.daily_use_offpeak','last_period')| float * 0.288)+(state_attr('sensor.daily_use_peak2','last_period') | float * 0.618+(state_attr('sensor.daily_use_offpeak2','last_period') | float *0.338)+(state_attr('sensor.daily_use_peak3','last_period') | float * 0.868)+(state_attr('sensor.daily_use_offpeak3','last_period')| float * 0.588))| round(3)}}
{% else %}
None
{% endif %}
电表校准:
任何电表都是有误差的,也是很正常的,我刚接入的时候,每天误差0.5度,月电量就会误差15度,年电量可能就会误差近200度,我考虑也好久,也没有想到完美解决方案,后来我想到了1个比较笨的方案,把误差控制在了0.1度1天左右,我还在观望中,不知道能不能长久,现在把方法分享出来。esp固件代码里,暴露总电量的部分,multiply: 0.001,kWh是千瓦时,1度差不多是1000w,所以才乘以0.001,所以我简单的吧multiply: 0.001改成了multiply: 0.00116,观察了几天,发现跟国家电网的误差基本上可以忽略不计了,这个方法肯定也不完美。
energy:
name: "Energy"
filters:
- multiply: 0.001
unit_of_measurement: kWh
device_class: "energy"
state_class: "total_increasing"
accuracy_decimals: 3
|