fix: 接收AI数据
This commit is contained in:
parent
7fb042387b
commit
a69695bafc
@ -0,0 +1,56 @@
|
||||
package com.yfd.platform.common.enums;
|
||||
|
||||
/**
|
||||
* @author xyx
|
||||
* @date 2023-11-27 15:53
|
||||
*/
|
||||
public enum AicomTypeEnum {
|
||||
PFW("AI_5001","漂浮物"),
|
||||
YYCYX("AI_5002","运鱼车运行"),
|
||||
YYCCG("AI_5003","运鱼船出港"),
|
||||
JYCJY("AI_5004","集鱼船集鱼"),
|
||||
DLMYX("AI_5005","叠梁门运行"),
|
||||
GYSYX("AI_5006","赶鱼栅运行"),
|
||||
SYJYX("AI_5007","升鱼机运行"),
|
||||
AGVXC("AI_5008","AGV小车"),
|
||||
YLZY("AI_5009","鱼类暂养"),
|
||||
BASYJ("AI_5010","坝上升鱼机"),
|
||||
PFWQL("AI_5011","漂浮物清理"),
|
||||
YDFL("AI_5012","鱼道放流");
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
|
||||
AicomTypeEnum(String code, String name){
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return this.name;
|
||||
}
|
||||
public enum DlmValueEnum {
|
||||
CLOSE("close","关闭"),
|
||||
OPEN("open","开启");
|
||||
|
||||
private String code;
|
||||
private String name;
|
||||
|
||||
DlmValueEnum(String code, String name){
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCode(){
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,9 @@ public class ImeVmsstbprptVo {
|
||||
@Schema(description = "站类编码")
|
||||
private String sttpCode;
|
||||
|
||||
@Schema(description = "站类编码")
|
||||
private String sttp;
|
||||
|
||||
@Schema(description = "描点状态")
|
||||
private String anchoPointState;
|
||||
|
||||
|
||||
@ -433,6 +433,7 @@ public class ImeServiceImpl implements ImeService {
|
||||
return "SELECT " +
|
||||
"src.STCD AS id, " +
|
||||
"src.STTP_CODE AS sttpCode, " +
|
||||
"src.STTP AS sttp, " +
|
||||
"CONCAT('ZHZB_', src.STTP_CODE) AS anchoPointState, " +
|
||||
"src.STLC AS stlc, " +
|
||||
"src.STCD AS stcd, " +
|
||||
@ -477,6 +478,7 @@ public class ImeServiceImpl implements ImeService {
|
||||
Map<String, String> columns = new LinkedHashMap<>();
|
||||
columns.put("id", "t.id AS id");
|
||||
columns.put("sttpCode", "t.sttpCode AS sttpCode");
|
||||
columns.put("sttp", "t.sttp AS sttp");
|
||||
columns.put("stcd", "t.stcd AS stcd");
|
||||
columns.put("stnm", "t.stnm AS stnm");
|
||||
columns.put("rstcd", "t.rstcd AS rstcd");
|
||||
|
||||
@ -2,15 +2,15 @@ package com.yfd.platform.qgc_env.warn.controller;
|
||||
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.qgc_env.warn.entity.ao.ReceiveAiDataAo;
|
||||
import com.yfd.platform.qgc_env.warn.service.WarnDataService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/warn")
|
||||
@ -80,4 +80,11 @@ public class WarnDataController {
|
||||
public ResponseResult getAiFileKendoListCust(@RequestBody DataSourceRequest dataSourceRequest) {
|
||||
return ResponseResult.successData(warnDataService.getAiFileKendoListCust(dataSourceRequest));
|
||||
}
|
||||
|
||||
@PostMapping("/receiveAiData")
|
||||
@Operation(summary = "接收AI数据")
|
||||
public ResponseResult receiveAiData(@RequestBody List<ReceiveAiDataAo> aoList) {
|
||||
warnDataService.receiveAiData(aoList);
|
||||
return ResponseResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
package com.yfd.platform.qgc_env.warn.entity.ao;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* AI识别数据(AI设备上抛识别的 aidata 载荷)
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "AI识别数据")
|
||||
public class AiDataAo {
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(description = "识别时间")
|
||||
private Date time;
|
||||
|
||||
@Schema(description = "漂浮物面积(平方米)")
|
||||
private BigDecimal area;
|
||||
|
||||
@Schema(description = "视频流量")
|
||||
private BigDecimal flow;
|
||||
|
||||
@Schema(description = "水位")
|
||||
private BigDecimal water_level;
|
||||
|
||||
@Schema(description = "断面流速分布")
|
||||
private Map<String, AiFlowAo> flow_info;
|
||||
|
||||
/**
|
||||
* 公共识别数据字段:各类型通用取数,写入 SD_AICOM_R.AI_VAL
|
||||
*/
|
||||
@Schema(description = "公共识别数据(各类型通用,写入AI_VAL)")
|
||||
private String value;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.yfd.platform.qgc_env.warn.entity.ao;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Schema(description = "AI视频流量数据")
|
||||
public class AiFlowAo {
|
||||
|
||||
@Schema(description = "流速")
|
||||
private BigDecimal v;
|
||||
|
||||
@Schema(description = "面积")
|
||||
private BigDecimal area;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package com.yfd.platform.qgc_env.warn.entity.ao;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 接收AI数据入参
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "接收AI数据入参")
|
||||
public class ReceiveAiDataAo {
|
||||
|
||||
@Schema(description = "设备编号")
|
||||
private String dvcd;
|
||||
|
||||
@Schema(description = "事件类型:0000=心跳 5001=漂浮物 5011=漂浮物清理 5021=视频流量 AI_RIV=河道识别 AI_FISHING=捕鱼识别")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "AI识别数据")
|
||||
private AiDataAo aidata;
|
||||
|
||||
@Schema(description = "文件id,多个逗号分隔")
|
||||
private String files;
|
||||
|
||||
@Schema(description = "AI识别发生时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date aitime;
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Boolean status;
|
||||
|
||||
@Schema(description = "消息")
|
||||
private String message;
|
||||
}
|
||||
@ -2,6 +2,7 @@ package com.yfd.platform.qgc_env.warn.service;
|
||||
|
||||
import com.yfd.platform.common.DataSourceRequest;
|
||||
import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.qgc_env.warn.entity.ao.ReceiveAiDataAo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.AlarmPointVo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.AiRecordVo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.AiProtectVo;
|
||||
@ -35,4 +36,11 @@ public interface WarnDataService {
|
||||
DataSourceResult<StcdWarnStateVo> getWarnStcdKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
DataSourceResult<AiFileVo> getAiFileKendoListCust(DataSourceRequest dataSourceRequest);
|
||||
|
||||
/**
|
||||
* 接收AI设备上抛的识别数据,合并写入 SD_AICOM_R / SD_AIHEARTBEAT_R
|
||||
*
|
||||
* @param aoList AI数据列表
|
||||
*/
|
||||
void receiveAiData(List<ReceiveAiDataAo> aoList);
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ import com.yfd.platform.common.DataSourceResult;
|
||||
import com.yfd.platform.common.GroupHelper;
|
||||
import com.yfd.platform.common.GroupingInfo;
|
||||
import com.yfd.platform.common.MicroservicDynamicSQLMapper;
|
||||
import com.yfd.platform.common.exception.BizException;
|
||||
import com.yfd.platform.qgc_env.warn.entity.ao.ReceiveAiDataAo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.AlarmPointVo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.AiComListVo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.AiDmRunVo;
|
||||
@ -22,9 +24,12 @@ import com.yfd.platform.qgc_env.warn.entity.vo.EngWarnCountVo;
|
||||
import com.yfd.platform.qgc_env.warn.entity.vo.StcdWarnStateVo;
|
||||
import com.yfd.platform.qgc_env.warn.service.WarnDataService;
|
||||
import com.yfd.platform.utils.QgcQueryWrapperUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@ -43,6 +48,9 @@ public class WarnDataServiceImpl implements WarnDataService {
|
||||
@Resource
|
||||
private MicroservicDynamicSQLMapper microservicDynamicSQLMapper;
|
||||
|
||||
@Resource
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public DataSourceResult<EngWarnCountVo> getEngWarnCount(DataSourceRequest dataSourceRequest) {
|
||||
DataSourceLoadOptionsBase loadOptions = dataSourceRequest == null ? null : dataSourceRequest.toDevRequest();
|
||||
@ -2586,4 +2594,123 @@ public class WarnDataServiceImpl implements WarnDataService {
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
// ==================== 接收AI数据(SD_AICOM_R / SD_AIHEARTBEAT_R) ====================
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void receiveAiData(List<ReceiveAiDataAo> aoList) {
|
||||
if (CollUtil.isEmpty(aoList)) {
|
||||
throw new BizException("数据不能为空");
|
||||
}
|
||||
List<Object[]> aicomRows = new ArrayList<>();
|
||||
List<Object[]> heartbeatRows = new ArrayList<>();
|
||||
for (ReceiveAiDataAo ao : aoList) {
|
||||
if (ao == null) {
|
||||
continue;
|
||||
}
|
||||
if (StrUtil.isBlank(ao.getDvcd())) {
|
||||
throw new BizException("站码不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(ao.getType())) {
|
||||
throw new BizException("AI数据类型不能为空");
|
||||
}
|
||||
if (ao.getAitime() == null) {
|
||||
throw new BizException("AI数据发生时间不能为空");
|
||||
}
|
||||
String stcd = ao.getDvcd().trim();
|
||||
String tm = DateUtil.formatDateTime(ao.getAitime());
|
||||
String remarkJson = JSONUtil.toJsonStr(ao.getAidata());
|
||||
switch (ao.getType()) {
|
||||
case "0000":
|
||||
// ai心跳数据
|
||||
heartbeatRows.add(new Object[]{stcd, tm, ao.getFiles()});
|
||||
break;
|
||||
case "5001":
|
||||
// 漂浮物识别
|
||||
if (ao.getAidata() == null || ao.getAidata().getArea() == null) {
|
||||
throw new BizException("漂浮物面积不能为空");
|
||||
}
|
||||
aicomRows.add(new Object[]{
|
||||
stcd, tm, "AI_5001",
|
||||
ao.getAidata().getArea().toPlainString(),
|
||||
ao.getFiles(), remarkJson
|
||||
});
|
||||
break;
|
||||
case "5011":
|
||||
// 漂浮物清理
|
||||
aicomRows.add(new Object[]{stcd, tm, "AI_5011", null, ao.getFiles(), remarkJson});
|
||||
break;
|
||||
case "5021":
|
||||
// 视频流量
|
||||
aicomRows.add(new Object[]{
|
||||
stcd, tm, "AI_5014",
|
||||
ao.getAidata() != null && ao.getAidata().getFlow() != null
|
||||
? ao.getAidata().getFlow().toPlainString() : null,
|
||||
ao.getFiles(), remarkJson
|
||||
});
|
||||
break;
|
||||
case "AI_RIV":
|
||||
case "AI_FISHING":
|
||||
// 新增类型:AI_VAL 取自 aidata 公共识别字段 value
|
||||
aicomRows.add(new Object[]{
|
||||
stcd, tm, ao.getType(),
|
||||
ao.getAidata() != null ? ao.getAidata().getValue() : null,
|
||||
ao.getFiles(), remarkJson
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new BizException("未知的AI数据类型");
|
||||
}
|
||||
}
|
||||
if (!aicomRows.isEmpty()) {
|
||||
mergeAiCom(aicomRows);
|
||||
}
|
||||
if (!heartbeatRows.isEmpty()) {
|
||||
mergeAiHeartbeat(heartbeatRows);
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeAiCom(List<Object[]> rows) {
|
||||
StringBuilder sql = new StringBuilder("MERGE INTO SD_AICOM_R target USING (");
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
if (i > 0) {
|
||||
sql.append(" UNION ALL ");
|
||||
}
|
||||
sql.append("SELECT ? AS STCD, TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS') AS TM, ")
|
||||
.append("? AS TYPE, ? AS AI_VAL, ? AS FID, ? AS REMARK FROM DUAL");
|
||||
}
|
||||
sql.append(") source ON (target.STCD = source.STCD AND target.TM = source.TM AND target.TYPE = source.TYPE) ")
|
||||
.append("WHEN NOT MATCHED THEN INSERT (STCD, TM, TYPE, AI_VAL, FID, REMARK, RECORD_TIME, IS_DELETED) ")
|
||||
.append("VALUES (source.STCD, source.TM, source.TYPE, source.AI_VAL, source.FID, source.REMARK, SYSDATE, 0) ")
|
||||
.append("WHEN MATCHED THEN UPDATE SET ")
|
||||
.append("target.AI_VAL = source.AI_VAL, ")
|
||||
.append("target.FID = source.FID, ")
|
||||
.append("target.REMARK = source.REMARK, ")
|
||||
.append("target.MODIFY_TIME = SYSDATE");
|
||||
List<Object> params = new ArrayList<>();
|
||||
for (Object[] row : rows) {
|
||||
params.addAll(Arrays.asList(row));
|
||||
}
|
||||
jdbcTemplate.update(sql.toString(), params.toArray());
|
||||
}
|
||||
|
||||
private void mergeAiHeartbeat(List<Object[]> rows) {
|
||||
StringBuilder sql = new StringBuilder("MERGE INTO SD_AIHEARTBEAT_R target USING (");
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
if (i > 0) {
|
||||
sql.append(" UNION ALL ");
|
||||
}
|
||||
sql.append("SELECT ? AS STCD, TO_DATE(?, 'YYYY-MM-DD HH24:MI:SS') AS TM, ? AS FID FROM DUAL");
|
||||
}
|
||||
sql.append(") source ON (target.STCD = source.STCD AND target.TM = source.TM) ")
|
||||
.append("WHEN NOT MATCHED THEN INSERT (STCD, TM, FID, RECORD_TIME, IS_DELETED) ")
|
||||
.append("VALUES (source.STCD, source.TM, source.FID, SYSDATE, 0) ")
|
||||
.append("WHEN MATCHED THEN UPDATE SET target.FID = source.FID, target.MODIFY_TIME = SYSDATE");
|
||||
List<Object> params = new ArrayList<>();
|
||||
for (Object[] row : rows) {
|
||||
params.addAll(Arrays.asList(row));
|
||||
}
|
||||
jdbcTemplate.update(sql.toString(), params.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,9 @@ public class WeVmsstbprptVo {
|
||||
@Schema(description = "主键")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "站类编码")
|
||||
private String sttp;
|
||||
|
||||
@Schema(description = "站类编码")
|
||||
private String sttpCode;
|
||||
|
||||
|
||||
@ -4232,6 +4232,7 @@ public class WeFishServiceImpl implements WeFishService {
|
||||
private String buildWeVmsstbprptViewSql() {
|
||||
return "SELECT " +
|
||||
"src.STCD AS id, " +
|
||||
"src.STTP AS sttp, " +
|
||||
"src.STTP_CODE AS sttpCode, " +
|
||||
"src.STLC AS stlc, " +
|
||||
"src.STCD AS stcd, " +
|
||||
@ -4370,6 +4371,7 @@ public class WeFishServiceImpl implements WeFishService {
|
||||
Map<String, String> columns = new LinkedHashMap<>();
|
||||
columns.put("id", "t.id AS id");
|
||||
columns.put("sttpCode", "t.sttpCode AS sttpCode");
|
||||
columns.put("sttp", "t.sttp AS sttp");
|
||||
columns.put("stcd", "t.stcd AS stcd");
|
||||
columns.put("stnm", "t.stnm AS stnm");
|
||||
columns.put("rstcd", "t.rstcd AS rstcd");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user