better Webex
This commit is contained in:
+33
-6
@@ -66,7 +66,7 @@ class WebexManager:
|
|||||||
new_doc = self.save_tokens(res.json())
|
new_doc = self.save_tokens(res.json())
|
||||||
return new_doc["access_token"]
|
return new_doc["access_token"]
|
||||||
|
|
||||||
def create_support_room(self, client_name: str, client_email: str) -> str:
|
def create_support_room(self, client_name: str, client_email: str, alert_type: str, alert_message: str, alert_id: str) -> str:
|
||||||
"""Creates a team support room and invites the client and yourself."""
|
"""Creates a team support room and invites the client and yourself."""
|
||||||
access_token = self.get_access_token()
|
access_token = self.get_access_token()
|
||||||
headers = {
|
headers = {
|
||||||
@@ -79,12 +79,13 @@ class WebexManager:
|
|||||||
f"{self.base_url}/rooms",
|
f"{self.base_url}/rooms",
|
||||||
headers=headers,
|
headers=headers,
|
||||||
json={
|
json={
|
||||||
"title": f"Smartwave Support: {client_name}",
|
"title": f"Smartwave Support: {client_name} - {alert_type} ({alert_id})",
|
||||||
"teamId": self.team_id
|
"teamId": self.team_id
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
room_res.raise_for_status()
|
room_res.raise_for_status()
|
||||||
room_id = room_res.json()["id"]
|
room_details = room_res.json()
|
||||||
|
room_id = room_details["id"]
|
||||||
|
|
||||||
# 2. Add Client via email (Webex sends invite if user does not exist)
|
# 2. Add Client via email (Webex sends invite if user does not exist)
|
||||||
if client_email:
|
if client_email:
|
||||||
@@ -103,13 +104,39 @@ class WebexManager:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 4. Optional: Send initial welcome message in the room
|
# 4. Optional: Send initial welcome message in the room
|
||||||
|
self.send_message(
|
||||||
|
room_id,
|
||||||
|
message=f"Support room initialized for {client_name}. An agent will be with you shortly.",
|
||||||
|
access_token=access_token
|
||||||
|
)
|
||||||
|
self.send_alert_info_message(room_id, alert_type, alert_message, alert_id, access_token=access_token)
|
||||||
|
|
||||||
|
return room_details
|
||||||
|
|
||||||
|
def send_message(self, room_id: str, message: str | None = None, markdown: str | None = None, access_token: str | None = None):
|
||||||
|
# Fetch the token so it auto-refreshes if needed
|
||||||
|
if not access_token:
|
||||||
|
access_token = self.get_access_token()
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {access_token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
requests.post(
|
requests.post(
|
||||||
f"{self.base_url}/messages",
|
f"{self.base_url}/messages",
|
||||||
headers=headers,
|
headers=headers,
|
||||||
json={
|
json={
|
||||||
"roomId": room_id,
|
"roomId": room_id,
|
||||||
"text": f"Support room initialized for {client_name}. An agent will be with you shortly."
|
"text": message,
|
||||||
|
"markdown": markdown
|
||||||
}
|
}
|
||||||
)
|
).raise_for_status()
|
||||||
|
|
||||||
return room_id
|
def send_alert_info_message(self, room_id: str, alert_type: str, alert_message: str, alert_id: str, added_alert_info: bool = False, access_token: str | None = None):
|
||||||
|
"""Sends a structured alert info message to the specified Webex room."""
|
||||||
|
if added_alert_info:
|
||||||
|
message = f"Additional Alert Details:\n- Type: {alert_type}\n- Message: {alert_message}\n- Alert ID: {alert_id}"
|
||||||
|
else:
|
||||||
|
message = f"Alert Details:\n- Type: {alert_type}\n- Message: {alert_message}\n- Alert ID: {alert_id}"
|
||||||
|
|
||||||
|
self.send_message(room_id, message=message, access_token=access_token)
|
||||||
+90
-19
@@ -2,19 +2,17 @@ import os
|
|||||||
import asyncio
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
import uuid
|
import uuid
|
||||||
import datetime
|
from datetime import datetime, timedelta, timezone
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import time
|
from flask import Flask, request, jsonify, current_app
|
||||||
import urllib.parse
|
|
||||||
import requests
|
|
||||||
from flask import Flask, request, jsonify, current_app, redirect, url_for
|
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
from APIs import generate, EdamamAPI
|
from APIs import generate, EdamamAPI
|
||||||
from APIs.mqtt import send_command
|
from APIs.mqtt import send_command
|
||||||
from APIs.webex import WebexManager
|
from APIs.webex import WebexManager
|
||||||
from microwaveCookPlanner import MicrowaveCookPlanner
|
from microwaveCookPlanner import MicrowaveCookPlanner
|
||||||
import safety_checker
|
import safety_checker
|
||||||
|
import pymongo
|
||||||
|
|
||||||
sys.path.insert(0, '..')
|
sys.path.insert(0, '..')
|
||||||
try:
|
try:
|
||||||
@@ -177,27 +175,100 @@ async def cooking_params():
|
|||||||
@app.route("/alert", methods=["POST"])
|
@app.route("/alert", methods=["POST"])
|
||||||
def alert():
|
def alert():
|
||||||
data = request.get_json() or {}
|
data = request.get_json() or {}
|
||||||
alert_collection.insert_one(data)
|
|
||||||
|
|
||||||
# Extract client metadata from alert payload (or use fallback values)
|
# 1. Inject a UTC timestamp so we can easily query the 3-minute window
|
||||||
client_name = data.get("client_name", "Unknown Client")
|
data["created_at"] = datetime.now(timezone.utc)
|
||||||
client_email = data.get("client_email")
|
saved_alert = alert_collection.insert_one(data)
|
||||||
|
|
||||||
room_id = None
|
# Extract orchestrator_id from the incoming alert
|
||||||
|
orchestrator_id = data.get("orchestrator_id")
|
||||||
|
|
||||||
|
# Safely extract alert info (prevents errors if "alert" is missing)
|
||||||
|
alert_info = data.get("alert", {})
|
||||||
|
alert_type = alert_info.get("type", "Unknown")
|
||||||
|
alert_message = alert_info.get("message", "No message provided")
|
||||||
|
|
||||||
|
# --- GET CLIENT METADATA ---
|
||||||
|
client_name = f"Unknown Client (Orchestrator {orchestrator_id})" if orchestrator_id else "Unknown Client"
|
||||||
|
client_email = None
|
||||||
|
|
||||||
|
if orchestrator_id:
|
||||||
|
client_doc = client_collection.find_one({
|
||||||
|
"devices": {
|
||||||
|
"$elemMatch": {
|
||||||
|
"device_type": "orchestrator",
|
||||||
|
"device_id": str(orchestrator_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if client_doc:
|
||||||
|
client_name = client_doc.get("client_name", client_name)
|
||||||
|
client_email = client_doc.get("contact_info", {}).get("email")
|
||||||
|
|
||||||
|
# --- WEBEX ROOM LOGIC ---
|
||||||
|
webex_room_id = None
|
||||||
webex_status = "skipped"
|
webex_status = "skipped"
|
||||||
|
|
||||||
# Automatically create Webex room if email or client name is supplied
|
# 2. Check if a room was created for this orchestrator in the last 3 minutes
|
||||||
try:
|
three_minutes_ago = datetime.now(timezone.utc) - timedelta(minutes=3)
|
||||||
room_id = webex_manager.create_support_room(client_name, client_email)
|
|
||||||
webex_status = "created"
|
recent_alert = alert_collection.find_one({
|
||||||
except Exception as e:
|
"orchestrator_id": orchestrator_id,
|
||||||
current_app.logger.exception("Failed to create Webex support room")
|
"webex_room_id": {"$exists": True, "$ne": None},
|
||||||
webex_status = f"failed: {str(e)}"
|
"created_at": {"$gte": three_minutes_ago},
|
||||||
|
"_id": {"$ne": saved_alert.inserted_id} # Exclude the alert we just inserted
|
||||||
|
}, sort=[("created_at", pymongo.DESCENDING)])
|
||||||
|
|
||||||
|
if recent_alert:
|
||||||
|
# A room was created recently -> Reuse it and just send a message
|
||||||
|
webex_room_id = recent_alert["webex_room_id"]
|
||||||
|
try:
|
||||||
|
webex_manager.send_alert_info_message(
|
||||||
|
room_id=webex_room_id,
|
||||||
|
alert_type=alert_type,
|
||||||
|
alert_message=alert_message,
|
||||||
|
alert_id=str(saved_alert.inserted_id)
|
||||||
|
)
|
||||||
|
webex_status = "reused_room"
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.exception("Failed to send follow-up message to existing Webex room")
|
||||||
|
webex_status = f"message_failed: {str(e)}"
|
||||||
|
|
||||||
|
else:
|
||||||
|
# No recent room -> Create a new one
|
||||||
|
try:
|
||||||
|
# Assuming your modified create_support_room returns a dict with {"id": ...}
|
||||||
|
room_details = webex_manager.create_support_room(
|
||||||
|
client_name,
|
||||||
|
client_email,
|
||||||
|
alert_type,
|
||||||
|
alert_message,
|
||||||
|
str(saved_alert.inserted_id) # Cast ObjectId to string for JSON serialization
|
||||||
|
)
|
||||||
|
|
||||||
|
# Extract ID based on whether your function returns a dict or just the ID string
|
||||||
|
webex_room_id = room_details["id"] if isinstance(room_details, dict) else room_details
|
||||||
|
webex_status = "created_new_room"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.exception("Failed to create Webex support room")
|
||||||
|
webex_status = f"creation_failed: {str(e)}"
|
||||||
|
|
||||||
|
# 3. Update the alert document with the Webex Room ID (whether new or reused)
|
||||||
|
if webex_room_id:
|
||||||
|
alert_collection.update_one(
|
||||||
|
{"_id": saved_alert.inserted_id},
|
||||||
|
{"$set": {"webex_room_id": webex_room_id}}
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- SEND SMS WITH DETAILS ---
|
||||||
|
# TODO: Add SMS logic here
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"status": "success",
|
"status": "success",
|
||||||
"message": "Alert saved",
|
"message": "Alert saved",
|
||||||
"webex_room_id": room_id,
|
"webex_room_id": webex_room_id,
|
||||||
"webex_status": webex_status
|
"webex_status": webex_status
|
||||||
}), 200
|
}), 200
|
||||||
|
|
||||||
@@ -220,7 +291,7 @@ def telemetry():
|
|||||||
return jsonify({"error": "Expected a JSON object/dictionary"}), 400
|
return jsonify({"error": "Expected a JSON object/dictionary"}), 400
|
||||||
|
|
||||||
# Stamp UTC timestamp for Node-RED queries
|
# Stamp UTC timestamp for Node-RED queries
|
||||||
data["received_at"] = datetime.datetime.now(datetime.timezone.utc).isoformat()
|
data["received_at"] = datetime.now(datetime.timezone.utc).isoformat()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
telemetry_collection.insert_one(data)
|
telemetry_collection.insert_one(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user