Files
opencaser/lib/OCer.py
2026-01-18 19:32:43 +09:00

161 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import serial.tools.list_ports
import time
import configparser
import logging
import socket
import lib.lomka as lomka
class caser:
#добавить по умолчанию с конфигом
def __init__(self, device_hwid, config,
logger=logging.getLogger(socket.gethostname()), baudrate=9600,
bc_calculator=lomka.BCCCalculator, config_name="config.ini"):
'''
Создает объект контроллера, к которому прикрепленна информация о существующем
локере.
connection - объект активного соединения с контроллером
device_hwid - pid USB конвертера(необязательно USB)
пример: "PID=1A86:7523"
logger - logging.getLogger() object
baudrate - скорость соединения
bc_calculator - метод вычисления хеш-суммы (должен возвращать один байт в int)
config_name - имя до файла конфигурации
'''
try:
config.read(config_name)
self.device_hwid = config['DEFAULT']['device_hwid']
self.baudrate = config['DEFAULT']['baudrate']
self.controller_capacity = config['DEFAULT']['controller_capacity']
# узнать какое исключение вызывается конкретно, ибо нужно проверять каждое по отдельности
except:
self.device_hwid = device_hwid
self.baudrate = baudrate
self.controller_capacity: int
self.logger = logger
self.bc_calculator = bc_calculator # xor_bcc method(returns int)
self.comport: str # только адрес
self.active_comport = serial.tools.list_ports.comports()[0] # объект порта (dummy)
self.controller_number: bytes = 1
self.connection : serial.Serial
# Определение базовых констант/команд
self.default_consts = {True: 17,
False: 0,
"INFO": 51,
"READ_HEADER": 128,
"RESPONSE_LENGHT": 5,
"MANIPULATE_HEADER": 138}
def find_comport(self, some_open_ports : list):
'''Находит и возвращает корректный comport (объект)'''
for port in some_open_ports:
self.logger.debug(f'{port.location}, {port.description}, {port.hwid}')
if self.device_hwid in port.hwid:
self.logger.info(f"Found the correct port: {port.device}")
return str(port.device)
def set_controller_capacity(self, capacity: int):
'''Устанавливает количество доступных замков'''
#сделать автоматом
if capacity:
self.controller_capacity = capacity
else:
self.controller_capacity = 18
def set_port_device(self, port_device=None):
'''Устанавливает com port'''
if port_device is None:
self.comport = self.find_comport(serial.tools.list_ports.comports())
else:
self.comport = port_device
def set_controller_number(self, controller_number : int):
'''Определяет номер контроллера. Значения хранятся в виде bytes'''
self.controller_number = hex(controller_number)
def send_command(self, cell_number : int, command : int,
bytes_count=5, header=138):
active_comport = serial.Serial(self.comport, baudrate=self.baudrate)
self.logger.info(f"Connected to {active_comport.name }")
# 1 - header(8Ahex) (138dec), 2 - controller number(01), 3 - cell number(04), 4 - command(11), 5 - checksum(9E)
# *4 - (11) - open, (00) - close
data = [int(header).to_bytes(1, 'little'),
int(self.controller_number, 16).to_bytes(1, 'little'),
cell_number.to_bytes(1, 'little'),
command.to_bytes(1, 'little')]
data_string = b''
for i in data:
data_string += i
checksum = self.bc_calculator.xor_bcc(data_string)
data_string += checksum.to_bytes(1, 'little')
active_comport.write(data_string)
return active_comport.read(bytes_count)
def read_controller(self, cell_number : int, command=51, header=128):
active_comport = serial.Serial(self.comport, baudrate=self.baudrate)
self.logger.info(f"Connected to {active_comport.name }")
data = [header.to_bytes(1, 'little'),
int(self.controller_number, 16).to_bytes(1, 'little'),
cell_number.to_bytes(1, 'little'),
command.to_bytes(1, 'little')]
data_string = b''
for i in data:
data_string += i
checksum = self.bc_calculator.xor_bcc(data_string)
data_string += checksum.to_bytes(1, 'little')
active_comport.write(data_string)
return active_comport.read(5)
def READ_ALL_LOCKS(self):
# try:
return self.send_command(0, self.default_consts["INFO"],
5,
header=self.default_consts["READ_HEADER"])
# except Exception as error:
# return str(error)
def OPEN_ALL_LOCKS(self, confirm : bool):
'''и возвращает состояние всех замков'''
if confirm:
try:
return self.send_command(0, self.default_consts[True],
self.default_consts["READ_HEADER"],
bytes_count=self.controller_capacity)
except Exception as error:
return str(error)
else:
return 1
def set_controller_capacity(self, capacity=0) -> str:
'''Устанавливает количество доступных замков'''
if capacity != 0:
self.controller_capacity = capacity
return self.controller_capacity
else:
# тут должно быть автоматическое определение кол-ва замков на контроллере
# try:
# return self.send_command(0, self.default_consts[True],
# self.default_consts["MANIPULATE_HEADER"],
# bytes_count=self.controller_capacity)
# except Exception as error:
# return str(error)
pass
def watchdog(self):
pass