Эх сурвалжийг харах

1. 修复告警接口
2. 添加一键忽略告警功能

kindring 2 жил өмнө
parent
commit
b2a638065f

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/storager/IAiControlStorage.java

@@ -12,8 +12,9 @@ import org.springframework.stereotype.Component;
  */
  */
 @SuppressWarnings("rawtypes")
 @SuppressWarnings("rawtypes")
 public interface IAiControlStorage {
 public interface IAiControlStorage {
-    public PageInfo<AiAlarmData> searchAiAlarm(String startTime, String endTime, String order, String sort, int p, int l);
+    public PageInfo<AiAlarmData> searchAiAlarm(int arithmetic,String key,String alarmState,String startTime, String endTime, String order, String sort, int p, int l);
     public AiAlarmData getAlarmData(String alarmId);
     public AiAlarmData getAlarmData(String alarmId);
-
+    public int getUnreadAlarmTotal();
+    public int markAllAlarm(int arithmetic);
     public int changeAiAlarm(String alarmId,String cmder);
     public int changeAiAlarm(String alarmId,String cmder);
 }
 }

+ 3 - 2
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java

@@ -1,5 +1,6 @@
 package com.genersoft.iot.vmp.storager;
 package com.genersoft.iot.vmp.storager;
 
 
+import com.alibaba.fastjson.JSONArray;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.gb28181.bean.*;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
@@ -162,8 +163,8 @@ public interface IVideoManagerStorage {
 	public PageInfo<AiLib> searchAiLibItems(int page,int count,int libraryId,String key);
 	public PageInfo<AiLib> searchAiLibItems(int page,int count,int libraryId,String key);
 	public PageInfo<AiLib> searchAiLib(int page,int count,String key,Integer arithmetic);
 	public PageInfo<AiLib> searchAiLib(int page,int count,String key,Integer arithmetic);
 
 
-	public int saveAlarm(String deviceId, String channelId, String arithmetic, List<AiAlarm> alarmItems,List<MultipartFile> uploads,
-						 String firmware_version,String timestamp,String battery,String signal,String temp_env,String temp_cpu,String ccid);
+	public int saveAlarm(String deviceId, String channelId, String arithmetic, JSONArray alarmItems, List<MultipartFile> uploads,
+						 String firmware_version, String timestamp, String battery, String signal, String temp_env, String temp_cpu, String ccid);
 	/**
 	/**
 	 * 获取多个设备
 	 * 获取多个设备
 	 *
 	 *

+ 26 - 5
src/main/java/com/genersoft/iot/vmp/storager/dao/HfyDevAiMapper.java

@@ -239,7 +239,7 @@ public interface HfyDevAiMapper {
             ")"
             ")"
             )
             )
 
 
-    int inertAiarmItem(int alarmId,String score,String x1,String x2,String y1,String y2,String info,String trait,String uid);
+    int inertAiarmItem(int alarmId,String score,int x1,int x2,int y1,int y2,String info,String trait,String uid);
 
 
 
 
     @Select("<script>" +
     @Select("<script>" +
@@ -248,22 +248,43 @@ public interface HfyDevAiMapper {
             "<if test='startTime != null'  >" +
             "<if test='startTime != null'  >" +
             " createTime &gt;= #{startTime}" +
             " createTime &gt;= #{startTime}" +
             "</if>" +
             "</if>" +
+            "<if test='arithmetic != 0'  >" +
+            " and arithmetic = #{arithmetic}" +
+            "</if>" +
+            "<if test='(key != null)and(key != \"\")'  >" +
+            " and firmware_version like '%${key}%'" +
+            "</if>" +
+            "<if test='alarmState != null'  >" +
+            " and alarmState = #{alarmState}" +
+            "</if>" +
             "<if test='endTime != null' >" +
             "<if test='endTime != null' >" +
-                " and createTime &lt;= #{endTime}" +
+            " and createTime &lt;= #{endTime}" +
             "</if>" +
             "</if>" +
             "</where>" +
             "</where>" +
             "ORDER BY ${sort} ${order}" +
             "ORDER BY ${sort} ${order}" +
             "</script>")
             "</script>")
-    List<AiAlarmData> getAiAlarms(int startTime, int endTime, String order , String sort);
+    List<AiAlarmData> getAiAlarms(int arithmetic,String key,String alarmState,int startTime, int endTime, String order , String sort);
 
 
     @Select("select * from ai_alarm" +
     @Select("select * from ai_alarm" +
             " where alarmId = #{alarmId}")
             " where alarmId = #{alarmId}")
     List<AiAlarmData> getAiAlarmData(String alarmId);
     List<AiAlarmData> getAiAlarmData(String alarmId);
 
 
+    @Select("select count(*) from ai_alarm" +
+            " where alarmState = #{alarmState}")
+    public int getAlarmStateTotal(String alarmStateStr);
+
+
+
     @Select("select * from ai_alarm_item" +
     @Select("select * from ai_alarm_item" +
             " where alarmId = #{alarmId}")
             " where alarmId = #{alarmId}")
     List<AiAlarm> getAiAlarmItemsByAlarmId(String alarmId);
     List<AiAlarm> getAiAlarmItemsByAlarmId(String alarmId);
 
 
-    @Update("update ai_alarm set readState = #{readState} where alarmId = #{alarmId}")
-    int changeAlarmState(String alarmId,int readState);
+    @Update("update ai_alarm set alarmState = #{alarmState} where alarmId = #{alarmId}")
+    int changeAlarmState(String alarmId,int alarmState);
+
+    @Update("update ai_alarm set alarmState = #{alarmState} where arithmetic = #{arithmetic} and alarmState = 1")
+    int changeAllAlarmState(int arithmetic,int alarmState);
+
+    @Update("update ai_alarm set alarmType = #{alarmType} where alarmId = #{alarmId}")
+    int changeAlarmType(int alarmId,int alarmType);
 }
 }

+ 40 - 4
src/main/java/com/genersoft/iot/vmp/storager/impl/AiControlStorageImpl.java

@@ -25,9 +25,9 @@ public class AiControlStorageImpl implements IAiControlStorage {
     @Autowired
     @Autowired
     private HfyDevAiMapper HfyDevAiMapper;
     private HfyDevAiMapper HfyDevAiMapper;
 
 
-    public PageInfo<AiAlarmData> searchAiAlarm(String startTime, String endTime, String order, String sort, int p, int l){
+    public PageInfo<AiAlarmData> searchAiAlarm(int arithmetic,String key,String alarmState,String startTime, String endTime, String order, String sort, int p, int l){
         PageHelper.startPage(p, l);
         PageHelper.startPage(p, l);
-        // 默认使用创建时间进行desc降序
+        // 排序不分
         logger.info("search prop:{} order:{}",sort,order);
         logger.info("search prop:{} order:{}",sort,order);
         if(sort == "createTime" || sort == "create"){
         if(sort == "createTime" || sort == "create"){
             sort = "createTime";
             sort = "createTime";
@@ -52,8 +52,23 @@ public class AiControlStorageImpl implements IAiControlStorage {
         int _endTime = Integer.parseInt(endTime),
         int _endTime = Integer.parseInt(endTime),
                 _startTime = Integer.parseInt(startTime);
                 _startTime = Integer.parseInt(startTime);
         logger.info("查询时间 start={} end={}" ,_startTime, _endTime);
         logger.info("查询时间 start={} end={}" ,_startTime, _endTime);
+
+        // 分析算法
+        if(arithmetic>0){
+            // 启用算法
+        }
+        // 分析 阅读类型
+        if(alarmState.contains("unread")){
+            alarmState="1";
+        }else if(alarmState.contains("Ignored")){
+            alarmState="2";
+        }else if(alarmState.contains("read")){
+            alarmState="3";
+        }else{
+            alarmState=null;
+        }
         // 查表
         // 查表
-        List<AiAlarmData> result = HfyDevAiMapper.getAiAlarms(_startTime,_endTime,order ,sort);
+        List<AiAlarmData> result = HfyDevAiMapper.getAiAlarms(arithmetic,key,alarmState,_startTime,_endTime,order ,sort);
         return new PageInfo<>(result);
         return new PageInfo<>(result);
     }
     }
 
 
@@ -65,15 +80,34 @@ public class AiControlStorageImpl implements IAiControlStorage {
         }
         }
         AiAlarmData alarmData = alarmList.stream().findFirst().get();
         AiAlarmData alarmData = alarmList.stream().findFirst().get();
         List <AiAlarm> alarmItems = HfyDevAiMapper.getAiAlarmItemsByAlarmId(alarmId);
         List <AiAlarm> alarmItems = HfyDevAiMapper.getAiAlarmItemsByAlarmId(alarmId);
+        // 修改已读状态
+        HfyDevAiMapper.changeAlarmState(alarmId,3);
         alarmData.setItems(alarmItems);
         alarmData.setItems(alarmItems);
         return alarmData;
         return alarmData;
     }
     }
 
 
+    public int getUnreadAlarmTotal(){
+//        HfyDevAiMapper.getAiAlarmItemsByAlarmId(alarmId);
+        int alarmTotal = HfyDevAiMapper.getAlarmStateTotal("1");
+//        logger.info("[测试数据库]alarmTotal:{}",alarmTotal);
+        return alarmTotal;
+    }
+
+    /**
+     * 指定算法类型告警全部忽略
+     * @param arithmetic
+     * @return
+     */
+    public int markAllAlarm(int arithmetic){
+        int alarmTotal = HfyDevAiMapper.changeAllAlarmState(arithmetic,2);
+        return alarmTotal;
+    }
+
     public int changeAiAlarm(String alarmId,String cmder){
     public int changeAiAlarm(String alarmId,String cmder){
         int stateCode = 0;
         int stateCode = 0;
         if(cmder == "read"){
         if(cmder == "read"){
             // 已读
             // 已读
-            stateCode = 1;
+            stateCode = 3;
         }else if(cmder == "ignore"){
         }else if(cmder == "ignore"){
             // 未读
             // 未读
             stateCode = 2;
             stateCode = 2;
@@ -90,4 +124,6 @@ public class AiControlStorageImpl implements IAiControlStorage {
     }
     }
 
 
 
 
+
+
 }
 }

+ 45 - 9
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java

@@ -1,5 +1,7 @@
 package com.genersoft.iot.vmp.storager.impl;
 package com.genersoft.iot.vmp.storager.impl;
 
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.conf.UserSetting;
 import com.genersoft.iot.vmp.conf.exception.ControllerException;
 import com.genersoft.iot.vmp.conf.exception.ControllerException;
@@ -565,8 +567,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 	 * @param uploads
 	 * @param uploads
 	 * @return
 	 * @return
 	 */
 	 */
-	public int saveAlarm(String deviceId, String channelId, String arithmetic, List<AiAlarm> alarmItems, List<MultipartFile> uploads,
-	String firmware_version,String timestamp,String battery,String signal,String temp_env,String temp_cpu,String ccid){
+	public int saveAlarm(String deviceId, String channelId, String arithmetic, JSONArray alarmItems, List<MultipartFile> uploads,
+						 String firmware_version, String timestamp, String battery, String signal, String temp_env, String temp_cpu, String ccid){
 		// 1. 转储上传文件
 		// 1. 转储上传文件
 		UploadService uploadHandle = new UploadService();
 		UploadService uploadHandle = new UploadService();
 		String filePaths = uploadHandle.saveDevAlarm(sipConfig.getMediaPath(),deviceId,uploads);
 		String filePaths = uploadHandle.saveDevAlarm(sipConfig.getMediaPath(),deviceId,uploads);
@@ -574,6 +576,10 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 		long unixTimestamp = date.getTime()/1000;
 		long unixTimestamp = date.getTime()/1000;
 		logger.info("[文件操作] 告警文件存储成功 文件:{}",filePaths);
 		logger.info("[文件操作] 告警文件存储成功 文件:{}",filePaths);
 		logger.info("[数据库操作] alarmItems:{}",alarmItems);
 		logger.info("[数据库操作] alarmItems:{}",alarmItems);
+		int arithmeticNum = Integer.parseInt(arithmetic);
+		arithmeticNum = arithmeticNum + 1;
+		arithmetic = String.valueOf(arithmeticNum);
+
 		HfyDevAiMapper.saveAiAlarm(deviceId,channelId,arithmetic,alarmItems.size(), String.valueOf(unixTimestamp),filePaths,
 		HfyDevAiMapper.saveAiAlarm(deviceId,channelId,arithmetic,alarmItems.size(), String.valueOf(unixTimestamp),filePaths,
 				firmware_version, timestamp, battery,signal,temp_env,temp_cpu,ccid);
 				firmware_version, timestamp, battery,signal,temp_env,temp_cpu,ccid);
 		logger.info("[数据库操作] saveAiAlarm ok");
 		logger.info("[数据库操作] saveAiAlarm ok");
@@ -583,15 +589,45 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
 		logger.info("[数据库操作] findInsertAiAlarm ok ,alarmId:{}",agoAlarm.getAlarmId());
 		logger.info("[数据库操作] findInsertAiAlarm ok ,alarmId:{}",agoAlarm.getAlarmId());
 
 
 		// 4. 存储info信息
 		// 4. 存储info信息
-		// todo 修改循环单条加入到数据库中.
 		int AlarmId = agoAlarm.getAlarmId();
 		int AlarmId = agoAlarm.getAlarmId();
-		for (int i = 0; i < alarmItems.size(); i++)
-		{
-			AiAlarm alarm = alarmItems.get(i);
-			HfyDevAiMapper.inertAiarmItem(AlarmId, alarm.getSimilarity(),
-					alarm.getX1(),alarm.getX2(),alarm.getY1(),alarm.getY2(),
-					alarm.getInfo(),alarm.getTrackId(),alarm.getUid());
+		Boolean isFindUid = false;
+//		arithmetic = "2";
+		if (alarmItems.size()>0){
+			for (int i = 0; i < alarmItems.size(); i++) {
+				// 遍历 jsonarray 数组,把每一个对象转成 json 对象
+				JSONObject alarm = alarmItems.getJSONObject(i);
+				String msgid = alarm.getString("msgid");
+				String track_id = alarm.getString("track_id");
+				String uid = alarm.getString("uid");
+				int x1 = alarm.getIntValue("x1");
+				int y1 = alarm.getIntValue("y1");
+				int x2 = alarm.getIntValue("x2");
+				int y2 = alarm.getIntValue("y2");
+				String similarity = String.valueOf(alarm.getDoubleValue("similarity"));
+				logger.info("Uid={}",uid);
+				if(!uid.equals("-1") ){
+					isFindUid = true;
+				}
+				String info = "uid="+uid;
+				HfyDevAiMapper.inertAiarmItem(AlarmId, similarity,
+						x1,x2,y1,y2,
+						info,track_id,uid);
+			}
+		}
+		logger.info("arithmetic:{}",arithmetic);
+		if(arithmetic == "1"){
+			logger.info("人脸识别算法");
 		}
 		}
+		if(isFindUid){
+			logger.info("匹配到uid");
+		}
+		// 指定算法修改指定的记录
+		if(arithmeticNum == 1 && isFindUid){
+			logger.info("成功匹配到人脸");
+			// 修改是否有匹配到库中的数据
+			HfyDevAiMapper.changeAlarmType(AlarmId,1);
+		}
+
 		// 返回正常值
 		// 返回正常值
 		return 0;
 		return 0;
 	}
 	}

+ 11 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/bean/AiAlarmData.java

@@ -62,6 +62,17 @@ public class AiAlarmData {
 
 
     @Schema(description = "告警子项")
     @Schema(description = "告警子项")
     private List<AiAlarm> items;
     private List<AiAlarm> items;
+    @Schema(description = "是否匹配到库")
+    private int alarmType;
+    public int getAlarmType() {
+        return alarmType;
+    }
+
+    public void setAlarmType(int alarmType) {
+        this.alarmType = alarmType;
+    }
+
+
 
 
 
 
     public String getChannelId() {
     public String getChannelId() {

+ 25 - 0
src/main/java/com/genersoft/iot/vmp/vmanager/bean/AiRequestBody.java

@@ -22,6 +22,28 @@ public class AiRequestBody {
     @Schema(description = "搜索关键字")
     @Schema(description = "搜索关键字")
     private String key;
     private String key;
 
 
+    @Schema(description = "搜索关键字")
+    private String alarmState;
+
+    public int getArithmetic() {
+        return arithmetic;
+    }
+
+    public void setArithmetic(int arithmetic) {
+        this.arithmetic = arithmetic;
+    }
+
+    @Schema(description = "算法")
+    private int arithmetic;
+    public String getAlarmState() {
+        return alarmState!=null?alarmState:"";
+    }
+
+    public void setAlarmState(String alarmState) {
+        this.alarmState = alarmState;
+    }
+
+
     public String getTemp_env() {
     public String getTemp_env() {
         return temp_env;
         return temp_env;
     }
     }
@@ -105,6 +127,7 @@ public class AiRequestBody {
         this.key = key;
         this.key = key;
     }
     }
 
 
+
     @Override
     @Override
     public String toString() {
     public String toString() {
         return "AiRequestBody{" +
         return "AiRequestBody{" +
@@ -117,6 +140,8 @@ public class AiRequestBody {
                 ", startTime='" + startTime + '\'' +
                 ", startTime='" + startTime + '\'' +
                 ", endTime='" + endTime + '\'' +
                 ", endTime='" + endTime + '\'' +
                 ", key='" + key + '\'' +
                 ", key='" + key + '\'' +
+                ", alarmState='" + alarmState + '\'' +
+                ", arithmetic=" + arithmetic +
                 '}';
                 '}';
     }
     }
 }
 }

+ 43 - 6
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/aiLib/AiApi.java

@@ -29,17 +29,25 @@ public class AiApi {
     @Parameter(name = "sort", description = "排序字段", required = false)
     @Parameter(name = "sort", description = "排序字段", required = false)
     @Parameter(name = "p", description = "page" , required = false)
     @Parameter(name = "p", description = "page" , required = false)
     @Parameter(name = "l", description = "limit" , required = false)
     @Parameter(name = "l", description = "limit" , required = false)
+    @Parameter(name = "alarmState", description = "告警阅读类型",required = false)
+    @Parameter(name = "key", description = "关键字",required = false)
+    @Parameter(name = "arithmetic", description = "算法类型",required = false)
     @PostMapping("/alarms")
     @PostMapping("/alarms")
     public WVPResult getAlarms(@RequestBody AiRequestBody req){
     public WVPResult getAlarms(@RequestBody AiRequestBody req){
         WVPResult result = new WVPResult<>();
         WVPResult result = new WVPResult<>();
         String startTime = req.getStartTime(),
         String startTime = req.getStartTime(),
         endTime = req.getEndTime(),
         endTime = req.getEndTime(),
         order = req.getOrder(),
         order = req.getOrder(),
-        sort = req.getSort();
+        sort = req.getSort(),
+        key = req.getKey(),
+        alarmState = req.getAlarmState();
+
         int p = req.getPage(),
         int p = req.getPage(),
-        l=req.getLimit();
+        l=req.getLimit(),
+        arithmetic = req.getArithmetic();
+
         logger.info("req data is {}",req);
         logger.info("req data is {}",req);
-        PageInfo<AiAlarmData> pageInfo = storager.searchAiAlarm(startTime,endTime,order,sort,p,l);
+        PageInfo<AiAlarmData> pageInfo = storager.searchAiAlarm(arithmetic,key,alarmState,startTime,endTime,order,sort,p,l);
         result.setCode(ErrorCode.SUCCESS.getCode());
         result.setCode(ErrorCode.SUCCESS.getCode());
         result.setData(pageInfo.getList());
         result.setData(pageInfo.getList());
         result.setTotal((int) pageInfo.getTotal());
         result.setTotal((int) pageInfo.getTotal());
@@ -59,13 +67,39 @@ public class AiApi {
         return result;
         return result;
     }
     }
 
 
+    @Operation(summary = "获取告警数量信息")
+    @GetMapping("/unread")
+    public WVPResult getAlarmInfo(){
+        WVPResult result = new WVPResult<>();
+        int count = storager.getUnreadAlarmTotal();
+        result.setCode(ErrorCode.SUCCESS.getCode());
+        result.setData(count);
+        return result;
+    }
+
+    @Operation(summary = "标记所有告警信息")
+    @Parameter(name = "arithmetic",description = "对应算法")
+    @GetMapping("/markAll")
+    public WVPResult markAllAlarm(@RequestParam int arithmetic){
+        WVPResult result = new WVPResult<>();
+        if(arithmetic<1){
+            result.setCode(ErrorCode.ERROR400.getCode());
+            result.setMsg("未受支持的算法");
+            return result;
+        }
+        int count = storager.markAllAlarm(arithmetic);
+        result.setCode(ErrorCode.SUCCESS.getCode());
+        result.setData(count);
+        return result;
+    }
+
 
 
     @Operation(summary = "告警信息状态改变")
     @Operation(summary = "告警信息状态改变")
     @Parameter(name = "alarmId",description = "告警id",required = true)
     @Parameter(name = "alarmId",description = "告警id",required = true)
-    @Parameter(name = "cmder",description = "命令",required = true)
-    public WVPResult changeAiAlarm(@RequestParam String alarmId,@RequestParam String cmder){
+    @GetMapping("/alarm/ignore/{alarmId}")
+    public WVPResult changeAiAlarm(@PathVariable String alarmId){
         WVPResult result = new WVPResult<>();
         WVPResult result = new WVPResult<>();
-        int code = storager.changeAiAlarm(alarmId,cmder);
+        int code = storager.changeAiAlarm(alarmId,"ignore");
         if(code == 0){
         if(code == 0){
             result.setCode(ErrorCode.SUCCESS.getCode());
             result.setCode(ErrorCode.SUCCESS.getCode());
         }else{
         }else{
@@ -73,4 +107,7 @@ public class AiApi {
         }
         }
         return result;
         return result;
     }
     }
+
+//    ai/alarm/unread
+
 }
 }

+ 6 - 4
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/aiLib/AiControl.java

@@ -1,6 +1,7 @@
 package com.genersoft.iot.vmp.vmanager.gb28181.aiLib;
 package com.genersoft.iot.vmp.vmanager.gb28181.aiLib;
 
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.conf.SipConfig;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
 import com.genersoft.iot.vmp.vmanager.bean.*;
 import com.genersoft.iot.vmp.vmanager.bean.*;
@@ -149,8 +150,9 @@ public class AiControl {
         String deviceId = bodyAiAlarm.getDev_id();
         String deviceId = bodyAiAlarm.getDev_id();
         String channelId = bodyAiAlarm.getChannelId();
         String channelId = bodyAiAlarm.getChannelId();
         String arithmetic = bodyAiAlarm.getType();
         String arithmetic = bodyAiAlarm.getType();
-        Object recoInfo = JSON.parseObject(bodyAiAlarm.getReco_info()).get("results");
-        List<AiAlarm> items = new ArrayList<>();
+        JSONArray results_recoInfos = JSON.parseObject(bodyAiAlarm.getReco_info()).getJSONArray("results");
+
+//        List<AiAlarm> items = results_recoInfos;
         String firmware_version = bodyAiAlarm.getFirmware_version();
         String firmware_version = bodyAiAlarm.getFirmware_version();
         String timestamp = bodyAiAlarm.getTimestamp();
         String timestamp = bodyAiAlarm.getTimestamp();
         String battery = bodyAiAlarm.getBattery();
         String battery = bodyAiAlarm.getBattery();
@@ -169,7 +171,7 @@ public class AiControl {
                 upload7 = bodyAiAlarm.getUpload7();
                 upload7 = bodyAiAlarm.getUpload7();
 
 
         logger.debug("上报ai识别接口调用 body:{}",bodyAiAlarm);
         logger.debug("上报ai识别接口调用 body:{}",bodyAiAlarm);
-        logger.debug("上报ai识别接口调用 items:{}",items);
+        logger.debug("上报ai识别接口调用 items:{}",results_recoInfos);
         logger.info("test upload{},upload0{}",upload,upload0);
         logger.info("test upload{},upload0{}",upload,upload0);
         WVPResult result = new WVPResult<>();
         WVPResult result = new WVPResult<>();
         // 处理上传文件参数,合并 不同upload字段下的 file 文件
         // 处理上传文件参数,合并 不同upload字段下的 file 文件
@@ -186,7 +188,7 @@ public class AiControl {
             result.setMsg("未接收到上传文件.待处理");
             result.setMsg("未接收到上传文件.待处理");
         }else{
         }else{
             // todo 制作存储预警信息的 controller
             // todo 制作存储预警信息的 controller
-            storager.saveAlarm(deviceId,channelId,arithmetic, items,uploads,
+            storager.saveAlarm(deviceId,channelId,arithmetic, results_recoInfos,uploads,
                     firmware_version,timestamp,battery,signal,temp_env,temp_cpu,ccid);
                     firmware_version,timestamp,battery,signal,temp_env,temp_cpu,ccid);
             result.setCode(ErrorCode.SUCCESS.getCode());
             result.setCode(ErrorCode.SUCCESS.getCode());
             result.setMsg("ok");
             result.setMsg("ok");

+ 1 - 1
src/main/resources/application.yml

@@ -125,7 +125,7 @@ media:
     # [必须修改] zlm服务器的内网IP
     # [必须修改] zlm服务器的内网IP
     ip: 192.168.1.203
     ip: 192.168.1.203
     # [可选] 返回流地址时的ip,置空使用 media.ip
     # [可选] 返回流地址时的ip,置空使用 media.ip
-    stream-ip: szgpay.ticp.net
+    stream-ip: 192.168.1.203
     #stream-ip: 192.168.1.203
     #stream-ip: 192.168.1.203
     #stream-ip: 113.88.194.58
     #stream-ip: 113.88.194.58
     # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
     # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip

+ 85 - 22
web_src/src/components/bell.vue

@@ -7,6 +7,7 @@
         预警中心
         预警中心
       </div>
       </div>
       <div class="page-header-btn">
       <div class="page-header-btn">
+        <el-button @click="markAllEventRead">一键忽略</el-button>
         <el-tooltip class="item" effect="dark" content="..." placement="left-start">
         <el-tooltip class="item" effect="dark" content="..." placement="left-start">
           <el-button icon="el-icon-plus" circle size="mini" ></el-button>
           <el-button icon="el-icon-plus" circle size="mini" ></el-button>
         </el-tooltip>
         </el-tooltip>
@@ -21,30 +22,46 @@
       </el-tabs>
       </el-tabs>
       <div class="tab-header">
       <div class="tab-header">
         <el-input class=" input-with-select" placeholder="输入算法名片段" v-model="key" >
         <el-input class=" input-with-select" placeholder="输入算法名片段" v-model="key" >
-        <el-select v-model="triggerTypeVal"
-                   style="width: 120px;"
+          <el-select v-model="triggerTypeVal"
+                     style="width: 120px;"
+                     slot="prepend"
+                     @change="getNowTriggerType" placeholder="触发类型">
+            <el-option
+              :key="'trigger-0'"
+              label="全部类型"
+              :value="0">
+            </el-option>
+            <el-option
+              v-for="item in triggerTypeArr"
+              :key="'trigger-'+item.val"
+              :label="item.text"
+              :value="item.val"
+              :disabled="item.disabled">
+            </el-option>
+          </el-select>
+
+        </el-input>
+        <el-select v-model="alarmState" style="width: 120px;"
                    slot="prepend"
                    slot="prepend"
-                   @change="getNowTriggerType" placeholder="触发类型">
+                   @change="getNowTriggerType" placeholder="已读状态">
           <el-option
           <el-option
-            :key="'trigger-0'"
-            label="全部类型"
-            :value="0">
-          </el-option>
+            :key="'read-0'"
+            label="全部"
+            :value="0"/>
           <el-option
           <el-option
-            v-for="item in triggerTypeArr"
-            :key="'trigger-'+item.val"
+            v-for="item in alarmStateArr"
+            :key="'read-'+item.val"
             :label="item.text"
             :label="item.text"
             :value="item.val"
             :value="item.val"
-            :disabled="item.disabled">
-          </el-option>
+            :disabled="item.disabled"/>
         </el-select>
         </el-select>
+
         <el-button slot="append"
         <el-button slot="append"
                    style="width: 80px;"
                    style="width: 80px;"
                    icon="el-icon-search"
                    icon="el-icon-search"
                    type="primary"
                    type="primary"
                    :loading="isLoading"
                    :loading="isLoading"
                    @click="searchClickHandle">搜索</el-button>
                    @click="searchClickHandle">搜索</el-button>
-      </el-input>
       </div>
       </div>
       <div class="tab-content">
       <div class="tab-content">
         <el-table
         <el-table
@@ -55,6 +72,11 @@
           @sort-change="tableSortChange"
           @sort-change="tableSortChange"
         >
         >
           <el-table-column prop="alarmId" label="id" :sortable="'alarmId'"></el-table-column>
           <el-table-column prop="alarmId" label="id" :sortable="'alarmId'"></el-table-column>
+          <el-table-column label="是否识别" >
+            <template slot-scope="scope">
+              <span>{{parseAlarmType(scope.row.alarmType)}}</span>
+            </template>
+          </el-table-column>
           <el-table-column prop="deviceId" label="设备号"></el-table-column>
           <el-table-column prop="deviceId" label="设备号"></el-table-column>
           <el-table-column prop="infoNum" label="子项数量" :sortable="'infoNum'"></el-table-column>
           <el-table-column prop="infoNum" label="子项数量" :sortable="'infoNum'"></el-table-column>
           <el-table-column prop="firmware_version" label="固件版本号"></el-table-column>
           <el-table-column prop="firmware_version" label="固件版本号"></el-table-column>
@@ -103,7 +125,15 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import {triggerTypes,getTriggerTypeArr,getAITypeArr,toAlarmState} from "@/map/ai.js"
+import {
+  triggerTypes,
+  getTriggerTypeArr,
+  getAITypeArr,
+  toAlarmState,
+  alarmStates,
+  getAlarmStateArr,
+  toAlarmKey
+} from "@/map/ai.js"
 import handle from "@/until/handle";
 import handle from "@/until/handle";
 import timeUntil from "@/until/time";
 import timeUntil from "@/until/time";
 import SignalInfo from "@/components/common/signalInfo";
 import SignalInfo from "@/components/common/signalInfo";
@@ -120,8 +150,12 @@ export default {
       triggerTypeArr: getTriggerTypeArr(),
       triggerTypeArr: getTriggerTypeArr(),
       aiTypeVal: "1",
       aiTypeVal: "1",
       aiTypeArr: getAITypeArr(),
       aiTypeArr: getAITypeArr(),
+      alarmStates: alarmStates,
+      alarmStateArr: getAlarmStateArr(),
       key: '',
       key: '',
       searchKey: '',
       searchKey: '',
+      alarmState: 0,
+      searchAlarmState: '',
       searchOrder: "descending",
       searchOrder: "descending",
       searchSort: 'alarmId',
       searchSort: 'alarmId',
       lastPage: 1,
       lastPage: 1,
@@ -134,6 +168,7 @@ export default {
   },
   },
   beforeDestroy() {
   beforeDestroy() {
     this.stopQuest();
     this.stopQuest();
+    this.alarmState = this.$route.query.alarmState
   },
   },
   mounted() {
   mounted() {
     this.searchClickHandle();
     this.searchClickHandle();
@@ -169,7 +204,8 @@ export default {
       if(bellSearchSource){
       if(bellSearchSource){
         this.$message.warning("请等待请求完成");
         this.$message.warning("请等待请求完成");
       }
       }
-      searchParam.aiType = this.aiTypeVal;
+      searchParam.arithmetic = parseInt(this.aiTypeVal);
+      searchParam.alarmState = toAlarmKey(searchParam.alarmState);
       bellSearchSource = this.$axios.CancelToken.source();
       bellSearchSource = this.$axios.CancelToken.source();
       this.isLoading = true;
       this.isLoading = true;
       let [err,res] = await handle(
       let [err,res] = await handle(
@@ -199,11 +235,7 @@ export default {
       console.log(tab, event);
       console.log(tab, event);
       console.log(this.aiTypeVal);
       console.log(this.aiTypeVal);
       console.log(tab.name);
       console.log(tab.name);
-      if(this.aiTypeVal !== tab.name){
-        // todo 更新搜索界面
-      }else{
-        // todo
-      }
+      this.searchClickHandle();
     },
     },
     currentChange: function (val) {
     currentChange: function (val) {
       this.currentPage = val;
       this.currentPage = val;
@@ -219,6 +251,7 @@ export default {
         p: this.currentPage,
         p: this.currentPage,
         l: this.count,
         l: this.count,
         key: this.searchKey,
         key: this.searchKey,
+        alarmState: this.searchAlarmState,
         order: this.searchOrder,
         order: this.searchOrder,
         sort: this.searchSort,
         sort: this.searchSort,
       }
       }
@@ -229,12 +262,17 @@ export default {
         p: 1,
         p: 1,
         l: this.count,
         l: this.count,
         key: this.key,
         key: this.key,
+        alarmState: this.alarmState
       }
       }
       this.searchKey = this.key;
       this.searchKey = this.key;
+      this.searchAlarmState = this.alarmState;
       this.searchData(searchParam);
       this.searchData(searchParam);
     },
     },
-    editAlarmHandle(){
-
+    async editAlarmHandle(row){
+      let [err,res] = await handle(this.$axios.get(`/ai/alarm/ignore/${row.alarmId}`))
+      if(err){return this.$message.error(err.msg)}
+      if(res.data.code!==0){return this.$message.warning(res.data.msg)}
+      this.$message.success("操作成功!!!");
     },
     },
     moreAlarmHandle(row){
     moreAlarmHandle(row){
       this.$router.push(`/alarm/${row.alarmId}`)
       this.$router.push(`/alarm/${row.alarmId}`)
@@ -251,11 +289,35 @@ export default {
         sort: prop,
         sort: prop,
         p: 1,
         p: 1,
         l: this.count,
         l: this.count,
-        key: this.key,
+        key: this.searchKey,
+        alarmState: this.searchAlarmState
       }
       }
       this.searchSort = prop;
       this.searchSort = prop;
       this.searchOrder = order;
       this.searchOrder = order;
       this.searchData(searchParam);
       this.searchData(searchParam);
+    },
+
+    // 全部忽略
+    markAllEventRead(){
+      this.$confirm('此操作将忽略全部告警内容,请再次确认?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(async () => {
+        let [err,res] = await handle(this.$axios.get(`/ai/markAll?arithmetic=${this.aiTypeVal}`))
+        if(err){return this.$message.error(err.msg)}
+        if(res.data.code!==0){return this.$message.warning(res.data.msg)}
+        this.$message.success("操作成功!!!");
+      })
+    },
+    parseAlarmType(text){
+      let r = ""
+      if(text=="1"){
+        r = "设备名单人员";
+      }else{
+        r = "陌生人"
+      }
+      return r
     }
     }
   }
   }
 }
 }
@@ -281,6 +343,7 @@ export default {
 }
 }
 .tab-box .tab-header{
 .tab-box .tab-header{
   height: 40px;
   height: 40px;
+  width: 99%;
   display: flex;
   display: flex;
 }
 }
 .tab-box .tab-header > *{
 .tab-box .tab-header > *{

+ 13 - 0
web_src/src/components/mediaView.vue

@@ -16,6 +16,13 @@
       <div class="viewBox">
       <div class="viewBox">
         <div class="view">
         <div class="view">
           <img v-show="mediaImages[mediaInd]" :src="'/aiLib/'+mediaImages[mediaInd].url" alt="">
           <img v-show="mediaImages[mediaInd]" :src="'/aiLib/'+mediaImages[mediaInd].url" alt="">
+          <div v-show="mediaImages[mediaInd]" class="toolBox">
+            <a :href="'/aiLib/'+mediaImages[mediaInd].url">
+              <el-button icon="el-icon-download" circle />
+            </a>
+
+          </div>
+
         </div>
         </div>
         <div class="viewController">
         <div class="viewController">
           <div class="mediaImage"
           <div class="mediaImage"
@@ -172,6 +179,12 @@ export default {
 }
 }
 .viewBox .view{
 .viewBox .view{
   height: calc(100% - 150px);
   height: calc(100% - 150px);
+  position: relative;
+}
+.viewBox .view .toolBox{
+  position: absolute;
+  bottom: 0;
+  right: 0;
 }
 }
 .viewBox .viewController{
 .viewBox .viewController{
   height: 150px;
   height: 150px;

+ 40 - 3
web_src/src/layout/UiHeader.vue

@@ -15,9 +15,11 @@
       <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
       <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
       <el-menu-item index="/aiLib">算法管理</el-menu-item>
       <el-menu-item index="/aiLib">算法管理</el-menu-item>
 
 
-      <el-menu-item index="/bell">
+      <el-menu-item index="/bell?alarmState=1" class="emi">
         <el-tooltip content="告警中心" class="mr-5">
         <el-tooltip content="告警中心" class="mr-5">
-          <el-icon name="bell" color="#fff"></el-icon>
+          <el-badge class="badge" :value="unreadAlarmCount" :hidden="unreadAlarmCount<1">
+            <el-icon name="bell" color="#fff"></el-icon>
+          </el-badge>
         </el-tooltip>
         </el-tooltip>
       </el-menu-item>
       </el-menu-item>
 
 
@@ -50,6 +52,7 @@
 <script>
 <script>
 
 
 import changePasswordDialog from '../components/dialog/changePassword.vue'
 import changePasswordDialog from '../components/dialog/changePassword.vue'
+import handle from "@/until/handle";
 
 
 export default {
 export default {
   name: "UiHeader",
   name: "UiHeader",
@@ -59,6 +62,10 @@ export default {
       alarmNotify: false,
       alarmNotify: false,
       sseSource: null,
       sseSource: null,
       activeIndex: this.$route.path,
       activeIndex: this.$route.path,
+      unreadAlarmCount: 0,
+      // 刷新时间
+      refreshTime: 15000,
+      requestInProgress: false,
       editUser: this.$cookies.get("session").roleId==1
       editUser: this.$cookies.get("session").roleId==1
     };
     };
   },
   },
@@ -73,6 +80,7 @@ export default {
     // window.addEventListener('unload', e => this.unloadHandler(e))
     // window.addEventListener('unload', e => this.unloadHandler(e))
     this.alarmNotify = this.getAlarmSwitchStatus() === "true";
     this.alarmNotify = this.getAlarmSwitchStatus() === "true";
     this.sseControl();
     this.sseControl();
+    this.fetchAlarmCount();
   },
   },
   methods: {
   methods: {
     loginout() {
     loginout() {
@@ -89,6 +97,7 @@ export default {
         console.error(error)
         console.error(error)
       });
       });
     },
     },
+
     changePassword() {
     changePassword() {
       this.$refs.changePasswordDialog.openDialog()
       this.$refs.changePasswordDialog.openDialog()
     },
     },
@@ -150,7 +159,25 @@ export default {
     },
     },
     setAlarmSwitchStatus() {
     setAlarmSwitchStatus() {
       localStorage.setItem("alarmSwitchStatus", this.alarmNotify);
       localStorage.setItem("alarmSwitchStatus", this.alarmNotify);
-    }
+    },
+    async fetchAlarmCount() {
+      if (this.requestInProgress) return;
+      this.requestInProgress = true;
+      let [err,res] = await handle(this.$axios.get('/ai/unread'));
+      this.requestInProgress = false;
+      setTimeout(() => { this.fetchAlarmCount(); }, this.refreshTime);
+      if(err){
+        return console.error(err);
+      }
+
+      if (res.data.code === 0) {
+        this.unreadAlarmCount = res.data.data;
+      } else {
+        console.log("未知错误")
+        this.$message.error(res.data.msg);
+      }
+
+    },
   },
   },
   destroyed() {
   destroyed() {
     window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
     window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
@@ -161,6 +188,8 @@ export default {
       this.sseSource.close();
       this.sseSource.close();
     }
     }
   },
   },
