Обработка ошибок подключения к QUIK

This commit is contained in:
denis
2023-02-05 18:49:42 +00:00
parent 4835c35906
commit d31495c989
2 changed files with 50 additions and 14 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
__pycache__

View File

@@ -37,10 +37,14 @@ class QuikPy(metaclass=Singleton): # Singleton класс
fragments = [] # Будем получать ответ в виде списка фрагментов. Они могут быть разной длины. Ответ может состоять из нескольких фрагментов
while getattr(currentThread, 'process', True): # Пока поток нужен
while True: # Пока есть что-то в буфере ответов
fragment = socketCallbacks.recv(self.bufferSize) # Читаем фрагмент из буфера
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
break # то, возможно, это был последний фрагмент, выходим из чтения буфера
try:
fragment = socketCallbacks.recv(self.bufferSize) # Читаем фрагмент из буфера
except ConnectionResetError:
print("Соединение сброшено")
else:
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
break # то, возможно, это был последний фрагмент, выходим из чтения буфера
data = ''.join(fragments) # Собираем список фрагментов в строку
dataList = data.split('\n') # Одновременно могут прийти несколько функций обратного вызова, разбираем их по одной
fragments = [] # Сбрасываем фрагменты. Если последнюю строку не сможем разобрать, то занесем ее сюда
@@ -111,10 +115,32 @@ class QuikPy(metaclass=Singleton): # Singleton класс
def ProcessRequest(self, Request):
"""Отправляем запрос в QUIK, получаем ответ из QUIK"""
rawData = json.dumps(Request) # Переводим запрос в формат JSON
self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
# self.socketRequests.settimeout(1)
# print(self.socketRequests.timeout)
# self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
try:
self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
except Exception:
# raise TimeoutError("Истёк таймаут подключения к QUIK")
print("Истёк таймаут подключения к QUIK")
data = {"data": "error"}
return data
fragments = [] # Гораздо быстрее получать ответ в виде списка фрагментов
while True: # Пока фрагменты есть в буфере
fragment = self.socketRequests.recv(self.bufferSize) # Читаем фрагмент из буфера
# print(fragments)
try:
fragment = self.socketRequests.recv(self.bufferSize) # Читаем фрагмент из буфера
assert len(fragment) > 0
except (TimeoutError, AssertionError):
print("Истёк таймаут подключения к QUIK")
data = {"data": "error"}
return data
except ConnectionResetError:
print("Соединение сброшено")
data = {"data": "error"}
return data
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
data = ''.join(fragments) # Собираем список фрагментов в строку
@@ -125,7 +151,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
# Инициализация и вход
def __init__(self, Host='127.0.0.1', RequestsPort=34130, CallbacksPort=34131):
def __init__(self, Host='127.0.0.1', RequestsPort=34130, CallbacksPort=34131, connection_timeout=None):
"""Инициализация"""
# 2.2. Функции обратного вызова
self.OnFirm = self.DefaultHandler # 1. Новая фирма
@@ -162,17 +188,25 @@ class QuikPy(metaclass=Singleton): # Singleton класс
self.RequestsPort = RequestsPort # Порт для отправки запросов и получения ответов
self.CallbacksPort = CallbacksPort # Порт для функций обратного вызова
self.socketRequests = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Создаем соединение для запросов
self.socketRequests.connect((self.Host, self.RequestsPort)) # Открываем соединение для запросов
if connection_timeout is not None:
self.socketRequests.settimeout(connection_timeout)
self.callbackThread = threading.Thread(target=self.CallbackHandler,
name='CallbackThread') # Создаем поток обработки функций обратного вызова
try:
self.socketRequests.connect((self.Host, self.RequestsPort)) # Открываем соединение для запросов
except TimeoutError:
raise ConnectionError("Истёк таймаут подключения к QUIK")
else:
self.callbackThread.start() # Запускаем поток
self.callbackThread = threading.Thread(target=self.CallbackHandler, name='CallbackThread') # Создаем поток обработки функций обратного вызова
self.callbackThread.start() # Запускаем поток
def __enter__(self):
"""Вход в класс, например, с with"""
return self
# Фукнции связи с QuikSharp
def Ping(self, TransId=0):
"""Проверка соединения. Отправка ping. Получение pong"""
return self.ProcessRequest({'data': 'Ping', 'id': TransId, 'cmd': 'ping', 't': ''})
@@ -221,7 +255,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
# isDarkTheme - 9. Тема оформления. true - тёмная, false - светлая
# Сервисные функции QuikSharp
def MessageInfo(self, Message, TransId=0): # В QUIK LUA message icon_type=1
"""Отправка информационного сообщения в терминал QUIK"""
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'message', 't': ''})
@@ -250,7 +284,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
def GetTradeAccount(self, ClassCode, TransId=0):
"""Торговый счет для запрашиваемого кода класса"""
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getTradeAccount', 't': ''})
def GetAllOrders(self, TransId=0):
"""Таблица заявок (вся)"""
return self.ProcessRequest({'data': f'', 'id': TransId, 'cmd': 'get_orders', 't': ''})
@@ -332,7 +366,7 @@ class QuikPy(metaclass=Singleton): # Singleton класс
def GetClassSecurities(self, ClassCode, TransId=0): # 3
"""Список инструментов класса"""
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getClassSecurities', 't': ''})
# Функции для обращения к спискам доступных параметров QuikSharp
def GetOptionBoard(self, ClassCode, SecCode, TransId=0):
@@ -590,3 +624,4 @@ class QuikPy(metaclass=Singleton): # Singleton класс
def __del__(self):
self.CloseConnectionAndThread() # Закрываем соединение для запросов и поток обработки функций обратного вызова