11
Z-397 WEB / Re: Запаковка, распаковка пакетов по протоколу Advanced
« Последний ответ от gsa 23 Августа 2024, 16:58 »Не знаю почему не получается, вроде всё правильно.
Для i = 0 По 3 Цикл
Результат.Вставить(i, ПобитовоеИли(Вход[i],ПобитовыйСдвигВлево(ПобитовоеИ(ПобитовыйСдвигВправо(Вход[4],i),1),7)));
КонецЦикла;
Это копия того кода что в мануале. Для i = 0 По 3 Цикл
b = Вход[i];
if b > 127 Then
b = cmBin2Dec(cmXOR(HexToBin("0xCA"), Dec2Bin(b)));
endif;
a.Вставить(i, b);
КонецЦикла;
b = cmBin2Dec(cmXOR(HexToBin("0xCA"), Dec2Bin(Вход[4]))); //xоr-им пятый байт, хотя нигде не сказано об этом,
//Если этого не делать, то результат CF 96 12 9B как и у меня.
Для i = 0 По 3 Цикл
Если ПобитовоеИ(b,(ПобитовыйСдвигВлево(1, i))) > 0 Тогда
a[i] = ПобитовоеИли(a[i],ЧислоИзШестнадцатеричнойСтроки("0x80"));
КонецЕсли;
КонецЦикла;
Вот поэтому и проблема, распаковав пакет - он не соответтсвует тому что описано в мануале.function TAdvancedProto.DecodeCvtPack(AData: PByte; ACount: Integer;
var VPacketId, VLicenseN, VCmd: Byte; var VParams: Cardinal;
var VBody: TByteBuffer): HResult;
procedure _DecodeCvt5to4(AIn5: PByte; VOut4: PByte);
var
pOut: PByte;
I: Integer;
b: Byte;
begin
pOut := VOut4;
for I := 0 to 3 do
begin
pOut^ := AIn5^;
Inc(AIn5);
if pOut^ > $7F then
pOut^ := pOut^ xor $CA;
Inc(pOut);
end;
pOut := VOut4;
b := AIn5^ xor $CA;
for I := 0 to 3 do
begin
if (b and (1 shl I)) <> 0 then
pOut^ := pOut^ or $80;
Inc(pOut);
end;
end;
var
nChannel, nCS, nHdrSize: Byte;
I, nPkSize, nBlockCnt: Integer;
pOut, pIn, pInEnd: PByte;
begin
if ACount < 9 then
Exit(GC_E_BAD_CVT_RESPONSE); // Размер пакета слишком мал
nChannel := AData^;
Inc(AData);
Dec(ACount);
if (AData + ACount - 1)^ = $0d then
begin
Dec(ACount);
if ACount < 8 then
Exit(GC_E_BAD_CVT_RESPONSE); // Размер пакета слишком мал
end;
// Преобразуем 5 -> 4
nBlockCnt := (ACount div 5);
m_rTempBuf.Size := (nBlockCnt * 4);
pIn := AData;
pOut := m_rTempBuf.Memory;
for I := 1 to nBlockCnt do
begin
_DecodeCvt5to4(pIn, pOut);
Inc(pIn, 5);
Inc(pOut, 4);
end;
// Читаем заголовок 4-8 байт
if TChannel(nChannel) = cnUpdateFw then
nHdrSize := 6
else
nHdrSize := 8;
nPkSize := m_rTempBuf[1];
// Если указанный размер пакета > размера декодированного,
if nPkSize > m_rTempBuf.Size then
Exit(GC_E_BAD_CVT_RESPONSE); // Некорректный пакет
VLicenseN := m_rTempBuf[2];
VPacketId := m_rTempBuf[3];
VCmd := m_rTempBuf[4];
VParams := 0;
Move(m_rTempBuf.Memory[5], VParams, 3);
// Считаем контрольную сумму
nCS := 0;
pIn := m_rTempBuf.Memory;
pInEnd := pIn + nPkSize;
// Выключаем Overflow checking
{$IFOPT Q+}
{$DEFINE CKOVERFLOW}
{$Q-}
{$ENDIF}
while pIn <> pInEnd do
begin
Inc(nCS, pIn^);
Inc(pIn);
end;
{$IFDEF CKOVERFLOW}
{$UNDEF CKOVERFLOW}
{$Q+}
{$ENDIF}
if nCS <> $ff then
Exit(GC_E_BAD_CVT_RESPONSE); // ошибка CRC
VBody.SetData(@m_rTempBuf.Memory[nHdrSize], nPkSize - nHdrSize);
Result := S_OK;
end;
UINT_PTR DecodePack(vector<BYTE> &oDst, LPCBYTE pPack, UINT_PTR nCount)
{
LPCBYTE pIn = pPack;
LPCBYTE pEof = (pPack + nCount);
BYTE nCS = 0;
INT i;
BYTE a[4];
BYTE b;
oDst.clear();
pIn++;
while (pIn < pEof)
{
for (i = 0; i < 4; i++)
{
b = *pIn;
if (b > 0x7F)
b ^= 0xCA;
a[i] = b;
pIn++;
}
b = (*pIn++) ^ 0xCA;
for (i = 0; i < 4; i++)
if ((b & (1 << i)) > 0)
a[i] |= 0x80;
AppendByteArray(oDst, a, _countof(a));
}
if (oDst[1] > oDst.size()) // если реальный размер пакета > размера декодированного
{
return 0; // некорректный пакет
}
pIn = oDst.data();
pEof = oDst.data() + oDst[1];
while (pIn < pEof)
nCS += *pIn++;
if (nCS != 255)
{
return 0; // ошибка CRC
}
oDst.resize(oDst[1]);
return oDst.size();
}