first commit

This commit is contained in:
不求圣剑
2025-10-14 10:44:00 +08:00
commit 3f698d6e16
21 changed files with 1632 additions and 0 deletions

191
main.py Normal file
View File

@@ -0,0 +1,191 @@
import json
import time
import random
import paho.mqtt.client as mqtt
MQTT_BROKER = "192.168.0.101"
MQTT_PORT = 1883
MQTT_CLIENT_ID = "hem_simulator"
# 模式控制变量
# 0: 自发自用模式 (Self-consumption)
# 1: 电池优先模式 (Battery Priority)
current_mode = 0
# 模式名称映射
MODE_NAMES = {
0: "自发自用模式",
1: "电池优先模式"
}
client = mqtt.Client(client_id=MQTT_CLIENT_ID, callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
# MQTT 连接回调
def on_connect(client, userdata, flags, rc, properties):
print("Connected to MQTT broker with result code " + str(rc))
publish_discovery_configs()
# 订阅模式控制命令主题
client.subscribe("homeassistant/select/mode_control/set")
print("Subscribed to mode control command topic")
# MQTT 消息接收回调
def on_message(client, userdata, msg):
global current_mode
if msg.topic == "homeassistant/select/mode_control/set":
try:
payload = msg.payload.decode()
# 支持数字或模式名称
if payload.isdigit():
new_mode = int(payload)
elif payload == "自发自用模式":
new_mode = 0
elif payload == "电池优先模式":
new_mode = 1
else:
print(f"Invalid mode payload: {payload}")
return
if new_mode in [0, 1]:
current_mode = new_mode
# 发布新的状态(使用模式名称)
client.publish("homeassistant/select/mode_control/state", MODE_NAMES[current_mode])
print(f"模式已切换到: {MODE_NAMES[current_mode]} ({current_mode})")
else:
print(f"Invalid mode value: {new_mode}")
except ValueError:
print(f"Invalid mode payload: {msg.payload.decode()}")
client.on_connect = on_connect
client.on_message = on_message
def publish_discovery_configs():
"""发布 Home Assistant MQTT Discovery 配置"""
sensors = {
"solar_power": {
"name": "Solar Power",
"unit": "W",
"icon": "mdi:solar-power",
"device_class": "power",
},
"home_power": {
"name": "Home Power",
"unit": "W",
"icon": "mdi:home-lightning-bolt",
"device_class": "power",
},
# 电网 - 分为购买和出售
"grid_import": {
"name": "Grid Import",
"unit": "W",
"icon": "mdi:transmission-tower-import",
"device_class": "power",
},
"grid_export": {
"name": "Grid Export",
"unit": "W",
"icon": "mdi:transmission-tower-export",
"device_class": "power",
},
# 电池 - 分为充电和放电
"battery_charge": {
"name": "Battery Charge",
"unit": "W",
"icon": "mdi:battery-charging",
"device_class": "power",
},
"battery_discharge": {
"name": "Battery Discharge",
"unit": "W",
"icon": "mdi:battery-minus",
"device_class": "power",
},
"battery_soc": {
"name": "Battery State of Charge",
"unit": "%",
"icon": "mdi:battery-70",
"device_class": "battery",
},
}
for sensor_id, props in sensors.items():
topic = f"homeassistant/sensor/{sensor_id}/config"
payload = {
"name": props["name"],
"state_topic": f"homeassistant/sensor/{sensor_id}/state",
"unit_of_measurement": props["unit"],
"device_class": props["device_class"],
"icon": props["icon"],
"unique_id": sensor_id,
}
client.publish(topic, json.dumps(payload), retain=True)
print(f"Published discovery config for {sensor_id}")
# 发布模式控制的 discovery 配置
mode_topic = "homeassistant/select/mode_control/config"
mode_payload = {
"name": "运行模式",
"state_topic": "homeassistant/select/mode_control/state",
"command_topic": "homeassistant/select/mode_control/set",
"options": ["自发自用模式", "电池优先模式"],
"icon": "mdi:cog-outline",
"unique_id": "mode_control",
}
client.publish(mode_topic, json.dumps(mode_payload), retain=True)
print("Published discovery config for mode_control")
# 发布初始模式状态(使用模式名称)
client.publish("homeassistant/select/mode_control/state", MODE_NAMES[current_mode])
print(f"Published initial mode state: {MODE_NAMES[current_mode]} ({current_mode})")
def publish_sensor_data():
"""定期发布模拟功率数据"""
battery_soc = random.uniform(20, 100) # 初始电池电量
while True:
solar = random.uniform(200, 3000) # 太阳能发电
home = random.uniform(500, 3500) # 家庭负载
grid = home - solar # 电网供电(可能为负)
battery = random.uniform(-1000, 1000) # 电池充/放电
# 将电网功率分离为购买import和出售export
grid_import = max(0, grid) # 从电网购买(正值)
grid_export = max(0, -grid) # 向电网出售(转为正值)
# 将电池功率分离为充电和放电
battery_charge = max(0, -battery) # 充电(转为正值)
battery_discharge = max(0, battery) # 放电(正值)
# 根据电池充放电模拟电量变化
if battery < 0: # 充电
battery_soc = min(100, battery_soc + 0.5)
elif battery > 0: # 放电
battery_soc = max(0, battery_soc - 0.3)
data = {
"solar_power": round(solar, 2),
"home_power": round(home, 2),
"grid_import": round(grid_import, 2),
"grid_export": round(grid_export, 2),
"battery_charge": round(battery_charge, 2),
"battery_discharge": round(battery_discharge, 2),
"battery_soc": round(battery_soc, 1),
}
for key, value in data.items():
topic = f"homeassistant/sensor/{key}/state"
client.publish(topic, value)
# 发布当前模式状态
client.publish("homeassistant/select/mode_control/state", MODE_NAMES[current_mode])
print("Published:", data, f"| 运行模式: {MODE_NAMES[current_mode]}")
time.sleep(5)
if __name__ == "__main__":
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()
publish_sensor_data()