
我的Home Assistant本來有一支自動化,會在每個工作日早上的6:50自動執行語音廣播,描述一下今天是幾月幾號星期幾以及天氣預報怎麼樣等等,但被嫌太吵只好改成以通知的形式傳送。
- alias: Information:Today
triggers:
- trigger: time
at: "06:50:00"
actions:
- action: script.turn_on
target:
entity_id: script.notify_information
data:
variables:
msg: >
{% set greeting = ['早安', 'おはよう', 'Good morning', 'Buongiorno', '좋은 아침이에요', 'Guten Morgen', 'Bonjour'] | random %}
{% if state_attr('sensor.today', 'note') != "" and state_attr('sensor.today', 'note') is not none %}
{% set holiday = "," + state_attr('sensor.today', 'note') %}
{% else %}
{% set holiday = "" %}
{% endif %}
{{ greeting }},今天是{{ now().year }}年{{ now().month }}月{{ now().day }}日,星期{{ states('sensor.today') }}{{ holiday }}。目前室外溫度為{{ states('sensor.balcony4fr_climatesensor_temperature') | round(1) }}度,天氣{{ state_attr('sensor.today', 'Wx') }}。氣象預報未來十二小時內最高溫為{{ state_attr('sensor.today', 'MaxT') }}度,最低溫為{{ state_attr('sensor.today', 'MinT') }}度,降雨機率為{{ state_attr('sensor.today', 'PoP') }}%,整體體感{{ state_attr('sensor.today', 'CI') }}。
結果大概是長這樣,最前面的問候語是中、日、英、義、韓、德與法文隨機挑一個,用廣播形式講出來還滿好玩的。
整個自動化看下來,核心是sensor.today這個資料來源,sensor.today有二個主要的資料來源:
第一個資料來源是當年度的行事曆,以json的形式儲存,在自動化中可以搭配今天的日期,用來判斷今天是不是假日,本來用意是如果是假日就不會執行廣播避免被吵醒,但改成通知後其實也就沒有這個困擾。
[
{"date": "20250101", "weekday": "三", "holiday": true, "note": "元旦"},
{"date": "20250102", "weekday": "四", "holiday": false, "note": ""},
{"date": "20250103", "weekday": "五", "holiday": false, "note": ""},
{"date": "20250104", "weekday": "六", "holiday": true, "note": "例假日"},
{"date": "20250105", "weekday": "日", "holiday": true, "note": "例假日"},
{"date": "20250106", "weekday": "一", "holiday": false, "note": ""},
{"date": "20250107", "weekday": "二", "holiday": false, "note": ""},
{"date": "20250108", "weekday": "三", "holiday": false, "note": ""},
{"date": "20250109", "weekday": "四", "holiday": false, "note": ""},
{"date": "20250110", "weekday": "五", "holiday": false, "note": ""},
{"date": "20250111", "weekday": "六", "holiday": true, "note": "例假日"},
{"date": "20250112", "weekday": "日", "holiday": true, "note": "例假日"},
...
]
要產生這個json,可以利用python來處理,但需手動提供該年度假日的資訊在holidays裡
import calendar
import json
holidays = {
"20250101": "元旦",
"20250127": "小年夜",
"20250128": "除夕",
"20250129": "初一",
"20250130": "初二",
"20250131": "初三",
"20250201": "初四",
"20250202": "初五",
"20250228": "和平紀念日",
"20250403": "清明連假",
"20250404": "兒童節",
"20250405": "清明節",
"20250501": "勞動節",
"20250530": "端午連假",
"20250531": "端午節",
"20251006": "中秋節",
"20251010": "國慶日"
}
def generate_calendar(year):
day_list = []
week_map = ["一", "二", "三", "四", "五", "六", "日"]
for month in range(1, 13):
_, num_days = calendar.monthrange(year, month)
for day in range(1, num_days + 1):
date = f"{year}{month:02d}{day:02d}"
weekday = week_map[calendar.weekday(year, month, day)]
holiday = date in holidays
note = holidays.get(date, "")
if not holiday and weekday in ["六", "日"]:
holiday = True
note = "例假日"
day_info = f" {{\"date\": \"{date}\", \"weekday\": \"{weekday}\", \"holiday\": {str(holiday).lower()}, \"note\": \"{note}\"}}"
day_list.append(day_info)
return day_list
calendar_2025 = generate_calendar(2025)
with open('Calendar_2025.json', 'w', encoding='utf-8') as f:
f.write("[\n")
f.write(",\n".join(calendar_2025))
f.write("\n]")
第二個資料來源是天氣狀況,可以從中央氣象局的API獲取的json中提取,但需要先取得授權碼。
將這二個資料來源用一支python整合成一個MQTT訊息發送出去,程式碼today.py如下
import requests
from datetime import datetime
import json
import paho.mqtt.client as mqtt
mqtt_broker = "xxx.xxx.xxx.xxx"
mqtt_port = 1883
mqtt_username = "yyy"
mqtt_password = "zzz"
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.username_pw_set(mqtt_username, mqtt_password)
client.connect(mqtt_broker, mqtt_port)
today_year = datetime.today().strftime("%Y")
today_date = datetime.today().strftime("%Y%m%d")
with open(f"Calendar_{today_year}.json", 'r', encoding='utf-8') as f:
data = json.load(f)
today_items = [item for item in data if item["date"] == today_date]
for item in today_items:
weekday = item["weekday"]
holiday = item["holiday"]
note = item["note"]
url = 'https://opendata.cwa.gov.tw/fileapi/v1/opendataapi/F-C0032-001?Authorization=CWA-xxxxxx&downloadType=WEB&format=JSON'
response = requests.get(url)
if response.status_code == 200:
data = response.json()
location = data['cwaopendata']['dataset']['location']
weather = {}
for i in location:
if i['locationName'] == "臺南市":
for item in i['weatherElement']:
weather[item['elementName']] = item['time'][0]['parameter']['parameterName']
today = {
"Weekday": weekday,
"Holiday": holiday,
"Note": note,
"Wx": weather['Wx'],
"MaxT": weather['MaxT'],
"MinT": weather['MinT'],
"CI": weather['CI'],
"PoP": weather['PoP'],
}
result = json.dumps(today, ensure_ascii=False).encode('utf-8').decode()
client.publish(f"today", payload=result, retain=True)
client.disconnect()
發送出去的MQTT訊息長的像這樣
{
"Weekday": "一",
"Holiday": false,
"Note": "",
"Wx": "晴時多雲",
"MaxT": "15",
"MinT": "14",
"CI": "寒冷",
"PoP": "0"
}
利用cronjob,可以設定在每天的6:45發送一次這個MQTT訊息
45 6 * * * cd /home/tzungshiun/Python3/Weather/ && /usr/bin/python3 /home/tzungshiun/Python3/Weather/today.py
在Home Assistant中建立一個名為sensor.today的MQTT sensor,主要屬性為weekday,其他都是寫入attributes,這個sensor.today就是自動化裡的資料來源。
- name: Today
state_topic: "today"
value_template: "{{ value_json['Weekday'] }}"
json_attributes_topic: "today"
json_attributes_template: "{{ value_json | tojson }}"
action裡的script.turn_on,是取代原本Line Notify的服務,用的是Home Assistant Campion本身的通知功能,再搭配HACS HA-NotifyHelper所建構的script,這裡可以換成自己慣用的通知服務即可。