package com.genersoft.iot.vmp.jt1078.controller;

import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.conf.ftpServer.FtpSetting;
import com.genersoft.iot.vmp.conf.security.JwtUtils;
import com.genersoft.iot.vmp.jt1078.bean.*;
import com.genersoft.iot.vmp.jt1078.controller.bean.*;
import com.genersoft.iot.vmp.jt1078.proc.request.J1205;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078PlayService;
import com.genersoft.iot.vmp.jt1078.service.Ijt1078Service;
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;


@Slf4j
@ConditionalOnProperty(value = "jt1078.enable", havingValue = "true")
@RestController
@Tag(name  = "部标设备控制")
@RequestMapping("/api/jt1078")
public class JT1078Controller {

    @Resource
    private Ijt1078Service service;

    @Resource
    private Ijt1078PlayService jt1078PlayService;

    @Autowired
    private UserSetting userSetting;

    @Autowired
    private FtpSetting ftpSetting;

    @Operation(summary = "JT-开始点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "type", description = "类型：0:音视频,1:视频,3:音频", required = true)
    @GetMapping("/live/start")
    public DeferredResult<WVPResult<StreamContent>> startLive(HttpServletRequest request,
                                                              @Parameter(required = true) String phoneNumber,
                                                              @Parameter(required = true) Integer channelId,
                                                              @Parameter(required = false) Integer type) {
        if (type == null || (type != 0 && type != 1 && type != 3)) {
            type = 0;
        }
        DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
        result.onTimeout(()->{
            log.info("[JT-点播等待超时] phoneNumber：{}, channelId：{}, ", phoneNumber, channelId);
            // 释放rtpserver
            WVPResult<StreamContent> wvpResult = new WVPResult<>();
            wvpResult.setCode(ErrorCode.ERROR100.getCode());
            wvpResult.setMsg("超时");
            result.setResult(wvpResult);
            jt1078PlayService.stopPlay(phoneNumber, channelId);
        });

        jt1078PlayService.play(phoneNumber, channelId, type, wvpResult -> {
            WVPResult<StreamContent> wvpResultForFinish = new WVPResult<>();
            wvpResultForFinish.setCode(wvpResult.getCode());
            wvpResultForFinish.setMsg(wvpResult.getMsg());
            if (wvpResult.getCode() == InviteErrorCode.SUCCESS.getCode()) {
                StreamInfo streamInfo  = wvpResult.getData();

                if (streamInfo != null) {
                    if (userSetting.getUseSourceIpAsStreamIp()) {
                        streamInfo=streamInfo.clone();//深拷贝
                        String host;
                        try {
                            URL url=new URL(request.getRequestURL().toString());
                            host=url.getHost();
                        } catch (MalformedURLException e) {
                            host=request.getLocalAddr();
                        }
                        streamInfo.changeStreamIp(host);
                    }
                    wvpResultForFinish.setData(new StreamContent(streamInfo));
                }
            }
            result.setResult(wvpResultForFinish);
        });

        return result;
    }

    @Operation(summary = "JT-结束点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @GetMapping("/live/stop")
    public void stopLive(HttpServletRequest request,
                                                              @Parameter(required = true) String phoneNumber,
                                                              @Parameter(required = true) Integer channelId) {
        jt1078PlayService.stopPlay(phoneNumber, channelId);
    }

    @Operation(summary = "JT-语音对讲", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @GetMapping("/talk/start")
    public StreamContent startTalk(HttpServletRequest request,
                         @Parameter(required = true) String phoneNumber,
                         @Parameter(required = true) Integer channelId) {

        StreamInfo streamInfo = jt1078PlayService.startTalk(phoneNumber, channelId);
        if (userSetting.getUseSourceIpAsStreamIp()) {
            String host;
            try {
                URL url=new URL(request.getRequestURL().toString());
                host=url.getHost();
            } catch (MalformedURLException e) {
                host=request.getLocalAddr();
            }
            streamInfo.changeStreamIp(host);
        }
        streamInfo.setIp("localhost");
        return new StreamContent(streamInfo);
    }

    @Operation(summary = "JT-结束对讲", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @GetMapping("/talk/stop")
    public void stopTalk(HttpServletRequest request,
                         @Parameter(required = true) String phoneNumber,
                         @Parameter(required = true) Integer channelId) {
        jt1078PlayService.stopTalk(phoneNumber, channelId);
    }


    @Operation(summary = "JT-暂停点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @GetMapping("/live/pause")
    public void pauseLive(HttpServletRequest request,
                         @Parameter(required = true) String phoneNumber,
                         @Parameter(required = true) Integer channelId) {
        jt1078PlayService.pausePlay(phoneNumber, channelId);
    }

    @Operation(summary = "JT-继续点播", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @GetMapping("/live/continue")
    public void continueLive(HttpServletRequest request,
                          @Parameter(required = true) String phoneNumber,
                          @Parameter(required = true) Integer channelId) {

        jt1078PlayService.continueLivePlay(phoneNumber, channelId);
    }

    @Operation(summary = "JT-切换码流类型", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "streamType", description = "0:主码流; 1:子码流", required = true)
    @GetMapping("/live/switch")
    public void changeStreamType(HttpServletRequest request,
                             @Parameter(required = true) String phoneNumber,
                             @Parameter(required = true) Integer channelId,
                             @Parameter(required = true) Integer streamType) {
        service.changeStreamType(phoneNumber, channelId, streamType);
    }

    @Operation(summary = "JT-录像-查询资源列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "startTime", description = "开始时间,格式： yyyy-MM-dd HH:mm:ss", required = true)
    @Parameter(name = "endTime", description = "结束时间,格式： yyyy-MM-dd HH:mm:ss", required = true)
    @GetMapping("/record/list")
    public WVPResult<List<J1205.JRecordItem>> playbackList(HttpServletRequest request,
                                                                     @Parameter(required = true) String phoneNumber,
                                                                     @Parameter(required = true) Integer channelId,
                                                                     @Parameter(required = true) String startTime,
                                                                     @Parameter(required = true) String endTime
    ) {
        List<J1205.JRecordItem> recordList = jt1078PlayService.getRecordList(phoneNumber, channelId, startTime, endTime);
        if (recordList == null) {
            return WVPResult.fail(ErrorCode.ERROR100);
        }else {
            return WVPResult.success(recordList);
        }
    }
    @Operation(summary = "JT-录像-开始回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "startTime", description = "开始时间,格式： yyyy-MM-dd HH:mm:ss", required = true)
    @Parameter(name = "endTime", description = "结束时间,格式： yyyy-MM-dd HH:mm:ss", required = true)
    @Parameter(name = "type", description = "0.音视频 1.音频 2.视频 3.视频或音视频", required = true)
    @Parameter(name = "rate", description = "0.所有码流 1.主码流 2.子码流(如果此通道只传输音频,此字段置0)", required = true)
    @Parameter(name = "playbackType", description = "0.正常回放 1.快进回放 2.关键帧快退回放 3.关键帧播放 4.单帧上传", required = true)
    @Parameter(name = "playbackSpeed", description = "0.无效 1.1倍 2.2倍 3.4倍 4.8倍 5.16倍 (回放控制为1和2时,此字段内容有效,否则置0)", required = true)
    @GetMapping("/playback/start")
    public DeferredResult<WVPResult<StreamContent>> recordLive(HttpServletRequest request,
                                                              @Parameter(required = true) String phoneNumber,
                                                              @Parameter(required = true) Integer channelId,
                                                              @Parameter(required = true) String startTime,
                                                              @Parameter(required = true) String endTime,
                                                              @Parameter(required = false) Integer type,
                                                              @Parameter(required = false) Integer rate,
                                                              @Parameter(required = false) Integer playbackType,
                                                              @Parameter(required = false) Integer playbackSpeed

    ) {
        DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
        result.onTimeout(()->{
            log.info("[JT-回放-等待超时] phoneNumber：{}, channelId：{}, ", phoneNumber, channelId);
            // 释放rtpserver
            WVPResult<StreamContent> wvpResult = new WVPResult<>();
            wvpResult.setCode(ErrorCode.ERROR100.getCode());
            wvpResult.setMsg("回放超时");
            result.setResult(wvpResult);
            jt1078PlayService.stopPlay(phoneNumber, channelId);
        });

        jt1078PlayService.playback(phoneNumber, channelId, startTime, endTime,type, rate, playbackType, playbackSpeed,  wvpResult -> {
            WVPResult<StreamContent> wvpResultForFinish = new WVPResult<>();
            wvpResultForFinish.setCode(wvpResult.getCode());
            wvpResultForFinish.setMsg(wvpResult.getMsg());
            if (wvpResult.getCode() == InviteErrorCode.SUCCESS.getCode()) {
                StreamInfo streamInfo  = wvpResult.getData();
                if (streamInfo != null) {
                    if (userSetting.getUseSourceIpAsStreamIp()) {
                        String host;
                        try {
                            URL url=new URL(request.getRequestURL().toString());
                            host=url.getHost();
                        } catch (MalformedURLException e) {
                            host=request.getLocalAddr();
                        }
                        streamInfo.changeStreamIp(host);
                    }
                    wvpResultForFinish.setData(new StreamContent(streamInfo));
                }
            }
            result.setResult(wvpResultForFinish);
        });

        return result;
    }

    @Operation(summary = "JT-录像-回放控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "command", description = "0:开始回放; 1:暂停回放; 2:结束回放; 3:快进回放; 4:关键帧快退回放; 5:拖动回放; 6:关键帧播放", required = true)
    @Parameter(name = "playbackSpeed", description = "0.无效 1.1倍 2.2倍 3.4倍 4.8倍 5.16倍 (回放控制为3和4时,此字段内容有效,否则置0)", required = false)
    @Parameter(name = "time", description = "拖动回放位置(时间)", required = false)
    @GetMapping("/playback/control")
    public void recordControl(@Parameter(required = true) String phoneNumber,
                              @Parameter(required = true) Integer channelId,
                              @Parameter(required = false) Integer command,
                              @Parameter(required = false) String time,
                              @Parameter(required = false) Integer playbackSpeed

    ) {
        jt1078PlayService.playbackControl(phoneNumber, channelId, command, playbackSpeed, time);
    }

    @Operation(summary = "JT-录像-结束回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @GetMapping("/playback/stop")
    public void stopPlayback(HttpServletRequest request,
                         @Parameter(required = true) String phoneNumber,
                         @Parameter(required = true) Integer channelId) {
        jt1078PlayService.stopPlayback(phoneNumber, channelId);
    }

    @Operation(summary = "JT-录像-获取下载地址", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "startTime", description = "开始时间,格式： yyyy-MM-dd HH:mm:ss", required = true)
    @Parameter(name = "endTime", description = "结束时间,格式： yyyy-MM-dd HH:mm:ss", required = true)
    @Parameter(name = "alarmSign", description = "报警标志", required = true)
    @Parameter(name = "mediaType", description = "音视频资源类型： 0.音视频 1.音频 2.视频 3.视频或音视频", required = true)
    @Parameter(name = "streamType", description = "码流类型：0.所有码流 1.主码流 2.子码流(如果此通道只传输音频,此字段置0)", required = true)
    @Parameter(name = "storageType", description = "存储器类型", required = true)
    @GetMapping("/playback/downloadUrl")
    public String getRecordTempUrl(HttpServletRequest request,
                                   @Parameter(required = true) String phoneNumber,
                                   @Parameter(required = true) Integer channelId,
                                   @Parameter(required = true) String startTime,
                                   @Parameter(required = true) String endTime,
                                   @Parameter(required = false) Integer alarmSign,
                                   @Parameter(required = false) Integer mediaType,
                                   @Parameter(required = false) Integer streamType,
                                   @Parameter(required = false) Integer storageType

    ){
        log.info("[JT-录像] 下载，设备:{}， 通道： {}， 开始时间： {}， 结束时间： {}，报警标志: {}, 音视频类型： {}， 码流类型： {}，存储器类型： {}， ",
                phoneNumber, channelId, startTime, endTime, alarmSign, mediaType, streamType, storageType);
        if (!ftpSetting.getEnable()) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未启用ftp服务，无法下载录像");
        }
        return service.getRecordTempUrl(phoneNumber, channelId, startTime, endTime, alarmSign, mediaType, streamType, storageType);
    }

    @Operation(summary = "JT-录像-下载", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "path", description = "临时下载路径", required = true)
    @GetMapping("/playback/download")
    public void download(HttpServletRequest request, HttpServletResponse response, @Parameter(required = true) String path) throws IOException {
        if (!ftpSetting.getEnable()) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), "未启用ftp服务，无法下载录像");
        }
        DeferredResult<String> result = new DeferredResult<>();
        ServletOutputStream outputStream = response.getOutputStream();
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(path + ".mp4", "UTF-8"));
//        response.setContentLength(394983300);
        response.setStatus(HttpServletResponse.SC_OK);
        service.recordDownload(path, outputStream);
    }

    @Operation(summary = "JT-云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, zoomin, zoomout, irisin, irisout, focusnear, focusfar, stop", required = true)
    @Parameter(name = "speed", description = "速度(0-255)， command,值 left, right, up, down时有效", required = true)
    @GetMapping("/ptz")
    public void ptz(String phoneNumber, Integer channelId, String command, int speed){

        log.info("[JT-云台控制] phoneNumber：{}, channelId：{}, command: {}, speed: {}", phoneNumber, channelId, command, speed);
        service.ptzControl(phoneNumber, channelId, command, speed);
    }

    @Operation(summary = "JT-补光灯开关", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "command", description = "控制指令,允许值: on off", required = true)
    @GetMapping("/fill-light")
    public void fillLight(String phoneNumber, Integer channelId, String command){

        log.info("[JT-补光灯开关] phoneNumber：{}, channelId：{}, command: {}", phoneNumber, channelId, command);
        service.supplementaryLight(phoneNumber, channelId, command);
    }

    @Operation(summary = "JT-雨刷开关", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "channelId", description = "通道国标编号, 一般为从1开始的数字", required = true)
    @Parameter(name = "command", description = "控制指令,允许值: on off", required = true)
    @GetMapping("/wiper")
    public void wiper(String phoneNumber, Integer channelId, String command){

        log.info("[JT-雨刷开关] phoneNumber：{}, channelId：{}, command: {}", phoneNumber, channelId, command);
        service.wiper(phoneNumber, channelId, command);
    }

    @Operation(summary = "JT-查询终端参数", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @GetMapping("/config/get")
    public JTDeviceConfig config(String phoneNumber, String[] params){

        log.info("[JT-查询终端参数] phoneNumber：{}", phoneNumber);
        return service.queryConfig(phoneNumber, params);
    }

    @Operation(summary = "JT-设置终端参数", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "config", description = "终端参数", required = true)
    @PostMapping("/config/set")
    public void setConfig(@RequestBody SetConfigParam config){

        log.info("[JT-设置终端参数] 参数: {}", config.toString());
        service.setConfig(config.getPhoneNumber(), config.getConfig());
    }

    @Operation(summary = "终端控制-连接指定的服务器", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "control", description = "终端控制参数", required = true)
    @PostMapping("/control/connection")
    public void connectionControl(@RequestBody ConnectionControlParam control){

        log.info("[JT-终端控制] 参数: {}", control.toString());
        service.connectionControl(control.getPhoneNumber(), control.getControl());
    }

    @Operation(summary = "JT-终端控制-复位", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @PostMapping("/control/reset")
    public void resetControl(String phoneNumber){

        log.info("[JT-复位] phoneNumber: {}", phoneNumber);
        service.resetControl(phoneNumber);
    }

    @Operation(summary = "JT-终端控制-恢复出厂设置", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @PostMapping("/control/factory-reset")
    public void factoryResetControl(String phoneNumber){

        log.info("[JT-恢复出厂设置] phoneNumber: {}", phoneNumber);
        service.factoryResetControl(phoneNumber);
    }

    @Operation(summary = "JT-查询终端属性", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/attribute")
    public JTDeviceAttribute attribute(String phoneNumber){

        log.info("[JT-查询终端属性] phoneNumber: {}", phoneNumber);
        return service.attribute(phoneNumber);
    }

    @Operation(summary = "JT-查询位置信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/position-info")
    public JTPositionBaseInfo queryPositionInfo(String phoneNumber){

        log.info("[JT-查询位置信息] phoneNumber: {}", phoneNumber);
        return service.queryPositionInfo(phoneNumber);
    }

    @Operation(summary = "JT-临时位置跟踪控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "timeInterval", description = "时间间隔,单位为秒,时间间隔为0 时停止跟踪,停止跟踪无需带后继字段", required = true)
    @Parameter(name = "validityPeriod", description = "位置跟踪有效期, 单位为秒,终端在接收到位置跟踪控制消息后,在有效期截止时间之前依据消息中的时间间隔发送位置汇报", required = true)
    @GetMapping("/control/temp-position-tracking")
    public void tempPositionTrackingControl(String phoneNumber, Integer timeInterval, Long validityPeriod){

        log.info("[JT-临时位置跟踪控制] phoneNumber: {}, 时间间隔 {}秒, 位置跟踪有效期 {}秒", phoneNumber, timeInterval, validityPeriod);
        service.tempPositionTrackingControl(phoneNumber, timeInterval, validityPeriod);
    }

    @Operation(summary = "JT-人工确认报警消息", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "timeInterval", description = "时间间隔,单位为秒,时间间隔为0 时停止跟踪,停止跟踪无需带后继字段", required = true)
    @Parameter(name = "validityPeriod", description = "位置跟踪有效期, 单位为秒,终端在接收到位置跟踪控制消息后,在有效期截止时间之前依据消息中的时间间隔发送位置汇报", required = true)
    @PostMapping("/confirmation-alarm-message")
    public void confirmationAlarmMessage(@RequestBody ConfirmationAlarmMessageParam param){

        log.info("[JT-人工确认报警消息] 参数: {}", param);
        service.confirmationAlarmMessage(param.getPhoneNumber(), param.getAlarmPackageNo(), param.getAlarmMessageType());
    }

    @Operation(summary = "JT-链路检测", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/link-detection")
    public Integer linkDetection(String phoneNumber){

        log.info("[JT-链路检测] phoneNumber: {}", phoneNumber);
        return service.linkDetection(phoneNumber);
    }

    @Operation(summary = "JT-文本信息下发", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "textMessageParam", description = "文本信息下发参数", required = true)
    @PostMapping("/text-msg")
    public WVPResult<Integer> textMessage(@RequestBody TextMessageParam textMessageParam){

        log.info("[JT-文本信息下发] textMessageParam: {}", textMessageParam);
        int result = service.textMessage(textMessageParam.getPhoneNumber(), textMessageParam.getSign(), textMessageParam.getTextType(), textMessageParam.getContent());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-电话回拨", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "sign", description = "标志: 0:普通通话,1:监听", required = true)
    @Parameter(name = "destPhoneNumber", description = "回拨电话号码", required = true)
    @GetMapping("/telephone-callback")
    public WVPResult<Integer> telephoneCallback(String phoneNumber, Integer sign, String destPhoneNumber){

        log.info("[JT-电话回拨] phoneNumber: {}, sign: {}, phoneNumber: {},", phoneNumber, sign, phoneNumber);
        int result = service.telephoneCallback(phoneNumber, sign, destPhoneNumber);
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-设置电话本", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "setPhoneBookParam", description = "设置电话本参数", required = true)
    @PostMapping("/set-phone-book")
    public WVPResult<Integer> setPhoneBook(@RequestBody SetPhoneBookParam setPhoneBookParam){

        log.info("[JT-设置电话本] setPhoneBookParam: {}", setPhoneBookParam);
        int result = service.setPhoneBook(setPhoneBookParam.getPhoneNumber(), setPhoneBookParam.getType(), setPhoneBookParam.getPhoneBookContactList());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-车门控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "open", description = "开启车门", required = true)
    @GetMapping("/control/door")
    public WVPResult<Integer> controlDoor(String phoneNumber, Boolean open){

        log.info("[JT-车门控制] phoneNumber: {}, open: {},", phoneNumber, open);
        JTPositionBaseInfo positionBaseInfo = service.controlDoor(phoneNumber, open);
        if (positionBaseInfo == null || positionBaseInfo.getStatus() == null) {
            return WVPResult.fail(ErrorCode.ERROR100.getCode(), "控制失败");
        }
        if (open == !positionBaseInfo.getStatus().isDoorLocking()) {
            return WVPResult.success(null);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100.getCode(), "控制失败");
        }
    }

    @Operation(summary = "JT-更新圆形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/circle/update")
    public WVPResult<Integer> updateAreaForCircle(@RequestBody SetAreaParam areaParam){

        log.info("[JT-更新圆形区域] areaParam: {},", areaParam);
        int result = service.setAreaForCircle(0, areaParam.getPhoneNumber(), areaParam.getCircleAreaList());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-追加圆形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/circle/add")
    public WVPResult<Integer> addAreaForCircle(@RequestBody SetAreaParam areaParam){

        log.info("[JT-追加圆形区域] areaParam: {},", areaParam);
        int result = service.setAreaForCircle(1, areaParam.getPhoneNumber(), areaParam.getCircleAreaList());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-修改圆形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/circle/edit")
    public WVPResult<Integer> editAreaForCircle(@RequestBody SetAreaParam areaParam){

        log.info("[JT-修改圆形区域] areaParam: {},", areaParam);
        int result = service.setAreaForCircle(2, areaParam.getPhoneNumber(), areaParam.getCircleAreaList());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-删除圆形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "ids", description = "待删除圆形区域的id，例如1,2,3", required = true)
    @GetMapping("/area/circle/delete")
    public WVPResult<Integer> deleteAreaForCircle(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-删除圆形区域] phoneNumber: {}, ids:{}", phoneNumber, ids);
        int result = service.deleteAreaForCircle(phoneNumber, ids);
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-查询圆形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/area/circle/query")
    public WVPResult<List<JTAreaOrRoute>> queryAreaForCircle(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-查询圆形区域] phoneNumber: {}, ids:{}", phoneNumber, ids);
        List<JTAreaOrRoute> result = service.queryAreaForCircle(phoneNumber, ids);
        if (result != null) {
            return WVPResult.success(result);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }


    @Operation(summary = "JT-更新矩形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/rectangle/update")
    public WVPResult<Integer> updateAreaForRectangle(@RequestBody SetAreaParam areaParam){

        log.info("[JT-更新矩形区域] areaParam: {},", areaParam);
        int result = service.setAreaForRectangle(0, areaParam.getPhoneNumber(), areaParam.getRectangleAreas());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-追加矩形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/rectangle/add")
    public WVPResult<Integer> addAreaForRectangle(@RequestBody SetAreaParam areaParam){

        log.info("[JT-追加矩形区域] areaParam: {},", areaParam);
        int result = service.setAreaForRectangle(1, areaParam.getPhoneNumber(), areaParam.getRectangleAreas());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-修改矩形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/rectangle/edit")
    public WVPResult<Integer> editAreaForRectangle(@RequestBody SetAreaParam areaParam){

        log.info("[JT-修改矩形区域] areaParam: {},", areaParam);
        int result = service.setAreaForRectangle(2, areaParam.getPhoneNumber(), areaParam.getRectangleAreas());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-删除矩形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "ids", description = "待删除圆形区域的id，例如1,2,3", required = true)
    @GetMapping("/area/rectangle/delete")
    public WVPResult<Integer> deleteAreaForRectangle(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-删除矩形区域] phoneNumber: {}, ids:{}", phoneNumber, ids);
        int result = service.deleteAreaForRectangle(phoneNumber, ids);
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-查询矩形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/area/rectangle/query")
    public WVPResult<List<JTAreaOrRoute>> queryAreaForRectangle(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-查询矩形区域] phoneNumber: {}, ids:{}", phoneNumber, ids);
        List<JTAreaOrRoute> result = service.queryAreaForRectangle(phoneNumber, ids);
        if (result != null) {
            return WVPResult.success(result);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }

    @Operation(summary = "JT-设置多边形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/area/polygon/set")
    public WVPResult<Integer> setAreaForPolygon(@RequestBody SetAreaParam areaParam){

        log.info("[JT-设置多边形区域] areaParam: {},", areaParam);
        int result = service.setAreaForPolygon(areaParam.getPhoneNumber(), areaParam.getPolygonArea());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-删除多边形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "ids", description = "待删除圆形区域的id，例如1,2,3", required = true)
    @GetMapping("/area/polygon/delete")
    public WVPResult<Integer> deleteAreaForPolygon(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-删除多边形区域] phoneNumber: {}, ids:{}", phoneNumber, ids);
        int result = service.deleteAreaForPolygon(phoneNumber, ids);
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-查询多边形区域", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/area/polygon/query")
    public WVPResult<List<JTAreaOrRoute>> queryAreaForPolygon(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-查询多边形区域] phoneNumber: {}, ids:{}", phoneNumber, ids);
        List<JTAreaOrRoute> result = service.queryAreaForPolygon(phoneNumber, ids);
        if (result != null) {
            return WVPResult.success(result);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }

    @Operation(summary = "JT-设置路线", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "areaParam", description = "设置区域参数", required = true)
    @PostMapping("/route/set")
    public WVPResult<Integer> setRoute(@RequestBody SetAreaParam areaParam){

        log.info("[JT-设置路线] areaParam: {},", areaParam);
        int result = service.setRoute(areaParam.getPhoneNumber(), areaParam.getRoute());
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-删除路线", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "ids", description = "待删除圆形区域的id，例如1,2,3", required = true)
    @GetMapping("/route/delete")
    public WVPResult<Integer> deleteRoute(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-删除路线] phoneNumber: {}, ids:{}", phoneNumber, ids);
        int result = service.deleteRoute(phoneNumber, ids);
        if (result == 0) {
            return WVPResult.success(result);
        }else {
            WVPResult<Integer> fail = WVPResult.fail(ErrorCode.ERROR100);
            fail.setData(result);
            return fail;
        }
    }

    @Operation(summary = "JT-查询路线", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/route/query")
    public WVPResult<List<JTAreaOrRoute>> queryRoute(String phoneNumber, @RequestParam(value = "ids", required = false) List<Long> ids){

        log.info("[JT-查询路线] phoneNumber: {}, ids:{}", phoneNumber, ids);
        List<JTAreaOrRoute> result = service.queryRoute(phoneNumber, ids);
        if (result != null) {
            return WVPResult.success(result);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }

    // TODO 待实现 行驶记录数据采集命令 行驶记录数据上传 行驶记录参数下传命令 电子运单上报 CAN总线数据上传

    @Operation(summary = "JT-上报驾驶员身份信息请求", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @GetMapping("/driver-information")
    public WVPResult<JTDriverInformation> queryDriverInformation(String phoneNumber){

        log.info("[JT-上报驾驶员身份信息请求] phoneNumber: {}", phoneNumber);
        JTDriverInformation jtDriverInformation = service.queryDriverInformation(phoneNumber);
        if (jtDriverInformation != null) {
            return WVPResult.success(jtDriverInformation);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }

    @Operation(summary = "JT-摄像头立即拍摄命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @PostMapping("/shooting")
    public WVPResult<List<Long>> shooting(@RequestBody ShootingParam param){

        log.info("[JT-摄像头立即拍摄命令] param: {}", param );
        List<Long> ids = service.shooting(param.getPhoneNumber(), param.getShootingCommand());
        if (ids != null) {
            return WVPResult.success(ids);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }

    @Operation(summary = "JT-抓图", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "channelId", description = "通道编号", required = true)
    @GetMapping("/snap")
    public void snap(HttpServletResponse response, String phoneNumber, Integer channelId){

        log.info("[JT-抓图] 设备编号: {}, 通道编号: {}", phoneNumber, channelId );
        Assert.notNull(channelId, "缺少通道编号");
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType(MediaType.IMAGE_JPEG_VALUE);
//            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(phoneNumber + "_" + channelId + ".jpg", "UTF-8"));
            byte[] data = service.snap(phoneNumber, channelId);
            outputStream.write(data);
            outputStream.flush();
        }catch (Exception e) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
        }
    }

    @Operation(summary = "JT-存储多媒体数据检索", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "param", description = "存储多媒体数据参数", required = true)
    @PostMapping("/media/list")
    public WVPResult<List<JTMediaDataInfo>> queryMediaData(@RequestBody QueryMediaDataParam param){

        log.info("[JT-存储多媒体数据检索] param: {}", param );
        List<JTMediaDataInfo> ids = service.queryMediaData(param.getPhoneNumber(), param.getQueryMediaDataCommand());
        if (ids != null) {
            return WVPResult.success(ids);
        }else {
            return WVPResult.fail(ErrorCode.ERROR100);
        }
    }

    @Operation(summary = "JT-单条存储多媒体数据上传", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "mediaId", description = "多媒体ID", required = true)
    @GetMapping("/media/upload/one/upload")
    public void uploadOneMedia(HttpServletResponse response, String phoneNumber, Long mediaId){

        log.info("[JT-单条存储多媒体数据上传] 设备编号: {}, 多媒体ID: {}", phoneNumber, mediaId );
        Assert.notNull(mediaId, "缺少通道编号");
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            service.uploadOneMedia(phoneNumber, mediaId, outputStream, false);
        }catch (Exception e) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
        }
    }

    @Operation(summary = "JT-单条存储多媒体数据删除", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备编号", required = true)
    @Parameter(name = "mediaId", description = "多媒体ID", required = true)
    @GetMapping("/media/upload/one/delete")
    public void deleteOneMedia(HttpServletResponse response, String phoneNumber, Long mediaId){

        log.info("[JT-单条存储多媒体数据上传] 设备编号: {}, 多媒体ID: {}", phoneNumber, mediaId );
        Assert.notNull(mediaId, "缺少通道编号");
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            service.uploadOneMedia(phoneNumber, mediaId, outputStream, true);
        }catch (Exception e) {
            throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
        }
    }

//    @Operation(summary = "JT-存储多媒体数据上传命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
//    @Parameter(name = "param", description = "存储多媒体数据参数", required = true)
//    @PostMapping("/media-data-upload")
//    public DeferredResult<WVPResult<List<String>>> updateMediaData(@RequestBody QueryMediaDataParam param){
//
//        log.info("[JT-存储多媒体数据上传命令] param: {}", param );
//        DeferredResult<WVPResult<List<String>>> deferredResult = new DeferredResult<>(30000L);
//        List<String> resultList = new ArrayList<>();
//
//        deferredResult.onTimeout(()->{
//            log.info("[JT-存储多媒体数据上传命令超时] param: {}", param );
//            WVPResult<List<String>> fail = WVPResult.fail(ErrorCode.ERROR100);
//            fail.setMsg("超时");
//            fail.setData(resultList);
//            deferredResult.setResult(fail);
//        });
//        List<JTMediaDataInfo> ids;
//        if (param.getMediaId() != null) {
//            ids = new ArrayList<>();
//            JTMediaDataInfo mediaDataInfo = new JTMediaDataInfo();
//            mediaDataInfo.setId(param.getMediaId());
//            ids.add(mediaDataInfo);
//        }else {
//            ids = service.queryMediaData(param.getPhoneNumber(), param.getQueryMediaDataCommand());
//        }
//        if (ids.isEmpty()) {
//            deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100));
//            return deferredResult;
//        }
//        Map<String, JTMediaDataInfo> idMap= new HashMap<>();
//        for (JTMediaDataInfo mediaDataInfo : ids) {
//            idMap.put(mediaDataInfo.getId() + ".jpg", mediaDataInfo);
//        }
//        // 开启文件监听
//        FileAlterationObserver observer = new FileAlterationObserver(new File("mediaEvent"));
//        observer.addListener(new FileAlterationListenerAdaptor() {
//            @Override
//            public void onFileCreate(File file) {
//               if (idMap.containsKey(file.getName())) {
//                   idMap.remove(file.getName());
//                   resultList.add("mediaEvent" + File.separator + file.getName());
//                   if (idMap.isEmpty()) {
//                       deferredResult.setResult(WVPResult.success(resultList));
//                   }
//               }
//            }
//        });
//        FileAlterationMonitor monitor = new FileAlterationMonitor(5, observer);
//        try {
//            monitor.start();
//        } catch (Exception e) {
//            log.info("[JT-存储多媒体数据上传命令监听文件失败] param: {}", param );
//            deferredResult.setResult(null);
//            return deferredResult;
//        }
//        taskExecutor.execute(()->{
//            if (param.getMediaId() != null) {
//                service.uploadMediaDataForSingle(param.getPhoneNumber(), param.getMediaId(), param.getDelete());
//            }else {
//                service.uploadMediaData(param.getPhoneNumber(), param.getQueryMediaDataCommand());
//            }
//
//        });
//        return deferredResult;
//    }

    @Operation(summary = "JT-开始录音", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "time", description = "录音时间，单位为秒(s) ,0 表示一直录音", required = false)
    @Parameter(name = "save", description = "0:实时上传；1:保存", required = false)
    @Parameter(name = "samplingRate", description = "音频采样率， 0:8K；1:11K；2:23K；3:32K", required = false)
    @GetMapping("/record/start")
    public void startRecord(HttpServletRequest request,
                         @Parameter(required = true) String phoneNumber,
                         @Parameter(required = false) Integer time,
                         @Parameter(required = false) Integer save,
                         @Parameter(required = false) Integer samplingRate
                            ) {
        if (ObjectUtils.isEmpty(time)) {
            time = 0;
        }
        if (ObjectUtils.isEmpty(save)) {
            save = 0;
        }
        if (ObjectUtils.isEmpty(samplingRate)) {
            samplingRate = 0;
        }
        service.record(phoneNumber, 1, time, save, samplingRate);
    }

    @Operation(summary = "JT-停止录音", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @Parameter(name = "time", description = "录音时间，单位为秒(s) ,0 表示一直录音", required = false)
    @Parameter(name = "save", description = "0:实时上传；1:保存", required = false)
    @Parameter(name = "samplingRate", description = "音频采样率， 0:8K；1:11K；2:23K；3:32K", required = false)
    @GetMapping("/record/stop")
    public void stopRecord(HttpServletRequest request,
                            @Parameter(required = true) String phoneNumber,
                            @Parameter(required = false) Integer time,
                            @Parameter(required = false) Integer save,
                            @Parameter(required = false) Integer samplingRate
    ) {
        if (ObjectUtils.isEmpty(time)) {
            time = 0;
        }
        if (ObjectUtils.isEmpty(save)) {
            save = 0;
        }
        if (ObjectUtils.isEmpty(samplingRate)) {
            samplingRate = 0;
        }
        service.record(phoneNumber, 0, time, save, samplingRate);
    }

    @Operation(summary = "JT-查询终端音视频属性", security = @SecurityRequirement(name = JwtUtils.HEADER))
    @Parameter(name = "phoneNumber", description = "设备手机号", required = true)
    @GetMapping("/media/attribute")
    public JTMediaAttribute queryMediaAttribute( @Parameter(required = true) String phoneNumber
    ) {
        return service.queryMediaAttribute(phoneNumber);
    }

    // TODO 视频报警上报


}

