Narete stvari da delajo

This commit is contained in:
Miha Frangež 2025-09-12 17:43:50 +02:00
parent 64a10b0512
commit 29b2beca5a
45 changed files with 809 additions and 1600 deletions

View file

@ -1,30 +1,23 @@
#import gpiozero.pins.mock
#from gpiozero import *
#from grove.factory import Factory
#from grove.grove_relay import GroveRelay
MOCK = False
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
import os
# ONLY FOR TESTING ON NON RPI
#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 #TODO get actual projector motor things from config (dont hardcode main/side)
room = ""
use_offset = False
room: str
use_offset = False
""" 0 1 2 3 """
relayMasks = [0b0001, 0b0010, 0b0100, 0b1000] #probably ne rabim
bus = SMBus(1)
i2c_map = {
'main': -1,
'side': -1,
}
relMapping = {
'service_down': 0,
'service_up': 1,
@ -38,36 +31,26 @@ currentState = {
}
async def msgRelayBoard(projSelect, command, state: bool):
#i2cAddr = relayBoardMain if projSelect == 'glavni' else relayBoardSide
#TODO this is not optimal, check for more crap
# 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
# Select the correct relay board
i2c_addr = i2c_map[projSelect]
# Get the relay position for the given command
maskShift = relMapping[command]
# Set the corresponding bit
mask = (1 << maskShift)
if state:
currentState[projSelect] = currentState[projSelect] | mask
else:
currentState[projSelect] = currentState[projSelect] & ~mask
bus.write_byte_data(I2CAddr, 0x10, currentState[projSelect])
print("Command sent")
#print('testirovano jako')
# Write it to the I2C bus (0x10 is the register for relay states)
bus.write_byte_data(i2c_addr, 0x10, currentState[projSelect])
print(projSelect, "{:04b}".format(currentState[projSelect]))
"""
SrvDwn SrvUp OpDwn OpUp
MAIN: 0x42 0001 0010 0100 1000
MAIN: 0x42 0001 0010 0100 1000
SIDE: 0x43 0001 0010 0100 1000
"""
@ -81,45 +64,84 @@ 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)
"""Read commands from MQTT and send them to the relays"""
await controlClient.subscribe(f"{room}/projectors/+/lift/#")
msgs = controlClient.messages
async for mesg in msgs:
mesg: aiomqtt.Message
if mesg.topic.matches(f'{room}/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] #TODO projselect odzadaj indexed (just works tm)
if projSel != 'main' and projSel != 'side':
continue #TODO error hnadling?
command = msgTopicArr[5] #TODO same
await msgRelayBoard(projSel, command, state == '1')
await controlClient.publish(f'{room}/projectors/{projSel}/lift/status', payload="", qos=1, retain=True)
async for mesg in controlClient.messages:
msgTopicArr = mesg.topic.value.split('/')
value = mesg.payload.decode()
if mesg.topic.matches(f'{room}/projectors/+/lift/manual/+'):
command = msgTopicArr[-1]
projSel = msgTopicArr[-4]
if projSel not in ("main", "side") or command not in relMapping.keys() or value not in ("0", "1"):
print("Invalid manual command:", projSel, command, value)
continue
await msgRelayBoard(projSel, command, value == '1')
# Service move
if "service" in command:
# Manual control makes the position unknown, so we clear it
if value == "1":
status = "MOVING"
else:
status = "STOPPED"
await controlClient.publish(f'{room}/projectors/{projSel}/lift/status', payload=status, qos=1, retain=True)
# Normal move
else:
# HACK: if the press is too short it doesn't register, so we sleep for a bit
if value == "1":
await asyncio.sleep(.2)
#print("Pushing \'off\' to other relays to prevent conflicts")
await asyncio.sleep(0.01)
elif mesg.topic.matches(f'{room}/projectors/+/lift/goto'):
projSel = msgTopicArr[-3]
if projSel not in ("main", "side") or value not in ("UP", "DOWN"):
print("Invalid goto command:", projSel, value)
continue
# Clear manual control
await msgRelayBoard(projSel, "service_down", False)
await msgRelayBoard(projSel, "service_up", False)
if value == "UP":
other = "down"
elif value == "DOWN":
other = "up"
await msgRelayBoard(projSel, other, False)
# Click the buttom for a bit and release it, then publish that the lift has moved
await msgRelayBoard(projSel, value.lower(), True)
await asyncio.sleep(1)
await msgRelayBoard(projSel, value.lower(), False)
await controlClient.publish(f'{room}/projectors/{projSel}/lift/status', payload=value, qos=1, retain=True)
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'] #TODO spremen v dict
global i2c_map, room
room = conf["global"]["room"]
config_file = os.getenv('MM_CONFIG_PATH', './malinaConfig.toml')
conf = toml.load(config_file)
room = conf['global']['room']
mqttHost = conf['global']['mqttHost']
mqttPort = conf['global']['mqttPort']
async with aiomqtt.Client('localhost', 1883) as client:
projMotors = conf["projector_motors"]
i2c_map['main'] = projMotors["main"]['i2c_address']
i2c_map['side'] = projMotors["side"]['i2c_address']
async with aiomqtt.Client(mqttHost, mqttPort) as client:
task_control = asyncio.create_task(task_command2relays(client))
await asyncio.gather(task_control)
if __name__ == '__main__':
asyncio.run(main())
asyncio.run(main())