Commit 0dc1807f621ce9077b58dff40ad4485c9a3d6c40

Authored by 648540858
1 parent 25102229

优化通道同步添加对SN的判断,精简代码

src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
... ... @@ -4,6 +4,7 @@ import java.util.Date;
4 4 import java.util.List;
5 5  
6 6 public class CatalogData {
  7 + private int sn; // 命令序列号
7 8 private int total;
8 9 private List<DeviceChannel> channelList;
9 10 private Date lastTime;
... ... @@ -15,6 +16,15 @@ public class CatalogData {
15 16 }
16 17 private CatalogDataStatus status;
17 18  
  19 +
  20 + public int getSn() {
  21 + return sn;
  22 + }
  23 +
  24 + public void setSn(int sn) {
  25 + this.sn = sn;
  26 + }
  27 +
18 28 public int getTotal() {
19 29 return total;
20 30 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java
... ... @@ -54,6 +54,7 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
54 54 @Autowired
55 55 private SIPCommander cmder;
56 56  
  57 +
57 58 private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
58 59  
59 60 @Override
... ... @@ -76,7 +77,7 @@ public class OnlineEventListener implements ApplicationListener&lt;OnlineEvent&gt; {
76 77 if (deviceInStore == null) { //第一次上线
77 78 logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId());
78 79 cmder.deviceInfoQuery(device);
79   - cmder.catalogQuery(device, null);
  80 + deviceService.sync(device);
80 81 }
81 82 break;
82 83 // 设备主动发送心跳触发的在线事件
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
... ... @@ -26,28 +26,35 @@ public class CatalogDataCatch {
26 26 @Autowired
27 27 private IVideoManagerStorage storager;
28 28  
29   - public void addReady(String key) {
30   - CatalogData catalogData = data.get(key);
  29 + public void addReady(Device device, int sn ) {
  30 + CatalogData catalogData = data.get(device.getDeviceId());
31 31 if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
32 32 catalogData = new CatalogData();
33 33 catalogData.setChannelList(new ArrayList<>());
  34 + catalogData.setDevice(device);
  35 + catalogData.setSn(sn);
34 36 catalogData.setStatus(CatalogData.CatalogDataStatus.ready);
35 37 catalogData.setLastTime(new Date(System.currentTimeMillis()));
36   - data.put(key, catalogData);
  38 + data.put(device.getDeviceId(), catalogData);
37 39 }
38 40 }
39 41  
40   - public void put(String key, int total, Device device, List<DeviceChannel> deviceChannelList) {
41   - CatalogData catalogData = data.get(key);
  42 + public void put(String deviceId, int sn, int total, Device device, List<DeviceChannel> deviceChannelList) {
  43 + CatalogData catalogData = data.get(deviceId);
42 44 if (catalogData == null) {
43 45 catalogData = new CatalogData();
  46 + catalogData.setSn(sn);
44 47 catalogData.setTotal(total);
45 48 catalogData.setDevice(device);
46 49 catalogData.setChannelList(new ArrayList<>());
47 50 catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
48 51 catalogData.setLastTime(new Date(System.currentTimeMillis()));
49   - data.put(key, catalogData);
  52 + data.put(deviceId, catalogData);
50 53 }else {
  54 + // 同一个设备的通道同步请求只考虑一个,其他的直接忽略
  55 + if (catalogData.getSn() != sn) {
  56 + return;
  57 + }
51 58 catalogData.setTotal(total);
52 59 catalogData.setDevice(device);
53 60 catalogData.setStatus(CatalogData.CatalogDataStatus.runIng);
... ... @@ -56,20 +63,20 @@ public class CatalogDataCatch {
56 63 }
57 64 }
58 65  
59   - public List<DeviceChannel> get(String key) {
60   - CatalogData catalogData = data.get(key);
  66 + public List<DeviceChannel> get(String deviceId) {
  67 + CatalogData catalogData = data.get(deviceId);
61 68 if (catalogData == null) return null;
62 69 return catalogData.getChannelList();
63 70 }
64 71  
65   - public int getTotal(String key) {
66   - CatalogData catalogData = data.get(key);
  72 + public int getTotal(String deviceId) {
  73 + CatalogData catalogData = data.get(deviceId);
67 74 if (catalogData == null) return 0;
68 75 return catalogData.getTotal();
69 76 }
70 77  
71   - public SyncStatus getSyncStatus(String key) {
72   - CatalogData catalogData = data.get(key);
  78 + public SyncStatus getSyncStatus(String deviceId) {
  79 + CatalogData catalogData = data.get(deviceId);
73 80 if (catalogData == null) return null;
74 81 SyncStatus syncStatus = new SyncStatus();
75 82 syncStatus.setCurrent(catalogData.getChannelList().size());
... ... @@ -78,10 +85,6 @@ public class CatalogDataCatch {
78 85 return syncStatus;
79 86 }
80 87  
81   - public void del(String key) {
82   - data.remove(key);
83   - }
84   -
85 88 @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时
86 89 private void timerTask(){
87 90 Set<String> keys = data.keySet();
... ... @@ -92,23 +95,30 @@ public class CatalogDataCatch {
92 95 Calendar calendarBefore30S = Calendar.getInstance();
93 96 calendarBefore30S.setTime(new Date());
94 97 calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30);
95   - for (String key : keys) {
96   - CatalogData catalogData = data.get(key);
97   - if (catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据
98   - storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
99   - String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条";
  98 + for (String deviceId : keys) {
  99 + CatalogData catalogData = data.get(deviceId);
  100 + if ( catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据
  101 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) {
  102 + storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList());
  103 + if (catalogData.getTotal() != catalogData.getChannelList().size()) {
  104 + String errorMsg = "更新成功,共" + catalogData.getTotal() + "条,已更新" + catalogData.getChannelList().size() + "条";
  105 + catalogData.setErrorMsg(errorMsg);
  106 + }
  107 + }else if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.ready)) {
  108 + String errorMsg = "同步失败,等待回复超时";
  109 + catalogData.setErrorMsg(errorMsg);
  110 + }
100 111 catalogData.setStatus(CatalogData.CatalogDataStatus.end);
101   - catalogData.setErrorMsg(errorMsg);
102 112 }
103   - if (catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除
104   - data.remove(key);
  113 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除
  114 + data.remove(deviceId);
105 115 }
106 116 }
107 117 }
108 118  
109 119  
110   - public void setChannelSyncEnd(String key, String errorMsg) {
111   - CatalogData catalogData = data.get(key);
  120 + public void setChannelSyncEnd(String deviceId, String errorMsg) {
  121 + CatalogData catalogData = data.get(deviceId);
112 122 if (catalogData == null)return;
113 123 catalogData.setStatus(CatalogData.CatalogDataStatus.end);
114 124 catalogData.setErrorMsg(errorMsg);
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -250,7 +250,7 @@ public interface ISIPCommander {
250 250 *
251 251 * @param device 视频设备
252 252 */
253   - boolean catalogQuery(Device device, SipSubscribe.Event errorEvent);
  253 + boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent);
254 254  
255 255 /**
256 256 * 查询录像信息
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -1208,14 +1208,14 @@ public class SIPCommander implements ISIPCommander {
1208 1208 * @param device 视频设备
1209 1209 */
1210 1210 @Override
1211   - public boolean catalogQuery(Device device, SipSubscribe.Event errorEvent) {
  1211 + public boolean catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) {
1212 1212 try {
1213 1213 StringBuffer catalogXml = new StringBuffer(200);
1214 1214 String charset = device.getCharset();
1215 1215 catalogXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
1216 1216 catalogXml.append("<Query>\r\n");
1217 1217 catalogXml.append("<CmdType>Catalog</CmdType>\r\n");
1218   - catalogXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1218 + catalogXml.append("<SN>" + sn + "</SN>\r\n");
1219 1219 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
1220 1220 catalogXml.append("</Query>\r\n");
1221 1221  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
... ... @@ -86,23 +86,17 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
86 86 rootElement = getRootElement(evt, device.getCharset());
87 87 Element deviceListElement = rootElement.element("DeviceList");
88 88 Element sumNumElement = rootElement.element("SumNum");
89   - if (sumNumElement == null || deviceListElement == null) {
  89 + Element snElement = rootElement.element("SN");
  90 + if (snElement == null || sumNumElement == null || deviceListElement == null) {
90 91 responseAck(evt, Response.BAD_REQUEST, "xml error");
91 92 return;
92 93 }
93 94 int sumNum = Integer.parseInt(sumNumElement.getText());
  95 +
94 96 if (sumNum == 0) {
95 97 // 数据已经完整接收
96 98 storager.cleanChannelsForDevice(device.getDeviceId());
97   - RequestMessage msg = new RequestMessage();
98   - msg.setKey(key);
99   - WVPResult<Object> result = new WVPResult<>();
100   - result.setCode(0);
101   - result.setData(device);
102   - msg.setData(result);
103   - result.setMsg("更新成功,共0条");
104   - deferredResultHolder.invokeAllResult(msg);
105   - catalogDataCatch.del(key);
  99 + catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null);
106 100 }else {
107 101 Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
108 102 if (deviceListIterator != null) {
... ... @@ -123,24 +117,18 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
123 117  
124 118 channelList.add(deviceChannel);
125 119 }
  120 + int sn = Integer.parseInt(snElement.getText());
126 121 logger.info("收到来自设备【{}】的通道: {}个,{}/{}", device.getDeviceId(), channelList.size(), catalogDataCatch.get(key) == null ? 0 :catalogDataCatch.get(key).size(), sumNum);
127   - catalogDataCatch.put(key, sumNum, device, channelList);
128   - if (catalogDataCatch.get(key).size() == sumNum) {
  122 + catalogDataCatch.put(device.getDeviceId(), sn, sumNum, device, channelList);
  123 + if (catalogDataCatch.get(device.getDeviceId()).size() == sumNum) {
129 124 // 数据已经完整接收
130   - boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(key));
131   - RequestMessage msg = new RequestMessage();
132   - msg.setKey(key);
133   - WVPResult<Object> result = new WVPResult<>();
134   - result.setCode(0);
135   - result.setData(device);
136   - if (resetChannelsResult || sumNum ==0) {
137   - result.setMsg("更新成功,共" + sumNum + "条,已更新" + catalogDataCatch.get(key).size() + "条");
  125 + boolean resetChannelsResult = storager.resetChannels(device.getDeviceId(), catalogDataCatch.get(device.getDeviceId()));
  126 + if (!resetChannelsResult) {
  127 + String errorMsg = "接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(device.getDeviceId()).size() + "条";
  128 + catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), errorMsg);
138 129 }else {
139   - result.setMsg("接收成功,写入失败,共" + sumNum + "条,已接收" + catalogDataCatch.get(key).size() + "条");
  130 + catalogDataCatch.setChannelSyncEnd(device.getDeviceId(), null);
140 131 }
141   - msg.setData(result);
142   - deferredResultHolder.invokeAllResult(msg);
143   - catalogDataCatch.del(key);
144 132 }
145 133 }
146 134 // 回复200 OK
... ... @@ -228,21 +216,18 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
228 216 }
229 217  
230 218 public SyncStatus getChannelSyncProgress(String deviceId) {
231   - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
232   - if (catalogDataCatch.get(key) == null) {
  219 + if (catalogDataCatch.get(deviceId) == null) {
233 220 return null;
234 221 }else {
235   - return catalogDataCatch.getSyncStatus(key);
  222 + return catalogDataCatch.getSyncStatus(deviceId);
236 223 }
237 224 }
238 225  
239   - public void setChannelSyncReady(String deviceId) {
240   - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
241   - catalogDataCatch.addReady(key);
  226 + public void setChannelSyncReady(Device device, int sn) {
  227 + catalogDataCatch.addReady(device, sn);
242 228 }
243 229  
244 230 public void setChannelSyncEnd(String deviceId, String errorMsg) {
245   - String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
246   - catalogDataCatch.setChannelSyncEnd(key, errorMsg);
  231 + catalogDataCatch.setChannelSyncEnd(deviceId, errorMsg);
247 232 }
248 233 }
... ...
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
... ... @@ -44,15 +44,8 @@ public interface IDeviceService {
44 44 SyncStatus getChannelSyncStatus(String deviceId);
45 45  
46 46 /**
47   - * 设置通道同步状态
48   - * @param deviceId 设备ID
49   - */
50   - void setChannelSyncReady(String deviceId);
51   -
52   - /**
53   - * 设置同步结束
54   - * @param deviceId 设备ID
55   - * @param errorMsg 错误信息
  47 + * 通道同步
  48 + * @param device
56 49 */
57   - void setChannelSyncEnd(String deviceId, String errorMsg);
  50 + void sync(Device device);
58 51 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
... ... @@ -100,12 +100,16 @@ public class DeviceServiceImpl implements IDeviceService {
100 100 }
101 101  
102 102 @Override
103   - public void setChannelSyncReady(String deviceId) {
104   - catalogResponseMessageHandler.setChannelSyncReady(deviceId);
105   - }
106   -
107   - @Override
108   - public void setChannelSyncEnd(String deviceId, String errorMsg) {
109   - catalogResponseMessageHandler.setChannelSyncEnd(deviceId, errorMsg);
  103 + public void sync(Device device) {
  104 + if (catalogResponseMessageHandler.getChannelSyncProgress(device.getDeviceId()) != null) {
  105 + logger.info("开启同步时发现同步已经存在");
  106 + return;
  107 + }
  108 + int sn = (int)((Math.random()*9+1)*100000);
  109 + catalogResponseMessageHandler.setChannelSyncReady(device, sn);
  110 + sipCommander.catalogQuery(device, sn, event -> {
  111 + String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg);
  112 + catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg);
  113 + });
110 114 }
111 115 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
... ... @@ -238,12 +238,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
238 238  
239 239 @Override
240 240 public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) {
  241 + if (deviceChannelList == null) {
  242 + return false;
  243 + }
241 244 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
242 245 // 数据去重
243 246 List<DeviceChannel> channels = new ArrayList<>();
244 247 StringBuilder stringBuilder = new StringBuilder();
245 248 Map<String, Integer> subContMap = new HashMap<>();
246   - if (deviceChannelList.size() > 1) {
  249 + if (deviceChannelList != null && deviceChannelList.size() > 1) {
247 250 // 数据去重
248 251 Set<String> gbIdSet = new HashSet<>();
249 252 for (DeviceChannel deviceChannel : deviceChannelList) {
... ... @@ -300,6 +303,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
300 303 dataSourceTransactionManager.commit(transactionStatus); //手动提交
301 304 return true;
302 305 }catch (Exception e) {
  306 + e.printStackTrace();
303 307 dataSourceTransactionManager.rollback(transactionStatus);
304 308 return false;
305 309 }
... ... @@ -415,10 +419,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
415 419 TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
416 420 boolean result = false;
417 421 try {
418   - if (platformChannelMapper.delChannelForDeviceId(deviceId) <0 // 删除与国标平台的关联
419   - || deviceChannelMapper.cleanChannelsByDeviceId(deviceId) < 0 // 删除他的通道
420   - || deviceMapper.del(deviceId) < 0 // 移除设备信息
421   - ) {
  422 + platformChannelMapper.delChannelForDeviceId(deviceId);
  423 + deviceChannelMapper.cleanChannelsByDeviceId(deviceId);
  424 + if ( deviceMapper.del(deviceId) < 0 ) {
422 425 //事务回滚
423 426 dataSourceTransactionManager.rollback(transactionStatus);
424 427 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
... ... @@ -172,12 +172,8 @@ public class DeviceQuery {
172 172 wvpResult.setData(syncStatus);
173 173 return wvpResult;
174 174 }
175   - SyncStatus syncStatusReady = new SyncStatus();
176   - deviceService.setChannelSyncReady(deviceId);
177   - cmder.catalogQuery(device, event -> {
178   - String errorMsg = String.format("同步通道失败,错误码: %s, %s", event.statusCode, event.msg);
179   - deviceService.setChannelSyncEnd(deviceId, errorMsg);
180   - });
  175 + deviceService.sync(device);
  176 +
181 177 WVPResult<SyncStatus> wvpResult = new WVPResult<>();
182 178 wvpResult.setCode(0);
183 179 wvpResult.setMsg("开始同步");
... ...
web_src/src/components/dialog/SyncChannelProgress.vue
... ... @@ -61,23 +61,36 @@ export default {
61 61 if (!this.syncFlag) {
62 62 this.syncFlag = true;
63 63 }
64   - if (res.data.data == null) {
65   - this.syncStatus = "success"
66   - this.percentage = 100;
67   - this.msg = '同步成功';
68   - }else if (res.data.data.total == 0){
69   - this.msg = `等待同步中`;
70   - this.timmer = setTimeout(this.getProgress, 300)
71   - }else if (res.data.data.errorMsg !== null ){
72   - this.msg = res.data.data.errorMsg;
73   - this.syncStatus = "exception"
74   - }else {
75   - this.total = res.data.data.total;
76   - this.current = res.data.data.current;
77   - this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
78   - this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
79   - this.timmer = setTimeout(this.getProgress, 300)
  64 +
  65 + if (res.data.data != null) {
  66 + if (res.data.data.total == 0) {
  67 + if (res.data.data.errorMsg !== null ){
  68 + this.msg = res.data.data.errorMsg;
  69 + this.syncStatus = "exception"
  70 + }else {
  71 + this.msg = `等待同步中`;
  72 + this.timmer = setTimeout(this.getProgress, 300)
  73 + }
  74 + }else {
  75 + if (res.data.data.total == res.data.data.current) {
  76 + this.syncStatus = "success"
  77 + this.percentage = 100;
  78 + this.msg = '同步成功';
  79 + }else {
  80 + if (res.data.data.errorMsg !== null ){
  81 + this.msg = res.data.data.errorMsg;
  82 + this.syncStatus = "exception"
  83 + }else {
  84 + this.total = res.data.data.total;
  85 + this.current = res.data.data.current;
  86 + this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
  87 + this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
  88 + this.timmer = setTimeout(this.getProgress, 300)
  89 + }
  90 + }
  91 + }
80 92 }
  93 +
81 94 }else {
82 95 if (this.syncFlag) {
83 96 this.syncStatus = "success"
... ...