Delphi之东进数字语音卡(SS1)可复用源码

news/2024/7/4 8:56:36

Delphi之东进数字语音卡(SS1)可复用源码

作者:成晓旭

Bloghttp://blog.csdn.net/cxxsoft

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

        由于工作原因,本人将不在从事商业应有软件的开发工作,现在开始逐级“解密”自己以前写的部分自有产权代码,但愿对后来的朋友有点参考、借鉴的价值。

        本代码是本人开发的计划开源的CIT通用平台的东进1号信令数字语言卡封装,设计思路与模拟语音卡的封装非常类似,在此不再赘述。有兴趣的朋友,请参考本人的另外一篇文章《Delphi之东进模拟语音卡(D 160A )可复用源码》:http://blog.csdn.net/cxxsoft/archive/2006/08/23/1108211.aspx

        核心思想是一致的:卡、通道分别设计和实现;通道内,核心的还是状态机模式轮巡通道状态来管理硬件卡设备;板卡封装内实现不实现任何业务接口,但允许动态注入实现业务接口的对象,来近一步分发、处理板卡层采集的基础数据。

卡类源代码:

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

interface
uses
  Windows,SysUtils,Classes,
  unBaseDefine,
  Tce1_32,
  Tce1_FSK;

type
  TDJCommCardSS1 
=   class (TThread)
  
private
    onTrunkEvent:TTrunkSatausEvent;
    onRecEvent:TTrunkReceiveEvent;
    isLoadFSK:boolean;
    CommIsFSK:boolean;
    Trunks:array of TObject;
    function  InitCardForFSK():boolean;
    procedure FreeCardForFSK();
    procedure ThreadKernelProcess();
  
protected
    procedure Execute(); 
override ;
  
public
    TotalTrunkNum,InTrunkNum,OutTrunkNum:Word;
    TrunkConnected:array of boolean;

    constructor Create(
const  aStateEvent: TTrunkSatausEvent; const  aRecEvent:TTrunkReceiveEvent);
    destructor Destroy(); 
override ;
    
// 初始化中继卡
    function  InitCard( const  isFSKComm: boolean): Boolean;
    
// 释放中继卡  
    function  FreeCommCard():boolean;
    
// 开始运行中继卡管理模块
    procedure StartRunCommModule();
    
// 获取一个空闲通道(指定通道类型)
    function  GetAFreeTrunkByType( const  aTrunkType:TTrunkType):integer;
    
// 获取一个空闲呼出通道
    function  GetAFreeTrunkByOut():integer;
    
// 挂断指定通道
    procedure HangOfByTrunkID( const  aChannelID:integer);
    
// 通过指定通道拨号
    procedure DialPhoneByTrunkID( const  aChannelID:integer; const  phoneNumber,callerNumber:PChar; const  aDevID:integer =- 1 );
    
// 通过指定通道发送数据
    function  SendStringByTrunkID( const  aChannelID:integer; const  sendBuffer:PChar):boolean;
  end;

implementation

{ TDJCommCardSS1 }
uses
  unDJChannelSS1;

constructor TDJCommCardSS1.Create(
const  aStateEvent: TTrunkSatausEvent;
  
const  aRecEvent:TTrunkReceiveEvent);
begin
  inherited Create(
true );
  Self.FreeOnTerminate :
=   true ;
  onTrunkEvent :
=  aStateEvent;
  onRecEvent :
=  aRecEvent;
end;

destructor TDJCommCardSS1.Destroy();
begin
  Self.Suspend();
  Self.Terminate();
  FreeCommCard();
end;

procedure TDJCommCardSS1.DialPhoneByTrunkID(
const  aChannelID: integer;
  
const  phoneNumber, callerNumber: PChar; const  aDevID:integer);
begin
  
if  (aChannelID  >  ErrTrunkId) and (DJTrk_CheckTrunkFree(aChannelID)) then
    TDJCommChannelsSS1(Trunks[aChannelID]).StartDialPhone(phoneNumber,callerNumber,aDevID,);
end;

