Skip to content

Instantly share code, notes, and snippets.

@mariodivece
Created April 17, 2016 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mariodivece/526b3395bc36638b1c75ee7309935fd5 to your computer and use it in GitHub Desktop.
Save mariodivece/526b3395bc36638b1c75ee7309935fd5 to your computer and use it in GitHub Desktop.
A very simple wrapper to control the popular fingerprint reader model GT511C3
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Unosquare.Devices
{
public class GT511C3 : IDisposable
{
private const int InitialBaudRate = 9600;
private const int TargetBaudRate = 115200;
private SerialPort m_SerialPort;
private bool IsDisposing = false;
public enum Command : ushort
{
Open = 0x01,
Close = 0x02,
UsbInternalCheck = 0x03,
ChangeBaudRate = 0x04,
SetIAPMode = 0x05,
CmosLed = 0x12,
GetEnrollCount = 0x20,
CheckEnrolled = 0x21,
EnrollStart = 0x22,
Enroll1 = 0x23,
Enroll2 = 0x24,
Enroll3 = 0x25,
IsPressFinger = 0x26,
DeleteID = 0x40,
DeleteAll = 041,
Verify = 0x50,
Identify = 0x51,
VerifyTemplate = 0x52,
IdentifyTemplate = 0x53,
CaptureFinger = 0x60,
MakeTemplate = 0x61,
}
public GT511C3()
{
}
public void Open(string portName)
{
if (this.m_SerialPort != null) throw new InvalidOperationException("Device is already open. Call the Close method first.");
this.m_SerialPort = new SerialPort(portName, InitialBaudRate);
this.m_SerialPort.Open();
this.Send(Command.Open, 1);
this.Send(Command.ChangeBaudRate, TargetBaudRate);
this.Close();
this.m_SerialPort = new SerialPort(portName, TargetBaudRate);
this.m_SerialPort.Open();
var result = this.Send(Command.Open, 1);
}
public ResponsePacket Send(Command command, int param)
{
var packet = new CommandPacket() { Command = (ushort)command, Parameter = param };
var packetBytes = packet.ToByteArray();
this.m_SerialPort.Write(packetBytes, 0, packetBytes.Length);
this.m_SerialPort.BaseStream.Flush();
if (this.m_SerialPort.IsOpen && this.m_SerialPort.BytesToRead == 0)
System.Threading.Thread.Sleep(100);
var response = new List<byte>(this.m_SerialPort.BytesToRead);
while (this.m_SerialPort.BytesToRead > 0)
{
var count = this.m_SerialPort.BytesToRead;
var buffer = new byte[count];
this.m_SerialPort.Read(buffer, 0, count);
response.AddRange(buffer);
}
return ResponsePacket.FromBytes(response.ToArray());
}
public class ResponsePacket
{
public static ResponsePacket FromBytes(byte[] payload)
{
var response = new ResponsePacket();
response.Payload = payload;
return response;
}
private byte[] Payload { get; set; }
public bool IsDataPacket { get { return Payload != null && Payload.Length >= 2 && Payload[1] == 0xA5; } }
public byte[] Data
{
get
{
if (IsDataPacket == false)
return new byte[] { };
var data = new byte[Payload.Length - 6];
Array.Copy(Payload, 4, data, 0, data.Length);
return data;
}
}
public int Parameter
{
get
{
var dataBytes = new byte[4];
Array.Copy(Payload, 4, dataBytes, 0, dataBytes.Length);
if (BitConverter.IsLittleEndian == false)
Array.Reverse(dataBytes);
return BitConverter.ToInt32(dataBytes, 0);
}
}
public ushort Response
{
get
{
var dataBytes = new byte[2];
Array.Copy(Payload, 8, dataBytes, 0, dataBytes.Length);
if (BitConverter.IsLittleEndian == false)
Array.Reverse(dataBytes);
return BitConverter.ToUInt16(dataBytes, 0);
}
}
public ushort Checksum
{
get
{
var dataBytes = new byte[2];
Array.Copy(Payload, Payload.Length - 2, dataBytes, 0, dataBytes.Length);
if (BitConverter.IsLittleEndian == false)
Array.Reverse(dataBytes);
return BitConverter.ToUInt16(dataBytes, 0);
}
}
public bool IsError
{
get
{
if (IsDataPacket) return false;
return Response == 0x31;
}
}
}
private class CommandPacket
{
private static readonly byte[] Header = { 0x55, 0xAA, 0x00, 0x01 };
private static readonly ushort HeaderSum = Convert.ToUInt16(Header.Sum(b => Convert.ToInt32(b)));
public int Parameter { get; set; }
public ushort Command { get; set; }
public byte[] ToByteArray()
{
var paramBytes = BitConverter.GetBytes(Parameter);
var commandBytes = BitConverter.GetBytes(Command);
var checksum = HeaderSum;
var payload = paramBytes.Concat(commandBytes).ToArray();
foreach (var b in payload)
checksum += Convert.ToUInt16(b);
var checksumBytes = BitConverter.GetBytes(checksum);
if (BitConverter.IsLittleEndian == false)
{
Array.Reverse(paramBytes);
Array.Reverse(commandBytes);
Array.Reverse(checksumBytes);
}
return Header.Concat(payload).Concat(checksumBytes).ToArray();
}
}
private void Close()
{
if (this.m_SerialPort == null) return;
try
{
if (this.m_SerialPort.IsOpen)
this.m_SerialPort.Close();
}
finally
{
this.m_SerialPort.Dispose();
this.m_SerialPort = null;
}
}
public void Dispose()
{
if (this.IsDisposing) return;
this.IsDisposing = true;
this.Close();
}
}
}
@nekszer
Copy link

nekszer commented May 26, 2016

Thanks!! 🎉

@nekszer
Copy link

nekszer commented May 26, 2016

Hi, can you make an example?

The method IdentifyTemplate, is equals to GetTemplate of GT511C3 c++ library?

Sorry for my bad english. 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment