增加文字转语音和与串口通信模块
This commit is contained in:
parent
42582707ce
commit
5667fa8665
89
README.md
89
README.md
|
|
@ -1,87 +1,2 @@
|
||||||
## 平台简介
|
## ruoyi-tts
|
||||||
|
1. (解压doc文件夹下jacob-1.18-x64.rar)把jacob-1.18-x64.dll文件复制到jdk安装位置的bin目录下。
|
||||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
|
|
||||||
|
|
||||||
性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)
|
|
||||||
|
|
||||||
* 感谢 [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群: [](https://jq.qq.com/?_wv=1027&k=5HBAaYN) [](https://jq.qq.com/?_wv=1027&k=5cHeRVW) [](https://jq.qq.com/?_wv=1027&k=53R0L5Z) [](https://jq.qq.com/?_wv=1027&k=5g75dCU) [](https://jq.qq.com/?_wv=1027&k=58cPoHA) [](https://jq.qq.com/?_wv=1027&k=5Ofd4Pb) [](https://jq.qq.com/?_wv=1027&k=5yugASz) [](https://jq.qq.com/?_wv=1027&k=5Rf3d2P) [](https://jq.qq.com/?_wv=1027&k=5ZIjaeP) [](https://jq.qq.com/?_wv=1027&k=5CJw1jY) [](https://jq.qq.com/?_wv=1027&k=5omzbKc)
|
|
||||||
Binary file not shown.
|
|
@ -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.sql,quartz.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
|
|
||||||
9
pom.xml
9
pom.xml
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "没有该端口对应的串口设备!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "端口指向设备不是串口类型!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "端口已被占用!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "从串口读取数据时出错";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "关闭串口对象输入流出错";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "关闭串口对象的输出流出错";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "设置串口参数失败!打开串口操作未完成!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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 "监听类对象过多!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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小时,负责人为林志峰");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue