72 lines
2.5 KiB
Python
72 lines
2.5 KiB
Python
"""Workflow execution engine.
|
|
|
|
When a board input fires a webhook, this module evaluates all matching
|
|
enabled workflows and triggers the configured relay action.
|
|
"""
|
|
import logging
|
|
from datetime import datetime
|
|
|
|
from app import db, socketio
|
|
from app.models.workflow import Workflow
|
|
from app.models.board import Board
|
|
from app.services import board_service
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def process_input_event(board_id: int, input_num: int, new_state: bool) -> None:
|
|
"""Called from the webhook route. Finds and fires matching workflows."""
|
|
# Determine event type from state
|
|
event = "press" if new_state else "release"
|
|
|
|
workflows = Workflow.query.filter_by(
|
|
trigger_board_id=board_id,
|
|
trigger_input=input_num,
|
|
is_enabled=True,
|
|
).all()
|
|
|
|
for wf in workflows:
|
|
if wf.trigger_event not in (event, "both"):
|
|
continue
|
|
|
|
target = db.session.get(Board, wf.action_board_id)
|
|
if target is None:
|
|
logger.warning("Workflow %d: target board %d not found", wf.id, wf.action_board_id)
|
|
continue
|
|
|
|
success = False
|
|
new_relay_state = None
|
|
|
|
if wf.action_type == "on":
|
|
success = board_service.set_relay(target, wf.action_relay, True)
|
|
new_relay_state = True
|
|
elif wf.action_type == "off":
|
|
success = board_service.set_relay(target, wf.action_relay, False)
|
|
new_relay_state = False
|
|
elif wf.action_type == "toggle":
|
|
new_relay_state = board_service.toggle_relay(target, wf.action_relay)
|
|
success = new_relay_state is not None
|
|
|
|
if success:
|
|
wf.last_triggered = datetime.utcnow()
|
|
# Update cached relay state in DB
|
|
if new_relay_state is not None:
|
|
states = target.relay_states
|
|
states[f"relay_{wf.action_relay}"] = new_relay_state
|
|
target.relay_states = states
|
|
|
|
db.session.commit()
|
|
logger.info(
|
|
"Workflow '%s' fired: Board#%d.input%d=%s → Board#%d.relay%d [%s]",
|
|
wf.name, board_id, input_num, new_state,
|
|
target.id, wf.action_relay, wf.action_type,
|
|
)
|
|
# Push update so dashboard reflects new relay state instantly
|
|
socketio.emit("board_update", {
|
|
"board_id": target.id,
|
|
"relay_states": target.relay_states,
|
|
"is_online": target.is_online,
|
|
})
|
|
else:
|
|
logger.warning("Workflow '%s' failed to reach board %s", wf.name, target.name)
|