资料名称 IF3报钟器C版公共接口程序(TXT文本方式)备驱动-有数量有匙牌
更新时间 2013-9-14 16:02:27
下载地址
http://pan.baidu.com/share/link?shareid=3158305806&uk=624116759
资料说明
刷卡报钟系统用到了2个接口程序,一个是我公司开发的底层接口程序:fst _sn_card_data.exe,他负责完成和室内刷卡器的底层接口,(下称公共接口程序,窗口标题是“桑拿刷卡器公共接口”),一个是合作软件公司依据自己软件开发的上层接口程序,(下称私有接口程序,窗口标题是“桑拿数据处理程序”)。
公共接口程序完成了对刷卡器发来数据的解包,并以文本文件“接口.TXT”保存信息内容,然后向私有接口程序,也就是窗口标题是“桑拿数据处理程序”的程序发送一条标号是1088的通知消息,然后一直等待。私有接口程序收到这个通知消息后,打开“接口.TXT”文件,依据其中内容,完成对应的操作,比如技师起钟等,然后将操作结果,写会“接口.TXT”文件,并向公共接口程序发送一条标号是1088,lParam是2的通知消息。公共接口程序收到该通知消息后,从“接口.txt”里提取返回信息,然后返回给室内刷卡器,并删除“接口.TXT”文件。
工作流程图如下:                    
 
 
 
 
 
 
 
 
 
 
1、编写私有接口程序需要做的是:
a)    不停检测是否收到1088号消息,如果收到,就打开“接口.TXT”文件。
b)    从“接口.TXT”文件读取数据,然后按照要求执行对应的操作,然后将返回结果,增加到这个文件的尾部。
c)    保存“接口.TXT”文件,退出对这个文件的占用。
d)    向“桑拿刷卡器公共接口”程序,也就是fst _sn_card_data.exe发送编号是1088的系统消息,并且消息的lParam参数是2,就可以了。
2、“接口.TXT”文件文件结构
例子格式如下:
串口号:1
设备号:1
命令内容:安排技师-撤钟;客人卡号:0000106496;部长卡号:0000106496
其中第一行是:串口号:1
第二行是:设备号:1
在实际施工中,通过串口扩展卡,一个PCI插槽可以扩展8个串口,每个串口最多可以连接32个房间。
客户应该在自己的系统中建立房间与串口号和设备号的对应关系。
这样通过串口号,和设备号,软件就可以得到是哪个房间发送的信息了。
第三行是:命令内容:
不同的命令,内容格式不一样。
3、命令内容的详细格式:
1、  起钟:
命令内容:起钟;技师卡号:0008712735
2、  加钟:
命令内容:加钟;技师卡号:0008712735
3、  出钟:
命令内容:出钟;技师卡号:0008712735
4、  应钟:
命令内容:应钟;技师卡号:0008712735
等等
例如:催钟的实现方法:
刷卡器操作命令是由刷卡器操作,向电脑发送操作命令,公共接口程序接收生成“接口.TXT”文件,私有接口程序处理数据,然后返回操作结果给公共接口程序,公共接口程序发送给刷卡器。
文件内容如下:
格式一、
串口号:1
设备号:1
催钟:004,005
这样,报钟器就会发出“技师004 005已经到钟”的声音
格式二、
串口号:1
设备号:1
催钟[5]:004,005
这样,报钟器就会发出“技师004 005 5分钟以后到钟”的声音
5、私有接口程序可以向“接口.TXT”写入的信息:
1、 起钟:
语音提示,请刷技师卡,
操作回复:
A、  起钟成功
B、  房间错误
C、  钟房没有安排
D、  已经起钟
E、  技师卡错误
完成技师开始计钟的功能,具体的操作流程按程序设计的不同而不同,详见设备实际操作菜单。
2、 加钟:
语音提示,请刷技师卡
操作回复:
A、  加钟成功
B、  房间错误
C、  没有起钟
D、  技师卡错误
完成客人对技师的续钟要求。
3、  出钟:
语音提示,请刷技师卡,
操作回复:
A、  出钟成功
B、  房间错误
C、  没有起钟
D、  技师卡错误
结束技师的上钟,并生成客人消费记录和技师的提成记录。
4、  应钟:
语音提示,请刷技师卡,
操作回复;
A、  应钟成功
B、  钟房没有安排
C、  技师卡错误
对技师安排以后,技师进行响应。
5、  服务:
语音提示,服务代码--请刷技师卡,
操作恢复:
A、  服务成功
B、  房间错误
C、  没有起钟
D、  技师卡错误
向服务台发送需要指定服务的求助信息。比如送免费饮料等。
6、  小费,
语音提示:金额---请刷技师卡
操作回复
A、  小费成功
B、  没有上钟
C、  技师卡错误
技师自行录入消费,可以防止小费跑单。
7、  商品,
语音提示:商品编号---请刷技师卡
操作回复:
A、  商品成功
B、  没有上钟
C、  技师卡错误
D、  商品编号错误
在上钟过程中,客人的消费录入,可以打印单据到吧台等地方,并记录技师的提成信息。
服务员[部长]功能界面操作:包括轮钟、点钟、括钟、选钟和撤消对技师安排,并把信息通过打印机、语音、显示屏幕、电脑显示屏来通知给技师房。
8、  轮钟
语音提示:模式编号---技师编号—请刷客人卡
操作回复
A、  101号技师安排成功
B、  该技师不是排钟状态
C、  部长卡错误
D、  模式错误
E、  客人卡错误
9、  点钟
语音提示:模式编号---技师编号—请刷客人卡
操作回复:
A、  101号技师安排成功
B、  该技师不是排钟状态
C、  部长卡错误
D、  模式编号错误
E、  客人卡错误
10、括钟
语音提示:模式编号---技师编号—请刷客人卡
操作回复:
A、  101号技师安排成功
B、  该技师不是排钟状态
C、  部长卡错误
D、  模式编号错误
E、  客人卡错误
11、选种
语音提示:模式编号---技师编号—请刷客人卡
操作回复:
A、  101号技师安排成功
B、  该技师不是排钟状态
C、  部长卡错误
D、  模式编号错误
E、  客人卡错误
12、撤钟
语音提示:请刷客人卡
操作回复:
A、  撤钟成功
B、  没有安排
C、  客人卡错误
D、  部长卡错误
13、退技师
语音提示:请刷客人卡
操作回复
A、  退技师成功
B、  没有安排
C、  客人卡错误
D、  部长卡错误
14、换房间
语音提示:请刷客人卡
操作回复:
A、  换房间成功
B、  客人卡错误
C、  部长卡错误
15、换模式
语音提示:模式编号,请刷客人卡
操作回复
A、  换模式成功,当前模式101
B、  客人卡错误
C、  部长卡错误
D、  模式号错误
E、  没有安排技师
16、商品
语音提示:商品编号---请刷客人卡
操作回复:
A、  商品成功
B、  客人卡错误
C、  部长卡错误
D、  商品编号错误
给客人录入商品消费,并自动打印单据到吧台等地方
*、赠送
语音提示:商品编号---请刷客人卡
操作回复:
E、  商品成功
F、  客人卡错误
G、  部长卡错误
H、  商品编号错误
赠送客人的商品消费录入,并自动打印单据到吧台等地方。
0、  询技师排钟
语音提示:技师类别编号
操作恢复:
               i.      101 102
              ii.      技师类别编号错误
            iii.      部长卡错误
