<!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> 
 | 
        .top-buffer { 
 | 
            margin-top: 10px; 
 | 
        } 
 | 
  
 | 
        .container { 
 | 
            border: 2px solid #1b6d85; 
 | 
            padding: 20px; 
 | 
        } 
 | 
    </style> 
 | 
<body> 
 | 
<div class="container"> 
 | 
    <div class="row "> 
 | 
        <div class="col-md-12"> 
 | 
            相机id:<select id="select" style="width: 330px;"> 
 | 
        </select> 
 | 
        </div> 
 | 
    </div> 
 | 
    <div class="row"> 
 | 
        <div class="col-md-5"> 
 | 
            <div class="row top-buffer"> 
 | 
                <div class="col-md-1 col-md-offset-1"> 
 | 
                    <button id="up" type="button" class="btn btn-primary">上</button> 
 | 
                </div> 
 | 
                <div class="col-md-6 col-md-offset-2"> 
 | 
                    <div class="btn-group" role="group"> 
 | 
                        <button id="controlZoomIn" type="button" class="btn btn-primary">调焦-</button> 
 | 
                        <button id="controlZoomOut" type="button" class="btn btn-primary">调焦+</button> 
 | 
                    </div> 
 | 
                </div> 
 | 
            </div> 
 | 
            <div class="row "> 
 | 
                <div class="col-md-1"> 
 | 
                    <button id="left" type="button" class="btn btn-primary">左</button> 
 | 
                </div> 
 | 
                <div class="col-md-1 col-md-offset-1"> 
 | 
                    <button id="right" type="button" class="btn btn-primary">右</button> 
 | 
                </div> 
 | 
                <div class="col-md-6 col-md-offset-1"> 
 | 
                    <div class="btn-group" role="group"> 
 | 
                        <button id="controlFocusNear" type="button" class="btn btn-primary">聚焦-</button> 
 | 
                        <button id="controlFocusFar" type="button" class="btn btn-primary">聚焦+</button> 
 | 
                    </div> 
 | 
                </div> 
 | 
            </div> 
 | 
            <div class="row "> 
 | 
                <div class="col-md-1 col-md-offset-1"> 
 | 
                    <button id="down" type="button" class="btn btn-primary">下</button> 
 | 
                </div> 
 | 
                <div class="col-md-6 col-md-offset-2"> 
 | 
                    <div class="btn-group" role="group"> 
 | 
                        <button id="controlIrisOpen" type="button" class="btn btn-primary">光圈-</button> 
 | 
                        <button id="controlIrisClose" type="button" class="btn btn-primary">光圈+</button> 
 | 
                    </div> 
 | 
                </div> 
 | 
            </div> 
 | 
            <div class="row "> 
 | 
                <div class="col-md-10"> 
 | 
                    <div class="row top-buffer"> 
 | 
                        <div class="input-group"> 
 | 
                            <span class="input-group-addon">目的坐标值:</span> 
 | 
                            <input id="targetPostion" class="form-control" placeholder="目的坐标"/> 
 | 
                            <button id="setTargetPostion" type="button" class="btn btn-default">指向坐标</button> 
 | 
                        </div> 
 | 
                        <div class="input-group"> 
 | 
                            <span class="input-group-addon">P值:</span> 
 | 
                            <input id="p" class="form-control" placeholder="请输入P值"/> 
 | 
                        </div> 
 | 
                        <div class="input-group"> 
 | 
                            <span class="input-group-addon">T值:</span> 
 | 
                            <input id="t" class="form-control" placeholder="请输入T值"/> 
 | 
                        </div> 
 | 
                        <div class="input-group"> 
 | 
                            <span class="input-group-addon">Z值:</span> 
 | 
                            <input id="z" class="form-control" placeholder="请输入Z值"/> 
 | 
                        </div> 
 | 
                    </div> 
 | 
                    <div class="row top-buffer"> 
 | 
                        <div class="btn-group" role="group"> 
 | 
                            <button id="getPTZ" type="button" class="btn btn-default">获取ptz</button> 
 | 
                            <button id="setPTZ" type="button" class="btn btn-default">设置ptz</button> 
 | 
                            <button id="setPreset" type="button" class="btn btn-default">设预置点</button> 
 | 
                            <button id="gotoPreset" type="button" class="btn btn-default">调预置点</button> 
 | 
                            <button id="setZeroPTZ" type="button" class="btn btn-default">设置零方位角</button> 
 | 
                        </div> 
 | 
                    </div> 
 | 
                    <div class="row top-buffer"> 
 | 
                        <div class="btn-group" role="group"> 
 | 
                            <button id="FocusMode" type="button" class="btn btn-default">手动聚焦</button> 
 | 
                            <div id="focusDiv" class="input-group"> 
 | 
                                <span class="input-group-addon">聚焦值:</span> 
 | 
                                <input id="focus" class="form-control" placeholder="聚焦值"/> 
 | 
                            </div> 
 | 
                            <button id="getFocusPos" type="button" class="btn btn-default">获取聚焦值</button> 
 | 
                            <button id="setFocusPos" type="button" class="btn btn-default">设置聚焦值</button> 
 | 
                        </div> 
 | 
                    </div> 
 | 
                    <div class="row top-buffer"> 
 | 
                        <div class="btn-group" role="group"> 
 | 
                            <button id="WiperPwron" type="button" class="btn btn-default">开启雨刷</button> 
 | 
                            <button id="Defogcfg" type="button" class="btn btn-default">开启透雾</button> 
 | 
                            <button id="Infrarecfg" type="button" class="btn btn-default">开启红外</button> 
 | 
                            <button id="HeateRpwron" type="button" class="btn btn-default">开启云台加热</button> 
 | 
                            <button id="CameraDeicing" type="button" class="btn btn-default">开启镜头加热</button> 
 | 
                        </div> 
 | 
                    </div> 
 | 
                    <div class="row top-buffer"> 
 | 
                        <div class="btn-group" role="group"> 
 | 
                            <button id="voice" type="button" class="btn btn-default">开始语音对讲</button> 
 | 
                            <button id="record" type="button" class="btn btn-default">开始录像</button> 
 | 
                            <button id="saveCutPic" type="button" class="btn btn-default">存储抓图</button> 
 | 
                        </div> 
 | 
                    </div> 
 | 
                </div> 
 | 
            </div> 
 | 
        </div> 
 | 
        <div class="col-md-6"> 
 | 
            <div class="row"> 
 | 
                <div class="row top-buffer"> 
 | 
                    <video id="video" muted autoplay loop controls 
 | 
                           style="width: 100%; height: 360px; object-fit: fill; border: 2px solid #3498db;"/> 
 | 
                </div> 
 | 
                <div class="row"> 
 | 
                    <img class="thumbnail" id="imgContainer" 
 | 
                         style="width: 100%; height: 360px; border: 2px solid #3498db;"/> 
 | 
                </div> 
 | 
            </div> 
 | 
        </div> 
 | 
    </div> 
 | 
