程序在向中Alarm[]中写内容的同时,语音播报程序将Alarm[].desc[64]的内容读出。然而写内存较快,读语音却时间较长。读语音的指针i_speech会跟不上写内存的数组i_alarm指针,即128>i_alarm>i_speech(见图3.3.a)。但随着告警事件增多时i_speech还没有读完一个循环,i_alarm已经进入下一循环了,即128>i_speech>i_alarm(见图3.3.b)。
图3.3 a 图3.3 b
经过上述分析可以看出,程序无法通过简单的比较两个数组指针大小来判断是否有刚写入待播报的告警事件。
要解决这个问题,可以通过设置标志,标识i_alarm是否已经进入下一循环,从而进行进一步的判断。但这个方法算法实现比较麻烦,需要通过一套较复杂的逻辑判断。比较之下,本文利用构建线程的方式设计了一种较为简单的方式,具体如下:
添加Alarm结构体中的成员变量soundflag。其含义:0—已播报;1—待播报。首先在初始化构建Alarm[]数组时,就将所有共128个成员的soundflag全部置为0。然后将生成的告警事件写入Alarm[]时将其对应的soundflag置为1。此时,构建语音检测的线程,用数组指针i_speech循环判断Alarm[]中所有成员的soundflag,若为1,则播报内容,完成后将其清零,并继续检测。由于这里的语音播报和语音检测是独立的线程,其运行不会影响到监控系统其它程序。
3.4 函数代码实现
限于篇幅限制,下面之阐述一些有代表性的函数代码。具体告警事件生成部分和语音告警实现部分详见x.x3.4节和第4章x.x。
3.4.1 初始化程序
如下为主要的初始化程序代码
。。。
InitTTS(this->GetSafeHwnd(), WM_USER+100,WM_USER+101);
Load_data();
。。。
说明:
InitTTS()函数用于初始化化语音合成引擎。将在x.x详述。
Load_data()即为载入配置参数函数,具体代码如下:
int Load_data()
{
Load_Device_Data(); //载入设备配置参数
Load_Analog_Data(); //载入模拟量配置参数
Load_Status_Data(); //载入状态量配置参数
//以上三个函数已经在2.3.1的第5点中详述
sreco.SpeakAsyn(L"资料载入成功!");//封装好的语音合成函数,详见x.x,完成资料载入后
//播报“资料载入成功”以对值班员进行提示
return TRUE;
}
其中,三个载入函数是将设备信息参数、模拟量参数和状态量参数的设定是通过文件读取的方式输入的,且载入的方式相似,限于篇幅,下面只以模拟量参数输入为例进行说明。
模拟量参数信息输入,在Analog_data.txt中写入模拟量参数信息,格式如下:
所属设备编码数据,变量监测点代码,变量描述,变量类型,一级上限值,二级上限值,一级下限值,二级下限值,变量系数,告警标志,通信频道好,通信编号,仿真基准值,仿真系数。
例如:Dev103 Volt_A A相上的电压 1 6300 6600 5700 5400 1 1 001 001 5300 0.14
以下为读取设备信息的程序(Load_Analog_Data())代码:
bool Load_Analog_Data()//需要头文件fstream.h的支持
{
FILE *stream_Analog; //定义文件指针
fstream fs_Analog; //定义文件流
if( fopen_s(&stream_Analog, "Analog_data.txt", "r" ) != 0 ) 35kV变电站监控系统中告警事件生成与语音告警软件设计(10):http://www.751com.cn/zidonghua/lunwen_7940.html