Merge remote-tracking branch 'origin/wvp-28181-2.0' into wvp-28181-2.0
New file |
| | |
| | | package com.genersoft.iot.vmp.common.enums; |
| | | |
| | | import org.dom4j.Element; |
| | | import org.springframework.util.ObjectUtils; |
| | | |
| | | |
| | | /** |
| | | * @author gaofuwang |
| | | * @date 2023/01/18/ 10:09:00 |
| | | * @since 1.0 |
| | | */ |
| | | public enum DeviceControlType { |
| | | |
| | | /** |
| | | * 云台控制 |
| | | * 上下左右,预置位,扫描,辅助功能,巡航 |
| | | */ |
| | | PTZ("PTZCmd","云台控制"), |
| | | /** |
| | | * 远程启动 |
| | | */ |
| | | TELE_BOOT("TeleBoot","远程启动"), |
| | | /** |
| | | * 录像控制 |
| | | */ |
| | | RECORD("RecordCmd","录像控制"), |
| | | /** |
| | | * 布防撤防 |
| | | */ |
| | | GUARD("GuardCmd","布防撤防"), |
| | | /** |
| | | * 告警控制 |
| | | */ |
| | | ALARM("AlarmCmd","告警控制"), |
| | | /** |
| | | * 强制关键帧 |
| | | */ |
| | | I_FRAME("IFameCmd","强制关键帧"), |
| | | /** |
| | | * 拉框放大 |
| | | */ |
| | | DRAG_ZOOM_IN("DragZoomIn","拉框放大"), |
| | | /** |
| | | * 拉框缩小 |
| | | */ |
| | | DRAG_ZOOM_OUT("DragZoomOut","拉框缩小"), |
| | | /** |
| | | * 看守位 |
| | | */ |
| | | HOME_POSITION("HomePosition","看守位"); |
| | | |
| | | private final String val; |
| | | |
| | | private final String desc; |
| | | |
| | | DeviceControlType(String val, String desc) { |
| | | this.val = val; |
| | | this.desc = desc; |
| | | } |
| | | |
| | | public String getVal() { |
| | | return val; |
| | | } |
| | | |
| | | public String getDesc() { |
| | | return desc; |
| | | } |
| | | |
| | | public static DeviceControlType typeOf(Element rootElement) { |
| | | for (DeviceControlType item : DeviceControlType.values()) { |
| | | if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) { |
| | | return item; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.gb28181.bean; |
| | | |
| | | |
| | | /** |
| | | * 通过redis分发报警消息 |
| | | */ |
| | |
| | | * 国标编号 |
| | | */ |
| | | private String gbId; |
| | | |
| | | /** |
| | | * 报警编号 |
| | | */ |
| | | private int alarmSn; |
| | | |
| | | /** |
| | | * 告警类型 |
| | | */ |
| | | private int alarmType; |
| | | |
| | | /** |
| | | * 报警描述 |
| | |
| | | this.alarmSn = alarmSn; |
| | | } |
| | | |
| | | public int getAlarmType() { |
| | | return alarmType; |
| | | } |
| | | |
| | | public void setAlarmType(int alarmType) { |
| | | this.alarmType = alarmType; |
| | | } |
| | | |
| | | public String getAlarmDescription() { |
| | | return alarmDescription; |
| | | } |
| | |
| | | public int getVal() { |
| | | return val; |
| | | } |
| | | |
| | | /** |
| | | * 查询是否匹配类型 |
| | | * @param code |
| | | * @return |
| | | */ |
| | | public static DeviceAlarmMethod typeOf(int code) { |
| | | for (DeviceAlarmMethod item : DeviceAlarmMethod.values()) { |
| | | if (code==item.getVal()) { |
| | | return item; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | package com.genersoft.iot.vmp.gb28181.bean; |
| | | |
| | | import com.genersoft.iot.vmp.gb28181.utils.MessageElement; |
| | | |
| | | /** |
| | | * 设备信息查询响应 |
| | | * |
| | | * @author Y.G |
| | | * @version 1.0 |
| | | * @date 2022/6/28 14:55 |
| | | */ |
| | | public class DragZoomRequest { |
| | | /** |
| | | * 序列号 |
| | | */ |
| | | @MessageElement("SN") |
| | | private String sn; |
| | | |
| | | @MessageElement("DeviceID") |
| | | private String deviceId; |
| | | |
| | | @MessageElement(value = "DragZoomIn") |
| | | private DragZoom dragZoomIn; |
| | | |
| | | @MessageElement(value = "DragZoomOut") |
| | | private DragZoom dragZoomOut; |
| | | |
| | | /** |
| | | * 基本参数 |
| | | */ |
| | | public static class DragZoom { |
| | | /** |
| | | * 播放窗口长度像素值 |
| | | */ |
| | | @MessageElement("Length") |
| | | protected Integer length; |
| | | /** |
| | | * 播放窗口宽度像素值 |
| | | */ |
| | | @MessageElement("Width") |
| | | protected Integer width; |
| | | /** |
| | | * 拉框中心的横轴坐标像素值 |
| | | */ |
| | | @MessageElement("MidPointX") |
| | | protected Integer midPointX; |
| | | /** |
| | | * 拉框中心的纵轴坐标像素值 |
| | | */ |
| | | @MessageElement("MidPointY") |
| | | protected Integer midPointY; |
| | | /** |
| | | * 拉框长度像素值 |
| | | */ |
| | | @MessageElement("LengthX") |
| | | protected Integer lengthX; |
| | | /** |
| | | * 拉框宽度像素值 |
| | | */ |
| | | @MessageElement("LengthY") |
| | | protected Integer lengthY; |
| | | |
| | | public Integer getLength() { |
| | | return length; |
| | | } |
| | | |
| | | public void setLength(Integer length) { |
| | | this.length = length; |
| | | } |
| | | |
| | | public Integer getWidth() { |
| | | return width; |
| | | } |
| | | |
| | | public void setWidth(Integer width) { |
| | | this.width = width; |
| | | } |
| | | |
| | | public Integer getMidPointX() { |
| | | return midPointX; |
| | | } |
| | | |
| | | public void setMidPointX(Integer midPointX) { |
| | | this.midPointX = midPointX; |
| | | } |
| | | |
| | | public Integer getMidPointY() { |
| | | return midPointY; |
| | | } |
| | | |
| | | public void setMidPointY(Integer midPointY) { |
| | | this.midPointY = midPointY; |
| | | } |
| | | |
| | | public Integer getLengthX() { |
| | | return lengthX; |
| | | } |
| | | |
| | | public void setLengthX(Integer lengthX) { |
| | | this.lengthX = lengthX; |
| | | } |
| | | |
| | | public Integer getLengthY() { |
| | | return lengthY; |
| | | } |
| | | |
| | | public void setLengthY(Integer lengthY) { |
| | | this.lengthY = lengthY; |
| | | } |
| | | } |
| | | |
| | | public String getSn() { |
| | | return sn; |
| | | } |
| | | |
| | | public void setSn(String sn) { |
| | | this.sn = sn; |
| | | } |
| | | |
| | | public String getDeviceId() { |
| | | return deviceId; |
| | | } |
| | | |
| | | public void setDeviceId(String deviceId) { |
| | | this.deviceId = deviceId; |
| | | } |
| | | |
| | | public DragZoom getDragZoomIn() { |
| | | return dragZoomIn; |
| | | } |
| | | |
| | | public void setDragZoomIn(DragZoom dragZoomIn) { |
| | | this.dragZoomIn = dragZoomIn; |
| | | } |
| | | |
| | | public DragZoom getDragZoomOut() { |
| | | return dragZoomOut; |
| | | } |
| | | |
| | | public void setDragZoomOut(DragZoom dragZoomOut) { |
| | | this.dragZoomOut = dragZoomOut; |
| | | } |
| | | } |
New file |
| | |
| | | package com.genersoft.iot.vmp.gb28181.bean; |
| | | |
| | | import com.genersoft.iot.vmp.gb28181.utils.MessageElement; |
| | | |
| | | /** |
| | | * 设备信息查询响应 |
| | | * |
| | | * @author Y.G |
| | | * @version 1.0 |
| | | * @date 2022/6/28 14:55 |
| | | */ |
| | | public class HomePositionRequest { |
| | | /** |
| | | * 序列号 |
| | | */ |
| | | @MessageElement("SN") |
| | | private String sn; |
| | | |
| | | @MessageElement("DeviceID") |
| | | private String deviceId; |
| | | |
| | | @MessageElement(value = "HomePosition") |
| | | private HomePosition homePosition; |
| | | |
| | | |
| | | /** |
| | | * 基本参数 |
| | | */ |
| | | public static class HomePosition { |
| | | /** |
| | | * 播放窗口长度像素值 |
| | | */ |
| | | @MessageElement("Enabled") |
| | | protected String enabled; |
| | | /** |
| | | * 播放窗口宽度像素值 |
| | | */ |
| | | @MessageElement("ResetTime") |
| | | protected String resetTime; |
| | | /** |
| | | * 拉框中心的横轴坐标像素值 |
| | | */ |
| | | @MessageElement("PresetIndex") |
| | | protected String presetIndex; |
| | | |
| | | public String getEnabled() { |
| | | return enabled; |
| | | } |
| | | |
| | | public void setEnabled(String enabled) { |
| | | this.enabled = enabled; |
| | | } |
| | | |
| | | public String getResetTime() { |
| | | return resetTime; |
| | | } |
| | | |
| | | public void setResetTime(String resetTime) { |
| | | this.resetTime = resetTime; |
| | | } |
| | | |
| | | public String getPresetIndex() { |
| | | return presetIndex; |
| | | } |
| | | |
| | | public void setPresetIndex(String presetIndex) { |
| | | this.presetIndex = presetIndex; |
| | | } |
| | | } |
| | | |
| | | public String getSn() { |
| | | return sn; |
| | | } |
| | | |
| | | public void setSn(String sn) { |
| | | this.sn = sn; |
| | | } |
| | | |
| | | public String getDeviceId() { |
| | | return deviceId; |
| | | } |
| | | |
| | | public void setDeviceId(String deviceId) { |
| | | this.deviceId = deviceId; |
| | | } |
| | | |
| | | public HomePosition getHomePosition() { |
| | | return homePosition; |
| | | } |
| | | |
| | | public void setHomePosition(HomePosition homePosition) { |
| | | this.homePosition = homePosition; |
| | | } |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.gb28181.bean;
|
| | |
|
| | |
|
| | | import java.time.Instant;
|
| | | import java.util.List;
|
| | |
|
| | |
| | | private String name;
|
| | |
|
| | | private int sumNum;
|
| | |
|
| | | private int count;
|
| | |
|
| | | private Instant lastTime;
|
| | |
|
| | |
| | | public void setLastTime(Instant lastTime) {
|
| | | this.lastTime = lastTime;
|
| | | }
|
| | |
|
| | | public int getCount() {
|
| | | return count;
|
| | | }
|
| | |
|
| | | public void setCount(int count) {
|
| | | this.count = count;
|
| | | }
|
| | | }
|
| | |
| | | package com.genersoft.iot.vmp.gb28181.event.record; |
| | | |
| | | import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; |
| | | import com.genersoft.iot.vmp.utils.redis.RedisUtil; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.context.ApplicationListener; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(RecordEndEventListener.class); |
| | | |
| | | private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>(); |
| | | public interface RecordEndEventHandler{ |
| | | void handler(RecordInfo recordInfo); |
| | | } |
| | | |
| | | private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>(); |
| | | |
| | | @Override |
| | | public void onApplicationEvent(RecordEndEvent event) { |
| | | logger.info("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}条", event.getRecordInfo().getDeviceId(), |
| | | event.getRecordInfo().getChannelId(), event.getRecordInfo().getSumNum() ); |
| | | String deviceId = event.getRecordInfo().getDeviceId(); |
| | | String channelId = event.getRecordInfo().getChannelId(); |
| | | int count = event.getRecordInfo().getCount(); |
| | | int sumNum = event.getRecordInfo().getSumNum(); |
| | | logger.info("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}/{}条", event.getRecordInfo().getDeviceId(), |
| | | event.getRecordInfo().getChannelId(), count,sumNum); |
| | | if (handlerMap.size() > 0) { |
| | | for (RecordEndEventHandler recordEndEventHandler : handlerMap.values()) { |
| | | recordEndEventHandler.handler(event.getRecordInfo()); |
| | | RecordEndEventHandler handler = handlerMap.get(deviceId + channelId); |
| | | if (handler !=null){ |
| | | handler.handler(event.getRecordInfo()); |
| | | if (count ==sumNum){ |
| | | handlerMap.remove(deviceId + channelId); |
| | | } |
| | | } |
| | | } |
| | | handlerMap.clear(); |
| | | } |
| | | |
| | | /** |
| | | * 添加 |
| | | * @param device |
| | | * @param channelId |
| | | * @param recordEndEventHandler |
| | | */ |
| | | public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) { |
| | | handlerMap.put(device + channelId, recordEndEventHandler); |
| | | } |
| | | /** |
| | | * 添加 |
| | | * @param device |
| | | * @param channelId |
| | | */ |
| | | public void delEndEventHandler(String device, String channelId) { |
| | | handlerMap.remove(device + channelId); |
| | | } |
| | | |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.gb28181.session; |
| | | |
| | | import com.genersoft.iot.vmp.gb28181.bean.*; |
| | | import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEventListener; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; |
| | | import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| | |
| | | |
| | | @Autowired |
| | | private DeferredResultHolder deferredResultHolder; |
| | | @Autowired |
| | | private RecordEndEventListener recordEndEventListener; |
| | | |
| | | |
| | | public int put(String deviceId, String sn, int sumNum, List<RecordItem> recordItems) { |
| | | public int put(String deviceId,String channelId, String sn, int sumNum, List<RecordItem> recordItems) { |
| | | String key = deviceId + sn; |
| | | RecordInfo recordInfo = data.get(key); |
| | | if (recordInfo == null) { |
| | | recordInfo = new RecordInfo(); |
| | | recordInfo.setDeviceId(deviceId); |
| | | recordInfo.setChannelId(channelId); |
| | | recordInfo.setSn(sn.trim()); |
| | | recordInfo.setSumNum(sumNum); |
| | | recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>())); |
| | |
| | | msg.setKey(msgKey); |
| | | msg.setData(recordInfo); |
| | | deferredResultHolder.invokeAllResult(msg); |
| | | recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId()); |
| | | data.remove(key); |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException { |
| | | ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME); |
| | | String transport = "UDP"; |
| | | if (viaHeader == null) { |
| | | logger.warn("[消息头缺失]: ViaHeader, 使用默认的UDP方式处理数据"); |
| | | }else { |
| | | transport = viaHeader.getTransport(); |
| | | } |
| | | if (message.getHeader(UserAgentHeader.NAME) == null) { |
| | | try { |
| | | message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); |
| | | } catch (ParseException e) { |
| | | logger.error("添加UserAgentHeader失败", e); |
| | | try { |
| | | ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME); |
| | | String transport = "UDP"; |
| | | if (viaHeader == null) { |
| | | logger.warn("[消息头缺失]: ViaHeader, 使用默认的UDP方式处理数据"); |
| | | }else { |
| | | transport = viaHeader.getTransport(); |
| | | } |
| | | } |
| | | |
| | | CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME); |
| | | // 添加错误订阅 |
| | | if (errorEvent != null) { |
| | | sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> { |
| | | errorEvent.response(eventResult); |
| | | sipSubscribe.removeErrorSubscribe(eventResult.callId); |
| | | sipSubscribe.removeOkSubscribe(eventResult.callId); |
| | | })); |
| | | } |
| | | // 添加订阅 |
| | | if (okEvent != null) { |
| | | sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> { |
| | | okEvent.response(eventResult); |
| | | sipSubscribe.removeOkSubscribe(eventResult.callId); |
| | | sipSubscribe.removeErrorSubscribe(eventResult.callId); |
| | | }); |
| | | } |
| | | if ("TCP".equals(transport)) { |
| | | SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip); |
| | | if (tcpSipProvider == null) { |
| | | logger.error("[发送信息失败] 未找到tcp://{}的监听信息", ip); |
| | | return; |
| | | } |
| | | if (message instanceof Request) { |
| | | tcpSipProvider.sendRequest((Request)message); |
| | | }else if (message instanceof Response) { |
| | | tcpSipProvider.sendResponse((Response)message); |
| | | if (message.getHeader(UserAgentHeader.NAME) == null) { |
| | | try { |
| | | message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); |
| | | } catch (ParseException e) { |
| | | logger.error("添加UserAgentHeader失败", e); |
| | | } |
| | | } |
| | | |
| | | } else if ("UDP".equals(transport)) { |
| | | SipProviderImpl sipProvider = sipLayer.getUdpSipProvider(ip); |
| | | if (sipProvider == null) { |
| | | logger.error("[发送信息失败] 未找到udp://{}的监听信息", ip); |
| | | return; |
| | | CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME); |
| | | // 添加错误订阅 |
| | | if (errorEvent != null) { |
| | | sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> { |
| | | errorEvent.response(eventResult); |
| | | sipSubscribe.removeErrorSubscribe(eventResult.callId); |
| | | sipSubscribe.removeOkSubscribe(eventResult.callId); |
| | | })); |
| | | } |
| | | if (message instanceof Request) { |
| | | sipProvider.sendRequest((Request)message); |
| | | }else if (message instanceof Response) { |
| | | sipProvider.sendResponse((Response)message); |
| | | // 添加订阅 |
| | | if (okEvent != null) { |
| | | sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> { |
| | | okEvent.response(eventResult); |
| | | sipSubscribe.removeOkSubscribe(eventResult.callId); |
| | | sipSubscribe.removeErrorSubscribe(eventResult.callId); |
| | | }); |
| | | } |
| | | if ("TCP".equals(transport)) { |
| | | SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip); |
| | | if (tcpSipProvider == null) { |
| | | logger.error("[发送信息失败] 未找到tcp://{}的监听信息", ip); |
| | | return; |
| | | } |
| | | if (message instanceof Request) { |
| | | tcpSipProvider.sendRequest((Request)message); |
| | | }else if (message instanceof Response) { |
| | | tcpSipProvider.sendResponse((Response)message); |
| | | } |
| | | |
| | | } else if ("UDP".equals(transport)) { |
| | | SipProviderImpl sipProvider = sipLayer.getUdpSipProvider(ip); |
| | | if (sipProvider == null) { |
| | | logger.error("[发送信息失败] 未找到udp://{}的监听信息", ip); |
| | | return; |
| | | } |
| | | if (message instanceof Request) { |
| | | sipProvider.sendRequest((Request)message); |
| | | }else if (message instanceof Response) { |
| | | sipProvider.sendResponse((Response)message); |
| | | } |
| | | } |
| | | } finally { |
| | | logger.info("[SEND]:SUCCESS:{}", message); |
| | | } |
| | | } |
| | | |
| | |
| | | * @param channelId 预览通道
|
| | | * @param recordCmdStr 录像命令:Record / StopRecord
|
| | | */
|
| | | void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | | void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | |
|
| | | /**
|
| | | * 远程启动控制命令
|
| | |
| | | *
|
| | | * @param device 视频设备
|
| | | */
|
| | | void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | | void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | |
|
| | | /**
|
| | | * 报警复位命令
|
| | |
| | | * @param alarmMethod 报警方式(可选)
|
| | | * @param alarmType 报警类型(可选)
|
| | | */
|
| | | void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | | void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | |
|
| | | /**
|
| | | * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
|
| | |
| | | * @param channelId 预览通道
|
| | | */
|
| | | void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
|
| | | |
| | |
|
| | | /**
|
| | | * 看守位控制命令
|
| | | * |
| | | * @param device 视频设备
|
| | | * @param enabled 看守位使能:1 = 开启,0 = 关闭
|
| | | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
| | | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
| | | *
|
| | | * @param device 视频设备
|
| | | * @param channelId 通道id,非通道则是设备本身
|
| | | * @param frontCmd 上级平台的指令,如果存在则直接下发
|
| | | * @param enabled 看守位使能:1 = 开启,0 = 关闭
|
| | | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
| | | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
| | | */
|
| | | void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | | |
| | | void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
| | |
|
| | | /**
|
| | | * 设备配置命令
|
| | | *
|
| | |
| | | import org.springframework.context.annotation.DependsOn;
|
| | | import org.springframework.stereotype.Component;
|
| | | import org.springframework.util.ObjectUtils;
|
| | | import org.springframework.util.StringUtils;
|
| | |
|
| | | import javax.sip.InvalidArgumentException;
|
| | | import javax.sip.ResponseEvent;
|
| | |
| | | * @param recordCmdStr 录像命令:Record / StopRecord
|
| | | */
|
| | | @Override
|
| | | public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | | public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | | StringBuffer cmdXml = new StringBuffer(200);
|
| | | String charset = device.getCharset();
|
| | | cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
|
| | |
| | |
|
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | * @param guardCmdStr "SetGuard"/"ResetGuard"
|
| | | */
|
| | | @Override
|
| | | public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | | public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | |
|
| | | StringBuffer cmdXml = new StringBuffer(200);
|
| | | String charset = device.getCharset();
|
| | |
| | | cmdXml.append("</Control>\r\n");
|
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | * @param device 视频设备
|
| | | */
|
| | | @Override
|
| | | public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | | public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | |
|
| | | StringBuffer cmdXml = new StringBuffer(200);
|
| | | String charset = device.getCharset();
|
| | |
| | |
|
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | * 看守位控制命令
|
| | | *
|
| | | * @param device 视频设备
|
| | | * @param channelId 通道id,非通道则是设备本身
|
| | | * @param frontCmd 上级平台的指令,如果存在则直接下发
|
| | | * @param enabled 看守位使能:1 = 开启,0 = 关闭
|
| | | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
| | | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
| | | */
|
| | | @Override
|
| | | public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | | public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
|
| | |
|
| | | StringBuffer cmdXml = new StringBuffer(200);
|
| | | String charset = device.getCharset();
|
| | |
| | |
|
| | |
|
| | | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
|
| | | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
|
| | | }
|
| | |
|
| | | /**
|
| | |
| | | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.cmd; |
| | | |
| | | import com.genersoft.iot.vmp.VManageBootstrap; |
| | | import com.genersoft.iot.vmp.common.enums.DeviceControlType; |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| | | import com.genersoft.iot.vmp.gb28181.bean.DragZoomRequest; |
| | | import com.genersoft.iot.vmp.gb28181.bean.HomePositionRequest; |
| | | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| | |
| | | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.ObjectUtils; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.sip.*; |
| | | import javax.sip.address.SipURI; |
| | | import javax.sip.header.HeaderAddress; |
| | | import javax.sip.header.ToHeader; |
| | | import javax.sip.message.Response; |
| | | import java.text.ParseException; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | |
| | | import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
| | | import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*; |
| | | |
| | | @Component |
| | | public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { |
| | |
| | | } catch (InvalidArgumentException | ParseException | SipException e) { |
| | | logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); |
| | | } |
| | | taskExecutor.execute(()->{ |
| | | taskExecutor.execute(() -> { |
| | | // 远程启动 |
| | | // try { |
| | | // Thread.sleep(3000); |
| | |
| | | // logger.error("[任务执行失败] 服务重启: {}", e.getMessage()); |
| | | // } |
| | | }); |
| | | } else { |
| | | // 远程启动指定设备 |
| | | } |
| | | } |
| | | // 云台/前端控制命令 |
| | | if (!ObjectUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) { |
| | | String cmdString = getText(rootElement,"PTZCmd"); |
| | | DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement); |
| | | logger.info("[接受deviceControl命令] 命令: {}", deviceControlType); |
| | | if (!ObjectUtils.isEmpty(deviceControlType) && !parentPlatform.getServerGBId().equals(targetGBId)) { |
| | | //判断是否存在该通道 |
| | | Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); |
| | | if (deviceForPlatform == null) { |
| | | try { |
| | |
| | | } |
| | | return; |
| | | } |
| | | try { |
| | | cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> { |
| | | // 失败的回复 |
| | | try { |
| | | responseAck(request, eventResult.statusCode, eventResult.msg); |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage()); |
| | | } |
| | | }, eventResult -> { |
| | | // 成功的回复 |
| | | try { |
| | | responseAck(request, eventResult.statusCode); |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage()); |
| | | } |
| | | }); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 云台/前端: {}", e.getMessage()); |
| | | switch (deviceControlType) { |
| | | case PTZ: |
| | | handlePtzCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.PTZ); |
| | | break; |
| | | case ALARM: |
| | | handleAlarmCmd(deviceForPlatform, rootElement, request); |
| | | break; |
| | | case GUARD: |
| | | handleGuardCmd(deviceForPlatform, rootElement, request, DeviceControlType.GUARD); |
| | | break; |
| | | case RECORD: |
| | | handleRecordCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.RECORD); |
| | | break; |
| | | case I_FRAME: |
| | | handleIFameCmd(deviceForPlatform, request, channelId); |
| | | break; |
| | | case TELE_BOOT: |
| | | handleTeleBootCmd(deviceForPlatform, request); |
| | | break; |
| | | case DRAG_ZOOM_IN: |
| | | handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_IN); |
| | | break; |
| | | case DRAG_ZOOM_OUT: |
| | | handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_OUT); |
| | | break; |
| | | case HOME_POSITION: |
| | | handleHomePositionCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.HOME_POSITION); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理云台指令 |
| | | * |
| | | * @param device 设备 |
| | | * @param channelId 通道id |
| | | * @param rootElement |
| | | * @param request |
| | | */ |
| | | private void handlePtzCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) { |
| | | String cmdString = getText(rootElement, type.getVal()); |
| | | try { |
| | | cmder.fronEndCmd(device, channelId, cmdString, |
| | | errorResult -> onError(request, errorResult), |
| | | okResult -> onOk(request, okResult)); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 云台/前端: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理强制关键帧 |
| | | * |
| | | * @param device 设备 |
| | | * @param channelId 通道id |
| | | */ |
| | | private void handleIFameCmd(Device device, SIPRequest request, String channelId) { |
| | | try { |
| | | cmder.iFrameCmd(device, channelId); |
| | | responseAck(request, Response.OK); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理重启命令 |
| | | * |
| | | * @param device 设备信息 |
| | | */ |
| | | private void handleTeleBootCmd(Device device, SIPRequest request) { |
| | | try { |
| | | cmder.teleBootCmd(device); |
| | | responseAck(request, Response.OK); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 重启: {}", e.getMessage()); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 处理拉框控制*** |
| | | * |
| | | * @param device 设备信息 |
| | | * @param channelId 通道id |
| | | * @param rootElement 根节点 |
| | | * @param type 消息类型 |
| | | */ |
| | | private void handleDragZoom(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) { |
| | | try { |
| | | DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class); |
| | | DragZoomRequest.DragZoom dragZoom = dragZoomRequest.getDragZoomIn(); |
| | | if (dragZoom == null) { |
| | | dragZoom = dragZoomRequest.getDragZoomOut(); |
| | | } |
| | | StringBuffer cmdXml = new StringBuffer(200); |
| | | cmdXml.append("<" + type.getVal() + ">\r\n"); |
| | | cmdXml.append("<Length>" + dragZoom.getLength() + "</Length>\r\n"); |
| | | cmdXml.append("<Width>" + dragZoom.getWidth() + "</Width>\r\n"); |
| | | cmdXml.append("<MidPointX>" + dragZoom.getMidPointX() + "</MidPointX>\r\n"); |
| | | cmdXml.append("<MidPointY>" + dragZoom.getMidPointY() + "</MidPointY>\r\n"); |
| | | cmdXml.append("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n"); |
| | | cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n"); |
| | | cmdXml.append("</" + type.getVal() + ">\r\n"); |
| | | cmder.dragZoomCmd(device, channelId, cmdXml.toString()); |
| | | responseAck(request, Response.OK); |
| | | } catch (Exception e) { |
| | | logger.error("[命令发送失败] 拉框控制: {}", e.getMessage()); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 处理看守位命令*** |
| | | * |
| | | * @param device 设备信息 |
| | | * @param channelId 通道id |
| | | * @param rootElement 根节点 |
| | | * @param request 请求信息 |
| | | * @param type 消息类型 |
| | | */ |
| | | private void handleHomePositionCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) { |
| | | try { |
| | | HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class); |
| | | //获取整个消息主体,我们只需要修改请求头即可 |
| | | HomePositionRequest.HomePosition info = homePosition.getHomePosition(); |
| | | cmder.homePositionCmd(device, channelId, info.getEnabled(), info.getResetTime(), info.getPresetIndex(), |
| | | errorResult -> onError(request, errorResult), |
| | | okResult -> onOk(request, okResult)); |
| | | } catch (Exception e) { |
| | | logger.error("[命令发送失败] 看守位设置: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理告警消息*** |
| | | * |
| | | * @param device 设备信息 |
| | | * @param rootElement 根节点 |
| | | * @param request 请求信息 |
| | | */ |
| | | private void handleAlarmCmd(Device device, Element rootElement, SIPRequest request) { |
| | | //告警方法 |
| | | String alarmMethod = ""; |
| | | //告警类型 |
| | | String alarmType = ""; |
| | | List<Element> info = rootElement.elements("Info"); |
| | | if (info != null) { |
| | | for (Element element : info) { |
| | | alarmMethod = getText(element, "AlarmMethod"); |
| | | alarmType = getText(element, "AlarmType"); |
| | | } |
| | | } |
| | | try { |
| | | cmder.alarmCmd(device, alarmMethod, alarmType, |
| | | errorResult -> onError(request, errorResult), |
| | | okResult -> onOk(request, okResult)); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 告警消息: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理录像控制 |
| | | * |
| | | * @param device 设备信息 |
| | | * @param channelId 通道id |
| | | * @param rootElement 根节点 |
| | | * @param request 请求信息 |
| | | * @param type 消息类型 |
| | | */ |
| | | private void handleRecordCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) { |
| | | //获取整个消息主体,我们只需要修改请求头即可 |
| | | String cmdString = getText(rootElement, type.getVal()); |
| | | try { |
| | | cmder.recordCmd(device, channelId, cmdString, |
| | | errorResult -> onError(request, errorResult), |
| | | okResult -> onOk(request, okResult)); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 录像控制: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理报警布防/撤防命令 |
| | | * |
| | | * @param device 设备信息 |
| | | * @param rootElement 根节点 |
| | | * @param request 请求信息 |
| | | * @param type 消息类型 |
| | | */ |
| | | private void handleGuardCmd(Device device, Element rootElement, SIPRequest request, DeviceControlType type) { |
| | | //获取整个消息主体,我们只需要修改请求头即可 |
| | | String cmdString = getText(rootElement, type.getVal()); |
| | | try { |
| | | cmder.guardCmd(device, cmdString, |
| | | errorResult -> onError(request, errorResult), |
| | | okResult -> onOk(request, okResult)); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 布防/撤防命令: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 错误响应处理 |
| | | * |
| | | * @param request 请求 |
| | | * @param eventResult 响应结构 |
| | | */ |
| | | private void onError(SIPRequest request, SipSubscribe.EventResult eventResult) { |
| | | // 失败的回复 |
| | | try { |
| | | responseAck(request, eventResult.statusCode, eventResult.msg); |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("[命令发送失败] 回复: {}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 成功响应处理 |
| | | * |
| | | * @param request 请求 |
| | | * @param eventResult 响应结构 |
| | | */ |
| | | private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult) { |
| | | // 成功的回复 |
| | | try { |
| | | responseAck(request, eventResult.statusCode); |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("[命令发送失败] 回复: {}", e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | logger.info("[收到报警通知]内容:{}", JSON.toJSONString(deviceAlarm)); |
| | | if ("7".equals(deviceAlarm.getAlarmMethod()) ) { |
| | | if (DeviceAlarmMethod.typeOf(Integer.parseInt(deviceAlarm.getAlarmMethod())) !=null) { |
| | | // 发送给平台的报警信息。 发送redis通知 |
| | | logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm)); |
| | | AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); |
| | | alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); |
| | | alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); |
| | | alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); |
| | | alarmChannelMessage.setGbId(channelId); |
| | | redisCatchStorage.sendAlarmMsg(alarmChannelMessage); |
| | | continue; |
| | |
| | | alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); |
| | | alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); |
| | | alarmChannelMessage.setGbId(channelId); |
| | | alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); |
| | | redisCatchStorage.sendAlarmMsg(alarmChannelMessage); |
| | | return; |
| | | } |
| | |
| | | Element recordListElement = rootElementForCharset.element("RecordList"); |
| | | if (recordListElement == null || sumNum == 0) { |
| | | logger.info("无录像数据"); |
| | | int count = recordDataCatch.put(take.getDevice().getDeviceId(),channelId, sn, sumNum, new ArrayList<>()); |
| | | recordInfo.setCount(count); |
| | | eventPublisher.recordEndEventPush(recordInfo); |
| | | recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, new ArrayList<>()); |
| | | releaseRequest(take.getDevice().getDeviceId(), sn); |
| | | } else { |
| | | Iterator<Element> recordListIterator = recordListElement.elementIterator(); |
| | |
| | | recordList.add(record); |
| | | } |
| | | recordInfo.setRecordList(recordList); |
| | | int count = recordDataCatch.put(take.getDevice().getDeviceId(),channelId, sn, sumNum, recordList);recordInfo.setCount(count); |
| | | logger.info("[国标录像], {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum); |
| | | // 发送消息,如果是上级查询此录像,则会通过这里通知给上级 |
| | | eventPublisher.recordEndEventPush(recordInfo); |
| | | int count = recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, recordList); |
| | | logger.info("[国标录像], {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum); |
| | | } |
| | | |
| | | if (recordDataCatch.isComplete(take.getDevice().getDeviceId(), sn)){ |
| | | releaseRequest(take.getDevice().getDeviceId(), sn); |
| | | } |
New file |
| | |
| | | package com.genersoft.iot.vmp.gb28181.utils; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * @author gaofuwang |
| | | * @version 1.0 |
| | | * @date 2022/6/28 14:58 |
| | | */ |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface MessageElement { |
| | | String value(); |
| | | |
| | | String subVal() default ""; |
| | | } |
| | |
| | | package com.genersoft.iot.vmp.gb28181.utils;
|
| | |
|
| | | import com.alibaba.fastjson2.JSON;
|
| | | import com.alibaba.fastjson2.JSONArray;
|
| | | import com.alibaba.fastjson2.JSONObject;
|
| | | import com.genersoft.iot.vmp.gb28181.bean.Device;
|
| | |
| | | import org.slf4j.Logger;
|
| | | import org.slf4j.LoggerFactory;
|
| | | import org.springframework.util.ObjectUtils;
|
| | | import org.springframework.util.StringUtils;
|
| | | import org.springframework.util.ReflectionUtils;
|
| | |
|
| | | import javax.sip.RequestEvent;
|
| | | import javax.sip.message.Request;
|
| | | import java.io.ByteArrayInputStream;
|
| | | import java.io.StringReader;
|
| | | import java.lang.reflect.Field;
|
| | | import java.lang.reflect.InvocationTargetException;
|
| | | import java.lang.reflect.ParameterizedType;
|
| | | import java.lang.reflect.Type;
|
| | | import java.util.*;
|
| | |
|
| | | /**
|
| | |
| | | }
|
| | | return deviceChannel;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 新增方法支持内部嵌套
|
| | | *
|
| | | * @param element xmlElement
|
| | | * @param clazz 结果类
|
| | | * @param <T> 泛型
|
| | | * @return 结果对象
|
| | | * @throws NoSuchMethodException
|
| | | * @throws InvocationTargetException
|
| | | * @throws InstantiationException
|
| | | * @throws IllegalAccessException
|
| | | */
|
| | | public static <T> T loadElement(Element element, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
| | | Field[] fields = clazz.getDeclaredFields();
|
| | | T t = clazz.getDeclaredConstructor().newInstance();
|
| | | for (Field field : fields) {
|
| | | ReflectionUtils.makeAccessible(field);
|
| | | MessageElement annotation = field.getAnnotation(MessageElement.class);
|
| | | if (annotation == null) {
|
| | | continue;
|
| | | }
|
| | | String value = annotation.value();
|
| | | String subVal = annotation.subVal();
|
| | | Element element1 = element.element(value);
|
| | | if (element1 == null) {
|
| | | continue;
|
| | | }
|
| | | if ("".equals(subVal)) {
|
| | | // 无下级数据
|
| | | Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType());
|
| | | Object o = simpleTypeDeal(field.getType(), fieldVal);
|
| | | ReflectionUtils.setField(field, t, o);
|
| | | } else {
|
| | | // 存在下级数据
|
| | | ArrayList<Object> list = new ArrayList<>();
|
| | | Type genericType = field.getGenericType();
|
| | | if (!(genericType instanceof ParameterizedType)) {
|
| | | continue;
|
| | | }
|
| | | Class<?> aClass = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
| | | for (Element element2 : element1.elements(subVal)) {
|
| | | list.add(loadElement(element2, aClass));
|
| | | }
|
| | | ReflectionUtils.setField(field, t, list);
|
| | | }
|
| | | }
|
| | | return t;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 简单类型处理
|
| | | *
|
| | | * @param tClass
|
| | | * @param val
|
| | | * @return
|
| | | */
|
| | | private static Object simpleTypeDeal(Class<?> tClass, Object val) {
|
| | | if (tClass.equals(String.class)) {
|
| | | return val.toString();
|
| | | }
|
| | | if (tClass.equals(Integer.class)) {
|
| | | return Integer.valueOf(val.toString());
|
| | | }
|
| | | if (tClass.equals(Double.class)) {
|
| | | return Double.valueOf(val.toString());
|
| | | }
|
| | | if (tClass.equals(Long.class)) {
|
| | | return Long.valueOf(val.toString());
|
| | | }
|
| | | return val;
|
| | | }
|
| | | } |
| | |
| | | deviceAlarm.setChannelId(gbId); |
| | | deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); |
| | | deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); |
| | | deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType()); |
| | | deviceAlarm.setAlarmPriority("1"); |
| | | deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); |
| | | deviceAlarm.setAlarmType("1"); |
| | | deviceAlarm.setLongitude(0); |
| | | deviceAlarm.setLatitude(0); |
| | | |
| | |
| | | " left join device d on dc.deviceId = d.deviceId\n" + |
| | | "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}") |
| | | List<Device> queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId); |
| | | |
| | | @Select("SELECT pgc.platformId FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}'") |
| | | List<String> queryParentPlatformByChannelId(String channelId); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public void sendAlarmMsg(AlarmChannelMessage msg) { |
| | | String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM; |
| | | String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE; |
| | | logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg)); |
| | | RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); |
| | | } |
| | |
| | | if (allChannelMap.containsKey(deviceChannel.getChannelId())) { |
| | | deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId()); |
| | | deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio()); |
| | | if (allChannelMap.get(deviceChannel.getChannelId()).getStatus() !=deviceChannel.getStatus()){ |
| | | List<String> strings = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getChannelId()); |
| | | if (!CollectionUtils.isEmpty(strings)){ |
| | | strings.forEach(platformId->{ |
| | | eventPublisher.catalogEventPublish(platformId, deviceChannel, deviceChannel.getStatus()==1?CatalogEvent.ON:CatalogEvent.OFF); |
| | | }); |
| | | } |
| | | |
| | | } |
| | | } |
| | | channels.add(deviceChannel); |
| | | if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) { |
| | |
| | | msg.setKey(key); |
| | | msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg)); |
| | | resultHolder.invokeAllResult(msg); |
| | | }); |
| | | },null); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 开始/停止录像: {}", e.getMessage()); |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); |
| | |
| | | msg.setKey(key); |
| | | msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg)); |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | },null); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage()); |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage()); |
| | |
| | | msg.setKey(key); |
| | | msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg)); |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | },null); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 报警复位: {}", e.getMessage()); |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); |
| | |
| | | msg.setKey(key); |
| | | msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg)); |
| | | resultHolder.invokeResult(msg); |
| | | }); |
| | | },null); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 看守位控制: {}", e.getMessage()); |
| | | throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); |