82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""REST API – board webhook receiver and JSON relay control."""
|
||
from datetime import datetime
|
||
from flask import Blueprint, request, jsonify, abort
|
||
|
||
from app import db, socketio
|
||
from app.models.board import Board
|
||
from app.services import workflow_engine
|
||
|
||
api_bp = Blueprint("api", __name__)
|
||
|
||
|
||
# ── webhook endpoint (boards POST input events here) ──────────────────────────
|
||
|
||
@api_bp.route("/webhook/<int:board_id>", methods=["POST"])
|
||
def webhook(board_id: int):
|
||
board = db.session.get(Board, board_id)
|
||
if board is None:
|
||
abort(404)
|
||
|
||
data = request.get_json(silent=True) or {}
|
||
input_num = data.get("input")
|
||
state = data.get("state")
|
||
|
||
if input_num is None or state is None:
|
||
return jsonify({"error": "missing input or state"}), 400
|
||
|
||
# Update cached input state
|
||
states = board.input_states
|
||
states[f"input_{input_num}"] = bool(state)
|
||
board.input_states = states
|
||
board.is_online = True
|
||
board.last_seen = datetime.utcnow()
|
||
db.session.commit()
|
||
|
||
# Let the workflow engine decide what to do
|
||
workflow_engine.process_input_event(board_id, int(input_num), bool(state))
|
||
|
||
# Push live update to all connected clients immediately
|
||
socketio.emit("board_update", {
|
||
"board_id": board_id,
|
||
"is_online": True,
|
||
"input_states": board.input_states,
|
||
"relay_states": board.relay_states,
|
||
})
|
||
|
||
return jsonify({"status": "ok"})
|
||
|
||
|
||
# ── JSON relay status ─────────────────────────────────────────────────────────
|
||
|
||
@api_bp.route("/boards/<int:board_id>/relays")
|
||
def relay_states(board_id: int):
|
||
board = db.get_or_404(Board, board_id)
|
||
return jsonify({
|
||
"board_id": board.id,
|
||
"name": board.name,
|
||
"is_online": board.is_online,
|
||
"relay_states": board.relay_states,
|
||
"input_states": board.input_states,
|
||
})
|
||
|
||
|
||
# ── JSON board list ───────────────────────────────────────────────────────────
|
||
|
||
@api_bp.route("/boards")
|
||
def board_list():
|
||
boards = Board.query.order_by(Board.name).all()
|
||
return jsonify([
|
||
{
|
||
"id": b.id,
|
||
"name": b.name,
|
||
"board_type": b.board_type,
|
||
"host": b.host,
|
||
"port": b.port,
|
||
"is_online": b.is_online,
|
||
"last_seen": b.last_seen.isoformat() if b.last_seen else None,
|
||
"relay_states": b.relay_states,
|
||
"input_states": b.input_states,
|
||
}
|
||
for b in boards
|
||
])
|