You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							650 lines
						
					
					
						
							29 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							650 lines
						
					
					
						
							29 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ################################################################################ | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| # | |
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |
| #    Author: Cybrosys Techno Solutions (odoo@cybrosys.com) | |
| # | |
| #    You can modify it under the terms of the GNU AFFERO | |
| #    GENERAL PUBLIC LICENSE (AGPL v3), Version 3. | |
| # | |
| #    This program is distributed in the hope that it will be useful, | |
| #    but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |
| #    GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. | |
| # | |
| #    You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE | |
| #    (AGPL v3) along with this program. | |
| #    If not, see <http://www.gnu.org/licenses/>. | |
| # | |
| ################################################################################ | |
| import base64 | |
| import binascii | |
| import datetime | |
| import logging | |
| import threading | |
| from threading import Thread | |
| import time | |
| import pytz | |
| from odoo import api, fields, models, registry, _ | |
| from odoo.exceptions import UserError, ValidationError | |
| live_capture_thread = None | |
| _logger = logging.getLogger(__name__) | |
| try: | |
|     from zk import const, ZK | |
|     from zk.finger import Finger | |
| except ImportError: | |
|     _logger.error("Please Install pyzk library.") | |
| 
 | |
| 
 | |
| class BiometricDeviceDetails(models.Model): | |
|     """Model for configuring and connect the biometric device with odoo""" | |
|     _name = 'biometric.device.details' | |
|     _description = 'Biometric Device Details' | |
|     _inherit = ['mail.thread', 'mail.activity.mixin'] | |
| 
 | |
|     name = fields.Char(string='Name', required=True, help='Record Name') | |
|     device_ip = fields.Char(string='Device IP', required=True, | |
|                             help='The IP address of the Device') | |
|     port_number = fields.Integer(string='Port Number', required=True, | |
|                                  help="The Port Number of the Device") | |
|     address_id = fields.Many2one('res.partner', string='Working Address', | |
|                                  help='Working address of the partner') | |
|     is_live_capture = fields.Boolean('Live Capturing', | |
|                                      help="if enabled, gets the live capture " | |
|                                           "from the device", | |
|                                      readonly=True) | |
|     company_id = fields.Many2one('res.company', string='Company', | |
|                                  default=lambda | |
|                                      self: self.env.user.company_id.id, | |
|                                  help='Current Company') | |
|     stopwatch_time = fields.Float('Stopwatch timer', | |
|                                   help='Time from Live capture enabled') | |
|     device_name = fields.Char(String='Device Name', readonly=True, | |
|                               help='Device Name') | |
|     device_firmware = fields.Char(String='Device Firmware Version', | |
|                                   readonly=True, help='Device Firmware') | |
|     device_serial_no = fields.Char(String='Device Serial No', readonly=True, | |
|                                    help='Device serial No') | |
|     device_platform = fields.Char(String='Device Platform', readonly=True, | |
|                                   help='Device platform') | |
|     device_mac = fields.Char(String='Device Mac ID', readonly=True, | |
|                              help='Device Mac') | |
|     live_capture_start_time = fields.Datetime('Live Capture Time', | |
|                                               help='The Time When Live ' | |
|                                                    'Capture Enabled') | |
| 
 | |
|     def device_connect(self, zk): | |
|         """Function for connecting the device with Odoo""" | |
|         try: | |
|             conn = zk.connect() | |
|             return conn | |
|         except Exception: | |
|             return False | |
| 
 | |
|     def action_test_connection(self): | |
|         """Checking the connection status""" | |
|         zk = ZK(self.device_ip, port=self.port_number, timeout=30, | |
|                 password=False, ommit_ping=False) | |
|         try: | |
|             if zk.connect(): | |
|                 zk.test_voice(index=0) | |
|                 return { | |
|                     'type': 'ir.actions.client', | |
|                     'tag': 'display_notification', | |
|                     'params': { | |
|                         'message': 'Successfully Connected', | |
|                         'type': 'success', | |
|                         'sticky': False | |
|                     } | |
|                 } | |
| 
 | |