</div> 
 | 
<script th:inline="javascript"> 
 | 
  
 | 
    var cameraId, opt, optOpen, optClose, token; 
 | 
    window.onload = function () { 
 | 
        console.log(RTCRtpReceiver.getCapabilities('video').codecs) 
 | 
        $.ajax({ 
 | 
            url: "../cameraSdk/list", 
 | 
            type: "get", 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
                var arr = data.data; 
 | 
                for (var i = 0; i < arr.length; i++) { 
 | 
                    console.log(arr[i].id); 
 | 
                    var camera = { 
 | 
                        name: arr[i].name, 
 | 
                        factory: arr[i].factory, 
 | 
                        ipaddr: arr[i].ip, 
 | 
                        username: arr[i].username, 
 | 
                        password: arr[i].password, 
 | 
                        port: arr[i].rtspPort, 
 | 
                        longitude: arr[i].longitude, 
 | 
                        latitude: arr[i].latitude, 
 | 
                        altitude: arr[i].altitude 
 | 
                    }; 
 | 
                    cameraMap.set(arr[i].id, camera); 
 | 
                    //先创建好select里面的option元素 
 | 
                    var option = document.createElement("option"); 
 | 
                    //给option的text赋值,这就是你点开下拉框能够看到的东西 
 | 
                    $(option).text(arr[i].id); 
 | 
                    //获取select 下拉框对象,并将option添加进select 
 | 
                    $('#select').append(option); 
 | 
                } 
 | 
            } 
 | 
        }) 
 | 
        opt = {"username": "admin", "password": "admin123"}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json' 
 | 
            }, 
 | 
            url: "../login", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                token = data.token; 
 | 
            } 
 | 
        }) 
 | 
        // 初始化内容 
 | 
        console.log(cameraMap); 
 | 
    } 
 | 
    //云台上下左右 
 | 
    $("#up").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 2; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
  
 | 
    }) 
 | 
    $("#up").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 2; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#down").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 8; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#down").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 8; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#left").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 4; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#left").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 4; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#right").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 6; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#right").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 6; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    //变倍 
 | 
    $("#controlZoomIn").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 10; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlZoomIn").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 10; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlZoomOut").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 11; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlZoomOut").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 11; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    //变焦 
 | 
    $("#controlFocusNear").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 12; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlFocusNear").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 12; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlFocusFar").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 13; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlFocusFar").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 13; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    //光圈 
 | 
    $("#controlIrisOpen").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 14; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlIrisOpen").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 14; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlIrisClose").mousedown(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 15; 
 | 
        var enable = true; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
    $("#controlIrisClose").mouseup(function () { 
 | 
        var url = "../cameraSdk/PTZControlWithSpeed"; 
 | 
        var code = 15; 
 | 
        var enable = false; 
 | 
        commondMethod(url, code, enable); 
 | 
    }) 
 | 
  
 | 
    $("#setPreset").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1, "speed": 8, "presetIndex": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/setPreset", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#gotoPreset").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1, "speed": 8, "presetIndex": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/gotoPreset", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#getPTZ").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/getPTZ", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (datas) { 
 | 
                console.log(datas); 
 | 
                $("#p").val(datas.data.p); 
 | 
                $("#t").val(datas.data.t); 
 | 
                $("#z").val(datas.data.z); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#setPTZ").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        var p = $('#p').val(); 
 | 
        var t = $('#t').val(); 
 | 
        var z = $('#z').val(); 
 | 
        //定义一个带有Map字段的实体对象 
 | 
        var myEntity = { 
 | 
            chanNo: 1, 
 | 
            cameraId: cameraId, 
 | 
            ptzMap: { 
 | 
                p: p, 
 | 
                t: t, 
 | 
                z: z 
 | 
            } 
 | 
        }; 
 | 
        console.log(opt) 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/setPTZ", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(myEntity), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#setTargetPostion").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        var camera = cameraMap.get(cameraId); 
 | 
        var camP = camera.longitude + ',' + camera.latitude + ',' + camera.altitude; 
 | 
        var targetP = $('#targetPostion').val(); 
 | 
        //定义一个带有Map字段的实体对象 
 | 
        var myEntity = { 
 | 
            chanNo: 1, 
 | 
            cameraId: cameraId, 
 | 
            targetPosition: targetP, 
 | 
            camPosition: camP, 
 | 
        }; 
 | 
        console.log(myEntity) 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/setTargetPosition", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(myEntity), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#setZeroPTZ").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/setZeroPTZ", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#WiperPwron").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1, "speed": 8, "enable": true, "code": 16}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/PTZControlWithSpeed", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    var defogflag = true; 
 | 
    $("#Defogcfg").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        optOpen = {"cameraId": cameraId, "chanNo": 1, "enable": true}; 
 | 
        optClose = {"cameraId": cameraId, "chanNo": 1, "enable": false}; 
 | 
        if (defogflag) { 
 | 
            $(this).text("关闭透雾"); 
 | 
            defogflag = false; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/defogcfg", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optOpen), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } else { 
 | 
            $(this).text("开启透雾"); 
 | 
            defogflag = true; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/defogcfg", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optClose), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } 
 | 
  
 | 
    }) 
 | 
    var infrareflag = true; 
 | 
    $("#Infrarecfg").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        optOpen = {"cameraId": cameraId, "chanNo": 1, "enable": true}; 
 | 
        optClose = {"cameraId": cameraId, "chanNo": 1, "enable": false}; 
 | 
        if (infrareflag) { 
 | 
            $(this).text("关闭红外"); 
 | 
            infrareflag = false; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/infrarecfg", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optOpen), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } else { 
 | 
  
 | 
            $(this).text("开启红外"); 
 | 
            infrareflag = true; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/infrarecfg", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optClose), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } 
 | 
    }) 
 | 
    var focusModeflag = true; 
 | 
    $("#FocusMode").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        optOpen = {"cameraId": cameraId, "chanNo": 1, "enable": true}; 
 | 
        optClose = {"cameraId": cameraId, "chanNo": 1, "enable": false}; 
 | 
        if (focusModeflag) { 
 | 
            $(this).text("自动聚焦"); 
 | 
            focusModeflag = false; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/focusMode", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optOpen), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } else { 
 | 
            $(this).text("手动聚焦"); 
 | 
            focusModeflag = true; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/focusMode", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optClose), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } 
 | 
    }) 
 | 
    $("#getFocusPos").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/getFocusPos", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (datas) { 
 | 
                console.log(datas); 
 | 
                $("#focus").val(datas.data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    var heateRpwronflag = true; 
 | 
    $("#HeateRpwron").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        optOpen = {"cameraId": cameraId, "chanNo": 1, "enable": true}; 
 | 
        optClose = {"cameraId": cameraId, "chanNo": 1, "enable": false}; 
 | 
        if (heateRpwronflag) { 
 | 
            $(this).text("关闭云台加热"); 
 | 
            heateRpwronflag = false; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/heateRpwron", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optOpen), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } else { 
 | 
            $(this).text("开启云台加热"); 
 | 
            heateRpwronflag = true; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/heateRpwron", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optClose), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } 
 | 
    }) 
 | 
    var CameraDeicingflag = true; 
 | 
    $("#CameraDeicing").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        optOpen = {"cameraId": cameraId, "chanNo": 1, "enable": true}; 
 | 
        optClose = {"cameraId": cameraId, "chanNo": 1, "enable": false}; 
 | 
        if (CameraDeicingflag) { 
 | 
            $(this).text("关闭镜头加热"); 
 | 
            CameraDeicingflag = false; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/cameraDeicing", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optOpen), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } else { 
 | 
            $(this).text("开启镜头加热"); 
 | 
            CameraDeicingflag = true; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/cameraDeicing", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optClose), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } 
 | 
    }) 
 | 
    $("#realCutPic").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/captureJPEGPicture", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data.data); 
 | 
                $("#imgContainer").attr("src", "data:image/png;base64," + data.data); 
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    $("#saveCutPic").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../cameraSdk/picCutCate", 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data.data); 
 | 
                setTimeout(() => { 
 | 
                    $('#imgContainer').attr('src', data.data); 
 | 
                }, 1000) 
 | 
  
 | 
            } 
 | 
        }) 
 | 
    }) 
 | 
    var recordflag = true; 
 | 
    $("#record").click(function () { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        optOpen = {"cameraId": cameraId, "chanNo": 1, "enable": true}; 
 | 
        optClose = {"cameraId": cameraId, "chanNo": 1, "enable": false}; 
 | 
        if (recordflag) { 
 | 
            $(this).text("停止录像"); 
 | 
            recordflag = false; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/record", 
 | 
                type: "post", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optOpen), 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } else { 
 | 
            $(this).text("开始录像"); 
 | 
            recordflag = true; 
 | 
            $.ajax({ 
 | 
                headers: { 
 | 
                    'Accept': 'application/json', 
 | 
                    'Content-Type': 'application/json', 
 | 
                    'Authorization': token 
 | 
                }, 
 | 
                url: "../cameraSdk/record", 
 | 
                dataType: "json", 
 | 
                data: JSON.stringify(optClose), 
 | 
                type: "post", 
 | 
                success: function (data) { 
 | 
                    console.log(data); 
 | 
                } 
 | 
            }) 
 | 
        } 
 | 
    }) 
 | 
  
 | 
    var cameraMap = new Map(); 
 | 
  
 | 
    /*云台公共方法*/ 
 | 
    function commondMethod(url, code, enable) { 
 | 
        cameraId = $('#select option:selected').val(); 
 | 
        opt = {"cameraId": cameraId, "chanNo": 1, "speed": 4, "enable": enable, "code": code}; 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: url, 
 | 
            type: "post", 
 | 
            dataType: "json", 
 | 
            data: JSON.stringify(opt), 
 | 
            success: function (data) { 
 | 
                console.log(data); 
 | 
            } 
 | 
        }) 
 | 
    } 
 | 
  
 | 
    $('video').click(function (e) { 
 | 
        var cameraId = $('#select option:selected').val(); 
 | 
        $.ajax({ 
 | 
            headers: { 
 | 
                'Accept': 'application/json', 
 | 
                'Content-Type': 'application/json', 
 | 
                'Authorization': token 
 | 
            }, 
 | 
            url: "../vtdu/media/" + cameraId + "_" + 1, 
 | 
            type: "get", 
 | 
            dataType: "json", 
 | 
            success: function (data) { 
 | 
                realView(data.data.webrtcUrl + "/", e.target.id); 
 | 
            } 
 | 
        }) 
 | 
    }); 
 | 
  
 | 
    let webrtcClient; 
 | 
    //whep操作方法 
 | 
    const restartPause = 2000; 
 | 
    const unquoteCredential = (v) => ( 
 | 
        JSON.parse(`"${v}"`) 
 | 
    ); 
 | 
    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(whepUrl, videoId) { 
 | 
            this.video = videoId; 
 | 
            this.wurl = new URL('whep', whepUrl); 
 | 
            this.pc = null; 
 | 
            this.restartTimeout = null; 
 | 
            this.eTag = ''; 
 | 
            this.queuedCandidates = []; 
 | 
            this.start(); 
 | 
        } 
 | 
  
 | 
        start() { 
 | 
            console.log("requesting ICE servers"); 
 | 
            fetch(this.wurl, { 
 | 
                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"); 
 | 
            console.log(this.wurl); 
 | 
            fetch(this.wurl, { 
 | 
                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('ETag'); 
 | 
                    this.eTag = res.headers.get("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.wurl, { 
 | 
                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 = []; 
 | 
        } 
 | 
  
 | 
        stop() { 
 | 
            if (this.pc) { 
 | 
                try { 
 | 
                    this.pc.close(); 
 | 
                } catch (e) { 
 | 
                    console.log("Failure close peer connection:" + e); 
 | 
                } 
 | 
                this.pc = null; 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    function realView(whepUrl, videoId) { 
 | 
        console.log(whepUrl) 
 | 
        webrtcClient = new WHEPClient(whepUrl, videoId); 
 | 
    } 
 | 
</script> 
 | 
</body> 
 | 
</html> 
 |