[Kiosk - Planning/Overview] Building a 20-Million-Won Parking Kiosk from a 50,000-Won Secondhand One • 2026-03-17

[Kiosk - Operations/Troubleshooting] Live Operations — CI/CD and PEBCAK

Failure types encountered in live operation, root-cause analysis, remote-recovery procedures, and a checklist to prevent recurrence.

1. OS Compatibility Issues: Which Windows 10?

I wiped the existing Windows 8-to-10 upgrade install and put on the lighter Windows 10 LTSB 2016. LTSB stands for Long Term Servicing Branch — a high-stability OS variant that gets security updates only, with no feature updates.

The problem: the app crashed outright the moment Flutter tried to load the Firestore library. It turns out Firestore Native requires a modern HTTP/2-based service called gRPC, which Windows 10 2016 simply doesn’t have.

Even reinstalling with Windows 10 LTSC 2021 didn’t fix it — the low-spec hardware plus gRPC compatibility issues still kept it from working. The cleanest fix would be running the Firebase Admin SDK or a MongoDB compatibility mode, but I wasn’t confident the hardware could keep up.

So I settled on Firebase RTDB instead. It runs on plain old HTTP/1.1. Since the HTTPService it relies on was already running for other parts of the app, I could stand up a remote DB with essentially no added overhead. I added a fallback that switches to local logging if initialization fails, and made sure no “personal information” ever gets transmitted — giving me a stable server setup.

2. Encoding Issues: Gibberish Showing Up in the DB

After wiring up Firebase RTDB for payment data, a bug surfaced: garbled “mojibake” text. The catch was that it wasn’t the whole string — only the card name was affected. A “KB Card” would come through fine, but “KB ‘Wise’ Card” would show up mangled, like “???댁즈.”

The cause: the EVCAT software uses Windows’ CP949 encoding, and Flutter’s UTF-8 handling was mangling it on the way out. So I added a CP949-to-UTF-8 translation layer before sending the data, unified the encoding, and the problem went away.

3. Data Security and Compliance

Under Korea’s Personal Information Protection Act, logs and stored data can never contain personal information as plain text. There’s also a rule that logged data must be discarded after 3 months. I implemented app-level logic to auto-purge data after 3 months, and since EVCAT supports masking, I settled on masking card numbers and storing them locally only.

I also made it so that only high-severity log entries (error/payment) get pushed out in real time over Firebase RTDB, keeping that channel tidy.

4. CI/CD and Auto-Update System (In Progress)

The goal is to check for the latest build via the GitHub Releases API and, when a new build is available, run a batch script to apply the update.

The update script was designed to download to a temp folder → kill the running process → replace the files → relaunch, but this got shelved due to hardware constraints.

5. A PEBCAK Problem: Please, Just Wait for the Receipt to Finish Cutting

The receipt printer runs over a basic 115200 serial connection. A few issues came up along the way — printer jams, specifically. Cutting is a separate command, so I set it up to flush the serial buffer and then cut — but if a user grabs and pulls the receipt during the 3-second loop between those steps instead of waiting, it jams and the next receipt can’t print. “Please, just wait!!!”

I plan to fix this later with a receipt guard or a faster flush.

6. A Docs Problem, and Payment vs. DB Update: Chicken or Egg?

The docs the parking operator provided marked a field as “required,” but a note in the remarks column said “if left blank, defaults to the vehicle’s plate number.” I trusted that note completely and assumed “if I leave it blank, there must be server-side logic that substitutes the plate number,” so I sent it empty. The problem: it really was a required field, so it errored out — resulting in the worst kind of message: “I paid, but it’s not letting me out of the lot.” Once the DB throws an error, there’s no way to undo a payment that already went through — an awful situation to be in.

This is also something I plan to fix later.

7. Wrapping Up the Project

I thought this would just be building a simple front-end app, but I came away realizing that thinking from the real user’s perspective, building maintenance and repair systems, and iterating on a product’s polish by listening to user feedback takes more than just development skill — it’s fundamentally about communication. Especially now, when so much programming is being handed off to AI, isn’t the ability to build for what users actually need the real baseline skill?