mirror of https://github.com/LedFx/LedFx.git
Fix QLC+ Integration ✅
This commit is contained in:
parent
adfea1d9fa
commit
ec5f19ac8d
|
@ -24,9 +24,11 @@
|
||||||
{
|
{
|
||||||
"label": "[3]-[Frontend]:3000-start",
|
"label": "[3]-[Frontend]:3000-start",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
// "command": "runuser -l vscode -c 'cd /workspaces/${workspaceFolderBasename}/frontend; yarn; yarn start'",
|
|
||||||
"command": "cd /workspaces/${workspaceFolderBasename}/frontend; yarn; yarn start",
|
"command": "cd /workspaces/${workspaceFolderBasename}/frontend; yarn; yarn start",
|
||||||
"group": "build",
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -60,7 +62,7 @@
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "rm -rf /workspaces/${workspaceFolderBasename}/ledfx_frontend/*; runuser -l vscode -c 'cd /workspaces/${workspaceFolderBasename}/frontend; yarn build'",
|
"command": "rm -rf /workspaces/${workspaceFolderBasename}/ledfx_frontend/*; runuser -l vscode -c 'cd /workspaces/${workspaceFolderBasename}/frontend; yarn build'",
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,7 +50,7 @@ function ConfirmationDialogRaw(props) {
|
||||||
// console.log("qlcInfo - Response: ", qlcInfo);
|
// console.log("qlcInfo - Response: ", qlcInfo);
|
||||||
const effectNames = qlcInfo && qlcInfo.event_types && qlcInfo.event_types.effect_set.event_filters.effect_name
|
const effectNames = qlcInfo && qlcInfo.event_types && qlcInfo.event_types.effect_set.event_filters.effect_name
|
||||||
//const effectCleared = qlcInfo && qlcInfo.event_types && qlcInfo.event_types.effect_cleared.event_name
|
//const effectCleared = qlcInfo && qlcInfo.event_types && qlcInfo.event_types.effect_cleared.event_name
|
||||||
const SceneSet = qlcInfo && qlcInfo.event_types && qlcInfo.event_types.scene_set.event_filters.scene_name
|
const SceneSet = qlcInfo && qlcInfo.event_types && qlcInfo.event_types.scene_activated.event_filters.scene_name
|
||||||
const QLCWidgets = qlcInfo && qlcInfo.qlc_widgets && qlcInfo.qlc_widgets.sort((a,b) => parseInt(a[0]) - parseInt(b[0]) )
|
const QLCWidgets = qlcInfo && qlcInfo.qlc_widgets && qlcInfo.qlc_widgets.sort((a,b) => parseInt(a[0]) - parseInt(b[0]) )
|
||||||
const EVENT_TYPES= qlcInfo && qlcInfo.event_types && qlcInfo.event_types
|
const EVENT_TYPES= qlcInfo && qlcInfo.event_types && qlcInfo.event_types
|
||||||
// console.log("test3",EVENT_TYPES);
|
// console.log("test3",EVENT_TYPES);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import logging
|
import logging
|
||||||
from json import JSONDecodeError
|
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
||||||
|
@ -15,60 +14,70 @@ class QLCEndpoint(RestEndpoint):
|
||||||
|
|
||||||
ENDPOINT_PATH = "/api/integrations/qlc/{integration_id}"
|
ENDPOINT_PATH = "/api/integrations/qlc/{integration_id}"
|
||||||
|
|
||||||
async def get(self, integration_id) -> web.Response:
|
async def get(self, integration_id, request) -> web.Response:
|
||||||
"""Get info from QLC+ integration"""
|
"""Get info from QLC+ integration"""
|
||||||
integration = self._ledfx.integrations.get(integration_id)
|
integration = self._ledfx.integrations.get(integration_id)
|
||||||
if (integration is None) or (integration.type != "qlc"):
|
if (integration is None) or (integration.type != "qlc"):
|
||||||
response = {"not found": 404}
|
response = {"not found": 404}
|
||||||
return web.json_response(data=response, status=404)
|
return web.json_response(data=response, status=404)
|
||||||
|
|
||||||
response = {}
|
data = await request.json()
|
||||||
|
info = data.get("info")
|
||||||
|
if info is None:
|
||||||
|
response = {
|
||||||
|
"status": "failed",
|
||||||
|
"reason": 'Required attribute "info" was not provided',
|
||||||
|
}
|
||||||
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
# generate dict of {effect_id: effect_name}
|
if info == "event_types":
|
||||||
effect_names = []
|
# generate dict of {effect_id: effect_name}
|
||||||
for effect_type, effect in self._ledfx.effects.classes().items():
|
effect_names = []
|
||||||
effect_names.append(effect.NAME)
|
for effect_type, effect in self._ledfx.effects.classes().items():
|
||||||
|
effect_names.append(effect.NAME)
|
||||||
|
|
||||||
scene_names = []
|
scene_names = []
|
||||||
for scene in self._ledfx.config["scenes"]:
|
for scene in self._ledfx.config["scenes"]:
|
||||||
scene_names.append(self._ledfx.config["scenes"][scene]["name"])
|
scene_names.append(self._ledfx.config["scenes"][scene]["name"])
|
||||||
|
|
||||||
response["event_types"] = {
|
response = {
|
||||||
Event.EFFECT_SET: {
|
Event.EFFECT_SET: {
|
||||||
"event_name": "Effect Set",
|
"event_name": "Effect Set",
|
||||||
"event_filters": {"effect_name": effect_names},
|
"event_filters": {"effect_name": effect_names},
|
||||||
},
|
},
|
||||||
Event.EFFECT_CLEARED: {
|
Event.EFFECT_CLEARED: {
|
||||||
"event_name": "Effect Cleared",
|
"event_name": "Effect Cleared",
|
||||||
"event_filters": {},
|
"event_filters": {},
|
||||||
},
|
},
|
||||||
Event.SCENE_SET: {
|
Event.SCENE_SET: {
|
||||||
"event_name": "Scene Set",
|
"event_name": "Scene Set",
|
||||||
"event_filters": {"scene_name": scene_names},
|
"event_filters": {"scene_name": scene_names},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
response["qlc_widgets"] = await integration.get_widgets()
|
elif info == "qlc_widgets":
|
||||||
|
response = await integration.get_widgets()
|
||||||
|
|
||||||
response["qlc_listeners"] = integration.data
|
elif info == "qlc_listeners":
|
||||||
|
response = integration.data
|
||||||
|
|
||||||
|
else:
|
||||||
|
response = {
|
||||||
|
"status": "failed",
|
||||||
|
"reason": f'Unknown info parameter "{info}"',
|
||||||
|
}
|
||||||
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
return web.json_response(data=response, status=200)
|
return web.json_response(data=response, status=200)
|
||||||
|
|
||||||
async def put(self, integration_id, request) -> web.Response:
|
async def put(self, integration_id, request) -> web.Response:
|
||||||
"""Toggle a QLC event listener"""
|
""" Toggle a QLC event listener """
|
||||||
integration = self._ledfx.integrations.get(integration_id)
|
integration = self._ledfx.integrations.get(integration_id)
|
||||||
if (integration is None) or (integration.type != "qlc"):
|
if (integration is None) or (integration.type != "qlc"):
|
||||||
response = {"not found": 404}
|
response = {"not found": 404}
|
||||||
return web.json_response(data=response, status=404)
|
return web.json_response(data=response, status=404)
|
||||||
|
|
||||||
try:
|
data = await request.json()
|
||||||
data = await request.json()
|
|
||||||
except JSONDecodeError:
|
|
||||||
response = {
|
|
||||||
"status": "failed",
|
|
||||||
"reason": "JSON Decoding failed",
|
|
||||||
}
|
|
||||||
return web.json_response(data=response, status=400)
|
|
||||||
event_type = data.get("event_type")
|
event_type = data.get("event_type")
|
||||||
event_filter = data.get("event_filter")
|
event_filter = data.get("event_filter")
|
||||||
|
|
||||||
|
@ -77,21 +86,21 @@ class QLCEndpoint(RestEndpoint):
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "event_type" was not provided',
|
"reason": 'Required attribute "event_type" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if event_filter is None:
|
if event_filter is None:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "event_filter" was not provided',
|
"reason": 'Required attribute "event_filter" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if type(event_filter) is not dict:
|
if type(event_filter) is not dict:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": f'Invalid filter "{event_filter}", should be dictionary eg. {{ "scene_name" : "my scene" }} ',
|
"reason": f'Invalid filter "{event_filter}", should be dictionary eg. {{ "scene_name" : "my scene" }} ',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
# toggle the event listener
|
# toggle the event listener
|
||||||
if not integration.toggle_event(event_type, event_filter):
|
if not integration.toggle_event(event_type, event_filter):
|
||||||
|
@ -99,7 +108,7 @@ class QLCEndpoint(RestEndpoint):
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": f"Could not find event with type {event_type} and filter {event_filter}",
|
"reason": f"Could not find event with type {event_type} and filter {event_filter}",
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
# Save the configuration (integration will handle modifying "data")
|
# Save the configuration (integration will handle modifying "data")
|
||||||
for _integration in self._ledfx.config["integrations"]:
|
for _integration in self._ledfx.config["integrations"]:
|
||||||
|
@ -115,20 +124,13 @@ class QLCEndpoint(RestEndpoint):
|
||||||
return web.json_response(data=response, status=200)
|
return web.json_response(data=response, status=200)
|
||||||
|
|
||||||
async def post(self, integration_id, request) -> web.Response:
|
async def post(self, integration_id, request) -> web.Response:
|
||||||
"""Add a new QLC event listener or update an existing one"""
|
""" Add a new QLC event listener or update an existing one """
|
||||||
integration = self._ledfx.integrations.get(integration_id)
|
integration = self._ledfx.integrations.get(integration_id)
|
||||||
if (integration is None) or (integration.type != "qlc"):
|
if (integration is None) or (integration.type != "qlc"):
|
||||||
response = {"not found": 404}
|
response = {"not found": 404}
|
||||||
return web.json_response(data=response, status=404)
|
return web.json_response(data=response, status=404)
|
||||||
|
|
||||||
try:
|
data = await request.json()
|
||||||
data = await request.json()
|
|
||||||
except JSONDecodeError:
|
|
||||||
response = {
|
|
||||||
"status": "failed",
|
|
||||||
"reason": "JSON Decoding failed",
|
|
||||||
}
|
|
||||||
return web.json_response(data=response, status=400)
|
|
||||||
event_type = data.get("event_type")
|
event_type = data.get("event_type")
|
||||||
event_filter = data.get("event_filter")
|
event_filter = data.get("event_filter")
|
||||||
qlc_payload = data.get("qlc_payload")
|
qlc_payload = data.get("qlc_payload")
|
||||||
|
@ -138,28 +140,28 @@ class QLCEndpoint(RestEndpoint):
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "event_type" was not provided',
|
"reason": 'Required attribute "event_type" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if event_filter is None:
|
if event_filter is None:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "event_filter" was not provided',
|
"reason": 'Required attribute "event_filter" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if type(event_filter) is not dict:
|
if type(event_filter) is not dict:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": f'Invalid filter "{event_filter}", should be dictionary eg. {{ "scene_name" : "my scene" }} ',
|
"reason": f'Invalid filter "{event_filter}", should be dictionary eg. {{ "scene_name" : "my scene" }} ',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if qlc_payload is None:
|
if qlc_payload is None:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "qlc_payload" was not provided',
|
"reason": 'Required attribute "qlc_payload" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
# Create a link between ledfx event and sending the payload
|
# Create a link between ledfx event and sending the payload
|
||||||
integration.create_event(event_type, event_filter, True, qlc_payload)
|
integration.create_event(event_type, event_filter, True, qlc_payload)
|
||||||
|
@ -178,20 +180,13 @@ class QLCEndpoint(RestEndpoint):
|
||||||
return web.json_response(data=response, status=200)
|
return web.json_response(data=response, status=200)
|
||||||
|
|
||||||
async def delete(self, integration_id, request) -> web.Response:
|
async def delete(self, integration_id, request) -> web.Response:
|
||||||
"""Delete a QLC event listener"""
|
""" Delete a QLC event listener """
|
||||||
integration = self._ledfx.integrations.get(integration_id)
|
integration = self._ledfx.integrations.get(integration_id)
|
||||||
if (integration is None) or (integration.type != "qlc"):
|
if (integration is None) or (integration.type != "qlc"):
|
||||||
response = {"not found": 404}
|
response = {"not found": 404}
|
||||||
return web.json_response(data=response, status=404)
|
return web.json_response(data=response, status=404)
|
||||||
|
|
||||||
try:
|
data = await request.json()
|
||||||
data = await request.json()
|
|
||||||
except JSONDecodeError:
|
|
||||||
response = {
|
|
||||||
"status": "failed",
|
|
||||||
"reason": "JSON Decoding failed",
|
|
||||||
}
|
|
||||||
return web.json_response(data=response, status=400)
|
|
||||||
event_type = data.get("event_type")
|
event_type = data.get("event_type")
|
||||||
event_filter = data.get("event_filter")
|
event_filter = data.get("event_filter")
|
||||||
|
|
||||||
|
@ -200,21 +195,21 @@ class QLCEndpoint(RestEndpoint):
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "event_type" was not provided',
|
"reason": 'Required attribute "event_type" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if event_filter is None:
|
if event_filter is None:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": 'Required attribute "event_filter" was not provided',
|
"reason": 'Required attribute "event_filter" was not provided',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
if type(event_filter) is not dict:
|
if type(event_filter) is not dict:
|
||||||
response = {
|
response = {
|
||||||
"status": "failed",
|
"status": "failed",
|
||||||
"reason": f'Invalid filter "{event_filter}", should be dictionary eg. {{ "scene_name" : "my scene" }} ',
|
"reason": f'Invalid filter "{event_filter}", should be dictionary eg. {{ "scene_name" : "my scene" }} ',
|
||||||
}
|
}
|
||||||
return web.json_response(data=response, status=400)
|
return web.json_response(data=response, status=500)
|
||||||
|
|
||||||
# Delete the listener and event from data
|
# Delete the listener and event from data
|
||||||
integration.delete_event(event_type, event_filter)
|
integration.delete_event(event_type, event_filter)
|
||||||
|
|
|
@ -62,7 +62,7 @@ class QLC(Integration):
|
||||||
self.restore_from_data(data)
|
self.restore_from_data(data)
|
||||||
|
|
||||||
def restore_from_data(self, data):
|
def restore_from_data(self, data):
|
||||||
"""Creates the event listeners from saved data"""
|
""" Creates the event listeners from saved data """
|
||||||
if data is not None:
|
if data is not None:
|
||||||
try:
|
try:
|
||||||
for entry in data:
|
for entry in data:
|
||||||
|
@ -84,7 +84,7 @@ class QLC(Integration):
|
||||||
return self._data
|
return self._data
|
||||||
|
|
||||||
def create_event(self, event_type, event_filter, active, qlc_payload):
|
def create_event(self, event_type, event_filter, active, qlc_payload):
|
||||||
"""Create or update event listener that sends a qlc payload on a specific event"""
|
""" Create or update event listener that sends a qlc payload on a specific event """
|
||||||
# If it exists, remove the existing listener and update data
|
# If it exists, remove the existing listener and update data
|
||||||
for idx, entry in enumerate(self._data):
|
for idx, entry in enumerate(self._data):
|
||||||
_event_type, _event_filter, _active, _qlc_payload = entry
|
_event_type, _event_filter, _active, _qlc_payload = entry
|
||||||
|
@ -110,7 +110,7 @@ class QLC(Integration):
|
||||||
)
|
)
|
||||||
|
|
||||||
def delete_event(self, event_type, event_filter):
|
def delete_event(self, event_type, event_filter):
|
||||||
"""Completely delete event listener and saved payload from data"""
|
""" Completely delete event listener and saved payload from data """
|
||||||
# remove listener if it exists
|
# remove listener if it exists
|
||||||
self._remove_listener(event_type, event_filter)
|
self._remove_listener(event_type, event_filter)
|
||||||
# remove event and payload from data
|
# remove event and payload from data
|
||||||
|
@ -123,7 +123,7 @@ class QLC(Integration):
|
||||||
)
|
)
|
||||||
|
|
||||||
def toggle_event(self, event_type, event_filter):
|
def toggle_event(self, event_type, event_filter):
|
||||||
"""Toggle a payload linked to event on or off"""
|
""" Toggle a payload linked to event on or off """
|
||||||
# Update "active" flag in data
|
# Update "active" flag in data
|
||||||
for idx, entry in enumerate(self._data):
|
for idx, entry in enumerate(self._data):
|
||||||
_event_type, _event_filter, _active, _qlc_payload = entry
|
_event_type, _event_filter, _active, _qlc_payload = entry
|
||||||
|
@ -149,7 +149,7 @@ class QLC(Integration):
|
||||||
return False # failed to find event_type with this event_filter
|
return False # failed to find event_type with this event_filter
|
||||||
|
|
||||||
def _remove_listener(self, event_type, event_filter):
|
def _remove_listener(self, event_type, event_filter):
|
||||||
"""Internal function to remove ledfx events listener if it exists"""
|
""" Internal function to remove ledfx events listener if it exists """
|
||||||
for idx, entry in enumerate(self._listeners):
|
for idx, entry in enumerate(self._listeners):
|
||||||
_event_type, _event_filter, listener = entry
|
_event_type, _event_filter, listener = entry
|
||||||
if (_event_type == event_type) and (_event_filter == event_filter):
|
if (_event_type == event_type) and (_event_filter == event_filter):
|
||||||
|
@ -159,7 +159,7 @@ class QLC(Integration):
|
||||||
break
|
break
|
||||||
|
|
||||||
def _add_listener(self, event_type, event_filter, qlc_payload):
|
def _add_listener(self, event_type, event_filter, qlc_payload):
|
||||||
"""Internal function that links payload to send on the specified event"""
|
""" Internal function that links payload to send on the specified event """
|
||||||
|
|
||||||
def make_callback(qlc_payload):
|
def make_callback(qlc_payload):
|
||||||
def callback(_):
|
def callback(_):
|
||||||
|
@ -180,7 +180,7 @@ class QLC(Integration):
|
||||||
self._listeners.append((event_type, event_filter, listener))
|
self._listeners.append((event_type, event_filter, listener))
|
||||||
|
|
||||||
async def get_widgets(self):
|
async def get_widgets(self):
|
||||||
"""Returns a list of widgets as tuples: [(ID, Type, Name),...]"""
|
""" Returns a list of widgets as tuples: [(ID, Type, Name),...] """
|
||||||
# First get list of widgets (ID, Name)
|
# First get list of widgets (ID, Name)
|
||||||
widgets = []
|
widgets = []
|
||||||
message = "QLC+API|getWidgetsList"
|
message = "QLC+API|getWidgetsList"
|
||||||
|
@ -198,7 +198,7 @@ class QLC(Integration):
|
||||||
return widgets
|
return widgets
|
||||||
|
|
||||||
async def _send_payload(self, qlc_payload):
|
async def _send_payload(self, qlc_payload):
|
||||||
"""Sends payload of {id:value, ...} pairs to QLC"""
|
""" Sends payload of {id:value, ...} pairs to QLC"""
|
||||||
for widget_id, value in qlc_payload.items():
|
for widget_id, value in qlc_payload.items():
|
||||||
await self._client.send(f"{int(widget_id)}|{value}")
|
await self._client.send(f"{int(widget_id)}|{value}")
|
||||||
|
|
||||||
|
@ -238,12 +238,14 @@ class QLCWebsocketClient:
|
||||||
self.websocket = None
|
self.websocket = None
|
||||||
self.url = url
|
self.url = url
|
||||||
self.domain = domain
|
self.domain = domain
|
||||||
|
self.session = aiohttp.ClientSession()
|
||||||
|
|
||||||
async def connect(self):
|
async def connect(self):
|
||||||
"""Connect to the WebSocket."""
|
"""Connect to the WebSocket."""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
self.websocket = await aiohttp.ClientSession.ws_connect(self.domain)
|
self.websocket = await self.session.ws_connect(self.url)
|
||||||
|
#self.websocket = await self.ws_connect(self.url)
|
||||||
return True
|
return True
|
||||||
except aiohttp.client_exceptions.ClientConnectorError:
|
except aiohttp.client_exceptions.ClientConnectorError:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
|
@ -276,7 +278,7 @@ class QLCWebsocketClient:
|
||||||
|
|
||||||
await self.websocket.send_str(message)
|
await self.websocket.send_str(message)
|
||||||
# Every call to the logger is a performance hit
|
# Every call to the logger is a performance hit
|
||||||
# _LOGGER.debug(f"Sent message {message} to {self.domain}")
|
_LOGGER.debug(f"Sent message {message} to {self.domain}")
|
||||||
|
|
||||||
async def receive(self):
|
async def receive(self):
|
||||||
"""Receive one message from the WebSocket."""
|
"""Receive one message from the WebSocket."""
|
||||||
|
@ -299,4 +301,4 @@ class QLCWebsocketClient:
|
||||||
elif message.type == aiohttp.WSMsgType.CLOSED:
|
elif message.type == aiohttp.WSMsgType.CLOSED:
|
||||||
break
|
break
|
||||||
elif message.type == aiohttp.WSMsgType.ERROR:
|
elif message.type == aiohttp.WSMsgType.ERROR:
|
||||||
break
|
break
|
Loading…
Reference in New Issue