|         except Exception as error: | |
|             raise ValidationError(f'{error}') | |
| 
 | |
|     def action_clear_attendance(self): | |
|         """Methode to clear record from the zk.machine.attendance model and | |
|         from the device""" | |
|         for info in self: | |
|             try: | |
|                 machine_ip = info.device_ip | |
|                 zk_port = info.port_number | |
|                 try: | |
|                     # Connecting with the device | |
|                     zk = ZK(machine_ip, port=zk_port, timeout=30, | |
|                             password=0, force_udp=False, ommit_ping=False) | |
|                 except NameError: | |
|                     raise UserError(_( | |
|                         "Please install it with 'pip3 install pyzk'.")) | |
|                 conn = self.device_connect(zk) | |
|                 if conn: | |
|                     conn.enable_device() | |
|                     clear_data = zk.get_attendance() | |
|                     if clear_data: | |
|                         # Clearing data in the device | |
|                         conn.clear_attendance() | |
|                         # Clearing data from attendance log | |
|                         self._cr.execute( | |
|                             """delete from zk_machine_attendance""") | |
|                         current_time = fields.datetime.now().strftime( | |
|                             '%Y-%m-%d %H:%M:%S') | |
|                         message = (f'Attendances Are cleared from the Device on' | |
|                                    f' {current_time} By {self.env.user.name}') | |
|                         self.message_post(body=message) | |
|                         conn.disconnect() | |
|                     else: | |
|                         raise UserError( | |
|                             _('Unable to clear Attendance log.Are you sure ' | |
|                               'attendance log is not empty.')) | |
|                 else: | |
|                     raise UserError( | |
|                         _('Unable to connect to Attendance Device. Please use ' | |
|                           'Test Connection button to verify.')) | |
|             except Exception as error: | |
|                 raise ValidationError(f'{error}') | |
| 
 | |