+
+
   showBell(){
   showBell(){
     console.log('11122')
     console.log('11122')
   }
   }
@@ -182,4 +211,12 @@ export default {
   color: #fff!important;
   color: #fff!important;
   background-color: #1890ff!important;
   background-color: #1890ff!important;
 }
 }
+.badge{
+  display: flex;
+}
+.emi{
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
 </style>
 </style>

+ 31 - 2
web_src/src/map/ai.js

@@ -39,7 +39,7 @@ const alarmStateEnum = {
     val: 2,
     val: 2,
     text: '不警告'
     text: '不警告'
   },
   },
-  readed: {
+  read: {
     val: 3,
     val: 3,
     text: '已读'
     text: '已读'
   }
   }
@@ -54,6 +54,13 @@ export const triggerTypes = {
   whiteList:triggerTypeEnum.whiteList.val,
   whiteList:triggerTypeEnum.whiteList.val,
   blackList:triggerTypeEnum.blackList.val,
   blackList:triggerTypeEnum.blackList.val,
 }
 }
+
+export const alarmStates = {
+  unread:alarmStateEnum.unread.val,
+  noAlarm:alarmStateEnum.noAlarm.val,
+  read:alarmStateEnum.read.val,
+}
+
 const aiTypes = {
 const aiTypes = {
   face:arithmeticEnum.face.val,
   face:arithmeticEnum.face.val,
   fire:arithmeticEnum.fire.val,
   fire:arithmeticEnum.fire.val,
@@ -106,6 +113,25 @@ export function toAlarmState(num){
   return key?alarmStateEnum[key]:false;
   return key?alarmStateEnum[key]:false;
 }
 }
 
 
+
+export function getAlarmStateArr(){
+  return Object.keys(alarmStateEnum).map(key=>{
+    return {
+      ...alarmStateEnum[key],
+      disabled: false,
+    };
+  })
+}
+
+/**
+ * 获取指定alarmState的英文key
+ * @param num
+ * @returns {string|string}
+ */
+export function toAlarmKey(num){
+  let key = Object.keys(alarmStateEnum).find(key=>alarmStateEnum[key].val===num);
+  return key?key:""
+}
 export default {
 export default {
   arithmeticEnum,
   arithmeticEnum,
   toArithmetic,
   toArithmetic,
@@ -115,6 +141,9 @@ export default {
   triggerTypes,
   triggerTypes,
   getAITypeArr,
   getAITypeArr,
   getTriggerTypeArr,
   getTriggerTypeArr,
+  alarmStates,
   alarmStateEnum,
   alarmStateEnum,
-  toAlarmState
+  getAlarmStateArr,
+  toAlarmState,
+  toAlarmKey
 }
 }

+ 0 - 1
web_src/src/until/handle.js

@@ -2,7 +2,6 @@
 
 
 
 
 function handle (promise){
 function handle (promise){
-  console.log(promise);
     return new Promise(resolve => {
     return new Promise(resolve => {
         try{
         try{
             promise.then(val => {
             promise.then(val => {