From 418a8806dba90a2463f194da759ed6338018d7d2 Mon Sep 17 00:00:00 2001 From: ‘liusuyi’ <1951119284@qq.com> Date: 星期一, 28 八月 2023 16:02:28 +0800 Subject: [PATCH] 增加实时报警聚合接口all --- /dev/null | 80 -------- ard-work/src/main/java/com/ruoyi/alarm/global/controller/GlobalAlarmController.java | 7 ard-work/src/main/resources/templates/test.html | 37 -- ard-work/src/main/java/com/ruoyi/alarm/global/service/IGlobalAlarmService.java | 1 ard-work/src/main/java/com/ruoyi/alarm/global/service/impl/GlobalAlarmServiceImpl.java | 172 ++++++++++++++++ ard-work/src/main/resources/templates/mediaMTX.html | 283 ++++++++++++++++++++++++++++ ard-work/src/main/java/com/ruoyi/device/hiksdk/controller/SdkController.java | 5 7 files changed, 469 insertions(+), 116 deletions(-) diff --git a/ard-work/src/main/java/com/ruoyi/alarm/global/controller/GlobalAlarmController.java b/ard-work/src/main/java/com/ruoyi/alarm/global/controller/GlobalAlarmController.java index ae518cb..0b7e7a6 100644 --- a/ard-work/src/main/java/com/ruoyi/alarm/global/controller/GlobalAlarmController.java +++ b/ard-work/src/main/java/com/ruoyi/alarm/global/controller/GlobalAlarmController.java @@ -45,6 +45,13 @@ List<GlobalAlarmData> result = globalAlarmService.selectAlarmLogs(condition); return AjaxResult.success(result); } + @GetMapping("/AllList") + @ApiOperation(value = "瀹炴椂鎶ヨ鑱氬悎鎺ュ彛(all)",notes = "鎸夋姤璀﹀埛鏂版椂闂磋仛鍚堟煡璇�") + @ApiOperationSupport(includeParameters = {"command"},order = 1) + public AjaxResult selectAlarmLogAll() { + List<GlobalAlarmData> result = globalAlarmService.selectAlarmLogsAll(); + return AjaxResult.success(result); + } @PostMapping("/view") @ApiOperation(value = "鏌ョ湅鎶ヨ鎺ュ彛",notes = "鎸囧畾鏌ョ湅鏌愪釜鎶ヨ鏁版嵁") @ApiOperationSupport(includeParameters = {"command","id"},order = 3) diff --git a/ard-work/src/main/java/com/ruoyi/alarm/global/service/IGlobalAlarmService.java b/ard-work/src/main/java/com/ruoyi/alarm/global/service/IGlobalAlarmService.java index ecdb659..c4b6d45 100644 --- a/ard-work/src/main/java/com/ruoyi/alarm/global/service/IGlobalAlarmService.java +++ b/ard-work/src/main/java/com/ruoyi/alarm/global/service/IGlobalAlarmService.java @@ -15,6 +15,7 @@ **/ public interface IGlobalAlarmService { public List<GlobalAlarmData> selectAlarmLogs(GlobalAlarmCondition condition); + public List<GlobalAlarmData> selectAlarmLogsAll(); Object updateAlarmViewTime(GlobalAlarmCondition condition); public void receiveAlarm(String topic,String message); public Map<String,Object> selectAlarmLogsCount(); diff --git a/ard-work/src/main/java/com/ruoyi/alarm/global/service/impl/GlobalAlarmServiceImpl.java b/ard-work/src/main/java/com/ruoyi/alarm/global/service/impl/GlobalAlarmServiceImpl.java index 4cefccd..1572fae 100644 --- a/ard-work/src/main/java/com/ruoyi/alarm/global/service/impl/GlobalAlarmServiceImpl.java +++ b/ard-work/src/main/java/com/ruoyi/alarm/global/service/impl/GlobalAlarmServiceImpl.java @@ -278,6 +278,167 @@ } } + @Override + public List<GlobalAlarmData> selectAlarmLogsAll() { + List<GlobalAlarmData> GlobalAlarmDataList = new ArrayList<>(); + String refreshTime = configService.selectConfigByKey("refreshTime"); + List<ArdAlarmStealelec> ardAlarmStealelecs = ardAlarmStealelecMapper.selectListAllByCommand(refreshTime); + List<GlobalAlarmData> alarmData1001 = ardAlarmStealelecs.stream() + .map(ardAlarmStealelec -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmStealelec.getId()) + .setName(ardAlarmStealelec.getDescribe()) + .setAlarmTime(ardAlarmStealelec.getStartTime()) + .setLongitude(ardAlarmStealelec.getLongitude()) + .setLatitude(ardAlarmStealelec.getLatitude()) + .setAltitude(ardAlarmStealelec.getAltitude()) + .setCount(ardAlarmStealelec.getCount()) + .setTotal(ardAlarmStealelec.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1001.size()>0) { + GlobalAlarmDataList.addAll(alarmData1001); + } + + List<ArdAlarmCamera> ardAlarmCameras = ardAlarmCameraMapper.selectListAllByCommand(refreshTime); + List<GlobalAlarmData> alarmData1002= ardAlarmCameras.stream() + .map(ardAlarmCamera -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmCamera.getId()) + .setName(ardAlarmCamera.getCameraName()) + .setAlarmTime(ardAlarmCamera.getAlarmTime()) + .setLongitude(ardAlarmCamera.getLongitude()) + .setLatitude(ardAlarmCamera.getLatitude()) + .setCount(ardAlarmCamera.getCount()) + .setTotal(ardAlarmCamera.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1002.size()>0) { + GlobalAlarmDataList.addAll(alarmData1002); + } + + List<ArdAlarmRadar> ardAlarmRadars = ardAlarmRadarMapper.selectListAllByCommand(refreshTime, "杩愬姩鐩爣妫�娴�"); + List<GlobalAlarmData> alarmData1003= ardAlarmRadars.stream() + .map(ardAlarmRadar -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmRadar.getId()) + .setName(ardAlarmRadar.getName()) + .setAlarmTime(ardAlarmRadar.getAlarmTime()) + .setLongitude(ardAlarmRadar.getLongitude()) + .setLatitude(ardAlarmRadar.getLatitude()) + .setCount(ardAlarmRadar.getCount()) + .setTotal(ardAlarmRadar.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1003.size()>0) { + GlobalAlarmDataList.addAll(alarmData1003); + } + + ardAlarmRadars = ardAlarmRadarMapper.selectListAllByCommand(refreshTime, "鐑簮妫�娴�"); + List<GlobalAlarmData> alarmData1004= ardAlarmRadars.stream() + .map(ardAlarmRadar -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmRadar.getId()) + .setName(ardAlarmRadar.getName()) + .setAlarmTime(ardAlarmRadar.getAlarmTime()) + .setLongitude(ardAlarmRadar.getLongitude()) + .setLatitude(ardAlarmRadar.getLatitude()) + .setCount(ardAlarmRadar.getCount()) + .setTotal(ardAlarmRadar.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1004.size()>0) { + GlobalAlarmDataList.addAll(alarmData1004); + } + + List<ArdAlarmExternal> ardAlarmExternals = ardAlarmExternalMapper.selectListAllByCommand(refreshTime, "闃插尯鎶ヨ"); + List<GlobalAlarmData> alarmData1005= ardAlarmExternals.stream() + .map(ardAlarmExternal -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmExternal.getId()) + .setName(ardAlarmExternal.getAlarmName()) + .setAlarmTime(ardAlarmExternal.getAlarmTime()) + .setLongitude(ardAlarmExternal.getLongitude()) + .setLatitude(ardAlarmExternal.getLatitude()) + .setCount(ardAlarmExternal.getCount()) + .setTotal(ardAlarmExternal.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1005.size()>0) { + GlobalAlarmDataList.addAll(alarmData1005); + } + + List<ArdAlarmAccess> ardAlarmAccesses = ardAlarmAccessMapper.selectListAllByCommand(refreshTime); + List<GlobalAlarmData> alarmData1006= ardAlarmAccesses.stream() + .map(ardAlarmAccess -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmAccess.getId()) + .setName(ardAlarmAccess.getAcsName()) + .setAlarmTime(ardAlarmAccess.getAlarmTime()) + .setLongitude(ardAlarmAccess.getLongitude()) + .setLatitude(ardAlarmAccess.getLatitude()) + .setCount(ardAlarmAccess.getCount()) + .setTotal(ardAlarmAccess.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1006.size()>0) { + GlobalAlarmDataList.addAll(alarmData1006); + } + + ardAlarmRadars = ardAlarmRadarMapper.selectListAllByCommand(refreshTime, "闆疯揪鎶芥补鏈哄仠鏈�"); + List<GlobalAlarmData> alarmData1007= ardAlarmRadars.stream() + .map(ardAlarmRadar -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmRadar.getId()) + .setName(ardAlarmRadar.getName()) + .setAlarmTime(ardAlarmRadar.getAlarmTime()) + .setLongitude(ardAlarmRadar.getLongitude()) + .setLatitude(ardAlarmRadar.getLatitude()) + .setCount(ardAlarmRadar.getCount()) + .setTotal(ardAlarmRadar.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1007.size()>0) { + GlobalAlarmDataList.addAll(alarmData1007); + } + + List<ArdAlarmApponekey> ardAlarmApponekeys = ardAlarmApponekeyMapper.selectListAllByCommand(refreshTime); + List<GlobalAlarmData> alarmData1009= ardAlarmApponekeys.stream() + .map(ardAlarmApponekey -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmApponekey.getId()) + .setName(ardAlarmApponekey.getName()) + .setAlarmTime(ardAlarmApponekey.getCreateTime()) + .setLongitude(ardAlarmApponekey.getLongitude()) + .setLatitude(ardAlarmApponekey.getLatitude()) + .setCount(ardAlarmApponekey.getCount()) + .setTotal(ardAlarmApponekey.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1009.size()>0) { + GlobalAlarmDataList.addAll(alarmData1009); + } + + List<ArdAlarmTube> ardAlarmTubes = ardAlarmTubeMapper.selectListAllByCommand(refreshTime); + List<GlobalAlarmData> alarmData1014= ardAlarmTubes.stream() + .map(ardAlarmTube -> { + GlobalAlarmData globalAlarmData = new GlobalAlarmData() + .setId(ardAlarmTube.getId()) + .setName(ardAlarmTube.getTubeName()) + .setAlarmTime(ardAlarmTube.getAlarmTime()) + .setLongitude(ardAlarmTube.getLongitude()) + .setLatitude(ardAlarmTube.getLatitude()) + .setAltitude(ardAlarmTube.getAltitude()) + .setCount(ardAlarmTube.getCount()) + .setTotal(ardAlarmTube.getTotal()); + return globalAlarmData; + }).collect(Collectors.toList()); + if(alarmData1014.size()>0) { + GlobalAlarmDataList.addAll(alarmData1014); + } + return GlobalAlarmDataList; +} + /** * @鎻忚堪 鍘嗗彶鎶ヨ鏌ヨ * @鍙傛暟 [command, beginTime, endTime, pageNum, pageSize] @@ -542,9 +703,8 @@ } //鎸夊叴瓒g偣鍘婚噸,鐒跺悗鎸夊紩瀵奸�昏緫杩涜寮曞鍏ラ槦 ardAlarmRadars = ardAlarmRadars.stream() - .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new java.util.TreeSet<>(java.util.Comparator.comparing(ArdAlarmRadar::getName))), ArrayList::new)); - for(ArdAlarmRadar ardAlarmRadar : ardAlarmRadars) - { + .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new java.util.TreeSet<>(java.util.Comparator.comparing(ArdAlarmRadar::getName))), ArrayList::new)); + for (ArdAlarmRadar ardAlarmRadar : ardAlarmRadars) { //閬嶅巻鎶ヨ鏁版嵁杩涜寮曞 if (StringUtils.isNull(ardAlarmRadar.getLongitude()) || StringUtils.isNull(ardAlarmRadar.getLatitude())) { //鍧愭爣涓虹┖涓嶅紩瀵� @@ -766,10 +926,8 @@ return " "; } } - } - catch (Exception ex) - { - log.error("鑾峰彇闄勮繎寮�鍚姤璀﹀紩瀵煎姛鑳藉厜鐢靛紓甯�:"+ex.getMessage()); + } catch (Exception ex) { + log.error("鑾峰彇闄勮繎寮�鍚姤璀﹀紩瀵煎姛鑳藉厜鐢靛紓甯�:" + ex.getMessage()); } return minDistanceCameraId; } diff --git a/ard-work/src/main/java/com/ruoyi/device/hiksdk/controller/SdkController.java b/ard-work/src/main/java/com/ruoyi/device/hiksdk/controller/SdkController.java index 5ea793d..2053d50 100644 --- a/ard-work/src/main/java/com/ruoyi/device/hiksdk/controller/SdkController.java +++ b/ard-work/src/main/java/com/ruoyi/device/hiksdk/controller/SdkController.java @@ -59,7 +59,10 @@ private String index() { return "test"; } - + @RequestMapping("/media") + private String media() { + return "mediaMTX"; + } @GetMapping("/list") public @ResponseBody AjaxResult list(ArdCameras ardCamera) { diff --git a/ard-work/src/main/resources/static/js/WHEPClient.js b/ard-work/src/main/resources/static/js/WHEPClient.js deleted file mode 100644 index f84398b..0000000 --- a/ard-work/src/main/resources/static/js/WHEPClient.js +++ /dev/null @@ -1,76 +0,0 @@ -import negotiateConnectionWithClientOffer from "./negotiateConnectionWithClientOffer.js"; -/** - * Example implementation of a client that uses WHEP to playback video over WebRTC - * - * https://www.ietf.org/id/draft-murillo-whep-00.html - */ -export default class WHEPClient { - constructor(endpoint, videoElement) { - this.endpoint = endpoint; - this.videoElement = videoElement; - this.stream = new MediaStream(); - /** - * Create a new WebRTC connection, using public STUN servers with ICE, - * allowing the client to disover its own IP address. - * https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Protocols#ice - */ - this.peerConnection = new RTCPeerConnection({ - iceServers: [ - { - urls: "stun:stun.cloudflare.com:3478", - }, - ], - bundlePolicy: "max-bundle", - }); - /** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addTransceiver */ - this.peerConnection.addTransceiver("video", { - direction: "recvonly", - }); - this.peerConnection.addTransceiver("audio", { - direction: "recvonly", - }); - /** - * When new tracks are received in the connection, store local references, - * so that they can be added to a MediaStream, and to the <video> element. - * - * https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/track_event - */ - this.peerConnection.ontrack = (event) => { - const track = event.track; - const currentTracks = this.stream.getTracks(); - const streamAlreadyHasVideoTrack = currentTracks.some( - (track) => track.kind === "video" - ); - const streamAlreadyHasAudioTrack = currentTracks.some( - (track) => track.kind === "audio" - ); - switch (track.kind) { - case "video": - if (streamAlreadyHasVideoTrack) { - break; - } - this.stream.addTrack(track); - break; - case "audio": - if (streamAlreadyHasAudioTrack) { - break; - } - this.stream.addTrack(track); - break; - default: - console.log("got unknown track " + track); - } - }; - this.peerConnection.addEventListener("connectionstatechange", (ev) => { - if (this.peerConnection.connectionState !== "connected") { - return; - } - if (!this.videoElement.srcObject) { - this.videoElement.srcObject = this.stream; - } - }); - this.peerConnection.addEventListener("negotiationneeded", (ev) => { - negotiateConnectionWithClientOffer(this.peerConnection, this.endpoint); - }); - } -} diff --git a/ard-work/src/main/resources/static/js/negotiateConnectionWithClientOffer.js b/ard-work/src/main/resources/static/js/negotiateConnectionWithClientOffer.js deleted file mode 100644 index 26c70b6..0000000 --- a/ard-work/src/main/resources/static/js/negotiateConnectionWithClientOffer.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Performs the actual SDP exchange. - * - * 1. Constructs the client's SDP offer - * 2. Sends the SDP offer to the server, - * 3. Awaits the server's offer. - * - * SDP describes what kind of media we can send and how the server and client communicate. - * - * https://developer.mozilla.org/en-US/docs/Glossary/SDP - * https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html#name-protocol-operation - */ -export default async function negotiateConnectionWithClientOffer( - peerConnection, - endpoint -) { - /** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer */ - const offer = await peerConnection.createOffer(); - /** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription */ - await peerConnection.setLocalDescription(offer); - /** Wait for ICE gathering to complete */ - let ofr = await waitToCompleteICEGathering(peerConnection); - if (!ofr) { - throw Error("failed to gather ICE candidates for offer"); - } - /** - * As long as the connection is open, attempt to... - */ - while (peerConnection.connectionState !== "closed") { - /** - * This response contains the server's SDP offer. - * This specifies how the client should communicate, - * and what kind of media client and server have negotiated to exchange. - */ - let response = await postSDPOffer(endpoint, ofr.sdp); - if (response.status === 201) { - let answerSDP = await response.text(); - await peerConnection.setRemoteDescription( - new RTCSessionDescription({ type: "answer", sdp: answerSDP }) - ); - return response.headers.get("Location"); - } else if (response.status === 405) { - console.error("Update the URL passed into the WHIP or WHEP client"); - } else { - const errorMessage = await response.text(); - console.error(errorMessage); - } - /** Limit reconnection attempts to at-most once every 5 seconds */ - await new Promise((r) => setTimeout(r, 5000)); - } -} -async function postSDPOffer(endpoint, data) { - return await fetch(endpoint, { - method: "POST", - mode: "cors", - headers: { - "content-type": "application/sdp", - }, - body: data, - }); -} -/** - * Receives an RTCPeerConnection and waits until - * the connection is initialized or a timeout passes. - * - * https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html#section-4.1 - * https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/iceGatheringState - * https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/icegatheringstatechange_event - */ -async function waitToCompleteICEGathering(peerConnection) { - return new Promise((resolve) => { - /** Wait at most 1 second for ICE gathering. */ - setTimeout(function () { - resolve(peerConnection.localDescription); - }, 1000); - peerConnection.onicegatheringstatechange = (ev) => - peerConnection.iceGatheringState === "complete" && - resolve(peerConnection.localDescription); - }); -} diff --git a/ard-work/src/main/resources/templates/mediaMTX.html b/ard-work/src/main/resources/templates/mediaMTX.html new file mode 100644 index 0000000..2ae58db --- /dev/null +++ b/ard-work/src/main/resources/templates/mediaMTX.html @@ -0,0 +1,283 @@ +<!DOCTYPE html> +<html lang="en" xmlns:th="http://www.thymeleaf.org"> +<head> + <meta charset="UTF-8"> + <title>娴嬭瘯椤�</title> + <script th:src="@{/js/jquery-3.6.4.min.js}"></script> + <link rel="stylesheet" th:href="@{/css/bootstrap.css}"/> + <script th:src="@{/js/bootstrap.js}"></script> + <style> + .video-container { + display: inline-block; + vertical-align: top; + width: 25%; /* 鍏釜瑙嗛骞冲潎鍒嗛厤涓�琛岀殑瀹藉害 */ + /*padding: 2px; !* 鍙互鏍规嵁闇�瑕佽皟鏁村唴杈硅窛 *!*/ + box-sizing: border-box; + } + + .video-container video { + width: 100%; + height: 100%; + /*object-fit: cover; !* 瑙嗛濉厖瀹瑰櫒锛屼繚鎸佸楂樻瘮 *!*/ + } + </style> +<body> +<div> + <div class="row"> + <div class="video-container"> + <video id="video1" muted autoplay loop controls></video> + </div> + <div class="video-container"> + <video id="video2" muted autoplay loop controls></video> + </div> + <div class="video-container"> + <video id="video3" muted autoplay loop controls></video> + </div> + <div class="video-container"> + <video id="video4" muted autoplay loop controls></video> + </div> + <div class="video-container"> + <video id="video5" muted autoplay loop controls></video> + </div> + </div> +</div> +<script th:inline="javascript"> + const restartPause = 2000; + const linkToIceServers = (links) => ( + (links !== null) ? links.split(', ').map((link) => { + const m = link.match(/^<(.+?)>; rel="ice-server"(; username="(.*?)"; credential="(.*?)"; credential-type="password")?/i); + const ret = { + urls: [m[1]], + }; + + if (m[3] !== undefined) { + ret.username = unquoteCredential(m[3]); + ret.credential = unquoteCredential(m[4]); + ret.credentialType = "password"; + } + + return ret; + }) : [] + ); + const parseOffer = (offer) => { + const ret = { + iceUfrag: '', + icePwd: '', + medias: [], + }; + + for (const line of offer.split('\r\n')) { + if (line.startsWith('m=')) { + ret.medias.push(line.slice('m='.length)); + } else if (ret.iceUfrag === '' && line.startsWith('a=ice-ufrag:')) { + ret.iceUfrag = line.slice('a=ice-ufrag:'.length); + } else if (ret.icePwd === '' && line.startsWith('a=ice-pwd:')) { + ret.icePwd = line.slice('a=ice-pwd:'.length); + } + } + + return ret; + }; + const generateSdpFragment = (offerData, candidates) => { + const candidatesByMedia = {}; + for (const candidate of candidates) { + const mid = candidate.sdpMLineIndex; + if (candidatesByMedia[mid] === undefined) { + candidatesByMedia[mid] = []; + } + candidatesByMedia[mid].push(candidate); + } + + let frag = 'a=ice-ufrag:' + offerData.iceUfrag + '\r\n' + + 'a=ice-pwd:' + offerData.icePwd + '\r\n'; + + let mid = 0; + + for (const media of offerData.medias) { + if (candidatesByMedia[mid] !== undefined) { + frag += 'm=' + media + '\r\n' + + 'a=mid:' + mid + '\r\n'; + + for (const candidate of candidatesByMedia[mid]) { + frag += 'a=' + candidate.candidate + '\r\n'; + } + } + mid++; + } + + return frag; + } + + class WHEPClient { + constructor(wurl, videoId) { + this.video = videoId; + this.url = new URL('whep', wurl); + this.pc = null; + this.restartTimeout = null; + this.eTag = ''; + this.queuedCandidates = []; + this.start(); + } + + start() { + console.log("requesting ICE servers"); + fetch(this.url, { + method: 'OPTIONS', + }) + .then((res) => this.onIceServers(res)) + .catch((err) => { + console.log('error: ' + err); + this.scheduleRestart(); + }); + } + + onIceServers(res) { + this.pc = new RTCPeerConnection({ + iceServers: linkToIceServers(res.headers.get('Link')), + }); + + const direction = "sendrecv"; + this.pc.addTransceiver("video", {direction}); + this.pc.addTransceiver("audio", {direction}); + + this.pc.onicecandidate = (evt) => this.onLocalCandidate(evt); + this.pc.oniceconnectionstatechange = () => this.onConnectionState(); + + this.pc.ontrack = (evt) => { + console.log("new track:", evt.track.kind); + document.getElementById(this.video).srcObject = evt.streams[0]; + }; + + this.pc.createOffer() + .then((offer) => this.onLocalOffer(offer)); + } + + onLocalOffer(offer) { + this.offerData = parseOffer(offer.sdp); + this.pc.setLocalDescription(offer); + + console.log("sending offer"); + + fetch(this.url, { + method: 'POST', + headers: { + 'Content-Type': 'application/sdp', + }, + body: offer.sdp, + }) + .then((res) => { + if (res.status !== 201) { + throw new Error('bad status code'); + } + this.eTag = res.headers.get('E-Tag'); + return res.text(); + }) + .then((sdp) => this.onRemoteAnswer(new RTCSessionDescription({ + type: 'answer', + sdp, + }))) + .catch((err) => { + console.log('error: ' + err); + this.scheduleRestart(); + }); + } + + onConnectionState() { + if (this.restartTimeout !== null) { + return; + } + + console.log("peer connection state:", this.pc.iceConnectionState); + + switch (this.pc.iceConnectionState) { + case "disconnected": + this.scheduleRestart(); + } + } + + onRemoteAnswer(answer) { + if (this.restartTimeout !== null) { + return; + } + + this.pc.setRemoteDescription(new RTCSessionDescription(answer)); + + if (this.queuedCandidates.length !== 0) { + this.sendLocalCandidates(this.queuedCandidates); + this.queuedCandidates = []; + } + } + + onLocalCandidate(evt) { + if (this.restartTimeout !== null) { + return; + } + + if (evt.candidate !== null) { + if (this.eTag === '') { + this.queuedCandidates.push(evt.candidate); + } else { + this.sendLocalCandidates([evt.candidate]) + } + } + } + + sendLocalCandidates(candidates) { + fetch(this.url, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/trickle-ice-sdpfrag', + 'If-Match': this.eTag, + }, + body: generateSdpFragment(this.offerData, candidates), + }) + .then((res) => { + if (res.status !== 204) { + throw new Error('bad status code'); + } + }) + .catch((err) => { + console.log('error: ' + err); + this.scheduleRestart(); + }); + } + + scheduleRestart() { + if (this.restartTimeout !== null) { + return; + } + + if (this.pc !== null) { + this.pc.close(); + this.pc = null; + } + + this.restartTimeout = window.setTimeout(() => { + this.restartTimeout = null; + this.start(); + }, restartPause); + + this.eTag = ''; + this.queuedCandidates = []; + } + } + + let videoMap = new Map(); + $('video').click(function (e) { + let ID = e.target.id;//鑾峰彇褰撳墠鐐瑰嚮浜嬩欢鐨勫厓绱� + console.log(ID); + if (videoMap.get(ID) != null) { + closeVideo(ID, videoMap.get(ID)); + } else { + let client = new WHEPClient("http://127.0.0.1:8889/165/", ID); + videoMap.set(ID, client); + } + }); + function closeVideo(id) { + let elementById = document.getElementById(id); + elementById.pause(); + videoMap.delete(id); + } +</script> +</body> +</html> \ No newline at end of file diff --git a/ard-work/src/main/resources/templates/test.html b/ard-work/src/main/resources/templates/test.html index a55bf5e..3c125fa 100644 --- a/ard-work/src/main/resources/templates/test.html +++ b/ard-work/src/main/resources/templates/test.html @@ -13,20 +13,6 @@ margin-top: 10px; } </style> - <!-- 瀵煎叆 ECMAScript 妯″潡 --> - <script th:type="module" th:src="@{/js/WHEPClient.js}"></script> - <!-- 鍐呰仈鑴氭湰鍧楋紝鍙互浣跨敤妯″潡涓殑鍐呭 --> - <script th:inline="javascript"> - /*<![CDATA[*/ - // 鍦ㄨ繖閲屼娇鐢� WHEPClient 妯″潡涓殑鍐呭 - $("#play").click(function webrtcClient(){ - const url = "http://127.0.0.1:8889/165"; // add the webRTC URL from your live input here - console.log(url) - const videoElement = document.getElementById("remote-video"); - const client = new WHEPClient(url, videoElement); - }) - /*]]>*/ - </script> <body> <div class="container"> <div class="row "> @@ -141,15 +127,12 @@ <div class="row top-buffer"> <video id="video" muted autoplay loop controls style="width: 800px; height: 100%; object-fit: fill;"/> </div> - <div class="row top-buffer"> - <button id="play" type="button" class="btn btn-default" >鎾斁</button> - <video id="remote-video" controls autoplay muted></video> - </div> </div> </div> </div> -<script th:inline="javascript"> - var cameraId, opt,optOpen,optClose, token; +<script th:inline="javascript" th:type="module"> + + var cameraId, opt, optOpen, optClose, token; window.onload = function () { $.ajax({ url: "../hik/list", @@ -179,7 +162,6 @@ } } }) - opt = {"username": "admin", "password": "admin123"}; $.ajax({ headers: { @@ -479,8 +461,8 @@ var defogflag = true; $("#Defogcfg").click(function () { cameraId = $('#select option:selected').val(); - optOpen = {"cameraId": cameraId, "channelNum": 1, "enable": true}; - optClose = {"cameraId": cameraId, "channelNum": 1, "enable": false}; + optOpen = {"cameraId": cameraId, "channelNum": 1, "enable": true}; + optClose = {"cameraId": cameraId, "channelNum": 1, "enable": false}; if (defogflag) { $(this).text("鍏抽棴閫忛浘"); defogflag = false; @@ -521,8 +503,8 @@ var infrareflag = true; $("#Infrarecfg").click(function () { cameraId = $('#select option:selected').val(); - optOpen = {"cameraId": cameraId, "channelNum": 1, "enable": true}; - optClose = {"cameraId": cameraId, "channelNum": 1, "enable": false}; + optOpen = {"cameraId": cameraId, "channelNum": 1, "enable": true}; + optClose = {"cameraId": cameraId, "channelNum": 1, "enable": false}; if (infrareflag) { $(this).text("鍏抽棴绾㈠"); infrareflag = false; @@ -563,8 +545,8 @@ var focusModeflag = true; $("#FocusMode").click(function () { cameraId = $('#select option:selected').val(); - optOpen = {"cameraId": cameraId, "channelNum": 1, "enable": true}; - optClose = {"cameraId": cameraId, "channelNum": 1, "enable": false}; + optOpen = {"cameraId": cameraId, "channelNum": 1, "enable": true}; + optClose = {"cameraId": cameraId, "channelNum": 1, "enable": false}; if (focusModeflag) { $(this).text("鑷姩鑱氱劍"); focusModeflag = false; @@ -846,6 +828,5 @@ webRtcServer.disconnect(); } </script> - </body> </html> \ No newline at end of file -- Gitblit v1.9.3