计算机电信集成技术第5章.ppt
计算机电信集成(计算机电信集成(CTI)技术)技术Computer Telecommunications Integration technology 网络工程与技术系College of Telecommunications&Information EngineeringNanjing University of Posts&Telecommunications1 1CH5 CTI系统软件开发平台数据库系统SQLODBC编程接口基于东进语音卡API的呼叫中心软件开发平台2 25.1.2 数据库系统数据库(DataBase)DBn指按一定组织方式存储在一起相互有关的若干个数据的组合。n数据库就是信息的仓库,它由一个表或多个表组成。n表(Table)也是一种数据库对象,它是由具有相同属性的记录(Record)组成的,记录是由一组相关的字段(Field)组成的,字段用来存储与表属性相关的值。3 35.1.2 数据库系统数据库管理系统(DataBase Management System)DBMSn是一种操纵和管理数据库的大型软件。n建立在操作系统的基础上,对数据库进行统一的管理和控制。n功能:数据库定义数据库管理数据库建立和维护与操作系统通信等基本功能。nDBMS通常由数据字典数据描述语言编译程序数据操作(查询)语言数据库例行程序等组成。n FoxproSQL ServerOracle4 45.1.2 数据库系统n按DBMS对数据的组织形式,一般可以分为:网状结构(Network)层次结构(Hierarchical)关系结构(Relational)面向对象的结构(object oriented)n通常使用的数据库系统基本上都是关系数据库。5 5关系型数据库n二维数据表称为关系,关系模型有如下特点:数据结构单一。在关系模型中,不管是实体还是实体之间的联系,都用关系来表示,而关系对应着每一张二维数据表,因此数据结构简单而清晰。利用公共属性连接,不同关系(二维表)之间是通过公共属性发生联系的。比如通过主关键字或关键字相对应,并可以通过不同表之间的联系延伸到所有相关表。严格的理论基础。二维表的数学基础是关系数据理论,对二维表进行的数据操作相当于关系理论中对关系进行运算。语言简练,操作简单。6 6SQL Server数据库基本概念n常用的关系型数据库分为:桌面型数据库(DeskTop)nAccess,FoxPro,dBASEn只能在本机系统使用,无法实现数据库系统的双备份或主冗备份。一旦运行的数据库软件损坏,数据库信息同样丢失。n主要使用于一些简单的CTI数据库或安全性要求不高的场所。客户/服务器型数据库(Client/Server)nSQL Server,Oracle,Sybasen可实现网络数据库,完成应用程序和后台数据库的分离,从而实现数据库的主冗备份。n数据库系统本身有很多强大的功能。如存储过程(Store Procedure),可简化应用程序的操作。nSQL Server适合于中型的CTI系统,Oracle适合于大型、电信级的分布式网络数据库。7 7SQL Server数据库基本概念n在SQL Server数据库中,通常将表格(Table)、视图(View)、存储过程(Store Procedure)、触发器(Trigger)及索引(Index)等具体存储结构或对数据库进行操作的实体都称为数据库对象。nSQL Server数据库也被称为容纳以上这些数据库对象的容器(Container)。8 8SQL Server数据库基本概念n表(Table)n由行(Row)和列(Column)组成,是具体组织和存储数据的对象,行和列的次序都可以任意排序。n在数据库容器内,不同的表的名字必须唯一,每一张表的列名必须唯一。n表内包含着数据的多种属性。序号序号姓名姓名年年龄龄职职位位1 1Wang Wang lanlan2626engineerengineer2 2Li Li xiaoxiao pengpeng2525officerofficer3 3Chen Chen yiyi bingbing 2121ChefChef9 9SQL Server数据库基本概念n字段(Field)与数据类型(Data Type)n字段是标记实体属性的符号集。n数据库表中的每一列称为字段。n表是由其中包含的各种字段定义的,每个字段描述了所包含的数据。n数据类型:int,char,date序号序号姓名姓名年年龄龄职职位位1 1Wang Wang lanlan2626engineerengineer2 2Li Li xiaoxiao pengpeng2525officerofficer3 3Chen Chen yiyi bingbing 2121ChefChef1010SQL Server数据库基本概念n记录(Record)n表的每一行数据被称为一个记录。n是存放具体相关数据的有序集。n可以对数据记录进行正向、反向的排序。序号序号姓名姓名年年龄龄职职位位1 1Wang Wang lanlan2626engineerengineer2 2Li Li xiaoxiao pengpeng2525officerofficer3 3Chen Chen yiyi bingbing 2121ChefChef1111SQL Server数据库基本概念n主键PK(Primary Key)在每一张表中,作为主键的字段内容 必须是唯一的、各不相同的,它的值必须唯一标识了表中的一行记录。如果在SQL Server 数据库操作中,使用Insert命令插入了相同主键的记录,一定会导致操作错误。n外键(Foreign Key)外键也是一列或多列的组合,它存在与表中,但不是该表的主键;但它也存在于另一张表中,是另一张表的主键,外键体现了不同表之间的密切的对应的联系。在进行索引查找的时候,外键起着重要的作用。序号序号姓名姓名年年龄龄职职位位1 1Wang Wang lanlan2626engineerengineer2 2Li Li xiaoxiao pengpeng2525officerofficer3 3Chen Chen yiyi bingbing 2121ChefChef1212SQL Server数据库基本概念n索引(Index)索引的主要用途是提供一种无须扫描整张表就能实现对数据快速访问的途径。可以通过主键(PK)对表中的记录进行分类,可以开辟一个专门存放索引的存储区,索引中列出全部主键字值及其相应的记录的地址。n存储过程(Store Procedure)存储过程是一种经过编译的可以重复使用的Transact-SQL代码的组合。存储过程在服务器端执行,用户可以调用存储过程,可以接收存储过程返回的结果。n触发器(Trigger)触发器是一种特殊的存储过程,触发器与表格的操作属性相关联,当用户在对指定的表进行了某些操作后,如Insert,Delete,及Update等操作时,触发器会自动执行,从而也减轻了应用软件的多SQL语句操作,尤其是应用软件采用TCP/IP协议远程操作网络数据库时,会占用大量的网络资源。1313SQL Server数据库基本语法nSQL:Structured Query Languagen结构化查询语言 n是一种关系数据库查询语言,它告诉数据库获取这个数据。nSQL着重做什么而不是如何做。n例如,SQL描述的是获取、删除或插入什么样的数据,而非如何执行这个操作。n常规的SQL命令包括有:Create,Drop,Select,Insert,Update,Delete。1414SQL Server数据库基本语法创建表格 使用存储过程Use Company数据库GoCreate Table Employee 建表(id numberic(10,0)IDENTITY PK,name varchar(20)not null,age numberic(10,0),address varchar(50)mobile varchar(50)others varchar(200)Goidnameageaddress mobile others1515SQL Server数据库基本语法ncreate命令用来建立一个表create table t_student1(t_name text(10)not null,t_number text(10),t_class text(10),t_sex text(10),t_phone text(10),t_minzu text(10),t_jiguan text(10),t_score short)nDrop命令用来删除一个表Drop Table CompanynSelect命令用来查询带有附件条件的数据记录Select*from Company;Select name from Company Where age=40;nInsert命令用来新增一条数据记录Insert Into Company(name,age,address,mobile)Values(Linda,23,模范马路66,18902523456);nUpdate命令用来更新一个能够被定位的数据记录的某个字段的内容Update Company Set age=30 Where name=Linda;nDelete命令用来删除一条能够被定位的数据记录Delete From Company Where name=Linda;1616ODBC编程接口nODBC:Open Database Connectivityn开放式数据库互连开放式数据库互连n是用于访问数据库的统一界面标准。是用于访问数据库的统一界面标准。n它包含一组可扩展的动态链接库,提供了一个标准的数据它包含一组可扩展的动态链接库,提供了一个标准的数据库应用的程序设计接口,可以通过它编写对数据库进行增库应用的程序设计接口,可以通过它编写对数据库进行增删删改改查和维护等操作的应用程序。查和维护等操作的应用程序。n是一种用来在相关或不相关的数据库管理系统(是一种用来在相关或不相关的数据库管理系统(DBMS)中存取数据的标准应用程序接口(中存取数据的标准应用程序接口(API)。)。n在在ODBC的的DLL(Dynamic Link Library,动态链接,动态链接库)库)之下安装不同数据库的驱动程序,开发人员可以访问之下安装不同数据库的驱动程序,开发人员可以访问不同的数据库资源。不同的数据库资源。1717ODBC编程接口n由于ODBC是基于关系数据库的结构化查询语言SQL而设计的,在ODBC层之上的应用程序看来,各个异构关系数据库只是相当于几个不同的数据源,而这些数据源的组织结构之不同对于程序员来说是透明的,因此就可以编写独立于数据库的访问程序。n大多数的数据库在进行设计时都遵守SQL标准,这使应用可以利用SQL标准对不同的数据源进行操作。n可以发出SQL命令,由ODBC发给数据库,数据库再将结果经过ODBC返回给应用程序。1818ODBC接口1919ODBC编程接口建立数据源n开始/控制面板/性能维护/管理工具/数据源(ODBC配置)n用户DSN添加创建新数据源SQL Server名称:callcenter数据库关联服务器:安装SQL Server的电脑的IP地址登录ID:sa密码:1234562020ODBC编程接口编程进行数据库操作n对于一个已经配置好的数据源,用户只要对数据源名进行操作就可以了。n在同力中间件IVR开发平台中,使用如下命令 Connect Database dsn=callcenter;uid=sa;pwd=123456n或者在VC+6.0中采用如下SQL命令CString CMyRecordset:GetDefaultConnect()Return_T(“ODBC;DSN=callcenter,uid=sa,pwd=123456”);21215.2 基于东进语音卡API的呼叫中心软件开发平台 nCTI应用软件编程接口(应用软件编程接口(API)标准厂家众多:Microsoft公司的APINetware和AT&T公司制定的TSAPINT、Sun的JTAPIn由ECTF提出的S.100和Microsoft 公司的TAPI由于与Windows系统的捆绑而成为应用开发人员的主流主流。n由于历史的原因,Netware的TSAPI也将继续获得强大的支持。2222基于东进语音卡的业务平台n在呼叫中心的设计中,使用Delphi6和Microsoft Vc+做为开发语言,充分利用了Delphi6对多层数据库模式和分布式系统的强有力支持和VC+与Windows系统的无缝结合的特点。23235.2.1 基于东进语音卡的业务平台 PSTN1 234 567 89*8#CTI 中间件局域网交换机坐席 PC班长 PCCTI 服务器客户服务系统行情服务器数据监控服务器Internet基于语音卡的呼叫中心结构2424基于东进语音卡的业务平台主要组件及功能介绍:nCTI服务器服务器:或称为:模拟交换机功能:n资源管理nACD(Auto Calling Distribution,自动话务分配)n IVR(Interactive Voice Response-交互式语音应答)nTTS(Text To Speech)nFAX功能描述:n对客户呼叫进行预处理,根据呼叫类别对呼叫进行语音应答、排队和呼叫路由,对呼叫的深层处理由CTI中间件(或流程控制模块)进行。2525基于东进语音卡的业务平台nCTI中间件:中间件:又称为流程控制模块流程控制模块功能:呼叫管理和数据路由呼叫管理和数据路由功能描述:n对呼叫进行深层处理,控制数据的流向,将客户的请求/数据处理后交由CTI服务器进行TTS处理,返回客户呼叫连接;nCTI业务、语音中间件:业务、语音中间件:功能:处理呼叫业务和语音合成等中间业务处理呼叫业务和语音合成等中间业务在本案例中其功能由CTI服务器和CTI中间件完成。2626基于东进语音卡的业务平台n人工坐席:功能:n实现人工服务和投诉功能描述:n可以接受客户的业务请求,进行人工应答。坐席管理对坐席的业务量进行统计、管理;n电话、传真:客户可以使用电话和传真经电话网进行呼叫n数据库系统(DBMS):提供业务数据支持,为呼叫中心提供强大的数据支持2727基于东进语音卡的业务平台n客户服务系统:进行客户的服务登记、管理。该部分可以将客户的服务类别进行登记,为邮件服务和手机短信息做好数据登记和管理,属于后台支持系统;n行情服务器:为整个系统提供行情支持;(本例是股票证券交易公司的业务平台)n数据监控服务器:为邮件服务和手机短信服务项目服务,通过局域网交换机到路由器进入Internet。28285.2.2 业务软件流程设计 n软件的流程设计软件的流程设计在整个系统构建中有着举足轻重的作用,流程设计的合理与否,直接影响到呼叫中心业务处理路径的长短,决定着呼叫中心项目最后的成败。29295.2.2 业务软件流程设计30305.2.2 业务软件流程设计n在直接面向PSTN的CTI服务器中,板卡可以采用深圳东进公司系列板卡,例如:一号信令数字中继卡 (D320/640)传真卡模拟接口语音处理卡(D161A PCI 16U)卡件之间用CTI-BUS总线连接,共同完成多路呼叫,传真资源,和用户坐席系统功能。31315.2.3 软件流程设计 CTI服务器逻辑结构在整个CTI服务器前台软件平台中,可以采用VC+开发,东进D系列(DN系列)板卡也提供了大量丰富的API函数,主要实现了电话软件交换机的功能,对系统资源进行管理,包括数字语音卡、传真卡、模拟坐席卡的开发,ACD算法的改进以及TTS实现等。IVR:Interactive Voice Response,交互式语音应答,交互式语音应答TTS:Text to Speech,文本到语音,文本到语音ACD:Auto Calling Distribution,自动呼叫分配,自动呼叫分配3232CTI服务器逻辑结构nCTI服务器软件包括:ACD、IVR、Agent、DBMS等逻辑单元。n当客户以某种方式呼入时,CTI服务器对其呼入业务进行预处理,根据其业务类别将呼入路由到不同的方向:CTI中间件和坐席、传真、业务查询等处理单元,最后进入业务中间件进行统一处理。3333主要组件程序设计 nCTI服务器程序设计服务器程序设计 由于CTI服务器在整个呼叫中心起着核心的资源管理、呼叫路由等作用,所以在CTI服务器软件设计中特别注意了应用软件应用软件与操作系统操作系统的无缝结合,采用VC+进行程序编写,保证系统运行的可靠性。n数字语音板卡的编程数字语音板卡的编程 对于对于CTI服务器的软件设计就是对语音板卡的开发编程服务器的软件设计就是对语音板卡的开发编程的过程的过程,CTI服务程序不仅能够对系统进行管理,同时要对语音板卡的资源进行调配。语音板卡的编程主要包括:n语音板卡的初始化处理n语音板卡的中继线路的参数配置(输入/输出)n语音板卡的状态转换(空闲/忙)n语音板卡语音通道的信号转换等3434数字语音板卡的编程数字语音板卡的编程n需要调用东进公司的CTI底层底层API函数,对板卡进行初始函数,对板卡进行初始化操作。化操作。n对于数字语音卡、模拟坐席卡以及传真卡的初始化过程基本类似。3535中继语音卡工作流程3636举例:电话银行3737举例:电话银行3838语音板卡的编程语音板卡的编程nyzInitSystem 语音卡初始化nyzDrawState监视每个通道的状态nyzExitSystem 关闭系统nyzResetChannel通道复原nyzConvertDtmf双音频转换nyzDoWork处理部分nGetVoicePath获取语音文件路径3939yzInitSystem()D161初始化程序初始化语音卡硬件GetVoicePath();DriverOpenFlag=LoadDRV();初始化设备驱动程序初始化设备驱动程序 if(DriverOpenFlag)MessageBox(hGWnd,“Load driver FAIL”,“Message”,MB_OK);加载语音卡驱动程序失败加载语音卡驱动程序失败return FALSE;TotalLine=CheckValidCh();if(EnableCard(TotalLine,1024*8)!=(long)0)FreeDRV();关闭驱动程序关闭驱动程序 MessageBox(hGWnd,Enable Board FAIL,Message,MB_OK);return FALSE;检测在当前机器内可用的通道总数检测在当前机器内可用的通道总数 激活语音卡失败激活语音卡失败4040另:初始化程序n在初始化中还可以设置语音板卡的忙音参数、回铃参数以及语音压缩率等系统参数,同时还可以对相关语音文件进行配置。n该部分可以放入语音卡的初始化过程中,程序如下:nSetBusyPara(350);/设置忙音参数nSetDialPara(1000,4000,350,7);/设置回铃音参数nSetPackRate(PACK_64BPS);/设置压缩率nSig_Init(0);/使用新的信号音检测函数4141D161初始化程序Lines=new LINESTRUCTTotalLine;SetBusyPara(350);设置忙音参数for(i=0;iTotalLine;i+)Linesi.nType=CheckChTypeNew(i);初始化通道初始化通道strcpy(Linesi.CallerID,);strcpy(Linesi.Dtmf,);Linesi.State=CH_FREE;初始状态Sig_Init(0);使用新的信号音检测函数初始化通道初始化通道4242yzExitSystemvoid WINAPI yzExitSystem()DisableCard();去激活语音卡FreeDRV();关闭设备驱动程序delete Lines;退出系统退出系统4343 yzDrawStatevoid WINAPI yzDrawState(int trkno)char state100;char tmpstr100;switch(Linestrkno.State)case CH_FREE:空闲空闲LoadString(hInst,IDS_CH_FREE,state,100);break;case CH_RECEIVEID:接收主叫号码接收主叫号码LoadString(hInst,IDS_CH_RECEIVEID,state,100);break;case CH_WAITSECONDRING:等待第二次振铃等待第二次振铃LoadString(hInst,IDS_CH_WAITSECONDRING,state,100);break;case CH_WELCOME:欢迎词欢迎词LoadString(hInst,IDS_CH_WELCOME,state,100);break;监视每个通道的状态监视每个通道的状态设计输出显示窗口设计输出显示窗口4444yzDrawStatecase CH_ACCOUNT:case CH_ACCOUNT1:请输入帐号请输入帐号LoadString(hInst,IDS_CH_ACCOUNT,state,100);break;case CH_PASSWORD:case CH_PASSWORD1:请输入密码请输入密码LoadString(hInst,IDS_CH_PINNUMBER,state,100);break;case CH_SELECT:case CH_SELECT1:选择功能选择功能LoadString(hInst,IDS_CH_SELECT,state,100);break;4545yzDrawStatecase CH_RECORDFILE:录制留言录制留言LoadString(hInst,IDS_CH_LEAVEMSG,state,100);break;case CH_PLAYRESULT:播放查询结果播放查询结果LoadString(hInst,IDS_CH_PLAYRESULT,state,100);break;case CH_PLAYRECORD:播放留言播放留言LoadString(hInst,IDS_CH_PLAYRECORD,state,100);break;case CH_OFFHOOK:摘机摘机LoadString(hInst,IDS_CH_OFFHOOK,state,100);break;case CH_WAITUSERONHOOK:等待内线挂机等待内线挂机LoadString(hInst,IDS_CH_WAITUSERONHOOK,state,100);break;4646yzDrawStateListView_GetItemText(GetDlgItem(hGWnd,IDC_STATELIST),trkno,2,tmpstr,99);if(strcmp(state,tmpstr)!=0)ListView_SetItemText(GetDlgItem(hGWnd,IDC_STATELIST),trkno,2,state);strcpy(state,Linestrkno.CallerID);ListView_GetItemText(GetDlgItem(hGWnd,IDC_STATELIST),trkno,3,tmpstr,99);if(strcmp(state,tmpstr)!=0)ListView_SetItemText(GetDlgItem(hGWnd,IDC_STATELIST),trkno,3,state);strcpy(state,Linestrkno.Dtmf);ListView_GetItemText(GetDlgItem(hGWnd,IDC_STATELIST),trkno,4,tmpstr,99);if(strcmp(state,tmpstr)!=0)ListView_SetItemText(GetDlgItem(hGWnd,IDC_STATELIST),trkno,4,state);根据监测结果,修改窗体显示值根据监测结果,修改窗体显示值4747yzResetChannelvoid yzResetChannel(int channelID)if(LineschannelID.nType=CHTYPE_TRUNK)HangUp(channelID);Sig_ResetCheck(channelID);StartSigCheck(channelID);LineschannelID.Dtmf0=0;LineschannelID.CallerID0=0;LineschannelID.State=CH_FREE;信号音检测复原信号音检测复原 外线挂机外线挂机 某路开始新的信号音检测某路开始新的信号音检测 4848yzConvertDtmfchar yzConvertDtmf(int ch)char c;switch(ch)case 10:c=0;break;case 11:c=*;break;case 12:c=#;break;case 13:case 14:case 15:c=ch-13+a;break;case 0:c=d;break;default:c=ch+0;/change DTMF from number to ASCIIreturn c;4949yzDoWorkchar FileName200;short int code;int len;PUSH_PLAY();维持文件录放音的持续进行维持文件录放音的持续进行 FeedSigFunc();/维持断续振铃及信号音的函数;for(int i=0;iTotalLine;i+)后续5050yzDoWorkyzDrawState(i);switch(Linesi.State)case CH_FREE:空闲状态空闲状态 if(RingDetect(i)检查(外线)是否有振铃信号或(内线)检查(外线)是否有振铃信号或(内线)是否有提机是否有提机 if(Linesi.nType=CHTYPE_USER)内线内线 Linesi.State=CH_OFFHOOK;摘机摘机 else Linesi.State=CH_RECEIVEID;接收主叫号码接收主叫号码 ResetCallerIDBuffer(i);初始化某路的初始化某路的Caller-ID缓缓冲区。冲区。Linesi.nTimeElapse=0;break;5151yzDoWorkcase CH_RECEIVEID:接收主叫号码 bool bOffHook=false;if(Linesi.nTimeElapse2000&RingDetect(i)监测到监测到外线振铃外线振铃bOffHook=true;if(Linesi.nTimeElapse7000)bOffHook=true;int a=GetCallerIDStr(i,Linesi.CallerID);/获得收到的Caller-ID的原始内容。if(a=3)bOffHook=true;else if(a=4)外线连接到外线连接到 3 和和 4 LoadString(hInst,IDS_CallerID_ERROR,Linesi.CallerID,32);bOffHook=true;if(bOffHook)OffHook(i);StartSigCheck(i);/某路开始新的信号音检测。某路开始新的信号音检测。一般在摘机或者挂机后,调用本函数来开始新的信号音检测。一般在摘机或者挂机后,调用本函数来开始新的信号音检测。Linesi.State=CH_OFFHOOK;Linesi.nTimeElapse+=50;break;5252yzDoWorkcase CH_WAITSECONDRING:等待第二次振铃 if(RingDetect(i)检查(外线)是否有振铃信号或检查(外线)是否有振铃信号或(内线)是否有提机(内线)是否有提机 OffHook(i);摘机 StartSigCheck(i);/某路开始新的信号音检测。一般在摘机或者挂机后,调用本函数来开始新的信号音检测。Linesi.State=CH_OFFHOOK;break;5353yzDoWorkcase CH_OFFHOOK:摘机strcpy(FileName,VoicePath);strcat(FileName,“bank.001”);欢迎词音文件欢迎词音文件InitDtmfBuf(i);/清空系统的清空系统的DTMF缓冲区,如果在缓冲区中有缓冲区,如果在缓冲区中有DTMF按键的值,将会丢失。按键的值,将会丢失。StartPlayFile(i,FileName,0L);/开始文件放音。停止该方式的开始文件放音。停止该方式的放音,一定要用放音,一定要用StopPlayFile。/检查放音是否结束,用CheckPlayEnd函数。/文件放音在本质上是利用循环内存放音,然后,不断的更新缓冲区。PUSH_PLAY函数的调用,能够保证对放音缓冲区的更新,从而达到放音的连续不断的进行。Linesi.State=CH_WELCOME;break;5454yzDoWorkcase CH_WELCOME:code=GetDtmfCode(i);/取该通道收到的取该通道收到的DTMF编码。编码。if(code!=-1)StopPlayFile(i);Linesi.Dtmf0=yzConvertDtmf(code);调用函数将收到调用函数将收到的数字转换为的数字转换为ASCII码码Linesi.Dtmf1=0;Linesi.State=CH_ACCOUNT1;改状态为输入卡号改状态为输入卡号break;if(CheckPlayEnd(i)正常播音结束正常播音结束 StopPlayFile(i);strcpy(FileName,VoicePath);strcat(FileName,“bank.002”);请输入卡号音文件请输入卡号音文件StartPlayFile(i,FileName,0L);Linesi.State=CH_ACCOUNT;break;5555yzDoWorkcase CH_ACCOUNT:输入卡号code=GetDtmfCode(i);接收卡号接收卡号if(code!=-1)StopPlayFile(i);Linesi.Dtmf0=yzConvertDtmf(code);/转换为转换为ASCIILinesi.Dtmf1=0;Linesi.State=CH_ACCOUNT1;break;if(CheckPlayEnd(i)StopPlayFile(i);停止放音停止放音Linesi.State=CH_ACCOUNT1;break;5656yzDoWorkcase CH_ACCOUNT1:len=strlen(Linesi.Dtmf);while(code=GetDtmfCode(i)!=-1)Linesi.Dtmflen+=yzConvertDtmf(code);Linesi.Dtmflen=0;if(len=8)Linesi.Dtmf0=0;strcpy(FileName,VoicePath);strcat(FileName,“bank.003”);请输入密码音文件请输入密码音文件StartPlayFile(i,FileName,0L);Linesi.State=CH_PASSWORD;break;5757yzDoWorkcase CH_PASSWORD:code=GetDtmfCode(i);/得到密码得到密码if(code!=-1)StopPlayFile(i);Linesi.Dtmf0=yzConvertDtmf(code);Linesi.Dtmf1=0;Linesi.State=CH_PASSWORD1;/修改状态修改状态break;if(CheckPlayEnd(i)/检查指定通道放音是否结束检查指定通道放音是否结束StopPlayFile(i);Linesi.State=CH_PASSWORD1;break;5858yzDoWorkcase CH_PASSWORD1:len=strlen(Linesi.Dtmf);/密码长度while(code=GetDtmfCode(i)!=-1)/没有输入密码没有输入密码Linesi.Dtmflen+=yzConvertDtmf(code);Linesi.Dtmflen=0;if(len=6)/密码长度大于密码长度大于6Linesi.Dtmf0=0;strcpy(FileName,VoicePath);strcat(FileName,“bank.004”);/播放功能选项播放功能选项StartPlayFile(i,FileName,0L);Linesi.State=CH_SELECT;break;5959yzDoWorkcase CH_SELECT:code=GetDtmfCode(i);得到所选择的功能得到所选择的功能if(code!=-1)Linesi.Dtmf0=yzConvertDtmf(code);Linesi.Dtmf1=0;6060yzDoWorkswitch(Linesi.Dtmf0)case 1:功能功能 1,播放余额,播放余额StopPlayFile(i);RsetIndexPlayFile(i);strcpy(FileName,VoicePath);strcat(FileName,“bank.005”);音 余额是AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d9);AddIndexPlayFile(i,FileName);6161yzDoWorkstrcpy(FileName,VoicePath);strcat(FileName,d9);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d8);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d9);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d6);AddIndexPlayFile(i,FileName);6262yzDoWorkstrcpy(FileName,VoicePath);strcat(FileName,d15);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d8);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,“bank.008”);音 元AddIndexPlayFile(i,FileName);StartIndexPlayFile(i);Linesi.State=CH_PLAYRESULT;break;6363yzDoWorkcase 2:功能功能 2StopPlayFile(i);RsetIndexPlayFile(i);strcpy(FileName,VoicePath);strcat(FileName,bank.006);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d0);AddIndexPlayFile(i,FileName);strcpy(FileName,VoicePath);strcat(FileName,d15);AddIn