Pre-release v1.0

This commit is contained in:
2026-01-23 00:34:28 +09:00
parent 25e04889c2
commit d43d90ac1e
7 changed files with 354 additions and 76 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
test/
temp/
test.py
# ---> Python

224
handlers.py Normal file
View File

@@ -0,0 +1,224 @@
import asyncio
import socket
import time
import logging
import datetime
from aiogram import Router, F
from aiogram import Bot, Dispatcher, types
from aiogram.filters.command import Command
from aiogram.types import FSInputFile
from aiogram.fsm.context import FSMContext
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.fsm.state import StatesGroup, State
from aiogram.utils.chat_action import ChatActionSender
#from aiogram.types import BufferedInputFile
import configparser
from asyncpg_lite import DatabaseManager
from os import listdir
from os.path import isfile, join
import lib.OCer as OCer
import serial
router = Router()
async def get_user_list(db_url, deletion_password, table_name):
try:
db_manager = DatabaseManager(db_url=db_url, deletion_password=deletion_password)
data = []
async with db_manager as manager:
one_data = await manager.select_data(table_name=table_name)
for i in one_data:
data.append(i)
logging.info(f"Fetched {len(data)} records from the database.")
return data
except Exception as err:
logging.error(err)
pass
def init(Bot):
global config, bot, logger, some_open_ports, zxc
bot = Bot
#consts&confs
config = configparser.ConfigParser()
#bc_calculator = lomka.BCCCalculator()
some_open_ports = serial.tools.list_ports.comports()
#load config file
config.read('config.ini')
# device_hwid = config['DEFAULT']['device_hwid']
# baudrate = config['DEFAULT']['baudrate']
#log section
logging.basicConfig(
level=logging.INFO if config['DEFAULT']['debug'] == "false" else logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('lastest.log'),
logging.StreamHandler()])
logger = logging.getLogger(socket.gethostname())
zxc = OCer.caser(device_hwid="PID=1A86:7523", baudrate=9600,
config=config, logger=logger)
zxc.set_controller_number(1)
zxc.set_port_device()
main_kb = [
[types.KeyboardButton(text="Выбрать контроллер")],
[types.KeyboardButton(text="Открыть секцию")],
[types.KeyboardButton(text="Статус секции")],
[types.KeyboardButton(text="Статус ВСЕХ секций")],
[types.KeyboardButton(text="Открыть ВСЕ секции")],
[types.KeyboardButton(text="Контакты")]]
keyboardos = types.ReplyKeyboardMarkup(keyboard=main_kb, resize_keyboard=True,
input_field_placeholder="amogus life420")
class Form(StatesGroup):
input_controller = State()
input_section = State()
input_status_section = State()
input_status_section_all = State()
input_approve = State()
@router.message(Command("start"))
async def cmd_start(message: types.Message):
keyboard = types.ReplyKeyboardMarkup(keyboard=main_kb, resize_keyboard=True,
input_field_placeholder="Выберите действие...", is_persistent=True)
await message.answer(f"{message.from_user.id}\n",
reply_markup=keyboard)
@router.message(F.text.lower() == "выбрать контроллер")
async def choose_controller(message: types.Message, state: FSMContext):
kb = [
[types.KeyboardButton(text="Домой")]
]
keyboard = types.ReplyKeyboardMarkup(keyboard=kb, resize_keyboard=True,
input_field_placeholder="amogus life420")
await message.reply("Определите номер управляемого контроллера", reply_markup=keyboard)
await state.set_state(Form.input_controller)
@router.message(F.text, Form.input_controller)
async def set_controller_number(message: types.Message, state: FSMContext):
await state.update_data(confirm=message.text)
user_data = await state.get_data()
try:
await zxc.set_controller_capacity(int(user_data["confirm"]))
await message.reply(f"Контроллер ({user_data["confirm"]}) выбран успешно!",
reply_markup=keyboardos)
except Exception as e:
await message.reply(f"Возникло исключение(ошибка): {e}", reply_markup=keyboardos)
await state.clear()
@router.message(F.text.lower() == "статус всех секций")
async def status_all_sections(message: types.Message, state: FSMContext):
cool_data = await zxc.READ_ALL_CELLS()
await message.reply(f"{cool_data}", reply_markup=keyboardos)
await state.clear()
@router.message(F.text.lower() == "открыть все секции")
async def open_all_sections(message: types.Message, state: FSMContext):
kb = [
[types.KeyboardButton(text="Продолжить")],
[types.KeyboardButton(text="Домой")]
]
keyboard = types.ReplyKeyboardMarkup(keyboard=kb, resize_keyboard=True,
input_field_placeholder="amogus life420")
await message.reply("Данная операция откроет ВСЕ секции доступные контроллеру.\nПродолжить?", reply_markup=keyboard)
await state.set_state(Form.input_approve)
@router.message(F.text, Form.input_approve)
async def open_all_sections_confirm(message: types.Message, state: FSMContext):
await state.update_data(confirm=message.text)
user_data = await state.get_data()
if str(user_data["confirm"]).lower() == "продолжить":
try:
cool_data = await zxc.OPEN_ALL_CELLS_LEGACY(True)
await message.reply(f"Статус ячеек:\n{cool_data}",
reply_markup=keyboardos)
except Exception as e:
await message.reply(f"Возникло исключение(ошибка): {e}", reply_markup=keyboardos)
await state.clear()
@router.message(F.text.lower() == "контакты")
async def contact_info(message: types.Message):
keyboard = types.ReplyKeyboardMarkup(keyboard=main_kb, resize_keyboard=True,
input_field_placeholder="amogus life420")
await message.reply("Настучать админу: \n" \
"Discord: Valo#1234 | @valoker\n" \
"GitHub: @Valoker\n" \
"Telegram: @Valoka", reply_markup=keyboard)
@router.message(F.text.lower() == "домой")
async def home(message: types.Message, state: FSMContext):
await message.answer(reply_markup=keyboardos,
text="Меню")
await state.clear()
@router.message(F.text.lower() == "открыть секцию")
async def open_section(message: types.Message, state: FSMContext):
kb = [
[types.KeyboardButton(text="Домой")]
]
keyboard = types.ReplyKeyboardMarkup(keyboard=kb, resize_keyboard=True,
input_field_placeholder="amogus life420")
await message.reply("Отправьте номер секции для открытия..", reply_markup=keyboard)
await state.set_state(Form.input_section)
@router.message(F.text, Form.input_section)
async def open_section_number(message: types.Message, state: FSMContext):
await state.update_data(confirm=message.text)
user_data = await state.get_data()
try:
await zxc.open_cell(int(user_data["confirm"]))
await message.reply(f"Секция ({user_data["confirm"]}) контроллера " \
f"({zxc.controller_number}) открыта.",
reply_markup=keyboardos)
except Exception as e:
await message.reply(f"Возникло исключение(ошибка): {e}", reply_markup=keyboardos)
await state.clear()
@router.message(F.text.lower() == "статус секции")
async def get_section_status(message: types.Message, state: FSMContext):
kb = [
[types.KeyboardButton(text="Домой")]
]
keyboard = types.ReplyKeyboardMarkup(keyboard=kb, resize_keyboard=True,
input_field_placeholder="amogus life420")
await message.reply("Отправьте номер желаемой секции..", reply_markup=keyboard)
await state.set_state(Form.input_status_section)
@router.message(F.text, Form.input_status_section)
async def get_section_status_fin(message: types.Message, state: FSMContext):
await state.update_data(confirm=message.text)
user_data = await state.get_data()
try:
controller_data = await zxc.read_controller(cell_number=int(user_data["confirm"]))
await message.reply(f"Секция ({user_data["confirm"]}) контроллера " \
f"({zxc.controller_number}) со статусом: {controller_data[0]["CURRENT_STATUS"]}. \n{controller_data}",
reply_markup=keyboardos)
except Exception as e:
await message.reply(f"Возникло исключение(ошибка): {e}", reply_markup=keyboardos)
await state.clear()

View File

@@ -1,6 +1,4 @@
import serial.tools.list_ports
import time
import configparser
import logging
import socket
import lib.lomka as lomka
@@ -28,7 +26,7 @@ class caser:
config.read(config_name)
self.device_hwid = config['DEFAULT']['device_hwid']
self.baudrate = config['DEFAULT']['baudrate']
self.controller_capacity = config['DEFAULT']['controller_capacity']
self.controller_capacity = int(config['DEFAULT']['controller_capacity'])
# узнать какое исключение вызывается конкретно, ибо нужно проверять каждое по отдельности
except:
@@ -41,8 +39,9 @@ class caser:
self.comport: str # только адрес
self.active_comport = serial.tools.list_ports.comports()[0] # объект порта (dummy)
self.controller_number: bytes = 1
self.connection : serial.Serial
#self.connection : serial.Serial
self.async_connection : tuple
self.instance_error_count : int = 0
# Определение базовых констант/команд
self.default_consts = {True: 17,
@@ -62,14 +61,6 @@ class caser:
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'''
@@ -84,13 +75,13 @@ class caser:
self.controller_number = hex(controller_number)
async def send_command(self, cell_number : int, command: int,
bytes_count=15, header=138):
bytes_count=5, header=138):
try:
# active_comport = serial.Serial(self.comport, baudrate=self.baudrate, timeout=2)
reader, writer = await serial_asyncio.open_serial_connection(
url=self.comport,
baudrate=self.baudrate
)
baudrate=self.baudrate,
timeout=2)
self.logger.info(f"Connected to {self.comport}")
@@ -112,11 +103,19 @@ class caser:
return await reader.read(bytes_count)
except Exception as error:
self.logger.error(f"{error}")
raise error
async def read_controller(self, cell_number : int, command=51,
header=128, bytes_count=5):
try:
# active_comport = serial.Serial(self.comport, baudrate=self.baudrate, timeout=2)
reader, writer = await serial_asyncio.open_serial_connection(
url=self.comport,
baudrate=self.baudrate
)
self.logger.info(f"Connected to {self.comport}")
def read_controller(self, cell_number : int, command=51, header=128):
active_comport = serial.Serial(self.comport, baudrate=self.baudrate, timeout=2)
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'),
@@ -129,73 +128,98 @@ class caser:
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)
writer.write(data_string)
return await reader.read(bytes_count)
except Exception as error:
raise error
def READ_ALL_CELLS(self):
async def open_cell(self, cell_number):
'''открывает замок по номеру'''
try:
result = []
answer = await self.send_command(cell_number=cell_number,
command=self.default_consts[True],
bytes_count=self.default_consts["RESPONSE_LENGHT"],
header=self.default_consts["MANIPULATE_HEADER"])
result.append({"CELL_NUMBER": cell_number,
"CURRENT_STATUS": True if answer[-2] == 17 else False if answer[-2] == 0 else None,
"FULL_ANSWER": answer})
return result
except Exception as error:
self.logger.error(f"{error}")
self.instance_error_count += 1
return str(error)
async def READ_ALL_CELLS(self):
'''и возвращает состояние всех замков'''
try:
result = []
for i in range(0, self.controller_capacity - 1):
answer = self.send_command(cell_number=i,
for i in range(1, self.controller_capacity + 1):
answer = await self.send_command(cell_number=i,
command=self.default_consts["INFO"],
bytes_count=self.default_consts["RESPONSE_LENGHT"],
header=self.default_consts["READ_HEADER"])
result.append({"CELL_NUMBER": i,
"CURRENT_STATUS": True if answer[-2] == 17 else False,
"CURRENT_STATUS": True if answer[-2] == 17 else False if answer[-2] == 0 else None,
"FULL_ANSWER": answer})
return result
except Exception as error:
self.logger.error(f"{error}")
self.instance_error_count += 1
return str(error)
def OPEN_ALL_CELLS_LEGACY(self, confirm : bool):
async def set_controller_capacity_unsafe(self, capacity: int = 0):
'''Устанавливает количество доступных замков'''
if capacity >= 0:
self.controller_capacity = capacity
# else:
# # target max capatity
# self.controller_capacity = 128
# result = await self.READ_ALL_CELLS()
# if isinstance(result, list):
# self.controller_capacity = len(result)
# self.logger.info(f"Controller capacity set to {self.controller_capacity}")
# else:
# self.logger.error("READ_ALL_CELLS() failed")
# return False
async def OPEN_ALL_CELLS_LEGACY(self, confirm : bool):
'''Открывает все замки вручную и возвращает состояние всех замков
Confirm - подтверждение операции'''
if confirm:
try:
result = []
for i in range(1, self.controller_capacity + 1):
answer = self.send_command(cell_number=i,
answer = await self.send_command(cell_number=i,
command=self.default_consts[True],
bytes_count=self.default_consts["RESPONSE_LENGHT"],
header=self.default_consts["MANIPULATE_HEADER"])
result.append({"CELL_NUMBER": i,
"CURRENT_STATUS": True if answer[-2] == 17 else False,
"CURRENT_STATUS": True if answer[-2] == 17 else False if answer[-2] == 0 else None,
"FULL_ANSWER": answer})
return result
except Exception as error:
self.logger.error(f"{error}")
self.instance_error_count += 1
return str(error)
else:
return 1
def set_controller_capacity(self, capacity=0) -> str:
async 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
try:
# написать
count = await 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)
# async def create_async_connection(self):
# try:
# self.async_connection = await serial_asyncio.open_serial_connection(
# url=self.comport,
# baudrate=self.baudrate
# )
# self.logger.info(f"Async connection to {self.comport}")
# except Exception as error:
# self.logger.error(f"Async connection error: {error}")
# pass
#хочу асинхронности
async def watchdog(self):
'''Слушает контролер в реальном времени и возвращает bytearray с событием'''
try:
@@ -212,9 +236,11 @@ class caser:
except Exception as error:
self.logger.error(f"{error}")
self.instance_error_count = self.instance_error_count + 1
writer.close()
await writer.wait_closed()
except Exception as error:
self.logger.critical(f"{error}")
self.instance_error_count = self.instance_error_count + 1

View File

@@ -1 +1,4 @@
pyserial
asyncpg_lite
pyserial-asyncio
aiogram

23
start-tg.py Normal file
View File

@@ -0,0 +1,23 @@
import asyncio
from aiogram import Router, F
from aiogram import Bot, Dispatcher
import configparser
import os
from asyncpg_lite import DatabaseManager
import handlers
token = configparser.ConfigParser()
token.read('temp/token.ini', encoding='utf-8-sig')
bot = Bot(token=token.get("Main", "token"))
handlers.init(bot)
async def main():
dp = Dispatcher()
dp.include_routers(handlers.router)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())

View File

@@ -4,7 +4,6 @@ import configparser
import serial
import socket
import asyncio
import time
if __name__ == "__main__":
#consts&confs
@@ -30,20 +29,22 @@ if __name__ == "__main__":
config=config, logger=logger)
zxc.set_controller_number(1)
zxc.set_port_device()
zxc.set_controller_capacity(18)
# добавь *aargs
#print(zxc.READ_ALL_CELLS())
#print(zxc.OPEN_ALL_CELLS_LEGACY(True))
# print(zxc.read_controller(1))
# print(zxc.read_controller(1))
async def main(zxc):
# await zxc.set_controller_capacity(18)
print(await zxc.send_command(1, 17))
exit()
# print(await zxc.watchdog())
# print(await zxc.OPEN_ALL_CELLS_LEGACY(True))
#print(await zxc.READ_ALL_CELLS())
# print(await zxc.read_controller(1))
# print(await zxc.send_command(1, 17))
# print(await zxc.open_cell(1))
# print(await zxc.set_controller_capacity_unsafe(18))
# print(await zxc.READ_ALL_CELLS())
pass
while True:
asyncio.run(main(zxc))