From aaaeec1efd58a4dc4d77822ae85bbffa72d2a372 Mon Sep 17 00:00:00 2001 From: Hemanth Date: Thu, 26 Jun 2025 23:43:39 +0530 Subject: [PATCH 01/14] rtsp client connection --- package.json | 1 + server/monitor-types/RtspMonitorType.js | 56 +++++++++++++++++++++++++ server/uptime-kuma-server.js | 2 + 3 files changed, 59 insertions(+) create mode 100644 server/monitor-types/RtspMonitorType.js diff --git a/package.json b/package.json index 97b7bc339..327be7598 100644 --- a/package.json +++ b/package.json @@ -133,6 +133,7 @@ "qs": "~6.10.4", "redbean-node": "~0.3.0", "redis": "~4.5.1", + "rtsp-client": "^1.4.5", "semver": "~7.5.4", "socket.io": "~4.8.0", "socket.io-client": "~4.8.0", diff --git a/server/monitor-types/RtspMonitorType.js b/server/monitor-types/RtspMonitorType.js new file mode 100644 index 000000000..bc4f57486 --- /dev/null +++ b/server/monitor-types/RtspMonitorType.js @@ -0,0 +1,56 @@ +const RTSPClient = require("rtsp-client"); +const { log, UP, DOWN } = require("../../src/util"); +class RtspMonitorType { + name = "rtsp"; + + /** + * @param {Object} monitor - monitor config containing rtspUrl and timeout + * @param {Object} heartbeat - object to update with status and message + */ + async check(monitor, heartbeat) { + const url = monitor.rtspUrl; + const timeoutMs = (monitor.timeout || 10) * 1000; + + heartbeat.status = DOWN; + heartbeat.msg = "Starting RTSP stream check..."; + + if (!url || !url.startsWith("rtsp://")) { + heartbeat.status = DOWN; + heartbeat.msg = "Invalid RTSP URL"; + return; + } + + const client = new RTSPClient(); + + // Timeout promise to kill hanging connections + const timeoutPromise = new Promise((_, reject) => + setTimeout(() => reject(new Error("RTSP connection timed out")), timeoutMs) + ); + + try { + // Use Promise.race to enforce timeout + await Promise.race([ + (async () => { + await client.connect(url); + const describe = await client.describe(); + await client.close(); + + heartbeat.status = UP; + heartbeat.msg = "RTSP stream is accessible"; + })(), + timeoutPromise, + ]); + } catch (error) { + heartbeat.status = DOWN; + heartbeat.msg = `Error: ${error.message}`; + log.debug("monitor", `[${monitor.name}] RTSP check failed: ${error.message}`); + try { + await client.close(); + } catch {} + } + } +} + +module.exports = { + RtspMonitorType, +}; diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index a04e6bd49..b410ae85a 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -119,6 +119,7 @@ class UptimeKumaServer { UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType(); UptimeKumaServer.monitorTypeList["manual"] = new ManualMonitorType(); + UptimeKumaServer.monitorTypeList["rtsp"] = new RtspMonitorType(); // Allow all CORS origins (polling) in development let cors = undefined; @@ -560,4 +561,5 @@ const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); const { ManualMonitorType } = require("./monitor-types/manual"); +const {RtspMonitorType}= require("./monitor-types/RtspMonitorType") const Monitor = require("./model/monitor"); From 656c28e267a47e4c8ac431a86d0f325c5a8a5c33 Mon Sep 17 00:00:00 2001 From: Hemanth Date: Fri, 27 Jun 2025 10:01:55 +0530 Subject: [PATCH 02/14] file name changed --- server/monitor-types/{RtspMonitorType.js => rtsp.js} | 0 server/uptime-kuma-server.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename server/monitor-types/{RtspMonitorType.js => rtsp.js} (100%) diff --git a/server/monitor-types/RtspMonitorType.js b/server/monitor-types/rtsp.js similarity index 100% rename from server/monitor-types/RtspMonitorType.js rename to server/monitor-types/rtsp.js diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index b410ae85a..7bd7f6196 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -561,5 +561,5 @@ const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); const { ManualMonitorType } = require("./monitor-types/manual"); -const {RtspMonitorType}= require("./monitor-types/RtspMonitorType") +const {RtspMonitorType}= require("./monitor-types/rtsp") const Monitor = require("./model/monitor"); From bd3c8050c91ee302ac805b359e7428bd28a84947 Mon Sep 17 00:00:00 2001 From: Hemanth Date: Fri, 27 Jun 2025 22:27:53 +0530 Subject: [PATCH 03/14] added new columns --- db/knex_migrations/2025-06-27-0001-add-rtsp.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 db/knex_migrations/2025-06-27-0001-add-rtsp.js diff --git a/db/knex_migrations/2025-06-27-0001-add-rtsp.js b/db/knex_migrations/2025-06-27-0001-add-rtsp.js new file mode 100644 index 000000000..ca43423e0 --- /dev/null +++ b/db/knex_migrations/2025-06-27-0001-add-rtsp.js @@ -0,0 +1,18 @@ +// Add new columns and alter 'manual_status' to smallint +// migration file: add_rtsp_fields_to_monitor.js + +exports.up = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.string("rtsp_username"); + table.string("rtsp_password"); + table.string("rtsp_path"); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("rtsp_username"); + table.dropColumn("rtsp_password"); + table.dropColumn("rtsp_path"); + }); +}; From 6bc8936bc79688d6a664451fa5a5b7cc6644f4e8 Mon Sep 17 00:00:00 2001 From: Hemanth Date: Fri, 27 Jun 2025 22:29:50 +0530 Subject: [PATCH 04/14] added rtsp option --- src/pages/EditMonitor.vue | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 0d628895d..0c2174a60 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -97,6 +97,9 @@ + @@ -300,7 +303,7 @@ -
+
-
+
@@ -515,6 +518,23 @@
+ + + - - + + + + From 9a1d0e919012e4ffa518647aa19ff0a84a049164 Mon Sep 17 00:00:00 2001 From: Hemanth Date: Sun, 29 Jun 2025 21:09:34 +0530 Subject: [PATCH 14/14] used translation --- src/lang/en.json | 6 +++++- src/pages/EditMonitor.vue | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lang/en.json b/src/lang/en.json index a979edcc2..5664b40be 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -1123,5 +1123,9 @@ "Staged Tags for Batch Add": "Staged Tags for Batch Add", "Clear Form": "Clear Form", "pause": "Pause", - "Manual": "Manual" + "Manual": "Manual", + "RTSP Username": "RTSP Username", + "RTSP Password": "RTSP Password", + "RTSP Path": "RTSP Path", + "Path": "Path" } diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 9f6d51368..b57cf7ca3 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -520,7 +520,7 @@ @@ -1066,14 +1066,14 @@

{{ $t("Authentication") }}

- +
- +