Files
homeassistant-jackery/main.py
不求圣剑 054fa172f2 feat: update MQTT broker and enhance data handling
- Changed MQTT broker address from 192.168.0.101 to 192.168.1.100 across multiple files.
- Introduced new data handling methods in data_transmission_example.py for constructing and parsing data requests and responses.
- Updated MQTT topics to follow a new structure for better organization and clarity.
- Enhanced sensor logic in JackeryHome component to support new data formats and improve device state management.
2025-11-18 11:06:31 +08:00

192 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import time
import random
import paho.mqtt.client as mqtt
MQTT_BROKER = "192.168.1.100"
MQTT_PORT = 1883
MQTT_CLIENT_ID = "jackery_home_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()