diff --git a/README.md b/README.md
index 27d4fe22a..6bad1dd8f 100644
--- a/README.md
+++ b/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
-
-## 演示图
-
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-  |
-  |
-
-
-
-
-## 若依交流群
-
-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)
\ No newline at end of file
+## ruoyi-tts
+1. (解压doc文件夹下jacob-1.18-x64.rar)把jacob-1.18-x64.dll文件复制到jdk安装位置的bin目录下。
\ No newline at end of file
diff --git a/doc/jacob-1.18-x64.rar b/doc/jacob-1.18-x64.rar
new file mode 100644
index 000000000..d8a58b0f4
Binary files /dev/null and b/doc/jacob-1.18-x64.rar differ
diff --git a/doc/若依环境使用手册.docx b/doc/若依环境使用手册.docx
index c0edbcc48..e69de29bb 100644
--- a/doc/若依环境使用手册.docx
+++ b/doc/若依环境使用手册.docx
@@ -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 文件
-
-改为自己需要的路径
-
-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模块
-
-
-
- spring-boot-starter-tomcat
- org.springframework.boot
-
-
-
-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
diff --git a/pom.xml b/pom.xml
index cc03afb23..45a0efa2d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,7 @@
1.3.3
3.17
1.7
+ 1.18.12
@@ -202,6 +203,14 @@
ruoyi-common
${ruoyi.version}
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
diff --git a/ruoyi-tts/pom.xml b/ruoyi-tts/pom.xml
index fa539e5d4..3329f58c8 100644
--- a/ruoyi-tts/pom.xml
+++ b/ruoyi-tts/pom.xml
@@ -11,5 +11,35 @@
ruoyi-tts
+
+
+
+
+ com.ruoyi
+ ruoyi-framework
+
+
+
+
+ org.bidib.jbidib.org.qbang.rxtx
+ rxtxcomm
+ 2.2
+
+
+
+
+ com.hynnet
+ jacob
+ 1.18
+
+
+
+
+ org.projectlombok
+ lombok
+ provided
+
+
+
\ No newline at end of file
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/JacobApp.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/JacobApp.java
new file mode 100644
index 000000000..2a78f1784
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/JacobApp.java
@@ -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();
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/config/ScheduleConfig.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/config/ScheduleConfig.java
new file mode 100644
index 000000000..4a040f810
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/config/ScheduleConfig.java
@@ -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);
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/NoSuchPortException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/NoSuchPortException.java
new file mode 100644
index 000000000..340787bb2
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/NoSuchPortException.java
@@ -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 "没有该端口对应的串口设备!";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/NotSerialPortException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/NotSerialPortException.java
new file mode 100644
index 000000000..303550df2
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/NotSerialPortException.java
@@ -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 "端口指向设备不是串口类型!";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/PortInUseException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/PortInUseException.java
new file mode 100644
index 000000000..a80080f9d
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/PortInUseException.java
@@ -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 "端口已被占用!";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/ReadDataFromSerialPortFailureException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/ReadDataFromSerialPortFailureException.java
new file mode 100644
index 000000000..1f5b10850
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/ReadDataFromSerialPortFailureException.java
@@ -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 "从串口读取数据时出错";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortInputStreamCloseFailureException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortInputStreamCloseFailureException.java
new file mode 100644
index 000000000..7fcccb105
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortInputStreamCloseFailureException.java
@@ -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 "关闭串口对象输入流出错";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortOutputStreamCloseFailureException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortOutputStreamCloseFailureException.java
new file mode 100644
index 000000000..22d44be53
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortOutputStreamCloseFailureException.java
@@ -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 "关闭串口对象的输出流出错";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortParameterFailureException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortParameterFailureException.java
new file mode 100644
index 000000000..cb7f38a85
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/SerialPortParameterFailureException.java
@@ -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 "设置串口参数失败!打开串口操作未完成!";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/TooManyListenersException.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/TooManyListenersException.java
new file mode 100644
index 000000000..2fd701777
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/exception/TooManyListenersException.java
@@ -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 "监听类对象过多!";
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/jacob/VoicePlayback.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/jacob/VoicePlayback.java
new file mode 100644
index 000000000..f3ab685cd
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/jacob/VoicePlayback.java
@@ -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小时,负责人为林志峰");
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/serial/SerialTool.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/serial/SerialTool.java
new file mode 100644
index 000000000..9075afa30
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/serial/SerialTool.java
@@ -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 findPort() {
+
+ //获得当前所有可用串口
+ @SuppressWarnings("unchecked")
+ Enumeration portList = CommPortIdentifier.getPortIdentifiers();
+ ArrayList portNameList = new ArrayList();
+ //将可用串口名添加到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();
+ }
+
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/task/VoicePlaybackTask.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/task/VoicePlaybackTask.java
new file mode 100644
index 000000000..31ddb5944
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/task/VoicePlaybackTask.java
@@ -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 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);
+ }
+ }
+}
diff --git a/ruoyi-tts/src/main/java/com.ruoyi.tts/utils/ByteUtils.java b/ruoyi-tts/src/main/java/com.ruoyi.tts/utils/ByteUtils.java
new file mode 100644
index 000000000..900773ace
--- /dev/null
+++ b/ruoyi-tts/src/main/java/com.ruoyi.tts/utils/ByteUtils.java
@@ -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());
+ }
+
+}
diff --git a/ruoyi-tts/src/main/resources/application.yml b/ruoyi-tts/src/main/resources/application.yml
new file mode 100644
index 000000000..173c5f573
--- /dev/null
+++ b/ruoyi-tts/src/main/resources/application.yml
@@ -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
\ No newline at end of file