11、  查询技师
语音提示:技师编号---请刷客人卡
操作恢复:
I、  101号技师,203房间,模式101,5分钟后出钟
J、  部长卡错误
K、  技师编号错误
17、买单
语音提示:请刷客人卡
操作恢复:
A、  当前消费金额50元
语音:是否结帐?---人民币结还是贵宾卡结帐
B、  结帐成功
6、私有接口程序可以向“接口.TXT”本接口可以接受的返回消息是固定的,可以接收以下消息:
起钟成功
加钟成功
小费成功
错误技师卡
已经起钟
房间错误
出钟成功
应钟成功
服务成功
没有起钟
错误部长卡
错误客人卡
错误模式编号
错误商品编号
错误技师编号
排钟成功
点钟成功
选钟成功
括钟成功
撤钟成功
退技师成功
更换房间成功
商品成功
赠送成功
错误技师类别
二、通信协议:
a)    从刷卡器到PC的数据传输协议:
[0x24头字节][设备号][0x33命令字节][数据长度][数据,长度=命令长度字节][校验位,从第2位到数据加总][0x2A尾部][发送次数]
b)    从PC到刷卡器的数据传输协议:
[0x24][设备号][0x22 命令字节][数据长度][数据][校验位][0x2A结尾]
三、设备的地址码设置
设备“编号房号拨码开关”在设备正上方“地址”字符位置。设备安装前,根据每个房间的编号,设置对应的设备地址码。设备的地址码开关排列如下图:
开关位号
1
2
3
4
5
地址码
1
2
4
8
16
 
 
 
