本帖最后由 relliky 于 2023-4-1 17:01 编辑
之前在论坛里讨论了一下如何更好的维护自动化代码,各位大神支招后我尝试了一种用python代替蓝图的自动化的方法。好处就是可以写一个房间的package模板,然后直接生成每个房间的yaml文件。这样的话减少了代码的重复性,也比蓝图好测试很多,而且不单单只有自动化模板,其他的各种sensor的模板也可以加进去。python比yaml+jinja灵活很多,加上网上python的资料多,要做个什么搜一搜就出来了。
举个例子,因为yaml和json基本等价,可以把现有的yaml自动化转成json格式,而又因为python的语法和json一样,所以可以直接使用。yaml转成json可以直接使用我的这个小程序 https://github.com/relliky/Tais_ ... ert_yaml_to_json.py
转换后可以把json的自动化里面需要根据每个房间不同的配置的部分改成变量。然后直接自动导出成yaml就好。举个简单的自动化例子:
{
"alias":"LB-" + self.automation_room_name + "Remote Button - Double - Toggle Lamps",
"trigger": [
{
"platform": "state",
"entity_id": self.xiaomi_buttons,
"to": "double"
}
],
"action": [
self.turn(self.lamps, "toggle"),
]
}
上面的turn函数是我自己定义的,减少代码量去不去写 service:light.turn on, entity_id: self.lamps
再举一个复杂一点的例子:
self.automations += [{
"alias" : "LB-" + self.automation_room_name + "Remote Button - Single - Toggle Bed Lights/Ceiling Lights",
"trigger": [
{
"platform": "state",
"entity_id": self.xiaomi_buttons,
"to": "single"
}
],
"mode":"queued",
"action": [
{
"choose": [
# State Machine
# "All White" -> "Lamp LED White" -> "LED White"
# -> "Hue" -> "Night Mode" -> "Dark Night Mode"
# -> "All Off"
{
"conditions": [
{
"condition": "state",
"entity_id": self.ceiling_lights + self.lamps + self.leds,
"state": "off"
}
],
"sequence": self.setSceneService("All White")
},
# Default Room support these scenes
self.ifOldSceneSetNewScene("All White", "Lamp LED White"),
self.ifOldSceneSetNewScene("Lamp LED White", "LED White")
] + ([
# Master Room supports a few more scenes
self.ifOldSceneSetNewScene("LED White", "Hue"),
self.ifOldSceneSetNewScene("Hue", "Night Mode"),
self.ifOldSceneSetNewScene("Night Mode", "Dark Night Mode"),
self.ifOldSceneSetNewScene("Dark Night Mode", "All Off")
] if self.room_entity == 'master_room' else [
# Default Room does not support extra scenes
self.ifOldSceneSetNewScene("LED White", "All Off")
])
}
]
}]
def ifOldSceneSetNewScene (self, old_scene, new_scene):
cond_seq = {
"conditions": [
{
"condition": "state",
"entity_id": "input_select." + self.room_scene,
"state": old_scene
}
],
"sequence": [
{ "service": "input_select.select_option",
"target": {
"entity_id": "input_select." + self.room_scene
},
"data":{
"option": new_scene
}
},
{ "service": "homeassistant.turn_on",
"entity_id": "scene." + self.room_entity + new_scene }
]
}
return cond_seq
以上是个状态机。因为python语言的灵活性,不像yaml只能把script放在冒号后,python可以把任何函数放在几乎任何地方。python的函数也比script要灵活很多。比如choose里面调用condition-sequence对,这样的话,我就不用把 ifOldSceneSetNewScene 这段代码调用的部分复制粘贴很多遍。
现有的我的完整python文件在这里:https://github.com/relliky/Tais_ ... /gen_config_yaml.py 生成的yaml文件在这里:https://github.com/relliky/Tais_ ... _generated_packages 以后还会迁移更多的东西进这个python代码。
因为我的几个房间自动化几乎一致,变成这样以后比蓝图还是灵活很多。
|