Compare commits

..

1 commit

Author SHA1 Message Date
305e19b3b8 Touch display Ansible config 2025-05-23 15:18:57 +02:00
39 changed files with 343 additions and 1912 deletions

View file

@ -1,38 +1,30 @@
[global]
room = "{{ room }}"
mqttIp = "{{ mqtt_ip }}"
mqttPort = "{{ mqtt_port }}"
Hostname: {{ ansible_facts['hostname'] }} running {{ansible_facts['distribution'] }} on address {{ addr }}
Connected projectors: {{ barco_G62[0].ip }}
{% if barco_G62 is defined %}
[global]
room = {{ room }}
mqttIp = {{ mqtt_ip }}
mqttPort = {{ mqtt_port }}
{% if barco_G62 %}
{%+ for projector in barco_G62 +%}
[{{projector.model}}.{{projector.position}}]
ip = "{{projector.ip}}"
ip = {{projector.ip}}
port = {{projector.port}}
{% endfor %}
{% endif %}
{%+ if tse_box is defined +%}
serial_device = "{{ tse_box.serial_device }}"
{%+ if tse_box +%}
serial_device = {{ tse_box.serial_device }}
{% endif %}
{%+ if projector_motors is defined +%} {# change to appropriate thingy for running them #}
{%+ for motor in projector_motors +%}
[projector_motors.{{motor.position}}]
i2c_address = {{motor.i2c_address}}
{% endfor %}
{% endif %}
{%+ if projector_motors +%} {# change to appropriate thingy for running them #}
{% end if %}
{%+ if extron_audio is defined +%}
{%+ if extron_audio +%}
{% endif %}
{%+ if extron_video is defined +%}
{%+ if extron_video +%}
{% endif %}
{%+ if lucke is defined +%}
[lucke]
url = "{{ lucke.url }}"
roomId = "{{ lucke.roomId }}"
bearer_token = "{{ lucke.bearer_token }}"
{% endif %}

View file

@ -10,12 +10,14 @@ P01:
- position: main
model: barco_G62
port: 3023
ip: localhost #for testirovanje
# ip: 192.168.192.13
# - position : side
# model: barco_G62
# port: 3023
# ip: 192.168.192.14
tse_box:
serial_device: /dev/ttyUSB0
ip: 192.168.192.13
- position : side
model: barco_G62
port: 3023
ip: 192.168.192.14
barco_old:
main_ip: 1.1.1.1
P22:

View file

@ -1,38 +0,0 @@
P01:
hosts:
10.32.50.170:
#192.168.192.42
vars:
static_ip: 192.168.192.42
static_mask: 24
static_routers: 192.168.192.1
static_nameservers: 192.168.192.1
room: P01
mqtt_ip: localhost
mqtt_port: 1883
barco_G62:
- position: main
model: barco_G62
port: 3023
# ip: localhost #for testirovanje
ip: 192.168.192.12
- position : side
model: barco_G62
port: 3023
ip: 192.168.192.13
tse_box:
serial_device: /dev/ttyUSB0
projector_motors:
- position: main
i2c_address: 0x42
offset: 0 #for when using single 8 channel relay board
- position: side
i2c_address: 0x43
offset: 4
lucke:
url: http://192.168.190.90:8091/rest/fri-fkkt/lecture-halls/{roomId}/scenes/{sceneId}/activate
roomId: 0
bearer_token: 0954afe1-4111-4f89-a123-fea08a55dc46

View file

@ -1,64 +1,49 @@
- name: Test playbook
- name: test playbook
hosts: P01
# vars_files:
#vars_files:
# - secret
vars:
# addr: "192.168.122.245"
handlers:
- name: restart NM
ansible.builtin.service:
name: NetworkManager
state: restarted
vars:
addr: "192.168.122.245"
os_environment:
- key: VITE_MQTT_HOST
value: polztest.local
tasks:
- name: Ping hosts
- name: ping hosts
ansible.builtin.ping:
- name: set eth0 static IP
become: true
community.general.nmcli:
conn_name: "Multimedia network"
ifname: eth0
type: ethernet
ip4: "{{ static_ip }}/{{ static_mask }}"
gw4: "{{ static_routers }}"
state: present
#notify: restart NM
- name: Install pkgs
- name: install pkgs
become: true
#become_user: root
apt:
name:
- python3-pip
- mosquitto
- python3-poetry
#- npm
- nginx
state: latest
- name: pip install
pip:
break_system_packages: true
name:
- poetry
- name: check for script directory
#- name: set env
- name: ensures services dir exists
file:
path: "/home/pi/pyServices"
path: "/home/kat/pyServices"
state: directory
- name: ensures services dir exists
file:
path: "/home/kat/pyServices/fri-mm-maline"
state: directory
- name: Copy poetry conf
#become: true
- name: Copy poetry
become: true
ansible.builtin.copy:
#seuser: root
src: "../{{ item }}"
dest: "/home/pi/pyServices/{{ item }}"
owner: pi
group: pi
dest: "/home/kat/pyServices/fri-mm-maline/{{ item }}"
owner: kat
group: kat
mode: '0644'
backup: yes
loop:
@ -66,19 +51,13 @@
- pyproject.toml
- README.md
- name: template config.toml
ansible.builtin.template:
src: ./conf.j2
dest: /home/pi/pyServices/malinaConfig.toml
- name: copy python scripts
#become: true
become: true
ansible.builtin.copy:
src: "../{{ item }}"
dest: "/home/pi/pyServices"
owner: pi
group: pi
dest: "/home/kat/pyServices/fri-mm-maline"
owner: kat
group: kat
mode: '0644'
backup: yes
loop:
@ -88,107 +67,30 @@
- projector_motors/projector_motors.py
- tse_serial/tse_serial_controler.py
- tse_serial/tse_serial_interpreter.py
- lucke/luckeControl.py
# - config.toml # bruh
- config.toml #TODO GENERATE CONFIG
- name: poetry installation
- name: poetry installation from thing
ansible.builtin.shell:
cmd: "poetry install"
chdir: "/home/pi/pyServices"
chdir: "/home/kat/pyServices/fri-mm-maline"
- name: mosquitto service and reload
- name: Copy barco config
become: true
ansible.builtin.systemd_service:
name: mosquitto.service
state: started
daemon_reload: true
- name: generate systemd services
become: true
block:
- name: barco services
when: barco_G62 is defined
block:
- name: template service
vars:
script_file: "/home/pi/pyServices/barco_G62_control.py %i"
ansible.builtin.template:
src: ./service.j2
dest: /lib/systemd/system/barco@.service
- name: enable service
ansible.builtin.systemd_service:
name: "{{item}}"
enabled: true
state: started
loop:
- barco@main.service
- barco@side.service
- name: template projector motors service
when: projector_motors is defined
block:
- name: template service
vars:
script_file: "/home/pi/pyServices/projector_motors.py"
ansible.builtin.template:
src: ./service.j2
dest: /lib/systemd/system/projector_motors.service
- name: enable service
ansible.builtin.systemd_service:
name: projector_motors.service
enabled: true
state: started
- name: template tse serial box service
when: tse_box is defined
block:
- name: template service
vars:
script_file: "/home/pi/pyServices/tse_serial_controler.py"
ansible.builtin.template:
src: ./service.j2
dest: /lib/systemd/system/tse_box.service
- name: enable service
ansible.builtin.systemd_service:
name: tse_box.service
enabled: true
state: started
- name: template lucke service
when: lucke is defined
block:
- name: tmeplate service
vars:
script_file: "/home/pi/pyServices/luckeControl.py"
ansible.builtin.template:
src: ./service.j2
dest: /lib/systemd/system/lucke.service
- name: enable service
ansible.builtin.systemd_service:
name: lucke.service
enabled: true
state: started
# - name: Copy barco config
# become: true
# ansible.builtin.copy:
# #seuser: root
# src: "./{{ item }}"
# dest: /lib/systemd/system
# owner: root
# group: root
# mode: '0644'
# #backup: yes
# loop:
# - barco@.service
# #- extron_audio.service
# # - mqtt_init.service
# - projector_motors.service
# # - tse_box.service
ansible.builtin.copy:
#seuser: root
src: "../{{ item }}"
dest: /lib/systemd/system
owner: root
group: root
mode: '0644'
#backup: yes
loop:
- barco@.service
- extron_audio.service
- mqtt_init.service
- projector_motors.service
- tse_box.service
@ -216,29 +118,35 @@
become: true
ansible.builtin.copy:
src: /home/kat/Documents/polzp/fri_multimedia_rework/frontend/vju_display/dist/
src: /home/kat/Documents/polzp/fri_multimedia_rework/frontend/vju_display/dist
#src: /home/kat/fri_multimedia_rework/frontend/vju_display/dist
#remote_src: true
#dest: /srv/www
dest: /var/www/html/
dest: /srv/www
#dest: /home/kat/testoa
owner: root
group: root
mode: '0755'
backup: yes
# - name: enable modules
# become: true
# ansible.builtin.systemd_service:
# #name: "{{[ 'barco@main.service', 'barco@side.service' ]}}"
# name: "{{ item }}"
# state: stopped
# enabled: false
# loop:
# - barco@main.service
# - barco@side.service
# # - extron_audio.service
# # - mqtt_init.service
# - projector_motors.service
# # - tse_box.service
- name: enable modules
become: true
ansible.builtin.systemd_service:
#name: "{{[ 'barco@main.service', 'barco@side.service' ]}}"
name: "{{ item }}"
state: stopped
enabled: false
loop:
- barco@main.service
- barco@side.service
- extron_audio.service
- mqtt_init.service
- projector_motors.service
- tse_box.service
- name: mosquitto service and reload
become: true
ansible.builtin.systemd_service:
name: mosquitto.service
state: started
daemon_reload: true

View file

@ -3,13 +3,12 @@ Description={{ script_file }}
After=multi-user.target
[Service]
ExecStart=/usr/local/bin/poetry run python3 {{ script_file }}
ExecStart=/usr/bin/poetry run /usr/bin/python3 {{ script_file }}
Type=simple
Restart=always
User=pi
Group=pi
User=kat
Group=kat
RestartSec=10
WorkingDirectory=/home/pi/pyServices
[Install]
WantedBy=multi-user.target

View file

@ -11,7 +11,7 @@
tasks:
- name: test things
when: barco_G62 is defined
when: barco_g62 is defined
block:
#- name: ping hosts
# ansible.builtin.ping:
@ -19,13 +19,13 @@
- name: template config.toml
ansible.builtin.template:
src: ./conf.j2
dest: /home/pi/conf.toml
dest: /home/kat/testo/conf.txt
- name: template barco systemd service
vars:
script_file: "/home/kat/pyServices/fri-mm-maline/barco_G62_control.py %i"
ansible.builtin.template:
src: ./service.j2
dest: /home/kat/testo/barco.service
dest: /home/kat/testo/barc.serv
- name: enable barcos
ansible.builtin.ping:
#itd itd itd
@ -34,5 +34,4 @@
block:
- name: pingerino
ansible.builtin.ping:

View file

@ -1,67 +0,0 @@
import re
import asyncio
import aiohttp
from asyncio.exceptions import CancelledError
PORT = 43680
RE_STATUS = re.compile(r".stats.txt(.+).value='(.+)';")
REMOTEKEY_TIMEOUT = aiohttp.ClientTimeout(total=1)
class BarcoRLM_Control:
def __init__(self, projector_ip):
self.projector_ip = projector_ip
self.session = None
async def _request(self, method, path, *args, **kwargs):
if not self.session:
self.session = aiohttp.ClientSession()
url = f"http://{self.projector_ip}{path}"
resp = await self.session.request(method, url, *args, **kwargs)
resp.raise_for_status()
return await resp.text()
async def get_status(self):
resp = await self._request("GET", "/tgi/firststatus.tgi")
matches = RE_STATUS.findall(resp)
status = dict(matches)
return status
async def toggle_power(self):
await self._request("GET", "/tgi/general.tgi?powertog")
async def click_remote(self, key):
try:
await self._request("GET", f"/tgi/remote.tgi?{key}", timeout=REMOTEKEY_TIMEOUT, raise_for_status=False)
except TimeoutError:
pass
async def set_shutter(self, shutter):
endpoint = f"/tgi/general.tgi?pause{onoff(shutter)}"
await self._request("GET", endpoint)
async def set_power(self, power):
key = onoff(power) + "ky"
await self.click_remote(key)
async def set_input(self, input):
endpoint = f"/tgi/input.tgi?{input}"
await self._request("GET", endpoint)
def onoff(state: bool) -> str:
if state:
return "on"
else:
return "off"
if __name__ == "__main__":
async def main():
barco = BarcoRLM_Control("192.168.192.12")
status = await barco.get_status()
print(status)
await barco.click_remote("kymenu")
asyncio.run(main())

View file

@ -1,80 +0,0 @@
import asyncio
import aiomqtt
from collections import defaultdict
from barco_legacy import BarcoRLM_Control
# TODO MAKE THIS CONFIGURALBE
PROJECTOR_IP = "192.168.192.12"
MQTT_PREFIX = "p22/projektorji/glavni"
MQTT_HOST = "-----"
POLLING_PERIOD_SEC = 10
class BarcoRLM_MQTT:
def __init__(self, projector_ip, mqtt_prefix):
self.projector_ip = projector_ip
self.mqtt_prefix = mqtt_prefix
self.barco = BarcoRLM_Control(projector_ip)
self.last_status = defaultdict(lambda: '')
async def run(self):
async with aiomqtt.Client(MQTT_HOST, 1883) as client:
self.client = client
task_polling = asyncio.create_task(self.task_polling())
task_control = asyncio.create_task(self.task_control())
await asyncio.gather(task_control, task_polling)
async def task_control(self):
topicMatch = f"{self.mqtt_prefix}/ukaz/+"
await self.client.subscribe(topicMatch)
async for mesg in self.client.messages:
cmd = mesg.topic.value.split("/")[-1]
val = mesg.payload.decode()
if cmd == "power":
await self.barco.set_power(onoff(val))
elif cmd == "shutter":
await self.barco.set_shutter(onoff(val))
async def task_polling(self):
while True:
status = await self.barco.get_status()
for key, val in status.items():
if self.last_status[key] != val:
print(f"Status change {key}={val}")
await self.on_status_change(key, val)
self.last_status = status
await asyncio.sleep(POLLING_PERIOD_SEC)
async def on_status_change(self, key, val):
mkey = mval = None
if key == "status":
mkey = "power"
if val == "Imaging":
mval = "1"
if val == "Standby":
mval = "0"
if key == "src":
mkey = "input"
mval = val
if key == "fmr":
mkey = "input_format"
mval = val
if mkey is not None and mval is not None:
await self.client.publish(f"{self.mqtt_prefix}/status/{mkey}", payload=mval)
def onoff(input):
#if input == "1":
# return True
#elif input == "0":
# return False
return input == "1"
if __name__ == '__main__':
barco = BarcoRLM_MQTT(PROJECTOR_IP, MQTT_PREFIX)
asyncio.run(barco.run())

View file

@ -1,98 +0,0 @@
import re
import asyncio
import telnetlib3
from dataclasses import dataclass
from enum import StrEnum
PORT = 43680
RE_STATUS = re.compile(r"OP (.+?)(?:$| = (.+)$)")
@dataclass(frozen=True)
class ACK:
command: str
@dataclass(frozen=True)
class ValueUpdate:
key: str
value: str
class Status(StrEnum):
standby = "0"
warmup = "1"
imaging = "2"
cooling = "3"
warning = "4"
class LampMode(StrEnum):
economy = "0"
standard = "1"
dimming = "2"
class ValueType(StrEnum):
status = "status"
picture_mute = "picture.mute"
lamp_mode = "lamp.mode"
class BarcoRLMW_TCP:
def __init__(self, projector_ip):
self.projector_ip = projector_ip
self.session = None
async def init(self):
self.reader, self.writer = await telnetlib3.open_connection(self.projector_ip, 3023)
async def exec(self, cmd):
await self.writer.write("op " + cmd + "\r")
async def set(self, key, val):
await self.writer.write("op " + key + " = " + val + "\r")
async def query(self, key):
await self.writer.write("op " + key + " ?\r")
async def set_power(self, power):
await self.exec(f"power.{onoff(power)}")
async def set_shutter(self, shutter):
await self.set("picture.mute", int(shutter))
async def iter_messages(self):
"""Async iterator that processes feedback from the projector.
Yields ACK (acknowledgement) and ValueUpdate (value has changed) messages."""
while True:
line = await self.reader.readuntil('\r').decode().strip()
msg = self.parse_response(line)
if msg:
yield msg
def parse_response(self, line):
matches = RE_STATUS.findall(line)
if len(matches) == 0:
return None
match = matches[0]
if len(match) == 2:
return ACK(match[1])
if len(match) == 3:
return ValueUpdate(match[1], match[2])
def onoff(state: bool) -> str:
if state:
return "on"
else:
return "off"
if __name__ == "__main__":
async def main():
barco = BarcoRLMW_TCP("192.168.192.12")
status = await barco.get_status()
print(status)
await barco.click_remote("kymenu")
asyncio.run(main())

View file

@ -1,72 +0,0 @@
import asyncio
import aiomqtt
from collections import defaultdict
from barco_rlmw_tcp import BarcoRLMW_TCP, ValueUpdate, Status, ACK, ValueType
# TODO MAKE THIS CONFIGURALBE
PROJECTOR_IP = "192.168.192.12"
MQTT_PREFIX = "p22/projektorji/glavni"
MQTT_HOST = "-------"
POLLING_PERIOD_SEC = 10
class BarcoRLMW_TCP_MQTT:
def __init__(self, projector_ip, mqtt_prefix):
self.projector_ip = projector_ip
self.mqtt_prefix = mqtt_prefix
self.barco = BarcoRLMW_TCP(projector_ip)
self.last_status = defaultdict(lambda: '')
async def run(self):
async with aiomqtt.Client(MQTT_HOST, 1883) as client:
self.client = client
task_polling = asyncio.create_task(self.task_polling())
task_control = asyncio.create_task(self.task_control())
await asyncio.gather(task_control, task_polling)
async def task_control(self):
topicMatch = f"{self.mqtt_prefix}/ukaz/+"
await self.client.subscribe(topicMatch)
async for mesg in self.client.messages:
cmd = mesg.topic.value.split("/")[-1]
val = mesg.payload.decode()
if cmd == "power":
await self.barco.set_power(onoff(val))
elif cmd == "shutter":
await self.barco.set_shutter(onoff(val))
async def task_polling(self):
while True:
await self.barco.query("status")
await asyncio.sleep(POLLING_PERIOD_SEC)
async def write_status(self, status, value):
await self.client.publish(f"{self.mqtt_prefix}/status/{status}", payload=value)
async def task_process_messages(self):
async for msg in self.barco.iter_messages():
# We only care about value updates
if isinstance(msg, ValueUpdate):
# Power status
if msg.key == ValueType.status:
if msg.value in (Status.imaging, Status.warmup):
self.write_status("power", 1)
elif msg.value in (Status.standby, Status.cooling):
self.write_status("power", 0)
# Video mute
if msg.key == ValueType.picture_mute:
self.write_status("shutter", msg.value)
def onoff(input):
if input == "1":
return True
elif input == "0":
return False
if __name__ == '__main__':
barco = BarcoRLMW_TCP_MQTT(PROJECTOR_IP, MQTT_PREFIX)
asyncio.run(barco.run())

View file

@ -8,7 +8,7 @@ import sys
#GLOBALS
room = "undefined"
position = "glavni"
position = "undefined"
barcoIP = "undefined"
telnetPort = 3023
mqttPort = 1883
@ -23,11 +23,9 @@ reverseCmdMap = {v: k for k, v in cmdMap.items()}
def parse_barco_response(raw: str):
global room, position
raw = raw[1:-1] # strip square brackets
#print(raw)
if raw.startswith("ERR"):
print("Projector" + room + " " + position + " returned" + raw)
return None # TODO parse type error - "disabled control" is special case which shouldnt normally happen
cmd, status = raw.split("!", maxsplit=2)
#print(cmd + " " + status)
@ -35,6 +33,7 @@ def parse_barco_response(raw: str):
status = '1' if status == '01' else '0'
return cmd, status
#TODO MAKE THESE USE GLOBAL INSTEAD OF PASSING BARCO POSITION IN MAIN
async def barco_telnet_command(client, writer, select: str):
global room
@ -91,20 +90,17 @@ async def barco_telnet_query_status(writer, select: str):
async def main():
global room
global barcoPosition, barcoIP, telnetPort, mqttIP, mqttPort
if len(sys.argv) < 2:
sys.exit("No position provided")
else:
barcoPosition = sys.argv[1]
conf = toml.load('./malinaConfig.toml')
g62Barcos = {k: v for k,v in conf["barco_G62"].items()}
currentBarco = g62Barcos[barcoPosition]
conf = toml.load('./config.toml')
g62Barcos = {k: v for k,v in barcos["barco_G62"].items()}
currentBarco = newBarcos[barcoPosition]
barcoIP = currentBarco['ip']
room = conf["global"]["room"]
barcoReader, barcoWriter = await telnetlib3.open_connection(barcoIP, telnetPort)
async with aiomqtt.Client(mqttIP, mqttPort) as client:
task_status_query_barco = asyncio.create_task(barco_telnet_query_status(barcoWriter, barcoPosition))

View file

@ -1,6 +1,5 @@
Prostor,Naprava,Model,IPv4,Naslov
-,Multimedija server,,192.168.192.9,multimedija.fri1.uni-lj.si
P01,Malinca,Raspberry Pi 5,192.168.192.42,
P01,Crestron krmilnik,Crestron AV3,192.168.192.10,
P01,Crestron tablica,Crestron TSW550,192.168.192.11,
P01,Glavni projektor,Barco G62,192.168.192.12,

1 Prostor Naprava Model IPv4 Naslov
2 - Multimedija server 192.168.192.9 multimedija.fri1.uni-lj.si
P01 Malinca Raspberry Pi 5 192.168.192.42
3 P01 Crestron krmilnik Crestron AV3 192.168.192.10
4 P01 Crestron tablica Crestron TSW550 192.168.192.11
5 P01 Glavni projektor Barco G62 192.168.192.12

View file

@ -7,7 +7,6 @@ import Tab from './components/tabs/Tab.vue';
import LightingPage from './components/pages/LightingPage.vue';
import ServisPage from './components/pages/ServisPage.vue';
let urlParams = new URLSearchParams(window.location.search);
const currentRoom = ref(urlParams.get('room') || 'none') // if no param specified
@ -17,16 +16,32 @@ const currentRoom = ref(urlParams.get('room') || 'none') // if no param specifie
const pageNum = ref(0)
const srvcUnlocked = ref(true)
const srvcUnlocked = ref(false)
const showPinPopup = ref(false)
function openPinDiag() {
}
function closePinDiag() {
}
function unlockServicePage() {
showPinPopup.value = true
while (true) {
if ('' == '') {
srvcUnlocked.value = true
closePinDiag()
break
}
}
}
function lockServicePage() {
srvcUnlocked.value = false
}
</script>
<template>
@ -44,17 +59,18 @@ function lockServicePage() {
<Tab @click="pageNum=1; lockServicePage()" :selected="pageNum==1">Video</Tab>
<Tab @click="pageNum=2; lockServicePage()" :selected="pageNum==2">Audio</Tab>
<Tab @click="pageNum=3; lockServicePage()" :selected="pageNum==3">Lučke</Tab>
<Tab @click="pageNum=4; lockServicePage()" :selected="pageNum==4">Servis</Tab>
<Tab @click="pageNum=4; unlockServicePage()" :selected="pageNum==4">Servis</Tab>
</VerticalTabs>
<large style="display: flex;">turbo odličen super mega kontrol panel</large>
</header>
<main>
<MainPage v-if="pageNum == 0" :room="currentRoom" />
<VideoPage v-else-if="pageNum == 1" :room="currentRoom" />
<LightingPage v-else-if="pageNum == 3" :room="currentRoom" />
<ServisPage v-else-if="pageNum == 4" :room="currentRoom" />
<ServisPage v-else-if="pageNum == 4 && srvcUnlocked" :room="currentRoom" />
</main>
</div>
</template>
@ -84,8 +100,4 @@ h1 {
padding: .4rem;
}
* {
cursor: none;
}
</style>

View file

@ -1,87 +0,0 @@
<script setup lang="ts">
//import HelloWorld from './components/HelloWorld.vue'
//import TheWelcome from './components/TheWelcome.vue'
import { ref, onMounted, reactive, watch } from 'vue'
import { $mqtt } from 'vue-paho-mqtt'
const props = defineProps({
room: String,
})
const topicstrs = [ //TODO everything else
props.room + '/power/audio/status',
]
const subscriptions =
topicstrs.map(topic => {
// console.log('subbing to', topic)
$mqtt.subscribe(topic, (msg) => {
// console.log('received:', topic, msg)
handleIncomingMQTT(topic, msg)
})
})
const audioStatus = ref(false)
function handleIncomingMQTT(topic: string, msg: string) {
console.log('Received on', topic, 'with message', msg)
audioStatus.value = msg == '1'
}
onMounted(() => {
// console.log('test')
//$mqtt.publish('peepee', 'poopoo', 'Qr') // dela
})
function publishMQTTMsg(topic: string, msg: string) {
//msg = msg.toString()
console.log('Sending to [', topic, '] with message [', msg, ']')
$mqtt.publish(topic, msg, 'Qr') //todo refactor to 1 or 0 maybe
console.log('sent')
}
async function setAudio() {
let topicPref = props.room + "/power/audio/set"
let command = '0'
if (!audioStatus.value) {
command = '1'
}
publishMQTTMsg(topicPref, command)
//audioStatus.value = command == '1'
}
//TODO organize better, binds, etc.
const roomState = ref(0)
// OFF -> 0; ON -> 1; IN BETWEEN -> 2
</script>
<template>
<div>
<!-- TODO lepš -->
<div>
<h3>Ozvočenje</h3>
<button style="" @click="setAudio()">
{{ audioStatus ? 'UGASNI' : 'PRIŽGI' }}
</button>
</div>
</div>
</template>
<style scoped>
.disabled {
opacity: .8;
pointer-events: none;
}
button {
padding: 1rem;
width: 100%;
}
</style>

View file

@ -66,17 +66,17 @@ function publishMQTTMsg(topic: string, msg: string) {
async function setLecture(pos?: String) {
if (!pos) { return }
let topicPref = props.room + "/projectors/" + props.position + "/"
let topicPref = props.room + "/projektorji/" + props.position + "/"
let command = '0'
if (roomState.value == 0) {
command = '1'
} // else if (roomState.value == 1) {
// command = '0'
// } else { return }
} else if (roomState.value == 1) {
command = '0'
} else { return }
publishMQTTMsg((topicPref + 'set/power'), command)
publishMQTTMsg((topicPref + 'platno/goto'), command == '1' ? 'DOWN' : 'UP')
publishMQTTMsg((topicPref + 'lift/move/' + (command == '1' ? 'down' : 'up') ), '1')
await sleep(1000)
publishMQTTMsg((topicPref + 'lift/move/' + (command == '1' ? 'down' : 'up') ), command)
await sleep(500)
publishMQTTMsg((topicPref + 'platno/goto'), 'STOP')
publishMQTTMsg((topicPref + 'lift/move/' + (command == '1' ? 'down' : 'up') ), '0')
}
@ -91,8 +91,6 @@ const roomStatus = reactive({
platno_state: 'UNKNOWN',
})
const roomState = ref(0)
// OFF -> 0; ON -> 1; IN BETWEEN -> 2
@ -100,15 +98,12 @@ watch (roomStatus, (_, _newState) => {
if (!_newState) { return }
let allOn = _newState.proj_power && _newState.platno_state == 'DOWN' && _newState.lift_state == 'DOWN'
let allOff = !_newState.proj_power && _newState.platno_state == 'UP' && _newState.lift_state == 'UP'
let anyUnknown = _newState.lift_state == 'UNKNOWN' || _newState.platno_state == 'UNKNOWN'
if (allOn) {
roomState.value = 1
} else if (allOff) {
roomState.value = 0
} else if (anyUnknown) {
roomState.value = 3
} else {
roomState.value = 2
roomState.value = 2
}
}, {immediate: true})
@ -120,10 +115,9 @@ watch (roomStatus, (_, _newState) => {
<!-- TODO lepš -->
<div>
<h3 v-if="roomState == 1">AKTIVNO</h3>
<h3 v-else-if="roomState == 0">PRIPRAVLJENOST</h3>
<h3 v-else-if="roomState == 0">V PRIPRAVLJENOSTI</h3>
<h3 v-else-if="roomState == 2">POČAKAJTE</h3>
<h3 v-else-if="roomState == 3">NEZNANO STANJE</h3>
<h3 v-else>NAPAKA</h3>
<h3 v-else="roomState == 1">NAPAKA</h3>
<button style="" @click="setLecture(props.position)" :disabled="roomState == 2">
{{ roomState == 1 ? 'UGASNI' : (roomState == 0 ? 'PRIŽGI' : '...') }}
</button>

View file

@ -1,87 +0,0 @@
<script setup lang="ts">
//import HelloWorld from './components/HelloWorld.vue'
//import TheWelcome from './components/TheWelcome.vue'
import { ref, onMounted, reactive, watch } from 'vue'
import { $mqtt } from 'vue-paho-mqtt'
const props = defineProps({
room: String,
})
const topicstrs = [ //TODO everything else
props.room + '/power/master/status',
]
const subscriptions =
topicstrs.map(topic => {
// console.log('subbing to', topic)
$mqtt.subscribe(topic, (msg) => {
// console.log('received:', topic, msg)
handleIncomingMQTT(topic, msg)
})
})
const MasterStatus = ref(false)
function handleIncomingMQTT(topic: string, msg: string) {
console.log('Received on', topic, 'with message', msg)
audioStatus.value = msg == '1'
}
onMounted(() => {
// console.log('test')
//$mqtt.publish('peepee', 'poopoo', 'Qr') // dela
})
function publishMQTTMsg(topic: string, msg: string) {
//msg = msg.toString()
console.log('Sending to [', topic, '] with message [', msg, ']')
$mqtt.publish(topic, msg, 'Qr') //todo refactor to 1 or 0 maybe
console.log('sent')
}
async function setMaster() {
let topicPref = props.room + "/power/audio/set"
let command = '0'
if (!MasterStatus.value) {
command = '1'
}
publishMQTTMsg(topicPref, command)
//audioStatus.value = command == '1'
}
//TODO organize better, binds, etc.
const roomState = ref(0)
// OFF -> 0; ON -> 1; IN BETWEEN -> 2
</script>
<template>
<div>
<!-- TODO lepš -->
<div>
<h3>Sistem</h3>
<button style="" @click="setMaster()">
{{ MasterStatus ? 'UGASNI' : 'PRIŽGI' }}
</button>
</div>
</div>
</template>
<style scoped>
.disabled {
opacity: .8;
pointer-events: none;
}
button {
padding: 1rem;
width: 100%;
}
</style>

View file

@ -1,78 +0,0 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const props = defineProps({
onClose: [Function, null],
onSuccess: [Function, null]
})
const pin = ref("1337")
const testPin = ref("0000")
// export default {
// props: ['onClose', 'onSuccess'],
// data() {
// return {
// pin: '',
// };
// },
// methods: {
function checkPin() {
// Your hard-coded pin
if (testPin.value === pin.value) {
if (props.onSuccess)
props.onSuccess(); // Let parent component know pin is correct
if (props.onClose)
props.onClose();
} else {
alert('Incorrect pin');
}
}
function close() {
if (props.onClose)
props.onClose();
}
</script>
<template>
<div class="pin-popup">
<div class="overlay" @click="close"></div>
<div class="popup">
<h2>Enter Pin Code</h2>
<input v-model="pin" type="password" placeholder="Pin Code" />
<button @click="checkPin">Submit</button>
</div>
</div>
</template>
<style scoped>
.pin-popup {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.popup {
background: white;
padding: 20px;
border-radius: 8px;
display: flex;
flex-direction: column;
gap: 10px;
}
</style>

View file

@ -87,17 +87,15 @@ const platnoStatus = ref(platnoState.UNKNOWN)
</script>
<template>
<div style="display:flex; gap: 1rem">
<div>
<!-- <h3>{{ props.room }}</h3> -->
<!-- <form> -->
<!-- TODO lepš -->
<div>
<h4>platna {{ props.position }}</h4>
<button
@click="publishMQTTMsg(publishPrefix + 'goto', 'UP')"><UpIcon/></button>
<button
@click="publishMQTTMsg(publishPrefix + 'goto', 'DOWN')"><DownIcon/></button>
</div>
<div v-if="props.ctrlType == 'service'">
<h5>Manual control</h5>
<button
@ -115,9 +113,5 @@ const platnoStatus = ref(platnoState.UNKNOWN)
</template>
<style scoped>
button {
padding: 1rem;
margin: 0.1rem;
width: 45%;
}
</style>

View file

@ -1,87 +0,0 @@
<script setup lang="ts">
//import HelloWorld from './components/HelloWorld.vue'
//import TheWelcome from './components/TheWelcome.vue'
import { ref, onMounted, reactive, watch } from 'vue'
import { $mqtt } from 'vue-paho-mqtt'
const props = defineProps({
room: String,
})
const topicstrs = [ //TODO everything else
props.room + '/power/projectors/status',
]
const subscriptions =
topicstrs.map(topic => {
// console.log('subbing to', topic)
$mqtt.subscribe(topic, (msg) => {
// console.log('received:', topic, msg)
handleIncomingMQTT(topic, msg)
})
})
const projectorsStatus = ref(false)
function handleIncomingMQTT(topic: string, msg: string) {
console.log('Received on', topic, 'with message', msg)
projectorsStatus.value = msg == '1'
}
onMounted(() => {
// console.log('test')
//$mqtt.publish('peepee', 'poopoo', 'Qr') // dela
})
function publishMQTTMsg(topic: string, msg: string) {
//msg = msg.toString()
console.log('Sending to [', topic, '] with message [', msg, ']')
$mqtt.publish(topic, msg, 'Qr') //todo refactor to 1 or 0 maybe
console.log('sent')
}
async function setProjectors() {
let topicPref = props.room + "/power/projectors/set"
let command = '0'
if (!projectorsStatus.value) {
command = '1'
}
publishMQTTMsg(topicPref, command)
//audioStatus.value = command == '1'
}
//TODO organize better, binds, etc.
const roomState = ref(0)
// OFF -> 0; ON -> 1; IN BETWEEN -> 2
</script>
<template>
<div>
<!-- TODO lepš -->
<div>
<h3>Projektorji</h3>
<button style="" @click="setProjectors()">
{{ projectorsStatus ? 'UGASNI' : 'PRIŽGI' }}
</button>
</div>
</div>
</template>
<style scoped>
.disabled {
opacity: .8;
pointer-events: none;
}
button {
padding: 1rem;
width: 100%;
}
</style>

View file

@ -7,7 +7,7 @@ import { $mqtt } from 'vue-paho-mqtt'
const props = defineProps({
room: String,
position: String,
ctrltype: [String, null]
ctrlType: [String, null]
})
const topicstrs = [ //TODO everything else

View file

@ -1,83 +0,0 @@
<script setup lang="ts">
//import HelloWorld from './components/HelloWorld.vue'
//import TheWelcome from './components/TheWelcome.vue'
import { ref, onMounted, reactive, watch } from 'vue'
import { $mqtt } from 'vue-paho-mqtt'
const props = defineProps({
room: String,
})
const topicstrs = [ //TODO everything else
props.room + '',
]
const subscriptions =
topicstrs.map(topic => {
// console.log('subbing to', topic)
$mqtt.subscribe(topic, (msg) => {
// console.log('received:', topic, msg)
handleIncomingMQTT(topic, msg)
})
})
const audioStatus = ref(false)
function handleIncomingMQTT(topic: string, msg: string) {
console.log('Received on', topic, 'with message', msg)
audioStatus.value = msg == '1'
}
onMounted(() => {
// console.log('test')
//$mqtt.publish('peepee', 'poopoo', 'Qr') // dela
})
function publishMQTTMsg(topic: string, msg: string) {
//msg = msg.toString()
console.log('Sending to [', topic, '] with message [', msg, ']')
$mqtt.publish(topic, msg, 'Qr') //todo refactor to 1 or 0 maybe
console.log('sent')
}
async function resetAll() {
let topicPref = props.room + "/power/"
publishMQTTMsg(topicPref + 'audio/set', '0')
publishMQTTMsg(topicPref + 'projectors/set', '1')
publishMQTTMsg(topicPref + 'master/set', '1')
publishMQTTMsg(props.room + "/projectors/main/lift/move/up", '1')
publishMQTTMsg(props.room + "/projectors/side/lift/move/up", '1')
//TODO NOT HARDCODE THISEFEWGJREWGREW
publishMQTTMsg(props.room + "/projectors/main/platno/goto", 'UP')
publishMQTTMsg(props.room + "/projectors/side/platno/goto", 'UP')
//audioStatus.value = command == '1'
}
</script>
<template>
<div>
<!-- TODO lepš -->
<div>
<h3>Reset sistema</h3>
<button style="" @click="resetAll()">
RESET
</button>
</div>
</div>
</template>
<style scoped>
.disabled {
opacity: .8;
pointer-events: none;
}
button {
padding: 1rem;
width: 100%;
}
</style>

View file

@ -14,11 +14,8 @@ const props = defineProps({
const topicstrs = [ //TODO everything else
props.room + '/projectors/' + props.position + 'platno/status',
props.room + '/projectors/' + props.position + 'platno/status',
props.room + '/lucke/preset/current',
]
const lastPreset = ref("-1")
const subscriptions =
topicstrs.map(topic => {
// console.log('subbing to', topic)
@ -34,8 +31,6 @@ function handleIncomingMQTT(topic: string, msg: string) {
//console.log(topic.split('/'))
let typ = topic.split('/')[4]
handlePlatnoStatus(msg)
} else if (topic.includes('current')) {
lastPreset.value = msg
}
}
@ -80,9 +75,7 @@ function publishMQTTMsg(topic: string, msg: string) {
$mqtt.publish(topic, msg, 'Qr') //todo refactor to 1 or 0 maybe
console.log('sent')
}
const publishPrefix = ref(props.room + '/')
const publishPrefix = ref(props.room + '/firanki/')
</script>
@ -96,27 +89,15 @@ const publishPrefix = ref(props.room + '/')
<h4>Firanki</h4>
<button
@mousedown="publishMQTTMsg(publishPrefix + 'firanki/move', 'MOVE_UP')"
@mouseup="publishMQTTMsg(publishPrefix + 'firanki/move', 'STOP')" >
@mousedown="publishMQTTMsg(publishPrefix + 'move', 'MOVE_UP')"
@mouseup="publishMQTTMsg(publishPrefix + 'move', 'STOP')" >
<UpIcon /></button>
<button
@mousedown="publishMQTTMsg(publishPrefix + 'firanki/move', 'MOVE_DOWN')"
@mouseup="publishMQTTMsg(publishPrefix + 'firanki/move', 'STOP')" >
@mousedown="publishMQTTMsg(publishPrefix + 'move', 'MOVE_DOWN')"
@mouseup="publishMQTTMsg(publishPrefix + 'move', 'STOP')" >
<DownIcon /></button>
</div>
</div>
<div style="display: flex; gap: 1rem;">
<div>
<h4>Lučka presets</h4>
<h5>CURRENT SCENE: {{ lastPreset }} -- TODO MAKE BUTTON LIGHT UP</h5>
<button :class="{currentlySelectedPreset: (lastPreset == '1')}" @click="publishMQTTMsg(publishPrefix + 'lucke/preset/recall', '1')"A>1</button>
<button :class="{currentlySelectedPreset: (lastPreset == '2')}" @click="publishMQTTMsg(publishPrefix + 'lucke/preset/recall', '2')"A>2</button>
<button :class="{currentlySelectedPreset: (lastPreset == '3')}" @click="publishMQTTMsg(publishPrefix + 'lucke/preset/recall', '3')"A>3</button>
<button :class="{currentlySelectedPreset: (lastPreset == '4')}" @click="publishMQTTMsg(publishPrefix + 'lucke/preset/recall', '4')"A>4</button>
<button :class="{currentlySelectedPreset: (lastPreset == '9')}" @click="publishMQTTMsg(publishPrefix + 'lucke/preset/recall', 'E')"A>Plchldr E</button>
<button :class="{currentlySelectedPreset: (lastPreset == '9')}" @click="publishMQTTMsg(publishPrefix + 'lucke/preset/recall', 'F')"A>Plchldr F</button>
</div>
</div>
</template>
<style scoped>
@ -129,8 +110,4 @@ button {
margin: 0.1rem;
width: 45%;
}
.currentlySelectedPreset {
background-color: orange;
}
</style>

View file

@ -5,22 +5,21 @@ import Projektor from '../Projektor.vue';
import Platno from '../Platno.vue';
import Lift from '../Lift.vue';
import LectureModule from '../LectureModule.vue';
import AudioControlModule from '../AudioControlModule.vue';
const props = defineProps({
room: String
})
const _glavni_position = ref('main')
const _stranski_position = ref('side')
const _glavni_position = ref('glavni')
const _stranski_position = ref('stranski')
let _glavni = ref('main')
let _stranski = ref('side')
let _glavni = ref('glavni')
let _stranski = ref('stranski')
</script>
<template>
<div style="display:flex; gap: 1rem; margin:inherit">
<div style="display:flex; gap: 1rem">
<div style="width: 50%;">
<h4>Glavni:</h4>
<LectureModule :room="props.room" :position="_glavni" />
@ -30,13 +29,4 @@ let _stranski = ref('side')
<LectureModule :room="props.room" :position="_stranski" />
</div>
</div>
<div>
<AudioControlModule :room="props.room" />
</div>
</template>
<style lang="css">
* {
cursor: pointer;
}
</style>
</template>

View file

@ -1,38 +0,0 @@
<script setup lang="ts">
//import HelloWorld from './components/HelloWorld.vue'
//import TheWelcome from './components/TheWelcome.vue'
import {ref, onMounted, reactive } from 'vue'
import { $mqtt } from 'vue-paho-mqtt'
// import Projektor from '../Projektor.vue'
// import Platno from '../Platno.vue'
import Lift from '../Lift.vue';
import Projektor from '../Projektor.vue';
const props = defineProps({
room: String,
})
const _glavni_position = ref('glavni')
const _stranski_position = ref('stranski')
const _ctrl_type = ref('service')
</script>
<template>
<div style="display: flex; gap: 1rem">
<div>
<Projektor :room="props.room" :position="_glavni_position" :ctrlType="_ctrl_type" />
<Lift :room="props.room" :position="_glavni_position" />
<Platno :room="props.room" :position="_glavni_position" :ctrlType="_ctrl_type"/>
</div>
<div>
<Projektor :room="props.room" :position="_stranski_position" :ctrlType="_ctrl_type"/>
<Lift :room="props.room" :position="_stranski_position" />
<Platno :room="props.room" :position="_stranski_position" :ctrlType="_ctrl_type" />
</div>
</div>
</template>
<style scoped>
</style>

View file

@ -4,21 +4,15 @@
import {ref, onMounted, reactive } from 'vue'
import { $mqtt } from 'vue-paho-mqtt'
// import Projektor from '../Projektor.vue'
import Platno from '../Platno.vue'
// import Platno from '../Platno.vue'
import Lift from '../Lift.vue';
import Projektor from '../Projektor.vue';
import ProjectorPowerModule from "@/components/ProjectorPowerModule.vue";
import AudioControlModule from "@/components/AudioControlModule.vue";
import MasterPowerControlModule from "@/components/MasterPowerControlModule.vue";
import ResetButton from "@/components/ResetButton.vue";
const props = defineProps({
room: String,
})
const _glavni_position = ref('main')
const _stranski_position = ref('side')
const _glavni_position = ref('glavni')
const _stranski_position = ref('stranski')
const _ctrl_type = ref('service')
</script>
@ -35,16 +29,6 @@ const _ctrl_type = ref('service')
<Lift :room="props.room" :position="_stranski_position" />
<Platno :room="props.room" :position="_stranski_position" :ctrlType="_ctrl_type" />
</div>
<div>
<h5>POWER CONTROL</h5>
<div>
<ProjectorPowerModule :room="props.room" />
<AudioControlModule :room="props.room" />
<MasterPowerControlModule :room="props.room" />
</div>
<div></div>
<ResetButton :room="props.room"/>
</div>
</div>
</template>

View file

@ -9,8 +9,8 @@ import Platno from '../Platno.vue'
const props = defineProps({
room: String,
})
const _glavni_position = ref('main')
const _stranski_position = ref('side')
const _glavni_position = ref('glavni')
const _stranski_position = ref('stranski')
const _test = ref('test')
</script>
@ -20,12 +20,12 @@ const _test = ref('test')
<div>
<h4>Glavni</h4>
<Projektor :room="props.room" :position="_glavni_position" :ctrl-type="_test" />
<Platno :room="props.room" :position="_glavni_position" :ctrl-type="_test" />
<Platno :room="props.room" :position="_glavni_position" />
</div>
<div>
<h4>Stranski</h4>
<Projektor :room="props.room" :position="_stranski_position" :ctrltype="_test"/>
<Platno :room="props.room" :position="_stranski_position" :ctrl-type="_test"/>
<Projektor :room="props.room" :position="_stranski_position" />
<Platno :room="props.room" :position="_stranski_position" />
</div>
</div>
</template>

View file

@ -1,50 +0,0 @@
from http import HTTPStatus
import aiomqtt
import asyncio
import toml
import aiohttp
lucke_bearer_token = ""
room = ""
url = ""
roomId = 0
async def sendSceneRequest(client, scene):
global roomId
endpoint = url.format(roomId=roomId, sceneId=scene)
# Content-Type needs to be JSON, but the content itself is ignored
async with aiohttp.request("POST", endpoint, headers={"Authorization": "Bearer " + lucke_bearer_token}, json={}) as resp:
#if 204 change was made
if resp.status != 204:
print(resp.status, await resp.text())
await client.publish(f'{room}/lucke/preset/current', payload=scene, qos=1, retain=True)
async def task_luckeCommand(controlClient):
await controlClient.subscribe(f"{room}/lucke/preset/recall")
msgs = controlClient.messages
async for mesg in msgs:
mesg: aiomqtt.Message
msgTopicArr = mesg.topic.value.split('/')
sceneNum = mesg.payload.decode()
print("Received: " + str(msgTopicArr) + " payload: [" + sceneNum + "]")
print('sending request to endpoint..')
await sendSceneRequest(controlClient, sceneNum)
await asyncio.sleep(0.01)
async def main():
global room, lucke_bearer_token, url, roomId
conf = toml.load('./malinaConfig.toml')
room = conf.get("global")['room']
url = conf.get("lucke")['url']
roomId = conf.get("lucke")['roomId']
lucke_bearer_token = conf.get("lucke")['bearer_token']
async with aiomqtt.Client('localhost', 1883) as client:
task_control = asyncio.create_task(task_luckeCommand(client))
await asyncio.gather(task_control)
if __name__ == '__main__':
asyncio.run(main())

View file

@ -1,5 +0,0 @@
[global]
room = "P01"
mqttIp = "localhost"
mqttPort = "1883"

650
poetry.lock generated
View file

@ -1,124 +1,5 @@
# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand.
[[package]]
name = "aiohappyeyeballs"
version = "2.6.1"
description = "Happy Eyeballs for asyncio"
optional = false
python-versions = ">=3.9"
files = [
{file = "aiohappyeyeballs-2.6.1-py3-none-any.whl", hash = "sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8"},
{file = "aiohappyeyeballs-2.6.1.tar.gz", hash = "sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558"},
]
[[package]]
name = "aiohttp"
version = "3.12.13"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.9"
files = [
{file = "aiohttp-3.12.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5421af8f22a98f640261ee48aae3a37f0c41371e99412d55eaf2f8a46d5dad29"},
{file = "aiohttp-3.12.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fcda86f6cb318ba36ed8f1396a6a4a3fd8f856f84d426584392083d10da4de0"},
{file = "aiohttp-3.12.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cd71c9fb92aceb5a23c4c39d8ecc80389c178eba9feab77f19274843eb9412d"},
{file = "aiohttp-3.12.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34ebf1aca12845066c963016655dac897651e1544f22a34c9b461ac3b4b1d3aa"},
{file = "aiohttp-3.12.13-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:893a4639694c5b7edd4bdd8141be296042b6806e27cc1d794e585c43010cc294"},
{file = "aiohttp-3.12.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:663d8ee3ffb3494502ebcccb49078faddbb84c1d870f9c1dd5a29e85d1f747ce"},
{file = "aiohttp-3.12.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0f8f6a85a0006ae2709aa4ce05749ba2cdcb4b43d6c21a16c8517c16593aabe"},
{file = "aiohttp-3.12.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1582745eb63df267c92d8b61ca655a0ce62105ef62542c00a74590f306be8cb5"},
{file = "aiohttp-3.12.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d59227776ee2aa64226f7e086638baa645f4b044f2947dbf85c76ab11dcba073"},
{file = "aiohttp-3.12.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06b07c418bde1c8e737d8fa67741072bd3f5b0fb66cf8c0655172188c17e5fa6"},
{file = "aiohttp-3.12.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9445c1842680efac0f81d272fd8db7163acfcc2b1436e3f420f4c9a9c5a50795"},
{file = "aiohttp-3.12.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:09c4767af0b0b98c724f5d47f2bf33395c8986995b0a9dab0575ca81a554a8c0"},
{file = "aiohttp-3.12.13-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f3854fbde7a465318ad8d3fc5bef8f059e6d0a87e71a0d3360bb56c0bf87b18a"},
{file = "aiohttp-3.12.13-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2332b4c361c05ecd381edb99e2a33733f3db906739a83a483974b3df70a51b40"},
{file = "aiohttp-3.12.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1561db63fa1b658cd94325d303933553ea7d89ae09ff21cc3bcd41b8521fbbb6"},
{file = "aiohttp-3.12.13-cp310-cp310-win32.whl", hash = "sha256:a0be857f0b35177ba09d7c472825d1b711d11c6d0e8a2052804e3b93166de1ad"},
{file = "aiohttp-3.12.13-cp310-cp310-win_amd64.whl", hash = "sha256:fcc30ad4fb5cb41a33953292d45f54ef4066746d625992aeac33b8c681173178"},
{file = "aiohttp-3.12.13-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c229b1437aa2576b99384e4be668af1db84b31a45305d02f61f5497cfa6f60c"},
{file = "aiohttp-3.12.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04076d8c63471e51e3689c93940775dc3d12d855c0c80d18ac5a1c68f0904358"},
{file = "aiohttp-3.12.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:55683615813ce3601640cfaa1041174dc956d28ba0511c8cbd75273eb0587014"},
{file = "aiohttp-3.12.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:921bc91e602d7506d37643e77819cb0b840d4ebb5f8d6408423af3d3bf79a7b7"},
{file = "aiohttp-3.12.13-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e72d17fe0974ddeae8ed86db297e23dba39c7ac36d84acdbb53df2e18505a013"},
{file = "aiohttp-3.12.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0653d15587909a52e024a261943cf1c5bdc69acb71f411b0dd5966d065a51a47"},
{file = "aiohttp-3.12.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a77b48997c66722c65e157c06c74332cdf9c7ad00494b85ec43f324e5c5a9b9a"},
{file = "aiohttp-3.12.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6946bae55fd36cfb8e4092c921075cde029c71c7cb571d72f1079d1e4e013bc"},
{file = "aiohttp-3.12.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f95db8c8b219bcf294a53742c7bda49b80ceb9d577c8e7aa075612b7f39ffb7"},
{file = "aiohttp-3.12.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:03d5eb3cfb4949ab4c74822fb3326cd9655c2b9fe22e4257e2100d44215b2e2b"},
{file = "aiohttp-3.12.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6383dd0ffa15515283c26cbf41ac8e6705aab54b4cbb77bdb8935a713a89bee9"},
{file = "aiohttp-3.12.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6548a411bc8219b45ba2577716493aa63b12803d1e5dc70508c539d0db8dbf5a"},
{file = "aiohttp-3.12.13-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:81b0fcbfe59a4ca41dc8f635c2a4a71e63f75168cc91026c61be665945739e2d"},
{file = "aiohttp-3.12.13-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6a83797a0174e7995e5edce9dcecc517c642eb43bc3cba296d4512edf346eee2"},
{file = "aiohttp-3.12.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a5734d8469a5633a4e9ffdf9983ff7cdb512524645c7a3d4bc8a3de45b935ac3"},
{file = "aiohttp-3.12.13-cp311-cp311-win32.whl", hash = "sha256:fef8d50dfa482925bb6b4c208b40d8e9fa54cecba923dc65b825a72eed9a5dbd"},
{file = "aiohttp-3.12.13-cp311-cp311-win_amd64.whl", hash = "sha256:9a27da9c3b5ed9d04c36ad2df65b38a96a37e9cfba6f1381b842d05d98e6afe9"},
{file = "aiohttp-3.12.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0aa580cf80558557285b49452151b9c69f2fa3ad94c5c9e76e684719a8791b73"},
{file = "aiohttp-3.12.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b103a7e414b57e6939cc4dece8e282cfb22043efd0c7298044f6594cf83ab347"},
{file = "aiohttp-3.12.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78f64e748e9e741d2eccff9597d09fb3cd962210e5b5716047cbb646dc8fe06f"},
{file = "aiohttp-3.12.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c955989bf4c696d2ededc6b0ccb85a73623ae6e112439398935362bacfaaf6"},
{file = "aiohttp-3.12.13-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d640191016763fab76072c87d8854a19e8e65d7a6fcfcbf017926bdbbb30a7e5"},
{file = "aiohttp-3.12.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dc507481266b410dede95dd9f26c8d6f5a14315372cc48a6e43eac652237d9b"},
{file = "aiohttp-3.12.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8a94daa873465d518db073bd95d75f14302e0208a08e8c942b2f3f1c07288a75"},
{file = "aiohttp-3.12.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f52420cde4ce0bb9425a375d95577fe082cb5721ecb61da3049b55189e4e6"},
{file = "aiohttp-3.12.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f7df1f620ec40f1a7fbcb99ea17d7326ea6996715e78f71a1c9a021e31b96b8"},
{file = "aiohttp-3.12.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3062d4ad53b36e17796dce1c0d6da0ad27a015c321e663657ba1cc7659cfc710"},
{file = "aiohttp-3.12.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:8605e22d2a86b8e51ffb5253d9045ea73683d92d47c0b1438e11a359bdb94462"},
{file = "aiohttp-3.12.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:54fbbe6beafc2820de71ece2198458a711e224e116efefa01b7969f3e2b3ddae"},
{file = "aiohttp-3.12.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:050bd277dfc3768b606fd4eae79dd58ceda67d8b0b3c565656a89ae34525d15e"},
{file = "aiohttp-3.12.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2637a60910b58f50f22379b6797466c3aa6ae28a6ab6404e09175ce4955b4e6a"},
{file = "aiohttp-3.12.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e986067357550d1aaa21cfe9897fa19e680110551518a5a7cf44e6c5638cb8b5"},
{file = "aiohttp-3.12.13-cp312-cp312-win32.whl", hash = "sha256:ac941a80aeea2aaae2875c9500861a3ba356f9ff17b9cb2dbfb5cbf91baaf5bf"},
{file = "aiohttp-3.12.13-cp312-cp312-win_amd64.whl", hash = "sha256:671f41e6146a749b6c81cb7fd07f5a8356d46febdaaaf07b0e774ff04830461e"},
{file = "aiohttp-3.12.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d4a18e61f271127465bdb0e8ff36e8f02ac4a32a80d8927aa52371e93cd87938"},
{file = "aiohttp-3.12.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:532542cb48691179455fab429cdb0d558b5e5290b033b87478f2aa6af5d20ace"},
{file = "aiohttp-3.12.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d7eea18b52f23c050ae9db5d01f3d264ab08f09e7356d6f68e3f3ac2de9dfabb"},
{file = "aiohttp-3.12.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad7c8e5c25f2a26842a7c239de3f7b6bfb92304593ef997c04ac49fb703ff4d7"},
{file = "aiohttp-3.12.13-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6af355b483e3fe9d7336d84539fef460120c2f6e50e06c658fe2907c69262d6b"},
{file = "aiohttp-3.12.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a95cf9f097498f35c88e3609f55bb47b28a5ef67f6888f4390b3d73e2bac6177"},
{file = "aiohttp-3.12.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8ed8c38a1c584fe99a475a8f60eefc0b682ea413a84c6ce769bb19a7ff1c5ef"},
{file = "aiohttp-3.12.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a0b9170d5d800126b5bc89d3053a2363406d6e327afb6afaeda2d19ee8bb103"},
{file = "aiohttp-3.12.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:372feeace612ef8eb41f05ae014a92121a512bd5067db8f25101dd88a8db11da"},
{file = "aiohttp-3.12.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a946d3702f7965d81f7af7ea8fb03bb33fe53d311df48a46eeca17e9e0beed2d"},
{file = "aiohttp-3.12.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a0c4725fae86555bbb1d4082129e21de7264f4ab14baf735278c974785cd2041"},
{file = "aiohttp-3.12.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b28ea2f708234f0a5c44eb6c7d9eb63a148ce3252ba0140d050b091b6e842d1"},
{file = "aiohttp-3.12.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d4f5becd2a5791829f79608c6f3dc745388162376f310eb9c142c985f9441cc1"},
{file = "aiohttp-3.12.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:60f2ce6b944e97649051d5f5cc0f439360690b73909230e107fd45a359d3e911"},
{file = "aiohttp-3.12.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:69fc1909857401b67bf599c793f2183fbc4804717388b0b888f27f9929aa41f3"},
{file = "aiohttp-3.12.13-cp313-cp313-win32.whl", hash = "sha256:7d7e68787a2046b0e44ba5587aa723ce05d711e3a3665b6b7545328ac8e3c0dd"},
{file = "aiohttp-3.12.13-cp313-cp313-win_amd64.whl", hash = "sha256:5a178390ca90419bfd41419a809688c368e63c86bd725e1186dd97f6b89c2706"},
{file = "aiohttp-3.12.13-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:36f6c973e003dc9b0bb4e8492a643641ea8ef0e97ff7aaa5c0f53d68839357b4"},
{file = "aiohttp-3.12.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6cbfc73179bd67c229eb171e2e3745d2afd5c711ccd1e40a68b90427f282eab1"},
{file = "aiohttp-3.12.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1e8b27b2d414f7e3205aa23bb4a692e935ef877e3a71f40d1884f6e04fd7fa74"},
{file = "aiohttp-3.12.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eabded0c2b2ef56243289112c48556c395d70150ce4220d9008e6b4b3dd15690"},
{file = "aiohttp-3.12.13-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:003038e83f1a3ff97409999995ec02fe3008a1d675478949643281141f54751d"},
{file = "aiohttp-3.12.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b6f46613031dbc92bdcaad9c4c22c7209236ec501f9c0c5f5f0b6a689bf50f3"},
{file = "aiohttp-3.12.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c332c6bb04650d59fb94ed96491f43812549a3ba6e7a16a218e612f99f04145e"},
{file = "aiohttp-3.12.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fea41a2c931fb582cb15dc86a3037329e7b941df52b487a9f8b5aa960153cbd"},
{file = "aiohttp-3.12.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:846104f45d18fb390efd9b422b27d8f3cf8853f1218c537f36e71a385758c896"},
{file = "aiohttp-3.12.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d6c85ac7dd350f8da2520bac8205ce99df4435b399fa7f4dc4a70407073e390"},
{file = "aiohttp-3.12.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:5a1ecce0ed281bec7da8550da052a6b89552db14d0a0a45554156f085a912f48"},
{file = "aiohttp-3.12.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5304d74867028cca8f64f1cc1215eb365388033c5a691ea7aa6b0dc47412f495"},
{file = "aiohttp-3.12.13-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:64d1f24ee95a2d1e094a4cd7a9b7d34d08db1bbcb8aa9fb717046b0a884ac294"},
{file = "aiohttp-3.12.13-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:119c79922a7001ca6a9e253228eb39b793ea994fd2eccb79481c64b5f9d2a055"},
{file = "aiohttp-3.12.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bb18f00396d22e2f10cd8825d671d9f9a3ba968d708a559c02a627536b36d91c"},
{file = "aiohttp-3.12.13-cp39-cp39-win32.whl", hash = "sha256:0022de47ef63fd06b065d430ac79c6b0bd24cdae7feaf0e8c6bac23b805a23a8"},
{file = "aiohttp-3.12.13-cp39-cp39-win_amd64.whl", hash = "sha256:29e08111ccf81b2734ae03f1ad1cb03b9615e7d8f616764f22f71209c094f122"},
{file = "aiohttp-3.12.13.tar.gz", hash = "sha256:47e2da578528264a12e4e3dd8dd72a7289e5f812758fe086473fab037a10fcce"},
]
[package.dependencies]
aiohappyeyeballs = ">=2.5.0"
aiosignal = ">=1.1.2"
async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""}
attrs = ">=17.3.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
propcache = ">=0.2.0"
yarl = ">=1.17.0,<2.0"
[package.extras]
speedups = ["Brotli", "aiodns (>=3.3.0)", "brotlicffi"]
[[package]]
name = "aiomqtt"
version = "2.3.0"
@ -146,50 +27,6 @@ files = [
[package.dependencies]
pyserial = "*"
[[package]]
name = "aiosignal"
version = "1.3.2"
description = "aiosignal: a list of registered asynchronous callbacks"
optional = false
python-versions = ">=3.9"
files = [
{file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"},
{file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"},
]
[package.dependencies]
frozenlist = ">=1.1.0"
[[package]]
name = "async-timeout"
version = "5.0.1"
description = "Timeout context manager for asyncio programs"
optional = false
python-versions = ">=3.8"
files = [
{file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"},
{file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"},
]
[[package]]
name = "attrs"
version = "25.3.0"
description = "Classes Without Boilerplate"
optional = false
python-versions = ">=3.8"
files = [
{file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"},
{file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"},
]
[package.extras]
benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"]
tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"]
[[package]]
name = "colorzero"
version = "2.0"
@ -208,119 +45,6 @@ setuptools = "*"
doc = ["pkginfo", "sphinx", "sphinx-rtd-theme"]
test = ["pytest", "pytest-cov"]
[[package]]
name = "frozenlist"
version = "1.7.0"
description = "A list-like structure which implements collections.abc.MutableSequence"
optional = false
python-versions = ">=3.9"
files = [
{file = "frozenlist-1.7.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cc4df77d638aa2ed703b878dd093725b72a824c3c546c076e8fdf276f78ee84a"},
{file = "frozenlist-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:716a9973a2cc963160394f701964fe25012600f3d311f60c790400b00e568b61"},
{file = "frozenlist-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0fd1bad056a3600047fb9462cff4c5322cebc59ebf5d0a3725e0ee78955001d"},
{file = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3789ebc19cb811163e70fe2bd354cea097254ce6e707ae42e56f45e31e96cb8e"},
{file = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af369aa35ee34f132fcfad5be45fbfcde0e3a5f6a1ec0712857f286b7d20cca9"},
{file = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac64b6478722eeb7a3313d494f8342ef3478dff539d17002f849101b212ef97c"},
{file = "frozenlist-1.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f89f65d85774f1797239693cef07ad4c97fdd0639544bad9ac4b869782eb1981"},
{file = "frozenlist-1.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1073557c941395fdfcfac13eb2456cb8aad89f9de27bae29fabca8e563b12615"},
{file = "frozenlist-1.7.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed8d2fa095aae4bdc7fdd80351009a48d286635edffee66bf865e37a9125c50"},
{file = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:24c34bea555fe42d9f928ba0a740c553088500377448febecaa82cc3e88aa1fa"},
{file = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:69cac419ac6a6baad202c85aaf467b65ac860ac2e7f2ac1686dc40dbb52f6577"},
{file = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:960d67d0611f4c87da7e2ae2eacf7ea81a5be967861e0c63cf205215afbfac59"},
{file = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:41be2964bd4b15bf575e5daee5a5ce7ed3115320fb3c2b71fca05582ffa4dc9e"},
{file = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:46d84d49e00c9429238a7ce02dc0be8f6d7cd0cd405abd1bebdc991bf27c15bd"},
{file = "frozenlist-1.7.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:15900082e886edb37480335d9d518cec978afc69ccbc30bd18610b7c1b22a718"},
{file = "frozenlist-1.7.0-cp310-cp310-win32.whl", hash = "sha256:400ddd24ab4e55014bba442d917203c73b2846391dd42ca5e38ff52bb18c3c5e"},
{file = "frozenlist-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:6eb93efb8101ef39d32d50bce242c84bcbddb4f7e9febfa7b524532a239b4464"},
{file = "frozenlist-1.7.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:aa51e147a66b2d74de1e6e2cf5921890de6b0f4820b257465101d7f37b49fb5a"},
{file = "frozenlist-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9b35db7ce1cd71d36ba24f80f0c9e7cff73a28d7a74e91fe83e23d27c7828750"},
{file = "frozenlist-1.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34a69a85e34ff37791e94542065c8416c1afbf820b68f720452f636d5fb990cd"},
{file = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a646531fa8d82c87fe4bb2e596f23173caec9185bfbca5d583b4ccfb95183e2"},
{file = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:79b2ffbba483f4ed36a0f236ccb85fbb16e670c9238313709638167670ba235f"},
{file = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a26f205c9ca5829cbf82bb2a84b5c36f7184c4316617d7ef1b271a56720d6b30"},
{file = "frozenlist-1.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcacfad3185a623fa11ea0e0634aac7b691aa925d50a440f39b458e41c561d98"},
{file = "frozenlist-1.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72c1b0fe8fe451b34f12dce46445ddf14bd2a5bcad7e324987194dc8e3a74c86"},
{file = "frozenlist-1.7.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61d1a5baeaac6c0798ff6edfaeaa00e0e412d49946c53fae8d4b8e8b3566c4ae"},
{file = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7edf5c043c062462f09b6820de9854bf28cc6cc5b6714b383149745e287181a8"},
{file = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:d50ac7627b3a1bd2dcef6f9da89a772694ec04d9a61b66cf87f7d9446b4a0c31"},
{file = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ce48b2fece5aeb45265bb7a58259f45027db0abff478e3077e12b05b17fb9da7"},
{file = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:fe2365ae915a1fafd982c146754e1de6ab3478def8a59c86e1f7242d794f97d5"},
{file = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:45a6f2fdbd10e074e8814eb98b05292f27bad7d1883afbe009d96abdcf3bc898"},
{file = "frozenlist-1.7.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:21884e23cffabb157a9dd7e353779077bf5b8f9a58e9b262c6caad2ef5f80a56"},
{file = "frozenlist-1.7.0-cp311-cp311-win32.whl", hash = "sha256:284d233a8953d7b24f9159b8a3496fc1ddc00f4db99c324bd5fb5f22d8698ea7"},
{file = "frozenlist-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:387cbfdcde2f2353f19c2f66bbb52406d06ed77519ac7ee21be0232147c2592d"},
{file = "frozenlist-1.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:3dbf9952c4bb0e90e98aec1bd992b3318685005702656bc6f67c1a32b76787f2"},
{file = "frozenlist-1.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:1f5906d3359300b8a9bb194239491122e6cf1444c2efb88865426f170c262cdb"},
{file = "frozenlist-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3dabd5a8f84573c8d10d8859a50ea2dec01eea372031929871368c09fa103478"},
{file = "frozenlist-1.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa57daa5917f1738064f302bf2626281a1cb01920c32f711fbc7bc36111058a8"},
{file = "frozenlist-1.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c193dda2b6d49f4c4398962810fa7d7c78f032bf45572b3e04dd5249dff27e08"},
{file = "frozenlist-1.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe2b675cf0aaa6d61bf8fbffd3c274b3c9b7b1623beb3809df8a81399a4a9c4"},
{file = "frozenlist-1.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8fc5d5cda37f62b262405cf9652cf0856839c4be8ee41be0afe8858f17f4c94b"},
{file = "frozenlist-1.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d5ce521d1dd7d620198829b87ea002956e4319002ef0bc8d3e6d045cb4646e"},
{file = "frozenlist-1.7.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:488d0a7d6a0008ca0db273c542098a0fa9e7dfaa7e57f70acef43f32b3f69dca"},
{file = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:15a7eaba63983d22c54d255b854e8108e7e5f3e89f647fc854bd77a237e767df"},
{file = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1eaa7e9c6d15df825bf255649e05bd8a74b04a4d2baa1ae46d9c2d00b2ca2cb5"},
{file = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4389e06714cfa9d47ab87f784a7c5be91d3934cd6e9a7b85beef808297cc025"},
{file = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:73bd45e1488c40b63fe5a7df892baf9e2a4d4bb6409a2b3b78ac1c6236178e01"},
{file = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99886d98e1643269760e5fe0df31e5ae7050788dd288947f7f007209b8c33f08"},
{file = "frozenlist-1.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:290a172aae5a4c278c6da8a96222e6337744cd9c77313efe33d5670b9f65fc43"},
{file = "frozenlist-1.7.0-cp312-cp312-win32.whl", hash = "sha256:426c7bc70e07cfebc178bc4c2bf2d861d720c4fff172181eeb4a4c41d4ca2ad3"},
{file = "frozenlist-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:563b72efe5da92e02eb68c59cb37205457c977aa7a449ed1b37e6939e5c47c6a"},
{file = "frozenlist-1.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ee80eeda5e2a4e660651370ebffd1286542b67e268aa1ac8d6dbe973120ef7ee"},
{file = "frozenlist-1.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d1a81c85417b914139e3a9b995d4a1c84559afc839a93cf2cb7f15e6e5f6ed2d"},
{file = "frozenlist-1.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb65198a9132ebc334f237d7b0df163e4de83fb4f2bdfe46c1e654bdb0c5d43"},
{file = "frozenlist-1.7.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dab46c723eeb2c255a64f9dc05b8dd601fde66d6b19cdb82b2e09cc6ff8d8b5d"},
{file = "frozenlist-1.7.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6aeac207a759d0dedd2e40745575ae32ab30926ff4fa49b1635def65806fddee"},
{file = "frozenlist-1.7.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bd8c4e58ad14b4fa7802b8be49d47993182fdd4023393899632c88fd8cd994eb"},
{file = "frozenlist-1.7.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04fb24d104f425da3540ed83cbfc31388a586a7696142004c577fa61c6298c3f"},
{file = "frozenlist-1.7.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a5c505156368e4ea6b53b5ac23c92d7edc864537ff911d2fb24c140bb175e60"},
{file = "frozenlist-1.7.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bd7eb96a675f18aa5c553eb7ddc24a43c8c18f22e1f9925528128c052cdbe00"},
{file = "frozenlist-1.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05579bf020096fe05a764f1f84cd104a12f78eaab68842d036772dc6d4870b4b"},
{file = "frozenlist-1.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:376b6222d114e97eeec13d46c486facd41d4f43bab626b7c3f6a8b4e81a5192c"},
{file = "frozenlist-1.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:0aa7e176ebe115379b5b1c95b4096fb1c17cce0847402e227e712c27bdb5a949"},
{file = "frozenlist-1.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3fbba20e662b9c2130dc771e332a99eff5da078b2b2648153a40669a6d0e36ca"},
{file = "frozenlist-1.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f4410a0a601d349dd406b5713fec59b4cee7e71678d5b17edda7f4655a940b"},
{file = "frozenlist-1.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cdfaaec6a2f9327bf43c933c0319a7c429058e8537c508964a133dffee412e"},
{file = "frozenlist-1.7.0-cp313-cp313-win32.whl", hash = "sha256:5fc4df05a6591c7768459caba1b342d9ec23fa16195e744939ba5914596ae3e1"},
{file = "frozenlist-1.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:52109052b9791a3e6b5d1b65f4b909703984b770694d3eb64fad124c835d7cba"},
{file = "frozenlist-1.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:a6f86e4193bb0e235ef6ce3dde5cbabed887e0b11f516ce8a0f4d3b33078ec2d"},
{file = "frozenlist-1.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:82d664628865abeb32d90ae497fb93df398a69bb3434463d172b80fc25b0dd7d"},
{file = "frozenlist-1.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:912a7e8375a1c9a68325a902f3953191b7b292aa3c3fb0d71a216221deca460b"},
{file = "frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9537c2777167488d539bc5de2ad262efc44388230e5118868e172dd4a552b146"},
{file = "frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f34560fb1b4c3e30ba35fa9a13894ba39e5acfc5f60f57d8accde65f46cc5e74"},
{file = "frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:acd03d224b0175f5a850edc104ac19040d35419eddad04e7cf2d5986d98427f1"},
{file = "frozenlist-1.7.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2038310bc582f3d6a09b3816ab01737d60bf7b1ec70f5356b09e84fb7408ab1"},
{file = "frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8c05e4c8e5f36e5e088caa1bf78a687528f83c043706640a92cb76cd6999384"},
{file = "frozenlist-1.7.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:765bb588c86e47d0b68f23c1bee323d4b703218037765dcf3f25c838c6fecceb"},
{file = "frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:32dc2e08c67d86d0969714dd484fd60ff08ff81d1a1e40a77dd34a387e6ebc0c"},
{file = "frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:c0303e597eb5a5321b4de9c68e9845ac8f290d2ab3f3e2c864437d3c5a30cd65"},
{file = "frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a47f2abb4e29b3a8d0b530f7c3598badc6b134562b1a5caee867f7c62fee51e3"},
{file = "frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:3d688126c242a6fabbd92e02633414d40f50bb6002fa4cf995a1d18051525657"},
{file = "frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:4e7e9652b3d367c7bd449a727dc79d5043f48b88d0cbfd4f9f1060cf2b414104"},
{file = "frozenlist-1.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1a85e345b4c43db8b842cab1feb41be5cc0b10a1830e6295b69d7310f99becaf"},
{file = "frozenlist-1.7.0-cp313-cp313t-win32.whl", hash = "sha256:3a14027124ddb70dfcee5148979998066897e79f89f64b13328595c4bdf77c81"},
{file = "frozenlist-1.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3bf8010d71d4507775f658e9823210b7427be36625b387221642725b515dcf3e"},
{file = "frozenlist-1.7.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cea3dbd15aea1341ea2de490574a4a37ca080b2ae24e4b4f4b51b9057b4c3630"},
{file = "frozenlist-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7d536ee086b23fecc36c2073c371572374ff50ef4db515e4e503925361c24f71"},
{file = "frozenlist-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dfcebf56f703cb2e346315431699f00db126d158455e513bd14089d992101e44"},
{file = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974c5336e61d6e7eb1ea5b929cb645e882aadab0095c5a6974a111e6479f8878"},
{file = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c70db4a0ab5ab20878432c40563573229a7ed9241506181bba12f6b7d0dc41cb"},
{file = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1137b78384eebaf70560a36b7b229f752fb64d463d38d1304939984d5cb887b6"},
{file = "frozenlist-1.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e793a9f01b3e8b5c0bc646fb59140ce0efcc580d22a3468d70766091beb81b35"},
{file = "frozenlist-1.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74739ba8e4e38221d2c5c03d90a7e542cb8ad681915f4ca8f68d04f810ee0a87"},
{file = "frozenlist-1.7.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e63344c4e929b1a01e29bc184bbb5fd82954869033765bfe8d65d09e336a677"},
{file = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2ea2a7369eb76de2217a842f22087913cdf75f63cf1307b9024ab82dfb525938"},
{file = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:836b42f472a0e006e02499cef9352ce8097f33df43baaba3e0a28a964c26c7d2"},
{file = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e22b9a99741294b2571667c07d9f8cceec07cb92aae5ccda39ea1b6052ed4319"},
{file = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:9a19e85cc503d958abe5218953df722748d87172f71b73cf3c9257a91b999890"},
{file = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f22dac33bb3ee8fe3e013aa7b91dc12f60d61d05b7fe32191ffa84c3aafe77bd"},
{file = "frozenlist-1.7.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ccec739a99e4ccf664ea0775149f2749b8a6418eb5b8384b4dc0a7d15d304cb"},
{file = "frozenlist-1.7.0-cp39-cp39-win32.whl", hash = "sha256:b3950f11058310008a87757f3eee16a8e1ca97979833239439586857bc25482e"},
{file = "frozenlist-1.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:43a82fce6769c70f2f5a06248b614a7d268080a9d20f7457ef10ecee5af82b63"},
{file = "frozenlist-1.7.0-py3-none-any.whl", hash = "sha256:9a5af342e34f7e97caf8c995864c7a396418ae2859cc6fdf1b1073020d516a7e"},
{file = "frozenlist-1.7.0.tar.gz", hash = "sha256:2e310d81923c2437ea8670467121cc3e9b0f76d3043cc1d2331d56c7fb7a3a8f"},
]
[[package]]
name = "gpiozero"
version = "2.0.1"
@ -339,142 +63,6 @@ colorzero = "*"
doc = ["sphinx (>=4.0)", "sphinx-rtd-theme (>=1.0)"]
test = ["pytest", "pytest-cov"]
[[package]]
name = "idna"
version = "3.10"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.6"
files = [
{file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
{file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
]
[package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
name = "multidict"
version = "6.5.0"
description = "multidict implementation"
optional = false
python-versions = ">=3.9"
files = [
{file = "multidict-6.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2e118a202904623b1d2606d1c8614e14c9444b59d64454b0c355044058066469"},
{file = "multidict-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a42995bdcaff4e22cb1280ae7752c3ed3fbb398090c6991a2797a4a0e5ed16a9"},
{file = "multidict-6.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2261b538145723ca776e55208640fffd7ee78184d223f37c2b40b9edfe0e818a"},
{file = "multidict-6.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e5b19f8cd67235fab3e195ca389490415d9fef5a315b1fa6f332925dc924262"},
{file = "multidict-6.5.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:177b081e4dec67c3320b16b3aa0babc178bbf758553085669382c7ec711e1ec8"},
{file = "multidict-6.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d30a2cc106a7d116b52ee046207614db42380b62e6b1dd2a50eba47c5ca5eb1"},
{file = "multidict-6.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a72933bc308d7a64de37f0d51795dbeaceebdfb75454f89035cdfc6a74cfd129"},
{file = "multidict-6.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96d109e663d032280ef8ef62b50924b2e887d5ddf19e301844a6cb7e91a172a6"},
{file = "multidict-6.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b555329c9894332401f03b9a87016f0b707b6fccd4706793ec43b4a639e75869"},
{file = "multidict-6.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6994bad9d471ef2156f2b6850b51e20ee409c6b9deebc0e57be096be9faffdce"},
{file = "multidict-6.5.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:b15f817276c96cde9060569023808eec966bd8da56a97e6aa8116f34ddab6534"},
{file = "multidict-6.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b4bf507c991db535a935b2127cf057a58dbc688c9f309c72080795c63e796f58"},
{file = "multidict-6.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:60c3f8f13d443426c55f88cf3172547bbc600a86d57fd565458b9259239a6737"},
{file = "multidict-6.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a10227168a24420c158747fc201d4279aa9af1671f287371597e2b4f2ff21879"},
{file = "multidict-6.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e3b1425fe54ccfde66b8cfb25d02be34d5dfd2261a71561ffd887ef4088b4b69"},
{file = "multidict-6.5.0-cp310-cp310-win32.whl", hash = "sha256:b4e47ef51237841d1087e1e1548071a6ef22e27ed0400c272174fa585277c4b4"},
{file = "multidict-6.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:63b3b24fadc7067282c88fae5b2f366d5b3a7c15c021c2838de8c65a50eeefb4"},
{file = "multidict-6.5.0-cp310-cp310-win_arm64.whl", hash = "sha256:8b2d61afbafc679b7eaf08e9de4fa5d38bd5dc7a9c0a577c9f9588fb49f02dbb"},
{file = "multidict-6.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8b4bf6bb15a05796a07a248084e3e46e032860c899c7a9b981030e61368dba95"},
{file = "multidict-6.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46bb05d50219655c42a4b8fcda9c7ee658a09adbb719c48e65a20284e36328ea"},
{file = "multidict-6.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:54f524d73f4d54e87e03c98f6af601af4777e4668a52b1bd2ae0a4d6fc7b392b"},
{file = "multidict-6.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529b03600466480ecc502000d62e54f185a884ed4570dee90d9a273ee80e37b5"},
{file = "multidict-6.5.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:69ad681ad7c93a41ee7005cc83a144b5b34a3838bcf7261e2b5356057b0f78de"},
{file = "multidict-6.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fe9fada8bc0839466b09fa3f6894f003137942984843ec0c3848846329a36ae"},
{file = "multidict-6.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f94c6ea6405fcf81baef1e459b209a78cda5442e61b5b7a57ede39d99b5204a0"},
{file = "multidict-6.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ca75ad8a39ed75f079a8931435a5b51ee4c45d9b32e1740f99969a5d1cc2ee"},
{file = "multidict-6.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4c08f3a2a6cc42b414496017928d95898964fed84b1b2dace0c9ee763061f9"},
{file = "multidict-6.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:046a7540cfbb4d5dc846a1fd9843f3ba980c6523f2e0c5b8622b4a5c94138ae6"},
{file = "multidict-6.5.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:64306121171d988af77d74be0d8c73ee1a69cf6f96aea7fa6030c88f32a152dd"},
{file = "multidict-6.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b4ac1dd5eb0ecf6f7351d5a9137f30a83f7182209c5d37f61614dfdce5714853"},
{file = "multidict-6.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bab4a8337235365f4111a7011a1f028826ca683834ebd12de4b85e2844359c36"},
{file = "multidict-6.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a05b5604c5a75df14a63eeeca598d11b2c3745b9008539b70826ea044063a572"},
{file = "multidict-6.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:67c4a640952371c9ca65b6a710598be246ef3be5ca83ed38c16a7660d3980877"},
{file = "multidict-6.5.0-cp311-cp311-win32.whl", hash = "sha256:fdeae096ca36c12d8aca2640b8407a9d94e961372c68435bef14e31cce726138"},
{file = "multidict-6.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:e2977ef8b7ce27723ee8c610d1bd1765da4f3fbe5a64f9bf1fd3b4770e31fbc0"},
{file = "multidict-6.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:82d0cf0ea49bae43d9e8c3851e21954eff716259ff42da401b668744d1760bcb"},
{file = "multidict-6.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1bb986c8ea9d49947bc325c51eced1ada6d8d9b4c5b15fd3fcdc3c93edef5a74"},
{file = "multidict-6.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:03c0923da300120830fc467e23805d63bbb4e98b94032bd863bc7797ea5fa653"},
{file = "multidict-6.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4c78d5ec00fdd35c91680ab5cf58368faad4bd1a8721f87127326270248de9bc"},
{file = "multidict-6.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadc3cb78be90a887f8f6b73945b840da44b4a483d1c9750459ae69687940c97"},
{file = "multidict-6.5.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5b02e1ca495d71e07e652e4cef91adae3bf7ae4493507a263f56e617de65dafc"},
{file = "multidict-6.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7fe92a62326eef351668eec4e2dfc494927764a0840a1895cff16707fceffcd3"},
{file = "multidict-6.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7673ee4f63879ecd526488deb1989041abcb101b2d30a9165e1e90c489f3f7fb"},
{file = "multidict-6.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa097ae2a29f573de7e2d86620cbdda5676d27772d4ed2669cfa9961a0d73955"},
{file = "multidict-6.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:300da0fa4f8457d9c4bd579695496116563409e676ac79b5e4dca18e49d1c308"},
{file = "multidict-6.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9a19bd108c35877b57393243d392d024cfbfdefe759fd137abb98f6fc910b64c"},
{file = "multidict-6.5.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:0f32a1777465a35c35ddbbd7fc1293077938a69402fcc59e40b2846d04a120dd"},
{file = "multidict-6.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9cc1e10c14ce8112d1e6d8971fe3cdbe13e314f68bea0e727429249d4a6ce164"},
{file = "multidict-6.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e95c5e07a06594bdc288117ca90e89156aee8cb2d7c330b920d9c3dd19c05414"},
{file = "multidict-6.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:40ff26f58323795f5cd2855e2718a1720a1123fb90df4553426f0efd76135462"},
{file = "multidict-6.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76803a29fd71869a8b59c2118c9dcfb3b8f9c8723e2cce6baeb20705459505cf"},
{file = "multidict-6.5.0-cp312-cp312-win32.whl", hash = "sha256:df7ecbc65a53a2ce1b3a0c82e6ad1a43dcfe7c6137733f9176a92516b9f5b851"},
{file = "multidict-6.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:0ec1c3fbbb0b655a6540bce408f48b9a7474fd94ed657dcd2e890671fefa7743"},
{file = "multidict-6.5.0-cp312-cp312-win_arm64.whl", hash = "sha256:2d24a00d34808b22c1f15902899b9d82d0faeca9f56281641c791d8605eacd35"},
{file = "multidict-6.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:53d92df1752df67a928fa7f884aa51edae6f1cf00eeb38cbcf318cf841c17456"},
{file = "multidict-6.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:680210de2c38eef17ce46b8df8bf2c1ece489261a14a6e43c997d49843a27c99"},
{file = "multidict-6.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e279259bcb936732bfa1a8eec82b5d2352b3df69d2fa90d25808cfc403cee90a"},
{file = "multidict-6.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1c185fc1069781e3fc8b622c4331fb3b433979850392daa5efbb97f7f9959bb"},
{file = "multidict-6.5.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6bb5f65ff91daf19ce97f48f63585e51595539a8a523258b34f7cef2ec7e0617"},
{file = "multidict-6.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8646b4259450c59b9286db280dd57745897897284f6308edbdf437166d93855"},
{file = "multidict-6.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d245973d4ecc04eea0a8e5ebec7882cf515480036e1b48e65dffcfbdf86d00be"},
{file = "multidict-6.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a133e7ddc9bc7fb053733d0ff697ce78c7bf39b5aec4ac12857b6116324c8d75"},
{file = "multidict-6.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80d696fa38d738fcebfd53eec4d2e3aeb86a67679fd5e53c325756682f152826"},
{file = "multidict-6.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:20d30c9410ac3908abbaa52ee5967a754c62142043cf2ba091e39681bd51d21a"},
{file = "multidict-6.5.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c65068cc026f217e815fa519d8e959a7188e94ec163ffa029c94ca3ef9d4a73"},
{file = "multidict-6.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e355ac668a8c3e49c2ca8daa4c92f0ad5b705d26da3d5af6f7d971e46c096da7"},
{file = "multidict-6.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08db204213d0375a91a381cae0677ab95dd8c67a465eb370549daf6dbbf8ba10"},
{file = "multidict-6.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ffa58e3e215af8f6536dc837a990e456129857bb6fd546b3991be470abd9597a"},
{file = "multidict-6.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3e86eb90015c6f21658dbd257bb8e6aa18bdb365b92dd1fba27ec04e58cdc31b"},
{file = "multidict-6.5.0-cp313-cp313-win32.whl", hash = "sha256:f34a90fbd9959d0f857323bd3c52b3e6011ed48f78d7d7b9e04980b8a41da3af"},
{file = "multidict-6.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fcb2aa79ac6aef8d5b709bbfc2fdb1d75210ba43038d70fbb595b35af470ce06"},
{file = "multidict-6.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:6dcee5e7e92060b4bb9bb6f01efcbb78c13d0e17d9bc6eec71660dd71dc7b0c2"},
{file = "multidict-6.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:cbbc88abea2388fde41dd574159dec2cda005cb61aa84950828610cb5010f21a"},
{file = "multidict-6.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70b599f70ae6536e5976364d3c3cf36f40334708bd6cebdd1e2438395d5e7676"},
{file = "multidict-6.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:828bab777aa8d29d59700018178061854e3a47727e0611cb9bec579d3882de3b"},
{file = "multidict-6.5.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9695fc1462f17b131c111cf0856a22ff154b0480f86f539d24b2778571ff94d"},
{file = "multidict-6.5.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b5ac6ebaf5d9814b15f399337ebc6d3a7f4ce9331edd404e76c49a01620b68d"},
{file = "multidict-6.5.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84a51e3baa77ded07be4766a9e41d977987b97e49884d4c94f6d30ab6acaee14"},
{file = "multidict-6.5.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8de67f79314d24179e9b1869ed15e88d6ba5452a73fc9891ac142e0ee018b5d6"},
{file = "multidict-6.5.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17f78a52c214481d30550ec18208e287dfc4736f0c0148208334b105fd9e0887"},
{file = "multidict-6.5.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2966d0099cb2e2039f9b0e73e7fd5eb9c85805681aa2a7f867f9d95b35356921"},
{file = "multidict-6.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:86fb42ed5ed1971c642cc52acc82491af97567534a8e381a8d50c02169c4e684"},
{file = "multidict-6.5.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:4e990cbcb6382f9eae4ec720bcac6a1351509e6fc4a5bb70e4984b27973934e6"},
{file = "multidict-6.5.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d99a59d64bb1f7f2117bec837d9e534c5aeb5dcedf4c2b16b9753ed28fdc20a3"},
{file = "multidict-6.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:e8ef15cc97c9890212e1caf90f0d63f6560e1e101cf83aeaf63a57556689fb34"},
{file = "multidict-6.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:b8a09aec921b34bd8b9f842f0bcfd76c6a8c033dc5773511e15f2d517e7e1068"},
{file = "multidict-6.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ff07b504c23b67f2044533244c230808a1258b3493aaf3ea2a0785f70b7be461"},
{file = "multidict-6.5.0-cp313-cp313t-win32.whl", hash = "sha256:9232a117341e7e979d210e41c04e18f1dc3a1d251268df6c818f5334301274e1"},
{file = "multidict-6.5.0-cp313-cp313t-win_amd64.whl", hash = "sha256:44cb5c53fb2d4cbcee70a768d796052b75d89b827643788a75ea68189f0980a1"},
{file = "multidict-6.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:51d33fafa82640c0217391d4ce895d32b7e84a832b8aee0dcc1b04d8981ec7f4"},
{file = "multidict-6.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c0078358470da8dc90c37456f4a9cde9f86200949a048d53682b9cd21e5bbf2b"},
{file = "multidict-6.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5cc7968b7d1bf8b973c307d38aa3a2f2c783f149bcac855944804252f1df5105"},
{file = "multidict-6.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ad73a60e11aa92f1f2c9330efdeaac4531b719fc568eb8d312fd4112f34cc18"},
{file = "multidict-6.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3233f21abdcd180b2624eb6988a1e1287210e99bca986d8320afca5005d85844"},
{file = "multidict-6.5.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:bee5c0b79fca78fd2ab644ca4dc831ecf793eb6830b9f542ee5ed2c91bc35a0e"},
{file = "multidict-6.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e053a4d690f4352ce46583080fefade9a903ce0fa9d820db1be80bdb9304fa2f"},
{file = "multidict-6.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42bdee30424c1f4dcda96e07ac60e2a4ede8a89f8ae2f48b5e4ccc060f294c52"},
{file = "multidict-6.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58b2ded1a7982cf7b8322b0645713a0086b2b3cf5bb9f7c01edfc1a9f98d20dc"},
{file = "multidict-6.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f805b8b951d1fadc5bc18c3c93e509608ac5a883045ee33bc22e28806847c20"},
{file = "multidict-6.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2540395b63723da748f850568357a39cd8d8d4403ca9439f9fcdad6dd423c780"},
{file = "multidict-6.5.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:c96aedff25f4e47b6697ba048b2c278f7caa6df82c7c3f02e077bcc8d47b4b76"},
{file = "multidict-6.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e80de5ad995de210fd02a65c2350649b8321d09bd2e44717eaefb0f5814503e8"},
{file = "multidict-6.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:6cb9bcedd9391b313e5ec2fb3aa07c03e050550e7b9e4646c076d5c24ba01532"},
{file = "multidict-6.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a7d130ed7a112e25ab47309962ecafae07d073316f9d158bc7b3936b52b80121"},
{file = "multidict-6.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:95750a9a9741cd1855d1b6cb4c6031ae01c01ad38d280217b64bfae986d39d56"},
{file = "multidict-6.5.0-cp39-cp39-win32.whl", hash = "sha256:7f78caf409914f108f4212b53a9033abfdc2cbab0647e9ac3a25bb0f21ab43d2"},
{file = "multidict-6.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:220c74009507e847a3a6fc5375875f2a2e05bd9ce28cf607be0e8c94600f4472"},
{file = "multidict-6.5.0-cp39-cp39-win_arm64.whl", hash = "sha256:d98f4ac9c1ede7e9d04076e2e6d967e15df0079a6381b297270f6bcab661195e"},
{file = "multidict-6.5.0-py3-none-any.whl", hash = "sha256:5634b35f225977605385f56153bd95a7133faffc0ffe12ad26e10517537e8dfc"},
{file = "multidict-6.5.0.tar.gz", hash = "sha256:942bd8002492ba819426a8d7aefde3189c1b87099cdf18aaaefefcf7f3f7b6d2"},
]
[package.dependencies]
typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""}
[[package]]
name = "paho-mqtt"
version = "2.1.0"
@ -489,113 +77,6 @@ files = [
[package.extras]
proxy = ["pysocks"]
[[package]]
name = "propcache"
version = "0.3.2"
description = "Accelerated property cache"
optional = false
python-versions = ">=3.9"
files = [
{file = "propcache-0.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:22d9962a358aedbb7a2e36187ff273adeaab9743373a272976d2e348d08c7770"},
{file = "propcache-0.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0d0fda578d1dc3f77b6b5a5dce3b9ad69a8250a891760a548df850a5e8da87f3"},
{file = "propcache-0.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3def3da3ac3ce41562d85db655d18ebac740cb3fa4367f11a52b3da9d03a5cc3"},
{file = "propcache-0.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bec58347a5a6cebf239daba9bda37dffec5b8d2ce004d9fe4edef3d2815137e"},
{file = "propcache-0.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55ffda449a507e9fbd4aca1a7d9aa6753b07d6166140e5a18d2ac9bc49eac220"},
{file = "propcache-0.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64a67fb39229a8a8491dd42f864e5e263155e729c2e7ff723d6e25f596b1e8cb"},
{file = "propcache-0.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da1cf97b92b51253d5b68cf5a2b9e0dafca095e36b7f2da335e27dc6172a614"},
{file = "propcache-0.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f559e127134b07425134b4065be45b166183fdcb433cb6c24c8e4149056ad50"},
{file = "propcache-0.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aff2e4e06435d61f11a428360a932138d0ec288b0a31dd9bd78d200bd4a2b339"},
{file = "propcache-0.3.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:4927842833830942a5d0a56e6f4839bc484785b8e1ce8d287359794818633ba0"},
{file = "propcache-0.3.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:6107ddd08b02654a30fb8ad7a132021759d750a82578b94cd55ee2772b6ebea2"},
{file = "propcache-0.3.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:70bd8b9cd6b519e12859c99f3fc9a93f375ebd22a50296c3a295028bea73b9e7"},
{file = "propcache-0.3.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2183111651d710d3097338dd1893fcf09c9f54e27ff1a8795495a16a469cc90b"},
{file = "propcache-0.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fb075ad271405dcad8e2a7ffc9a750a3bf70e533bd86e89f0603e607b93aa64c"},
{file = "propcache-0.3.2-cp310-cp310-win32.whl", hash = "sha256:404d70768080d3d3bdb41d0771037da19d8340d50b08e104ca0e7f9ce55fce70"},
{file = "propcache-0.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:7435d766f978b4ede777002e6b3b6641dd229cd1da8d3d3106a45770365f9ad9"},
{file = "propcache-0.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0b8d2f607bd8f80ddc04088bc2a037fdd17884a6fcadc47a96e334d72f3717be"},
{file = "propcache-0.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06766d8f34733416e2e34f46fea488ad5d60726bb9481d3cddf89a6fa2d9603f"},
{file = "propcache-0.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2dc1f4a1df4fecf4e6f68013575ff4af84ef6f478fe5344317a65d38a8e6dc9"},
{file = "propcache-0.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be29c4f4810c5789cf10ddf6af80b041c724e629fa51e308a7a0fb19ed1ef7bf"},
{file = "propcache-0.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59d61f6970ecbd8ff2e9360304d5c8876a6abd4530cb752c06586849ac8a9dc9"},
{file = "propcache-0.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62180e0b8dbb6b004baec00a7983e4cc52f5ada9cd11f48c3528d8cfa7b96a66"},
{file = "propcache-0.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c144ca294a204c470f18cf4c9d78887810d04a3e2fbb30eea903575a779159df"},
{file = "propcache-0.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5c2a784234c28854878d68978265617aa6dc0780e53d44b4d67f3651a17a9a2"},
{file = "propcache-0.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5745bc7acdafa978ca1642891b82c19238eadc78ba2aaa293c6863b304e552d7"},
{file = "propcache-0.3.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:c0075bf773d66fa8c9d41f66cc132ecc75e5bb9dd7cce3cfd14adc5ca184cb95"},
{file = "propcache-0.3.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5f57aa0847730daceff0497f417c9de353c575d8da3579162cc74ac294c5369e"},
{file = "propcache-0.3.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:eef914c014bf72d18efb55619447e0aecd5fb7c2e3fa7441e2e5d6099bddff7e"},
{file = "propcache-0.3.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2a4092e8549031e82facf3decdbc0883755d5bbcc62d3aea9d9e185549936dcf"},
{file = "propcache-0.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:85871b050f174bc0bfb437efbdb68aaf860611953ed12418e4361bc9c392749e"},
{file = "propcache-0.3.2-cp311-cp311-win32.whl", hash = "sha256:36c8d9b673ec57900c3554264e630d45980fd302458e4ac801802a7fd2ef7897"},
{file = "propcache-0.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53af8cb6a781b02d2ea079b5b853ba9430fcbe18a8e3ce647d5982a3ff69f39"},
{file = "propcache-0.3.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8de106b6c84506b31c27168582cd3cb3000a6412c16df14a8628e5871ff83c10"},
{file = "propcache-0.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:28710b0d3975117239c76600ea351934ac7b5ff56e60953474342608dbbb6154"},
{file = "propcache-0.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce26862344bdf836650ed2487c3d724b00fbfec4233a1013f597b78c1cb73615"},
{file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca54bd347a253af2cf4544bbec232ab982f4868de0dd684246b67a51bc6b1db"},
{file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55780d5e9a2ddc59711d727226bb1ba83a22dd32f64ee15594b9392b1f544eb1"},
{file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:035e631be25d6975ed87ab23153db6a73426a48db688070d925aa27e996fe93c"},
{file = "propcache-0.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee6f22b6eaa39297c751d0e80c0d3a454f112f5c6481214fcf4c092074cecd67"},
{file = "propcache-0.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ca3aee1aa955438c4dba34fc20a9f390e4c79967257d830f137bd5a8a32ed3b"},
{file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4f30862869fa2b68380d677cc1c5fcf1e0f2b9ea0cf665812895c75d0ca3b8"},
{file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:b77ec3c257d7816d9f3700013639db7491a434644c906a2578a11daf13176251"},
{file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:cab90ac9d3f14b2d5050928483d3d3b8fb6b4018893fc75710e6aa361ecb2474"},
{file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0b504d29f3c47cf6b9e936c1852246c83d450e8e063d50562115a6be6d3a2535"},
{file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:ce2ac2675a6aa41ddb2a0c9cbff53780a617ac3d43e620f8fd77ba1c84dcfc06"},
{file = "propcache-0.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:62b4239611205294cc433845b914131b2a1f03500ff3c1ed093ed216b82621e1"},
{file = "propcache-0.3.2-cp312-cp312-win32.whl", hash = "sha256:df4a81b9b53449ebc90cc4deefb052c1dd934ba85012aa912c7ea7b7e38b60c1"},
{file = "propcache-0.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7046e79b989d7fe457bb755844019e10f693752d169076138abf17f31380800c"},
{file = "propcache-0.3.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ca592ed634a73ca002967458187109265e980422116c0a107cf93d81f95af945"},
{file = "propcache-0.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9ecb0aad4020e275652ba3975740f241bd12a61f1a784df044cf7477a02bc252"},
{file = "propcache-0.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7f08f1cc28bd2eade7a8a3d2954ccc673bb02062e3e7da09bc75d843386b342f"},
{file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1a342c834734edb4be5ecb1e9fb48cb64b1e2320fccbd8c54bf8da8f2a84c33"},
{file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a544caaae1ac73f1fecfae70ded3e93728831affebd017d53449e3ac052ac1e"},
{file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:310d11aa44635298397db47a3ebce7db99a4cc4b9bbdfcf6c98a60c8d5261cf1"},
{file = "propcache-0.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c1396592321ac83157ac03a2023aa6cc4a3cc3cfdecb71090054c09e5a7cce3"},
{file = "propcache-0.3.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cabf5b5902272565e78197edb682017d21cf3b550ba0460ee473753f28d23c1"},
{file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0a2f2235ac46a7aa25bdeb03a9e7060f6ecbd213b1f9101c43b3090ffb971ef6"},
{file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:92b69e12e34869a6970fd2f3da91669899994b47c98f5d430b781c26f1d9f387"},
{file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:54e02207c79968ebbdffc169591009f4474dde3b4679e16634d34c9363ff56b4"},
{file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4adfb44cb588001f68c5466579d3f1157ca07f7504fc91ec87862e2b8e556b88"},
{file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fd3e6019dc1261cd0291ee8919dd91fbab7b169bb76aeef6c716833a3f65d206"},
{file = "propcache-0.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4c181cad81158d71c41a2bce88edce078458e2dd5ffee7eddd6b05da85079f43"},
{file = "propcache-0.3.2-cp313-cp313-win32.whl", hash = "sha256:8a08154613f2249519e549de2330cf8e2071c2887309a7b07fb56098f5170a02"},
{file = "propcache-0.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e41671f1594fc4ab0a6dec1351864713cb3a279910ae8b58f884a88a0a632c05"},
{file = "propcache-0.3.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:9a3cf035bbaf035f109987d9d55dc90e4b0e36e04bbbb95af3055ef17194057b"},
{file = "propcache-0.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:156c03d07dc1323d8dacaa221fbe028c5c70d16709cdd63502778e6c3ccca1b0"},
{file = "propcache-0.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74413c0ba02ba86f55cf60d18daab219f7e531620c15f1e23d95563f505efe7e"},
{file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f066b437bb3fa39c58ff97ab2ca351db465157d68ed0440abecb21715eb24b28"},
{file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1304b085c83067914721e7e9d9917d41ad87696bf70f0bc7dee450e9c71ad0a"},
{file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab50cef01b372763a13333b4e54021bdcb291fc9a8e2ccb9c2df98be51bcde6c"},
{file = "propcache-0.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fad3b2a085ec259ad2c2842666b2a0a49dea8463579c606426128925af1ed725"},
{file = "propcache-0.3.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:261fa020c1c14deafd54c76b014956e2f86991af198c51139faf41c4d5e83892"},
{file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:46d7f8aa79c927e5f987ee3a80205c987717d3659f035c85cf0c3680526bdb44"},
{file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:6d8f3f0eebf73e3c0ff0e7853f68be638b4043c65a70517bb575eff54edd8dbe"},
{file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:03c89c1b14a5452cf15403e291c0ccd7751d5b9736ecb2c5bab977ad6c5bcd81"},
{file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc17efde71e12bbaad086d679ce575268d70bc123a5a71ea7ad76f70ba30bba"},
{file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:acdf05d00696bc0447e278bb53cb04ca72354e562cf88ea6f9107df8e7fd9770"},
{file = "propcache-0.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4445542398bd0b5d32df908031cb1b30d43ac848e20470a878b770ec2dcc6330"},
{file = "propcache-0.3.2-cp313-cp313t-win32.whl", hash = "sha256:f86e5d7cd03afb3a1db8e9f9f6eff15794e79e791350ac48a8c924e6f439f394"},
{file = "propcache-0.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9704bedf6e7cbe3c65eca4379a9b53ee6a83749f047808cbb5044d40d7d72198"},
{file = "propcache-0.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a7fad897f14d92086d6b03fdd2eb844777b0c4d7ec5e3bac0fbae2ab0602bbe5"},
{file = "propcache-0.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1f43837d4ca000243fd7fd6301947d7cb93360d03cd08369969450cc6b2ce3b4"},
{file = "propcache-0.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:261df2e9474a5949c46e962065d88eb9b96ce0f2bd30e9d3136bcde84befd8f2"},
{file = "propcache-0.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e514326b79e51f0a177daab1052bc164d9d9e54133797a3a58d24c9c87a3fe6d"},
{file = "propcache-0.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a996adb6904f85894570301939afeee65f072b4fd265ed7e569e8d9058e4ec"},
{file = "propcache-0.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76cace5d6b2a54e55b137669b30f31aa15977eeed390c7cbfb1dafa8dfe9a701"},
{file = "propcache-0.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31248e44b81d59d6addbb182c4720f90b44e1efdc19f58112a3c3a1615fb47ef"},
{file = "propcache-0.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abb7fa19dbf88d3857363e0493b999b8011eea856b846305d8c0512dfdf8fbb1"},
{file = "propcache-0.3.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d81ac3ae39d38588ad0549e321e6f773a4e7cc68e7751524a22885d5bbadf886"},
{file = "propcache-0.3.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:cc2782eb0f7a16462285b6f8394bbbd0e1ee5f928034e941ffc444012224171b"},
{file = "propcache-0.3.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:db429c19a6c7e8a1c320e6a13c99799450f411b02251fb1b75e6217cf4a14fcb"},
{file = "propcache-0.3.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:21d8759141a9e00a681d35a1f160892a36fb6caa715ba0b832f7747da48fb6ea"},
{file = "propcache-0.3.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2ca6d378f09adb13837614ad2754fa8afaee330254f404299611bce41a8438cb"},
{file = "propcache-0.3.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:34a624af06c048946709f4278b4176470073deda88d91342665d95f7c6270fbe"},
{file = "propcache-0.3.2-cp39-cp39-win32.whl", hash = "sha256:4ba3fef1c30f306b1c274ce0b8baaa2c3cdd91f645c48f06394068f37d3837a1"},
{file = "propcache-0.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:7a2368eed65fc69a7a7a40b27f22e85e7627b74216f0846b04ba5c116e191ec9"},
{file = "propcache-0.3.2-py3-none-any.whl", hash = "sha256:98f1ec44fb675f5052cccc8e609c46ed23a35a1cfd18545ad4e29002d858a43f"},
{file = "propcache-0.3.2.tar.gz", hash = "sha256:20d7d62e4e7ef05f221e0db2856b979540686342e7dd9973b815599c7057e168"},
]
[[package]]
name = "pyserial"
version = "3.5"
@ -667,136 +148,7 @@ files = [
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
[[package]]
name = "typing-extensions"
version = "4.14.0"
description = "Backported and Experimental Type Hints for Python 3.9+"
optional = false
python-versions = ">=3.9"
files = [
{file = "typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af"},
{file = "typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4"},
]
[[package]]
name = "yarl"
version = "1.20.1"
description = "Yet another URL library"
optional = false
python-versions = ">=3.9"
files = [
{file = "yarl-1.20.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6032e6da6abd41e4acda34d75a816012717000fa6839f37124a47fcefc49bec4"},
{file = "yarl-1.20.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2c7b34d804b8cf9b214f05015c4fee2ebe7ed05cf581e7192c06555c71f4446a"},
{file = "yarl-1.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0c869f2651cc77465f6cd01d938d91a11d9ea5d798738c1dc077f3de0b5e5fed"},
{file = "yarl-1.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62915e6688eb4d180d93840cda4110995ad50c459bf931b8b3775b37c264af1e"},
{file = "yarl-1.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:41ebd28167bc6af8abb97fec1a399f412eec5fd61a3ccbe2305a18b84fb4ca73"},
{file = "yarl-1.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21242b4288a6d56f04ea193adde174b7e347ac46ce6bc84989ff7c1b1ecea84e"},
{file = "yarl-1.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bea21cdae6c7eb02ba02a475f37463abfe0a01f5d7200121b03e605d6a0439f8"},
{file = "yarl-1.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f8a891e4a22a89f5dde7862994485e19db246b70bb288d3ce73a34422e55b23"},
{file = "yarl-1.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd803820d44c8853a109a34e3660e5a61beae12970da479cf44aa2954019bf70"},
{file = "yarl-1.20.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b982fa7f74c80d5c0c7b5b38f908971e513380a10fecea528091405f519b9ebb"},
{file = "yarl-1.20.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:33f29ecfe0330c570d997bcf1afd304377f2e48f61447f37e846a6058a4d33b2"},
{file = "yarl-1.20.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:835ab2cfc74d5eb4a6a528c57f05688099da41cf4957cf08cad38647e4a83b30"},
{file = "yarl-1.20.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:46b5e0ccf1943a9a6e766b2c2b8c732c55b34e28be57d8daa2b3c1d1d4009309"},
{file = "yarl-1.20.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:df47c55f7d74127d1b11251fe6397d84afdde0d53b90bedb46a23c0e534f9d24"},
{file = "yarl-1.20.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76d12524d05841276b0e22573f28d5fbcb67589836772ae9244d90dd7d66aa13"},
{file = "yarl-1.20.1-cp310-cp310-win32.whl", hash = "sha256:6c4fbf6b02d70e512d7ade4b1f998f237137f1417ab07ec06358ea04f69134f8"},
{file = "yarl-1.20.1-cp310-cp310-win_amd64.whl", hash = "sha256:aef6c4d69554d44b7f9d923245f8ad9a707d971e6209d51279196d8e8fe1ae16"},
{file = "yarl-1.20.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47ee6188fea634bdfaeb2cc420f5b3b17332e6225ce88149a17c413c77ff269e"},
{file = "yarl-1.20.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d0f6500f69e8402d513e5eedb77a4e1818691e8f45e6b687147963514d84b44b"},
{file = "yarl-1.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a8900a42fcdaad568de58887c7b2f602962356908eedb7628eaf6021a6e435b"},
{file = "yarl-1.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bad6d131fda8ef508b36be3ece16d0902e80b88ea7200f030a0f6c11d9e508d4"},
{file = "yarl-1.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:df018d92fe22aaebb679a7f89fe0c0f368ec497e3dda6cb81a567610f04501f1"},
{file = "yarl-1.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f969afbb0a9b63c18d0feecf0db09d164b7a44a053e78a7d05f5df163e43833"},
{file = "yarl-1.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:812303eb4aa98e302886ccda58d6b099e3576b1b9276161469c25803a8db277d"},
{file = "yarl-1.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98c4a7d166635147924aa0bf9bfe8d8abad6fffa6102de9c99ea04a1376f91e8"},
{file = "yarl-1.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12e768f966538e81e6e7550f9086a6236b16e26cd964cf4df35349970f3551cf"},
{file = "yarl-1.20.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:fe41919b9d899661c5c28a8b4b0acf704510b88f27f0934ac7a7bebdd8938d5e"},
{file = "yarl-1.20.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:8601bc010d1d7780592f3fc1bdc6c72e2b6466ea34569778422943e1a1f3c389"},
{file = "yarl-1.20.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:daadbdc1f2a9033a2399c42646fbd46da7992e868a5fe9513860122d7fe7a73f"},
{file = "yarl-1.20.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:03aa1e041727cb438ca762628109ef1333498b122e4c76dd858d186a37cec845"},
{file = "yarl-1.20.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:642980ef5e0fa1de5fa96d905c7e00cb2c47cb468bfcac5a18c58e27dbf8d8d1"},
{file = "yarl-1.20.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:86971e2795584fe8c002356d3b97ef6c61862720eeff03db2a7c86b678d85b3e"},
{file = "yarl-1.20.1-cp311-cp311-win32.whl", hash = "sha256:597f40615b8d25812f14562699e287f0dcc035d25eb74da72cae043bb884d773"},
{file = "yarl-1.20.1-cp311-cp311-win_amd64.whl", hash = "sha256:26ef53a9e726e61e9cd1cda6b478f17e350fb5800b4bd1cd9fe81c4d91cfeb2e"},
{file = "yarl-1.20.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdcc4cd244e58593a4379fe60fdee5ac0331f8eb70320a24d591a3be197b94a9"},
{file = "yarl-1.20.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b29a2c385a5f5b9c7d9347e5812b6f7ab267193c62d282a540b4fc528c8a9d2a"},
{file = "yarl-1.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1112ae8154186dfe2de4732197f59c05a83dc814849a5ced892b708033f40dc2"},
{file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90bbd29c4fe234233f7fa2b9b121fb63c321830e5d05b45153a2ca68f7d310ee"},
{file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:680e19c7ce3710ac4cd964e90dad99bf9b5029372ba0c7cbfcd55e54d90ea819"},
{file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a979218c1fdb4246a05efc2cc23859d47c89af463a90b99b7c56094daf25a16"},
{file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255b468adf57b4a7b65d8aad5b5138dce6a0752c139965711bdcb81bc370e1b6"},
{file = "yarl-1.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a97d67108e79cfe22e2b430d80d7571ae57d19f17cda8bb967057ca8a7bf5bfd"},
{file = "yarl-1.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8570d998db4ddbfb9a590b185a0a33dbf8aafb831d07a5257b4ec9948df9cb0a"},
{file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:97c75596019baae7c71ccf1d8cc4738bc08134060d0adfcbe5642f778d1dca38"},
{file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1c48912653e63aef91ff988c5432832692ac5a1d8f0fb8a33091520b5bbe19ef"},
{file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4c3ae28f3ae1563c50f3d37f064ddb1511ecc1d5584e88c6b7c63cf7702a6d5f"},
{file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e9642f27036283550f5f57dc6156c51084b458570b9d0d96100c8bebb186a8"},
{file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2c26b0c49220d5799f7b22c6838409ee9bc58ee5c95361a4d7831f03cc225b5a"},
{file = "yarl-1.20.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564ab3d517e3d01c408c67f2e5247aad4019dcf1969982aba3974b4093279004"},
{file = "yarl-1.20.1-cp312-cp312-win32.whl", hash = "sha256:daea0d313868da1cf2fac6b2d3a25c6e3a9e879483244be38c8e6a41f1d876a5"},
{file = "yarl-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:48ea7d7f9be0487339828a4de0360d7ce0efc06524a48e1810f945c45b813698"},
{file = "yarl-1.20.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:0b5ff0fbb7c9f1b1b5ab53330acbfc5247893069e7716840c8e7d5bb7355038a"},
{file = "yarl-1.20.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:14f326acd845c2b2e2eb38fb1346c94f7f3b01a4f5c788f8144f9b630bfff9a3"},
{file = "yarl-1.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f60e4ad5db23f0b96e49c018596707c3ae89f5d0bd97f0ad3684bcbad899f1e7"},
{file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49bdd1b8e00ce57e68ba51916e4bb04461746e794e7c4d4bbc42ba2f18297691"},
{file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:66252d780b45189975abfed839616e8fd2dbacbdc262105ad7742c6ae58f3e31"},
{file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59174e7332f5d153d8f7452a102b103e2e74035ad085f404df2e40e663a22b28"},
{file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3968ec7d92a0c0f9ac34d5ecfd03869ec0cab0697c91a45db3fbbd95fe1b653"},
{file = "yarl-1.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1a4fbb50e14396ba3d375f68bfe02215d8e7bc3ec49da8341fe3157f59d2ff5"},
{file = "yarl-1.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11a62c839c3a8eac2410e951301309426f368388ff2f33799052787035793b02"},
{file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:041eaa14f73ff5a8986b4388ac6bb43a77f2ea09bf1913df7a35d4646db69e53"},
{file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:377fae2fef158e8fd9d60b4c8751387b8d1fb121d3d0b8e9b0be07d1b41e83dc"},
{file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1c92f4390e407513f619d49319023664643d3339bd5e5a56a3bebe01bc67ec04"},
{file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d25ddcf954df1754ab0f86bb696af765c5bfaba39b74095f27eececa049ef9a4"},
{file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:909313577e9619dcff8c31a0ea2aa0a2a828341d92673015456b3ae492e7317b"},
{file = "yarl-1.20.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:793fd0580cb9664548c6b83c63b43c477212c0260891ddf86809e1c06c8b08f1"},
{file = "yarl-1.20.1-cp313-cp313-win32.whl", hash = "sha256:468f6e40285de5a5b3c44981ca3a319a4b208ccc07d526b20b12aeedcfa654b7"},
{file = "yarl-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:495b4ef2fea40596bfc0affe3837411d6aa3371abcf31aac0ccc4bdd64d4ef5c"},
{file = "yarl-1.20.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f60233b98423aab21d249a30eb27c389c14929f47be8430efa7dbd91493a729d"},
{file = "yarl-1.20.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6f3eff4cc3f03d650d8755c6eefc844edde99d641d0dcf4da3ab27141a5f8ddf"},
{file = "yarl-1.20.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:69ff8439d8ba832d6bed88af2c2b3445977eba9a4588b787b32945871c2444e3"},
{file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cf34efa60eb81dd2645a2e13e00bb98b76c35ab5061a3989c7a70f78c85006d"},
{file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8e0fe9364ad0fddab2688ce72cb7a8e61ea42eff3c7caeeb83874a5d479c896c"},
{file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f64fbf81878ba914562c672024089e3401974a39767747691c65080a67b18c1"},
{file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6342d643bf9a1de97e512e45e4b9560a043347e779a173250824f8b254bd5ce"},
{file = "yarl-1.20.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56dac5f452ed25eef0f6e3c6a066c6ab68971d96a9fb441791cad0efba6140d3"},
{file = "yarl-1.20.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7d7f497126d65e2cad8dc5f97d34c27b19199b6414a40cb36b52f41b79014be"},
{file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:67e708dfb8e78d8a19169818eeb5c7a80717562de9051bf2413aca8e3696bf16"},
{file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:595c07bc79af2494365cc96ddeb772f76272364ef7c80fb892ef9d0649586513"},
{file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7bdd2f80f4a7df852ab9ab49484a4dee8030023aa536df41f2d922fd57bf023f"},
{file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:c03bfebc4ae8d862f853a9757199677ab74ec25424d0ebd68a0027e9c639a390"},
{file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:344d1103e9c1523f32a5ed704d576172d2cabed3122ea90b1d4e11fe17c66458"},
{file = "yarl-1.20.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88cab98aa4e13e1ade8c141daeedd300a4603b7132819c484841bb7af3edce9e"},
{file = "yarl-1.20.1-cp313-cp313t-win32.whl", hash = "sha256:b121ff6a7cbd4abc28985b6028235491941b9fe8fe226e6fdc539c977ea1739d"},
{file = "yarl-1.20.1-cp313-cp313t-win_amd64.whl", hash = "sha256:541d050a355bbbc27e55d906bc91cb6fe42f96c01413dd0f4ed5a5240513874f"},
{file = "yarl-1.20.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e42ba79e2efb6845ebab49c7bf20306c4edf74a0b20fc6b2ccdd1a219d12fad3"},
{file = "yarl-1.20.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:41493b9b7c312ac448b7f0a42a089dffe1d6e6e981a2d76205801a023ed26a2b"},
{file = "yarl-1.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5a5928ff5eb13408c62a968ac90d43f8322fd56d87008b8f9dabf3c0f6ee983"},
{file = "yarl-1.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30c41ad5d717b3961b2dd785593b67d386b73feca30522048d37298fee981805"},
{file = "yarl-1.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:59febc3969b0781682b469d4aca1a5cab7505a4f7b85acf6db01fa500fa3f6ba"},
{file = "yarl-1.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d2b6fb3622b7e5bf7a6e5b679a69326b4279e805ed1699d749739a61d242449e"},
{file = "yarl-1.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:749d73611db8d26a6281086f859ea7ec08f9c4c56cec864e52028c8b328db723"},
{file = "yarl-1.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9427925776096e664c39e131447aa20ec738bdd77c049c48ea5200db2237e000"},
{file = "yarl-1.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff70f32aa316393eaf8222d518ce9118148eddb8a53073c2403863b41033eed5"},
{file = "yarl-1.20.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c7ddf7a09f38667aea38801da8b8d6bfe81df767d9dfc8c88eb45827b195cd1c"},
{file = "yarl-1.20.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:57edc88517d7fc62b174fcfb2e939fbc486a68315d648d7e74d07fac42cec240"},
{file = "yarl-1.20.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:dab096ce479d5894d62c26ff4f699ec9072269d514b4edd630a393223f45a0ee"},
{file = "yarl-1.20.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:14a85f3bd2d7bb255be7183e5d7d6e70add151a98edf56a770d6140f5d5f4010"},
{file = "yarl-1.20.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:2c89b5c792685dd9cd3fa9761c1b9f46fc240c2a3265483acc1565769996a3f8"},
{file = "yarl-1.20.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:69e9b141de5511021942a6866990aea6d111c9042235de90e08f94cf972ca03d"},
{file = "yarl-1.20.1-cp39-cp39-win32.whl", hash = "sha256:b5f307337819cdfdbb40193cad84978a029f847b0a357fbe49f712063cfc4f06"},
{file = "yarl-1.20.1-cp39-cp39-win_amd64.whl", hash = "sha256:eae7bfe2069f9c1c5b05fc7fe5d612e5bbc089a39309904ee8b829e322dcad00"},
{file = "yarl-1.20.1-py3-none-any.whl", hash = "sha256:83b8eb083fe4683c6115795d9fc1cfaf2cbbefb19b3a1cb68f6527460f483a77"},
{file = "yarl-1.20.1.tar.gz", hash = "sha256:d017a4997ee50c91fd5466cef416231bb82177b93b029906cefc542ce14c35ac"},
]
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
propcache = ">=0.2.1"
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "a7ae9d972673e97295d579159de1fb320896ed53913cf68f5b270c50bd271e03"
content-hash = "5e30fcfae3a69f8475da0f4ba655b5194a80b2a2185c652cbce2c72fa83aa752"

View file

@ -6,7 +6,6 @@ import aiomqtt
import asyncio
#from i2cpy import I2C
from smbus2 import SMBus
import toml
#import i2cpy
#i2cset -y 1 0x11 0x11 0x42
#set i2c address from 0x11 to 0x42
@ -15,11 +14,8 @@ import toml
#Device.pin_factory = gpiozero.pins.mock.MockFactory()
#relays = [LED(17), LED(27), LED(22), LED(23), LED(5), LED(6), LED(24), LED(25)]
main_I2C_addr = 0 #default
side_I2C_addr = 0
room = ""
use_offset = False
relayBoardMain = 0x42
relayBoardSide = 0x43
""" 0 1 2 3 """
relayMasks = [0b0001, 0b0010, 0b0100, 0b1000] #probably ne rabim
@ -33,8 +29,8 @@ relMapping = {
}
currentState = {
'main': 0b0000,
'side': 0b0000
'glavni': 0b0000,
'stranski': 0b0000
}
async def msgRelayBoard(projSelect, command, state: bool):
@ -43,16 +39,10 @@ async def msgRelayBoard(projSelect, command, state: bool):
# register 0x10 za releje
I2CAddr = 0 #glavni
match projSelect:
case 'main':
I2CAddr = main_I2C_addr
case 'side':
I2CAddr = side_I2C_addr
#return #TODO TEMPORARY, REMOVE LATER#
case default:
return #ignore if unknown position
I2CAddr = 0x42 #glavni
if projSelect == 'stranski':
I2CAddr += 0x1
maskShift = relMapping[command]
mask = (1 << maskShift)
if state:
@ -61,8 +51,8 @@ async def msgRelayBoard(projSelect, command, state: bool):
currentState[projSelect] = currentState[projSelect] & ~mask
bus.write_byte_data(I2CAddr, 0x10, currentState[projSelect])
print("Command sent")
#print('testirovano jako')
print('testirovano jako')
"""
@ -81,42 +71,32 @@ SIDE: 4 5 6 7
#dej like bolš to podukumentiraj or smth
async def task_command2relays(controlClient: aiomqtt.Client):
global room
#relayCtrl = lambda cmd, relay: relays[relay].on() if cmd == 1 else relays[relay].off()
#relayCtrl = lambda cmd, relay: [relays[r].on() if cmd == 1 and r == relay else relays[r].off for r in range(len(relays))]
relayCtrl = lambda x, y: print(x, y)
await controlClient.subscribe(f"{room}/projectors/+/lift/#")
await controlClient.subscribe("p01/projectors/+/lift/#")
msgs = controlClient.messages
async for mesg in msgs:
mesg: aiomqtt.Message
if mesg.topic.matches(f'{room}/projectors/+/lift/move/#'):
if mesg.topic.matches('p01/projectors/+/lift/move/#'):
msgTopicArr = mesg.topic.value.split('/')
state = mesg.payload.decode()
print("Received: " + str(msgTopicArr) + " payload: [" + state + "]")
#testCase = (msgTopicArr[2], msgTopicArr[4])
projSel = msgTopicArr[2]
if projSel != 'main' and projSel != 'side':
continue #TODO error hnadling?
if projSel != 'glavni' and projSel != 'stranski':
continue
command = msgTopicArr[5]
await msgRelayBoard(projSel, command, state == '1')
await controlClient.publish(f'{room}/projectors/{projSel}/lift/status', payload="", qos=1, retain=True)
#print("Pushing \'off\' to other relays to prevent conflicts")
await asyncio.sleep(0.01)
async def main():
global main_I2C_addr, side_I2C_addr, room
conf = toml.load('./malinaConfig.toml')
projMotors = conf.get("projector_motors")
mainMotor = projMotors.get("main")
sideMotor = projMotors.get("side")
main_I2C_addr = mainMotor['i2c_address']
side_I2C_addr = sideMotor['i2c_address']
room = conf["global"]["room"]
async with aiomqtt.Client('localhost', 1883) as client:
task_control = asyncio.create_task(task_command2relays(client))
await asyncio.gather(task_control)

View file

@ -15,7 +15,6 @@ gpiozero = "^2.0.1"
telnetlib3 = "^2.0.4"
toml = "^0.10.2"
smbus2 = "^0.5.0"
aiohttp = "^3.12.13"
[build-system]

View file

@ -0,0 +1,18 @@
predavalnice_pi:
# Skupne spremenljivke za vse zaslone
vars:
# Check here: https://github.com/leukipp/touchkio/releases
touchkio_version: "1.1.2"
# Multimedia network
static_ip_netmask: "255.255.255.0"
static_ip_gateway: "192.168.190.1"
static_ip_dns_servers:
- "212.235.188.28"
- "212.235.188.29"
hosts:
p01_touch_display:
predavalnica: p01
static_ip_address: "192.168.190.111"
hostname: "p01_touch_display.local"
kiosk_url: "http://192.168.190.110"

6
touch_display/main.yml Normal file
View file

@ -0,0 +1,6 @@
- hosts: predavalnice_pi
# TODO: better include (import playbook)
tasks:
- include_tasks: static_ip.yml
- include_tasks: pi_stuff.yml
- include_tasks: touch_display.yml

View file

@ -0,0 +1,36 @@
- name: Enable boot splash screen
become: true
shell: "raspi-config nonint get_boot_splash && raspi-config nonint do_boot_splash 0"
register: boot_splash
changed_when:
- boot_splash == "1"
- name: Disable color splash
become: true
community.general.ini_file:
path: /boot/firmware/config.txt
option: disable_splash
value: 1
no_extra_spaces: true
- name: Change splash image
become: true
copy:
src: splash.png
dest: /usr/share/plymouth/themes/pix/splash.png
- name: Remove desktop bloat
become: true
apt:
name:
- gvfs
- gnome-keyring
- cups
state: absent
- name: Switch to wayfire
become: true
shell: "raspi-config nonint is_wayfire && raspi-config nonint do_wayland W2"
register: result
failed_when: ( result.rc not in [ 0, 1 ] )
changed_when: ( result.rc == 1 )

BIN
touch_display/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -0,0 +1,28 @@
- name: Configure static IP address (using Network Manager).
become: yes
community.general.nmcli:
conn_name: "Multimedia net"
ifname: eth0
type: ethernet
ip4: "{{ static_ip_address }}/{{ static_ip_netmask | ansible.utils.ipaddr('prefix') }}"
gw4: "{{static_ip_gateway}}"
state: present
- name: Restart NetworkManager
become: yes
service:
name: NetworkManager
state: restarted
- name: Wait for network to be available
become: yes
wait_for_connection:
timeout: 60
# TODO: get rid of netaddr
- name: Display new IP configuration
debug:
msg: "Static IP configured: {{ static_ip_address }}/{{ static_ip_netmask | ansible.utils.ipaddr('prefix') }}"

View file

@ -0,0 +1,32 @@
- name: Download .deb file
get_url:
url: "https://github.com/leukipp/touchkio/releases/download/v{{ touchkio_version }}/touchkio_{{ touchkio_version }}_arm64.deb"
dest: "/tmp/touchkio_{{ touchkio_version }}_arm64.deb"
register: deb_download
- name: Install the latest .deb package
become: yes
apt:
deb: "/tmp/touchkio_{{ touchkio_version }}_arm64.deb"
when: deb_download is succeeded
- name: Create systemd user service directory
file:
path: "{{ ansible_env.HOME }}/.config/systemd/user"
state: directory
- name: Create systemd user service
template:
src: touchkio.service.j2
dest: "{{ ansible_env.HOME }}/.config/systemd/user/touchkio.service"
- name: Enable systemd service
ansible.builtin.systemd_service:
name: touchkio
enabled: true
state: restarted
scope: user
daemon_reload: true
when: ansible_check_mode == false

View file

@ -0,0 +1,11 @@
[Unit]
Description=TouchKio
After=graphical.target
[Service]
ExecStart=/usr/bin/touchkio --web-url="{{ kiosk_url }}"
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=default.target

View file

@ -9,9 +9,7 @@ import sys
import toml
import serial.tools.list_ports
#GLOBALS
room = 'undefined' #TODO make be do get fronm file of configuration
room = 'p01' #TODO make be do get fronm file of configuration
# serPath = '/dev/serial/by-id/'
# devLst = os.listdir(serPath)
@ -20,7 +18,7 @@ room = 'undefined' #TODO make be do get fronm file of configuration
# serDev = devLst[0]
portList = serial.tools.list_ports.comports()
if len(portList) < 1:
if portList < 1:
sys.exit("No serial port found")
#TODO if multiple ports idk, shouldn't ever happen but still
(serport, serdesc, serhwid) = portList[0]
@ -43,19 +41,19 @@ mapping_toggles = {
}
# 4 is not connected to anything
platno_mapping = {
"main": {
"DOWN": 5,
"UP": 6
"glavni": {
"dol": 5,
"gor": 6
},
"side": {
"DOWN": 7,
"UP": 8
"stranski": {
"dol": 7,
"gor": 8
}
}
shades_mapping = {
"DOWN": 9,
"UP": 10
"dol": 9,
"gor": 10
}
reverse_lookup = {
@ -63,14 +61,14 @@ reverse_lookup = {
2: "audio",
3: "projectors",
5: "main_down",
6: "main_up",
5: "glavni_dol",
6: "glavni_gor",
7: "side_down",
8: "side_up",
7: "glavni_dol",
8: "glavni_gor",
9: "shades_down",
10: "shades_up"
9: "shades_dol",
10: "shades_gor"
}
@ -86,11 +84,11 @@ async def task_status2mqtt(statusClient: aiomqtt.Client):
action = relState.state
publishTopic = f"{room}/"
publishPayload = "ON" if relState.state else "OFF"
print("Publishing [" + publishPayload + "] to topic [" + publishTopic + "]")
await statusClient.publish(publishTopic, payload=publishPayload)
await asyncio.sleep(10)
#publishTopic = f"{room}/"
#publishPayload = "ON" if relState.state else "OFF"
#print("Publishing [" + publishPayload + "] to topic [" + publishTopic + "]")
#await statusClient.publish(publishTopic, payload=publishPayload)
await asyncio.sleep(0.01)
async def executeAndPublish(mqttClient, pubTopic, pubPayload, relStat):
@ -99,27 +97,26 @@ async def executeAndPublish(mqttClient, pubTopic, pubPayload, relStat):
print("Sending to TSE box: " + setRelayCmd)
print(f"Also publishing topic [{pubTopic}] with status [{pubPayload}]")
print()
#await aser.write_async(bytes(setRelayCmd + '\r\n', "ascii"))
await aser.write_async(bytes(setRelayCmd + '\r\n', "ascii"))
await mqttClient.publish(pubTopic, payload=pubPayload)
await asyncio.sleep(1)
async def handleTsePower(client, sysSelect, cmd):
rel = RelayState(mapping_toggles[sysSelect], cmd == '1')
await executeAndPublish(client, f'{room}/power/{sysSelect}/status', cmd, rel)
await executeAndPublish(client, f'{room}/power/{sysSelect}/platno/status', cmd, rel)
async def handleTseSencilo(client, cmd):
#relName = tval.split('/')[3]
topicPub = f'{room}/firanki/status'
if cmd == "MOVE_UP":
rel = RelayState(shades_mapping['UP'], True)
rel = RelayState(shades_mapping['gor'], True)
await executeAndPublish(client, topicPub, "MOVING_UP", rel)
elif cmd == "MOVE_DOWN":
rel = RelayState(shades_mapping['DOWN'], True)
rel = RelayState(shades_mapping['dol'], True)
await executeAndPublish(client, topicPub, "MOVING_DOWN", rel)
else:
await executeAndPublish(client, topicPub, "STOPPED", RelayState(shades_mapping['UP'], False))
await executeAndPublish(client, topicPub, "STOPPED", RelayState(shades_mapping['DOWN'], False))
await executeAndPublish(client, topicPub, "STOPPED", RelayState(shades_mapping['gor'], False))
await executeAndPublish(client, topicPub, "STOPPED", RelayState(shades_mapping['dol'], False))
platnoBckgdMoving = False # mucho importante variable prav zares dedoles
@ -142,8 +139,8 @@ async def handleTsePlatno(client, proj, cmdType, cmd):
if platnoBckgdMoving:
if cmd == 'STOP':
pubPld = 'UNKNOWN'
rel1 = RelayState(platno_mapping[proj]['UP'], False)
rel2 = RelayState(platno_mapping[proj]['DOWN'], False)
rel1 = RelayState(platno_mapping[proj]['gor'], False)
rel2 = RelayState(platno_mapping[proj]['dol'], False)
await executeAndPublish(client,pubTop, pubPld, rel1)
await executeAndPublish(client,pubTop, pubPld, rel2)
platnoBckgdMoving = False
@ -154,9 +151,9 @@ async def handleTsePlatno(client, proj, cmdType, cmd):
elif cmdType == 'move':
rel: RelayState
if cmd == 'UP':
rel = RelayState(platno_mapping[proj]['UP'], True)
rel = RelayState(platno_mapping[proj]['gor'], True)
elif cmd == 'DOWN':
rel = RelayState(platno_mapping[proj]['DOWN'], True)
rel = RelayState(platno_mapping[proj]['dol'], True)
else:
return # in case of invalid input skip
platnoBckgdMoving = True
@ -167,10 +164,10 @@ async def handleTsePlatno(client, proj, cmdType, cmd):
# print('received GOTO')
rel: RelayState
if cmd == 'UP':
rel = RelayState(platno_mapping[proj]['UP'], True)
rel = RelayState(platno_mapping[proj]['gor'], True)
intent = 'UP'
elif cmd == 'DOWN':
rel = RelayState(platno_mapping[proj]['DOWN'], True)
rel = RelayState(platno_mapping[proj]['dol'], True)
intent = 'DOWN'
else:
return # in case of invalid input skip
@ -189,7 +186,6 @@ async def task_command2serial(controlClient: aiomqtt.Client):
#async with controlClient.messages as msgs:
async for mesg in controlClient.messages:
#print('oge')
#print(mesg, mesg.topic)
#mesg: aiomqtt.Message
topicVal = mesg.topic.value
@ -197,16 +193,16 @@ async def task_command2serial(controlClient: aiomqtt.Client):
cmnd = mesg.payload.decode()
#print('Received on: ', topicVal, ' with:', cmnd)
#print('bfr')
if mesg.topic.matches(f'{room}/projectors/+/platno/+'):
if mesg.topic.matches(f'{room}/projectors/+/platno/#'):
proj = msgTopic[2] # glavni / stranski
cmdType = msgTopic[4] # move / goto
await handleTsePlatno(controlClient, proj, cmdType, cmnd)
elif mesg.topic.matches(f'{room}/power/+/set'):
elif mesg.topic.matches(f'{room}/power/#'):
systype = msgTopic[2]
await handleTsePower(controlClient, systype, cmnd)
elif mesg.topic.matches(f'{room}/firanki/move'):
elif mesg.topic.matches(f'{room}/firanki/move/#'):
await handleTseSencilo(controlClient, cmnd)
else:
@ -217,9 +213,6 @@ async def task_command2serial(controlClient: aiomqtt.Client):
async def main():
global room
conf = toml.load('./malinaConfig.toml')
room = conf['global']['room']
async with aiomqtt.Client('localhost', 1883) as client:
task_status = asyncio.create_task(task_status2mqtt(client))
task_control = asyncio.create_task(task_command2serial(client))