拨码开关的地址码定义如上表(地址码拨到OFF有效
拨码开关方式:采用地址码累加方式定义,全部拨到“ON”为“0”号地址,全部拨到“OFF”状态为“31”号设备。例如:如要设置设备为18号,设置方式:把拨码开关第2位和第5位拨到OFF状态,第1、3、4位拨到ON状态即可。设备重新设置地址码后,必须重新上电或复位后才生效。
 
四、接口程序中“配置文件.ini”的设置
1、打开接口程序文件夹中的“配置文件.ini”,找到
波特率=
正确修改波特率。比如电脑直接接第三代、第四代报钟器,应该设置成:
波特率=2400
保存该文件。
2、  打开接口程序文件夹中的“配置文件.ini”,找到
串口端口=
检查连接设备的串口号,如果使用COM1进行和报钟器通信,则设置成:
串口端口= 1
如果有多个串口同时工作,比如COM3,COM4,COM5,则设置成:
串口端口= 3,4,5
3、  检查当前电脑已经使用了的端口:
在【开始】--【运行】中录入CMD命令,进入命令操作窗口,执行NETSTAT –AN
红色部分是你的电脑已经占用了的端口,然后从6000开始找可以使用的端口,比如当前6003,6004是可以使用的。
4、  打开接口程序文件夹中的“配置文件.ini”,找到并设置成
接口程序端口=6003
工作程序端口=6004
5、  将我公司提供的例子程序,编译,生成可执行文件sn_lcdcard.exe,切记,文件名必须不能改变,而且不能直接运行它。
6、  将该文件sn_lcdcard.exe拷贝到接口程序目录中,然后运行fst_sn_card_data.exe,你可以系统初始化了你设置的端口,然后看到刚才编译后生成的sn_lcdcard.exe自动运行了起来。通过双击WINDOWS托盘区的【桑拿刷卡器公共接口】图标,可以打开程序界面,如果看到有初次握手字样,表示,您刚才的设置时正确的,而且例子接口程序已经基本可以工作了。
7、  试着操作报钟器的起钟命令,看看可否工作。
【经验之谈】:
当有多个串口同时工作,建议每个fst_sn_card_data.exe只负责一个串口的数据传输。比如有4个串口工作,分别是1、2、3、4,那么可以建立4个文件夹,每个文件夹通过修改配置文件的
串口端口=
接口程序端口=6000
工作程序端口=6001
工作程序名称=sn_lcdcard.exe
要确保每个文件夹中的端口互相不同,工作程序名称也不能相同。
可以把端口号按6000~6007排列。
五、第三方软件公司的接口开发方法
(一) 、客户写一个软件,名字是sn_lcdcard.exe。
(二) 、在主工作窗口放置winsock控件,命名OLE_1。
(三) 、在窗口打开的时候设置OLE_1的如下属性:
protocol=1             采用UDP方式连接
remotehost='127.0.0.1'    本地电脑通信
localport=6001          本程序使用6001端口
remoteport=6000         接口程序使用6000端口
bind()                  绑定网络协议
senddata("初次握手")     向接口程序发送握手信息
1、            在WINSOCK控件的dataarrive事件中,通过getdata函数得到从接口程序中传输来的内容,进行处理。具体命令内容可以在接口程序界面中看到,也可以从程序路径的data文件夹下,找到,基本格式如下。
串口号-设备号-命令序号-命令内容
比如:
1-31-0-命令内容:起钟;上钟方式:;模式编号:11;技师卡号:0010144830;客人卡号:0010144830
表示COM1上的设备31,第0次发送命令,要求起钟。
上钟方式没有指定。模式编号是11,卡号是0010144830的技师,要给匙牌号是0010144830的客人服务。
以上内容可以通过跟踪获得,也可以从接口程序的data文件夹下的跟踪记录中获得。
经过对上述命令进行处理,然后将操作结果按以下格式通过WINSOCK控件的senddata函数返回:串口号:N;设备号:N;返回内容
3、私有接口程序向“公共接口程序”发送数据的方法:
由于私有接口程序可能是由不同的语言编写的,所以方法会有一定差异。
例如VB:
首先定义以下外部函数:
Public Declare Function PostMessage& Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any)
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
然后使用使用FindWindowA函数先找到公共接口程序窗口的指针,然后调用PostMessage来发送信息。
DEPHI:
使用函数PostMessage()来发送信息
例如 PB
先定义外部函数:
FUNCTION ulong FindWindowA(ulong classname,string windowname) LIBRARY "user32.dll"
recheck:
wHandle = FindWindowA(0, "桑拿刷卡器公共接口")
if wHandle > 0 then//程序已经运行
     send(wHandle,1088,0,2)//
