增加文字转语音和与串口通信模块

This commit is contained in:
yachts_zh 2020-07-07 16:03:42 +08:00
parent 42582707ce
commit 5667fa8665
20 changed files with 734 additions and 87 deletions

View File

@ -1,87 +1,2 @@
## 平台简介 ## ruoyi-tts
1. (解压doc文件夹下jacob-1.18-x64.rar)把jacob-1.18-x64.dll文件复制到jdk安装位置的bin目录下。
一直想做一款后台管理系统看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序如网站管理后台网站会员中心CMSCRMOA。所有前端后台代码封装过后十分精简易上手出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)
* 感谢 [hplus](https://gitee.com/hplus_admin/hplus) 后台主题 UI 框架。
* 前后端分离版本,请移步[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)  
## 内置功能
1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
3. 岗位管理:配置系统用户所属担任职务。
4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
7. 参数管理:对系统动态配置常用参数。
8. 通知公告:系统通知公告信息发布维护。
9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
10. 登录日志:系统登录日志记录查询包含登录异常。
11. 在线用户:当前系统中活跃用户状态监控。
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
13. 代码生成前后端代码的生成java、html、xml、sql支持CRUD下载 。
14. 系统接口根据业务代码自动生成相关的api接口文档。
15. 服务监控监视当前系统CPU、内存、磁盘、堆栈等相关信息。
16. 在线构建器拖动表单元素生成相应的HTML代码。
17. 连接池监视监视当前系统数据库连接池状态可进行分析SQL找出系统性能瓶颈。
## 在线体验
- admin/admin123
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
演示地址http://ruoyi.vip
文档地址http://doc.ruoyi.vip
## 演示图
<table>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/25b5e333768d013d45a990c152dbe4d9d6e.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/e29fd81b2d43b517f99535564af41f9d1d5.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/629f1510fb6205f773c8c284863406b694f.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/9124eda87df0e72427cd63f458b813e3363.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/438c59467afd0097cfbe9c89db932661687.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/72a015041db6843aca7f7b273688cb346f8.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/ecb5f1c9929f1933f733f796749b2df73d9.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/e4283d500eb10e8dd8701e7742f7facb065.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/2531dbf419a1b114e1177f8d2a120b8a9c3.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/8b740a42dddc1e5a8a150d97c5060df258b.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/00e642dc3515919b3760968cc496a12a849.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/f72d28a3e60413a4e1b5c7c2f45f962fd65.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/19222e495869a2a99fc31c5d2bd4539e1e7.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/264d25176f4e22b4b38e95fe6ce73775299.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/d85fbb59be27fb33f68bdbb6e8bc967c97b.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/bb902d2c54bad02a052e9a05e5f22a93df1.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/30cda883bb9a7f74f1454314e64f949942d.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/deebaaa8d6b14a419ed5911f49e3f222a6f.jpg"/></td>
</tr>
<tr>
<td><img src="https://oscimg.oschina.net/oscnet/bed2b98a44e7ae820c2885329e711965c28.jpg"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td>
</tr>
</table>
## 若依交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-1389287-blue.svg)](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [![加入QQ群](https://img.shields.io/badge/已满-1679294-blue.svg)](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [![加入QQ群](https://img.shields.io/badge/已满-1529866-blue.svg)](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [![加入QQ群](https://img.shields.io/badge/已满-1772718-blue.svg)](https://jq.qq.com/?_wv=1027&k=5g75dCU) [![加入QQ群](https://img.shields.io/badge/已满-1366522-blue.svg)](https://jq.qq.com/?_wv=1027&k=58cPoHA) [![加入QQ群](https://img.shields.io/badge/已满-1382251-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [![加入QQ群](https://img.shields.io/badge/已满-1145125-blue.svg)](https://jq.qq.com/?_wv=1027&k=5yugASz) [![加入QQ群](https://img.shields.io/badge/已满-86752435-blue.svg)](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [![加入QQ群](https://img.shields.io/badge/已满-134072510-blue.svg)](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [![加入QQ群](https://img.shields.io/badge/已满-210336300-blue.svg)](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [![加入QQ群](https://img.shields.io/badge/339522636-blue.svg)](https://jq.qq.com/?_wv=1027&k=5omzbKc)

BIN
doc/jacob-1.18-x64.rar Normal file

Binary file not shown.

View File

@ -1,78 +0,0 @@
若依系统开发环境搭建手册
1. 准备工作
1.1 前置环境准备 -- -- 安装Maven
若依基于Maven管理项目的构建需要先安装好相应的版本。
1.2 开发工具
若依系统采用Eclipse作为开发工具。但不局限于Eclipse。此处仅介绍在Eclipse搭建开发环境所需的操作。
2. 开发环境搭建
2.1 开发工具的配置
2.1.1 配置Maven
进入Window->Preferences->Maven->Installations页面设置已经安装好的Maven
2.1.2 配置Maven仓库路径
进入Window->Preferences->Maven->User Settings页面配置仓库路径
2.1.4 关闭校验
进入Window->Preferences->Validation页面勾选"Suspend all validators",关闭校验
2.2 导入工程
通过Eclipse导入工程步骤如下
(1)点击左侧项目区域 -- >Import...
(2)选择RuoYi
(3)点击Finish(4)RuoYi的代码就被导出到Eclipse中了此时可以在工程视图中看到。
3. 运行若依系统
3.1 必要的配置
3.1.1 修改数据库连接
编辑src/main/ resources目录下的application-druid.yml 文件,修改数据库地址账号信息。
执行sql/ ry_20180423.sqlquartz.sql 两个文件 日期随版本变化
3.1.2 开发环境配置
编辑src/main/ resources目录下的application.yml 文件,
默认端口为80
3.1.3 代码生成配置
编辑src/main/ resources目录下的application.yml 文件,
默认为module根据实际情况修改即可。生成的表要有注释注如对模板有特殊需求可自行修改。编辑src/main/ resources/templates/vm目录下
3.1.4 日志配置
编辑src/main/ resources目录下的logback.yml 文件
<property name="log.path" value="/home/ruoyi/logs" />
改为自己需要的路径
<property name="log.path" value="/Users/jyking/project/logs" />
3.2 启动及验证
启动RuoYiApplication.java 出现如下图表示启动成功
打开浏览器输入http://localhost:80/若能正确展示登录页面,并能成功登录,登录后菜单及页面展示正常,则表明环境搭建成功。默认密码为 admin/admin123
演示地址http://www.ruoyi.club
4. 部署若依系统
4.1 war部署方式
4.1.1 修改pom.xml文件。将jar修改为war
如果是分模块需要修改ruoyi-admin
4.1.2 在spring-boot-starter依赖中移除tomcat模块
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
4.1.3 部署到tomcat的webapps目录下面
默认为RuoYi.war
4.1.4 启动及验证
运行startup.bat 出现如下图即部署成功
4.2 Jar方式部署
执行命令java - jar RuoYi.jar
脚本执行ry.sh start 启动stop 停止
演示地址ruoyi.vip
文档地址doc.ruoyi.vip

View File

@ -31,6 +31,7 @@
<commons.fileupload.version>1.3.3</commons.fileupload.version> <commons.fileupload.version>1.3.3</commons.fileupload.version>
<poi.version>3.17</poi.version> <poi.version>3.17</poi.version>
<velocity.version>1.7</velocity.version> <velocity.version>1.7</velocity.version>
<lombok.version>1.18.12</lombok.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
@ -202,6 +203,14 @@
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!--小辣椒 lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -11,5 +11,35 @@
<artifactId>ruoyi-tts</artifactId> <artifactId>ruoyi-tts</artifactId>
<dependencies>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
</dependency>
<!-- java串口通信 -->
<dependency>
<groupId>org.bidib.jbidib.org.qbang.rxtx</groupId>
<artifactId>rxtxcomm</artifactId>
<version>2.2</version>
</dependency>
<!-- 文字转语音 -->
<dependency>
<groupId>com.hynnet</groupId>
<artifactId>jacob</artifactId>
<version>1.18</version>
</dependency>
<!--小辣椒 lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project> </project>

View File

@ -0,0 +1,24 @@
package com.ruoyi.tts;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @author GideonYeung
* @date 2020/6/24 11:44
*/
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class JacobApp {
public static void main(String[] args) {
SpringApplication.run(JacobApp.class);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}

View File

@ -0,0 +1,26 @@
package com.ruoyi.tts.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
/**
* @author GideonYeung
* @date 2020/6/30 11:10
*/
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
// 设置线程池
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setThreadNamePrefix("Schedule-Task-");
taskScheduler.setPoolSize(5);
taskScheduler.initialize();
scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
}
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:50
*/
public class NoSuchPortException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public NoSuchPortException() {
}
@Override
public String toString() {
return "没有该端口对应的串口设备!";
}
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:51
*/
public class NotSerialPortException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public NotSerialPortException() {
}
@Override
public String toString() {
return "端口指向设备不是串口类型!";
}
}

View File

@ -0,0 +1,18 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:52
*/
public class PortInUseException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public PortInUseException() {
}
@Override
public String toString() {
return "端口已被占用!";
}
}

View File

@ -0,0 +1,21 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:57
*/
public class ReadDataFromSerialPortFailureException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public ReadDataFromSerialPortFailureException() {
}
@Override
public String toString() {
return "从串口读取数据时出错";
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:58
*/
public class SerialPortInputStreamCloseFailureException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public SerialPortInputStreamCloseFailureException() {
}
@Override
public String toString() {
return "关闭串口对象输入流出错";
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:55
*/
public class SerialPortOutputStreamCloseFailureException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public SerialPortOutputStreamCloseFailureException() {
}
@Override
public String toString() {
return "关闭串口对象的输出流出错";
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:49
*/
public class SerialPortParameterFailureException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public SerialPortParameterFailureException() {
}
@Override
public String toString() {
return "设置串口参数失败!打开串口操作未完成!";
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.tts.exception;
/**
* @author GideonYeung
* @date 2020/7/7 9:59
*/
public class TooManyListenersException extends Exception{
/**
*
*/
private static final long serialVersionUID = 1L;
public TooManyListenersException() {
}
@Override
public String toString() {
return "监听类对象过多!";
}
}

View File

@ -0,0 +1,80 @@
package com.ruoyi.tts.jacob;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
* @author GideonYeung
* @date 2020/6/24 11:39
*/
public class VoicePlayback {
/**
* 文字转语音播放
*
* @param text 需要播放的文字
*/
public static void textToSpeech(String text) {
ActiveXComponent ax;
try {
ax = new ActiveXComponent("Sapi.SpVoice");
// 运行时输出语音内容
Dispatch spVoice = ax.getObject();
// 音量 0-100
ax.setProperty("Volume", new Variant(100));
// 语音朗读速度 -10 +10
ax.setProperty("Rate", new Variant(-2));
// 执行朗读
Dispatch.call(spVoice, "Speak", new Variant(text));
// Dispatch.put(spVoice, "Volume", new Variant(100));
// 设置朗读速度
// Dispatch.put(spVoice, "Rate", new Variant(-2));
// 构建文件流把生成语音文件
// makefile(ax, spVoice, text);
spVoice.safeRelease();
ax.safeRelease();
} catch (Exception e) {
e.printStackTrace();
}
}
// public static void makefile(Dispatch spVoice, String text) {
// ActiveXComponent ax = new ActiveXComponent("Sapi.SpFileStream");
// Dispatch spFileStream = ax.getObject();
// ax = new ActiveXComponent("Sapi.SpAudioFormat");
// Dispatch spAudioFormat = ax.getObject();
// // 设置音频流格式
// Dispatch.put(spAudioFormat, "Type", new Variant(22));
// // 设置文件输出流格式
// Dispatch.putRef(spFileStream, "Format", spAudioFormat);
// // 调用输出 文件流打开方法创建一个.wav文件
// Dispatch.call(spFileStream, "Open", new Variant("./text.wav"), new
// Variant(3), new Variant(true));
// // 设置声音对象的音频输出流为输出文件对象
// Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream);
// // 设置音量 0到100
// Dispatch.put(spVoice, "Volume", new Variant(100));
// // 设置朗读速度
// Dispatch.put(spVoice, "Rate", new Variant(-2));
// // 开始朗读
// Dispatch.call(spVoice, "Speak", new Variant(text));
// // 关闭输出文件
// Dispatch.call(spFileStream, "Close");
// Dispatch.putRef(spVoice, "AudioOutputStream", null);
// spAudioFormat.safeRelease();
// spFileStream.safeRelease();
// }
public static void main(String[] args) {
textToSpeech("B54号机处于生产系统维护计划停机状态使用模具B54试模模具生产产品31003522蓝色盖子T耗时1827.5小时。处理方法为, 预计解决时长为0.5小时,负责人为林志峰");
}
}

View File

@ -0,0 +1,260 @@
package com.ruoyi.tts.serial;
import com.ruoyi.tts.exception.*;
import gnu.io.*;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.TooManyListenersException;
/**串口
* @author GideonYeung
* @date 2020/7/7 9:27
*/
@Slf4j
public class SerialTool {
/**
* 查找所有可用端口
* @return 可用端口名称列表
*/
public static ArrayList<String> findPort() {
//获得当前所有可用串口
@SuppressWarnings("unchecked")
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
ArrayList<String> portNameList = new ArrayList<String>();
//将可用串口名添加到List并返回该List
while (portList.hasMoreElements()) {
String portName = portList.nextElement().getName();
portNameList.add(portName);
}
return portNameList;
}
/**
* 打开串口
* @param portName 端口名称
* @param baudRate 波特率
* @return 串口对象
* @throws SerialPortParameterFailureException 设置串口参数失败
* @throws NotSerialPortException 端口指向设备不是串口类型
* @throws NoSuchPortException 没有该端口对应的串口设备
* @throws PortInUseException 端口已被占用
*/
public static SerialPort openPort(String portName, int baudRate) throws SerialPortParameterFailureException, NotSerialPortException, NoSuchPortException, PortInUseException {
try {
//通过端口名识别端口
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
//打开端口并给端口名字和一个timeout打开操作的超时时间
CommPort commPort = portIdentifier.open(portName, 2000);
//判断是不是串口
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
try {
//设置一下串口的波特率等参数
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
throw new SerialPortParameterFailureException();
}
log.info("Open " + portName + " successfully !");
return serialPort;
}
else {
//不是串口
throw new NotSerialPortException();
}
} catch (NoSuchPortException e1) {
throw new NotSerialPortException();
} catch (PortInUseException e2) {
throw new PortInUseException();
}
}
/**
* 关闭串口
* @param serialPort 待关闭的串口对象
*/
public static void closePort(SerialPort serialPort) {
if (serialPort != null) {
serialPort.close();
}
}
/**
* 往串口发送数据
* @param serialPort 串口对象
* @param order 待发送数据
* @throws SerialPortParameterFailureException 向串口发送数据失败
* @throws SerialPortOutputStreamCloseFailureException 关闭串口对象的输出流出错
*/
public static void sendToPort(SerialPort serialPort, byte[] order) throws SerialPortParameterFailureException, SerialPortOutputStreamCloseFailureException {
OutputStream out = null;
try {
out = serialPort.getOutputStream();
out.write(order);
out.flush();
log.info("写入成功");
} catch (IOException e) {
throw new SerialPortParameterFailureException();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
throw new SerialPortOutputStreamCloseFailureException();
}
}
}
/**
* 从串口读取数据
* @param serialPort 当前已建立连接的SerialPort对象
* @return 读取到的数据
* @throws ReadDataFromSerialPortFailureException 从串口读取数据时出错
* @throws SerialPortInputStreamCloseFailureException 关闭串口对象输入流出错
*/
public static byte[] readFromPort(SerialPort serialPort) throws ReadDataFromSerialPortFailureException, SerialPortInputStreamCloseFailureException {
InputStream in = null;
byte[] bytes = null;
try {
in = serialPort.getInputStream();
//获取buffer里的数据长度
int bufflenth = in.available();
while (bufflenth != 0) {
//初始化byte数组为buffer中数据的长度
bytes = new byte[bufflenth];
in.read(bytes);
bufflenth = in.available();
}
} catch (IOException e) {
throw new ReadDataFromSerialPortFailureException();
} finally {
try {
if (in != null) {
in.close();
in = null;
}
} catch(IOException e) {
throw new SerialPortInputStreamCloseFailureException();
}
}
log.info("读取成功");
return bytes;
}
/**
* 添加监听器
* @param port 串口对象
* @param listener 串口监听器
* @throws TooManyListenersException 监听类对象过多
*/
public static void addListener(SerialPort port, DataAvailableListener listener) throws TooManyListenersException {
try {
//给串口添加监听器
port.addEventListener(new SerialPortListener(listener));
//设置当有数据到达时唤醒监听接收线程
port.notifyOnDataAvailable(true);
//设置当通信中断时唤醒中断线程
port.notifyOnBreakInterrupt(true);
} catch (TooManyListenersException e) {
throw new TooManyListenersException();
}
}
/**
* 串口监听
*/
public static class SerialPortListener implements SerialPortEventListener {
private DataAvailableListener mDataAvailableListener;
public SerialPortListener(DataAvailableListener mDataAvailableListener) {
this.mDataAvailableListener = mDataAvailableListener;
}
@Override
public void serialEvent(SerialPortEvent serialPortEvent) {
switch (serialPortEvent.getEventType()) {
// 1.串口存在有效数据
case SerialPortEvent.DATA_AVAILABLE:
if (mDataAvailableListener != null) {
mDataAvailableListener.dataAvailable();
}
break;
// 2.输出缓冲区已清空
case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
break;
// 3.清除待发送数据
case SerialPortEvent.CTS:
break;
// 4.待发送数据准备好了
case SerialPortEvent.DSR:
break;
// 5.振铃指示
case SerialPortEvent.RI:
break;
// 6.载波检测
case SerialPortEvent.CD:
break;
// 7.溢位溢出错误
case SerialPortEvent.OE:
break;
// 8.奇偶校验错误
case SerialPortEvent.PE:
break;
// 9.帧错误
case SerialPortEvent.FE:
break;
// 10.通讯中断
case SerialPortEvent.BI:
log.error("与串口设备通讯中断");
break;
default:
break;
}
}
}
/**
* 串口存在有效数据监听
*/
public interface DataAvailableListener {
/**
* 串口存在有效数据
*/
void dataAvailable();
}
}

View File

@ -0,0 +1,75 @@
package com.ruoyi.tts.task;
import com.ruoyi.tts.exception.*;
import com.ruoyi.tts.jacob.VoicePlayback;
import com.ruoyi.tts.serial.SerialTool;
import com.ruoyi.tts.utils.ByteUtils;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
import java.util.TooManyListenersException;
/**
* @author GideonYeung
* @date 2020/6/24 11:42
*/
@Slf4j
@Component
@Configuration
@EnableScheduling
public class VoicePlaybackTask {
@Autowired
private RestTemplate restTemplate;
// 串口对象
private SerialPort mSerialport;
/**
* 2秒播放一次语音
*/
@Scheduled(fixedDelay = 3000)
private void configureTasks() throws SerialPortParameterFailureException, SerialPortOutputStreamCloseFailureException, NotSerialPortException, PortInUseException, NoSuchPortException, TooManyListenersException {
Map<String, Boolean> nodeValueMap = new HashMap<>();
try {
nodeValueMap = restTemplate.getForObject("http://127.0.0.1/icloud/nodeValue/getWmKey", Map.class);
} catch (HttpClientErrorException e) {
log.error("icloud暂无开启无法获取数据。");
}
boolean contains = nodeValueMap.values().contains(true);
byte[] bs;
SerialPort port = null;
if (contains) {
port = SerialTool.openPort("COM1", 9600);
//设定发送字符串
bs = ByteUtils.hex2Bytes("5501110000000168");
//打开串口
SerialTool.sendToPort(port, bs);
}
nodeValueMap.forEach((key, value) -> {
if (value) {
String message = key + "号机按下广播通知,请及时处理。";
log.info(message);
VoicePlayback.textToSpeech(message);
}
});
if (contains) {
//设定发送字符串
bs = ByteUtils.hex2Bytes("5501120000000169");
//关闭串口
SerialTool.sendToPort(port, bs);
SerialTool.closePort(port);
}
}
}

View File

@ -0,0 +1,57 @@
package com.ruoyi.tts.utils;
import java.util.Locale;
/**
* @author GideonYeung
* @date 2020/7/7 10:04
*/
public class ByteUtils {
public static byte[] hex2Bytes(String hex) {
if (hex == null || hex.length() == 0) {
return null;
}
char[] hexChars = hex.toCharArray();
// 如果 hex 中的字符不是偶数个, 则忽略最后一个
byte[] bytes = new byte[hexChars.length / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt("" + hexChars[i * 2] + hexChars[i * 2 + 1], 16);
}
return bytes;
}
/**
* byte[]转十六进制字符串
*
* @param array byte[]
* @return 十六进制字符串
*/
public static String byteArrayToHexString(byte[] array) {
if (array == null) {
return "";
}
StringBuilder buffer = new StringBuilder();
for (byte b : array) {
buffer.append(byteToHex(b));
}
return buffer.toString();
}
/**
* byte转十六进制字符
*
* @param b byte
* @return 十六进制字符
*/
public static String byteToHex(byte b) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
return hex.toUpperCase(Locale.getDefault());
}
}

View File

@ -0,0 +1,14 @@
# 开发环境配置
server:
# 服务器的HTTP端口默认为8881
port: 8881
servlet:
# 应用的访问路径
context-path: /
tomcat:
# tomcat的URI编码
uri-encoding: UTF-8
# tomcat最大线程数默认为200
max-threads: 800
# Tomcat启动初始化的线程数默认值25
min-spare-threads: 30