中控考勤机开发-专业性门禁终端
本文参考手册:《TFT 系列脱机通讯开发包开发手册》
业务需求:
1、定时同步考勤机的刷卡记录到数据库
2、推送人员信息到考勤机
主要内容:
1、定时同步考勤记录到数据库
2、用户信息、指纹操作
3、考勤记录批量操作
正文
1、定时任务
1-1、定义全局变量
#region 窗体变量 string USERID = "";//同步到数据库的参数 string CHARGE_TIME = "";//同步到数据库的参数 string VERIFYMODE = "";//同步到数据库的参数 string WORKCODE = "";//同步到数据库的参数 string PASSWORD = "";//同步到数据库的参数 string PRIVILEGE = "";//同步到数据库的参数 string ENABLE = "";//同步到数据库的参数 System.Timers.Timer atimer = new System.Timers.Timer(); //定时任务 #endregion #region 考勤机变量 public CZKEMClass axCZKEM1 = new CZKEMClass(); private bool bIsConnected = false; private int iMachineNumber = 1; string sdwEnrollNumber = "";//用户ID string sName = "";//姓名 string sPassword = "";//密码 int iPrivilege = 0; bool bEnabled = false; string sCardnumber = "";//卡号 int dwWorkCode = 0; int dwVerifyMode; int dwInOutMode; int dwYear;//刷卡时间 int dwMonth; int dwDay; int dwHour; int dwMinute; int dwSecond; string verifyMode = ""; string privilege = ""; string enabled = ""; #endregion
1-2、连接考勤机
#region 考勤机功能:打开连接 private void connectZK() { //若IP、端口号为空则不能连接 if (txtIP.Text.Trim() == "" || txtPort.Text.Trim() == "") { WriteLog.Write("WARN", txtIP.Text, "打开连接时IP或端口不能为空"); return; } //若状态为已连接则先关闭连接 if (bIsConnected == true) { disconnectZK(); } //连接机器 int idwErrorCode = 0; Cursor = Cursors.WaitCursor; bIsConnected = axCZKEM1.Connect_Net(txtIP.Text, Convert.ToInt32(txtPort.Text)); if (bIsConnected == true) { lblState.Text = "Current State:Connected"; iMachineNumber = 1;//In fact,when you are using the tcp/ip communication,this parameter will be ignored,that is any integer will all right.Here we use 1. axCZKEM1.RegEvent(iMachineNumber, 65535);//Here you can register the realtime events that you want to be triggered(the parameters 65535 means registering all) WriteLog.Write("INFO", txtIP.Text, "连接成功。"); } else { axCZKEM1.GetLastError(ref idwErrorCode); WriteLog.Write("WARN", txtIP.Text, "连接失败。ErrorCode=" + idwErrorCode.ToString()); } Cursor = Cursors.Default; } #endregion #region 考勤机功能:关闭连接 private void disconnectZK() { if (txtIP.Text.Trim() == "" || txtPort.Text.Trim() == "") { WriteLog.Write("WARN", txtIP.Text, "关闭连接时IP或端口不能为空"); return; } Cursor = Cursors.WaitCursor; if (bIsConnected) { axCZKEM1.Disconnect(); bIsConnected = false; lblState.Text = "Current State:DisConnected"; WriteLog.Write("INFO", txtIP.Text, "连接关闭。"); Cursor = Cursors.Default; return; } else { Cursor = Cursors.Default; } } #endregion
1-3、配置定时任务
这里使用.net工具箱提供的定时器System.Windows.Forms.Timer。
需要同步记录或推送人员时再打开连接,否则可能会出现因连接时间过长导致连接失去响应。
#region 定时任务配置 private void timerSync_Tick(object sender, EventArgs e) { int nowhour = int.Parse(DateTime.Now.Hour.ToString()); int nowminute = int.Parse(DateTime.Now.Minute.ToString()); // 8:00~23:00 if (nowhour >= 8 && nowhour <= 22) { // 打开连接 connectZK(); if (bIsConnected == true) { // 同步刷卡 getLogData(); // 关闭连接 disconnectZK(); } } // 23:00 if (nowhour == 23 && nowminute == 00) { // 打开连接 connectZK(); if (bIsConnected == true) { // 清空考勤机刷卡记录 clearRecord(); // 推送人员 pushEmp(); // 关闭连接 disconnectZK(); } } } #endregion
1-4、同步刷卡记录
#region 任务-同步刷卡数据到MES数据库 private void getLogData() { if (bIsConnected == false) { WriteLog.Write("WARN", "", "当前未连接考勤机"); return; } Cursor = Cursors.WaitCursor; //先禁用机器 axCZKEM1.EnableDevice(iMachineNumber, false); //获取所有用户的考勤记录到缓存区 axCZKEM1.ReadAllGLogData(iMachineNumber); while (axCZKEM1.SSR_GetGeneralLogData(iMachineNumber, out sdwEnrollNumber, out dwVerifyMode, out dwInOutMode, out dwYear, out dwMonth, out dwDay, out dwHour, out dwMinute, out dwSecond, ref dwWorkCode))//get user information from memory { switch (dwVerifyMode) { case 0: verifyMode = "密码验证"; break; case 1: verifyMode = "指纹验证"; break; case 2: verifyMode = "卡验证"; break; default: verifyMode = "其他验证"; break; } //循环获取用户信息 axCZKEM1.SSR_GetUserInfo(iMachineNumber, sdwEnrollNumber, out sName, out sPassword, out iPrivilege, out bEnabled); if (axCZKEM1.GetStrCardNumber(out sCardnumber))//get the card number from the memory { switch (iPrivilege) { case 0: privilege = "普通用户"; break; case 3: privilege = "管理员"; break; default: privilege = "其他权限"; break; } switch (bEnabled) { case true: enabled = "启用"; break; case false: enabled = "禁用"; break; } USERID = sdwEnrollNumber; CHARGE_TIME = dwYear.ToString() + "-" + dwMonth.ToString() + "-" + dwDay.ToString() + " " + dwHour.ToString() + ":" + dwMinute.ToString() + ":" + dwSecond.ToString(); CHARGE_DATE = dwYear.ToString("0000") + "-" +dwMonth.ToString("00") + "-" + dwDay.ToString("00"); VERIFYMODE = verifyMode; WORKCODE = dwWorkCode.ToString(); //NAME = sName+ "\0"; //NAME = NAME.Replace("\0", ""); PASSWORD = sPassword; PRIVILEGE = privilege; ENABLE = enabled; string ID = dwYear.ToString() + dwMonth.ToString() + dwDay.ToString() + dwHour.ToString() + dwMinute.ToString() + dwSecond.ToString(); DateTime now = DateTime.Now; string thisyear = now.Year.ToString(); string thismonth = now.Month.ToString(); string thisday = now.Day.ToString(); // 仅同步当天的刷卡记录 if (dwYear.ToString() == thisyear && dwMonth.ToString() == thismonth && dwDay.ToString() == thisday) { // 这个调用插入数据库的方法 WriteLog.Write("INFO", "", "同步刷卡记录到数据库"); } } } axCZKEM1.EnableDevice(iMachineNumber, true);//enable the device Cursor = Cursors.Default; } #endregion
1-5、推送数据库中人员到考勤机
private void pushEmp() { if (bIsConnected == false) { WriteLog.Write("WARN", "", "当前未连接考勤机"); return; } //获取orcale表推送状态为0的人员,推送到考勤机 DataTable pushdt = BllEmpSync.pushEmp(); string[] push_num = new string[pushdt.Rows.Count]; string[] push_name = new string[pushdt.Rows.Count]; string[] push_cardnum = new string[pushdt.Rows.Count]; WriteLog.Write("INFO", txtIP.Text, "开始推送人员信息...待推送人员数:" + pushdt.Rows.Count.ToString()); for (int i = 0; i < pushdt.Rows.Count; i++) { DataRow dr = pushdt.Rows[i]; push_num[i] = Convert.ToString(dr["T_USERID"]); push_name[i] = Convert.ToString(dr["T_USERNAME"]); push_cardnum[i] = Convert.ToString(dr["CARDID"]); axCZKEM1.SetStrCardNumber(push_cardnum[i]); //2、设置用户信息 bool a = axCZKEM1.SSR_SetUserInfo(iMachineNumber, push_num[i], push_name[i], push_num[i], 0, true); if (a) WriteLog.Write("INFO", txtIP.Text, "推送人员" + push_num[i] + "成功。"); else WriteLog.Write("WARN", txtIP.Text, "推送人员" + push_num[i] + "失败。"); } BllEmpSync.updateEmp(); }
1-6、每天定时清空考勤机刷卡记录
(防止同步时因数据太多而变卡,调用方法见2-7)
2、考勤机管理(注:以下方法省略了考勤机的打开与关闭连接)
2-1、查询考勤机内已注册用户
(注意:如果考勤机内没有注册指纹信息,代码里面有查询指纹,那么加载会变得非常慢。要提前注释掉查询指纹的代码!)
#region 考勤机功能:获取用户 private void btnGetStrCardNumber_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } lvCard.Items.Clear(); lvCard.BeginUpdate(); Cursor = Cursors.WaitCursor; //先禁用机器 axCZKEM1.EnableDevice(iMachineNumber, false);//disable the device //获取所有用户的记录到缓存区 axCZKEM1.ReadAllUserID(iMachineNumber);//获取所有信息到缓存区(提高效率) axCZKEM1.ReadAllTemplate(iMachineNumber);//获取所有指纹信息到缓存区(提高效率) while (axCZKEM1.SSR_GetAllUserInfo(iMachineNumber, out sdwEnrollNumber, out sName, out sPassword, out iPrivilege, out bEnabled))//get user information from memory { //循环获取用户信息 if (axCZKEM1.GetStrCardNumber(out sCardnumber))//get the card number from the memory { ListViewItem list = new ListViewItem(); list.Text = sdwEnrollNumber; list.SubItems.Add(sName); list.SubItems.Add(sCardnumber); list.SubItems.Add(iPrivilege.ToString()); list.SubItems.Add(sPassword); if (bEnabled == true) { list.SubItems.Add("true"); } else { list.SubItems.Add("false"); } for (int dwFingerIndex = 0; dwFingerIndex < 10; dwFingerIndex++) { if (axCZKEM1.SSR_GetUserTmpStr(iMachineNumber, sdwEnrollNumber, dwFingerIndex, out dwTmpData, out dwTmpLength)) { list.SubItems.Add(dwTmpData); } else { list.SubItems.Add(""); } } lvCard.Items.Add(list); } } axCZKEM1.EnableDevice(iMachineNumber, true);//enable the device lvCard.EndUpdate(); Cursor = Cursors.Default; } #endregion
2-2、注册单个用户到考勤机
#region 考勤机功能:注册用户 private void btnSetStrCardNumber_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } //下发用户到机器 //1、设置卡号 //string CardNo = System.Convert.ToInt32(txtCardNo.Text, 16).ToString();//转换16进制到十进制 axCZKEM1.SetStrCardNumber(txtCardNo.Text); //2、设置用户信息 axCZKEM1.SSR_SetUserInfo(iMachineNumber, "用户ID", "用户姓名", "密码", 0, true); } #endregion
2-3、批量注册用户
#region 考勤机功能:批量注册用户 private void btnSetStrCardNumbers_Click(object sender, EventArgs e) { if (XCMessageBox.Show("确定?", XCMessageBox.Buttons.OKCancel, XCMessageBox.Icon.Question) == DialogResult.OK) { System.Data.DataTable dt = getEmp();//getEmp()获取数据库中需要注册的用户 string[] useruid = new string[dt.Rows.Count]; string[] useruname = new string[dt.Rows.Count]; string[] cardid = new string[dt.Rows.Count]; for (int i = 0; i < dt.Rows.Count; i++) { DataRow dr = dt.Rows[i]; useruid[i] = Convert.ToString(dr["T_USERID"]); useruname[i] = Convert.ToString(dr["T_USERNAME"]); cardid[i] = Convert.ToString(dr["CARDID"]); //16进制转10进制 //string CardNo = System.Convert.ToInt32(cardid[i], 16).ToString(); axCZKEM1.SetStrCardNumber(cardid[i]); //2、设置用户信息 bool a = axCZKEM1.SSR_SetUserInfo(iMachineNumber, useruid[i], useruname[i], useruid[i], 0, true); } } } #endregion
2-4、删除用户
#region 考勤机功能:删除用户 private void btnDelStrCardNumber_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } if (XCMessageBox.Show("确定?", XCMessageBox.Buttons.OKCancel, XCMessageBox.Icon.Question) == DialogResult.OK) { axCZKEM1.SSR_DeleteEnrollData(iMachineNumber, "用户ID", 12); } } #endregion
2-5、增删指纹
(这里有一点要注意:考勤机算法不同的话,增加指纹所调用的方法不同,使用前先查看考勤机算法)
#region 考勤机功能:增删指纹 private void btnDelTmp_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } if (XCMessageBox.Show("确定?", XCMessageBox.Buttons.OKCancel, XCMessageBox.Icon.Question) == DialogResult.OK) { bool a = axCZKEM1.SSR_DelUserTmp(iMachineNumber, "用户ID", "(int)第几个指纹"); //bool a = axCZKEM1.SSR_DeleteEnrollDataExt(iMachineNumber, txtEmpNo.Text, 13);//删除所有指纹 } } private void btnAddTmp_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } System.Data.DataTable dt = new System.Data.DataTable(); for (int i = 0; i < 10; i++) { //循环获取十个指纹 dt = getEmpTmp(i.ToString());//获取数据库中第i个指纹 for (int j = 0; j < dt.Rows.Count; j++) { //循环数据库中的用户数 USERID = dt.Rows[j]["数据库中用户ID"].ToString(); dwTmpData = dt.Rows[j]["数据库中第i个指纹"].ToString(); bool a = axCZKEM1.SetUserTmpExStr(iMachineNumber, USERID, i, 1, dwTmpData); } } //获取算法版本 /*string sValue; axCZKEM1.GetSysOption(1, "~ZKFPVersion", out sValue); txtInfo.Text = sValue;*/ } #endregion
2-6、清空考勤机所有注册的用户
#region 考勤机功能:清空考勤机用户 private void btnDel_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } if (XCMessageBox.Show("确定?", XCMessageBox.Buttons.OKCancel, XCMessageBox.Icon.Question) == DialogResult.OK) { Cursor = Cursors.WaitCursor; //先禁用机器 axCZKEM1.EnableDevice(iMachineNumber, false);//disable the device //获取所有用户的记录到缓存区 axCZKEM1.ReadAllUserID(iMachineNumber);//获取所有信息到缓存区(提高效率) while (axCZKEM1.SSR_GetAllUserInfo(iMachineNumber, out sdwEnrollNumber, out sName, out sPassword, out iPrivilege, out bEnabled))//get user information from memory { axCZKEM1.SSR_DeleteEnrollDataExt(iMachineNumber, sdwEnrollNumber, 12); } axCZKEM1.EnableDevice(iMachineNumber, true);//enable the device Cursor = Cursors.Default; } } #endregion
2-7、清空考勤机所有刷卡记录
#region 考勤机功能:清空考勤记录 private void btnDelLogData_Click(object sender, EventArgs e) { if (bIsConnected == false) { MessageBox.Show("Please connect the device first!", "Error"); return; } if (XCMessageBox.Show("确定?", XCMessageBox.Buttons.OKCancel, XCMessageBox.Icon.Question) == DialogResult.OK) { axCZKEM1.ClearGLog(iMachineNumber); } } #endregion