增加文字转语音和与串口通信模块
This commit is contained in:
parent
42582707ce
commit
5667fa8665
89
README.md
89
README.md
|
|
@ -1,87 +1,2 @@
|
|||
## 平台简介
|
||||
|
||||
一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的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)
|
||||
## ruoyi-tts
|
||||
1. (解压doc文件夹下jacob-1.18-x64.rar)把jacob-1.18-x64.dll文件复制到jdk安装位置的bin目录下。
|
||||
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>
|
||||
<poi.version>3.17</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
<lombok.version>1.18.12</lombok.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
|
|
@ -202,6 +203,14 @@
|
|||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--小辣椒 lombok-->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
|
|
|||
|
|
@ -11,5 +11,35 @@
|
|||
|
||||
<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>
|
||||
|
|
@ -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