update the light library
also replaces smbus by smbus2 to allow for cleaner setups
This commit is contained in:
parent
156286a8da
commit
51ff3b7375
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.")
|
||||||
|
|
|
@ -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"}')
|
||||||
|
|
Loading…
Reference in a new issue