Ruby on Ice 2019

Hardware Hacking with Your Rails App

When working on a Rails app with lots of users and a plethora of requests, you’ll likely soon be addressing how you can have dedicated custom hardware for them.

In this talk, I’ll go over my experiences and lessons learned from working on dedicated hardware for industrial catering services.

By Ramón Huidobro https://twitter.com/@senorhuidobro

Ramón Huidobro is a chilean kids’ coding instructor and freelance software dev. He likes to introduce people to coding more than he enjoys coding itself. If you want pointless Nintendo trivia, look no further than Ramón! You’ll probably find him at a lot of conferences and has been told he has a distinctive laugh, so he’s easy to spot, especially when wearing a onesie.

https://rubyonice.com/speakers/ramon_huidobro

Ruby on Ice 2019

00:00:12.030 Let's start with the first talk. Back to the schedule, our first speaker of the day is Ramón Huidobro. I hope I present his name correctly. Ramón is from Chile but has been living in Vienna for the past nineteen years. Apparently, he loves wearing onesies! This is the first time I've heard something like that, but it is really cool. He also has an interesting passion for Nintendo trivia, so if you want to exchange anything like that, feel free to talk to him. He is super nice, and you can chat with him after the talk as we won’t have time for questions. The talk today is about hardware hacking with your Rails app. Thank you!
00:01:05.460 Thank you, Monica, for that lovely introduction. Good morning, everyone! Sorry for my vanillish accent; how are you all doing today? How about this conference, huh? That's better! Thanks for coming and for listening to me— I promise I won’t bore you. So, a little bit about me. Oh, yes, there we go. I am Ramón, a freelance software developer living in Vienna, Austria, and I also teach children to code. I enjoy this more than coding itself. You might have seen my photo on the website and wondered where the picture with the dog is. Don't worry; I have you covered. This is Fiona, she's the love of my life. She has eyes that say a million things in a way I’ve never seen in a human or creature before. She's very expressive and even judges my wife for eating mangoes. In Chile, there’s a word that I think is exclusive to us: 'dragón luna.' She’s my dragón luna. I tried searching for it in English, but unfortunately, Google Translate didn't help me out, which is fine.
00:02:40.900 I love working with Ruby. It's such a fun programming language, and Rails is a great framework that helps me get things done. As a freelancer, I love the variety of projects I get to work on. One minute I’m working on government projects that help people find emergency contacts; the next, I'm in the back of a cafeteria at an office building, helping people get their lunch. That’s actually what I’m going to tell you about today. One of my clients is a culinary catering business located just north of Vienna in the industrial zone. They specialize in three parts: catering, cafeteria lunch for workers, and a restaurant. Most of my work involves the cafeteria lunch service.
00:03:34.480 My work provides a service where users can go online to look up what they want to eat and order their menus for lunch for the week. Then, on the actual day, we prepare and serve the food to them. As the company has grown, they’ve taken on new clients to serve lunch, and each time this happens, we meet with them, and they usually say, 'This is great, but I need this or that. Can you add a checkbox here? Can you overload your database with more Boolean flags there?' Recently, a paper manufacturing company told us that their workers, who work on the factory floor, don’t have access to a computer at their desks as they are standing and working all day. They communicated that the current solution wasn’t going to work for them, and they needed a new one. Each employee has their own chip card, so they proposed a system where employees can scan their chip card and use a terminal set up in the cafeteria to order their food for the week.
00:04:51.070 So, we sat down, my client and I, and began drafting what we could do. I like to give my projects fun names, so I called this one Project Hairnet. The way it works is simple: you scan your chip card, and a screen displays the menu. You place your orders, and then on the day, you get your food and enjoy it! Immediately, my mind started racing with ideas. I envisioned a super fancy React app with a Rails REST API in the background, or perhaps some sort of native app with dedicated hardware that we could manufacture in China. However, my client, who happens to have a master's degree in computer science, said, 'Hold on, hold on, slow down! We already have a perfectly good Rails app running in the background. Why don't we just set up a very simple touchscreen to get this done?'
00:05:36.309 Great! So, we started looking at our requirements, the first of which was hardware. We needed a chip card reader; we found a compatible model that reads legitimate cards that have some embedded data on them. As for the PCs, we could have a special monitor touchscreen connected to the cloud, but ultimately, what we ended up using was an all-in-one PC with a touchscreen, which worked out great. In terms of software, all we needed was Ubuntu and Chromium, essentially just a browser, which took care of our hardware requirement. Great! First step done.
00:06:12.849 Next, we had to consider security. If you leave a computer standing in the middle of a cafeteria, where there will be plenty of people, anyone could come in, plug in a keyboard, and mess around with it—especially someone malicious who knows what they’re doing. We needed a way to protect that Chromium instance from being tampered with. I discovered that I could launch Chromium in full-screen mode. It managed to boot up and open the website, but I forgot to consider that resolving hosts could be an issue. Anyone could come in with a keyboard, press' alt' + 'tab', and mess everything up.
00:06:53.089 I found out that Ubuntu, as well as other operating systems, offers a way to set up what's called 'kiosk mode.' This mode opens up an application windowed out to limit access to the Start menu or any other desktop features or tools. After setting this up, I could turn on the computer, and I'd get a nice blank Ubuntu screen, which was exactly what I wanted. I then began sketching out how I could make this work right. On the laptop, users could log in, but we needed to have the same functionality on the touchscreen terminal. We thought about how to do this, and the best method we arrived at was using a simple 'before_action' with Rails and a request header.
00:07:56.720 You might think this isn't the fanciest way to achieve this, but it worked! All we did was ensure that the Chromium instance on our terminal would submit a request environment variable with a secret token to authorize the terminal to access the chip card scanning mode. I was able to create a helper to check that we had the secret. I didn’t embed the token into the code, but this was just for the sake of example, and with this, we could check whether we were in kiosk mode and display the page accordingly. At that time, I didn’t have much experience working with HTTP headers. I discovered that passing that header to the app wasn’t as straightforward as I'd thought. It was tricky to get the browser to submit that header.
00:09:06.400 After doing some research, I found a Chromium extension that allows you to set up request headers with the secret token, which ended up working well. However, this solution felt a bit hacky for a production environment, especially considering I had just three weeks to complete the project. I then discovered I could set up an Electron app. For those who don’t know, Electron lets you build native apps on your operating system that run in a Chromium instance. This turned out to be exactly what I needed.
00:09:55.240 With Electron, I could load the URL and pass the token I needed, and this worked out fantastically! So now, when you turned on the computer, we set it up to automatically run the Electron app. The terminal would be ready to scan the chip card, and I learned a critical lesson: preventing tampering with dedicated hardware is essential, whether for a large corporation or a small one. You always need to consider potential security vulnerabilities.
00:10:36.200 Next, we had to implement the chip card scanning process. We designed a simple Rails page that says in German, 'Welcome! Please scan your chip card.' This worked well. The idea was to take your chip card, scan it over the reader, and then access the menu for the week. I learned that each of these cards has a user ID embedded in them, provided by the company. My original idea was that by scanning the chip card, it would automatically open the menu for that user.
00:11:08.300 However, these chip card readers need to be configured to read that data because, by default, they show a UUID, which is not what we wanted. To get the specified functionality, I looked up the manufacturer’s documentation, but I discovered that the only way to program these units was via a Windows Vista app called 'App Blaster.' This app flashes firmware onto the card reader. While the manufacturer provided some code samples, I thought I could handle it; even if the documentation was outdated and partially in German, I ended up running into issues and receiving read errors due to the firmware configurations. I spent a week trying to fix this with no success.
00:12:34.080 Eventually, I decided to call the manufacturer for assistance. They informed me that not only was the number itself on the card encrypted, but the memory address where that number is stored was also encrypted. To get the address, I needed to sign a non-disclosure agreement. In the end, I asked them if they could provide the firmware, which they did, and I then successfully flashed it onto my device! The chip card reader acted like a USB keyboard, sending data directly into the web app without needing a specialized program reading from files or descriptors.
00:13:38.130 Moreover, it was interesting that the firmware was set to enter the digits and then perform a carriage return. As a result, I realized all I needed on our chip card scanning page was a simple input field. Users could just scan their chip cards, and they would be logged in without complicated interfaces. However, a couple of issues arose. When the computer loaded, the input field wasn’t focused, leading to confusion during the scanning process.
00:14:05.070 To resolve this, I used Rails’ autofocus feature. Another issue was when the computer went to sleep and was turned back on: the focus was lost. Thankfully, JavaScript has solutions for that as well! I showcased the solution to my client, and he suggested a more visually appealing method involving JavaScript waiting for input, and I thought, sure, but making the input field invisible worked just as well. Thus, a customer could arrive, scan their chip cards, beep, and access their menu seamlessly.
00:15:14.800 What I learned from this process is that it's totally fine to ask for help when stuck on a problem for too long. It’s a good idea to seek assistance instead of banging your head against the wall. Though it may have felt a little hacky, it worked, and finding better solutions later on is always possible.
00:16:07.340 Next, we had to focus on making the system stable. It's crucial that this terminal runs smoothly without any hiccups. Unexpected issues could arise, such as a lightning storm or a power outage, and logically, someone might tamper with the cables. Most computer BIOS settings allow auto restart after power loss, which worked well after we tested it out. However, I considered the worst-case scenarios where I would need to intervene remotely.
00:17:01.420 I thought about how to remotely access the terminal to perform a reboot or upgrade software without physically going there. SSH was a potential solution, but my client advised against leaving an SSH port open to the public for security reasons. We thought about using VNC— which allows remote screen sharing— but that would be disruptive for users placing their lunch orders. Ultimately, we needed a different option. My client, a master in computer science, suggested using reverse SSH tunneling.
00:17:43.750 While reverse SSH tunneling sounds complex, the concept is quite straightforward. On startup, the terminal connects to our server, keeping a constant connection open. Thus, I can connect to the server on that port, which redirects any SSH traffic to the terminal. Essentially, it feels like I'm connecting directly to the terminal.
00:18:24.450 This knowledge taught me that many solutions are easily accessible, even high-tech-sounding ones like reverse SSH tunnels. They can make a life easier, and with that thought, I was able to check off project Hairnet and call it a day.
00:19:56.720 However, after completing the project, clients often suggest additional features. They might ask us to add this or that. Adding automatic logout for users was one request because they sometimes leave the menu open after scanning their chip cards. For security reasons, we implemented a time-out feature. If a user is inactive, a message displays, alerting them of an impending log-out unless they interact with the terminal.
00:20:14.179 Another challenge was some users arriving at the cafeteria inquiring about their orders. We needed a way for them to confirm it while ensuring no duplicate orders were placed incorrectly. So, we set up an additional system to ensure both the user and the cafeteria staff could see what was ordered, while also confirming it was picked up when scanned.
00:20:37.880 To address this, I employed a Raspberry Pi setup that mirrored what we designed with the touchscreen terminal. By using Electroneering and automatic SSH maintenance to track the orders, we could say, 'Your order has been successfully picked up!' This allowed customers to quickly and efficiently manage their meal experience.
00:21:38.820 Ultimately, we ended up offering backup meals, which we could present on the screen based on the available food at the end of the ordering window. We even drafted an emergency menu for instances where someone might forget to order food beforehand.
00:22:31.840 In conclusion, these projects are just the beginning of what we can explore involving simple yet dedicated hardware connected to our Rails app. This experience sparked thoughts of maybe building a complete cash register system in the future, with dual screens for the cafeteria manager and the users alike.
00:23:35.250 Thank you for attending today! Remember: it is vital to keep experimenting with your existing technology; there is much potential in what you have at your fingertips. Lastly, for those feeling uncertain about speaking opportunities, I encourage you to consider attending events like the Global Diversity CFP Day, which helps improve public speaking skills. Your perspective matters, and sharing your story can inspire others. Thank you!