procedure TDJCommCardSS1.Execute;
begin
  
while  NOT Terminated  do
  begin
    Synchronize(ThreadKernelProcess);
    Sleep(
1 );
  end;
end;

procedure TDJCommCardSS1.FreeCardForFSK();
begin
  
if  CommIsFSK and isLoadFSK then
  begin
    DJFsk_Release();
  end;
end;

function TDJCommCardSS1.FreeCommCard(): boolean;
var
  Loop:Word;
begin
  Sleep(
1000 );
  
if  TotalTrunkNum  >   0  then
  begin
    
for  Loop: =   0  to TotalTrunkNum  -   1   do
    begin
      
if  Assigned(TDJCommChannelsSS1(Trunks[Loop])) then
      begin
        TDJCommChannelsSS1(Trunks[Loop]).Free();
        TDJCommChannelsSS1(Trunks[Loop]) :
=  nil;
      end;
    end;
  end;
  DJSys_DisableCard();
  FreeCardForFSK();
  Result :
=   true ;
end;

function TDJCommCardSS1.GetAFreeTrunkByOut(): integer;
begin
  Result :
=  GetAFreeTrunkByType(Type_Export);
end;

function TDJCommCardSS1.GetAFreeTrunkByType(
  
const  aTrunkType: TTrunkType): integer;
var
  Loop:Word;
begin
  Result :
=  ErrTrunkID;
  
for  Loop : =   0  to TotalTrunkNum  -   1   do
  begin
    
if  ((TDJCommChannelsSS1(Trunks[Loop]).GetTrunkType()  =  aTrunkType)
          and (DJTrk_CheckTrunkFree(Loop))) then
    begin
      Result :
=  Loop;
      
break ;
    end;
  end;
end;

procedure TDJCommCardSS1.HangOfByTrunkID(
const  aChannelID: integer);
begin
  TDJCommChannelsSS1(Trunks[aChannelID]).InOutHangOff();
end;

function TDJCommCardSS1.InitCard(
const  isFSKComm: boolean): Boolean;
const
  PromptFile 
=   ' Prompt.ini ' ;
var
  Loop: Integer;
  isOK: boolean;
  TimeOfNow: SystemTime;
begin
  Result :
=  False;
  CommIsFSK :
=  isFSKComm;
  isOK :
= (DJSys_EnableCard( '' ,PromptFile) = _ERR_OK);
  
if  Not isOK then exit;
  isOK :
=  InitCardForFSK();
  
if  NOT isOK then Exit;
  isLoadFSK :
=  isOK;
  GetLocalTime(TimeOfNow);
  DJSys_SetSysTime(TimeOfNow.wHour,TimeOfNow.wMinute,TimeOfNow.wSecond);
  TotalTrunkNum:
= DJTrk_GetTotalTrunkNum();
  InTrunkNum:
= TotalTrunkNum shr  1 ;
  OutTrunkNum:
= TotalTrunkNum  -  InTrunkNum;

  SetLength(Trunks,TotalTrunkNum);
  SetLength(TrunkConnected,TotalTrunkNum);

  
for  Loop: = 0  to OutTrunkNum - 1   do
    Trunks[Loop]:
= TDJCommChannelsSS1.Create(Self,Loop,Type_Export,CommIsFSK,onTrunkEvent,onRecEvent);
  
for  Loop: = OutTrunkNum to TotalTrunkNum - 1   do
    Trunks[Loop]:
= TDJCommChannelsSS1.Create(Self,Loop,Type_Import,CommIsFSK,onTrunkEvent,onRecEvent);
  
for  Loop: =   0  to TotalTrunkNum  -   1   do
  begin
    TDJCommChannelsSS1(Trunks[Loop]).ClearTrunkBuffer(csReceiving);
  end;

  DJSys_AutoApplyDtmf(ENABLEDTMF);    
// 自动分配DTMF资源
  DJSys_EnableAutoKB();                  // 自动回送KB信号
  isOK: = isOK and DJSys_EnableDtmfSend();
  Result :
=  isOK;
end;

function TDJCommCardSS1.InitCardForFSK(): boolean;
var
  k:integer;
begin
  Result :
=   true ;
  
if  CommIsFSK then
  begin
    k :
=  DJFsk_InitForFsk(SZK_Mode);
    Result :
=  (k  =   1 );
  end;
end;

function TDJCommCardSS1.SendStringByTrunkID(
const  aChannelID: integer;
  
const  sendBuffer: PChar):boolean;
begin
  Result :
=  TDJCommChannelsSS1(Trunks[aChannelID]).SendString(sendBuffer);
end;

procedure TDJCommCardSS1.StartRunCommModule();
begin
  Resume();
end;

procedure TDJCommCardSS1.ThreadKernelProcess();
var
  Loop:Word;
begin
  DJSys_PushPlay();
  
for  Loop : =   0  to TotalTrunkNum  -   1   do
  begin
    
try
      TDJCommChannelsSS1(Trunks[Loop]).DJChannelProcessor();
    except
    end;
  end;
end;

end.

  通道类源代码:

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

interface
uses
  Windows, SysUtils,
  unBaseDefine,
  Tce1_32,
  Tce1_FSK,
  unDJCardSS1;
type

  TCXXStatus 
=  (csSending,csReceiving,csPlaying);
  
  TDJCommChannelsSS1 
=   class (TObject)
  
private
    CommIsFSK:boolean;
    controller:TDJCommCardSS1;
    TrunkID:integer;
    TrunkStep:TTrunkStep;

    MaxBuffer: array [
0 ..DTMF_BUFFER_SIZE - 1 ] of Char;
    msgChannel:TTrunkStatusInfo;
    msgFrame:TRecCommFrame;

    commFrameNumber,recPos:Word;
    subStatus:TCXXStatus;
    commPhone:
string ;
    commFrameStr:
string ;

    
// 应该进一步优化为注入的接口,非简单的回调句柄
    onTrunkState:TTrunkSatausEvent;
    onRecEvent:TTrunkReceiveEvent;
    InOutType:TTrunkType;

    function  SendDataFromTrunk():boolean;
    function  CheckSendDataEnd():boolean;
    procedure SaveMaxBufferToFrameStr();
    procedure ProcessConnected();
    
// 注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
    function  CheckReceiveOverFSK( const  dataBuffer:array of  char ; const  dataNumber:Word):boolean;
    
// 注意:此方法与具体业务的通信协议存在严重依赖关系(IoC实现依赖反转)
    function  CheckReceiveOverDTMF( const  dataBuffer:array of  char ; const  dataNumber:Word):boolean;
    function  GetCommData(
const  dataBuffer:array of  char ; const  dataNumber:Word): string ;
    function  ReceiveDataFromTrunk():boolean;

    procedure InformChannelStatus(
const  aStep:TTrunkStep; const  lvof:TLVOperateFlag);
    procedure InformBusinessStatus(
const  aCommData: string ; const  cif:TCommInformFlag);
    procedure InformDialStatus(
const  aStep:TTrunkStep);
    procedure InWaitingIntoToConnect();
    function  GetCommFrameFromSendString(
const  commFrame: string ): string ;

    procedure RegisterTrunkEvent(
const  trunkStateEvent:TTrunkSatausEvent);
    procedure RegisterReceiveEvent(
const  trunkRecEvent:TTrunkReceiveEvent);
  
public
    
    constructor Create(
const  trunkController: TDJCommCardSS1;  const  TrkID: Integer;
      
const  TrunkType: TTrunkType; const  isFSKComm: boolean;
      
const  aStateEvent: TTrunkSatausEvent; const  aRecEvent:TTrunkReceiveEvent);
    destructor Destroy; 
override ;

    
// 获取通道状态
    function GetTrunkType():TTrunkType;
    procedure DJChannelProcessor();
    
// 通道挂机
    procedure InOutHangOff();
    
// 开始拨号
    procedure StartDialPhone( const  phoneNumber,callerNumber:PChar; const  aDevID:integer =- 1 );
    
