update the light library

also replaces smbus by smbus2 to allow for cleaner setups
This commit is contained in:
Romain Bazile 2020-11-30 00:17:30 +01:00
parent 156286a8da
commit 51ff3b7375
5 changed files with 22 additions and 67 deletions

View file

@ -327,8 +327,7 @@ class ImagerProcess(multiprocessing.Process):
# Publish the status "Interrupted" to via MQTT to Node-RED # Publish the status "Interrupted" to via MQTT to Node-RED
self.imager_client.client.publish("status/imager", '{"status":"Interrupted"}') self.imager_client.client.publish("status/imager", '{"status":"Interrupted"}')
# Set the LEDs as Green planktoscope.light.interrupted()
planktoscope.light.setRGB(0, 255, 0)
# Change state to Stop # Change state to Stop
self.__imager.change(planktoscope.imager_state_machine.Stop) self.__imager.change(planktoscope.imager_state_machine.Stop)
@ -542,6 +541,9 @@ class ImagerProcess(multiprocessing.Process):
def __pump_message(self): def __pump_message(self):
"""Sends a message to the pump process""" """Sends a message to the pump process"""
planktoscope.light.pumping()
# Pump during a given volume # Pump during a given volume
self.imager_client.client.publish( self.imager_client.client.publish(
"actuator/pump", "actuator/pump",
@ -595,22 +597,15 @@ class ImagerProcess(multiprocessing.Process):
f"The integrity file already exists in this export path {self.__export_path}" f"The integrity file already exists in this export path {self.__export_path}"
) )
# Set the LEDs as Blue
planktoscope.light.setRGB(0, 0, 255)
self.__pump_message() self.__pump_message()
# FIXME We should probably update the global metadata here with the current datetime/position/etc... # FIXME We should probably update the global metadata here with the current datetime/position/etc...
# Set the LEDs as Green
planktoscope.light.setRGB(0, 255, 0)
# Change state towards Waiting for pump # Change state towards Waiting for pump
self.__imager.change(planktoscope.imager_state_machine.Waiting) self.__imager.change(planktoscope.imager_state_machine.Waiting)
def __state_capture(self): def __state_capture(self):
# Set the LEDs as Cyan planktoscope.light.imaging()
planktoscope.light.setRGB(0, 255, 255)
filename = f"{datetime.datetime.now().strftime('%H_%M_%S_%f')}.jpg" filename = f"{datetime.datetime.now().strftime('%H_%M_%S_%f')}.jpg"
@ -638,13 +633,9 @@ class ImagerProcess(multiprocessing.Process):
self.__img_done = 0 self.__img_done = 0
# Change state towards stop # Change state towards stop
self.__imager.change(planktoscope.imager_state_machine.Stop) self.__imager.change(planktoscope.imager_state_machine.Stop)
# Set the LEDs as Green planktoscope.light.error()
planktoscope.light.setRGB(0, 255, 255)
return return
# Set the LEDs as Green
planktoscope.light.setRGB(0, 255, 0)
# Add the checksum of the captured image to the integrity file # Add the checksum of the captured image to the integrity file
try: try:
planktoscope.integrity.append_to_integrity_file(filename_path) planktoscope.integrity.append_to_integrity_file(filename_path)
@ -672,13 +663,10 @@ class ImagerProcess(multiprocessing.Process):
# Change state towards done # Change state towards done
self.__imager.change(planktoscope.imager_state_machine.Stop) self.__imager.change(planktoscope.imager_state_machine.Stop)
# Set the LEDs as Green planktoscope.light.ready()
planktoscope.light.setRGB(0, 255, 255)
return return
else: else:
# We have not reached the final stage, let's keep imaging # We have not reached the final stage, let's keep imaging
# Set the LEDs as Blue
planktoscope.light.setRGB(0, 0, 255)
# subscribe to status/pump # subscribe to status/pump
self.imager_client.client.subscribe("status/pump") self.imager_client.client.subscribe("status/pump")
@ -688,9 +676,6 @@ class ImagerProcess(multiprocessing.Process):
self.__pump_message() self.__pump_message()
# Set the LEDs as Green
planktoscope.light.setRGB(0, 255, 0)
# Change state towards Waiting for pump # Change state towards Waiting for pump
self.__imager.change(planktoscope.imager_state_machine.Waiting) self.__imager.change(planktoscope.imager_state_machine.Waiting)

