龙海儿
关注《电气外传》公众号,知乎,CSDN等同号
级别: 论坛先锋
精华主题: 0
发帖数量: 369 个
工控威望: 1392 点
下载积分: 914 分
在线时间: 104(小时)
注册时间: 2018-04-13
最后登录: 2025-11-23
查看龙海儿的 主题 / 回贴
楼主  发表于: 2025-07-02 12:35
图片:
图片:
图片:
图片:
图片:
1111MicrosoftInternetExplorer402DocumentNotSpecified7.8 磅Normal0如题,声音报警我们用的很多,但是如何实现差异化的语音报警呢?直接先看图看效果。
那语音报警都好理解,差异化又具体体现在哪里呢?
因为市面上已经有前辈开发出了语音报警,但是不能灵活单独的应用到每一条报警上面。比如我只想要一条或者两条重要信息实现语音播报,其它报警静默显示就行。那么通过本例可轻松解决。
特别说明!开发不易,本例所用脚本原件放在文章末尾,小额支持即可下载!感谢理解,欢迎交流。
第一步,打开WinCC创建内部变量(alarmComing)二进制类型与(alarmText)(prevAlarmText1)(prevAlarmText2)三个16位文本类型。(如需要多个报警可多建立两个Text变量)
第二步,用Win+r输入services.msc然后找到Windows Audio服务,启动它(一般都启动着)。
第三步,把gmsgfunc.fct脚本放到C:\Program Files (x86)\SIEMENS\WinCC\aplib\Alarm中替换掉以前的。
第四步,把Voice脚本vbs放到wincc项目ScriptAct文件夹中。
第五步,打开报警记录找到想要播报的变量勾选属性里面触发动作如图(不勾选的变量不会播报)。
通过以上操作就可以实现单独变量的声音报警,其它变量依然按照普通设置呈现。如果想触发报警之后一直播报,直到人员点击消音按钮才消失。那请看之下进阶操作。
将刚才第二步的Voice替换成cycle脚本(注意一定要替换,不可以都保留),然后在报警控件中将事件里面的OnToolbarButtonClicked属性加上记事本中的c脚本用于取消循环,也可以自己外加按钮来实现。
记得拷贝进去的每个脚本都打开再次保存一下,否则可能不能发声。以下是本例用到的脚本,各位也可以再次优化脚本生成更多功能。
更过截图和脚本链接请移步同名公众号查看

关注《电气外传》公众号,知乎,CSDN等同号
往事如风
科技改变制造
级别: 网络英雄

精华主题: 0
发帖数量: 11980 个
工控威望: 19775 点
下载积分: 15375 分
在线时间: 2835(小时)
注册时间: 2013-01-31
最后登录: 2025-12-14
查看往事如风的 主题 / 回贴
1楼  发表于: 2025-07-05 20:50
  
三人行者必有我师 ,择其善者而从之
hqokabc
级别: 正式会员
精华主题: 0
发帖数量: 72 个
工控威望: 82 点
下载积分: 419 分
在线时间: 6(小时)
注册时间: 2025-01-02
最后登录: 2025-12-14
查看hqokabc的 主题 / 回贴
2楼  发表于: 前天
全局脚本怎么写?
qwerty_123
www
级别: 略有小成
精华主题: 0
发帖数量: 159 个
工控威望: 284 点
下载积分: 5878 分
在线时间: 51(小时)
注册时间: 2010-09-26
最后登录: 2025-12-14
查看qwerty_123的 主题 / 回贴
3楼  发表于: 昨天
//wincc声音报警C脚本版,和wincc自身的报警没有任何关系,所以不要和wincc自带的报警相关联
//曾经用于工程中的语音报警,事先将语音先录好,然后将变量和语音关联起来

#include "apdefap.h"


//播放声音的函数声明
#pragma code("winmm.dll")
VOID WINAPI PlaySoundA(char *,char *,DWORD);
#pragma code()

struct datainfo    //变量名和声音文件名的对应关系
{
    const char * const tagname;    //变量名
    const char * const soundname;    //声音文件名
};
struct statusdatainfo        //保存报警变量的状态信息
{
    int prevStatus;
    int playing;
};
//所有的报警变量和声音文件名对应关系表
//注意:变量名和文件名要和实际的变量名、文件名完全一致
//注意:声音文件只支持wav文件
//注意:变量越靠前,则优先级越高,在同时发生多个报警时,优先级最高的声音优先播放,而且任一时刻只能播放一个声音
static struct datainfo data[]=  
{
{"www","Windows XP 启动.wav"},    
{"testalarm","ringin.wav"},
{"qqq","Windows XP 关机.wav"},
{"eee","Windows XP 注销音.wav"}
};

static struct statusdatainfo  statusdata[sizeof(data)/sizeof(data[0])];
////////////////////////////////////

int gscAction( void )
{
int totalnum=0;    //总的报警变量数量,也等于总的报警声音数量
int index=0;    //循环变量
int hasfound=0;    //已找到优先级最高的报警变量
char * filename=NULL;    //当前要播放声音的文件名
char * dirname="D:\\WINDOWS\\Media\\";    //声音文件存放的目录
static char * currfilename=NULL;    //当前正在播放声音的文件名,注意:该变量是静态变量
static char  FullName[200];    //当前正在播放声音的文件全名,注意:文件名全名不能太长,该变量是静态变量
char * ack_name="ack"; //报警确认变量的名字,一次只能确认优先级最高的报警
int ack_status=0;    //当前确认变量的状态

totalnum=sizeof(data)/sizeof(struct datainfo);    //报警变量的数量
ack_status=GetTagBit(ack_name);

for(index=0;index<totalnum;index++)    //查找当前第一个报警的变量所对应的声音文件名,搜索的顺序决定了优先级
{
    if (statusdata[index].playing)
    {
        statusdata[index].prevStatus=GetTagBit(data[index].tagname);
        if (ack_status)    //确认报警变量
        {
            ack_status=0;
            statusdata[index].playing=0;
        }
        else
        {  
            if (0==hasfound)
            {
                hasfound=1;
                filename=data[index].soundname;
            }
        }
    }
    else
    {
        statusdata[index].playing=!statusdata[index].prevStatus && GetTagBit(data[index].tagname);
        statusdata[index].prevStatus=GetTagBit(data[index].tagname);
        if (statusdata[index].playing)
        {
            if(0==hasfound)
            {
                filename=data[index].soundname;
                hasfound=1;
            }
        }  
    }
}

SetTagBit(ack_name,0);  

if (filename!=currfilename)    //当要播放的声音文件和当前正在播放的声音文件不同时才播放新的声音
{
    currfilename=filename;        //修改当前正在播放的声音文件名
  
    if (NULL==currfilename)    //如果没有报警则停止播放声音
    {
        FullName[0]=0x0;
        PlaySoundA(NULL,NULL,0x2000|1|8);        //停止播放声音
    }  
    else    //循环播放新的声音文件
    {
        strcpy(FullName,dirname);        //复制目录名
        strcat(FullName,currfilename);        //合成声音文件全名
        PlaySoundA(FullName,NULL,0x2000|1|8);    //播放声音
    }  
}

return 0;


}