|     def action_download_attendance(self): | |
|         """Function to download attendance records from the device""" | |
|         _logger.info("++++++++++++Cron Executed++++++++++++++++++++++") | |
|         zk_attendance = self.env['zk.machine.attendance'] | |
|         hr_attendance = self.env['hr.attendance'] | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             self.get_device_information() | |
|             if conn: | |
|                 conn.disable_device() | |
|                 self.get_all_users() | |
|                 self.action_set_timezone() | |
|                 user = conn.get_users() | |
|                 # get All Fingerprints | |
|                 fingers = conn.get_templates() | |
|                 for use in user: | |
|                     for finger in fingers: | |
|                         if finger.uid == use.uid: | |
|                             templates = conn.get_user_template(uid=use.uid, | |
|                                                                temp_id=finger.fid, | |
|                                                                user_id=use.user_id) | |
|                             hex_data = templates.template.hex() | |
|                             # Convert hex data to binary | |
|                             binary_data = binascii.unhexlify(hex_data) | |
|                             base64_data = base64.b64encode(binary_data).decode( | |
|                                 'utf-8') | |
|                             employee = self.env['hr.employee'].search( | |
|                                 [('device_id_num', '=', use.user_id)]) | |
|                             employee.write({ | |
|                                 'device_id': self.id, | |
|                             }) | |
|                             if str(finger.fid) in employee.fingerprint_ids.mapped( | |
|                                     'finger_id'): | |
|                                 employee.fingerprint_ids.search( | |
|                                     [('finger_id', '=', finger.fid)]).update({ | |
|                                     'finger_template': base64_data, | |
|                                 }) | |
|                             else: | |
|                                 employee.fingerprint_ids.create({ | |
|                                     'finger_template': base64_data, | |
|                                     'finger_id': finger.fid, | |
|                                     'employee_id': employee.id, | |
|                                     'filename': f'{employee.name}-finger-{finger.fid}' | |
|                                 }) | |
|                 # get all attendances | |
|                 attendance = conn.get_attendance() | |
|                 if attendance: | |
|                     for each in attendance: | |
|                         atten_time = each.timestamp | |
|                         local_tz = pytz.timezone( | |
|                             self.env.user.partner_id.tz or 'GMT') | |
|                         local_dt = local_tz.localize(atten_time, is_dst=None) | |
|                         utc_dt = local_dt.astimezone(pytz.utc) | |
|                         utc_dt = utc_dt.strftime("%Y-%m-%d %H:%M:%S") | |
|                         atten_time = datetime.datetime.strptime( | |
|                             utc_dt, "%Y-%m-%d %H:%M:%S") | |
|                         atten_time = fields.Datetime.to_string(atten_time) | |
|                         for uid in user: | |
|                             if uid.user_id == each.user_id: | |
|                                 get_user_id = self.env['hr.employee'].search( | |
|                                     [('device_id_num', '=', each.user_id)]) | |
|                                 if get_user_id: | |
|                                     duplicate_atten_ids = zk_attendance.search( | |
|                                         [('device_id_num', '=', each.user_id), | |
|                                          ('punching_time', '=', atten_time)]) | |
|                                     if not duplicate_atten_ids: | |
|                                         zk_attendance.create({ | |
|                                             'employee_id': get_user_id.id, | |
|                                             'device_id_num': each.user_id, | |
|                                             'attendance_type': str(each.status), | |
|                                             'punch_type': str(each.punch), | |
|                                             'punching_time': atten_time, | |
|                                             'address_id': info.address_id.id | |
|                                         }) | |
|                                         att_var = hr_attendance.search([( | |
|                                             'employee_id', '=', get_user_id.id), | |
|                                             ('check_out', '=', False)]) | |
|                                         if each.punch == 0:  # check-in | |
|                                             if not att_var: | |
|                                                 hr_attendance.create({ | |
|                                                     'employee_id': | |
|                                                         get_user_id.id, | |
|                                                     'check_in': atten_time | |
|                                                 }) | |
|                                         if each.punch == 1:  # check-out | |
|                                             if len(att_var) == 1: | |
|                                                 att_var.write({ | |
|                                                     'check_out': atten_time | |
|                                                 }) | |
|                                             else: | |
|                                                 att_var1 = hr_attendance.search( | |
|                                                     [('employee_id', '=', | |
|                                                       get_user_id.id)]) | |
|                                                 if att_var1: | |
|                                                     att_var1[-1].write({ | |
|                                                         'check_out': atten_time | |
|                                                     }) | |
|                                 else: | |
|                                     employee = self.env['hr.employee'].create({ | |
|                                         'device_id_num': each.user_id, | |
|                                         'device_id': self.id, | |
|                                         'name': uid.name | |
|                                     }) | |
|                                     zk_attendance.create({ | |
|                                         'employee_id': employee.id, | |
|                                         'device_id_num': each.user_id, | |
|                                         'attendance_type': str(each.status), | |
|                                         'punch_type': str(each.punch), | |
|                                         'punching_time': atten_time, | |
|                                         'address_id': info.address_id.id | |
|                                     }) | |
|                                     hr_attendance.create({ | |
|                                         'employee_id': employee.id, | |
|                                         'check_in': atten_time | |
|                                     }) | |
|                     if not self.is_live_capture: | |
|                         current_time = fields.datetime.now().strftime( | |
|                             '%Y-%m-%d %H:%M:%S') | |
|                         message = (f'Downloaded data from the device on ' | |
|                                    f'{current_time} by {self.env.user.name}') | |
|                         self.message_post(body=message) | |
|                     conn.disconnect() | |
|                     return True | |
|                 else: | |
|                     zk.test_voice(index=4) | |
|                     raise UserError(_('Unable to get the attendance log, please' | |
|                                       'try again later.')) | |
|             else: | |
|                 raise UserError(_('Unable to connect, please check the' | |
|                                   'parameters and network connections.')) | |
| 
 | |
