remove "test_image" definition
i removed the test image function from the get_data (because we don't need the test images longer) and capture image does not work.
Error
url is 'N/A'
log info:
2025-03-06 19:44:52,216 - bambu-analysis - INFO - API call: lambda with params: 200, 60, 60, 100, use_test_image: False, test_image_name:
2025-03-06 19:44:52,218 - bambu-analysis - INFO - Publishing request to bambu_a1_mini/request/0309CA471800852
2025-03-06 19:44:52,218 - bambu-analysis - INFO - No valid image data received, using default test image
2025-03-06 19:44:52,218 - bambu-analysis - ERROR - Error in lambda: name 'get_test_image' is not defined
Could you please check again? Thanks.
are we removing test images altogether? If so I'll remove the use_test_image and everything related to using test images.
Yes, we will not have any "test" part.
@SissiFeng
Could you please explain the changes to the rpi_on_message logic please?
Previously we followed a similar pattern to bambu_on_message where we just update the global latest_data. For images we just updated the image URL when the camera sent one back, but the logic has changed quite a bit.
We seem to be updating the same fields from both the Bambu MQTT and RPI MQTT (nozzle temp, bed temp, etc). And then we spawn a thread for image capture which I'm not sure where it comes from. Is there a thread where I can get caught up on changes? Thanks.
def bambu_on_message(client, userdata, message):
global latest_data
logger.info("Received message")
try:
data = json.loads(message.payload)
latest_data["bed_temperature"] = data.get("bed_temperature", "N/A")
latest_data["nozzle_temperature"] = data.get("nozzle_temperature", "N/A")
latest_data["status"] = data.get("status", "N/A")
latest_data["update_time"] = time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime()
)
latest_data["image_url"] = data.get("image_url", "N/A")
except Exception as e:
logger.error(f"Error parsing MQTT message: {e}")
def rpi_on_message(client, userdata, msg):
global latest_data
try:
payload = msg.payload.decode("utf-8")
logger.info(f"Received message from RPI: {payload}")
data = json.loads(payload)
status = data.get("status", "Unknown")
latest_data["status"] = status
latest_data["update_time"] = data.get(
"update_time", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
)
if "nozzle_temperature" in data:
latest_data["nozzle_temperature"] = data["nozzle_temperature"]
if "bed_temperature" in data:
latest_data["bed_temperature"] = data["bed_temperature"]
if "error" in data:
logger.error(f"Error from RPI: {data['error']}")
if status == "Ready":
latest_data["progress"] = 0
latest_data["message"] = "Printer ready"
elif status == "Processing":
latest_data["progress"] = 25
latest_data["message"] = "Processing G-code..."
except Exception as e:
logger.error(f"Error processing message from RPI: {e}")
try:
result = json.loads(payload)
if "status" in result:
status = result["status"]
latest_data["status"] = status
if (
"command" in result
and result["command"] == "capture_image"
and result.get("auto_triggered", False)
):
logger.info("receive capture command")
threading.Thread(
target=handle_auto_capture, args=(result,), daemon=True
).start()
except json.JSONDecodeError:
logger.error(f"Invalid JSON in message: {payload}")
My changes today introduce the following:
Overlapping data fields:
Indeed, both rpi_on_message and bambu_on_message are now updating the same fields (nozzle temperature, hotbed temperature, etc.)
This is because we now have two data sources: the data directly from the Bambu printer and the data forwarded by the Raspberry Pi
Automatic photo function:
Added handling of the capture_image command, when this command is received, a new thread is started to execute handle_auto_capture
This feature allows to automatically take a picture after the print is done and record the print result.
Status Handling:
Added handling of more printer status, including progress bar updates and message displays
There are several possible solutions to the problem of overlapping data:
- Data source prioritization:
A prioritization system can be set up so that, for example, if two sources both provide the same data, one source is used first
For example, it is possible to prioritize the use of data provided directly by Bambu, and only use Raspberry Pi data when Bambu data is not available - Data timestamp:
It is possible to add a timestamp to each piece of data and only use the most recent data
This ensures that the UI always shows the latest information, regardless of the source - Data source separation:
The responsibilities of the two data sources can be clearly separated
For example, Bambu MQTT only handles printer status and temperature, while RPI MQTT only handles images and custom commands.
Which one do you find more convenient?
Regarding the automatic photo thread:
The handle_auto_capture function is a new feature we added to handle automatic photo requests. Its workflow is:
Receive the capture_image command (usually after printing is complete)
A new thread is started to execute the handle_auto_capture function
This function logs the photo request information and may trigger the actual photo operation
This thread is asynchronous so that it does not block the main MQTT callback function, allowing the system to continue processing other messages.
Gotcha, thanks for that.
- Regarding the overlapping data, what's the motivation for having an RPI forward the data in addition to the data from the A1 itself? Although it's cleanest to keep the data sources separated, I think mixing is fine.
- For the automatic photo, where I was confused was the extra fields like
last_capture_jobandlast_capture_time. Do we expect to show those as sort of descriptors of the current image? If so I can add this retroactively to the manual image capture. - Also, as it stands the Gradio image is not being updated by the
handle_auto_capture, is this because this part is still in progress? - Thoughts on simplifying this by just triggering the capture image button manually https://github.com/gradio-app/gradio/issues/7713#issuecomment-2002741160
Thanks for helping us along with this hf part.
- A very important task for Raspberry Pi right now is to modify the gcode based on the new print parameters passed in by HF and send it to Bambu, acting as a middle layer.
- The last_capture_job and last_capture_time fields are meant to form a database record along with the image as well as the parameters. Maybe consider displaying relevant metadata next to the image?
- handle_auto_capture function is not fully implemented yet. This is because taking a picture requires the nozzle head to move with the camera to the center of the pattern for this print to complete the picture. Yesterday we were trying to get Bambu to move into place on its own at the end of the print, but it hasn't been implemented correctly yet.
I have two ideas for a solution: - create a core capture_image function that handles the actual picture taking operation. This function is called for both manual and automatic photo taking, just passed in different parameters (e.g. location information).
- after clicking the manual photo button, trigger a gcode command to move the camera to the right position before performing the photo taking.
Which option do you think is easier to implement on your end? Or do you have any other better suggestion?
Can we confidently say that there is a single spot we always want to take photos from? If so, then the second option is best.
Either way I envision a single capture_image routine. Within the current capture_image function we can move the camera and then capture.
We decided only use the manual capture function. After manually clicking, the camera will trigger a gcode command and move to a preset position and take the photo.
That sounds great.
BTW the camera might be down potentially due to it timing out. Reported here https://github.com/AccelerationConsortium/ac-training-lab/issues/159#issuecomment-2705046483