Skip to content

Document OT-2 / Hugging Face / MongoDB data flow for LCM demo#553

Draft
Copilot wants to merge 1 commit into
mainfrom
copilot/winter-2026-mse403h1-liquid-colour-matching-demo
Draft

Document OT-2 / Hugging Face / MongoDB data flow for LCM demo#553
Copilot wants to merge 1 commit into
mainfrom
copilot/winter-2026-mse403h1-liquid-colour-matching-demo

Conversation

Copilot AI commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Responds to the request in issue #552 to clarify how the OT-2, Hugging Face Space, MongoDB, HiveMQ broker, and Pico W colour sensor interact for the Winter 2026 MSE403H1 liquid colour-matching demo, plus the role of the NOKIA router.

No code changes. A plain-language, file-linked explanation (no assumed familiarity with MongoDB, Prefect, Hugging Face, MQTT, or OT-2 workflows) was posted as a reply to the comment (tagging @kbuchel), per repo convention of keeping documentation in comment replies rather than new files. After the firewall was opened, the answer was verified and completed against the actual HF Space, AccelerationConsortium/OT-2-LCM (a Gradio app.py, not the older light-mixing NeoPixel demo).

Findings posted

  • Component roles: HF Space (OT-2-LCM, Gradio) = orchestrator (state + hardware + livestream), HiveMQ = MQTT bus, MongoDB (LCM-OT-2-SLD) = well/quota/result/maintenance store, OT-2 + Pico W = hardware that only talk to HiveMQ.
  • Per-experiment flow (verified against app.py): student submit → HF quota/well lookup in MongoDB → mix command to command/ot2/{serial}/pipette → OT-2 dispenses + positions sensor, reports in_placeHF publishes the read command to command/picow/{id}/as7341/read → Pico W publishes AS7341 data to color-mixing/picow/{id}/as7341 → HF tells OT-2 to return the sensor (sensor_status: read) → OT-2 reports charging → HF persists result via save_result and the well is marked used. (HF, not the OT-2, triggers the sensor read; the corresponding lines are commented out in OT2mqtt.py.)
  • Credential / env-var map: the Space reads MQTT_BROKER/MQTT_PORT/MQTT_USERNAME/MQTT_PASSWORD (the HiveMQ creds, named MQTT_* on HF), plus MONGODB_PASSWORD, blinded_connection_string, and YT_API_KEY (livestream); HiveMQ creds must match across HF / OT-2 / Pico W; WiFi creds live on the OT-2 and Pico W.
  • MongoDB collections: wells, student, result (the live results collection), HITL_status, maintenance_logs.
  • Known-issue context: per-experiment_id experiment_store routing addresses the "wrong student's result" bug; yt_utils.get_latest_video_id walking the whole playlist by publishedAt addresses the livestream-ordering issue.
  • Maintenance: plate reset is the Prefect human-in-the-loop maintenance_flow.py (Slack notify → pause → generate_empty_well() → log), not a manual MongoDB edit.
  • NOKIA router: only needs to provide stable WiFi (matching my_secrets.py); HiveMQ is cloud-hosted and not in the data path. Hotspot swap recommended to isolate WiFi vs. broker/sensor faults.