// 发送通信数据
    function  SendString( const  pchSend:PChar):boolean;
    
// 清空通道数据缓冲
    procedure ClearTrunkBuffer( const  aSB:TCXXStatus);
    
// 获取通道号
    function  GetTrunkID():integer;
  end;

implementation

{ TDJCommChannelsSS1 }
const
  Frame_FillChar 
=  # 0 ;
  Leader_Flag 
=  $ 55 ;
  HeadNumber 
=   30 ;
  hasLeader 
=   true ;
  
function TDJCommChannelsSS1.CheckSendDataEnd(): boolean;
begin
  Result :
=   false ;
  
if  CommIsFSK then
  begin
    
if  (DJFsk_CheckSendFSKEnd(TrunkID,SZK_Mode)  =   1 ) then
    begin
      DJFsk_StopSend(TrunkID,SZK_Mode);
      Result :
=   true ;
    end;
  end
  
else
  begin
    
if  DJTrk_CheckDtmfSendEnd(TrunkID) then
    begin
      DJVoc_StopPlayFile(TrunkID);
      Result :
=   true ;
    end;
  end;
  
if  Result then
    ClearTrunkBuffer(csReceiving);
end;

procedure TDJCommChannelsSS1.ClearTrunkBuffer(
const  aSB:TCXXStatus);
begin
  subStatus :
=  aSB;
  
if  CommIsFSK then
    DJFsk_ResetFskBuffer(TrunkID,SZK_Mode)
  
else
    DJTrk_InitDtmfBufNew(TrunkID);
  commFrameNumber :
=   0 ;
  recPos :
=   0 ;
end;

constructor TDJCommChannelsSS1.Create(
const  trunkController: TDJCommCardSS1;  const  TrkID: Integer;
  
const  TrunkType: TTrunkType;  const  isFSKComm: boolean;
  
const  aStateEvent: TTrunkSatausEvent; const  aRecEvent:TTrunkReceiveEvent);
var
  t:TTrunkType;
begin
  inherited Create;
  RegisterTrunkEvent(aStateEvent);
  RegisterReceiveEvent(aRecEvent);
  controller :
= trunkController;
  TrunkID:
= TrkID;
  commPhone :
=   '' ;
  TrunkStep:
= TTrunkStep( - 1 );
  t :
=  TrunkType;
  
if  DJTrk_SetTrunkType(TrkID,t) then
    InOutType:
= TrunkType;
  CommIsFSK :
=  isFSKComm;
  controller.TrunkConnected[TrunkID] :
=   false ;
  ClearTrunkBuffer(csReceiving);
  InformChannelStatus(Step_Free,lvofAdd);
end;

destructor TDJCommChannelsSS1.Destroy();
begin
  inherited;
  DJTrk_BackwardHangUp(TrunkID);
end;

procedure TDJCommChannelsSS1.DJChannelProcessor();
var
  aStep: TTrunkStep;
begin
  
// DJSys_PushPlay();
  aStep: =  DJTrk_GetTrunkStatus(TrunkID);
  
// 状态变化
   if  TrunkStep  <>  aStep then
  begin
    TrunkStep:
=  aStep;
    InformChannelStatus(TrunkStep,lvofUpdate);
  end;
  
// 前向挂机
   if  (TrunkStep <> Step_Free) and DJTrk_CheckForwardHangUp(TrunkID) then
  begin
    InOutHangOff();
  end;
  
// 入中继拨入,等待接续(建立连接)
   if  (TrunkStep  =  Step_Wait) and (DJTrk_CheckTrunkIn(TrunkID)) then
  begin
    InWaitingIntoToConnect();
  end;
  
// 通道连接已经建立
   if  (TrunkStep  =  Step_Connect) then
  begin
    ProcessConnected();
  end;
  
// 出通道拨号失败
   if  TrunkStep = Step_DialFail then
  begin
    InformDialStatus(TrunkStep);
  end;
  
if  TrunkStep = Step_Delay then
    Exit;
  