|     def action_restart_device(self): | |
|         """For restarting the device""" | |
|         zk = ZK(self.device_ip, port=self.port_number, timeout=15, | |
|                 password=0, | |
|                 force_udp=False, ommit_ping=False) | |
|         if self.device_connect(zk): | |
|             if self.is_live_capture: | |
|                 self.action_stop_live_capture() | |
|             self.device_connect(zk).restart() | |
|             return { | |
|                 'type': 'ir.actions.client', | |
|                 'tag': 'display_notification', | |
|                 'params': { | |
|                     'message': 'Successfully Device Restarted', | |
|                     'type': 'success', | |
|                     'sticky': False | |
|                 } | |
|             } | |
|         else: | |
|             raise UserError(_( | |
|                 "Please Check the Connection")) | |
| 
 | |
|     def schedule_attendance(self): | |
|         """Schedule action for attendance downloading""" | |
|         for record in self.search([]): | |
|             if record.is_live_capture: | |
|                 record.action_stop_live_capture() | |
|                 record.action_download_attendance() | |
|                 record.action_live_capture() | |
|             else: | |
|                 record.action_download_attendance() | |
| 
 | |
|     def action_live_capture(self): | |
|         """ Enable Live capture With Thread""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 self.is_live_capture = True | |
|                 self.action_set_timezone() | |
|                 instance = ZKBioAttendance(machine_ip, zk_port, info) | |
|                 global live_capture_thread | |
|                 live_capture_thread = instance | |
|                 live_capture_thread.start() | |
|                 self.live_capture_start_time = fields.datetime.now() | |
|                 return { | |
|                     'type': 'ir.actions.client', | |
|                     'tag': 'reload', | |
|                 } | |
|             except NameError: | |
|                 raise UserError(_( | |
|                     "Please install it with 'pip3 install pyzk'.")) | |
| 
 | |
|     def action_stop_live_capture(self): | |
|         """Function to stop Live capture""" | |
|         try: | |
|             self.is_live_capture = False | |
|             if live_capture_thread: | |
|                 live_capture_thread.stop() | |
|             return { | |
|                 'type': 'ir.actions.client', | |
|                 'tag': 'reload', | |
|             } | |
|         except NameError: | |
|             raise UserError(_( | |
|                 "Please install it with 'pip3 install pyzk'.")) | |
| 
 | |
|     def action_set_timezone(self): | |
|         """Function to set user's timezone to device""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             if conn: | |
|                 user_tz = self.env.context.get( | |
|                     'tz') or self.env.user.tz or 'UTC' | |
|                 user_timezone_time = pytz.utc.localize(fields.Datetime.now()) | |
|                 user_timezone_time = user_timezone_time.astimezone( | |
|                     pytz.timezone(user_tz)) | |
|                 conn.set_time(user_timezone_time) | |
|                 return { | |
|                     'type': 'ir.actions.client', | |
|                     'tag': 'display_notification', | |
|                     'params': { | |
|                         'message': 'Successfully Set the Time', | |
|                         'type': 'success', | |
|                         'sticky': False | |
|                     } | |
|                 } | |
|             else: | |
|                 raise UserError(_( | |
|                     "Please Check the Connection")) | |
| 
 | |
|     def get_all_users(self): | |
|         """Function to get all user's details""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             if conn: | |
|                 users = conn.get_users() | |
|                 for user in users: | |
|                     employee = self.env['hr.employee'].search( | |
|                         [('device_id_num', '=', user.user_id), | |
|                          ('device_id', '=', self.id)]) | |
|                     if employee: | |
|                         employee.write({ | |
|                             'name': user.name, | |
|                         }) | |
|                     else: | |
|                         self.env['hr.employee'].create({ | |
|                             'name': user.name, | |
|                             'device_id_num': user.user_id, | |
|                             'device_id': self.id, | |
|                         }) | |
|             else: | |
|                 raise UserError(_( | |
|                     "Please Check the Connection")) | |
| 
 | |
|     def set_user(self, employee_id): | |
|         """Function to create or update users""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             employee = self.env['hr.employee'].browse(int(employee_id)) | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             if conn: | |
|                 last_user = conn.get_users()[-1] | |
|                 privilege = 0 | |
|                 password = '' | |
|                 group_id = '' | |
|                 card = 0 | |
|                 conn.enable_device() | |
|                 conn.disable_device() | |
|                 try: | |
|                     uids = [user.uid for user in conn.get_users()] | |
|                     candidate_uid = last_user.uid + 1 | |
|                     while candidate_uid in uids: | |
|                         candidate_uid += 1 | |
|                     conn.set_user(candidate_uid, employee.name, privilege, | |
|                                   password, group_id, str(candidate_uid), card) | |
|                 except Exception as e: | |
|                     _logger.info(e) | |
|                     raise ValidationError( | |
|                         _(" Here is the user information:\n" | |
|                           "uid: %s\n" | |
|                           "name: %s\n" | |
|                           "privilege: %s\n" | |
|                           "password: %s\n" | |
|                           "group_id: %s\n" | |
|                           "user_id: %s\n" | |
|                           "Here is the debugging information:\n%s\n" | |
|                           "Try Restarting the device") | |
|                         % (candidate_uid, employee.name, privilege, password, | |
|                            group_id, str(candidate_uid), e)) | |
|                 conn.enable_device() | |
|                 if conn.get_users()[-1].name in employee.name: | |
|                     employee.write({ | |
|                         'device_id': self.id, | |
|                         'device_id_num': conn.get_users()[-1].user_id | |
|                     }) | |
|                     current_time = fields.datetime.now().strftime( | |
|                         '%Y-%m-%d %H:%M:%S') | |
|                     message = (f'New User {employee.name} Created on ' | |
|                                f'{current_time} by {self.env.user.name}') | |
|                     self.message_post(body=message) | |
|             else: | |
|                 raise UserError(_( | |
|                     "Please Check the Connection")) | |
| 
 | |
|     def delete_user(self, employee_id, employee_user_selection): | |
|         """Function to Delete a user""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             if conn: | |
|                 employee = self.env['hr.employee'].browse(int(employee_id)) | |
|                 employee_name = employee.name | |
|                 conn.delete_user(uid=None, user_id=employee.device_id_num) | |
|                 employee.write({ | |
|                     'device_id_num': False, | |
|                     'device_id': False | |
|                 }) | |
|                 employee.fingerprint_ids.unlink() | |
|                 if employee_user_selection == 'both_device': | |
|                     employee.unlink() | |
|                 current_time = fields.datetime.now().strftime( | |
|                     '%Y-%m-%d %H:%M:%S') | |
|                 message = (f'Deleted User {employee_name} on ' | |
|                            f'{current_time} by {self.env.user.name}') | |
|                 self.message_post(body=message) | |
|             else: | |
|                 raise UserError(_( | |
|                     "Please Check the Connection")) | |
| 
 | |
|     def update_user(self, employee_id): | |
|         """Function to Update a user""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             if conn: | |
|                 conn.enable_device() | |
|                 conn.disable_device() | |
|                 employee = self.env['hr.employee'].browse(int(employee_id)) | |
|                 for line in conn.get_users(): | |
|                     if line.user_id == employee.device_id_num: | |
|                         privilege = 0 | |
|                         password = '' | |
|                         group_id = '' | |
|                         user_id = employee.device_id_num | |
|                         card = 0 | |
|                         conn.set_user(line.uid, employee.name, privilege, | |
|                                       password, group_id, user_id, card) | |
|                         conn.enable_device() | |
|                         return { | |
|                             'type': 'ir.actions.client', | |
|                             'tag': 'display_notification', | |
|                             'params': { | |
|                                 'message': 'Successfully Updated User', | |
|                                 'type': 'success', | |
|                                 'sticky': False | |
|                             } | |
|                         } | |
|                 else: | |
|                     raise UserError(_( | |
|                         "Please Check the Connection")) | |
| 
 | |
