应急预警系统-语音指令功能
This commit is contained in:
parent
0b266b2284
commit
e84b9ad0dc
5
pom.xml
5
pom.xml
@ -134,6 +134,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.belerweb</groupId>
|
||||
<artifactId>pinyin4j</artifactId>
|
||||
<version>2.5.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -58,7 +58,7 @@ public enum BusinessExceptionAssertEnum implements BusinessExceptionAssert {
|
||||
INVALID_CLIENT(40031, "invalid client"),
|
||||
INCORRECT_VERIFICATION_CODE(40051, "incorrect verification code"),
|
||||
THIRD_SERVICE_CALL_EXCEPTION(40071, "the third service call exception"),
|
||||
|
||||
VOICE_COMMAND_PARSE_ERROR(40061,"voice command parse error"),
|
||||
//支付异常
|
||||
PAY_ERROR(50000, "pay error"),
|
||||
WECHAT_NOTIFY_ERROR(401, "wechat notify error")
|
||||
|
@ -12,6 +12,8 @@ public interface IVoiceService {
|
||||
|
||||
VoiceRecognitionResult voiceRecognition(byte[] bytes, String filePath);
|
||||
|
||||
VoiceRecognitionResult voiceRecognition(String fileBase64);
|
||||
|
||||
/**
|
||||
* 语音合成,返回文件路径
|
||||
*
|
||||
|
@ -12,6 +12,7 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* 百度语音识别合成服务
|
||||
@ -115,6 +116,18 @@ public class BaiduVoiceServiceImpl implements IVoiceService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoiceRecognitionResult voiceRecognition(String fileBase64) {
|
||||
try {
|
||||
String base64 = fileBase64.substring(fileBase64.indexOf("base64,") + "base64,".length());
|
||||
byte[] bytes = Base64.getDecoder().decode(base64.trim());
|
||||
String filePath = VoiceFileUtils.saveFile(bytes);
|
||||
return voiceRecognition(bytes, filePath);
|
||||
} catch (Exception e) {
|
||||
throw BusinessExceptionAssertEnum.THIRD_SERVICE_CALL_EXCEPTION.exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String synthesis(String message, String per) {
|
||||
try {
|
||||
|
@ -64,5 +64,11 @@ public class HuaweiVoiceServiceImpl implements IVoiceService {
|
||||
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("语音识别失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoiceRecognitionResult voiceRecognition(String fileBase64) {
|
||||
String base64 = fileBase64.substring(fileBase64.indexOf("base64,") + "base64,".length());
|
||||
byte[] bytes = Base64.getDecoder().decode(base64.trim());
|
||||
String filePath = VoiceFileUtils.saveFile(bytes);
|
||||
return voiceRecognition(bytes, filePath);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Base64;
|
||||
|
||||
@Service("XunFeiVoiceService")
|
||||
public class XunFeiVoiceService implements IVoiceService {
|
||||
@ -57,6 +58,14 @@ public class XunFeiVoiceService implements IVoiceService {
|
||||
throw BusinessExceptionAssertEnum.SYSTEM_EXCEPTION.exception("语音识别失败");
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoiceRecognitionResult voiceRecognition(String fileBase64) {
|
||||
String base64 = fileBase64.substring(fileBase64.indexOf("base64,") + "base64,".length());
|
||||
byte[] bytes = Base64.getDecoder().decode(base64.trim());
|
||||
String filePath = VoiceFileUtils.saveFile(bytes);
|
||||
return voiceRecognition(bytes, filePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String synthesis(String message, String per) {
|
||||
return null;
|
||||
|
@ -1342,7 +1342,11 @@ public class Operation {
|
||||
*/
|
||||
REGULAR_TRAIN_LINE_STATION_UPDATE(new Label[]{Label.CLIENT}),
|
||||
REGULAR_TRAIN_LINE_STATION_UPDATE_LIST(new Label[]{Label.CLIENT}),
|
||||
REGULAR_TRAIN_LINE_STATION_UPDATE_LOAD(new Label[]{Label.CLIENT});
|
||||
REGULAR_TRAIN_LINE_STATION_UPDATE_LOAD(new Label[]{Label.CLIENT}),
|
||||
/**
|
||||
* 紧急应急语音命令
|
||||
*/
|
||||
YJDDZH_VOICE_COMMAND(new Label[]{Label.CLIENT});
|
||||
final Label[] labels;
|
||||
|
||||
Type(Label[] labels) {
|
||||
|
@ -0,0 +1,26 @@
|
||||
package club.joylink.rtss.simulation.cbtc.command;
|
||||
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.operation.Operation;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandler;
|
||||
import club.joylink.rtss.simulation.cbtc.ATS.operation.annotation.OperateHandlerMapping;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.command.service.VoiceCommandService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@OperateHandler
|
||||
@Slf4j
|
||||
public class VoiceCommandHandler {
|
||||
|
||||
@Resource
|
||||
@Qualifier("voiceCommand")
|
||||
private VoiceCommandService service;
|
||||
|
||||
@OperateHandlerMapping(type = Operation.Type.YJDDZH_VOICE_COMMAND)
|
||||
public void yjddzhVoiceCommand(Simulation simulation, String base64Str) {
|
||||
this.service.voiceCommand(simulation,base64Str);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
package club.joylink.rtss.simulation.cbtc.command.service;
|
||||
|
||||
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
|
||||
import club.joylink.rtss.services.voice.IVoiceService;
|
||||
import club.joylink.rtss.simulation.cbtc.CI.device.CiSwitchControlService;
|
||||
import club.joylink.rtss.simulation.cbtc.Simulation;
|
||||
import club.joylink.rtss.simulation.cbtc.conversation.SimulationVoiceHandler;
|
||||
import club.joylink.rtss.simulation.cbtc.data.SimulationDataRepository;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
|
||||
import club.joylink.rtss.simulation.cbtc.data.map.Switch;
|
||||
import club.joylink.rtss.vo.client.VoiceRecognitionResult;
|
||||
import net.sourceforge.pinyin4j.PinyinHelper;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
|
||||
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
|
||||
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service(value="voiceCommand")
|
||||
public class VoiceCommandService {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("baiDuVoiceService")
|
||||
private IVoiceService iVoiceService;
|
||||
|
||||
@Autowired
|
||||
private SimulationVoiceHandler voiceHandler;
|
||||
|
||||
@Autowired
|
||||
private CiSwitchControlService ciSwitchControlService;
|
||||
|
||||
public void voiceCommand(Simulation simulation,String base64Str){
|
||||
VoiceRecognitionResult result = this.iVoiceService.voiceRecognition(base64Str);
|
||||
if(Objects.equals(false, StringUtils.hasText(result.getResult()))){
|
||||
//TODO 未获取到语音识别的内容
|
||||
return;
|
||||
}
|
||||
this.parseCommand(simulation,result.getResult());
|
||||
}
|
||||
|
||||
|
||||
private final static String SWITCH_PINYIN = "DAOCHA";
|
||||
private final static String SWITCH_STATE_DINGWEI_PINGYIN = "DING";
|
||||
private final static String SWITCH_STATE_FANWEI_PINGYIN = "FAN";
|
||||
private void parseCommand(Simulation simulation,String result){
|
||||
String changeResultStr = voiceHandler.numHandle(result);
|
||||
String pinyinContent = this.toPinYin(changeResultStr);
|
||||
int switchIndex = pinyinContent.indexOf(SWITCH_PINYIN);
|
||||
BusinessExceptionAssertEnum.VOICE_COMMAND_PARSE_ERROR.assertTrue(switchIndex >=0,String.format("不能解析道岔的语音指令,语音识别:%s",changeResultStr));
|
||||
String pinyinCommand = pinyinContent.substring(switchIndex + SWITCH_PINYIN.length());
|
||||
String deviceName = pinyinContent.substring(0,switchIndex);
|
||||
boolean hasDingCommand = pinyinCommand.contains(SWITCH_STATE_DINGWEI_PINGYIN);
|
||||
boolean hasFanCommand = pinyinCommand.contains(SWITCH_STATE_FANWEI_PINGYIN);
|
||||
BusinessExceptionAssertEnum.VOICE_COMMAND_PARSE_ERROR.assertTrue(Objects.nonNull(deviceName),String.format("不能解析道岔的名称,语音识别:%s",changeResultStr));
|
||||
BusinessExceptionAssertEnum.VOICE_COMMAND_PARSE_ERROR.assertTrue(hasDingCommand || hasFanCommand,String.format("道岔的语音指令不明确,语音识别:%s",changeResultStr));
|
||||
BusinessExceptionAssertEnum.VOICE_COMMAND_PARSE_ERROR.assertNotTrue(hasDingCommand && hasFanCommand,String.format("道岔的语音指令只能有一个,语音识别:%s",changeResultStr));
|
||||
|
||||
this.turnSwitch(simulation,deviceName,hasDingCommand,hasFanCommand);
|
||||
}
|
||||
|
||||
private void turnSwitch(Simulation simulation,String name,boolean hasDingCommand,boolean hasFanCommand){
|
||||
|
||||
SimulationDataRepository repository = simulation.getRepository();
|
||||
Switch aSwitch = repository.getDeviceMap().values().stream()
|
||||
.filter(d->d.getDeviceType() == MapElement.DeviceType.SWITCH && Objects.equals(((Switch)d).getName().toUpperCase(),name.toUpperCase()))
|
||||
.map(d->(Switch) d).findFirst().orElse(null);
|
||||
BusinessExceptionAssertEnum.VOICE_COMMAND_PARSE_ERROR.assertTrue(Objects.nonNull(aSwitch),String.format("未找到对应的道岔:%s",name));
|
||||
if(hasDingCommand){
|
||||
this.ciSwitchControlService.turn2NormalPosition(simulation,aSwitch);
|
||||
}else if(hasFanCommand){
|
||||
this.ciSwitchControlService.turn2ReversePosition(simulation,aSwitch);
|
||||
}
|
||||
}
|
||||
|
||||
private final static HanyuPinyinOutputFormat PIN_YIN_FORMAT = new HanyuPinyinOutputFormat();
|
||||
static{
|
||||
/**
|
||||
* 输出大小写设置
|
||||
*
|
||||
* LOWERCASE:输出小写
|
||||
* UPPERCASE:输出大写
|
||||
*/
|
||||
PIN_YIN_FORMAT.setCaseType(HanyuPinyinCaseType.UPPERCASE);
|
||||
/**
|
||||
* 输出音标设置
|
||||
*
|
||||
* WITH_TONE_MARK:直接用音标符(必须设置WITH_U_UNICODE,否则会抛出异常)
|
||||
* WITH_TONE_NUMBER:1-4数字表示音标
|
||||
* WITHOUT_TONE:没有音标
|
||||
*/
|
||||
PIN_YIN_FORMAT.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
|
||||
}
|
||||
private String toPinYin(String content) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(char c : content.toCharArray()){
|
||||
if(Character.toString(c).matches("[\\u4E00-\\u9FA5]+")) {
|
||||
try {
|
||||
String[] ss = PinyinHelper.toHanyuPinyinStringArray(c,PIN_YIN_FORMAT);
|
||||
sb.append(ss[0]);
|
||||
} catch (BadHanyuPinyinOutputFormatCombination e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}else{
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -21,20 +21,26 @@ public class SimulationVoiceHandler {
|
||||
// static {
|
||||
// regexReplaceMap.put("一", "1");
|
||||
// }
|
||||
static List<Replacement> numReplacementList;
|
||||
|
||||
static {
|
||||
replacementList = new ArrayList<>();
|
||||
numReplacementList = new ArrayList<>();
|
||||
|
||||
//------------- 数字 --------------
|
||||
// replacementList.add(new Replacement("(零|洞|栋)", "0"));
|
||||
// replacementList.add(new Replacement("(一|幺)", "1"));
|
||||
// replacementList.add(new Replacement("(二|两)", "2"));
|
||||
// replacementList.add(new Replacement("(三)", "3"));
|
||||
// replacementList.add(new Replacement("(四)", "4"));
|
||||
// replacementList.add(new Replacement("(五)", "5"));
|
||||
// replacementList.add(new Replacement("(六)", "6"));
|
||||
// replacementList.add(new Replacement("(七|拐)", "7"));
|
||||
// replacementList.add(new Replacement("(八)", "8"));
|
||||
// replacementList.add(new Replacement("(九)", "9"));
|
||||
numReplacementList.add(new Replacement("(零|洞|栋)", "0"));
|
||||
numReplacementList.add(new Replacement("(一|幺|e|E)", "1"));
|
||||
numReplacementList.add(new Replacement("(二|两|r)", "2"));
|
||||
numReplacementList.add(new Replacement("(三)", "3"));
|
||||
numReplacementList.add(new Replacement("(四)", "4"));
|
||||
numReplacementList.add(new Replacement("(五)", "5"));
|
||||
numReplacementList.add(new Replacement("(六)", "6"));
|
||||
numReplacementList.add(new Replacement("(七|拐)", "7"));
|
||||
numReplacementList.add(new Replacement("(八)", "8"));
|
||||
numReplacementList.add(new Replacement("(九)", "9"));
|
||||
numReplacementList.add(new Replacement("(,|。)", ""));
|
||||
numReplacementList.add(new Replacement("( )", ""));
|
||||
numReplacementList.add(new Replacement("(低|地|第|敌|底|递)", "d"));
|
||||
//------------- 专业词汇 --------------
|
||||
replacementList.add(new Replacement("(行吊|情调|神雕|性交|心跳|香蕉|星标|平调|新调)", "行调"));
|
||||
replacementList.add(new Replacement("(茼蒿)", "通号"));
|
||||
@ -157,6 +163,12 @@ public class SimulationVoiceHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public String numHandle(String content){
|
||||
for (Replacement replacement : numReplacementList) {
|
||||
content = replacement.matchAndReplace(content);
|
||||
}
|
||||
return regexReplace(content);
|
||||
}
|
||||
/**
|
||||
* 对语音识别内容进行仿真用词处理
|
||||
*
|
||||
|
@ -26,10 +26,10 @@ public class VRDeviceLogicLoop {
|
||||
@Autowired
|
||||
private VirtualRealityDeviceService virtualRealityDeviceService;
|
||||
|
||||
public void runForTrainPosition(Simulation simulation){
|
||||
// 列车占压计轴区段检查
|
||||
this.updateTrainOccupySection(simulation);
|
||||
}
|
||||
// public void runForTrainPosition(Simulation simulation){
|
||||
// // 列车占压计轴区段检查
|
||||
// this.updateTrainOccupySection(simulation);
|
||||
// }
|
||||
public void run(Simulation simulation) {
|
||||
// long start = System.currentTimeMillis();
|
||||
// 虚拟真实道岔转动过程
|
||||
@ -90,6 +90,8 @@ public class VRDeviceLogicLoop {
|
||||
simulation.addJob(SimulationModule.VRD.name(), () -> this.run(simulation), SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
public void addJobsForTrainPosition(Simulation simulation) {
|
||||
simulation.addJob(SimulationModule.VRD.name(), () -> this.runForTrainPosition(simulation), SimulationConstants.VRD_LOOP_RATE);
|
||||
//
|
||||
simulation.addJob(SimulationModule.VRD.name(), () -> this.run(simulation), SimulationConstants.VRD_LOOP_RATE);
|
||||
// simulation.addJob(SimulationModule.VRD.name(), () -> this.runForTrainPosition(simulation), SimulationConstants.VRD_LOOP_RATE);
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ public class MemberManager {
|
||||
this.playRole(simulation, userId, supervisorList.get(0).getId());
|
||||
break;
|
||||
}
|
||||
case YJDDZH:
|
||||
case BIG_SCREEN:
|
||||
case ISCS:
|
||||
case CENTER:
|
||||
|
Loading…
Reference in New Issue
Block a user