From 51ff3b73759e6d38ea6dc33f8b2cb6be28a9dd7b Mon Sep 17 00:00:00 2001 From: Romain Bazile Date: Mon, 30 Nov 2020 00:17:30 +0100 Subject: [PATCH] update the light library also replaces smbus by smbus2 to allow for cleaner setups --- scripts/planktoscope/imager.py | 29 +++++++---------------------- scripts/planktoscope/light.py | 21 ++++----------------- scripts/planktoscope/mqtt.py | 3 --- scripts/planktoscope/segmenter.py | 20 ++++---------------- scripts/planktoscope/stepper.py | 16 +++++++--------- 5 files changed, 22 insertions(+), 67 deletions(-) diff --git a/scripts/planktoscope/imager.py b/scripts/planktoscope/imager.py index 06e67ab..36b8edc 100644 --- a/scripts/planktoscope/imager.py +++ b/scripts/planktoscope/imager.py @@ -327,8 +327,7 @@ class ImagerProcess(multiprocessing.Process): # Publish the status "Interrupted" to via MQTT to Node-RED self.imager_client.client.publish("status/imager", '{"status":"Interrupted"}') - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) + planktoscope.light.interrupted() # Change state to Stop self.__imager.change(planktoscope.imager_state_machine.Stop) @@ -542,6 +541,9 @@ class ImagerProcess(multiprocessing.Process): def __pump_message(self): """Sends a message to the pump process""" + + planktoscope.light.pumping() + # Pump during a given volume self.imager_client.client.publish( "actuator/pump", @@ -595,22 +597,15 @@ class ImagerProcess(multiprocessing.Process): 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() # 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 self.__imager.change(planktoscope.imager_state_machine.Waiting) def __state_capture(self): - # Set the LEDs as Cyan - planktoscope.light.setRGB(0, 255, 255) + planktoscope.light.imaging() filename = f"{datetime.datetime.now().strftime('%H_%M_%S_%f')}.jpg" @@ -638,13 +633,9 @@ class ImagerProcess(multiprocessing.Process): self.__img_done = 0 # Change state towards stop self.__imager.change(planktoscope.imager_state_machine.Stop) - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 255) + planktoscope.light.error() return - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) - # Add the checksum of the captured image to the integrity file try: planktoscope.integrity.append_to_integrity_file(filename_path) @@ -672,13 +663,10 @@ class ImagerProcess(multiprocessing.Process): # Change state towards done self.__imager.change(planktoscope.imager_state_machine.Stop) - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 255) + planktoscope.light.ready() return else: # 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 self.imager_client.client.subscribe("status/pump") @@ -688,9 +676,6 @@ class ImagerProcess(multiprocessing.Process): self.__pump_message() - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) - # Change state towards Waiting for pump self.__imager.change(planktoscope.imager_state_machine.Waiting) diff --git a/scripts/planktoscope/light.py b/scripts/planktoscope/light.py index 9432b79..a49a62a 100644 --- a/scripts/planktoscope/light.py +++ b/scripts/planktoscope/light.py @@ -8,13 +8,14 @@ # 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 try: import smbus2 as smbus -except ModuleNotFoundError: - subprocess.Popen("pip3 install smbus2".split(), stdout=subprocess.PIPE) # nosec +except ModuleNotFoundError: # We need this to install the library on machine that do not have the module yet + import subprocess # nosec + + subprocess.run("pip3 install smbus2".split()) # nosec import smbus2 as smbus import enum @@ -57,11 +58,6 @@ class EffectColor(enum.IntEnum): ################################################################################ # 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): """Update all LED at the same time""" 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.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}") @@ -82,7 +77,6 @@ def setRGBOff(): 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}") @@ -130,7 +124,6 @@ def ready(): setRGBColor(bus, EffectColor.Green) setRGBSpeed(bus, 1) setRGBEffect(bus, Effect.Breathing) - # i2c_update() def error(): @@ -138,7 +131,6 @@ def error(): setRGBColor(bus, EffectColor.Red) setRGBSpeed(bus, 3) setRGBEffect(bus, Effect.Water) - # i2c_update() def interrupted(): @@ -146,7 +138,6 @@ def interrupted(): setRGBColor(bus, EffectColor.Yellow) setRGBSpeed(bus, 3) setRGBEffect(bus, Effect.Water) - # i2c_update() def pumping(): @@ -154,7 +145,6 @@ def pumping(): setRGBColor(bus, EffectColor.Blue) setRGBSpeed(bus, 3) setRGBEffect(bus, Effect.Water) - # i2c_update() def focusing(): @@ -162,7 +152,6 @@ def focusing(): setRGBColor(bus, EffectColor.Purple) setRGBSpeed(bus, 3) setRGBEffect(bus, Effect.Water) - # i2c_update() def imaging(): @@ -170,7 +159,6 @@ def imaging(): setRGBColor(bus, EffectColor.White) setRGBSpeed(bus, 1) setRGBEffect(bus, Effect.Breathing) - # i2c_update() def segmenting(): @@ -178,7 +166,6 @@ def segmenting(): setRGBColor(bus, EffectColor.Purple) setRGBSpeed(bus, 1) setRGBEffect(bus, Effect.Breathing) - # i2c_update() # This is called if this script is launched directly diff --git a/scripts/planktoscope/mqtt.py b/scripts/planktoscope/mqtt.py index becb7b0..07b6645 100644 --- a/scripts/planktoscope/mqtt.py +++ b/scripts/planktoscope/mqtt.py @@ -53,7 +53,6 @@ # We can use collections.deque https://docs.python.org/3/library/collections.html#collections.deque import paho.mqtt.client as mqtt import json -import planktoscope.light # Logger library compatible with multiprocessing from loguru import logger @@ -117,8 +116,6 @@ class MQTT_Client: ) # When connected, run subscribe() self.client.subscribe(self.topic) - # Turn green the light module - planktoscope.light.setRGB(0, 255, 0) @logger.catch # Run this function in order to subscribe to all the topics begining by actuator diff --git a/scripts/planktoscope/segmenter.py b/scripts/planktoscope/segmenter.py index 1bcac80..217dc1d 100644 --- a/scripts/planktoscope/segmenter.py +++ b/scripts/planktoscope/segmenter.py @@ -60,7 +60,6 @@ class SegmenterProcess(multiprocessing.Process): if not os.path.exists(self.__objects_base_path): # create the 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!") @@ -82,8 +81,7 @@ class SegmenterProcess(multiprocessing.Process): lambda p: os.path.splitext(os.path.basename(p))[0], abs_path ) - # Set the LEDs as Green - morphocut.Call(planktoscope.light.setRGB, 0, 255, 0) + morphocut.Call(planktoscope.light.segmenting()) # Read image 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 ) - # Set the LEDs as Purple - morphocut.Call(planktoscope.light.setRGB, 255, 0, 255) - # For an object, extract a vignette/ROI from the image roi_orig = morphocut.image.ExtractROI(img, regionprops, bg_color=255) @@ -212,8 +207,6 @@ class SegmenterProcess(multiprocessing.Process): id_json, ) - # Set the LEDs as Green - morphocut.Call(planktoscope.light.setRGB, 0, 255, 0) logger.info("Morphocut's Pipeline has been created") @logger.catch @@ -287,6 +280,7 @@ class SegmenterProcess(multiprocessing.Process): try: self.__pipe.run() except Exception as e: + planktoscope.light.error() logger.exception(f"There was an error in the pipeline {e}") logger.info(f"Pipeline has been run for {path}") else: @@ -299,14 +293,7 @@ class SegmenterProcess(multiprocessing.Process): self.segmenter_client.client.publish( "status/segmenter", '{"status":"Done"}' ) - - # 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) + planktoscope.light.ready() elif action == "stop": logger.info("The segmentation has been interrupted.") @@ -315,6 +302,7 @@ class SegmenterProcess(multiprocessing.Process): self.segmenter_client.client.publish( "status/segmenter", '{"status":"Interrupted"}' ) + planktoscope.light.interrupted() elif action == "update_config": logger.error("We can't update the configuration while we are segmenting.") diff --git a/scripts/planktoscope/stepper.py b/scripts/planktoscope/stepper.py index fa7561e..85f8c82 100644 --- a/scripts/planktoscope/stepper.py +++ b/scripts/planktoscope/stepper.py @@ -269,13 +269,11 @@ class StepperProcess(multiprocessing.Process): "status/pump", '{"status":"Interrupted"}' ) - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) + planktoscope.light.ready() elif last_message["action"] == "move": logger.debug("We have received a move pump command") - # Set the LEDs as Blue - planktoscope.light.setRGB(0, 0, 255) + planktoscope.light.pumping() if ( "direction" not in last_message @@ -315,13 +313,11 @@ class StepperProcess(multiprocessing.Process): "status/focus", '{"status":"Interrupted"}' ) - # Set the LEDs as Green - planktoscope.light.setRGB(0, 255, 0) + planktoscope.light.ready() elif last_message["action"] == "move": logger.debug("We have received a move focus command") - # Set the LEDs as Yellow - planktoscope.light.setRGB(255, 255, 0) + planktoscope.light.focusing() if "direction" not in last_message or "distance" not in last_message: logger.error( @@ -354,7 +350,6 @@ class StepperProcess(multiprocessing.Process): # If the command is "pump" if command == "pump": self.__message_pump(last_message) - # If the command is "focus" elif command == "focus": self.__message_focus(last_message) @@ -507,15 +502,18 @@ class StepperProcess(multiprocessing.Process): # check if a new message has been received self.treat_command() if self.pump_stepper.move(): + planktoscope.light.ready() self.actuator_client.client.publish( "status/pump", '{"status":"Done"}', ) if self.focus_stepper.move(): + planktoscope.light.ready() self.actuator_client.client.publish( "status/focus", '{"status":"Done"}', ) + time.sleep(0.0001) logger.info("Shutting down the stepper process") self.actuator_client.client.publish("status/pump", '{"status":"Dead"}') self.actuator_client.client.publish("status/focus", '{"status":"Dead"}')