Files
Smartwave/cloud/app.py
T
Ninluc 1c2c07471e
Build, push image, and notify Watchtower / build-image (push) Successful in 43s
Build, push image, and notify Watchtower / notify (push) Successful in 11s
Timeout before sending + fix api
2026-08-10 14:20:36 +02:00

161 lines
5.2 KiB
Python

import os
import base64
import uuid
import datetime
import sys
import json
from flask import Flask, request, jsonify
from pymongo import MongoClient
from APIs import generate, EdamamAPI
from APIs.mqtt import send_command
from microwaveCookPlanner import MicrowaveCookPlanner
sys.path.insert(0, '..')
try:
from shared import config
except ImportError:
from ..shared import config
app = Flask(__name__)
# ---------------------------------------------------------
# Configuration & Setup
# ---------------------------------------------------------
# Configure MongoDB connection
MONGO_URI = os.getenv("MONGO_URI", "mongodb://localhost:27017/")
client = MongoClient(MONGO_URI)
db = client["microwave_network_db"]
cooking_collection = db["cooking_parameters"]
telemetry_collection = db["telemetry_data"]
# Ensure the camera image storage directory exists when the app starts
CAMERA_IMAGE_DIR = "storage/dishCameraImages"
os.makedirs(CAMERA_IMAGE_DIR, exist_ok=True)
# ---------------------------------------------------------
# Classes
# ---------------------------------------------------------
microwave_cook_planner = MicrowaveCookPlanner()
# ---------------------------------------------------------
# Routes
# ---------------------------------------------------------
@app.route("/")
def hello_world():
gen = generate(prompt="Say Hello, to the user !")
print(gen)
return f"<p>{gen}</p>"
@app.route("/cooking-params", methods=["POST"])
def cooking_params():
data = request.get_json()
if not data:
return jsonify({"error": "Invalid or missing JSON payload"}), 400
# Extract user or device parameters (with fallback defaults)
height_cm = float(data.get("dish_height", 4.0))
initial_temp_c = float(data.get("ir_initial_temp", 20.0)) # e.g., 4.0 for fridge, -18.0 for freezer
microwave_wattage = int(data.get("microwave_wattage", 900)) # e.g., 900W
defrost_mode = bool(data.get("defrost_mode", False)) # True for defrost, False for cook/reheat
print("Parsed parameters - Height (cm):", height_cm, "Initial Temp (C):", initial_temp_c, "Microwave Wattage:", microwave_wattage, "Defrost Mode:", defrost_mode)
# 1. Handle the Camera Image
camera_image_b64 = data.get("camera_image")
filepath = None
if camera_image_b64:
filename = f"dish_{uuid.uuid4().hex}.jpg"
filepath = os.path.join(CAMERA_IMAGE_DIR, filename)
try:
with open(filepath, "wb") as f:
f.write(base64.b64decode(camera_image_b64))
data["camera_image"] = filepath
except Exception as e:
return jsonify({"error": f"Failed to save camera image: {str(e)}"}), 500
else:
return jsonify({"error": "Missing required field 'camera_image'"}), 400
# 2. Run the Cook Planning Engine
try:
cook_plan = microwave_cook_planner.generate_plan(
image_path=filepath,
height_cm=height_cm,
initial_temp_c=initial_temp_c,
microwave_wattage=microwave_wattage,
defrost_mode=defrost_mode
)
except Exception as e:
return jsonify({"error": f"Failed to compute cooking plan: {str(e)}"}), 500
# 3. Attach cooking parameters to database record
data["analysis_results"] = cook_plan
# 4. Save to MongoDB
try:
cooking_collection.insert_one(data)
data.pop("_id", None)
except Exception as e:
return jsonify({"error": f"Database error: {str(e)}"}), 500
# 5. Return complete output
return jsonify(cook_plan), 201
@app.route("/telemetry", methods=["POST"])
def telemetry():
data = request.get_json()
if data is None:
return jsonify({"error": "Invalid or missing JSON payload"}), 400
# If the payload was double-encoded as a string, deserialize it
if isinstance(data, str):
try:
data = json.loads(data)
except (json.JSONDecodeError, TypeError):
return jsonify({"error": "String payload could not be parsed as JSON"}), 400
if not isinstance(data, dict):
return jsonify({"error": "Expected a JSON object/dictionary"}), 400
# Stamp UTC timestamp for Node-RED queries
data["received_at"] = datetime.datetime.now(datetime.timezone.utc).isoformat()
try:
telemetry_collection.insert_one(data)
return jsonify({"status": "success", "message": "Telemetry saved"}), 200
except Exception as e:
return jsonify({"error": f"Database error: {str(e)}"}), 500
@app.route("/debug", methods=["GET"])
def debug():
# Construct external HTTP endpoint dynamically based on incoming request host
telemetry_url = f"{request.host_url.rstrip('/')}/telemetry"
cmd_payload = {
"action": "request_telemetry",
"endpoint": telemetry_url
}
try:
send_command(topic="cmd/all", payload=cmd_payload)
return jsonify({
"status": "Telemetry command sent to cmd/all",
"published_payload": cmd_payload
}), 200
except Exception as e:
return jsonify({"error": f"Failed to publish MQTT command: {str(e)}"}), 500
if __name__ == "__main__":
app.run(debug=getattr(config, "DEBUG", True))