planktoscope/software/planktoscope-backend/src/planktoscope_backend/light.py
2022-11-11 20:21:52 +01:00

249 lines
6.3 KiB
Python

#!/usr/bin/env python
# SPDX-License-Identifier: GPL-3.0-or-later
# Turn on using this command line :
# python3.7 path/to/file/light.py on
# Turn off using this command line :
# python3.7 path/to/file/light.py off
# Logger library compatible with multiprocessing
from loguru import logger
import subprocess # nosec
# Library to send command over I2C for the light module on the fan
import smbus2 as smbus
import enum
DEVICE_ADDRESS = 0x0D
@enum.unique
class Register(enum.IntEnum):
led_select = 0x00
red = 0x01
green = 0x02
blue = 0x03
rgb_effect = 0x04
rgb_speed = 0x05
rgb_color = 0x06
rgb_off = 0x07
@enum.unique
class Effect(enum.IntEnum):
Water = 0
Breathing = 1
Marquee = 2
Rainbow = 3
Colorful = 4
@enum.unique
class EffectColor(enum.IntEnum):
Red = 0
Green = 1
Blue = 2
Yellow = 3
Purple = 4
Cyan = 5
White = 6
def i2c_update():
# Update the I2C Bus in order to really update the LEDs new values
subprocess.Popen("i2cdetect -y 1".split(), stdout=subprocess.PIPE) # nosec
################################################################################
# LEDs functions
################################################################################
def setRGB(R, G, B):
"""Update all LED at the same time"""
try:
with smbus.SMBus(1) as bus:
bus.write_byte_data(DEVICE_ADDRESS, Register.led_select, 0xFF)
bus.write_byte_data(
DEVICE_ADDRESS, Register.led_select, 0xFF
) # 0xFF write to all LEDs, 0x01/0x02/0x03 to choose first, second or third LED
bus.write_byte_data(DEVICE_ADDRESS, Register.red, R & 0xFF)
bus.write_byte_data(DEVICE_ADDRESS, Register.green, G & 0xFF)
bus.write_byte_data(DEVICE_ADDRESS, Register.blue, B & 0xFF)
i2c_update()
except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}")
def setRGBOff():
"""Turn off the RGB LED"""
try:
with smbus.SMBus(1) as bus:
bus.write_byte_data(DEVICE_ADDRESS, Register.rgb_off, 0x00)
i2c_update()
except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}")
def setRGBEffect(bus, effect):
"""Choose an effect, type Effect
Effect.Water: Rotating color between LEDs (color has an effect)
Effect.Breathing: Breathing color effect
Effect.Marquee: Flashing color transition between all LEDs
Effect.Rainbow: Smooth color transition between all LEDs
Effect.Colorful: Colorful transition separately between all LEDs
"""
if effect in Effect:
try:
bus.write_byte_data(DEVICE_ADDRESS, Register.rgb_effect, effect & 0xFF)
except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}")
def setRGBSpeed(bus, speed):
"""Set the effect speed, 1-3, 3 being the fastest speed"""
if 1 <= speed <= 3:
try:
bus.write_byte_data(DEVICE_ADDRESS, Register.rgb_speed, speed & 0xFF)
except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}")
def setRGBColor(bus, color):
"""Set the color of the water light and breathing light effect, of type EffectColor
EffectColor.Red, EffectColor.Green (default), EffectColor.Blue, EffectColor.Yellow,
EffectColor.Purple, EffectColor.Cyan, EffectColor.White
"""
if color in EffectColor:
try:
bus.write_byte_data(DEVICE_ADDRESS, Register.rgb_color, color & 0xFF)
except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}")
def ready():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.Blue)
setRGBSpeed(bus, 1)
setRGBEffect(bus, Effect.Breathing)
i2c_update()
def error():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.Red)
setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water)
i2c_update()
def interrupted():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.Yellow)
setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water)
i2c_update()
def pumping():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.Blue)
setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water)
i2c_update()
def focusing():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.Purple)
setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water)
i2c_update()
def imaging():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.White)
setRGBSpeed(bus, 1)
setRGBEffect(bus, Effect.Breathing)
i2c_update()
def segmenting():
with smbus.SMBus(1) as bus:
setRGBColor(bus, EffectColor.Purple)
setRGBSpeed(bus, 1)
setRGBEffect(bus, Effect.Breathing)
i2c_update()
# This is called if this script is launched directly
if __name__ == "__main__":
# TODO This should be a test suite for this library
import time
print("ready")
ready()
time.sleep(5)
print("error")
error()
time.sleep(5)
print("pumping")
pumping()
time.sleep(5)
print("focusing")
focusing()
time.sleep(5)
print("imaging")
imaging()
time.sleep(5)
print("segmenting")
segmenting()
time.sleep(5)
print("with i2c_update now!")
print("ready")
ready()
i2c_update()
time.sleep(5)
print("error")
error()
i2c_update()
time.sleep(5)
print("pumping")
pumping()
i2c_update()
time.sleep(5)
print("focusing")
focusing()
i2c_update()
time.sleep(5)
print("imaging")
imaging()
i2c_update()
time.sleep(5)
print("segmenting")
segmenting()
i2c_update()
time.sleep(5)
with smbus.SMBus(1) as bus:
setRGBSpeed(bus, 3)
for effect in Effect:
print(effect.name)
with smbus.SMBus(1) as bus:
setRGBEffect(bus, effect)
time.sleep(2)
with smbus.SMBus(1) as bus:
setRGBEffect(bus, Effect.Breathing)
for color in EffectColor:
print(color.name)
with smbus.SMBus(1) as bus:
setRGBColor(bus, color)
time.sleep(2)
setRGBOff()