mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
new ptz ui
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -78,8 +78,8 @@
|
||||
<script defer src="https://analytics.otter.land/script.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land"></script>
|
||||
<script defer src="https://analytics.otter.land/recorder.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land" data-sample-rate="0.15" data-mask-level="moderate" data-max-duration="300000"></script>
|
||||
<title>Roomba Rover</title>
|
||||
<script type="module" crossorigin src="/assets/index-DT82w9Sn.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Dyg2cJnP.css">
|
||||
<script type="module" crossorigin src="/assets/index-YgdVe0Du.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-17XZRVBQ.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -7,8 +7,15 @@ const roverManager = require('../roverManager');
|
||||
const { getRole } = require('../roleService');
|
||||
const { describeAssignment } = require('../assignmentService');
|
||||
const { getNickname } = require('../nicknameService');
|
||||
const ptzCameraService = require('../ptzCameraService');
|
||||
|
||||
function resolvePtzChatTarget(socketId) {
|
||||
return ptzCameraService.getChatTargetForSocket(socketId) || null;
|
||||
}
|
||||
|
||||
function resolveRoverId(socketId) {
|
||||
const ptzTarget = resolvePtzChatTarget(socketId);
|
||||
if (ptzTarget?.roverId) return ptzTarget.roverId;
|
||||
const primary = roverManager.getPrimaryRoverForSocket(socketId);
|
||||
if (primary) return primary;
|
||||
const assignment = describeAssignment(socketId);
|
||||
@@ -17,10 +24,22 @@ function resolveRoverId(socketId) {
|
||||
|
||||
function resolveRoverColor(roverId) {
|
||||
if (!roverId) return null;
|
||||
if (String(roverId) === ptzCameraService.PTZ_CAMERA_ID) {
|
||||
return ptzCameraService.getPublicState()?.color || null;
|
||||
}
|
||||
const record = roverManager.rovers.get(String(roverId));
|
||||
return record?.meta?.color || null;
|
||||
}
|
||||
|
||||
function resolveRoverName(roverId) {
|
||||
if (!roverId) return null;
|
||||
if (String(roverId) === ptzCameraService.PTZ_CAMERA_ID) {
|
||||
return ptzCameraService.getPublicState()?.name || null;
|
||||
}
|
||||
const record = roverManager.rovers.get(String(roverId));
|
||||
return record?.meta?.name || null;
|
||||
}
|
||||
|
||||
function isPrivateClosedRoverId(roverId) {
|
||||
if (!roverId) return false;
|
||||
return roverManager.canReplayRoverId(roverId) !== true;
|
||||
@@ -100,6 +119,7 @@ function buildRoverCtxSnapshot(roverId) {
|
||||
function buildMessage(socket, text, meta = {}) {
|
||||
const roverId = meta.roverId || resolveRoverId(socket?.id);
|
||||
const roverColor = meta.roverColor ?? resolveRoverColor(roverId);
|
||||
const roverName = meta.roverName ?? resolveRoverName(roverId);
|
||||
const toolCalls = Array.isArray(meta.toolCalls)
|
||||
? meta.toolCalls
|
||||
.map((entry) => {
|
||||
@@ -122,6 +142,7 @@ function buildMessage(socket, text, meta = {}) {
|
||||
nickname: meta.nickname || getNickname(socket) || null,
|
||||
role: meta.role || getRole(socket),
|
||||
roverId,
|
||||
roverName,
|
||||
roverColor,
|
||||
fromDiscord: Boolean(meta.fromDiscord),
|
||||
discordGuildId: meta.discordGuildId || null,
|
||||
@@ -143,6 +164,7 @@ function buildMessage(socket, text, meta = {}) {
|
||||
function buildTypingPayload(socket, meta = {}) {
|
||||
const roverId = meta.roverId || resolveRoverId(socket?.id);
|
||||
const roverColor = meta.roverColor ?? resolveRoverColor(roverId);
|
||||
const roverName = meta.roverName ?? resolveRoverName(roverId);
|
||||
const socketId = socket?.id || null;
|
||||
const fromDiscord = Boolean(meta.fromDiscord);
|
||||
let typingId = meta.typingId || null;
|
||||
@@ -165,6 +187,7 @@ function buildTypingPayload(socket, meta = {}) {
|
||||
nickname: meta.nickname || getNickname(socket) || null,
|
||||
role: meta.role || getRole(socket),
|
||||
roverId,
|
||||
roverName,
|
||||
roverColor,
|
||||
fromDiscord,
|
||||
discordGuildId: meta.discordGuildId || null,
|
||||
|
||||
@@ -27,6 +27,7 @@ const DEFAULT_TURN_DURATION_MS = 5 * 60 * 1000;
|
||||
// PTZ is a normal replay source now, so capture should be on unless the feature
|
||||
// explicitly disables replay for the camera.
|
||||
const DEFAULT_REPLAY_ENABLED = true;
|
||||
const DEFAULT_PTZ_COLOR = '#387bf8';
|
||||
const SNAPSHOT_DIR = process.env.ROVER_SNAPSHOT_DIR || '/var/lib/rover-snapshots';
|
||||
const SNAPSHOT_POLL_MS = 300;
|
||||
const SNAPSHOT_STREAM_INTERVAL_MS = 2000;
|
||||
@@ -268,6 +269,7 @@ function getPublicState(socket = null) {
|
||||
enabled,
|
||||
id: PTZ_CAMERA_ID,
|
||||
name: cameraConfig.name || 'PTZ Camera',
|
||||
color: cameraConfig.color || DEFAULT_PTZ_COLOR,
|
||||
initialized: state.initialized,
|
||||
error: state.error,
|
||||
streamPath: state.streamPath,
|
||||
@@ -286,6 +288,25 @@ function getPublicState(socket = null) {
|
||||
};
|
||||
}
|
||||
|
||||
function getChatTargetForSocket(socketId) {
|
||||
/*
|
||||
Chat badges are rendered through the same rover badge component on the
|
||||
browser, so PTZ presents itself as a rover-like chat target while a user is
|
||||
actively operating or waiting for the camera. Keeping this mapping in the
|
||||
PTZ service avoids making chat infer camera queue details from public state.
|
||||
*/
|
||||
if (!enabled || !socketId) return null;
|
||||
const normalized = String(socketId);
|
||||
const waiting = state.queue.includes(normalized);
|
||||
const operating = state.operatorSocketId === normalized;
|
||||
if (!waiting && !operating) return null;
|
||||
return {
|
||||
roverId: PTZ_CAMERA_ID,
|
||||
roverName: cameraConfig.name || 'PTZ Camera',
|
||||
roverColor: cameraConfig.color || DEFAULT_PTZ_COLOR,
|
||||
};
|
||||
}
|
||||
|
||||
function callOnvif(method, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!onvifCam || typeof onvifCam[method] !== 'function') {
|
||||
@@ -1131,6 +1152,7 @@ module.exports = {
|
||||
PTZ_STREAM_PATH,
|
||||
ptzCameraEvents: events,
|
||||
getPublicState,
|
||||
getChatTargetForSocket,
|
||||
canRequestLiveVideo,
|
||||
disableEmittersForIdle,
|
||||
getReplaySource: () => enabled && isReplayEnabled()
|
||||
|
||||
Reference in New Issue
Block a user