📄 sms_pudunit.pas
字号:
{ SMSPDUproc }
/// <summary>
/// 短信收发控件
/// </summary>
/// <author> agamem </author>
/// <date> 2005-7-12 </date>
unit SMS_PUDUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, SPComm, ExtCtrls, StrUtils;
type
/// <summary>
/// 用户信息编码方式
/// td7_Bit : 7-bit编码,只能用于发送英文字符,160个字符
/// td8_Bit : 8-bit编码,可用于发送透明数据
/// tdUCS2 : Unicode编码,可发送中英文,限制在70个字符
/// </summary>
TTP_DCS = (td7_Bit, td8_Bit, tdUCS2);
/// <summary>
/// 短信模块控制状态
/// </summary>
TSMSState = (NORMAL, ATE, ATCMGF, ATCNMI, ATCMGS_1, ATCMGS_2, ATCMGR, ATCMGD);
/// <summary>
/// 数据监视事件
/// </summary>
TSMSMonitor = procedure(Sender: TObject; RevString: string) of object;
/// <summary>
/// 接收短信通知事件
/// </summary>
TSMSRev = procedure(Sender: TObject; mSMSC, mPhoneID, mInfo: string; mGTime: TDateTime) of object;
/// <summary>
/// 短信控件
/// </summary>
TSMSPDUproc = class(TComponent)
private
/// <summary>
/// 串口控件
/// </summary>
SMScomm: TComm;
/// <summary>
/// 超时判断计时器
/// </summary>
OTTimer: TTimer;
/// <summary>
/// PDU包信息长度
/// </summary>
FCMGSLen: string;
/// <summary>
/// 用户信息编码模式(短消息编码模式)
/// </summary>
FTP_DCS: TTP_DCS;
/// <summary>
/// 目标号码
/// </summary>
FTP_DA: string;
/// <summary>
/// 短消息中心号码
/// </summary>
FSMSC: string;
/// <summary>
/// 透明数据短消息
/// </summary>
FTP_UDByte: array of Byte;
/// <summary>
/// 字符数据短消息
/// </summary>
FTP_UDStr: string;
/// <summary>
/// PUD包
/// </summary>
FPUDStr: string;
/// <summary>
/// 波特率
/// </summary>
FBaudRate: DWORD;
/// <summary>
/// 串口号
/// </summary>
FCommName: string;
/// <summary>
/// 数据位
/// </summary>
FByteSize: TByteSize;
/// <summary>
/// 校验位
/// </summary>
FParity: TParity;
/// <summary>
/// 停止位
/// </summary>
FStopBits: TStopBits;
/// <summary>
/// 激活控件
/// </summary>
FActive: Boolean;
/// <summary>
/// 当前收到短消息的编号
/// </summary>
FCurrSMSIndex: Integer;
/// <summary>
/// 当前短消息机的状态
/// </summary>
CurrState: TSMSState;
/// <summary>
/// 超时/错误 重发计数
/// </summary>
ReSendCount: Integer;
/// <summary>
/// 超时判断计数
/// </summary>
tver: Integer;
/// <summary>
/// 串口接收监视
/// </summary>
FOnRevMonitor: TSMSMonitor;
/// <summary>
/// 串口发送监视
/// </summary>
FOnSndMonitor: TSMSMonitor;
/// <summary>
/// 接收短消息后是否删除短消息
/// </summary>
FDelAfterRev: Boolean;
/// <summary>
/// 收到短消息事件
/// </summary>
FOnReceiveSMS: TSMSRev;
procedure setTP_DCS(const Value: TTP_DCS);
procedure setSMSC(const Value: string);
procedure setTP_DA(const Value: string);
/// <summary>
/// 获取PUD包
/// </summary>
function getPUDStr: string;
procedure SetBaudRate(const Value: DWORD);
procedure SetByteSize(const Value: TByteSize);
procedure SetStopBits(const Value: TStopBits);
procedure SetCommName(const Value: string);
procedure SetParity(const Value: TParity);
procedure setActive(const Value: Boolean);
/// <summary>
/// 串口接收事件
/// </summary>
procedure SMSReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
/// <summary>
/// 初始化短信机
/// </summary>
procedure resetSMS();
/// <summary>
/// 数据写入串口
/// </summary>
procedure sendStrToComm(str: string);
/// <summary>
/// 超时计数器事件
/// </summary>
procedure OTTimerTimer(Sender: TObject);
/// <summary>
/// PDU包解码
/// </summary>
procedure DecodePUD(s: string);
protected
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
/// <summary>
/// 设置发送的内容 透明数据
/// </summary>
procedure setTP_UD(value: array of Byte); overload;
/// <summary>
/// 设置发送的内容 字符数据
/// </summary>
procedure setTP_UD(value: string); overload;
/// <summary>
/// 发送消息
/// </summary>
procedure SendSM; overload;
/// <summary>
/// 发送消息
/// </summary>
procedure SendSM(mTP_DA, Info: string); overload;
published
/// <summary>
///用户信息编码方式(TP-DCS)
/// </summary>
property TP_DCS: TTP_DCS read FTP_DCS write setTP_DCS;
/// <summary>
/// SMSC地址,短消息中心号码
/// </summary>
property SMSC: string read FSMSC write setSMSC;
/// <summary>
/// 目标地址(TP-DA),目标号码
/// </summary>
property TP_DA: string read FTP_DA write setTP_DA;
/// <summary>
/// 取得PUD包
/// </summary>
property PUDStr: string read getPUDStr;
/// <summary>
/// PUD包长度
/// </summary>
property CMGSLen: string read FCMGSLen;
/// <summary>
/// 串口
/// </summary>
property CommName: string read FCommName write SetCommName;
/// <summary>
/// 波特率
/// </summary>
property BaudRate: DWORD read FBaudRate write SetBaudRate;
/// <summary>
/// 数据位
/// </summary>
property ByteSize: TByteSize read FByteSize write SetByteSize;
/// <summary>
/// 校验
/// </summary>
property Parity: TParity read FParity write SetParity;
/// <summary>
/// 停止位
/// </summary>
property StopBits: TStopBits read FStopBits write SetStopBits;
/// <summary>
/// 激活短消息控件
/// </summary>
property Active: Boolean read FActive write setActive;
/// <summary>
/// 回收数据监视
/// </summary>
property OnRevMonitor: TSMSMonitor read FOnRevMonitor write FOnRevMonitor;
/// <summary>
/// 发送数据监视
/// </summary>
property OnSndMonitor: TSMSMonitor read FOnSndMonitor write FOnSndMonitor;
/// <summary>
/// 错误信息
/// </summary>
property OnError: TSMSMonitor read FOnSndMonitor write FOnSndMonitor;
/// <summary>
/// 读出短消息后删除
/// </summary>
property DelAfterRev: Boolean read FDelAfterRev write FDelAfterRev;
/// <summary>
/// 收到短消息后触发事件
/// </summary>
property OnReceiveSMS: TSMSRev read FOnReceiveSMS write FOnReceiveSMS;
end;
procedure Register;
implementation
{ SMSPDUproc }
/// <summary>
/// 延时
/// </summary>
/// <param name="MSecs">需要延时的毫秒</param>
procedure Delay(MSecs: Longint);
//延时函数,MSecs单位为毫秒(千分之1秒)
var
FirstTickCount, Now: Longint;
begin
FirstTickCount := GetTickCount();
repeat
Application.ProcessMessages;
Now := GetTickCount();
until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount);
end;
function GB5ToUniCode(Value: WideString): string;
var
I, Len: Integer;
S: string;
begin
Result := '';
Len := Length(Value);
I := 1;
while I <= Len do
begin
FmtStr(S, '%4.4X', [ord(Value[I])]); //BCD转换
Result := Result + S;
Inc(I);
end;
end;
//******************************************************************************
// Function/Procedure : HexToInt
// Purpose : 把十六进制转换成十进制
// Inputs : 十六进制字符
// Return : 十进制数
//******************************************************************************
function HexToInt(HexStr: string): Integer;
begin
Result := StrToInt('$' + HexStr);
end;
//******************************************************************************
// Function/Procedure : UniCodeToGB5
// Purpose : 把十六进制的字符数组转换成UNICODE字符
// Inputs : 十六进制的字符数组
// Return : UNICODE字符
//******************************************************************************
function UniCodeToGB5(s: string): WideString;
var
P: PWord;
I, RealLen: Integer;
sStr: WideChar;
begin
New(p);
RealLen := Length(s) div 4; //计算UNICODE真实长度
for I := 0 to RealLen - 1 do begin
P^ := HexToInt(Copy(s, 4 * I + 1, 4));
Move(P^, sStr, 2);
Result := Result + sStr;
end;
Dispose(P);
end;
//******************************************************************************
// Function/Procedure : ChangeLeftAndRight
// Purpose : 将一个字符串在位置上进行奇数位与偶数
// 位的交换,字符串长度为奇数位时自动补F
// Inputs : 字符串
// Return : 字符串
//******************************************************************************
function ChangeLeftAndRight(Value: string): string;
var
I: Integer;
S: Char;
begin
Result := Trim(Value);
if Length(Result) = 0 then Exit;
if Length(Result) mod 2 = 1 then Result := Result + 'F';
I := 1;
while I < Length(Result) do begin
S := Result[I];
Result[I] := Result[I + 1];
Result[I + 1] := S;
I := I + 2;
end;
end;
//******************************************************************************
// Function/Procedure : ResumeOrder
// Purpose : ChangeOrder反向操作
// Inputs : 字符串
// Return : 字符串
//******************************************************************************
function ResumeOrder(OriStr: string): string;
var
I: Integer;
sStr: string;
begin
sStr := '';
for i := 1 to (Length(OriStr) div 2) do
sStr := sStr + OriStr[I * 2] + OriStr[I * 2 - 1];
Result := StringReplace(sStr, 'F', '', [rfReplaceAll]);
end;
function gsmEncode7bit(pSrc: string; nSrcLength: Integer): string;
var
nSrc: Integer; // 源字符串的计数值
nChar: Integer; // 当前正在处理的组内字符字节的序号,范围是0-7
nLeft: byte; // 上一字节残余的数据
tmpChar: Byte;
procChar: byte;
s, pDst: string;
i: Integer;
begin
// 计数值初始化
nSrc := 0;
nLeft := 0;
// 将源串每8个字节分为一组,压缩成7个字节
// 循环该处理过程,直至源串被处理完
// 如果分组不到8字节,也能正确处理
i := 1;
pDst := '';
while (nSrc <= nSrcLength) do
begin
// 取源字符串的计数值的最低3位
nChar := nSrc and 7;
// 处理源串的每个字节
if (nChar = 0) then
begin
// 组内第一个字节,只是保存起来,待处理下一个字节时使用
nLeft := Byte(pSrc[i]);
end
else
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -