Week 13: Application

Here’s a video of the website while I’m on the bike. It does work!!

I have the pico w connected to the bike, and sending data through serial to my computer (because I couldn’t get pico to connect to glitch websockets). Then the computer has a websocket to glitch to forward the messages. And then clients connect and get to see the current ride going on (or select a workout).

The website is here if you want to watch me bike: site.

Okay picking up from last week!

I’m going to simplify things a bit by dropping the intermediate server. Instead, I’ll have the Pico W talk directly to a glitch application to keep it updated with the latest bike stats.

Tweaking the app 🔗

First I took Char’s drawing app example, since it had sockets and a database and such.

From the bike 🔗

i thought i’d use a database to persist some storage, but it turned out complicated enough that that’s a nice to have in the future.

I finished up the work from last week and was able to parse out the data. the real secret was parsing the flags, and then referring to this doc to tell you which bytes were around. Then chatgpt told me about struct.unpack, which handles endian-ness too. so flags, speed, cadence, power, hr = struct.unpack("<HHHhb", data) handles it for my bike. (If I needed to handle arbitrary bikes, I’d need to parse flags first, and then go back and parse the rest of the struct. but yay for a user-base size of 1.)

Originally the plan was to have this connect to wifi and run, and then send to websockets. Spoilers, I couldn’t get micropython’s websockets to play nice with glitch’s. I was getting 502 errors, and the internet mentioned something about SSL errors, and so I decided to debug it later…

Defining a ride 🔗

I started with a simple ride, which actually cover most of the features.

[
  {
    "duration": 120,
    "type": "FreeRide"
  },
  {
    "duration": 30,
    "type": "MinCadence",
    "min": 100,
    "target": 120
  },
  {
    "duration": 30,
    "type": "FreeRide"
  },
  {
    "duration": 30,
    "type": "MinCadence",
    "min": 100,
    "target": 120
  },
  {
    "duration": 45,
    "type": "FreeRide"
  },
  {
    "duration": 45,
    "type": "MinCadence",
    "min": 100,
    "target": 120
  },
  {
    "duration": 60,
    "type": "FreeRide"
  },
  {
    "duration": 60,
    "type": "TargetZone",
    "zone": 2.5
  },
  {
    "duration": 60,
    "type": "TargetZone",
    "zone": 3.5
  },
  {
    "duration": 30,
    "type": "TargetZone",
    "zone": 4.5
  },
  {
    "duration": 15,
    "type": "TargetZone",
    "zone": 5.5
  },
  {
    "duration": 15,
    "type": "TargetZone",
    "zone": 6.5
  },
  {
    "duration": 60,
    "type": "FreeRide"
  },
  {
    "duration": 120,
    "type": "TargetZone",
    "zone": 2.5
  },
  {
    "duration": 180,
    "type": "TargetZone",
    "zone": 3.5
  },
  {
    "duration": 180,
    "type": "TargetZone",
    "zone": 4.5
  },
  {
    "duration": 180,
    "type": "TargetZone",
    "zone": 3.5
  },
  {
    "duration": 180,
    "type": "TargetZone",
    "zone": 4.5
  },
  {
    "duration": 180,
    "type": "TargetZone",
    "zone": 3.5
  },
  {
    "duration": 180,
    "type": "TargetZone",
    "zone": 4.5
  },
  {
    "duration": 600,
    "type": "TargetZone",
    "zone": 2.5
  }
]

I spent some time implementing something in Rust to handle this: take in a new update, and check where in the workout you are, and give you feedback.

Okay now i have Rust code that can load a workout, then start a new workout, and receive updates. It was nice to write in Rust. Now I bring it into glitch…

server glitch.io 🔗

let’s work a bit on the central hosted server. This will be the page that I open up to view the workout.

  • used chatgpt to give me a build command to deploy code to the device with a keyboard shortcut. that was very nice. (have to update the /dev/tty based on the usb, but still cool.)
  • this ended up… so messy and insecure. the workout is on the frontend (because loading in the server requires different code), timestamps are controlled client-side… the server-side just kinda stores the start time and workout description.
  • websockets, was really helpful to get the bits of code that makes it restart automatically. yay chatgpt.
  • while micropython now has aiohttp, i had trouble connecting to sockets.io, so instead I went back to pure websockets.
  • oh wait… socket is still a bidirectional thing, back and forth. so it’s not going to send the message to the others (needed the chatgpt o1 model to tell me that), so now i set up a little list of websockets that i’ll broadcast too.
  • blargh, moving the WASM to the backend will require changing loading the file, and i’m getting errors with chatgpt code. so just going to stick in the frontend.

Here’s all the code that’s not on glitch on github.

You've found my documentation of the Fall 2024 class for how to make (almost) anything at MIT. At the time of writing, I am a first year MAS student (MIT Media Lab) in the Future Sketches lab. When I'm not making almost anything, I'm making specific other things, like making cool-looking things with code, which I sometimes pen plot or live code.