View file

@ -8,13 +8,14 @@
# Logger library compatible with multiprocessing # Logger library compatible with multiprocessing
from loguru import logger from loguru import logger
import subprocess # nosec
# Library to send command over I2C for the light module on the fan # Library to send command over I2C for the light module on the fan
try: try:
import smbus2 as smbus import smbus2 as smbus
except ModuleNotFoundError: except ModuleNotFoundError: # We need this to install the library on machine that do not have the module yet
subprocess.Popen("pip3 install smbus2".split(), stdout=subprocess.PIPE) # nosec import subprocess # nosec
subprocess.run("pip3 install smbus2".split()) # nosec
import smbus2 as smbus import smbus2 as smbus
import enum import enum
@ -57,11 +58,6 @@ class EffectColor(enum.IntEnum):
################################################################################ ################################################################################
# LEDs functions # LEDs functions
################################################################################ ################################################################################
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
def setRGB(R, G, B): def setRGB(R, G, B):
"""Update all LED at the same time""" """Update all LED at the same time"""
try: try:
@ -72,7 +68,6 @@ def setRGB(R, G, B):
bus.write_byte_data(DEVICE_ADDRESS, Register.red, R & 0xFF) 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.green, G & 0xFF)
bus.write_byte_data(DEVICE_ADDRESS, Register.blue, B & 0xFF) bus.write_byte_data(DEVICE_ADDRESS, Register.blue, B & 0xFF)
# i2c_update()
except Exception as e: except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}") logger.exception(f"An Exception has occured in the light library at {e}")
@ -82,7 +77,6 @@ def setRGBOff():
try: try:
with smbus.SMBus(1) as bus: with smbus.SMBus(1) as bus:
bus.write_byte_data(DEVICE_ADDRESS, Register.rgb_off, 0x00) bus.write_byte_data(DEVICE_ADDRESS, Register.rgb_off, 0x00)
# i2c_update()
except Exception as e: except Exception as e:
logger.exception(f"An Exception has occured in the light library at {e}") logger.exception(f"An Exception has occured in the light library at {e}")
@ -130,7 +124,6 @@ def ready():
setRGBColor(bus, EffectColor.Green) setRGBColor(bus, EffectColor.Green)
setRGBSpeed(bus, 1) setRGBSpeed(bus, 1)
setRGBEffect(bus, Effect.Breathing) setRGBEffect(bus, Effect.Breathing)
# i2c_update()
def error(): def error():
@ -138,7 +131,6 @@ def error():
setRGBColor(bus, EffectColor.Red) setRGBColor(bus, EffectColor.Red)
setRGBSpeed(bus, 3) setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water) setRGBEffect(bus, Effect.Water)
# i2c_update()
def interrupted(): def interrupted():
@ -146,7 +138,6 @@ def interrupted():
setRGBColor(bus, EffectColor.Yellow) setRGBColor(bus, EffectColor.Yellow)
setRGBSpeed(bus, 3) setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water) setRGBEffect(bus, Effect.Water)
# i2c_update()
def pumping(): def pumping():
@ -154,7 +145,6 @@ def pumping():
setRGBColor(bus, EffectColor.Blue) setRGBColor(bus, EffectColor.Blue)
setRGBSpeed(bus, 3) setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water) setRGBEffect(bus, Effect.Water)
# i2c_update()
def focusing(): def focusing():
@ -162,7 +152,6 @@ def focusing():
setRGBColor(bus, EffectColor.Purple) setRGBColor(bus, EffectColor.Purple)
setRGBSpeed(bus, 3) setRGBSpeed(bus, 3)
setRGBEffect(bus, Effect.Water) setRGBEffect(bus, Effect.Water)
# i2c_update()
def imaging(): def imaging():
@ -170,7 +159,6 @@ def imaging():
setRGBColor(bus, EffectColor.White) setRGBColor(bus, EffectColor.White)
setRGBSpeed(bus, 1) setRGBSpeed(bus, 1)
setRGBEffect(bus, Effect.Breathing) setRGBEffect(bus, Effect.Breathing)
# i2c_update()
def segmenting(): def segmenting():
@ -178,7 +166,6 @@ def segmenting():
setRGBColor(bus, EffectColor.Purple) setRGBColor(bus, EffectColor.Purple)
setRGBSpeed(bus, 1) setRGBSpeed(bus, 1)
setRGBEffect(bus, Effect.Breathing) setRGBEffect(bus, Effect.Breathing)
# i2c_update()
# This is called if this script is launched directly # This is called if this script is launched directly