// 出入通道空闲
   if  TrunkStep  =  Step_Free then
  begin
    
// 等待接收呼入
  end;
end;

function TDJCommChannelsSS1.GetTrunkID(): integer;
begin
  Result :
=  Self.TrunkID;
end;

procedure TDJCommChannelsSS1.InformChannelStatus(
const  aStep: TTrunkStep; const  lvof:TLVOperateFlag);
begin
  msgChannel.lvFlag :
=  lvof;
  msgChannel.TrunkID :
=  IntToStr(Self.TrunkID);
  msgChannel.DeviceID :
=   '' ;
  msgChannel.TrunkTypeStr:
= TrunkTypeInStr[InOutType];
  msgChannel.TrunkStep :
=  Ord(aStep);
  msgChannel.TrunkStepStr:
= TrunkStepInStr[aStep];
  
if  aStep  =  Step_Free then
  begin
    msgChannel.Phone:
= '' ;
    msgChannel.Data:
= '' ;
  end
  
else
  begin
    msgChannel.Phone:
= commPhone;
    msgChannel.Data:
= commFrameStr;
  end;
  
if  Assigned(onTrunkState) then
    onTrunkState(msgChannel);
end;

procedure TDJCommChannelsSS1.InformDialStatus(
const  aStep: TTrunkStep);
var
  dStatus:TDialStatus;
begin
  dStatus :
=  DJTrk_GetDialStatus(TrunkID);
  
case  dStatus of
  DS_Busy,DS_OverTime,DS_NoUser,DS_LineError:
  begin
    InOutHangOff();
  end;
  end;
end;

procedure TDJCommChannelsSS1.InformBusinessStatus(
const  aCommData:  string ; const  cif:TCommInformFlag);
begin
  
// 依赖注入的业务处理接口调用,实现业务处理的
end;

procedure TDJCommChannelsSS1.InOutHangOff();
begin
  DJTrk_BackwardHangUp(TrunkID);
  controller.TrunkConnected[TrunkID] :
=   false ;
  InformBusinessStatus(
'' ,cifDisconnected);
end;

procedure TDJCommChannelsSS1.InWaitingIntoToConnect;
begin
  DJVoc_PlayFile(TrunkID,
' .Voicedtmf13 ' );
  DJVoc_StopPlayFile(TrunkID);
end;


procedure TDJCommChannelsSS1.ProcessConnected();
var
  ss:TCXXStatus;  
begin
  
if  NOT controller.TrunkConnected[TrunkID] then
  begin
    controller.TrunkConnected[TrunkID] :
=   true ;
    ss :
=  csReceiving;
    InformBusinessStatus(
'' ,cifConnected);
    ClearTrunkBuffer(ss);
  end;
  
case  subStatus of
  csSending:
  begin
    
if  CheckSendDataEnd() then
    begin
        InformChannelStatus(Step_Connect,lvofUpdate);
        InformBusinessStatus(commFrameStr,cifSend);
    end;
  end;
  csReceiving:
  begin
    
if  ReceiveDataFromTrunk() then
    begin
      msgFrame.CommFrame :
=  commFrameStr;
      msgFrame.CommType :
=  Comm_FSK;
      InformChannelStatus(Step_Connect,lvofUpdate);
      InformBusinessStatus(commFrameStr,cifReceive);
    end;
  end;
  csPlaying:
  begin
    
  end;
  end;
end;

function TDJCommChannelsSS1.ReceiveDataFromTrunk(): boolean;
var
  num,Loop:integer;
  tempBuffer:array[
0 ..DTMF_BUFFER_SIZE - 1 ] of Char;
begin
  Result :
=   false ;
  
try
    
if  Self.CommIsFSK then
    begin
      
// FSK方式版本
      FillChar(tempBuffer,DTMF_BUFFER_SIZE,Frame_FillChar);
      num :
=  DJFsk_GetFSK(TrunkID,tempBuffer,SZK_MODE);
      
if  (num  >   0 ) then
      begin
        
if  CheckReceiveOverFSK(tempBuffer,num) then
        begin
          Self.commFrameStr :