Flagged (not changed, out of scope)

  • HiveMQ credentials are hard-coded in OT2mqtt.py and the orchestrator notebooks; OT2_SERIAL/PICO_ID are hard-coded in the Space's app.py — device swaps or credential rotation require updating all relevant locations (OT-2, HF, Pico W).
  • The Space's DB_utils.py has diverged from the repo's DB_utls.py (e.g. live collection result vs. MSE403_result, added maintenance helpers); may be worth syncing.
  • Confirm the Pico W runs the mqtt_as.py variant, not mqtt.simple (wireless-color-sensor#13).

Copilot AI changed the title [WIP] Fix liquid colour matching demo for winter 2026 MSE403H1 Document OT-2 / Hugging Face / MongoDB data flow for LCM demo Jun 19, 2026
Copilot AI requested a review from sgbaird June 19, 2026 16:40
@sgbaird

sgbaird commented Jun 19, 2026

Copy link
Copy Markdown
Member

@copilot more so I mean provide an explanation to @kbuchel about how each of these pieces work together, without assuming familiarity with MongoDB, Prefect, Hugging Face, or OT-2 firmware / workflows. Include hyperlinks to specific files to provide additional context.

Note also that you'll want to access the hugging face space for the OT-2 LCM, looking at the files there, too.

Copilot AI commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

@copilot more so I mean provide an explanation to @kbuchel about how each of these pieces work together, without assuming familiarity with MongoDB, Prefect, Hugging Face, or OT-2 firmw...

@kbuchel here's a from-scratch walkthrough of how the liquid colour-matching (LCM) demo works, assuming no prior exposure to MongoDB, Prefect, Hugging Face, MQTT, or the OT-2. I've linked the specific files for each piece.

First, a note: I wasn't able to open the Hugging Face Space files from my sandbox (the huggingface.co domain is blocked here), so the explanation below is reconstructed from the code that lives in this repo, including the file that runs on the HF side (DB_utls.py). The one thing I can't directly confirm is the exact HF web-app layout (app.py). If you paste those files here or grant access, I can fill in that last gap. @******, that's the bit I'm missing.


The 5 pieces, in plain terms

Think of it like a tiny restaurant:

  1. Hugging Face Space = the front counter + manager. A "Space" is just a small website that Hugging Face hosts for free, running a Python program. This is where a student types in the colour they want (how much Red/Yellow/Blue) and their student ID. The manager also decides which empty well on the plate to use and whether the student still has experiments left.

  2. MongoDB = the notebook the manager writes in. MongoDB is a cloud database — basically an online spreadsheet/filing cabinet. It remembers three things (collections):

    • wells — which of the 96 wells on the plate are still empty vs used.
    • student — each student ID and how many runs they have left (their quota).
    • MSE403_result — the saved colour readings from every experiment.
      The code that reads/writes all of this is in DB_utls.py (e.g. find_unused_wells, get_student_quota, save_result).
  3. HiveMQ = the order-ticket rail between the counter and the kitchen. HiveMQ is a cloud "message broker" using a protocol called MQTT. MQTT works like a bulletin board: programs "publish" (pin up) messages on named topics, and other programs "subscribe" (watch) those topics. Nobody talks directly to anybody — they just post and read tickets. This is how the website (which is on the internet) reaches the robot (which is on a local bench) without them needing each other's addresses.

  4. OT-2 = the line cook / hands. The OT-2 is the liquid-handling robot. It runs the script OT2mqtt.py. It watches HiveMQ for "make this colour" tickets, pipettes the paint, then picks up the colour sensor and holds it over the well.

  5. Pico W colour sensor = the eyes. A tiny wireless microcontroller with an 8-colour light sensor (AS7341). It runs sensor_file/main.py. When the robot holds it over the well, it measures the colour and posts the numbers back on HiveMQ.


One experiment, step by step

  1. Student fills out the form on the HF website: target R/Y/B + student ID.
  2. Manager checks the notebook (MongoDB): does this student have quota left (get_student_quota), and which well is free (find_unused_wells)? See DB_utls.py lines 55–108.
  3. Manager posts a ticket to HiveMQ on the topic command/ot2/{serial}/pipette, saying e.g. "Red=120, Yellow=50, Blue=80, well=B2".
  4. The robot is watching that topic (OT2mqtt.py lines 33–48), grabs the ticket, and runs mix_color: it pipettes each colour into well B2, then picks up the sensor and lowers it over the well (lines 87–141). It then posts "sensor is in place" back on status/ot2/{serial}/complete.
  5. The sensor measures and posts the 8 colour-channel numbers on color-mixing/picow/{id}/as7341 (sensor main.py).
  6. Manager tells the robot to put the sensor back; the robot runs move_sensor_back (lines 144–161), dropping it into its charging port.
  7. Manager writes results to the notebook: save_result stores the reading, and the well is marked used (update_used_wells). The student's quota goes down by one.

So the data path is always: Website ⇄ HiveMQ ⇄ Robot/Sensor, with the Website ⇄ MongoDB on the side for remembering state. The robot and sensor never touch MongoDB or the website directly — only HiveMQ.


"Prefect" — what that word means here

You'll see Prefect mentioned. Prefect is just a tool for scheduling and re-running Python jobs automatically (like a smart cron / task runner). In this demo it was used to fire off the manual "refill the vials / reset the plate" reminders and to wrap the robot steps as restartable "flows" — see prefect/device.py and prefect/orchestrator.py. It's optional plumbing, not core to the colour logic — the simpler, no-Prefect version of the same flow is ot2_orchestrator_mqtt.ipynb, which is the clearest file to read if you want to see the whole loop end to end.


What you need credentials for (and where)

  • HiveMQ (host, username, password): needed in three places that must all match — the website, OT2mqtt.py lines 13–16, and the Pico W's my_secrets.py. (Kelvin already found these.)
  • MongoDB (MONGODB_PASSWORD + blinded_connection_string): only the website needs these — DB_utls.py lines 10–14. They're stored as "Secrets" in the HF Space settings.
  • WiFi (the NOKIA router's SSID + password): needed by the OT-2 and the Pico W so they can reach HiveMQ. HiveMQ itself lives in the cloud, so the router only has to give those two devices stable internet — it isn't otherwise part of the data path.

Handy maintenance command

To start a fresh plate, instead of editing MongoDB by hand, run generate_empty_well() (DB_utls.py lines 17–35) — it resets all 96 wells back to empty.

Happy to go deeper on any single piece (e.g. exactly how the website subscribes to the sensor's results) once I can see the HF Space's app.py.

@sgbaird

sgbaird commented Jun 19, 2026

Copy link
Copy Markdown
Member

@copilot should be unblocked on firewall now

@sgbaird

sgbaird commented Jun 19, 2026

Copy link
Copy Markdown
Member

@kbuchel does the above make sense? #553 (comment)

To what extent does this answer your question? Noting again that I no longer have access to the MongoDB that was being used.

Copilot AI commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

@copilot should be unblocked on firewall now

Firewall's working now — I read the actual Space, AccelerationConsortium/OT-2-LCM (a Gradio app, last updated 2026-06-18). Note the light-mixing Space I linked before is a different, older NeoPixel demo; OT-2-LCM is the one driving this course. Here's the corrected/filled-in picture for @kbuchel.

The HF Space's files (the "manager")

  • app.py — the Gradio website + the brain. It holds the experiment queue, talks MQTT, and renders the page (student-ID box, R/Y/B sliders, queue status, and the YouTube livestream iframe).
  • DB_utils.py — all MongoDB reads/writes (this matches the repo's DB_utls.py, plus extra maintenance helpers).
  • yt_utils.py — fetches the current livestream.
  • maintenance_flow.py + prefect_utils.py — the Prefect "human-in-the-loop" maintenance reminders.

What I can now confirm (and correct)

1. The website is the one that triggers the sensor read. Earlier I had to guess this. It's confirmed in app.py: the OT-2 only positions the sensor and reports in_place; then the HF app publishes the read command to the sensor, receives the data, and tells the OT-2 to put the sensor back. The full ping-pong over HiveMQ is:

  1. HF → command/ot2/{serial}/pipette (mix R/Y/B in well) — app.py#L327-339
  2. OT-2 → status/.../complete = in_place
  3. HF → command/picow/{id}/as7341/readapp.py#L176-188
  4. Sensor → color-mixing/picow/{id}/as7341 (the 8 channel values)
  5. HF → OT-2 sensor_status: read (return the sensor) — app.py#L144-151
  6. OT-2 → status/.../complete = charging; HF then calls save_resultapp.py#L190-218

(This is why the sensor-command lines are commented out in the repo's OT2mqtt.py — that job moved to the HF side.)

2. Env-var names on HF are MQTT_*, not HIVEMQ_*. The Space reads MQTT_BROKER, MQTT_PORT, MQTT_USERNAME, MQTT_PASSWORD (app.py#L37-40) — these are the HiveMQ creds, just named differently in the Space's Secrets. Also needs MONGODB_PASSWORD, blinded_connection_string, and YT_API_KEY (for the livestream). @kbuchel, that's the complete secret list for the Space.

3. MongoDB collection names (db LCM-OT-2-SLD): wells, student, result (the live collection is result, not MSE403_result — I had the latter from the repo copy), plus HITL_status and maintenance_logs for the maintenance flow.

4. The "wrong student's result" bug Neil mentioned: app.py now keys every experiment by a unique experiment_id in an experiment_store, each with its own result queue, and drops messages whose experiment_id is unknown (app.py#L112-130) — so results are matched to the originating submission, not whoever's page is open.

5. The livestream / playlist issue Neil flagged is addressed in yt_utils.get_latest_video_id: it now walks the entire playlist (PLAYLIST_ID = PL8uZlc2...) and picks the newest item by publishedAt rather than trusting playlist UI order (yt_utils.py#L51-96). So if the wrong video shows, check that the live video is in that playlist (and that YT_API_KEY is valid).

6. Plate reset = Prefect maintenance flow. maintenance_flow.py posts a Slack message, pauses for a human to confirm, then calls generate_empty_well() to reset all wells to empty and logs who did it. So the "human-in-the-loop" reset Sterling/Neil described is this flow, not a manual DB edit.

One thing still hard-coded in app.py: OT2_SERIAL and PICO_ID (L43-44) — if either device is swapped, that has to be updated in the Space and kept in sync with the OT-2 script and the Pico's my_secrets.py.

No code changes here — this is the documentation answer requested. Happy to diff the Space's DB_utils.py against the repo's DB_utls.py if it's worth syncing them.

@skule-webmaster

Copy link
Copy Markdown

@kbuchel does the above make sense? #553 (comment)

To what extent does this answer your question? Noting again that I no longer have access to the MongoDB that was being used.

Hi Dr. Baird,

This fully answers my question--thank you! Do you have any update on the router yet?

@sgbaird

sgbaird commented Jun 19, 2026

Copy link
Copy Markdown
Member

@kbuchel I sent a message to Gurpaul but haven't heard back. You might consider reaching out. A stop gap would be to pair it to a phone hotspot (needs to be in "compatibility mode" to switch to it 2.4 GHz instead of 5G), which would at least unblock you from testing.

@kbuchel

kbuchel commented Jun 19, 2026

Copy link
Copy Markdown

@kbuchel I sent a message to Gurpaul but haven't heard back. You might consider reaching out. A stop gap would be to pair it to a phone hotspot (needs to be in "compatibility mode" to switch to it 2.4 GHz instead of 5G), which would at least unblock you from testing.

Hi Dr. Baird,

I tried this, but the sensor was having a lot of trouble connecting to my hotspot, and so was the robot. Also side note—is the SFTP subsystem broken? Cyberducks is throwing an EOF error when I try to connect to the Opentrons.

@sgbaird

sgbaird commented Jun 19, 2026

Copy link
Copy Markdown
Member

@kbuchel what phone do you have? It might also help to canonicalize the SSID and password (no spaces for example)

Cyberducks is throwing an EOF error when I try to connect to the Opentrons.

What is Cyberducks? How are you using it?

Have you been able to SSH into the OT-2? I believe this is the primary way we interfaced with the OT-2 in terms of initial setup.

@kbuchel

kbuchel commented Jun 22, 2026

Copy link
Copy Markdown

@kbuchel what phone do you have? It might also help to canonicalize the SSID and password (no spaces for example)

Cyberducks is throwing an EOF error when I try to connect to the Opentrons.

What is Cyberducks? How are you using it?

Have you been able to SSH into the OT-2? I believe this is the primary way we interfaced with the OT-2 in terms of initial setup.

Hi Dr. Baird,

  1. I have an iPhone13--it is letting me hotspot my sensor now, but I have been having trouble connecting the Opentrons robot to it--I am going to try again right now. On this note, is there any update on the router? I still cannot connect it to the sensor.

  2. Cyberducks is a system extension which allows for remote file transfer--I gave up on using it because the SFTP connection appears to be broken, but I found another (and simpler) way to transfer files so this issue is resolved.

  3. I have been able to SSH into the Opentrons.

@sgbaird

sgbaird commented Jun 23, 2026

Copy link
Copy Markdown
Member

I have been having trouble connecting the Opentrons robot to it

Ah.. I'm not sure why that would be. I haven't heard back about the router. I have a vague memory that of the three routers we had, some of the plans might have been cancelled. I'll cc you on another email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants