现在的位置: 首页 > 综合 > 正文

Delphi之东进模拟语音卡(D160A)可复用源码

2013年02月23日 ⁄ 综合 ⁄ 共 6817字 ⁄ 字号 评论关闭
  
Delphi之东进模拟语音卡(D160A)可复用源码

作者:成晓旭

Bloghttp://blog.csdn.net/cxxsoft

(声明:欢迎转载,请保证文章的完整性)

设计简介:

1、   将卡、通道分别单独进行设计与封装。

2、   所有的外部操作接口都封装在卡类这一类。

3、   在我的项目中,在卡类这一级还增加了适配器或者代理,分别实现了AdapterProxy模式;以尽可能地解耦卡设备的实现细节与具体应用业务之间的关系。因为,我们的系统中使用了几家不同的卡设备,另一方面,这些卡设备,在不同的软件系统中,又有不同的业务应用需求。

4、   当然,卡这一级,也可以实现一个统一的接口,这样对外部可以表现出相对统一的行为,以方便业务层代码的调用,比如说:在数据采集的应用中,统一的接口可以让采集控制层不必依赖于具体的采集设备和通信方式,可以一致地实现数据收发,不管通信方式是RS232RS485TCP/IPPSTN,还是别的方式或者通信设备。

5、   在通道设计中,核心的就是一个“状态机模式”,通过轮巡通道状态来管理硬件卡设备,并且,还自己设计了一个业务级的“业务状态机”,来抽象业务方面需要关心的“业务状态”,通过增加“业务状态机”这样一个中间层,以解耦业务状态与设备状态之间的依赖。(这一点,在我看到的所有卡厂商提供的各类Demo程序里面都没有这样做,这也无形中误导了很多的开发人员,我看到的所有应用软件开发的源码都是:设备细节、尤其是通道状态,与业务逻辑代码紧紧地耦合在一起,难解难分)

6、   此设计的另一个亮点是:IoC模式的应用(2004年自己在设计此类时还不知道这个概念,全凭自己的经验总结出这样的设计)。对通道进入“呼入成功”、“呼出成功”等业务状态的调用代码从通道类是解耦出来:设计一个接口,在各个业务状态的处理方法中,再调用接口方法,将具体的业务处理逻辑委托给实现此接口的对象。并且这个接口的实现是通过“依赖注入”实现IoC的。这样设计,就达到了很好的可复用性和灵活性。

7、   当然,更好的实现可以采用AOP(面向方法编程)的思想或者实现技术,这样可复用性更好,如此设计,在业务与卡方法的调用之间,耦合度将是最低的。

8、   目前的版本,没有在代码中体现接口的实现……

9、   类图(以后补上)

    10、卡类源码:

//------------------------------------------------------------------------------
//
//      产品名称:   成晓旭的个人软件Delphi源码库
//      产品版本:   CXXSoft delphi code source lib 2.0
//      模块名称:   Delphi之东进模拟语音卡类
//      模块描述:   
//      单元文件:   unDJCard160A.pas   
//      开发作者:   成晓旭
//      备注:       任何人使用此文件时,请保留此段自述文件,谢谢!
//      开发时间:   2004-08-03
//      修改历史:   
//      修改描述:
//------------------------------------------------------------------------------
unit unDJCard160A;

interface
uses
  Windows,
  unDJTC08a32,unDJNewSig,
  unBaseDefine,unDJ160ADefine,
  unDJChanne160A;
type
  TCXXCommCard160A 
= class(TObject)
  
private

    ChannelNumber:Word;
    channelObject:array of TCXXDJChannel160A;
    OnCardChannelState:TTrunkStatusEvent;

    procedure Stop();
    procedure ReleaseCommDevice();
    function  GetChannelObjectOrder(
const aChannelID:Word):Word;

  
public

    constructor Create(
const trunkEvent:TTrunkStatusEvent);
    destructor Destroy(); 
override;

    function  LoadCommDevice(
const loadAll:boolean=false):boolean;
    function  Startup():boolean;
    function  GetAFreeChannel():Word;
    function  GetChannelNumber():Word;
    function  DialPhone(
const aChannelID:Word;const DialPhoneNumber:PChar):boolean;
    function  HangUp(
const aChannelID:Word):boolean;

  end;


implementation

{ TCXXCommCard160A }
constructor TCXXCommCard160A.Create(
const trunkEvent:TTrunkStatusEvent);
begin
  ChannelNumber :
= 0;
  Self.OnCardChannelState :
= trunkEvent;
end;

destructor TCXXCommCard160A.Destroy;
var
  Loop:Word;
begin
  Stop();
  
if (Length(channelObject) > 0) and (channelNumber > 0) then
  begin
    
for Loop := 0 to ChannelNumber - 1 do
    begin
      
if Assigned(channelObject[Loop]) then
      begin
        channelObject[Loop].Free();
        channelObject[Loop] :
= nil;
      end;
    end;
  end;
  ReleaseCommDevice();
end;

function TCXXCommCard160A.DialPhone(
const aChannelID: Word;
  
const DialPhoneNumber: PChar): boolean;
var
  K:Word;
begin
  Result :
= false;
  K :
= GetChannelObjectOrder(aChannelID);
  