=  GetCommData(tempBuffer,num);
          Self.ClearTrunkBuffer(csReceiving);
          Result :
=   true ;
        end;
      end;
    end
    
else
    begin
      
// DTMF方式版本
      num : =  DJTrk_GetReceiveDtmfNumNew(TrunkID);
      
if  num  >   0  then
      begin
        
for  Loop : =   0  to num  -   1   do
        begin
          MaxBuffer[recPos
+ Loop] : =  DJTrk_GetDtmfCodeNew(TrunkID);
          recPos :
=  (recPos  +   1 ) mod DTMF_BUFFER_SIZE;
        end;
        Inc(commFrameNumber,num);
        
if  CheckReceiveOverDTMF(tempBuffer,num) then
        begin
          ClearTrunkBuffer(csReceiving);
          Result :
=   true ;
        end;
      end;
    end;
  except
    Result :
=   false ;
  end;
end;

procedure TDJCommChannelsSS1.RegisterReceiveEvent(
  
const  trunkRecEvent: TTrunkReceiveEvent);
begin
  onRecEvent :
=  trunkRecEvent;
end;

procedure TDJCommChannelsSS1.RegisterTrunkEvent(
  
const  trunkStateEvent: TTrunkSatausEvent);
begin
  onTrunkState :
=  trunkStateEvent;
end;

procedure TDJCommChannelsSS1.SaveMaxBufferToFrameStr();
var
  Loop:Word;
begin
  commFrameStr :
=   '' ;
  
for  Loop : =   0  to commFrameNumber  -   1   do
  begin
    commFrameStr :
=  commFrameStr  +  MaxBuffer[Loop];
  end;
end;

function TDJCommChannelsSS1.SendDataFromTrunk():boolean;
begin
  Result :
=   false ;
  
if  controller.TrunkConnected[TrunkID] then
  begin
    
if  CommIsFSK then
    begin
      Result :
=  DJFsk_SendFSK(TrunkID,@MaxBuffer[ 0 ],commFrameNumber,SZK_Mode)  =   1 ;
    end
    
else
    begin
      Result :
=  DJTrk_SendDtmfStr(TrunkID,@MaxBuffer[ 0 ])  =   1 ;
    end;
  end;
  
if  Result then
    subStatus :
=  csSending;
end;

function TDJCommChannelsSS1.SendString(
const  pchSend: PChar):boolean;
var
  Loop:integer;
  strTemp:
string ;
begin
  Result :
=   false ;
  
if  Self.CommIsFSK and hasLeader then
  begin
    
// 加FSK前导字符的版本
    strTemp : =  GetCommFrameFromSendString(pchSend);
    commFrameNumber :
=  Length(strTemp);
    
if  commFrameNumber  >   0  then
    begin
      
for  Loop : =   0  to commFrameNumber - 1   do
        MaxBuffer[Loop] :
=  strTemp[Loop + 1 ];
      MaxBuffer[commFrameNumber] :
=  # 0 ;
      SaveMaxBufferToFrameStr();
      Result :
=  SendDataFromTrunk();
    end;
  end
  
else
  begin
    
// 不加前导字符的版本
    commFrameNumber : =  Length(pchSend);
    
if  commFrameNumber  >   0  then
    begin
      
for  Loop : =   0  to commFrameNumber - 1   do
        MaxBuffer[Loop] :
=  pchSend[Loop];
      MaxBuffer[commFrameNumber] :
=  # 0 ;
      SaveMaxBufferToFrameStr();
      Result :
=  SendDataFromTrunk();
    end;
  end;
end;

procedure TDJCommChannelsSS1.StartDialPhone(
const  phoneNumber,
  callerNumber: PChar;
const  aDevID:integer);
begin
  
if  DJTrk_CheckTrunkFree(TrunkID) and(Trim(phoneNumber)  <>   '' ) then
  begin
    commPhone :
=  Trim(phoneNumber);
    DJTrk_StartDial(TrunkID,PChar(commPhone),
'' );
  end;
end;