View file

@ -53,7 +53,6 @@
# We can use collections.deque https://docs.python.org/3/library/collections.html#collections.deque # We can use collections.deque https://docs.python.org/3/library/collections.html#collections.deque
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
import json import json
import planktoscope.light
# Logger library compatible with multiprocessing # Logger library compatible with multiprocessing
from loguru import logger from loguru import logger
@ -117,8 +116,6 @@ class MQTT_Client:
) )
# When connected, run subscribe() # When connected, run subscribe()
self.client.subscribe(self.topic) self.client.subscribe(self.topic)
# Turn green the light module
planktoscope.light.setRGB(0, 255, 0)
@logger.catch @logger.catch
# Run this function in order to subscribe to all the topics begining by actuator # Run this function in order to subscribe to all the topics begining by actuator

View file

@ -60,7 +60,6 @@ class SegmenterProcess(multiprocessing.Process):
if not os.path.exists(self.__objects_base_path): if not os.path.exists(self.__objects_base_path):
# create the path! # create the path!
os.makedirs(self.__objects_base_path) os.makedirs(self.__objects_base_path)
# Morphocut's pipeline will be created at runtime otherwise shit ensues
logger.success("planktoscope.segmenter is initialised and ready to go!") logger.success("planktoscope.segmenter is initialised and ready to go!")
@ -82,8 +81,7 @@ class SegmenterProcess(multiprocessing.Process):
lambda p: os.path.splitext(os.path.basename(p))[0], abs_path lambda p: os.path.splitext(os.path.basename(p))[0], abs_path
) )
# Set the LEDs as Green morphocut.Call(planktoscope.light.segmenting())
morphocut.Call(planktoscope.light.setRGB, 0, 255, 0)
# Read image # Read image
img = morphocut.image.ImageReader(abs_path) img = morphocut.image.ImageReader(abs_path)
@ -143,9 +141,6 @@ class SegmenterProcess(multiprocessing.Process):
mask, img_gray, min_area=1000, padding=10, warn_empty=name mask, img_gray, min_area=1000, padding=10, warn_empty=name
) )
# Set the LEDs as Purple
morphocut.Call(planktoscope.light.setRGB, 255, 0, 255)
# For an object, extract a vignette/ROI from the image # For an object, extract a vignette/ROI from the image
roi_orig = morphocut.image.ExtractROI(img, regionprops, bg_color=255) roi_orig = morphocut.image.ExtractROI(img, regionprops, bg_color=255)
@ -212,8 +207,6 @@ class SegmenterProcess(multiprocessing.Process):
id_json, id_json,
) )
# Set the LEDs as Green
morphocut.Call(planktoscope.light.setRGB, 0, 255, 0)
logger.info("Morphocut's Pipeline has been created") logger.info("Morphocut's Pipeline has been created")
@logger.catch @logger.catch
@ -287,6 +280,7 @@ class SegmenterProcess(multiprocessing.Process):
try: try:
self.__pipe.run() self.__pipe.run()
except Exception as e: except Exception as e:
planktoscope.light.error()
logger.exception(f"There was an error in the pipeline {e}") logger.exception(f"There was an error in the pipeline {e}")
logger.info(f"Pipeline has been run for {path}") logger.info(f"Pipeline has been run for {path}")
else: else:
@ -299,14 +293,7 @@ class SegmenterProcess(multiprocessing.Process):
self.segmenter_client.client.publish( self.segmenter_client.client.publish(
"status/segmenter", '{"status":"Done"}' "status/segmenter", '{"status":"Done"}'
) )
planktoscope.light.ready()
# Set the LEDs as White
planktoscope.light.setRGB(255, 255, 255)
# cmd = os.popen("rm -rf /home/pi/PlanktonScope/tmp/*.jpg")
# Set the LEDs as Green
planktoscope.light.setRGB(0, 255, 0)
elif action == "stop": elif action == "stop":
logger.info("The segmentation has been interrupted.") logger.info("The segmentation has been interrupted.")
@ -315,6 +302,7 @@ class SegmenterProcess(multiprocessing.Process):
self.segmenter_client.client.publish( self.segmenter_client.client.publish(
"status/segmenter", '{"status":"Interrupted"}' "status/segmenter", '{"status":"Interrupted"}'
) )
planktoscope.light.interrupted()
elif action == "update_config": elif action == "update_config":
logger.error("We can't update the configuration while we are segmenting.") logger.error("We can't update the configuration while we are segmenting.")