else
     goto recheck
end if
5、PB例子代码
在窗口的OTHER事件中
string handerrorkf,iszd='N'//是否主动发送
long sc,i,czjg
string stype,cznr,jg
long lastxh,whandle
 
if message.number <> 1088 then return
st_1.text=string(now())+"得到数据"+string(message.LongParm)
st_1.setredraw(true)
long filenum
string ss
long commno//串口号
long devno//设备号
long commxh//命令序号
string s_mlnr //命令内容
string mlkey,mldata
filenum=fileopen("接口.txt",linemode!,read!)
//读入串口号:
fileread(filenum,ss)
commno=long(mid(ss,8))
//设备号
fileread(filenum,ss)
devno=long(mid(ss,8))
//命令内容
fileread(filenum,ss)
fileclose(filenum)
 
s_mlnr=mid(ss,10)
mlkey=left(s_mlnr,pos(s_mlnr,';') - 1)
 
mldata=mid(s_mlnr,pos(s_mlnr,';') + 1)
string kfname
select kfname into :kfname from n_kf where sbno=:devno and comm=:commno;
string cardno
choose case mlkey
     case '起钟'
         cardno=right(mldata,10)
         wf_qz(cardno,kfname,commxh)
     case '加钟'
         cardno=right(mldata,10)
         wf_jz_js(cardno,kfname,commxh)
     case '出钟'
         cardno=right(mldata,10)
         wf_czok(cardno,kfname,commxh)
     case '应钟'
         cardno=right(mldata,10)
         wf_outroom(cardno,kfname,commxh)
     case '服务'
         wf_server(kfname,commxh,mldata)
     case '小费'
         wf_xf_enter(kfname,commxh,mldata)
     case '安排技师-排钟'
         wf_needjs(kfname,commxh,mldata,'排钟')
     case '安排技师-点钟'
         wf_needjs(kfname,commxh,mldata,'点钟')
     case '安排技师-选钟'
         wf_needjs(kfname,commxh,mldata,'选钟')
     case '安排技师-括钟'
         wf_needjs(kfname,commxh,mldata,'括钟')
     case '安排技师-撤钟'
         wf_needjs_cancel(kfname,commxh,mldata)
     case '退技师'
         wf_change_js(kfname,commxh,mldata)
     case '更换房间'
         wf_change_room(kfname,commxh,mldata)
     case '更换模式'
         wf_change_ms(kfname,commxh,mldata)
     case '技师商品'
         wf_shop(kfname,commxh,mldata,'=')
     case '部长商品'
         wf_shop(kfname,commxh,mldata,'N')
     case '赠送商品'
         wf_shop(kfname,commxh,mldata,'Y')
     case '结帐查询'
         wf_select_money(kfname,commxh,mldata)
     case '查询技师排钟'
         wf_select_jspz(kfname,commxh,mldata)
     case '查询技师状态'
         wf_select_jsstate(kfname,commxh,mldata)
end choose
//over: