Skip to content

Commit

Permalink
more fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
sainak committed Aug 29, 2024
1 parent 7e4e7a9 commit a8e782e
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 89 deletions.
12 changes: 4 additions & 8 deletions src/Components/Assets/AssetType/ONVIFCamera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import routes from "../../../Redux/api";
import useQuery from "../../../Utils/request/useQuery";

import CareIcon from "../../../CAREUI/icons/CareIcon";
import useOperateCamera from "../../CameraFeed/useOperateCamera";

interface Props {
assetId: string;
Expand Down Expand Up @@ -47,6 +48,8 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => {
});
const authUser = useAuthUser();

const { operate } = useOperateCamera(assetId ?? "", true);

useEffect(() => {
if (asset) {
setAssetType(asset?.asset_class);
Expand Down Expand Up @@ -92,21 +95,14 @@ const ONVIFCamera = ({ assetId, facilityId, asset, onUpdated }: Props) => {

const addPreset = async (e: SyntheticEvent) => {
e.preventDefault();
const config = getCameraConfig(asset as AssetData);
const data = {
bed_id: bed.id,
preset_name: newPreset,
};
try {
setLoadingAddPreset(true);

const response = await fetch(
`https://${resolvedMiddleware?.hostname}/status?hostname=${config.hostname}&port=${config.port}&username=${config.username}&password=${config.password}`,
);
if (!response.ok) {
throw new Error("Network error");
}
const presetData = await response.json();
const { data: presetData } = await operate({ type: "get_status" });

const { res } = await request(routes.createAssetBed, {
body: {
Expand Down
86 changes: 62 additions & 24 deletions src/Components/CameraFeed/CameraFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function CameraFeed(props: Props) {
const streamUrl = getStreamUrl(props.asset);
const inlineControls = useBreakpoints({ default: false, sm: true });

const player = usePlayer(streamUrl, playerRef);
const player = usePlayer(playerRef);

const [isFullscreen, setFullscreen] = useFullscreen();
const [state, setState] = useState<FeedAlertState>();
Expand Down Expand Up @@ -72,8 +72,27 @@ export default function CameraFeed(props: Props) {
getPresets(props.onCameraPresetsObtained);
}, [props.operate, props.onCameraPresetsObtained]);

const initializeStream = useCallback(() => {
const initializeStream = useCallback(async () => {
if (!playerRef.current) return;

const _streamUrl = await props
.operate({ type: "get_stream_token" })
.then(({ res, data }) => {
if (res?.status != 200) {
setState("authentication_error");
return props.onStreamError?.();
}
const result = data?.result as { token: string };
return getStreamUrl(props.asset, result.token);
})
.catch(() => {
setState("host_unreachable");
return props.onStreamError?.();
});

if (!_streamUrl) return;
player.initializeStream({
url: _streamUrl,
onSuccess: async () => {
props.onStreamSuccess?.();
const { res } = await props.operate({ type: "get_status" });
Expand All @@ -83,10 +102,12 @@ export default function CameraFeed(props: Props) {
},
onError: props.onStreamError,
});
}, [player.initializeStream]);
}, [playerRef.current]);

// Start stream on mount
useEffect(() => initializeStream(), [initializeStream]);
useEffect(() => {
initializeStream();
}, [initializeStream]);

const resetStream = () => {
setState("loading");
Expand Down Expand Up @@ -202,26 +223,43 @@ export default function CameraFeed(props: Props) {
{player.status === "playing" && <FeedWatermark />}

{/* No Feed informations */}
{state === "host_unreachable" && (
<NoFeedAvailable
message="Host Unreachable"
className="text-warning-500"
icon="l-exclamation-triangle"
streamUrl={streamUrl}
asset={props.asset}
onResetClick={resetStream}
/>
)}
{player.status === "offline" && (
<NoFeedAvailable
message="Offline"
className="text-secondary-500"
icon="l-exclamation-triangle"
streamUrl={streamUrl}
asset={props.asset}
onResetClick={resetStream}
/>
)}
{(() => {
switch (state) {
case "host_unreachable":
return (
<NoFeedAvailable
message="Host Unreachable"
className="text-warning-500"
icon="l-exclamation-triangle"
streamUrl={streamUrl}
asset={props.asset}
onResetClick={resetStream}
/>
);
case "authentication_error":
return (
<NoFeedAvailable
message="Authentication Error"
className="text-warning-500"
icon="l-exclamation-triangle"
streamUrl={streamUrl}
asset={props.asset}
onResetClick={resetStream}
/>
);
case "offline":
return (
<NoFeedAvailable
message="Offline"
className="text-secondary-500"
icon="l-exclamation-triangle"
streamUrl={streamUrl}
asset={props.asset}
onResetClick={resetStream}
/>
);
}
})()}

{/* Video Player */}
<video
Expand Down
32 changes: 20 additions & 12 deletions src/Components/CameraFeed/CameraFeedOld.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState, useRef } from "react";
import { useEffect, useState, useRef, useCallback } from "react";
import { useDispatch } from "react-redux";
import useKeyboardShortcut from "use-keyboard-shortcut";
import {
Expand Down Expand Up @@ -106,14 +106,11 @@ const CameraFeedOld = (props: any) => {

const videoEl = liveFeedPlayerRef.current as HTMLVideoElement;

const streamUrl = `wss://${middlewareHostname}/stream/${cameraAsset?.accessKey}/channel/0/mse?uuid=${cameraAsset?.accessKey}&channel=0`;

const { startStream } = useMSEMediaPlayer({
config: {
middlewareHostname,
...cameraAsset,
},
url: streamUrl,
videoEl,
});

Expand All @@ -124,6 +121,7 @@ const CameraFeedOld = (props: any) => {
const {
absoluteMove,
getCameraStatus,
getStreamToken,
getPTZPayload,
getPresets,
gotoPreset,
Expand Down Expand Up @@ -243,12 +241,25 @@ const CameraFeedOld = (props: any) => {
}
}, [page.offset, cameraAsset.id, refreshPresetsHash]);

const startStreamFeed = () => {
const startStreamFeed = useCallback(async () => {
if (!liveFeedPlayerRef.current) return;

let _streamUrl = "";
await getStreamToken({
onSuccess: (data) => {
_streamUrl = `wss://${middlewareHostname}/stream/${cameraAsset?.accessKey}/channel/0/mse?uuid=${cameraAsset?.accessKey}&channel=0&token=${data.token}`;
},
onError: () => {
setStreamStatus(StreamStatus.Offline);
},
});
if (!_streamUrl) return;
startStream({
url: _streamUrl,
onSuccess: () => setStreamStatus(StreamStatus.Playing),
onError: () => setStreamStatus(StreamStatus.Offline),
});
};
}, [liveFeedPlayerRef.current]);

const viewOptions = (page: number) => {
return presets
Expand All @@ -272,7 +283,7 @@ const CameraFeedOld = (props: any) => {
return () => {
clearTimeout(tId);
};
}, [startStream, streamStatus]);
}, [startStreamFeed, streamStatus]);

const handlePagination = (cOffset: number) => {
setPage({
Expand All @@ -287,13 +298,10 @@ const CameraFeedOld = (props: any) => {
precision === 16 ? 1 : precision * 2,
);
},
reset: () => {
reset: async () => {
setStreamStatus(StreamStatus.Loading);
setVideoStartTime(null);
startStream({
onSuccess: () => setStreamStatus(StreamStatus.Playing),
onError: () => setStreamStatus(StreamStatus.Offline),
});
await startStreamFeed();
},
fullScreen: () => {
if (!liveFeedPlayerRef.current) return;
Expand Down
4 changes: 3 additions & 1 deletion src/Components/CameraFeed/FeedAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export type FeedAlertState =
| "moving"
| "zooming"
| "saving_preset"
| "host_unreachable";
| "host_unreachable"
| "authentication_error";

interface Props {
state?: FeedAlertState;
Expand All @@ -24,6 +25,7 @@ const ALERT_ICON_MAP: Partial<Record<FeedAlertState, IconName>> = {
zooming: "l-search",
saving_preset: "l-save",
host_unreachable: "l-exclamation-triangle",
authentication_error: "l-exclamation-triangle",
};

export default function FeedAlert({ state }: Props) {
Expand Down
10 changes: 9 additions & 1 deletion src/Components/CameraFeed/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export type GetStatusResponse = {
};
};

export type GetStreamTokenResponse = {
result: {
token: string;
};
};

export type GetPresetsResponse = {
result: Record<string, number>;
};
Expand All @@ -21,7 +27,9 @@ export const FeedRoutes = {
operateAsset: {
path: "/api/v1/asset/{id}/operate_assets/",
method: "POST",
TRes: Type<GetStatusResponse | GetPresetsResponse>(),
TRes: Type<
GetStreamTokenResponse | GetStatusResponse | GetPresetsResponse
>(),
TBody: Type<{ action: OperationAction }>(),
},
} as const;
19 changes: 19 additions & 0 deletions src/Components/CameraFeed/useFeedPTZ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ interface UseMSEMediaPlayerReturnType {
value?: number,
) => PTZPayload;
getCameraStatus: (options: IOptions) => void;
getStreamToken: (options: IOptions) => void;
getPresets: (options: IOptions) => void;
gotoPreset: (payload: IGotoPresetPayload, options: IOptions) => void;
}
Expand Down Expand Up @@ -88,6 +89,23 @@ const getCameraStatus =
: options?.onError && options.onError(resp));
};

const getStreamToken =
(config: IAsset, dispatch: any) =>
async (options: IOptions = {}) => {
if (!config.id) return;
const resp = await dispatch(
operateAsset(config.id, {
action: {
type: "get_stream_token",
},
}),
);
resp &&
(resp.status === 200
? options?.onSuccess && options.onSuccess(resp.data.result)
: options?.onError && options.onError(resp));
};

const getPresets =
(config: IAsset, dispatch: any) =>
async (options: IOptions = {}) => {
Expand Down Expand Up @@ -205,6 +223,7 @@ export const useFeedPTZ = ({
relativeMove: relativeMove(config, dispatch),
getPTZPayload,
getCameraStatus: getCameraStatus(config, dispatch),
getStreamToken: getStreamToken(config, dispatch),
getPresets: getPresets(config, dispatch),
gotoPreset: gotoPreset(config, dispatch),
};
Expand Down
Loading

0 comments on commit a8e782e

Please sign in to comment.