Reputation: 916
I am trying to convert the following payload into a readable string. It is a log containing information I want to use afterwards to analyze and process.
This is the payload message:
0x234453006AD2C3005B71436C6173733A2061203A3A204173696D6F764661636164652E63616C6C28292072656672657368207B746F6B656E3D65303466663731622D336265342D343836632D623339622D3663633762396365646236397D10070D02040256
I know that the protocol is as follows:
Header: 3 bytes
ID: 4 bytes
Length: 2 bytes
LogDebug: 1 byte
LogData: N
Timestamp: 6 bytes
CS: 1 byte
I tried using:
CONVERT(VARCHAR(MAX), SUBSTRING(payload, 0, 3) + SUBSTRING(payload, 3, 4) + ...)
but couldn't get it to work. I saw in the SSMS documentation that SUBSTRING accepts only certain data types where I typed payload, such as character, binary, text, ntext, or image. I tried
CONVERT(VARCHAR(MAX), (SUBSTRING(CONVERT(BINARY,Payload),0, 3)) + (SUBSTRING(CONVERT(BINARY,Payload),3, 4)))
as well but no luck :(
Any suggestions?
EDIT: The expected log should look like this:
000: ← 2016/07/13 00:04:02, (0x71)U2H.LOGDEBUG - Class: a :: AsimovFacade.call() refresh {token=e04ff71b-3be4-486c-b39b-6cc7b9cedb69}
I get:
#DS
Upvotes: 3
Views: 932
Reputation: 2587
Try the code below. You pretty much just need to substring the varbinary into the fields in your protocol, then convert to an appropriate type.
I've assumed your 4 byte ID is an int
, and it seems that your length field includes the timestamp and "cs" fields at the end, so you need to deduct 7 from the value.
DECLARE @payload varbinary(MAX) = 0x234453006AD2C3005B71436C6173733A2061203A3A204173696D6F764661636164652E63616C6C28292072656672657368207B746F6B656E3D65303466663731622D336265342D343836632D623339622D3663633762396365646236397D10070D02040256
DECLARE @header char(3),
@id int,
@length smallint,
@logdebug char(1),
@logdata varchar(MAX),
@timestamp char(6),
@cs char(1)
SET @header = convert(char(3), substring(@payload, 1, 3))
SET @id = convert(int, substring(@payload, 4, 4))
SET @length = convert(smallint, substring(@payload, 8, 2)) - 7
SET @logdebug = convert(char(1), substring(@payload, 10, 1))
SET @logdata = convert(varchar(MAX), substring(@payload, 11, @length))
SET @timestamp = convert(char(6), substring(@payload, @length + 11, 6))
SET @cs = convert(char(1), substring(@payload, @length + 17, 1))
SELECT @header,@id,@length, @logdebug, @logdata, @timestamp, @cs
Upvotes: 0
Reputation: 176016
Substring works fine for varbinary and will return varbinary.
Seems the data length field includes the last 2 fields in addition to the LogData length.
The string U2H.LOGDEBUG
does not appear in your input.
declare @b varbinary(max) = 0x234453006AD2C3005B71436C6173733A2061203A3A204173696D6F764661636164652E63616C6C28292072656672657368207B746F6B656E3D65303466663731622D336265342D343836632D623339622D3663633762396365646236397D10070D02040256
select cast(substring(@b, 1, 3) as char(3)) as hdr
select cast(substring(@b, 4, 4) as int) as id
-- store length of the payload
declare @len int = cast(substring(@b, 8, 2) as int)
select @len as length
select cast(substring(@b, 10, 1) as binary(1)) as logdebug
-- read payload for the read length, less 7 bytes for the timestamp & cs
select cast(substring(@b, 11, @len - 7) as varchar(max)) as logdata
-- read past payload for 6 bytes for the timestamp (whatever format that is - not epoch)
select substring(@b, @len + 11 - 7, 6) as timestamp
select substring(@b, @len + 11 - 7 + 6, 1) as cs
For
hdr
----
#DS
id
-----------
7000771
length
-----------
91
logdebug
--------
0x71
logdata
----
Class: a :: AsimovFacade.call() refresh {token=e04ff71b-3be4-486c-b39b-6cc7b9cedb69}
timestamp
----
0x10070D020402
cs
----
0x56
Upvotes: 1