Home Assistant每日問候語與台灣2025年行事曆json檔案

我的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,這裡可以換成自己慣用的通知服務即可。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端