📄 uniprotocol_cutehouse.pas
字号:
srACK:
begin
FFrameNO := 0;
FPacketCommState := csGetHistoryData;
end;
else
FPacketCommState := csHalt;
end;
end;
csGetHistoryData:
begin
case SendResult of
srGetData:
begin
Inc(FFrameNO);
if FDataCount > 0 then
FProcessRatio := FFrameNo * 100 div FDataCount;
if FProcessRatio > 100 then FProcessRatio := 100;
// 如果数据传输完毕,则进入下一状态
if Copy(Packet, 6, 17) = StringOfChar(#0, 17) then
begin
FFrameNO := 0;
if FindParams(FSenderSerialNO + '_GetCableLength') = '1' then
FPacketCommState := csGetCableLength
else
FPacketCommState := csNotifyHangup
end
else
begin
// 如果数据尚未传输完毕,则保存数据
currentData := IntToStr(Ord(Packet[6])) + ',';
for i := 1 to 16 do
currentData := currentData + IntToHex(Ord(Packet[6 + i]), 2);
FDatas.Add('Data=' + currentData);
end;
end;
else
FPacketCommState := csHalt;
end;
end;
csGetCableLength:
begin
case SendResult of
srGetData:
begin
currentData := IntToStr(Ord(Packet[6])) + ',';
for i := 1 to 16 do
currentData := currentData + IntToHex(Ord(Packet[6 + i]), 2);
FDatas.Add('Data=' + currentData);
FPacketCommState := csNotifyHangup;
end;
else
FPacketCommState := csHalt;
end;
end;
csNotifyHangup:
begin
Inc(FFrameNo);
if FFrameNo = 1 then
begin
if SendResult <> srACK then
FPacketCommState := csHalt;
end
else
begin
FCommSuccess := True;
FPacketCommState := csHalt;
end;
end;
end;
// 生成命令
if FPacketCommState <> csHalt then
with FHostCmd do
begin
case FPacketCommState of
csGetDataInfo:
begin
Comment := '【读取数据信息】';
Command := #$F0 + #$10;
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 300;
No_Response_Interval := 300;
Max_Send_Times := 10;
SetLength(Echos, 1);
Echos[0].Echo_Head :=csACK;
Echos[0].Echo_Size := 10;
Echos[0].Echo_HaveCRC := True;
curACK := '';
curNAK := '';
end;
csAdjustTime:
begin
Comment := '【校正时间】';
Command := AdjustTimeCommand;
Send_Interval := 500;
No_Response_Interval := 500;
Max_Send_Times := 10;
SetLength(Echos, 0);
curACK := csACK + #$F1;
curNAK := '';
end;
csSetPhoneCode:
begin
Comment := '【校正电话号码】';
Command := #$F2 + Chr(FFrameNo) + Chr(Length(GetSubParams(FSenderSerialNO + '_Phone', FFrameNo))) + GetSubParams(FSenderSerialNO + '_Phone', FFrameNo);
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 500;
No_Response_Interval := 500;
Max_Send_Times := 10;
SetLength(Echos, 0);
curACK := csACK + #$F2 + Chr(FFrameNo);
curNAK := '';
end;
csSetSecureKey:
begin
Comment := '【设定密钥】';
Command := #$F3 + Chr(FFrameNo shr 8) + Chr(FFrameNo and $FF);
Command := Command + ConvHexStrToBinary(GetSubParams(FSenderSerialNO + '_Key', FFrameNO)) + #0#0#0;
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 500;
No_Response_Interval := 500;
Max_Send_Times := 10;
SetLength(Echos, 0);
curACK := csACK + #$F3 + Chr(FFrameNo shr 8) + Chr(FFrameNo and $FF);
curNAK := '';
end;
csSetAlertLimit:
begin
Comment := '【设定报警条件】';
Command := #$F4 +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 0))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 1))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 2))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 3))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 4)) + $80) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 5)) + $80) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 6))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 7))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 8))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 9))) +
Chr(StrToInt(GetSubParams(FSenderSerialNO + '_AlertLimit', 10)));
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 500;
No_Response_Interval := 500;
Max_Send_Times := 10;
SetLength(Echos, 0);
curACK := csACK + #$F4;
curNAK := '';
end;
csGetHistoryData:
begin
Comment := '【接收数据】';
Command := #$F5 + Chr(FFrameNo shr 8) + Chr(FFrameNo and $FF);
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 500;
No_Response_Interval := 500;
Max_Send_Times := 10;
SetLength(Echos, 1);
Echos[0].Echo_Head := csACK + #$F5 + Chr(FFrameNo shr 8) + Chr(FFrameNo and $FF);
Echos[0].Echo_Size := 23;
Echos[0].Echo_HaveCRC := True;
curACK := '';
curNAK := '';
end;
csGetCableLength:
begin
Comment := '【测定电缆长度】';
Command := #$F8 + #$10;
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 60000;
No_Response_Interval := 1000;
Max_Send_Times := 10;
SetLength(Echos, 1);
Echos[0].Echo_Head := csACK + #$F5 + #0 + #0 + #5;
Echos[0].Echo_Size := 23;
Echos[0].Echo_HaveCRC := True;
curACK := '';
curNAK := '';
end;
csControlDevice:
begin
Comment := '【控制设备】';
Command := #$F9;
// 空调
if FindParams(FSenderSerialNO + '_AirCondition') = '0' then
Command := Command + #$AA
else if FindParams(FSenderSerialNO + '_AirCondition') = '1' then
Command := Command + #$55
else
Command := Command + #0;
// 风扇
if FindParams(FSenderSerialNO + '_Fan') = '0' then
Command := Command + #$AA
else if FindParams(FSenderSerialNO + '_Fan') = '1' then
Command := Command + #$55
else
Command := Command + #0;
// 门禁
if FindParams(FSenderSerialNO + '_Door') <> '' then
Command := Command + Chr(StrToInt('$' + FindParams(FSenderSerialNO + '_Door')))
else
Command := Command + #0;
// 清除告警
if FindParams(FSenderSerialNO + '_ClearAlert') = '1' then
Command := Command + #$55
else
Command := Command + #0;
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 1000;
No_Response_Interval := 1000;
Max_Send_Times := 10;
SetLength(Echos, 0);
curACK := csACK + #$F9;
curNAK := '';
end;
csNotifyHangup:
begin
Comment := '【请求挂机】';
Command := #$FA + #$10;
Command := Command + Chr(CrcOfString(Command));
Send_Interval := 500;
No_Response_Interval := 300;
Max_Send_Times := 10;
SetLength(Echos, 0);
curACK := csACK + #$FA;
curNAK := '';
end;
end;
end;
Result := FHostCmd;
end;
{--------------------------------------------------------------------------
class function TCuteHouse.ParseEnvData
功能: 将数据转化为环境数据
输入: data: String 数据
输出: TEnvData 环境数据
---------------------------------------------------------------------------}
class function TCuteHouse.ParseEnvData(Data: string): TEnvData;
var
i: Integer;
Year, Mon, day, Hour, Min, Sec: Dword;
mState:String;
begin
with result do
begin
Year := 2000 + StrToInt(Copy(Data, 9, 2));
Mon := StrToInt(Copy(Data, 7, 2));
day := StrToInt(Copy(Data, 5, 2));
Hour := StrToInt(Copy(Data, 3, 2));
Min := StrToInt(Copy(Data, 1, 2));
Sec := 0;
try
if (Mon = 0) and (day = 0) and (Hour = 0) and (min = 0) then
dtTime := Now
else
dtTime := EncodeDate(Year, Mon, day) + EncodeTime(Hour, Min, Sec, 0);
except
dtTime := 0;
end;
mState := Copy(Data, 11, 2);
SmogState := (StrToInt('$' + mState) shr 1) and 1;
WaterState := (StrToInt('$' + mState) shr 2) and 1;
LightState := (StrToInt('$' + mState) shr 3) and 1;
FanState := (StrToInt('$' + mState) shr 4) and 1;
AirConditionState := (StrToInt('$' + mState) shr 5) and 1;
DoorState := StrToInt('$' + mState) shr 6;
VoltageAC := StrToInt('$' + Copy(Data, 13, 2));
VoltageDC := StrToInt('$' + Copy(Data, 15, 2));
Humidity := StrToInt('$' + Copy(Data, 17, 2));
for i := 1 to 7 do
begin
Temperatures[i] := StrToInt('$' + Copy(Data, 17 + i * 2, 2)) - $80;
end;
end;
end;
{--------------------------------------------------------------------------
class function TCuteHouse.ParseDoorData
功能: 将数据转化为门禁数据
输入: data: String 数据
输出: TDoorData 门禁数据
---------------------------------------------------------------------------}
class function TCuteHouse.ParseDoorData(Data: string): TDoorData;
var
i: Integer;
Year, Mon, day, Hour, Min, Sec: Dword;
begin
with result do
begin
Year := 2000 + StrToInt(Copy(Data, 11, 2));
Mon := StrToInt(Copy(Data, 9, 2));
day := StrToInt(Copy(Data, 7, 2));
Hour := StrToInt(Copy(Data, 5, 2));
Min := StrToInt(Copy(Data, 3, 2));
Sec := StrToInt(Copy(Data, 1, 2));
try
dtTime := EncodeDate(Year, Mon, day) + EncodeTime(Hour, Min, Sec, 0);
except
dtTime := 0;
end;
CardSerial := Copy(Data, 13, 8);
ReaderNO := StrToInt('$' + Copy(Data, 21, 2));
DoorState := StrToInt('$' + Copy(Data, 23, 2)) shr 6;
for i := 1 to 4 do
Reserved[i] := StrToInt('$' + Copy(Data, 23 + i * 2, 2));
end;
end;
{--------------------------------------------------------------------------
class function TCuteHouse.ParseAlertData
功能: 将数据转化为报警数据
输入: data: String 数据
输出: TAlertData 报警数据
---------------------------------------------------------------------------}
class function TCuteHouse.ParseAlertData(Data: string): TAlertData;
var
i: Integer;
begin
with result do
begin
VoltageAC := StrToInt('$' + Copy(Data, 1, 2));
VoltageDC := StrToInt('$' + Copy(Data, 3, 2));
Humidity := StrToInt('$' + Copy(Data, 5, 2));
DoorState := StrToInt('$' + Copy(Data, 7, 2)) shr 6;
AirConditionState := (StrToInt('$' + Copy(Data, 7, 2)) shr 5) and 1;
FanState := (StrToInt('$' + Copy(Data, 7, 2)) shr 4) and 1;
for i := 0 to 7 do
CableState[i + 1] := (StrToInt('$' + Copy(Data, 9, 2)) and (1 shl i)) shr i;
for i := 1 to 7 do
begin
Temperatures[i] := StrToInt('$' + Copy(Data, 9 + i * 2, 2)) - $80;
end;
for i := 1 to 4 do
Reserved[i] := StrToInt('$' + Copy(Data, 23 + i * 2, 2));
end;
end;
{--------------------------------------------------------------------------
class function TCuteHouse.ParseCableData
功能: 将数据转化为电缆长度数据
输入: data: String 数据
输出: TCableData 电缆长度数据
---------------------------------------------------------------------------}
class function TCuteHouse.ParseCableData(Data: string): TCableData;
var
i: Integer;
begin
with result do
for i := 1 to 8 do
begin
if UpperCase(Copy(Data, i * 4 - 3, 4)) = 'FFFF' then
CableLength[i] := -1
else
try
CableLength[i] := StrToInt(Copy(Data, i * 4 - 3, 2)) * 1000 + StrToInt(Copy(Data, i * 4 - 1, 2)) * 10
except
CableLength[i] := 0;
end
end;
end;
{-----------------------------------------------------------------------------}
initialization
// 注册协议处理插件
RegisterExecutorClass(TCuteHouse);
finalization
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -