FactoryTalk SE Alarm 报警服务器语音报警提示
目录
最近项目中有要求进行语音报警,之前有同学使用语音合成软件生成wav格式文件进行播放,能够实现项目语音报警。
考虑语音软件生成wav文件的方式只针对当前项目有效,换一个项目需要重新生成声音播放文件,于是考虑是否能通过tts的方式直接播报系统故障。
TTS
弯路
TTS即语音合成技术(Text To Speech),国内做的比较好的是科大讯飞、百度云等,国外的有微软等。对比发现,讯飞的TTS人耳听起来更悦耳一些,于是决定使用讯飞的离线语音合成技术。
原型制作出来后,在开发电脑上运行良好,部署到现场电脑发现报10202故障,后了解到该技术需要联网使用,并非完全离线的TTS,对于工业环境十分不友好。
于是投入微软TTS的怀抱。
微软TTS
使用微软的TTS需要安装.NET Framework 4.5
dll方式
制作DLL
项目属性设置
新建一个VB.NET类库项目,命名为TTS_RIC。目标框架.NET Framework 4.5
编译-选中"为COM互操作注册"
签名-勾选为程序集签名,创建一个密钥文件并选中
NuGet程序包
在项目的"引用…"上单击右键,选择"管理NuGet程序包…"
搜索System.Speech,安装5.00版。6.00版只支持.NETCore
新建tts.vb类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
Imports System.Speech.Synthesis <ComClass(TTS.ClassId, TTS.InterfaceId, TTS.EventsId)> Public Class TTS #Region "COM GUID" ' 这些 GUID 提供此类的 COM 标识 ' 及其 COM 接口。若更改它们,则现有的 ' 客户端将不再能访问此类。 Public Const ClassId As String = "E0E5468F-94ED-46C2-990D-FEA789F20F08" Public Const InterfaceId As String = "FA7214AA-D881-4273-BD72-F9D163EA0E82" Public Const EventsId As String = "1C57302F-D786-49D8-A2E0-0CDCA5B3944D" #End Region ' 可创建的 COM 类必须具有一个不带参数的 Public Sub New() ' 否则, 将不会在 ' COM 注册表中注册此类,且无法通过 ' CreateObject 创建此类。 Public Sub New() MyBase.New() End Sub Private _s As String Function S(ByVal sender As String) _s = sender Dim Speech As New SpeechSynthesizer Speech.Rate = 1 Speech.Speak(_s) Speech.Dispose() Return True End Function End Class |
ClassId、InterfaceId、EventsId通过guidgen.exe软件进行生成,在"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\Tools\"目录下。
生成DLL
在项目上单击右键,生成项目,在项目目录的debug文件夹下找到生成的.DLL和.TLB文件复制到现场电脑上。
使用DLL
注册DLL
进入CMD先进入.NET的目录,注册一下该dll文件,后面一定要带/codebase
C:\Windows\Microsoft.NET\Framework\v4.0.30319>regasm C:\Users\KING\Desktop\tts\ric_tts.dll /codebase
引用DLL
在SE软件中打开VBA环境,引用.TLB文件,不是引用.DLL文件。
代码
1 2 3 4 5 |
Dim a1 As TTS_RIC.TTS Public Sub a() Set a1 = New TTS_RIC.TTS a1.S ("与人玫瑰,手有余香") End Sub |
缺陷
用此方法无法直接获取报警信息,需要修改较多的画面或者PLC程序。
exe方式
制作EXE文件
项目属性设置
新建一个VB.NET Windows窗体应用程序项目,命名为TTS。目标框架.NET Framework 4.5,启动对象Sub Main。
NuGet程序包
在项目的"引用…"上单击右键,选择"管理NuGet程序包…"
搜索System.Speech,安装5.00版。6.00版只支持.NETCore
新建tts.vb类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Imports System.Speech.Synthesis Public Class tts Public Shared Sub Main(ByVal aa() As String) Dim InputValue As String If aa.GetUpperBound(0) < 0 Then InputValue = "" Else InputValue = aa(0) End If Dim Speech As New SpeechSynthesizer With { .Rate = 1 } Speech.Speak(InputValue) Speech.Dispose() End Sub End Class |
从启动参数中获取要播报的语音内容。
生成EXE
在项目上单击右键,生成项目,在项目目录的debug文件夹下找到生成的.EXE文件复制到现场电脑上。
使用EXE
在SE中使用
可以在按钮的操作命令里输入"AppStart C:\Users\KING\Desktop\tts\TTS.exe 温度超过最高限制值"进行调用
也可以从宏命令里调用。
关键难点还是无法直接获取报警信息。
利用SQL Server的触发器
这种方式可以获取到报警信息,也可以直接播放声音,缺点是滞后比较大,大概有3秒滞后时间。
首先在SE中创建报警的历史数据存储
设置如下
关键的一点是记录事件的触发数量,一定要改成1。
在SE的报警服务器中启用历史记录
在SQL Server中的表结构如下,我们要在AllEvent表下创建一个触发器,这个表储存着所有报警信息。
新建查询,启用xp_cmdshell
1 2 3 4 5 6 |
exec sp_configure 'show advanced options', 1; reconfigure; exec sp_configure 'xp_cmdshell', 1; reconfigure; exec sp_configure 'show advanced options', 0; reconfigure; |
新建查询,输入以下信息创建触发器,当插入数据时,则会调用外部命令TTS.exe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
USE [SE_alarm] GO /****** Object: Trigger [dbo].[tgr_AllEvent_updtim] Script Date: 2022/9/28 14:24:56 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- 创建触发器 ALTER TRIGGER [dbo].[tgr_AllEvent_updtim] ON [dbo].[AllEvent] -- 触发时机、条件 AFTER INSERT AS BEGIN SET NOCOUNT ON; Declare @activ int; Declare @name nvarchar(512),@cmd nvarchar(612); Select @activ=[Active] ,@name=[Message] From inserted; IF(@activ=1) Begin print @name; SET @cmd ='C:\Users\KING\Desktop\tts\TTS.exe ' + @name; print @cmd; EXEC xp_cmdshell @cmd; End --UPDATE dbo.[AllEvent] --SET [AutoUnshelveTime]=SYSDATETIME() --WHERE EventID IN (SELECT DISTINCT EventID FROM inserted) END |
新建查询,启用触发器
1 |
ALTER TABLE [dbo].[AllEvent] ENABLE TRIGGER tgr_AllEvent_updtim |
这样当有新报警记录到数据库时,会播报报警信息。
如果有以下提示,需要检查SQL的登陆账号所关联的windows账号权限是否是管理员权限。