|     def get_device_information(self): | |
|         """Gets device Information""" | |
|         for info in self: | |
|             machine_ip = info.device_ip | |
|             zk_port = info.port_number | |
|             try: | |
|                 # Connecting with the device with the ip and port provided | |
|                 zk = ZK(machine_ip, port=zk_port, timeout=15, | |
|                         password=0, | |
|                         force_udp=False, ommit_ping=False) | |
|             except NameError: | |
|                 raise UserError( | |
|                     _("Pyzk module not Found. Please install it" | |
|                       "with 'pip3 install pyzk'.")) | |
|             conn = self.device_connect(zk) | |
|             if conn: | |
|                 self.device_name = conn.get_device_name() | |
|                 self.device_firmware = conn.get_firmware_version() | |
|                 self.device_serial_no = conn.get_serialnumber() | |
|                 self.device_platform = conn.get_platform() | |
|                 self.device_mac = conn.get_mac() | |
|             else: | |
|                 raise UserError(_( | |
|                     "Please Check the Connection")) | |
| 
 | |
| 
 | |
| class ZKBioAttendance(Thread): | |
|     """ | |
|     Represents a thread for capturing live attendance data from a ZKTeco | |
|     biometric device. | |
|  | |
|     Attributes: - machine_ip: The IP address of the ZKTeco biometric device. | |
|     - port_no: The port number for communication with the ZKTeco biometric | |
|     device. - conn: The connection object to the ZKTeco biometric device. | |
|  | |
|     Methods: - run(): Overrides the run method of the Thread class to capture | |
|     live attendance data. | |
|     """ | |
| 
 | |
|     def __init__(self, machine_ip, port_no, record): | |
|         """Function to Initialize the thread""" | |
|         Thread.__init__(self) | |
|         self.machine_ip = machine_ip | |
|         self.port_no = port_no | |
|         self.record = record | |
|         self.env = record.env | |
|         self.stop_event = threading.Event() | |
| 
 | |
|         zk_device = ZK( | |
|             machine_ip, | |
|             port=port_no, | |
|             timeout=5, | |
|             password=0, | |
|             force_udp=False, | |
|             ommit_ping=False, | |
|         ) | |
|         conn = zk_device.connect() | |
|         if conn: | |
|             self.conn = conn | |
|         else: | |
|             raise UserError(_( | |
|                 "Please Check the Connection")) | |
| 
 | |
|     def run(self): | |
|         """Function to run the Thread""" | |
|         while not self.stop_event.is_set(): | |
|             try: | |
|                 if not self.conn.end_live_capture: | |
|                     for attendance in self.conn.live_capture(2000): | |
|                         self._data_live_capture() | |
|                 time.sleep(10) | |
|             except Exception as e: | |
|                 self.env.cr.rollback()  # Rollback the current transaction | |
|                 time.sleep(1) | |
| 
 | |
|     def stop(self): | |
|         """Stops the live capture and stops the thread""" | |
|         if self.conn: | |
|             self.conn.end_live_capture = True | |
|         self.stop_event.set() | |
| 
 | |
|     def _data_live_capture(self): | |
|         """Updated the Live Capture real time""" | |
|         with registry(self.env.cr.dbname).cursor() as new_cr: | |
|             new_env = api.Environment(new_cr, self.env.uid, self.env.context) | |
|             if self.conn.get_attendance(): | |
|                 self.record.with_env(new_env).action_download_attendance() | |
|             new_cr.commit()
 | |
| 
 |