本文提供了银行计算机网络报警系统触发控制的一种新方法 , 即外接报警开关 , 计算机内利用 COM 口监控报警开关状态 , 当报警开关被触发时计算机发出报警。
如今各银行通过计算机网络实现报警联动已经是很平常的事了 , 其报警触发方式较为常见的有两种 : 一是使用键盘 , 利用特殊键组合触发报警 二是在计算机内加上一块报警卡 , 外接报警开关 , 利用报警卡监测开关状态 , 当开关触动时触发报警。对这两种报警触发方式比较 , 报警卡方式要先进一些 , 当警况出现时 , 经常情况是歹徒强迫操作员举起双手 , 而一旦操作员双手被控 , 键盘方式将无法发出报警 , 但报警卡方式却仍可通过身体其他部位触动报警开关发出报警 , 因此 , 报警卡方式更为可靠。在日常应用中应优先选用报警卡方式。
但是 , 在报警卡方式中 , 报警卡要占用主板上一个卡槽 , 同时要占用一个中断及一个 I/O 地址 , 当计算机内插卡较多时容易与其他卡发生冲突 , 调整起来十分麻烦。那么 , 有没有其他的解决办法呢 ? 通过分析报警卡工作原理可以发现 , 在报警卡方式中报警卡并不是必需的 , 完全可以利用 COM 口实现报警卡的主要功能。
报警开关可用种类很多 , 特殊的如雷达深测式开关、红外感应式开关、脚踢式开关等 , 一般的普通开关也能用 , 但不管什么样的开关 , 在电路上其输出状态只有两种 : 通或断 , 逻辑上可定义其中一种状态为真、另一种为假。
" 接线盒 " 的功能就是将各 " 报警开关 " 并联起来 , 同时将各开关的合成状态通过其输出线传递给报警卡 , 是典型的多入一出设备。其输出逻辑为 :B=A1|A2|...|An, 式中 B 为 " 接线盒 " 的输出状态 ,A1 ~ An 为接在 " 接线盒 " 上各 " 报警开关 " 状态 , 定义报警态为真。
" 报警卡 " 主要的功能就是监控 " 接线盒 " 的输出状态 , 当 " 接线盒 " 输出为真时发出报警。由于 " 接线盒 " 在物理上的输出只有通、断两种 ," 报警卡 " 担负的任务是很简单的 , 可以通过对 COM 口的编程轻松地实现 " 报警卡 " 的主要功能。
本文提供了一个简单的模型 , 说明如下 :
模型中只有一个报警开关 ,COM 口通过信号线直接与报警开关连接 ," 信号线 " 使用普通的三芯双绞线即可 , 实际上只用到了其中的两根线芯 , 两根线芯的一端分别接在 COM 口的 2pin 和 3pin 上 , 另一端分别接在报警开关的两个输出端子上。 " 报警开关 " 用于操作员报警 , 本例中定义开关状态 " 通 " 为正常态、 " 断 " 为报警态 , 正常态定义为逻辑假、报警态定义为逻辑真 "COM 口 " 用于监控报警开关状态 , 这需要通过编程实现。
很显然 , 当报警开关为 " 通 ",COM 口的 2pin 和 3pin 也为联通状态 , 反之亦然。所以 , 程序中通过检测 COM 口 2pin 和 3pin 的通断状态即可判断报警开关的通断状态。
那么在程序中如何检测 COM 口 2pin 和 3pin 的通断状态呢 ? 我们知道 , 在 COM 口接口规范中 ,2pin 用于发送数据、 3pin 用于接收数据 , 因此我们可以定时从 2pin 发送数据 , 同时又从 3pin 接收数据 , 如果 3pin 能够接收到数据并且接收到的数据与 2pin 发送的数据一致 , 则可以判断 2pin 和 3pin 是联通的 , 反之则是断开的。另外 , 在 UNIX 系统中用户程序不能直接访问 COM 口 , 但可通过打开相应设备文件实现对 COM 口的间接访问。以 SCO UNIX 为例 , 设备文件 /dev/ttyla 指向的就是 COM 口 , 对 /dev/ttyla 的访问即是对 COM 口的访问 , 这一点在编程中需要注意。本文采用的是 C 语言 , 运行环境为 SCO UNIX Openserver 3.0 。
顾名思义 , 显示 /dev/ttyla 是终端设备 , 我们可以通过 UNIX 提供的多个 ioct1 ommands 系统调用对其进行控制 , 程序中需要用到的结构变量 termio 在 usr/include/sys/temio.h 头文件中定义。 termio 具体结构如下 :
#define NCC 8
struct termio {
unsigned short c_iflag; /* 输入模式 */
unsigned short c_oflag; /* 输出模式 */
unsigned short c_cflag; /* 模式控制 */
unsigned short c_1flag; /* 行律模式 */
char
c_1ine; /* 行律 */
unsigned char c_cc[NCC];/* 控制字 */
};
termio 的 ioct1 调用格式很多 , 下面只简要介绍程序用到的格式 :
ioct1(fildes,command,arg)
struct termio *arg;
其中 command 参数有下列可用值 :
TCGETA 获取终端当前参数并将返回值保存在参数 arg 中
TCSETA 立即将终端参改变为 arg 中的值
TCSETAW 等待终端输出队列为空后将终端参数改变为 arg 中的值。
TCSETAF 等待终端输出队列为空后 , 清空输入队列 , 同时将终端参数改变为 arg 中的值。
程序每隔 5 秒种向 COM 口 2pin 发送字符 "@", 同时从 3pin 读取字符 , 读取成功则认为 2pin 和 3pin 为联通态 ( 即正常态 ), 反之为断开态 ( 报警态 ) 。为正常态时程序在控制终端上显示 "Alarm is off", 为报警态时则显示 "Alarm is on" 。程序稍加改动后加上网络传输部分即可实现网络报警联动。
程序清单如下 :
#include
#include
#include
#include
#include
int AlarmPort=-1;
struct termio PortBuf;
char PortBXName[20]="/dev/ttyla";
void Alarm_d()
{
int flag,fork_ret=256;
charch;
signal(SIGALRM,Alarm_d);
if (!fork())
{ch="@";
flag=SEND_BYTE(AlarmPort,ch);
if (flag==0) exit(0);
else exit(1);
}
flag=RECEIVE_BYTE(AlarmPort.&ch);
if (flag==0 ‖ ch!="@") flag=0;
else flag=1;
wait(&fork_ret);
if (flag==0 ‖ fork_ret==0)
prinft("Alarm is on !\n");
else
prinft("Alarm is off !\n");
alarm(5);pause();
}
/* 打开并初始化端口 , 返回端口文件句柄 */
/* struct termio ComBuf: 保存端口参数用于关闭端口时恢复 */
int INIT_PORT(char *PortName,struct termio *
ComBuf)
{
int fp,i;
struct termio tbuf1;
if
((fp=open(PortName,O_RDWR|O_NDELAY))|<0){
prinft("\n can not open prot[%s]\n",PortName);
fflush(stderr);
return(-1);
}
ioct1(fp,TCGETA,ComBuf);
ioct1(fp,TCGETA,&tbuf1);
tbuf1.c_iflag=0;
tbuf1.c_oflag=0;&= ~ OPOST;
tbuf1.c_cflag=0;&= ~ (CBAUD|CSIZE|PARENB);
tbuf1.c_cflag=0;=tbuf1.c_cflag|(B9600|CS8|CREAD|CLOCAL);
tbuf1.c_1flag=0;&= ~ (ICANON|ISIG|ECHO);
tbuf1.c_cc[VMIN]=1;
tbuf1.c_cc[VTIME]=0;
ioct1(tp,TCSETAF,&tbuf1); /* 设置端口参数 */
return(fp);
}
/* 关闭端口并恢复端口原参数 */
int CLOSE_PORT(int ComPort,struct termio *ComBuf)
{
ioct1(ComPort,TCSETAF,ComBuf);
close(ComPort);
return(0);
}
/* 从端口接收一字节 , 最大等待时间 2 秒 */
int RECEIVE_BYTE(int ComPort,char *c)
{
int received;
time_t t1,t2;
longdiftiom;
t1=time(NULL);
do{
received=read(ComPort,c,1);
t2=time(NULL);
diftim=(long)difftime(t1,t2);
if (diftim<0) diftim=-diftim;
}while((received<1)&&(diftim<(long)2));
if (received<1)
received=0;
return(received);
}
/* 从端口发送一字节 , 最大等待时间 2 秒 */
int SEND_BYTE(int ComPort,char c)
{
int sent;
time_t t1,t2;
longdiftim;
t1=time(null);
do{
sent=write(ComPort,&c,1);
t2=time(NULL);
diftim=(long)difftime(t1,t2);
if (diftim<0)diftim=-diftim;
}while((sent<1)&&(diftim<(long)2));
if (sent<1)
sent=0;
return(sent);
}
/* 与端口连接 , 返回值 :0- 成功 1- 失败 */
int Connect(char *PortName)
{
if(AlarmPort<0){
AlarmPort=INIT_PORT(PortName,&PortBuf);
if (AlarmPort<0){
return(1);
}
}
return(0);
}
/* 与端口断开连接 */
voidDisConnect()
{
int flag;
if(AlarmPort>0){
CLOSE_PORT(AlarmPort,&PortBuf);
AlarmPort=-1;
}
return;
}
main()
{
charflag;
voidDisConnect();
flag=Connect(PortBXName);
if (flag!=0) {
printf("\nChecker connect failed!\n");
return(flag);
}
signal (SIGTERM,DisConnect);
Alarm_d();
}
| | |