I have a ZKTeco K80 device, what I can get now are the logs data ( DateTime, InOut, VerifyMethod..)
private void btnPullData_Click(object sender, EventArgs e)
{
try
{
ShowStatusBar(string.Empty, true);
ICollection<MachineInfo> lstMachineInfo = manipulator.GetLogData(objZkeeper, int.Parse(tbxMachineNumber.Text.Trim()));
if (lstMachineInfo != null && lstMachineInfo.Count > 0)
{
BindToGridView(lstMachineInfo);
ShowStatusBar(lstMachineInfo.Count + " records found !!", true);
}
else
DisplayListOutput("No records found");
}
catch (Exception ex)
{
DisplayListOutput(ex.Message);
}
}
public ICollection<MachineInfo> GetLogData(ZkemClient objZkeeper, int machineNumber)
{
string dwEnrollNumber1 = "";
int dwVerifyMode = 0;
int dwInOutMode = 0;
int dwYear = 0;
int dwMonth = 0;
int dwDay = 0;
int dwHour = 0;
int dwMinute = 0;
int dwSecond = 0;
int dwWorkCode = 0;
ICollection<MachineInfo> lstEnrollData = new List<MachineInfo>();
objZkeeper.ReadAllGLogData(machineNumber);
while (objZkeeper.SSR_GetGeneralLogData(machineNumber, out dwEnrollNumber1, out dwVerifyMode, out dwInOutMode, out dwYear, out dwMonth, out dwDay, out dwHour, out dwMinute, out dwSecond, ref dwWorkCode))
{
string inputDate = new DateTime(dwYear, dwMonth, dwDay, dwHour, dwMinute, dwSecond).ToString();
MachineInfo objInfo = new MachineInfo();
objInfo.MachineNumber = machineNumber;
objInfo.IndRegID = int.Parse(dwEnrollNumber1);
objInfo.DateTimeRecord = inputDate;
objInfo.dwInOutMode = dwInOutMode;
lstEnrollData.Add(objInfo);
}
return lstEnrollData;
}
Ref : Csharp-ZKTeco-Biometric-Device-Getting-Started
I'm searching for a method to get the absent days , how can I configure the device to count all the absent days starting from a week and except Saturday and Sunday or this is not related to the device and should I configure it myself using SQL tables??
Well, you can not get the absent days from the biometric device. It must be part of your application logic. You have to read all the attendance data from the biometric device, and consider all the missing dates as absent days.
Related
Regedit Directx informations
I have found this register and I need to know how I can do convert and take real values for these items:
DriverVersion
LastSeen
MaxD3D11FeatureLevel
MaxD3D12FeatureLevel
SharedSystemMemory
UDMVersion
I used this to get values, but I don't know the real values after conversion.
public void CheckDirectx()
{
RegistryKey registerKey;
string description = string.Empty;
long driverVersion = -1;
long lastSeen = -1;
int d11FeatureLevel = -1;
int d12FeatureLevel = -1;
long umdVersion = -1;
try
{
registerKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\DirectX\{AA4CC8A5-889A-11E9-B1F8-1062E5C8AC0E}");
description = registerKey.GetValue("Description") as string;
driverVersion = (long)registerKey.GetValue("DriverVersion");
lastSeen = (long)registerKey.GetValue("LastSeen");
d11FeatureLevel = (int)registerKey.GetValue("MaxD3D11FeatureLevel");
d12FeatureLevel = (int)registerKey.GetValue("MaxD3D12FeatureLevel");
umdVersion = (long)registerKey.GetValue("UMDVersion");
}catch (IOException e)
{
Console.WriteLine("{0}: {1}",e.GetType().Name, e.Message);
return;
}
finally
{
Console.WriteLine("{0}", description);
Console.WriteLine("{0}", lastSeen);
Console.WriteLine("{0}", d11FeatureLevel);
Console.WriteLine("{0}", d12FeatureLevel);
Console.WriteLine("{0}", umdVersion);
}
}
Most of those values can be read with DXGI interfaces (DXGI_ADAPTER_DESC1 structure and others) and are LARGE_INTEGER.
From the values in your sample, you can convert them like (I get yesterday for your LastSeen date) :
LARGE_INTEGER nDriverVersion;
nDriverVersion.QuadPart = 0x190015000e0768LL;
WORD nProduct = HIWORD(nDriverVersion.HighPart);
WORD nVersion = LOWORD(nDriverVersion.HighPart);
WORD nSubVersion = HIWORD(nDriverVersion.LowPart);
WORD nBuild = LOWORD(nDriverVersion.LowPart);
LARGE_INTEGER nLastSeen;
nLastSeen.QuadPart = 0x1D51F80F1EA7FB1LL;
FILETIME ft;
ft.dwLowDateTime = nLastSeen.LowPart;
ft.dwHighDateTime = nLastSeen.HighPart;
SYSTEMTIME st;
FileTimeToSystemTime(&ft, &st);
I'm stucked for a while trying to use zkemkeeper sdk to use on a application that uses a InBios(Controller) for fingerprint. While i trying to trigger some event nothing happen, i just created a Console Application for test the SDK before start implementing on ASP.NET MVC here is my code, i first connect to the device and then i add the event OnAttTransactionEx someone can point me what i'm doing wrong.
Here is my code:
private static void Main(string[] args)
{
CZKEMClass zkem = new CZKEMClass();
int idwErrorCode = 0;
const string ipAddr = "10.0.1.240";
bool isConnected;
try
{
isConnected = zkem.Connect_Net(ipAddr, Convert.ToInt32(4370));
}
catch (Exception ext)
{
Console.WriteLine("Erro: " + ext);
zkem.GetLastError(ref idwErrorCode);
if (idwErrorCode != 0)
{
zkem.GetLastError(idwErrorCode);
}
else
{
Console.WriteLine("No data from terminal returns!");
}
throw new Exception();
}
if (isConnected)
{
//Here you can register the realtime events that you want to be triggered(the parameters 65535 means registering all)
zkem.EnableDevice(1, true);
zkem.RegEvent(1, 65535);
zkem.OnAttTransactionEx += axCZKEM1_OnAttTransactionEx;
string sdwEnrollNumber = "";
int idwVerifyMode = 0;
int idwInOutMode = 0;
int idwYear = 0;
int idwMonth = 0;
int idwDay = 0;
int idwHour = 0;
int idwMinute = 0;
int idwSecond = 0;
int idwWorkcode = 0;
zkem.EnableDevice(1, false); //disable the device
if (zkem.ReadGeneralLogData(1))
{
//read all the attendance records to the memory
while (zkem.SSR_GetGeneralLogData(1, out sdwEnrollNumber, out idwVerifyMode,
out idwInOutMode, out idwYear, out idwMonth, out idwDay, out idwHour,
out idwMinute, out idwSecond, ref idwWorkcode))
{
//get records from the memory
DateTime datetime = new DateTime(idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond);
int unixDate = (int) datetime.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
try
{
Console.WriteLine(idwInOutMode);
Console.WriteLine(sdwEnrollNumber);
Console.WriteLine(unixDate);
}
catch (Exception ex)
{
//ignored
}
try
{
Console.WriteLine("inserted: " +
$"{idwYear}/{idwMonth}/{idwDay} {idwHour}:{idwMinute}:{idwSecond}.000");
}
catch (Exception ex)
{
}
}
}
Console.WriteLine("Fim");
}
else
{
zkem.GetLastError(ref idwErrorCode);
if (idwErrorCode != 0)
{
zkem.GetLastError(idwErrorCode);
}
else
{
Console.WriteLine("No data from terminal returns!");
}
}
zkem.EnableDevice(1, true);
Console.WriteLine("Teste");
do
{
while (!Console.KeyAvailable)
{
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
public static void axCZKEM1_OnAttTransactionEx(string sEnrollNumber, int iIsInValid, int iAttState,
int iVerifyMethod, int iYear, int iMonth, int iDay, int iHour, int iMinute, int iSecond, int iWorkCode)
{
Console.WriteLine("Finger Recognized");
}
You must use STA thread .
Thread TT = new Thread(() =>
{
CZKEMClass zkem = new CZKEMClass();
Application.Run();
});
TT.IsBackground = true;
TT.SetApartmentState(ApartmentState.STA);
TT.Start();
Then create event. ZKEM events fire on STA threads.
I'm working in C# (2013) Windows Forms. My instructor wanted us to ensure that the txtStateInput is upperCase when we hit the calculate button. However when I input a two character string such as "wi" and then hit calculate, it throws the message "enter valid state" and clears out the textbox. When I enter the "wi" in a second time then it works. I can't figure out why this is happening, the code would lead me to believe that it would check to ensure the string in txtStateInput is two characters and then when calculate is clicked it would uppercase the string. I can't figure out why it only works once I enter in the state "wi" a second time.
private void btnCalc_Click(object sender, EventArgs e)
{
//declare variables.
int startPop = 0;
int endPop = 0;
string Message = "Error";
decimal Percent = 0.0m;
string State = "";
string City = String.Empty;
int dTimes = 0;
try
{
City = txtCityInput.Text;
//System Globalization was initialized so this method works.
TextInfo myTI = new CultureInfo("en-US", false).TextInfo;
txtCityInput.Text = myTI.ToTitleCase(City);
if(txtStateInput.Text.Length != 2)
{
MessageBox.Show("Enter valid State");
txtStateInput.Focus();
txtStateInput.SelectAll();
}
else
{
State = txtStateInput.Text.ToUpper();
txtStateInput.Text = State;
if ((int.TryParse(txtStartPopInput.Text, out startPop)) && int.TryParse(txtEndPopInput.Text, out endPop))
{
if ((startPop > 0) && (endPop > 0))
{
//if population has decreased.
if ((startPop > endPop))
{
Percent = ((decimal.Parse(endPop.ToString()) - decimal.Parse(startPop.ToString())) / decimal.Parse(startPop.ToString()));
Message = "Pop. Decrease of " + Percent.ToString("p");
}
//if population has increased.
if ((startPop < endPop))
{
Percent = ((decimal.Parse(endPop.ToString()) - decimal.Parse(startPop.ToString())) / decimal.Parse(startPop.ToString()));
Message = "Pop. Increase of " + Percent.ToString("p");
}
//if population has not changed.
if ((startPop == endPop))
{
Percent = ((decimal.Parse(endPop.ToString()) - decimal.Parse(startPop.ToString())) / decimal.Parse(startPop.ToString()));
Message = "No Change in Population";
}
}
else
{
MessageBox.Show("Please enter valid population figures.");
}
}
if (int.TryParse(txtDisplayTimes.Text, out dTimes))
{
if (dTimes > 0)
{
lstResults.Items.Clear();
int iSum = 0;
int iLoopCount = dTimes;
//displays the results according to value in txtDisplayTimes.
for (iSum = 1; iSum <= iLoopCount; iSum++)
{
lstResults.Items.Add(Message);
}
}
}
}
}
catch
{
MessageBox.Show("Something went wrong.");
}
}
static void barreader_method()
{
barreader.OpenPort(barport, 19200); //opens the port connected to the rfid reader
byte TagType; //tag type
byte[] TagSerial = new byte[4]; //tag serial in reverse order
byte ReturnCode = 0; //return code sent from the rfid reader
string bartagno; //tag no as a string
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode)) /*wait until a tag is present in the rf field, if present return the tag number.*/
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
barprocess(bartagno); //barprocess method
Thread.Sleep(1200); //this is to prevent multiple reads
}
}
If the bartagno variable gets the same value within a minute, i don't want to execute the barprocess method but to continue the infinite loop. Otherwise barprocess method will be executed. How can i achieve this? I don't even know where to start. I tried different datetime, loop combinations with no success.
---------------------------------------------------------progress added below-----------------------------------------------
Multiple cards can be read within a minute, so comparing only with the previous one won't help unfortunately. I tried to use an arraylist instead building on Kelly Ethridge's answer (thanks). But if we get readings once every ten seconds for example, this will be useless. We still have to delete items older than 1 minute.
static void barreader_method()
{
barreader.OpenPort(barport, 19200);
byte TagType;
byte[] TagSerial = new byte[4];
byte ReturnCode = 0;
string bartagno;
ArrayList previoustagnos = new ArrayList();
DateTime lastreaddt = DateTime.MinValue;
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode))
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
if (DateTime.Now - lastreaddt > TimeSpan.FromMinutes(1))
{
previoustagnos.Clear();
barprocess(bartagno);
previoustagnos.Add(bartagno);
lastreaddt = DateTime.Now;
}
else
{
previoustagnos.Sort();
if (previoustagnos.BinarySearch(bartagno) < 0)
{
barprocess(bartagno);
previoustagnos.Add(bartagno);
lastreaddt = DateTime.Now;
}
}
Thread.Sleep(1200);
}
}
You'll need to keep track of the last time the barprocess was called and what the previous bartango was.
static void barreader_method()
{
barreader.OpenPort(barport, 19200); //opens the port connected to the rfid reader
byte TagType; //tag type
byte[] TagSerial = new byte[4]; //tag serial in reverse order
byte ReturnCode = 0; //return code sent from the rfid reader
string bartagno; //tag no as a string
string previousbartango;
var lastTimeCalled = DateTime.MinValue;
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode)) /*wait until a tag is present in the rf field, if present return the tag number.*/
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
var spanSinceLastCalled = DateTime.Now - lastTimeCalled;
if (spanSinceLastCalled > TimeSpan.FromMinutes(1) || bartango != previousbartango)
{
barprocess(bartagno); //barprocess method
previousbartango = bartango;
lastTimeCalled = DateTime.Now;
}
Thread.Sleep(1200); //this is to prevent multiple reads
}
}
This is air-code, but I think you get the idea.
That depends on how many tags you expect to see in a minute.
An ugly way that comes to mind is to create a new variable
List<Tuple<DateTime, String>> recentTags = new List<Tuple<DateTime, String>>()
Every time you see a bartagno, search this list to see if it's already here. If it is, skip over it. If not, add it to the list:
recentTags.Add(Tuple.Create(DateTime.Now, bartagno));
Occasionally (perhaps once 5 - 10 times through your main loop) you'll want to remove old records from this list.
recentTags.RemoveAll(e => e.Item1....
(crud - I don't recall the syntax for "e.Item1 is more than 1 minute in the past")
Isn't it as simple as storing the last processed values and a datetime. If the read is within the time limit then test for sameness before calling the barprocess() method?
...
String lastBarTagNo = "";
DateTime lastTagProcessDateTime = DateTime.MinValue;
...
while(true){
...
// read tag and build new bartagno
if(DateTime.Now - lastTagProcessDateTime <
TimeSpan.FromMinutes(1)) && lastBarTagNo.Equals(bartagno){
barprocess();
}
}
(Sorry about the formatting - doing this on a smart phone)
static void barreader_method()
{
barreader.OpenPort(barport, 19200);
byte TagType;
byte[] TagSerial = new byte[4];
byte ReturnCode = 0;
string bartagno;
List<Tuple<DateTime, String>> previoustags = new List<Tuple<DateTime, String>>();
DateTime lastreaddt = DateTime.MinValue;
while (true)
{
bartagno = "";
while (!barreader.CMD_SelectTag(out TagType, out TagSerial, out ReturnCode))
{
}
for (int i = 0; i < 4; i++)
{
bartagno += TagSerial[i].ToString("X2");
}
if (DateTime.Now - lastreaddt > TimeSpan.FromMinutes(1))
{
previoustags.Clear();
barprocess(bartagno);
previoustags.Add(Tuple.Create(DateTime.Now, bartagno));
lastreaddt = DateTime.Now;
}
else
{
if (!previoustags.Exists(a => a.Item2.Equals(bartagno)))
{
barprocess(bartagno);
previoustags.Add(Tuple.Create(DateTime.Now, bartagno));
lastreaddt = DateTime.Now;
}
}
previoustags.RemoveAll(a => a.Item1.CompareTo(DateTime.Now - TimeSpan.FromMinutes(1)) < 0);
Thread.Sleep(1200);
}
}
Thanks a lot Dan and Kelly. Without your help, i wouldn't be able to solve this.
if I have more than one camera attached to my PC ... I want to know the best available resolutions for a specific camera ...
for example some cameras are HD or FullHD (1,280×720 pixels (720p) or 1,920×1,080 pixels (1080i/1080p)) or the most common are web cameras....
I want to know at least the best video mode that the camera work properly...(the mode that the camera made to work with)
my work is on WPF using C# (I am using Directshow)
thanks in advance
This is a code that I wrote, its working perfectly for me
public static List<Point> GetAllAvailableResolution(DsDevice vidDev)
{
try
{
int hr;
int max = 0;
int bitCount = 0;
IBaseFilter sourceFilter = null;
var m_FilterGraph2 = new FilterGraph() as IFilterGraph2;
hr = m_FilterGraph2.AddSourceFilterForMoniker(vidDev.Mon, null, vidDev.Name, out sourceFilter);
var pRaw2 = DsFindPin.ByCategory(sourceFilter, PinCategory.Capture, 0);
var AvailableResolutions = new List<Point>();
VideoInfoHeader v = new VideoInfoHeader();
IEnumMediaTypes mediaTypeEnum;
hr = pRaw2.EnumMediaTypes(out mediaTypeEnum);
AMMediaType[] mediaTypes = new AMMediaType[1];
IntPtr fetched = IntPtr.Zero;
hr = mediaTypeEnum.Next(1, mediaTypes, fetched);
while (fetched != null && mediaTypes[0] != null)
{
Marshal.PtrToStructure(mediaTypes[0].formatPtr, v);
if (v.BmiHeader.Size != 0 && v.BmiHeader.BitCount != 0)
{
if (v.BmiHeader.BitCount > bitCount)
{
AvailableResolutions.Clear();
max = 0;
bitCount = v.BmiHeader.BitCount;
}
AvailableResolutions.Add(new Point(v.BmiHeader.Width, v.BmiHeader.Height));
if (v.BmiHeader.Width > max || v.BmiHeader.Height > max)
max = (Math.Max(v.BmiHeader.Width, v.BmiHeader.Height));
}
hr = mediaTypeEnum.Next(1, mediaTypes, fetched);
}
return AvailableResolutions;
}
catch (Exception ex)
{
Log(ex);
return new List<Point>();
}
}
(E.g. this can be added to VideoCaptureElement in WPF-MediaKit)
i use this to get max frame size, just change to suit your needs ;)
private Point GetMaxFrameSize(IPin pStill)
{
VideoInfoHeader v;
IAMStreamConfig videoStreamConfig = pStill as IAMStreamConfig;
int iCount = 0, iSize = 0;
videoStreamConfig.GetNumberOfCapabilities(out iCount, out iSize);
IntPtr TaskMemPointer = Marshal.AllocCoTaskMem(iSize);
int iMaxHeight = 0;
int iMaxWidth = 0;
for (int iFormat = 0; iFormat < iCount; iFormat++)
{
AMMediaType pmtConfig = null;
IntPtr ptr = IntPtr.Zero;
videoStreamConfig.GetStreamCaps(iFormat, out pmtConfig, TaskMemPointer);
v = (VideoInfoHeader)Marshal.PtrToStructure(pmtConfig.formatPtr, typeof(VideoInfoHeader));
if (v.BmiHeader.Width > iMaxWidth)
{
iMaxWidth = v.BmiHeader.Width;
iMaxHeight = v.BmiHeader.Height;
}
DsUtils.FreeAMMediaType(pmtConfig);
}
Marshal.FreeCoTaskMem(TaskMemPointer);
return new Point(iMaxWidth, iMaxHeight);
}
/// <summary>
/// Free the nested structures and release any
/// COM objects within an AMMediaType struct.
/// </summary>
public static void FreeAMMediaType(AMMediaType mediaType)
{
if (mediaType != null)
{
if (mediaType.formatSize != 0)
{
Marshal.FreeCoTaskMem(mediaType.formatPtr);
mediaType.formatSize = 0;
mediaType.formatPtr = IntPtr.Zero;
}
if (mediaType.unkPtr != IntPtr.Zero)
{
Marshal.Release(mediaType.unkPtr);
mediaType.unkPtr = IntPtr.Zero;
}
}
}
According to this webpage:
http://www.e-consystems.com/blog/camera/?p=651, you should use this call for getting the capabilities of this device:
g_DShowCaptureGraph.GetNumberOfCapabilities(nStream, &iCount, &iSize);
g_DShowCaptureGraph.GetStreamCaps(nStream,iFormat, &pmtConfig, (BYTE*)&scc);
They are C++, however.