if (K  ErrorTrunkNumber) and (Assigned(channelObject[K])) then
  begin
    Result :
= channelObject[K].DialPhone(DialPhoneNumber);
  end;
end;

procedure TCXXCommCard160A.ReleaseCommDevice();
begin
  DisableCard();
  FreeDrv();
end;

function TCXXCommCard160A.GetAFreeChannel(): Word;
var
  Loop:Word;
begin
  Result :
= ErrorTrunkNumber;
  
for Loop := Low(channelObject) to High(channelObject) do
  begin
    
if (channelObject[Loop].GetChannelType() = ctEmpty) then continue;
    
if (channelObject[Loop].GetChannelStatus() = atsFree) then
    begin
      Result :
= channelObject[Loop].GetChannelID();
      
break;
    end;
  end;
end;

function TCXXCommCard160A.GetChannelNumber(): Word;
begin
  Result :
= channelNumber;
end;

function TCXXCommCard160A.GetChannelObjectOrder(
  
const aChannelID: Word): Word;
var
  Loop:Word;
begin
  Result :
= ErrorTrunkNumber;
  
for Loop := Low(channelObject) to High(channelObject) do
  begin
    
if (channelObject[Loop].GetChannelID = aChannelID) then
    begin
      Result :
= Loop;
      
break;
    end;
  end;
end;

function TCXXCommCard160A.HangUp(
const aChannelID: Word): boolean;
var
  K:Word;
begin
  Result :
= false;
  K :
= GetChannelObjectOrder(aChannelID);
  
if (K  ErrorTrunkNumber) and (Assigned(channelObject[K])) then
  begin
    channelObject[K].ChannelHangUp();
    Result :
= true;
  end;
end;

function TCXXCommCard160A.LoadCommDevice(
const loadAll:boolean): boolean;
const
  loadEmpty 
= true;
var
  Loop,tempNumber:Word;
  isFlag:LongInt;
  function CheckLoadTrunk():boolean;
  begin
    Result :
= loadAll or ((NOT loadAll) and(TChannelType(CheckChType(Loop))  ctEmpty));
  end;
begin
  isFlag :
= LoadDRV();
  Result :
= (isFlag=0);
  
if NOT Result then Exit;
  tempNumber :
= CheckValidCh();
  Result :
= EnableCard(tempNumber,1024*8)=0;
  
if NOT Result then
  begin
    FreeDrv();
    Exit;
  end;
  Result :
= Sig_Init()=1;
  
if NOT Result then Exit;
  SetBusyPara(
700);
  SetPackRate(PACK_64KBPS );
  channelNumber :
= tempNumber;
  SetLength(channelObject,channelNumber);
  
for Loop := 0 to channelNumber - 1 do
  begin
    
if CheckLoadTrunk() then
    begin
      channelObject[Loop] :
= TCXXDJChannel160A.Create(OnCardChannelState);
      channelObject[Loop].CreateCommChannel(Loop);
    end;
  end;
end;

function TCXXCommCard160A.Startup(): boolean;
var
  Loop:integer;
begin
  
for Loop := 0 to channelNumber - 1 do
  begin
    channelObject[Loop].Resume();
  end;
  Result :
= true;
end;

procedure TCXXCommCard160A.Stop();
var
  Loop:integer;
begin
  
for Loop := 0 to channelNumber - 1 do
  begin
    channelObject[Loop].Suspend();
    channelObject[Loop].Terminate();
    channelObject[Loop] :
= nil;
  end;
end;

end.

11、              通道类源码:
//------------------------------------------------------------------------------
//
//      产品名称:   成晓旭的个人软件Delphi源码库
//      产品版本:   CXXSoft delphi code source lib 2.0
//      模块名称:   Delphi之东进模拟语音卡通道类
//      模块描述:   
//      单元文件:   unDJChanne160A.pas   
//      开发作者:   成晓旭
//      备注:       任何人使用此文件时,请保留此段自述文件,谢谢!
//      开发时间:   2004-08-03
//      修改历史:   
//      修改描述:
//------------------------------------------------------------------------------
unit unDJChanne160A;

interface

uses
  Windows,Classes,SysUtils,
  unBaseDefine,unDJ160ADefine,
  unDJTC08a32,unDJNewSig;
Type
  TCXXDJChannel160A 
= class(TThread)
  
//TCXXDJChannel160A = class(TObject)
  private
    channelType:TChannelType;
    oldChannelState,channelState:TTrunkState;
    channelID:Word;
    phoneNumber:
string;
    dtmfString:
string;

    isConntectd:boolean;

    isDialOut:boolean;
    aTrunkState:TTrunkStatus;
    
    procedure InformTrunkStatus(
const aMsgFlag: TLVOperateFlag);

    procedure ClearTrunkStatus();
    function  CheckSigHangup():boolean;
    function  CheckCallIn():boolean;
    function  SwitchOnCallIn():boolean;

    procedure ProcessCallInSuccess();
    procedure ProcessDialSuccess();

    procedure ProcessCheckDialSend();
  
protected
    procedure Execute(); 
override;
  
public
    strMessage:
string;
    OnChannelState:TTrunkStatusEvent;

    constructo

抱歉!评论已关闭.