?? uniprotocol_timepos.pas
字號:
unit UniProtocol_TimePos;
{----------------------------------------------
UniProtocol_TimePos
考勤機協議插件
Ver 1.04
Copyright 1999-2001 AT Corp.Ltd
-----------------------------------------------}
interface
uses
UniCommX, SysUtils, Classes, Windows;
type
TPosData = record
rtTime: TDateTime; // 日期
rtCard: string; // 卡號
rtReaderNO: string; // 讀卡頭號
rtVoltage: Integer; // 電壓
rtTemperature: Integer; // 溫度
end;
TTimePos = class(TCustomProtocolExecutor)
private
FSenderSerialNO: string;
FHostCmd: THostCommand;
FFrameNo: Integer;
FAlertData: string; // 報警數據
FDataCount: Integer;
function AdjustTimeCommand: string;
public
constructor Create(SenderID, ProtocolVersion: Integer; Hwnd: THandle); override;
destructor Destroy; override;
class function ParsePos(Data: string): TPosData;
class function ProtocolImplemented(ProtocolType: Integer; ProtocolVersion: Integer; isCommander: Boolean): Boolean; override;
class function SaveUncompletedData: Boolean; override;
function ProcessProtocol(var FCommState: Integer; SendResult: Integer; Packet: string; Parameters: TStrings): THostCommand; override;
end;
implementation
const
MonitorID = 2;
csACK = #$A5#$A5; // csACK: 確認
csNAK = #$5A#$5A; // csNAK: 否定回應
constructor TTimePos.Create(SenderID, ProtocolVersion: Integer; Hwnd: THandle);
begin
inherited;
end;
destructor TTimePos.Destroy;
begin
inherited;
end;
class function TTimePos.ParsePos(Data: string): TPosData;
var
Year, Mon, day, Hour, Min, Sec: Word;
begin
DecodeDate(Now, year, Mon, day);
Sec := 0;
Min := StrtoInt(Copy(Data, 1, 2));
Hour := StrtoInt(Copy(Data, 3, 2));
day := StrtoInt(Copy(Data, 5, 2));
Mon := StrtoInt(Copy(Data, 7, 2));
with Result do
begin
rtTime := EncodeDate(year, mon, day) + EnCodeTime(Hour, Min, Sec, 0);
rtCard := Copy(Data, 9, 8);
rtReaderNO := Copy(Data, 17, 2);
rtVoltage := StrtoInt('$' + Copy(Data, 19, 2));
rtTemperature := StrtoInt('$' + Copy(Data, 21, 2));
end;
end;
class function TTimePos.ProtocolImplemented(ProtocolType: Integer; ProtocolVersion: Integer; isCommander: Boolean): Boolean;
begin
Result := (ProtocolType = cnTimePosID) and isCommander;
end;
class function TTimePos.SaveUncompletedData: Boolean;
begin
Result := True;
end;
function TTimePos.AdjustTimeCommand: string;
var
Year, Month, day, Hour, Min, Sec, Msec: Word;
begin
decodeDate(now, Year, Month, day);
decodeTime(now, Hour, Min, Sec, msec);
Year := Year mod 100;
SetLength(Result, 8);
Result[1] := #$FD;
Result[2] := Chr(convBCDToHex(Sec));
Result[3] := Chr(convBCDToHex(Min));
Result[4] := Chr(convBCDToHex(Hour));
Result[5] := Chr(convBCDToHex(day));
Result[6] := Chr(convBCDToHex(Month));
Result[7] := Chr(convBCDToHex(Year));
Result[8] := Chr(GenerateCRC(Result[1], 7));
end;
{ (主機與考勤機)
考勤機 ?----------------------------------------------------------------------------------------à主機
等待主機呼叫
?------------------------------------------------呼叫考勤機------------------------------------定時收集考勤信息
收到并確認是呼叫本機--------------------------------應答---------------------------------------------à
?------------------------------------------------呼叫考勤機------------------------------------未收到應答(超時呼叫其它考勤機)
?------------------------------------------------發送命令---------------------------------------收到應答,確定呼叫成功
收到命令 -------------------------------------------------應答---------------------------------------------à
命令及回答:
注:◆為主機命令 ⊙考勤機應答 【】內為注解
ACK = 0xA5 + 0xA5 NAK = 0x5A + 0x5A
●握手信號:
◆ "SWAT"
⊙ ACK+0002(考勤機標識)+0001(協議版本號)+CRC 【ACK】
●讀取考勤機號:
◆ 0xFE+0x10+CRC
⊙ ACK+4B(考勤機號)+2B(記錄條數)+5B(報警數據)+CRC 【ACK】
● 校正考勤機時間
◆ 0xFD+SSMMHHDDMMYY+CRC
⊙ ACK+0xFD+CRC 【ACK】
● 請求數據
◆ 0xFB+2B(記錄條數)+CRC 【請求記錄】
⊙ 0xFB+2B(記錄條數)+16B(數據)+CRC
【16B數據:分時日月(4B)+卡號(4B)+讀卡頭號(1B)+電壓(1B)+溫度補碼(1B)+ [00000交流電紅外入侵門磁開關](1B)+預留(4B)】
● 下傳主機電話號碼:
◆ 0xFA+1B(號碼序號)+1B(號碼長度)+電話號碼+CRC
⊙ ACK+1B(號碼序號)+0xFA+CRC 【ACK】
● 更新密鑰:
◆ 0xF9+2B(幀號)+6B(數據)+CRC 【幀號為密鑰位置,6B數據為4B密鑰+1B權限(80H以上可開門)+1B預留】
⊙ ACK++2B(幀號)+CRC 【ACK】
● 追加新密鑰:
◆ 0xF8+6B(數據)+CRC
⊙ ACK+0xF8+CRC 【ACK】
● 掛機命令:
◆ 0xF7+0x10+CRC
⊙ ACK+0xF7+CRC 【ACK】
● 設置報警范圍:
◆ 0xF5+7B(報警范圍)+CRC 【7B報警范圍:2B溫度上下限,2B電壓上下限,1B交流,紅外,門磁(低三位為1可報警),2B預留】
⊙ ACK+0xF5+CRC 【ACK】
● 命令接收錯誤應答:
⊙ NCK+4B(考勤機號)+CRC 【NCK】
注:
1、固定數據取CRC只是為延長命令長度,減少"正確誤碼"或為處理方便。
2、當主機沒有收到應答時,要求重發都由主機來執行。
3、當收到下一條命令,校驗正確,就屏蔽上條命令,以次類推。
}
function TTimePos.ProcessProtocol(var FCommState: Integer; SendResult: Integer; Packet: string; Parameters: TStrings): THostCommand;
const
csGetDataInfo = csUser + 1;
csAdjustTime = csUser + 2;
csGetHistoryData = csUser + 3;
csSetPhoneCode = csUser + 4;
csUpdateKey = csUser + 5;
csAppendKey = csUser + 6;
csSetAlertLimit = csUser + 7;
function FindParams(Key: string): string;
begin
Result := Parameters.Values[IntToStr(cnTimePosID) + '_' + Key];
end;
function GetSubParams(Key: string; KeyIndex: Integer): string;
var
i: Integer;
curKeyIndex: Integer;
Params: string;
begin
Result := '';
Params := FindParams(Key);
if Params = '' then Exit;
curKeyIndex := 0;
if Params[Length(Params)] <> ',' then Params := Params + ',';
while Pos(',', Params) > 0 do
begin
i := Pos(',', Params);
if curKeyIndex = KeyIndex then
begin
Result := Copy(Params, 1, i - 1);
Break;
end;
Delete(Params, 1, i);
Inc(curKeyIndex);
end;
end;
function GetAlterLimit: string;
var
i: integer;
begin
Result := '';
for i := 0 to 3 do
Result := Result + chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', i)));
Result := Result + chr(
(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 4)) shl 2) or
(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 5)) shl 1) or
(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 6))));
Result := Result + #0#0;
end;
var
i: integer;
currentData: string;
begin
FProcessRatio := 0;
// 處理狀態改變
case FCommState of
csHandShake:
begin
FFrameNo := 0;
FCommState := csGetDataInfo;
end;
csGetDataInfo:
begin
case SendResult of
srGetData:
begin
FSenderSerialNO := '';
for i := 0 to 3 do
FSenderSerialNO := FSenderSerialNO + IntToHex(ord(Packet[3 + i]), 2);
FDatas.Add('SenderSerialNo=' + FSenderSerialNO);
FDataCount := (Ord(Packet[7]) shl 8) + Ord(Packet[8]);
FAlertData := '';
for i := 0 to 4 do
FAlertData := FAlertData + IntToHex(ord(Packet[9 + i]), 2);
FCommState := csAdjustTime;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -