Initial commit: Location Management Flask app
This commit is contained in:
71
app/services/workflow_engine.py
Normal file
71
app/services/workflow_engine.py
Normal file
@@ -0,0 +1,71 @@
|
||||
"""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)
|
||||
Reference in New Issue
Block a user