From 7313cdf24c1284270fa286b4e4ce7d5efe2eea7c Mon Sep 17 00:00:00 2001 From: William Le Date: Wed, 16 Apr 2025 18:43:38 +0800 Subject: [PATCH 1/2] feat(place/webhook_to_teams_msg): new logic driver --- drivers/place/webhook_to_teams_msg.cr | 44 ++++++++++++++++++++++ drivers/place/webhook_to_teams_msg_spec.cr | 5 +++ 2 files changed, 49 insertions(+) create mode 100644 drivers/place/webhook_to_teams_msg.cr create mode 100644 drivers/place/webhook_to_teams_msg_spec.cr diff --git a/drivers/place/webhook_to_teams_msg.cr b/drivers/place/webhook_to_teams_msg.cr new file mode 100644 index 0000000000..c5b6aa3bbf --- /dev/null +++ b/drivers/place/webhook_to_teams_msg.cr @@ -0,0 +1,44 @@ +require "placeos-driver" + +class Place::WebhookToTeamsMsg < PlaceOS::Driver + descriptive_name "Webhook to Teams Message" + generic_name :Webhook + description "Receive a webhook POST and send it's body to an MS Teams Channel" + + default_settings({ + teams_channel_id: "Required", + teams_group_id: "Required", + prepend_text_to_message: "", + append_text_to_message: "" + }) + + accessor staff_api : StaffAPI + + @teams_channel_id : String = "Required" + @teams_group_id : String = "Required" + @text_to_prepend : String = "" + @text_to_append : String = "" + + def on_load + on_update + end + + def on_update + @teams_channel_id = setting(String, :teams_channel_id) || "Required" + @teams_group_id = setting(String, :teams_group_id) || "Required" + @text_to_prepend = setting(String, :prepend_text_to_message) || "" + @text_to_append = setting(String, :append_text_to_message) || "" + end + + def receive_webhook(method : String, headers : Hash(String, Array(String)), body : String) + logger.debug { "Received Webhook with Method:#{method}, \nHeaders: #{headers}, \nBody: #{body}" } + return unless method == "POST" + + send_teams_message(body) + end + + def send_teams_message(message : String) + message = @text_to_prepend + message + @text_to_append + staff_api.send_channel_message(@teams_channel_id, @teams_group_id, message) + end +end diff --git a/drivers/place/webhook_to_teams_msg_spec.cr b/drivers/place/webhook_to_teams_msg_spec.cr new file mode 100644 index 0000000000..369a662b12 --- /dev/null +++ b/drivers/place/webhook_to_teams_msg_spec.cr @@ -0,0 +1,5 @@ +require "placeos-driver/spec" + +DriverSpecs.mock_driver "Place::WebhookToTeamsMsg" do + +end From bce0279c3415ad64e571018b58c2ec81b07957c3 Mon Sep 17 00:00:00 2001 From: William Le Date: Mon, 12 May 2025 16:57:04 +0800 Subject: [PATCH 2/2] feat(place/webhook_to_teams_msg): add Cisco RoomOS macro which triggers webhook --- ...webhook_to_teams_msg_Cisco_RoomOS_Macro.cr | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 drivers/place/webhook_to_teams_msg_Cisco_RoomOS_Macro.cr diff --git a/drivers/place/webhook_to_teams_msg_Cisco_RoomOS_Macro.cr b/drivers/place/webhook_to_teams_msg_Cisco_RoomOS_Macro.cr new file mode 100644 index 0000000000..a3598f91d1 --- /dev/null +++ b/drivers/place/webhook_to_teams_msg_Cisco_RoomOS_Macro.cr @@ -0,0 +1,104 @@ +// RoomOS Macro to create a touch panel button that sends a webhook with the device display name + +// Setup Instructions: +// Replace 'WEBHOOK_URL' with your actual webhook endpoint URL. +// You can customize the button appearance by changing: +// BUTTON_NAME: The text that appears on the button +// icon: The icon displayed (options include 'Webex', 'Handset', etc.) +// color: The button color in hex format +// Upload this macro to your Cisco device via the web interface: + // Access your device's Cisco admin web interface + // Go to Integration > Macro Editor + // Create a new macro and paste the code below + // Save and enable the macro + // The macro will create a persistent button on the home screen that sends the device name (which should be the room name) as a text body to your webhook endpoint when pressed. + + +const xapi = require('xapi'); + +// Configuration +const WEBHOOK_URL = 'https://_____/api/engine/v2/webhook/trig-IUWnbJR24C/notify/______________/Webhook/1/receive_webhook'; +const BUTTON_NAME = 'Request Assistance'; +const PANEL_ID = 'webhook_button'; + +// Create the touch panel button +function createPanel() { + const panel = { + panelId: PANEL_ID, + type: 'Home', + persistent: true, + icon: 'Webex', + color: '#0000FF', + name: BUTTON_NAME, + activityType: 'Custom' + }; + + xapi.command('UserInterface Extensions Panel Save', panel) + .then(() => { + console.log('Panel created successfully'); + }) + .catch((error) => { + console.error('Error creating panel:', error.message); + }); +} + +// Get the device display name +async function getDeviceDisplayName() { + try { + const config = await xapi.config.get('SystemUnit Name'); + return config; + } catch (error) { + console.error('Error getting device name:', error.message); + return 'Unknown Device'; + } +} + +// Send the webhook with device display name +async function sendWebhook() { + try { + // Get the device display name + const displayName = await getDeviceDisplayName(); + + // Send the webhook with the display name + await xapi.command('HttpClient Post', { + Url: WEBHOOK_URL, + Header: ['Content-Type: text/plain'], + Body: displayName + }); + + console.log('Webhook sent successfully with device name:', displayName); + + // Show feedback to user + xapi.command('UserInterface Message Alert Display', { + Title: 'Success', + Text: 'Webhook sent with device name', + Duration: 5 + }); + } catch (error) { + console.error('Failed to send webhook:', error.message); + xapi.command('UserInterface Message Alert Display', { + Title: 'Error', + Text: 'Failed to send webhook', + Duration: 5 + }); + } +} + +// Event listener for panel clicks +function listenForPanelClicks() { + xapi.event.on('UserInterface Extensions Panel Clicked', (event) => { + if (event.PanelId === PANEL_ID) { + console.log('Webhook button clicked'); + sendWebhook(); + } + }); +} + +// Initialize the macro +function init() { + createPanel(); + listenForPanelClicks(); + console.log('Webhook button macro initialized'); +} + +init(); \ No newline at end of file