View file

@ -269,13 +269,11 @@ class StepperProcess(multiprocessing.Process):
"status/pump", '{"status":"Interrupted"}' "status/pump", '{"status":"Interrupted"}'
) )
# Set the LEDs as Green planktoscope.light.ready()
planktoscope.light.setRGB(0, 255, 0)
elif last_message["action"] == "move": elif last_message["action"] == "move":
logger.debug("We have received a move pump command") logger.debug("We have received a move pump command")
# Set the LEDs as Blue planktoscope.light.pumping()
planktoscope.light.setRGB(0, 0, 255)
if ( if (
"direction" not in last_message "direction" not in last_message
@ -315,13 +313,11 @@ class StepperProcess(multiprocessing.Process):
"status/focus", '{"status":"Interrupted"}' "status/focus", '{"status":"Interrupted"}'
) )
# Set the LEDs as Green planktoscope.light.ready()
planktoscope.light.setRGB(0, 255, 0)
elif last_message["action"] == "move": elif last_message["action"] == "move":
logger.debug("We have received a move focus command") logger.debug("We have received a move focus command")
# Set the LEDs as Yellow planktoscope.light.focusing()
planktoscope.light.setRGB(255, 255, 0)
if "direction" not in last_message or "distance" not in last_message: if "direction" not in last_message or "distance" not in last_message:
logger.error( logger.error(
@ -354,7 +350,6 @@ class StepperProcess(multiprocessing.Process):
# If the command is "pump" # If the command is "pump"
if command == "pump": if command == "pump":
self.__message_pump(last_message) self.__message_pump(last_message)
# If the command is "focus" # If the command is "focus"
elif command == "focus": elif command == "focus":
self.__message_focus(last_message) self.__message_focus(last_message)
@ -507,15 +502,18 @@ class StepperProcess(multiprocessing.Process):
# check if a new message has been received # check if a new message has been received
self.treat_command() self.treat_command()
if self.pump_stepper.move(): if self.pump_stepper.move():
planktoscope.light.ready()
self.actuator_client.client.publish( self.actuator_client.client.publish(
"status/pump", "status/pump",
'{"status":"Done"}', '{"status":"Done"}',
) )
if self.focus_stepper.move(): if self.focus_stepper.move():
planktoscope.light.ready()
self.actuator_client.client.publish( self.actuator_client.client.publish(
"status/focus", "status/focus",
'{"status":"Done"}', '{"status":"Done"}',
) )
time.sleep(0.0001)
logger.info("Shutting down the stepper process") logger.info("Shutting down the stepper process")
self.actuator_client.client.publish("status/pump", '{"status":"Dead"}') self.actuator_client.client.publish("status/pump", '{"status":"Dead"}')
self.actuator_client.client.publish("status/focus", '{"status":"Dead"}') self.actuator_client.client.publish("status/focus", '{"status":"Dead"}')