添加统计接口
决策,区域管理接口优化
This commit is contained in:
parent
f78920ea33
commit
9a1fe4a96a
8
pom.xml
8
pom.xml
@ -133,14 +133,6 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<!-- <resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/java</directory>
|
|
||||||
<includes>
|
|
||||||
<include>**/*.xml</include>
|
|
||||||
</includes>
|
|
||||||
</resource>
|
|
||||||
</resources>-->
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -25,6 +25,7 @@ import org.springframework.util.CollectionUtils;
|
|||||||
public class DeviceNameChangerManage {
|
public class DeviceNameChangerManage {
|
||||||
|
|
||||||
final static Table<Integer, DeviceType, List<NameChangerFilter>> CHANGER_TABLE = HashBasedTable.create();
|
final static Table<Integer, DeviceType, List<NameChangerFilter>> CHANGER_TABLE = HashBasedTable.create();
|
||||||
|
private final static Integer TMP_DEFAULT_LINEID = 3;
|
||||||
|
|
||||||
public static String findMatch(DeviceType deviceType, String occName) {
|
public static String findMatch(DeviceType deviceType, String occName) {
|
||||||
if (Objects.isNull(deviceType)) {
|
if (Objects.isNull(deviceType)) {
|
||||||
@ -35,7 +36,7 @@ public class DeviceNameChangerManage {
|
|||||||
log.debug("错误的设备名称 occName[{}]", occName);
|
log.debug("错误的设备名称 occName[{}]", occName);
|
||||||
return occName;
|
return occName;
|
||||||
}
|
}
|
||||||
List<NameChangerFilter> filters = CHANGER_TABLE.get(3, deviceType);
|
List<NameChangerFilter> filters = CHANGER_TABLE.get(TMP_DEFAULT_LINEID, deviceType);
|
||||||
if (CollectionUtils.isEmpty(filters)) {
|
if (CollectionUtils.isEmpty(filters)) {
|
||||||
log.debug("未找到对应的转换的occName:[{}] deviceType[{}]", occName, deviceType);
|
log.debug("未找到对应的转换的occName:[{}] deviceType[{}]", occName, deviceType);
|
||||||
return occName;
|
return occName;
|
||||||
@ -60,7 +61,7 @@ public class DeviceNameChangerManage {
|
|||||||
Map<DeviceType, List<NameChangerFilter>> filteMaper = filters.stream().collect(Collectors.groupingBy(NameChangerFilter::deviceType));
|
Map<DeviceType, List<NameChangerFilter>> filteMaper = filters.stream().collect(Collectors.groupingBy(NameChangerFilter::deviceType));
|
||||||
filteMaper.forEach((k, v) -> {
|
filteMaper.forEach((k, v) -> {
|
||||||
Collections.sort(v, Comparator.comparingInt(NameChangerFilter::filterIndex));
|
Collections.sort(v, Comparator.comparingInt(NameChangerFilter::filterIndex));
|
||||||
CHANGER_TABLE.put(3, k, v);
|
CHANGER_TABLE.put(TMP_DEFAULT_LINEID, k, v);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package club.joylink.xiannccda.controller;
|
package club.joylink.xiannccda.controller;
|
||||||
|
|
||||||
import club.joylink.xiannccda.alert.NccAlertInfo;
|
import club.joylink.xiannccda.alert.NccAlertInfo;
|
||||||
import club.joylink.xiannccda.dto.AlertRecordQueryDTO;
|
import club.joylink.xiannccda.dto.record.AlertRecordQueryDTO;
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportDTO;
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportResponseDTO;
|
||||||
import club.joylink.xiannccda.entity.AlertRecord;
|
import club.joylink.xiannccda.entity.AlertRecord;
|
||||||
import club.joylink.xiannccda.entity.AlertTip;
|
import club.joylink.xiannccda.entity.AlertTip;
|
||||||
import club.joylink.xiannccda.repository.IAlertRecordRepository;
|
import club.joylink.xiannccda.repository.IAlertRecordRepository;
|
||||||
@ -11,6 +13,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import java.util.List;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@ -68,4 +71,13 @@ public class AlertRecordController {
|
|||||||
public Page<NccAlertInfo> pageQueryAlertDetail(AlertRecordQueryDTO queryDTO) {
|
public Page<NccAlertInfo> pageQueryAlertDetail(AlertRecordQueryDTO queryDTO) {
|
||||||
return alertRecordService.pageQueryAlertDetail(queryDTO);
|
return alertRecordService.pageQueryAlertDetail(queryDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/report/{lineId}")
|
||||||
|
@SecurityRequirement(name = "jwt")
|
||||||
|
@Operation(summary = "报警统计")
|
||||||
|
@ApiResponse(description = "报警统计")
|
||||||
|
public List<AlertRecordReportResponseDTO> reportStatistics(@PathVariable("lineId") Integer lineId, AlertRecordReportDTO reportDTO) {
|
||||||
|
return this.alertRecordService.report(lineId, reportDTO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,9 +70,9 @@ public class DeviceAreaConfigController {
|
|||||||
|
|
||||||
@SecurityRequirement(name = "jwt")
|
@SecurityRequirement(name = "jwt")
|
||||||
@Operation(summary = "获取详情数据")
|
@Operation(summary = "获取详情数据")
|
||||||
@GetMapping("/page")
|
@GetMapping("/page/{lineId}")
|
||||||
public Page<DeviceAreaConfig> page(DeviceAreaConfigQueryDto queryDto) {
|
public Page<DeviceAreaConfig> page(@PathVariable("lineId") Integer lineId, DeviceAreaConfigQueryDto queryDto) {
|
||||||
return this.areaConfigService.page(queryDto);
|
return this.areaConfigService.page(queryDto, lineId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SecurityRequirement(name = "jwt")
|
@SecurityRequirement(name = "jwt")
|
||||||
|
@ -13,7 +13,9 @@ import lombok.Setter;
|
|||||||
@Setter
|
@Setter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class AlertTipQueryDTO extends PageDTO<AlertTip> {
|
public class AlertTipQueryDTO extends PageDTO<AlertTip> {
|
||||||
|
|
||||||
private AlertType alertType;
|
private AlertType alertType;
|
||||||
private AlertTipTimeType timeType;
|
private AlertTipTimeType timeType;
|
||||||
private AlertLocation locationType;
|
private AlertLocation locationType;
|
||||||
|
private Long areaConfigId;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package club.joylink.xiannccda.dto.config;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.alert.core.AlertDeviceType;
|
||||||
|
import club.joylink.xiannccda.entity.DeviceAreaConfig;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class DeviceAreaConfigPageDto {
|
||||||
|
|
||||||
|
public DeviceAreaConfigPageDto(DeviceAreaConfig pageDto, Map<Long, String> tipIdsMap) {
|
||||||
|
this.id = pageDto.getId();
|
||||||
|
this.lineId = pageDto.getLineId();
|
||||||
|
this.areaName = pageDto.getAreaName();
|
||||||
|
this.deviceType = pageDto.getDeviceType();
|
||||||
|
this.data = pageDto.getData();
|
||||||
|
this.alertTypes = pageDto.getAlertTypes();
|
||||||
|
this.alertTipIds = tipIdsMap.get(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Integer lineId;
|
||||||
|
|
||||||
|
private String areaName;
|
||||||
|
|
||||||
|
private AlertDeviceType deviceType;
|
||||||
|
|
||||||
|
private String data;
|
||||||
|
private String alertTypes;
|
||||||
|
@Schema(description = "已经绑定决策辅助信息对应的id 以,号隔开")
|
||||||
|
private String alertTipIds;
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package club.joylink.xiannccda.dto.config;
|
package club.joylink.xiannccda.dto.config;
|
||||||
|
|
||||||
import club.joylink.xiannccda.ats.message.line3.device.DeviceType;
|
import club.joylink.xiannccda.ats.message.line3.device.DeviceType;
|
||||||
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
import club.joylink.xiannccda.entity.DeviceAreaConfig;
|
import club.joylink.xiannccda.entity.DeviceAreaConfig;
|
||||||
import club.joylink.xiannccda.entity.DeviceGuardConfig;
|
import club.joylink.xiannccda.entity.DeviceGuardConfig;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
|
||||||
@ -10,9 +11,11 @@ import lombok.Data;
|
|||||||
@Data
|
@Data
|
||||||
public class DeviceAreaConfigQueryDto extends PageDTO<DeviceAreaConfig> {
|
public class DeviceAreaConfigQueryDto extends PageDTO<DeviceAreaConfig> {
|
||||||
|
|
||||||
@Schema(description = "线路id")
|
|
||||||
private Integer lineId;
|
|
||||||
|
|
||||||
@Schema(description = "设备类型")
|
@Schema(description = "设备类型")
|
||||||
private DeviceType deviceType;
|
private DeviceType deviceType;
|
||||||
|
|
||||||
|
private String areaName;
|
||||||
|
|
||||||
|
private AlertType alertType;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package club.joylink.xiannccda.dto;
|
package club.joylink.xiannccda.dto.record;
|
||||||
|
|
||||||
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
import club.joylink.xiannccda.entity.AlertRecord;
|
import club.joylink.xiannccda.entity.AlertRecord;
|
||||||
@ -7,6 +7,7 @@ import lombok.Data;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class AlertRecordQueryDTO extends PageDTO<AlertRecord> {
|
public class AlertRecordQueryDTO extends PageDTO<AlertRecord> {
|
||||||
|
|
||||||
private AlertType alertType;
|
private AlertType alertType;
|
||||||
|
|
||||||
private Integer lineId;
|
private Integer lineId;
|
@ -0,0 +1,15 @@
|
|||||||
|
package club.joylink.xiannccda.dto.record;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlertRecordReportDTO {
|
||||||
|
|
||||||
|
private List<AlertType> alertTypes;
|
||||||
|
private LocalDateTime beginDateTime;
|
||||||
|
private LocalDateTime endDateTime;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package club.joylink.xiannccda.dto.record;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AlertRecordReportResponseDTO {
|
||||||
|
|
||||||
|
private AlertType alertType;
|
||||||
|
private Integer counter;
|
||||||
|
}
|
@ -1,8 +1,13 @@
|
|||||||
package club.joylink.xiannccda.mapper;
|
package club.joylink.xiannccda.mapper;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportDTO;
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportResponseDTO;
|
||||||
import club.joylink.xiannccda.entity.AlertRecord;
|
import club.joylink.xiannccda.entity.AlertRecord;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import java.util.List;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@ -13,6 +18,8 @@ import org.apache.ibatis.annotations.Mapper;
|
|||||||
* @since 2023-07-25
|
* @since 2023-07-25
|
||||||
*/
|
*/
|
||||||
@Mapper
|
@Mapper
|
||||||
|
@Repository
|
||||||
public interface AlertRecordMapper extends BaseMapper<AlertRecord> {
|
public interface AlertRecordMapper extends BaseMapper<AlertRecord> {
|
||||||
|
|
||||||
|
List<AlertRecordReportResponseDTO> report(AlertRecordReportDTO dto, @Param("lineId") Integer lineId);
|
||||||
}
|
}
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
|
||||||
<mapper namespace="club.joylink.xiannccda.mapper.AlertRecordMapper">
|
|
||||||
|
|
||||||
<!-- 通用查询映射结果 -->
|
|
||||||
<resultMap id="BaseResultMap" type="club.joylink.xiannccda.entity.AlertRecord">
|
|
||||||
<id column="id" property="id" />
|
|
||||||
<result column="alert_type" property="alertType" />
|
|
||||||
<result column="line_id" property="lineId" />
|
|
||||||
<result column="alert_object" property="alertObject" />
|
|
||||||
<result column="alert_time" property="alertTime" />
|
|
||||||
<result column="alert_location" property="alertLocation" />
|
|
||||||
</resultMap>
|
|
||||||
|
|
||||||
<!-- 通用查询结果列 -->
|
|
||||||
<sql id="Base_Column_List">
|
|
||||||
id, alert_type, line_id, alert_object, alert_time, alert_location
|
|
||||||
</sql>
|
|
||||||
|
|
||||||
</mapper>
|
|
@ -1,6 +1,6 @@
|
|||||||
package club.joylink.xiannccda.repository;
|
package club.joylink.xiannccda.repository;
|
||||||
|
|
||||||
import club.joylink.xiannccda.dto.AlertRecordQueryDTO;
|
import club.joylink.xiannccda.dto.record.AlertRecordQueryDTO;
|
||||||
import club.joylink.xiannccda.entity.AlertRecord;
|
import club.joylink.xiannccda.entity.AlertRecord;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
@ -14,5 +14,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
* @since 2023-07-25
|
* @since 2023-07-25
|
||||||
*/
|
*/
|
||||||
public interface IAlertRecordRepository extends IService<AlertRecord> {
|
public interface IAlertRecordRepository extends IService<AlertRecord> {
|
||||||
|
|
||||||
Page<AlertRecord> page(AlertRecordQueryDTO queryDTO);
|
Page<AlertRecord> page(AlertRecordQueryDTO queryDTO);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import club.joylink.xiannccda.dto.alertTip.AlertTipQueryDTO;
|
|||||||
import club.joylink.xiannccda.entity.AlertTip;
|
import club.joylink.xiannccda.entity.AlertTip;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@ -16,4 +18,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||||||
public interface IAlertTipRepository extends IService<AlertTip> {
|
public interface IAlertTipRepository extends IService<AlertTip> {
|
||||||
|
|
||||||
Page<AlertTip> page(AlertTipQueryDTO queryDTO);
|
Page<AlertTip> page(AlertTipQueryDTO queryDTO);
|
||||||
|
|
||||||
|
Map<Long, String> findBindAreaConfigId(List<Long> areaConfigList);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package club.joylink.xiannccda.repository.impl;
|
package club.joylink.xiannccda.repository.impl;
|
||||||
|
|
||||||
import club.joylink.xiannccda.dto.AlertRecordQueryDTO;
|
import club.joylink.xiannccda.dto.record.AlertRecordQueryDTO;
|
||||||
import club.joylink.xiannccda.entity.AlertRecord;
|
import club.joylink.xiannccda.entity.AlertRecord;
|
||||||
import club.joylink.xiannccda.mapper.AlertRecordMapper;
|
import club.joylink.xiannccda.mapper.AlertRecordMapper;
|
||||||
import club.joylink.xiannccda.repository.IAlertRecordRepository;
|
import club.joylink.xiannccda.repository.IAlertRecordRepository;
|
||||||
|
@ -10,7 +10,11 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,10 +37,29 @@ public class AlertTipRepository extends ServiceImpl<AlertTipMapper, AlertTip> im
|
|||||||
if (queryDTO.getTimeType() != null) {
|
if (queryDTO.getTimeType() != null) {
|
||||||
queryWrapper.eq(AlertTip::getTimeType, queryDTO.getTimeType().name());
|
queryWrapper.eq(AlertTip::getTimeType, queryDTO.getTimeType().name());
|
||||||
}
|
}
|
||||||
|
queryWrapper.eq(queryDTO.getAreaConfigId() != null, AlertTip::getAreaConfigId, queryDTO.getAreaConfigId());
|
||||||
|
|
||||||
/* if (queryDTO.getLocationType() != null) {
|
/* if (queryDTO.getLocationType() != null) {
|
||||||
queryWrapper.eq(AlertTip::getLocationType, queryDTO.getLocationType().name());
|
queryWrapper.eq(AlertTip::getLocationType, queryDTO.getLocationType().name());
|
||||||
}*/
|
}*/
|
||||||
queryWrapper.notIn(AlertTip::getAlertType, List.of(AlertType.SWITCH_LOST.name()));
|
queryWrapper.notIn(AlertTip::getAlertType, List.of(AlertType.SWITCH_LOST.name()));
|
||||||
return page(queryDTO, queryWrapper);
|
return page(queryDTO, queryWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, String> findBindAreaConfigId(List<Long> areaConfigList) {
|
||||||
|
LambdaQueryWrapper<AlertTip> queryWrapper = Wrappers.lambdaQuery(AlertTip.class);
|
||||||
|
queryWrapper.select(List.of(AlertTip::getId, AlertTip::getAreaConfigId));
|
||||||
|
queryWrapper.in(AlertTip::getAreaConfigId, areaConfigList);
|
||||||
|
|
||||||
|
List<AlertTip> tipList = this.list(queryWrapper);
|
||||||
|
Map<Long, List<AlertTip>> tipListMap = tipList.stream().collect(Collectors.groupingBy(AlertTip::getAreaConfigId));
|
||||||
|
Map<Long, String> areaConfigIdTipIdsMap = Maps.newHashMap();
|
||||||
|
tipListMap.forEach((k, v) -> {
|
||||||
|
String tipIds = v.stream().map(d -> d.getId().toString()).collect(Collectors.joining(","));
|
||||||
|
areaConfigIdTipIdsMap.put(k, tipIds);
|
||||||
|
});
|
||||||
|
return areaConfigIdTipIdsMap;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,35 @@
|
|||||||
package club.joylink.xiannccda.service;
|
package club.joylink.xiannccda.service;
|
||||||
|
|
||||||
import club.joylink.xiannccda.alert.NccAlertInfo;
|
import club.joylink.xiannccda.alert.NccAlertInfo;
|
||||||
import club.joylink.xiannccda.dto.AlertRecordQueryDTO;
|
import club.joylink.xiannccda.dto.record.AlertRecordQueryDTO;
|
||||||
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
import club.joylink.xiannccda.dto.protos.LayoutGraphicsProto.Station;
|
import club.joylink.xiannccda.dto.record.AlertRecordReportDTO;
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportResponseDTO;
|
||||||
import club.joylink.xiannccda.entity.AlertRecord;
|
import club.joylink.xiannccda.entity.AlertRecord;
|
||||||
import club.joylink.xiannccda.entity.AlertTip;
|
import club.joylink.xiannccda.entity.AlertTip;
|
||||||
import club.joylink.xiannccda.exception.BusinessExceptionAssertEnum;
|
import club.joylink.xiannccda.exception.BusinessExceptionAssertEnum;
|
||||||
import club.joylink.xiannccda.repository.IAlertRecordRepository;
|
import club.joylink.xiannccda.repository.IAlertRecordRepository;
|
||||||
|
import club.joylink.xiannccda.repository.impl.AlertRecordRepository;
|
||||||
import club.joylink.xiannccda.repository.impl.AlertTipRepository;
|
import club.joylink.xiannccda.repository.impl.AlertTipRepository;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AlertRecordService {
|
public class AlertRecordService {
|
||||||
|
|
||||||
private final IAlertRecordRepository alertRecordRepository;
|
private final AlertRecordRepository alertRecordRepository;
|
||||||
private final AlertTipService alertTipService;
|
|
||||||
|
|
||||||
private final AlertTipRepository alertTipRepository;
|
private final AlertTipRepository alertTipRepository;
|
||||||
|
|
||||||
public AlertRecordService(IAlertRecordRepository alertRecordRepository, AlertTipService alertTipService, AlertTipRepository alertTipRepository) {
|
public AlertRecordService(AlertRecordRepository alertRecordRepository, AlertTipRepository alertTipRepository) {
|
||||||
this.alertRecordRepository = alertRecordRepository;
|
this.alertRecordRepository = alertRecordRepository;
|
||||||
this.alertTipService = alertTipService;
|
|
||||||
this.alertTipRepository = alertTipRepository;
|
this.alertTipRepository = alertTipRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,9 +55,6 @@ public class AlertRecordService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<NccAlertInfo> changeData(List<AlertRecord> ars) {
|
private List<NccAlertInfo> changeData(List<AlertRecord> ars) {
|
||||||
// List<Long> ids = ars.stream().map(AlertRecord::getAlertTipId).filter(Objects::nonNull).distinct().toList();
|
|
||||||
// List<AlertTip> ats = alertTipRepository.listByIds(ids);
|
|
||||||
// Map<Integer, AlertTip> tipMap = ats.stream().collect(Collectors.toMap(AlertTip::getId, Function.identity()));
|
|
||||||
List<NccAlertInfo> alertInfos = Lists.newArrayList();
|
List<NccAlertInfo> alertInfos = Lists.newArrayList();
|
||||||
for (AlertRecord record : ars) {
|
for (AlertRecord record : ars) {
|
||||||
NccAlertInfo nccAlertInfo = new NccAlertInfo(record.getAlertTime(),
|
NccAlertInfo nccAlertInfo = new NccAlertInfo(record.getAlertTime(),
|
||||||
@ -82,4 +76,12 @@ public class AlertRecordService {
|
|||||||
nccPage.setRecords(collect);
|
nccPage.setRecords(collect);
|
||||||
return nccPage;
|
return nccPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<AlertRecordReportResponseDTO> report(Integer lineId, AlertRecordReportDTO reportDTO) {
|
||||||
|
if (Objects.nonNull(reportDTO.getBeginDateTime()) && Objects.nonNull(reportDTO.getEndDateTime())) {
|
||||||
|
BusinessExceptionAssertEnum.ARGUMENT_ILLEGAL.assertTrue(reportDTO.getEndDateTime().isAfter(reportDTO.getBeginDateTime()), "开始时间不能大于结束时间");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.alertRecordRepository.getBaseMapper().report(reportDTO, lineId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,14 @@ package club.joylink.xiannccda.service.config;
|
|||||||
|
|
||||||
import club.joylink.xiannccda.alert.core.AlertDeviceType;
|
import club.joylink.xiannccda.alert.core.AlertDeviceType;
|
||||||
import club.joylink.xiannccda.ats.message.line3.device.DeviceType;
|
import club.joylink.xiannccda.ats.message.line3.device.DeviceType;
|
||||||
|
import club.joylink.xiannccda.dto.alertTip.AlertTipInfoDto;
|
||||||
import club.joylink.xiannccda.dto.config.DeviceAreaConfigDto;
|
import club.joylink.xiannccda.dto.config.DeviceAreaConfigDto;
|
||||||
|
import club.joylink.xiannccda.dto.config.DeviceAreaConfigPageDto;
|
||||||
import club.joylink.xiannccda.dto.config.DeviceAreaConfigQueryDto;
|
import club.joylink.xiannccda.dto.config.DeviceAreaConfigQueryDto;
|
||||||
import club.joylink.xiannccda.dto.protos.GuardConfigProto.GuardConfig;
|
import club.joylink.xiannccda.dto.protos.GuardConfigProto.GuardConfig;
|
||||||
import club.joylink.xiannccda.entity.DeviceAreaConfig;
|
import club.joylink.xiannccda.entity.DeviceAreaConfig;
|
||||||
import club.joylink.xiannccda.exception.BusinessExceptionAssertEnum;
|
import club.joylink.xiannccda.exception.BusinessExceptionAssertEnum;
|
||||||
|
import club.joylink.xiannccda.repository.IAlertTipRepository;
|
||||||
import club.joylink.xiannccda.repository.impl.DeviceAreaConfigRepository;
|
import club.joylink.xiannccda.repository.impl.DeviceAreaConfigRepository;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
@ -37,6 +40,9 @@ public class DeviceAreaConfigService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceAreaConfigRepository deviceAreaConfigRepository;
|
private DeviceAreaConfigRepository deviceAreaConfigRepository;
|
||||||
|
@Autowired
|
||||||
|
private IAlertTipRepository iAlertTipRepository;
|
||||||
|
|
||||||
private final static Cache<Integer, Map<AlertDeviceType, List<DeviceAreaConfig>>> AREA_CONFIG_CACHE = CacheBuilder.newBuilder().expireAfterWrite(5 * 60, TimeUnit.SECONDS).build();
|
private final static Cache<Integer, Map<AlertDeviceType, List<DeviceAreaConfig>>> AREA_CONFIG_CACHE = CacheBuilder.newBuilder().expireAfterWrite(5 * 60, TimeUnit.SECONDS).build();
|
||||||
|
|
||||||
|
|
||||||
@ -109,17 +115,32 @@ public class DeviceAreaConfigService {
|
|||||||
return this.convertDto(areaConfig);
|
return this.convertDto(areaConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<DeviceAreaConfig> page(DeviceAreaConfigQueryDto queryDTO) {
|
public Page<DeviceAreaConfigPageDto> page(DeviceAreaConfigQueryDto queryDTO, Integer lineId) {
|
||||||
LambdaQueryWrapper<DeviceAreaConfig> queryWrapper = Wrappers.lambdaQuery(DeviceAreaConfig.class);
|
LambdaQueryWrapper<DeviceAreaConfig> queryWrapper = Wrappers.lambdaQuery(DeviceAreaConfig.class);
|
||||||
queryWrapper.select(List.of(DeviceAreaConfig::getId, DeviceAreaConfig::getAreaName, DeviceAreaConfig::getLineId, DeviceAreaConfig::getDeviceType));
|
queryWrapper.select(List.of(DeviceAreaConfig::getId, DeviceAreaConfig::getAreaName, DeviceAreaConfig::getLineId, DeviceAreaConfig::getDeviceType));
|
||||||
if (Objects.nonNull(queryDTO.getLineId())) {
|
queryWrapper.eq(DeviceAreaConfig::getLineId, lineId);
|
||||||
|
queryWrapper.like(StringUtils.isNotEmpty(queryDTO.getAreaName()), DeviceAreaConfig::getAreaName, queryDTO.getAreaName());
|
||||||
queryWrapper.eq(DeviceAreaConfig::getLineId, queryDTO.getLineId());
|
|
||||||
}
|
|
||||||
if (Objects.nonNull(queryDTO.getDeviceType())) {
|
if (Objects.nonNull(queryDTO.getDeviceType())) {
|
||||||
queryWrapper.eq(DeviceAreaConfig::getDeviceType, queryDTO.getDeviceType().name());
|
queryWrapper.eq(DeviceAreaConfig::getDeviceType, queryDTO.getDeviceType().name());
|
||||||
}
|
}
|
||||||
return deviceAreaConfigRepository.page(queryDTO, queryWrapper);
|
if (Objects.nonNull(queryDTO.getAlertType())) {
|
||||||
|
queryWrapper.last(String.format(" and find_in_set('%s',%s) > 0", queryDTO.getAlertType().name(), DeviceAreaConfig.ALERT_TYPES));
|
||||||
|
}
|
||||||
|
|
||||||
|
Page<DeviceAreaConfig> pageConfig = deviceAreaConfigRepository.page(queryDTO, queryWrapper);
|
||||||
|
return this.convertPage(pageConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Page<DeviceAreaConfigPageDto> convertPage(Page<DeviceAreaConfig> pageConfig) {
|
||||||
|
List<Long> areaConfigIds = pageConfig.getRecords().stream().map(DeviceAreaConfig::getId).toList();
|
||||||
|
List<DeviceAreaConfigPageDto> pageList = Lists.newArrayListWithCapacity(pageConfig.getRecords().size());
|
||||||
|
Map<Long, String> areaIdMapTipIds = iAlertTipRepository.findBindAreaConfigId(areaConfigIds);
|
||||||
|
for (DeviceAreaConfig ac : pageConfig.getRecords()) {
|
||||||
|
pageList.add(new DeviceAreaConfigPageDto(ac, areaIdMapTipIds));
|
||||||
|
}
|
||||||
|
Page<DeviceAreaConfigPageDto> dtoPage = Page.of(pageConfig.getCurrent(), pageConfig.getSize(), pageConfig.getTotal());
|
||||||
|
dtoPage.setRecords(pageList);
|
||||||
|
return dtoPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AreaFinder> findAlertType(Integer lineId, String alertType) {
|
public List<AreaFinder> findAlertType(Integer lineId, String alertType) {
|
||||||
|
26
src/main/resources/mybatis/mapper/AlertRecordMapper.xml
Normal file
26
src/main/resources/mybatis/mapper/AlertRecordMapper.xml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="club.joylink.xiannccda.mapper.AlertRecordMapper">
|
||||||
|
|
||||||
|
<select id="report" parameterType="club.joylink.xiannccda.dto.record.AlertRecordReportDTO" resultType="club.joylink.xiannccda.dto.record.AlertRecordReportResponseDTO">
|
||||||
|
select alert_type, count(1) as counter
|
||||||
|
from alert_record
|
||||||
|
|
||||||
|
where line_id = #{lineId}
|
||||||
|
<if test="alertTypes != null and alertTypes.size() > 0">
|
||||||
|
<foreach collection="alertTypes" open=" and alert_type in (" separator="," close=")" item="t">
|
||||||
|
#{t}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
<choose>
|
||||||
|
<when test="beginDateTime != null">
|
||||||
|
and alert_time <![CDATA[>=]]> #{beginDateTime}
|
||||||
|
</when>
|
||||||
|
<when test="endDateTime != null">
|
||||||
|
and alert_time <![CDATA[<=]]> #{endDateTime}
|
||||||
|
</when>
|
||||||
|
</choose>
|
||||||
|
GROUP BY alert_type
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</mapper>
|
65
src/test/java/club/joylink/xiannccda/GenerateVoiceUtil.java
Normal file
65
src/test/java/club/joylink/xiannccda/GenerateVoiceUtil.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package club.joylink.xiannccda;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.service.BaiduVoiceService;
|
||||||
|
import club.joylink.xiannccda.vo.BaseVoiceSynthesisVO;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
||||||
|
public class GenerateVoiceUtil {
|
||||||
|
|
||||||
|
public byte[] synthesisSource(BaseVoiceSynthesisVO vo) {
|
||||||
|
BaiduVoiceService voiceService = new BaiduVoiceService();
|
||||||
|
byte[] data = voiceService.voiceSynthesis(vo);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void voiceService() {
|
||||||
|
BaseVoiceSynthesisVO svo = new BaseVoiceSynthesisVO("请注意,三号线,出现红光带");
|
||||||
|
byte[] data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\red.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,出现橙光带");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\orange.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,出现大面积红光带");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\red-most.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,出现大面积橙光带");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\orange-most.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,道岔失表了");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\switch-lost.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,出现大面积道岔失表");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\switch-lost-most.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,站台屏蔽门无法打开");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\cannot-open.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,站台屏蔽门无法关闭");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\cannot-close.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,出现蓝显");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\blue.mp3", data);
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,出现全线");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\all-line-blue.mp3", data);
|
||||||
|
|
||||||
|
svo = new BaseVoiceSynthesisVO("请注意,三号线,列车禁制ATP切除");
|
||||||
|
data = this.synthesisSource(svo);
|
||||||
|
writeFile("d:\\voice\\atp-cut.mp3", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void writeFile(String path, byte[] data) {
|
||||||
|
try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(path))) {
|
||||||
|
outputStream.write(data);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package club.joylink.xiannccda.service;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportDTO;
|
||||||
|
import club.joylink.xiannccda.dto.record.AlertRecordReportResponseDTO;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONWriter.Feature;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
public class AlertRecordServiceTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AlertRecordService alertRecordService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportEmpty() {
|
||||||
|
AlertRecordReportDTO dto = new AlertRecordReportDTO();
|
||||||
|
List<AlertRecordReportResponseDTO> list = this.alertRecordService.report(3, dto);
|
||||||
|
System.out.println(JSON.toJSONString(list, Feature.PrettyFormat, Feature.WriteEnumsUsingName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportType() {
|
||||||
|
AlertRecordReportDTO dto = new AlertRecordReportDTO();
|
||||||
|
dto.setAlertTypes(List.of(AlertType.AXLE_LED_RED));
|
||||||
|
List<AlertRecordReportResponseDTO> list = this.alertRecordService.report(3, dto);
|
||||||
|
System.out.println(JSON.toJSONString(list, Feature.PrettyFormat, Feature.WriteEnumsUsingName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportDate() {
|
||||||
|
AlertRecordReportDTO dto = new AlertRecordReportDTO();
|
||||||
|
// dto.setAlertTypes(List.of(AlertType.AXLE_LED_RED));
|
||||||
|
dto.setBeginDateTime(LocalDateTime.parse("2023-09-05 13:21:46", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||||
|
dto.setEndDateTime(LocalDateTime.now());
|
||||||
|
List<AlertRecordReportResponseDTO> list = this.alertRecordService.report(3, dto);
|
||||||
|
System.out.println(JSON.toJSONString(list, Feature.PrettyFormat, Feature.WriteEnumsUsingName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void reportErrorDate() {
|
||||||
|
LocalDateTime begin = LocalDateTime.parse("2023-09-05 13:21:46", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
System.out.println(begin.isBefore(now));
|
||||||
|
System.out.println(now.isBefore(begin));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
package club.joylink.xiannccda.service;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.util.ConnUtil;
|
||||||
|
import club.joylink.xiannccda.util.TokenHolder;
|
||||||
|
import club.joylink.xiannccda.vo.BaseVoiceSynthesisVO;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 百度语音识别合成服务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
|
||||||
|
public class BaiduVoiceService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码 用户输入/服务端 含义 一般解决方法 3300 用户输入错误 输入参数不正确 请参考技术文档及demo,核对输入参数 3301 用户输入错误 音频质量过差或没有清晰语音 请上传包含语音的清晰音频 3302 用户输入错误 鉴权失败 token字段校验失败。请使用正确的API_KEY 和
|
||||||
|
* SECRET_KEY生成。或并发、调用量超出限额。或音频采样率不正确(可尝试更换为16k采样率)。 3303 服务端问题 百度服务器后端繁忙 有可能是原始音频质量过差。可以将api返回结果和原始音频反馈至工单、论坛或者QQ群 3304 用户请求超限 用户的请求并发超限 请降低识别api请求频率(账号内所有应用APPID共用并发限额)
|
||||||
|
* 3305 用户请求超限 用户的日调用量(日请求量)超限 请开通付费,购买调用量资源(账号内所有应用APPID共用调用量限额) 3307 服务端问题 语音服务器后端识别出错问题 有可能是原始音频质量过差。可以将api返回结果和原始音频反馈至论坛或者QQ群 3308 用户输入错误 音频过长 音频时长不超过60s或音频base64后超过2MB,请将音频时长截取为更短的音频
|
||||||
|
* 3309 用户输入错误 音频数据问题 服务端无法将音频转为pcm格式,可能是长度问题,音频格式问题等。 请将输入的音频时长截取为60s以下,并核对下音频的编码,采样率16000,单声道,小端序,16bits 3310 用户输入错误 输入的音频文件过大 语音文件共有3种输入方式: json 里的speech 参数(base64后); 直接post 二进制数据;callback参数里url。
|
||||||
|
* 分别对应三种情况:json超过10M;直接post的语音文件超过10M;callback里回调url的音频文件超过10M 3311 用户输入错误 采样率rate参数不在选项里 目前rate参数仅支持16000,填写其他值即会有此错误。 3312 用户输入错误 音频格式format参数不在选项里 目前格式仅仅支持pcm、wav、amr、m4a,如填写mp3即会有此错误
|
||||||
|
* 3313 服务端问题 语音服务器解析超时 请将api返回结果反馈至工单、论坛或者QQ群 3314 用户输入错误 音频长度过短 音频长度的len参数不能小于等于4 3315 服务端问题 语音服务器处理超时 请将api返回结果反馈至工单、论坛或者QQ群 3316 用户输入错误 音频转为pcm失败 使用pcm格式,或者确认wav和amr的采样率16000,单声道。
|
||||||
|
* wav文件需要是pcm编码,小端序,16bits
|
||||||
|
*
|
||||||
|
* @param errCode
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String handleErrMsg(Integer errCode) {
|
||||||
|
String errMsg = "未知错误";
|
||||||
|
switch (errCode) {
|
||||||
|
case 3300:
|
||||||
|
case 3302:
|
||||||
|
case 3311:
|
||||||
|
case 3312:
|
||||||
|
case 3313:
|
||||||
|
case 3315:
|
||||||
|
errMsg = "参数错误或语音服务异常";
|
||||||
|
break;
|
||||||
|
case 3301:
|
||||||
|
case 3303:
|
||||||
|
case 3307:
|
||||||
|
errMsg = "音频质量过差或没有清晰语音或识别异常";
|
||||||
|
break;
|
||||||
|
case 3304:
|
||||||
|
log.error("百度语音识别请求并发超限");
|
||||||
|
errMsg = "参数错误或语音服务异常";
|
||||||
|
break;
|
||||||
|
case 3308:
|
||||||
|
case 3310:
|
||||||
|
case 3314:
|
||||||
|
errMsg = "音频时长过长或过短";
|
||||||
|
break;
|
||||||
|
case 3309:
|
||||||
|
case 3316:
|
||||||
|
errMsg = "音频格式错误";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return errMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spd 选填 语速,取值0-15,默认为5中语速 pit 选填 音调,取值0-15,默认为5中语调 vol 选填 音量,取值0-15,默认为5中音量(取值为0时为音量最小值,并非为无声) per(基础音库) 选填 度小宇=1,度小美=0,度逍遥(基础)=3,度丫丫=4
|
||||||
|
* per(精品音库) 选填 度逍遥(精品)=5003,度小鹿=5118,度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5 aue 选填 3为mp3格式(默认); 4为pcm-16k;5为pcm-8k;6为wav(内容同pcm-16k); 注意aue=4或者6是语音识别要求的格式,但是音频内容不是语音识别要求的自然人发音,所以识别效果会受影响。
|
||||||
|
*/
|
||||||
|
|
||||||
|
// private String aue = "6";
|
||||||
|
private Map<String, Object> toMapParam(BaseVoiceSynthesisVO vo) {
|
||||||
|
Map<String, Object> dataMap = Maps.newHashMap();
|
||||||
|
vo.checkBaiduParam();
|
||||||
|
dataMap.put("spd", vo.getSpd());
|
||||||
|
dataMap.put("pit", vo.getPit());
|
||||||
|
dataMap.put("vol", vo.getVol());
|
||||||
|
dataMap.put("pre", vo.getPer());
|
||||||
|
dataMap.put("aue", "3");
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] voiceSynthesis(BaseVoiceSynthesisVO vo) {
|
||||||
|
try {
|
||||||
|
byte[] data = this.run(vo, TokenHolder.getInstance().getToken());
|
||||||
|
return data;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static String TEXT_VOICE_URL = "http://tsn.baidu.com/text2audio"; // 可以使用https
|
||||||
|
|
||||||
|
private byte[] run(BaseVoiceSynthesisVO vo, String token) throws IOException {
|
||||||
|
StringBuilder sb = new StringBuilder("tex=");
|
||||||
|
// 此处2次urlencode, 确保特殊字符被正确编码
|
||||||
|
sb.append(ConnUtil.urlEncode(ConnUtil.urlEncode(vo.getMessage())));
|
||||||
|
Map<String, Object> dataMap = toMapParam(vo);
|
||||||
|
dataMap.forEach((k, v) -> {
|
||||||
|
sb.append("&").append(k).append("=").append(v);
|
||||||
|
});
|
||||||
|
sb.append("&cuid=").append(TokenHolder.APP_ID);
|
||||||
|
sb.append("&tok=").append(token);
|
||||||
|
sb.append("&lan=zh&ctp=1");
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) new URL(TEXT_VOICE_URL).openConnection();
|
||||||
|
conn.setDoInput(true);
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
conn.setConnectTimeout(9000);
|
||||||
|
PrintWriter printWriter = new PrintWriter(conn.getOutputStream());
|
||||||
|
printWriter.write(sb.toString());
|
||||||
|
printWriter.close();
|
||||||
|
String contentType = conn.getContentType();
|
||||||
|
if (contentType.contains("audio/")) {
|
||||||
|
return ConnUtil.getResponseBytes(conn);
|
||||||
|
} else {
|
||||||
|
String res = ConnUtil.getResponseString(conn);
|
||||||
|
throw new RuntimeException(String.format("百度语音合成失败:%s", res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package club.joylink.xiannccda.service;
|
||||||
|
|
||||||
|
import club.joylink.xiannccda.dto.config.DeviceAreaConfigQueryDto;
|
||||||
|
import club.joylink.xiannccda.dto.protos.AlertConstProto.AlertType;
|
||||||
|
import club.joylink.xiannccda.service.config.DeviceAreaConfigService;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
public class DeviceAreaConfigServiceTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DeviceAreaConfigService areaConfigService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void page() {
|
||||||
|
DeviceAreaConfigQueryDto dto = new DeviceAreaConfigQueryDto();
|
||||||
|
dto.setAlertType(AlertType.BLUE_DISPLAY);
|
||||||
|
// dto.setLineId(3);
|
||||||
|
this.areaConfigService.page(dto, 3);
|
||||||
|
}
|
||||||
|
}
|
94
src/test/java/club/joylink/xiannccda/util/ConnUtil.java
Normal file
94
src/test/java/club/joylink/xiannccda/util/ConnUtil.java
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package club.joylink.xiannccda.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与连接相关的Util类
|
||||||
|
*/
|
||||||
|
public class ConnUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UrlEncode, UTF-8 编码
|
||||||
|
*
|
||||||
|
* @param str 原始字符串
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String urlEncode(String str) {
|
||||||
|
String result = null;
|
||||||
|
try {
|
||||||
|
result = URLEncoder.encode(str, "UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从HttpURLConnection 获取返回的字符串
|
||||||
|
*
|
||||||
|
* @param conn
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static String getResponseString(HttpURLConnection conn) throws IOException {
|
||||||
|
return new String(getResponseBytes(conn));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从HttpURLConnection 获取返回的bytes 注意 HttpURLConnection自身问题, 400类错误,会直接抛出异常。不能获取conn.getInputStream();
|
||||||
|
*
|
||||||
|
* @param conn
|
||||||
|
* @return
|
||||||
|
* @throws IOException http请求错误
|
||||||
|
*/
|
||||||
|
public static byte[] getResponseBytes(HttpURLConnection conn) throws IOException {
|
||||||
|
int responseCode = conn.getResponseCode();
|
||||||
|
InputStream inputStream = conn.getInputStream();
|
||||||
|
if (responseCode != 200) {
|
||||||
|
System.err.println("http 请求返回的状态码错误,期望200, 当前是 " + responseCode);
|
||||||
|
if (responseCode == 401) {
|
||||||
|
System.err.println("可能是appkey appSecret 填错");
|
||||||
|
}
|
||||||
|
System.err.println("response headers" + conn.getHeaderFields());
|
||||||
|
if (inputStream == null) {
|
||||||
|
inputStream = conn.getErrorStream();
|
||||||
|
}
|
||||||
|
byte[] result = getInputStreamContent(inputStream);
|
||||||
|
System.err.println(new String(result));
|
||||||
|
|
||||||
|
throw new RuntimeException("接口调用异常:" + responseCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] result = getInputStreamContent(inputStream);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将InputStream内的内容全部读取,作为bytes返回
|
||||||
|
*
|
||||||
|
* @param is
|
||||||
|
* @return
|
||||||
|
* @throws IOException @see InputStream.read()
|
||||||
|
*/
|
||||||
|
public static byte[] getInputStreamContent(InputStream is) throws IOException {
|
||||||
|
byte[] b = new byte[1024];
|
||||||
|
// 定义一个输出流存储接收到的数据
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
// 开始接收数据
|
||||||
|
int len = 0;
|
||||||
|
while (true) {
|
||||||
|
len = is.read(b);
|
||||||
|
if (len == -1) {
|
||||||
|
// 数据读完
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
byteArrayOutputStream.write(b, 0, len);
|
||||||
|
}
|
||||||
|
return byteArrayOutputStream.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
144
src/test/java/club/joylink/xiannccda/util/TokenHolder.java
Normal file
144
src/test/java/club/joylink/xiannccda/util/TokenHolder.java
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
package club.joylink.xiannccda.util;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token的获取类 将apiKey和secretKey换取token,注意有效期保存在expiresAt
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class TokenHolder {
|
||||||
|
|
||||||
|
public static final String APP_ID = "17048486";
|
||||||
|
static final String API_KEY = "owDE3FR55ZXpZzAATbBlwKZZ";
|
||||||
|
static final String SECRET_KEY = "oFjGfwXFkIGCrK8OntwfuxgzNK4k0oNH";
|
||||||
|
private static final String SCOPE = "brain_enhanced_asr";
|
||||||
|
static final TokenHolder holder = new TokenHolder(API_KEY, SECRET_KEY, SCOPE);
|
||||||
|
|
||||||
|
public static final String TTS_SCOPE = "audio_tts_post";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* url , Token的url,http可以改为https
|
||||||
|
*/
|
||||||
|
private static final String url = "http://openapi.baidu.com/oauth/2.0/token";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* asr的权限 scope 是 "audio_voice_assistant_get" tts 的权限 scope 是 "audio_tts_post"
|
||||||
|
*/
|
||||||
|
private String scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网页上申请语音识别应用获取的apiKey
|
||||||
|
*/
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网页上申请语音识别应用获取的secretKey
|
||||||
|
*/
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存访问接口获取的token
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前的时间戳,毫秒
|
||||||
|
*/
|
||||||
|
private long expiresAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param apiKey 网页上申请语音识别应用获取的apiKey
|
||||||
|
* @param secretKey 网页上申请语音识别应用获取的secretKey
|
||||||
|
*/
|
||||||
|
private TokenHolder(String apiKey, String secretKey, String scope) {
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
this.scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TokenHolder getInstance() {
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token,refresh 方法后调用有效
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getToken() {
|
||||||
|
if (this.isExpire()) {
|
||||||
|
try {
|
||||||
|
this.resfresh();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("百度语音获取token失败。", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isExpire() {
|
||||||
|
return System.currentTimeMillis() > this.expiresAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取过期时间,refresh 方法后调用有效
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long getExpiresAt() {
|
||||||
|
return expiresAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws IOException http请求错误
|
||||||
|
*/
|
||||||
|
public void resfresh() throws IOException {
|
||||||
|
String getTokenURL = url + "?grant_type=client_credentials"
|
||||||
|
+ "&client_id=" + ConnUtil.urlEncode(apiKey) + "&client_secret=" + ConnUtil.urlEncode(secretKey);
|
||||||
|
|
||||||
|
// 打印的url出来放到浏览器内可以复现
|
||||||
|
log.debug("token url:" + getTokenURL);
|
||||||
|
|
||||||
|
URL url = new URL(getTokenURL);
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setConnectTimeout(5000);
|
||||||
|
String result = ConnUtil.getResponseString(conn);
|
||||||
|
log.debug("Token result json:" + result);
|
||||||
|
parseJson(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param result token接口获得的result result示例: { "access_token": "1.a6b7dbd428f731035f771b8d********.86400.1292922000-2346678-124328", "expires_in": 86400, "refresh_token":
|
||||||
|
* "2.385d55f8615fdfd9edb7c4b********.604800.1293440400-2346678-124328", "scope": "public audio_voice_assistant_get 。。。", "session_key": "ANXxSNjwQDugf8615Onqeik********CdlLxn",
|
||||||
|
* "session_secret": "248APxvxjCZ0VEC********aK4oZExMB", }
|
||||||
|
*/
|
||||||
|
private void parseJson(String result) {
|
||||||
|
|
||||||
|
Map<String, Object> map = JSONObject.parseObject(result, HashMap.class);
|
||||||
|
if (!map.containsKey("access_token")) {
|
||||||
|
// 返回没有access_token字段
|
||||||
|
throw new RuntimeException("access_token not obtained, " + result);
|
||||||
|
}
|
||||||
|
if (!map.containsKey("scope")) {
|
||||||
|
// 返回没有scope字段
|
||||||
|
throw new RuntimeException("scopenot obtained, " + result);
|
||||||
|
}
|
||||||
|
// scope = null, 忽略scope检查
|
||||||
|
|
||||||
|
if (scope != null && !((String) map.get("scope")).contains(scope)) {
|
||||||
|
throw new RuntimeException("scope not exist, " + scope + "," + result);
|
||||||
|
}
|
||||||
|
token = (String) map.get("access_token");
|
||||||
|
expiresAt = System.currentTimeMillis() + (Long.parseLong(map.get("expires_in").toString())) * 1000;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
package club.joylink.xiannccda.vo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class BaseVoiceSynthesisVO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
/**
|
||||||
|
* 语速
|
||||||
|
*/
|
||||||
|
private int spd;
|
||||||
|
/**
|
||||||
|
* 音调
|
||||||
|
*/
|
||||||
|
private int pit;
|
||||||
|
/**
|
||||||
|
* 音量
|
||||||
|
*/
|
||||||
|
private int vol;
|
||||||
|
/**
|
||||||
|
* 语音样式
|
||||||
|
*/
|
||||||
|
private String per;
|
||||||
|
/**
|
||||||
|
* 是否启用服务商的默认参数
|
||||||
|
*/
|
||||||
|
private boolean defaultParam = true;
|
||||||
|
|
||||||
|
public BaseVoiceSynthesisVO(String message) {
|
||||||
|
this.message = message;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseVoiceSynthesisVO(String message, boolean defaultParam) {
|
||||||
|
this.message = message;
|
||||||
|
this.defaultParam = defaultParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spd 选填 语速,取值0-15,默认为5中语速 pit 选填 音调,取值0-15,默认为5中语调 vol 选填 音量,取值0-15,默认为5中音量(取值为0时为音量最小值,并非为无声) per(基础音库) 选填 度小宇=1,度小美=0,度逍遥(基础)=3,度丫丫=4
|
||||||
|
* per(精品音库) 选填 度逍遥(精品)=5003,度小鹿=5118,度博文=106,度小童=110,度小萌=111,度米朵=103,度小娇=5 aue 选填 3为mp3格式(默认); 4为pcm-16k;5为pcm-8k;6为wav(内容同pcm-16k); 注意aue=4或者6是语音识别要求的格式,但是音频内容不是语音识别要求的自然人发音,所以识别效果会受影响。
|
||||||
|
*/
|
||||||
|
public void checkBaiduParam() {
|
||||||
|
if (this.spd < 0 || this.spd > 15) {
|
||||||
|
this.spd = 5;
|
||||||
|
}
|
||||||
|
if (this.pit < 0 || this.pit > 15) {
|
||||||
|
this.pit = 5;
|
||||||
|
}
|
||||||
|
if (this.vol < 0 || this.vol > 15) {
|
||||||
|
this.vol = 5;
|
||||||
|
}
|
||||||
|
if (this.defaultParam) {
|
||||||
|
this.spd = 5;
|
||||||
|
this.pit = 5;
|
||||||
|
this.vol = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public SynthesisXunFei toBuildXunFei(){
|
||||||
|
if(this.spd <0 || this.spd > 100){
|
||||||
|
this.spd = 50;
|
||||||
|
}
|
||||||
|
if(this.pit < 0 || this.pit > 100){
|
||||||
|
this.pit = 50;
|
||||||
|
}
|
||||||
|
if(this.vol < 0 || this.vol> 100){
|
||||||
|
this.vol = 50;
|
||||||
|
}
|
||||||
|
SynthesisXunFei fei = new SynthesisXunFei(this.message);
|
||||||
|
return fei;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* public static class SynthesisXunFei extends BaseVoiceSynthesisVO {
|
||||||
|
*//**
|
||||||
|
* voice_name 合成发音人 合成所需发音人,对应发音人参数可在控制台"发音人授权管理"查看。
|
||||||
|
* speed 语速 通过此参数,设置合成返回音频的语速。默认值:50,取值范围:[0,100]。
|
||||||
|
* volume 音量 通过此参数,设置合成返回音频的音量。默认值:50,取值范围:[0,100]。
|
||||||
|
* pitch 语调 通过此参数,设置合成返回音频的语调。默认值:50,取值范围:[0,100]。
|
||||||
|
* sample_rate 采样率 音频的采样率是音频属性的其中一个,一般来说,采样率越高音频的质量越好,识别的匹配率越高,但上传带宽消耗也越大。 默认:16KHZ,取值{8KHZ,16KHZ}。
|
||||||
|
* tts_audio_path 合成录音保存路径 通过此参数,可以在合成完成后在本地保存一个音频文件 。
|
||||||
|
* engine_type 引擎类型 设置使用的引擎类型:在线、离线、混合。在线合成设置参数为:"cloud" 。
|
||||||
|
*
|
||||||
|
*//*
|
||||||
|
|
||||||
|
private String engine_type = "cloud";
|
||||||
|
public SynthesisXunFei(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> toMapParam() {
|
||||||
|
Map<String,Object> dataMap = Maps.newHashMap();
|
||||||
|
dataMap.put("speed",this.getSpd());
|
||||||
|
dataMap.put("volume",this.getVol());
|
||||||
|
dataMap.put("pitch",this.getPit());
|
||||||
|
dataMap.put("voice_name",this.getPer());
|
||||||
|
dataMap.put("engine_type",this.engine_type);
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user