Coverage for flask/src/rasp_water/webapp_schedule.py: 98%
64 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-28 13:51 +0900
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-28 13:51 +0900
1#!/usr/bin/env python3
2import json
3import multiprocessing
4import threading
5import urllib.parse
7import flask_cors
8import my_lib.flask_util
9import my_lib.webapp.config
10import my_lib.webapp.event
11import my_lib.webapp.log
12import rasp_water.scheduler
14import flask
16blueprint = flask.Blueprint("rasp-water-schedule", __name__, url_prefix=my_lib.webapp.config.URL_PREFIX)
18schedule_lock = threading.Lock()
19schedule_queue = None
20worker = None
22WDAY_STR = ["日", "月", "火", "水", "木", "金", "土"]
25def init(config):
26 global worker # noqa: PLW0603
27 global schedule_queue # noqa: PLW0603
29 if worker is not None: 29 ↛ 30line 29 didn't jump to line 30 because the condition on line 29 was never true
30 raise ValueError("worker should be None") # noqa: TRY003, EM101
32 schedule_queue = multiprocessing.Queue()
33 rasp_water.scheduler.init()
34 worker = threading.Thread(
35 target=rasp_water.scheduler.schedule_worker,
36 args=(
37 config,
38 schedule_queue,
39 ),
40 )
41 worker.start()
44def term():
45 global worker # noqa: PLW0603
47 if worker is None:
48 return
50 rasp_water.scheduler.should_terminate.set()
51 worker.join()
53 worker = None
56def wday_str_list(wday_list):
57 wday_str = WDAY_STR
58 return [wday_str[i] for i in range(len(wday_list)) if wday_list[i]]
61def schedule_entry_str(entry):
62 return "{} 開始 {} 分間 {}".format(entry["time"], entry["period"], ",".join(wday_str_list(entry["wday"])))
65def schedule_str(schedule):
66 str_buf = []
67 for entry in schedule:
68 if not entry["is_active"]:
69 continue
70 str_buf.append(schedule_entry_str(entry))
72 if len(str_buf) == 0:
73 return "∅ 全て無効"
75 return "、\n".join(str_buf)
78@blueprint.route("/api/schedule_ctrl", methods=["GET", "POST"])
79@my_lib.flask_util.support_jsonp
80@flask_cors.cross_origin()
81def api_schedule_ctrl():
82 cmd = flask.request.args.get("cmd", None)
83 data = flask.request.args.get("data", None)
84 if cmd == "set":
85 schedule_data = json.loads(data)
87 if not rasp_water.scheduler.schedule_validate(schedule_data):
88 my_lib.webapp.log.error("😵 スケジュールの指定が不正です。")
89 return flask.jsonify(rasp_water.scheduler.schedule_load())
91 with schedule_lock:
92 endpoint = urllib.parse.urljoin(
93 flask.request.url_root,
94 flask.url_for("rasp-water-valve.api_valve_ctrl"),
95 )
97 for entry in schedule_data:
98 entry["endpoint"] = endpoint
99 schedule_queue.put(schedule_data)
101 rasp_water.scheduler.schedule_store(schedule_data)
102 my_lib.webapp.event.notify_event(my_lib.webapp.event.EVENT_TYPE.SCHEDULE)
104 user = my_lib.flask_util.auth_user(flask.request)
105 my_lib.webapp.log.info(
106 "📅 スケジュールを更新しました。\n{schedule}\n{by}".format(
107 schedule=schedule_str(schedule_data),
108 by=f"by {user}" if user != "" else "",
109 )
110 )
112 return flask.jsonify(rasp_water.scheduler.schedule_load())