added force end transmition for dispatchers

This commit is contained in:
PxlLoewe
2025-05-30 22:47:02 -07:00
parent eaedd78202
commit 6950e24e54
13 changed files with 179 additions and 100 deletions

View File

@@ -2,15 +2,15 @@ import { PublicUser } from "@repo/db";
import { dispatchSocket } from "dispatch/socket";
import { serverApi } from "_helpers/axios";
import {
handleActiveSpeakerChange,
handleDisconnect,
handleLocalTrackUnpublished,
handleTrackSubscribed,
handleTrackUnsubscribed,
} from "_helpers/liveKitEventHandler";
import { ConnectionQuality, Room, RoomEvent } from "livekit-client";
import { ConnectionQuality, Participant, Room, RoomEvent } from "livekit-client";
import { pilotSocket } from "pilot/socket";
import { create } from "zustand";
import axios from "axios";
let interval: NodeJS.Timeout;
@@ -18,19 +18,22 @@ type TalkState = {
micDeviceId: string | null;
micVolume: number;
isTalking: boolean;
source: string;
removeMessage: () => void;
state: "connecting" | "connected" | "disconnected" | "error";
message: string | null;
connectionQuality: ConnectionQuality;
remoteParticipants: number;
toggleTalking: () => void;
setMic: (micDeviceId: string | null, volume: number) => void;
connect: (roomName: string) => void;
connect: (roomName: string, role: string) => void;
disconnect: () => void;
speakingParticipants: Participant[];
addSpeakingParticipant: (participant: Participant) => void;
removeSpeakingParticipant: (speakingParticipants: Participant) => void;
room: Room | null;
};
const getToken = async (roomName: string) => {
const response = await serverApi.get(`/livekit/token?roomName=${roomName}`);
const response = await axios.get(`/api/livekit-token?roomName=${roomName}`);
const data = response.data;
return data.token;
};
@@ -39,12 +42,31 @@ export const useAudioStore = create<TalkState>((set, get) => ({
isTalking: false,
message: null,
micDeviceId: null,
speakingParticipants: [],
micVolume: 1,
state: "disconnected",
source: "",
remoteParticipants: 0,
connectionQuality: ConnectionQuality.Unknown,
room: null,
addSpeakingParticipant: (participant) => {
set((state) => {
if (!state.speakingParticipants.some((p) => p.identity === participant.identity)) {
return { speakingParticipants: [...state.speakingParticipants, participant] };
}
return state;
});
},
removeMessage: () => {
set({ message: null });
},
removeSpeakingParticipant: (participant) => {
set((state) => ({
speakingParticipants: state.speakingParticipants.filter(
(p) => !(p.identity === participant.identity),
),
}));
},
setMic: (micDeviceId, micVolume) => {
set({ micDeviceId, micVolume });
},
@@ -71,9 +93,9 @@ export const useAudioStore = create<TalkState>((set, get) => ({
});
}
set((state) => ({ isTalking: !state.isTalking, source: "web-app" }));
set((state) => ({ isTalking: !state.isTalking }));
},
connect: async (roomName) => {
connect: async (roomName, role) => {
set({ state: "connecting" });
console.log("Connecting to room: ", roomName);
try {
@@ -107,9 +129,11 @@ export const useAudioStore = create<TalkState>((set, get) => ({
// Track events
.on(RoomEvent.TrackSubscribed, handleTrackSubscribed)
.on(RoomEvent.TrackUnsubscribed, handleTrackUnsubscribed)
.on(RoomEvent.ActiveSpeakersChanged, handleActiveSpeakerChange)
.on(RoomEvent.LocalTrackUnpublished, handleLocalTrackUnpublished);
await room.connect(url, token, {});
room.localParticipant.setAttributes({
role,
});
set({ room });
interval = setInterval(() => {
@@ -137,14 +161,12 @@ interface PTTData {
}
const handlePTT = (data: PTTData) => {
console.log("PTT", data);
const { shouldTransmit, source } = data;
const { room } = useAudioStore.getState();
if (!room) return;
useAudioStore.setState({
isTalking: shouldTransmit,
source,
});
if (shouldTransmit) {
@@ -154,16 +176,19 @@ const handlePTT = (data: PTTData) => {
}
};
const handleOtherPTT = (data: { publicUser: PublicUser; channel: string; source: string }) => {
const currentChannel = useAudioStore.getState().room?.name;
console.log("Other PTT", data);
if (data.channel === currentChannel)
useAudioStore.setState({
source: data.source,
});
const handleForceEndTransmission = ({ by }: { by?: string }) => {
const { room } = useAudioStore.getState();
if (!room) return;
room.localParticipant.setMicrophoneEnabled(false);
useAudioStore.setState({
isTalking: false,
message: `Ruf beendet durch ${by || "unknown"}`,
});
};
pilotSocket.on("ptt", handlePTT);
pilotSocket.on("other-ptt", handleOtherPTT);
dispatchSocket.on("ptt", handlePTT);
dispatchSocket.on("other-ptt", handleOtherPTT);
pilotSocket.on("force-end-transmission", handleForceEndTransmission);
dispatchSocket.on("force-end-transmission", handleForceEndTransmission);

View File

@@ -34,7 +34,7 @@ export const useDispatchConnectionStore = create<ConnectionStore>((set) => ({
dispatchSocket.on("connect", () => {
const { logoffTime, selectedZone } = useDispatchConnectionStore.getState();
useAudioStore.getInitialState().connect("LST_01");
useAudioStore.getState().connect("LST_01", selectedZone || "Leitstelle");
dispatchSocket.emit("connect-dispatch", {
logoffTime,
selectedZone,

View File

@@ -64,7 +64,7 @@ pilotSocket.on("connect", () => {
usePilotConnectionStore.setState({ status: "connected", message: "" });
const { logoffTime, selectedStation } = usePilotConnectionStore.getState();
dispatchSocket.disconnect();
useAudioStore.getInitialState().connect("LST_01");
useAudioStore.getState().connect("LST_01", selectedStation?.bosCallsignShort || "pilot");
pilotSocket.emit("connect-pilot", {
logoffTime,