Todays example uses a dll to access a Barcode Scanner. The used Barcode Scanner is the CS1504 (SDK available here).
The CS1504 has a buffer where it stores all scanned barcodes and this buffer can be accessed via a COM-Port. Luckily, the SDK has a dll which takes care of the communication. The only problem is, that the header is written in C/C++. I translated it (in parts) to Delphi, you can grab the file here.
Now we could just use it as is, but it would be much nicer if we had a class to wrap it all up.
We need some object to store the data, which is really simple:
And now the class that does all the work:
The TScanner class returns a generic TList<TBarcode> with all the Barcodes from the device.
The most important function is of course getBarcodes.
The implementation is pretty much straight forward, the trickiest part was to convert the 4-byte timestamp from each barcode to TDateTime. They crammed the six values for year, month, day, hour, minute and second into 4 bytes. (seriously, a SD Card that has the size of my fingernail can hold easily 4 GB and they worry about 2 bytes per scanned barcode)
This uses T4Bytes which is a packed record.
The bytes are accessible indivudually and as the resulting 4-Byte Cardinal.
Full Sourcecode is available here.
The CS1504 has a buffer where it stores all scanned barcodes and this buffer can be accessed via a COM-Port. Luckily, the SDK has a dll which takes care of the communication. The only problem is, that the header is written in C/C++. I translated it (in parts) to Delphi, you can grab the file here.
Now we could just use it as is, but it would be much nicer if we had a class to wrap it all up.
We need some object to store the data, which is really simple:
TBarcode = class
private
fTimestamp : TDateTime;
fCode : string;
public
constructor Create(aTimestamp : TDateTime; aCode : string);
property TimeStamp : TDateTime read fTimestamp;
property Code : string read fCode;
end;And now the class that does all the work:
TScanner = class
private
fPort : integer;
fReady : boolean;
fHasData: boolean;
function TimestampToDateTime(aTimestamp : Ansistring) : TDateTime;
public
constructor Create(aPort : integer);
destructor Destroy; override;
function getBarcodes : TList<TBarcode>;
procedure clearBarcodes;
property IsReady : boolean read fReady;
property HasData : boolean read fHasData;
procedure setDateTime(aDateTime : TDateTime);
function getDateTime : TDateTime;
end;The TScanner class returns a generic TList<TBarcode> with all the Barcodes from the device.
The most important function is of course getBarcodes.
function TScanner.getBarcodes: TList<TBarcode>;
var
bc : TBarcode;
i, count, pl : integer;
buffer : array[0..63] of AnsiChar;
dt : TDateTime;
s : string;
begin
result := TList<TBarcode>.Create;
begin
count := csp2ReadData;
for i := 0 to count -1 do
begin
FillChar(buffer,64,#0);
pl := csp2GetPacket(@buffer,i,63);
// The Last 4 Bytes hold the timestamp
dt := TimestampToDateTime(copy(buffer,pl-3,4));
s := copy(buffer,3,pl-6);
bc := TBarcode.Create(dt,s);
result.Add(bc);
end;
end;
end;The implementation is pretty much straight forward, the trickiest part was to convert the 4-byte timestamp from each barcode to TDateTime. They crammed the six values for year, month, day, hour, minute and second into 4 bytes. (seriously, a SD Card that has the size of my fingernail can hold easily 4 GB and they worry about 2 bytes per scanned barcode)
function TScanner.TimestampToDateTime(aTimestamp: Ansistring): TDateTime; var i1,i2,i3,i4,i5,i6 : integer; qb : T4Bytes; y,m,d,h,n,s : word; begin // CharToByte qb.Bytes[3] := Ord(aTimestamp[1]); qb.Bytes[2] := Ord(aTimestamp[2]); qb.Bytes[1] := Ord(aTimestamp[3]); qb.Bytes[0] := Ord(aTimestamp[4]); // split up the bits i1 := qb.Total and $fc000000; // 6 Bit i2 := qb.Total and $03f00000; // 6 Bit i3 := qb.Total and $000f8000; // 5 Bit i4 := qb.Total and $00007c00; // 5 Bit i5 := qb.Total and $000003c0; // 4 Bit i6 := qb.Total and $0000003f; // 6 Bit // Shift right to align the bits s := i1 shr 26; n := i2 shr 20; h := i3 shr 15; d := i4 shr 10; m := i5 shr 6; y := i6; result := EncodeDate(y+2000,m,d) + EncodeTime(h,n,s,0); end;
This uses T4Bytes which is a packed record.
T4Bytes = packed record
case Integer of
0: (Bytes: array[0..3] of Byte);
1: (Total: Cardinal);
end;The bytes are accessible indivudually and as the resulting 4-Byte Cardinal.
Full Sourcecode is available here.
Keine Kommentare:
Kommentar veröffentlichen