function TDJCommChannelsSS1.CheckReceiveOverFSK(
const  dataBuffer: array of  char ;
  
const  dataNumber: Word): boolean;
begin
  
// 业务实现方法:判定通信帧串发送结束
  Result : =   true ;
end;

function TDJCommChannelsSS1.GetCommData(
const  dataBuffer: array of  char ;
  
const  dataNumber: Word):  string ;
var
  Loop:Word;
begin
  Result :
=   '' ;
  
if  dataNumber  <=   0  then Exit;
  
for  Loop : =   0  to dataNumber  -   1   do
  begin
    
if  (dataBuffer[Loop]  <>  Frame_FillChar) then
      Result :
=  Result  +  dataBuffer[Loop];
  end;
end;

function TDJCommChannelsSS1.GetCommFrameFromSendString(
  
const  commFrame:  string ):  string ;
var
  Loop:integer;
begin
  Result :
=  commFrame;
  
for  Loop : =   0  to HeadNumber  -   1   do
    Result :
=  CHR(Leader_Flag)  +  Result;
end;

function TDJCommChannelsSS1.CheckReceiveOverDTMF(
  
const  dataBuffer: array of  char const  dataNumber: Word): boolean;
begin
  
// 业务实现方法:判定通信帧串发送结束
  Result : =   true ;
end;

function TDJCommChannelsSS1.GetTrunkType(): TTrunkType;
begin
  Result :
=  Self.InOutType;
end;

end.

 

 



http://www.niftyadmin.cn/n/3649246.html

相关文章

沉浸式状态栏——状态栏的实现封装类

沉浸式状态栏有两种方式&#xff1a;一&#xff1a;当状态栏下面是一张图片的时候&#xff0c;设置上面状态栏为透明&#xff0c;这样状态栏就会被图片覆盖&#xff08;这里为方便我设置了一个button颜色为#FF4081&#xff09; 首先看下没有设置沉浸式状态栏时的状态栏: 设置状…

得到了国内第一本《And I thought I Knew QTP》

承蒙作者厚爱&#xff0c;得到了一本签名版的书&#xff0c;撒几张照片&#xff1a; 加我微博吧&#xff0c;分享更多测试讯息&#xff1a;http://www.weibo.com/quicktest 作者在米国发行此书的照片&#xff1a;

Android之探秘蓝牙隐藏API

上次讲解Android的蓝牙基本用法&#xff0c;这次讲得深入些&#xff0c;探讨下蓝牙方面的隐藏API。用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对&#xff0c;但是这两项功能的函数没有在SDK中给出&#xff0c;那么如何去使用这两项功能呢&#x…

golang flag 包_如何在Go中使用Flag包

golang flag 包介绍 (Introduction) Command-line utilities are rarely useful out of the box without additional configuration. Good defaults are important, but useful utilities need to accept configuration from users. On most platforms, command-line utilities…

Ubuntu 装 Samba 安装详解 (已在Ubuntu11Server测试通过)

转自&#xff1a;http://wiki.ubuntu.org.cn/Samba Samba Samba是Ubuntu和Windows进行网络共享的工具&#xff0c;比如分享打印机&#xff0c;互相之间传输资料文件。 目录 [隐藏]1 安装Samba2 Kubuntu3 配置4 Ubuntu访问windows xp/2003/2000系统5 排错 5.1 乱码 6 smb用户…

golang接口的使用场景_如何在Go中使用接口

golang接口的使用场景介绍 (Introduction) Writing flexible, reusable, and modular code is vital for developing versatile programs. Working in this way ensures code is easier to maintain by avoiding the need to make the same change in multiple places. How you…

android以欺骗的方法使用隐藏API调用举例(国际化,多语言)

Android对国际化与多语言切换已经做得不错了&#xff0c;一个应用只要命名相应语系的values-[language]文件夹&#xff0c;通过“设置”→“语言&键盘”→“选择语言”即可实现应用多种语言的切换。 但如何在应用里自己实现&#xff1f;搜索过发现网上有如下的做法&…