RubyKaigi 2023

Ruby vs Kickboxer - the state of MRuby, JRuby and CRuby

RubyKaigi 2023

00:00:02.280 Welcome everyone.
00:00:24.800 Hi everyone, I'm Selena and this is my sparring partner, Michael. We're here today to talk about our journey with Ruby and Kickboxer.
00:00:29.460 That's right! Today we’ll be exploring the state of MRuby, JRuby, and CRuby. But maybe we should start with some background. I’m sure the audience is thinking to themselves, what’s Kickboxer? Is it some kind of new tool or library?
00:00:40.980 Yeah, you're probably right. So, Selena here is an actual kickboxer. I'm sure you'll remember that a few years ago, a worldwide pandemic broke out, and Melbourne, where we're both from in Australia, endured harsh lockdowns. This meant that Selena couldn't train with her usual sparring partners, so she came up with this crazy idea: why not build a sparring robot using Ruby?
00:01:04.260 That's right! A key part of training for combat sports is improving your footwork. I thought, well, I could take a drill that I’ve been using at the gym with my coach and create a robot where pool noodles essentially strike the athlete, requiring them to swiftly evade using their footwork.
00:01:32.100 I reached out to my friend Michael, who loves collaborating on projects and knows a bit about hardware.
00:02:00.420 Yeah, I love an opportunity to work on hardware. I started thinking about the various moving parts and whether there would be any potential blockers to this project. So let's break them down. We start with the actuator, which is the hardware device that Selena will be training with. For this, we could use a motor or a servo along with a simple microcontroller like an Arduino.
00:02:30.600 We'll probably want to control it remotely using Wi-Fi, so maybe use something like an ESP32, which is basically an Arduino with Wi-Fi. That should fit the bill perfectly.
00:02:43.020 But can we run it in Ruby? Quite likely! We can use MRuby, which is a lightweight implementation of Ruby specifically designed for embedded systems. It’s perfect for running a device like the actuator, which has limited resources.
00:03:02.640 Great! And if we want to control it remotely, we’re probably going to need some kind of server for the actuator to connect to. But will that run Ruby? Yes, it will! We’ll probably use CRuby, also known as Ruby MRI, which is Matz’s Ruby interpreter.
00:03:21.420 The server will receive data from the actuator and also communicate with a mobile device that Michael will be using to control the actuator. For the mobile client, we have two options: Android or iPhone.
00:03:44.520 But could we run that with Ruby? Android is a Java platform, so surely it can just run JRuby on it. JRuby famously implements 98% of Ruby, so if we write it in Ruby, it should run in JRuby because JRuby is just Java.
00:04:03.840 So in the end, I’d be sparring with a pool noodle to practice my footwork. This is going to be such a cool project! I can’t wait for it to all come together.
00:04:26.100 Me neither! Especially since I'll be on the other end, throwing out the attacks at you with a mobile app. All right! I think everyone gets it. They understand the plan. Let’s get started with the actuator. Our initial thoughts here were MRuby. We heard Yuji Okuda talk about this numerous times at conferences where he made a Wordle game using MRuby C and ran it off a Sega Mega Drive.
00:05:09.900 Back in 2020 at Rubicon for Australia, Paul and Tharn presented a voice-based smart home system using Sinatra and MRuby C, showcasing so many possibilities.
00:05:46.300 We came across the MRuby ESP32 application template, and it sounded like a quick start. But we soon found out it was not as simple as we thought it would be. It was quite the journey! We assumed we could just run ASDF MRuby and it would be installed on our device, but it turned out to be much more complicated. We had to go through many steps like copying C project files into Ruby source files and MRuby components.
00:06:11.200 Then we had to use the ESP-IDF (Espressif IoT Development Framework), which actually uses Python to compile the project. After all that, we could finally push our code onto the ESP32. Do you want to see a demo?
00:06:46.620 Yeah, should we look at a demo now?
00:07:05.639 But what we also have is an MRuby implementation, so let's just plug that in. There we go! Whoa! MRuby is so much brighter!
00:07:39.500 Cool! I'm sure everyone's interested in the story, but can we just look at some code?
00:08:10.500 Great idea! On the left, we have some straightforward ESP32 C or Arduino code. We define a pin, set the pin to be an output, and in an infinite loop, we set the output high for one second, low for one second, and repeat. That's blink.
00:08:51.400 How does this compare to MRuby? In MRuby, we can do all the same things with way less code. Well, it's only two lines less, but still less, right? Although it is very verbose and all the functionalities are really just hidden away in other classes.
00:09:13.700 This was enough to get a light flashing, but we actually had to do a little bit more to get it connected to a server so we could control it remotely. Should we do another demo?
00:09:39.300 Yeah!
00:09:41.660 All right! Over here, I have an MQTT server running. We’ll talk about that later. If I bring this to the terminal, we can see that we're running Ruby 3.2.1.
00:09:58.680 If I connect to that Kickboxer LAN and run our client, we'll see that it’s got an actuator. So one has been registered. As Selena plugs in the second actuator...
00:10:32.060 It's all good! Live demos! So at this point, we see an event log at the bottom saying these actuators are live. We’re waiting for a second one to show up. There’s the second one! So now there are two, and if I go down the arrow, I can move between them. If I kick that top one and press enter, we get... yes, a lot going on!
00:11:30.000 On the right, we've got the MRuby code; it's about one page, not too bad. On the left, we have the ESP32 C code: one page, two pages, three pages, four pages. Look at all that code!
00:12:19.500 Yeah, it's as if the Ruby code was petite and easy to understand, while the C code was really big and clumsy. So what's going on under the covers?
00:12:42.900 Well, in the C code implementation on the left, we need to check that the connection is there, poll, and do a few other things, whereas in MRuby, it just works, as we know it!
00:13:02.580 Then we need to connect to the server via mDNS (Multicast DNS). In the C code, it needs a separate lookup, but in MRuby, it just works with MQTT. Easy as that!
00:13:34.320 Here we’re looking at some of the code used to send the keep-alive message every five seconds. Again, you can see in the left C code, there’s a lot more going on to copy the data into buffers just to concatenate strings.
00:14:08.720 As you can see, the MRuby code is much more familiar and accessible for Ruby developers, allowing more people to be involved in writing code for IoT and hardware projects.
00:14:43.240 Every project needs a server, right? We all know how to use CRuby and servers like Rails and Roda, so we knew this would be a piece of cake! Except when we’re dealing with an IoT device with limited capabilities that needs to communicate with a server requiring minimal communications.
00:15:07.360 One such protocol is MQTT (Message Queuing Telemetry Transport). That’s right; MQTT is a message broker allowing messages to be passed between various systems in a publish/subscribe style.
00:15:23.780 This means our client could talk to our actuator. We looked around and found Eclipse Mosquitto, which seemed to just work!
00:15:52.100 It worked so well we didn’t even need any server code at all. What? No CRuby? No! There’s plenty of other talks on CRuby at RubyKaigi, so we presumed it was okay to just go with Mosquitto and have no CRuby in our project.
00:16:14.740 And that brings us to the mobile client using JRuby. We started off with the assumption that it would be super easy on mobile devices, but boy were we in for a surprise!
00:16:38.060 We thought it would just work: you know, write some code, hit run, and voila! But it turns out building a mobile client with JRuby is not that straightforward.
00:17:02.920 We began by writing the client in plain old CRuby, and it worked! It listened to the MQTT server for actuators registering and allowed us to activate the actuators remotely.
00:17:30.160 Do you remember this demo from before? Everything’s all powered up. Which way are we going? This way? Probably the other way.
00:17:54.420 This is the demo from before. The lights are flashing. This is CRuby! If I go to the other side, the other light is flashing. Cool!
00:18:22.740 As you can see at the top, it's running Ruby 3.2.1 and that’s through our MQTT controlling the actuators.
00:18:49.260 But we really wanted to build the mobile client with JRuby. Since this is a presentation about the state of all Rubies, we thought we could just switch the example code over to JRuby.
00:19:12.380 But did it just work? No! Not at all. With a few tweaks and changes in the libraries we used, we managed to get a version running with JRuby.
00:19:45.080 If I now switch over to the other tab, was it command two? Yep! There we go! And we run. Well, you can see that Ruby version—there! That’s JRuby 9.4.2.0.
00:20:17.960 And if we run now, the client loads up the actuators register.
00:20:43.720 With this, we can't just use up and down arrows like we did before. If I press some keys, we get a hit to see one there. If I use J and K keys to move up and down, we get the other side! Whoa! JRuby wins!
00:21:42.740 But there was a client on a laptop, not exactly a mobile device that we were going for. That one’s out. We heard none of that! We heard about another option, though—Roberto!
00:22:12.340 That’s right! It was recommended to us at Rubicon in Thailand last year, and we were so excited to try it out! But when we went to the website... it was down! Ouch!
00:22:41.800 That didn’t stop us, though! We reached out to Charles Nutter, one of the contributors of Ruboto, and soon enough, the site was back up and running! We were all set to go, but when we tried to run Ruboto, we ran into incompatibility issues with the latest Android SDK.
00:23:09.700 It felt like an abandoned project since it hadn’t been worked on since 2019. But we kept looking. We scoured through conference videos and found some about Dragon Ruby and RubyMotion.
00:23:34.060 RubyMotion is a framework to build cross-platform apps for various UI environments like iOS, Android, and OS X in Ruby. It looked promising, and after a quick download, agreeing to some Android setup, and updating some Motion repo templates, we could finally create an Android project!
00:24:01.300 For running the project, it failed. We spent time chasing down versions for compatibility with ARM architectures on our MacBook Pro laptops, but to no avail.
00:24:29.520 Also, we believe RubyMotion is built on MRuby. Nothing against RubyMotion, but we needed our trifecta of CRuby, MRuby, and JRuby. RubyMotion just was not going to cut it.
00:24:56.820 So it was back to the drawing board. We looked in the App Store and found the iSH terminal app on mobile.
00:25:22.360 And sure enough, it successfully installed Ruby. That’s CRuby running its version command, displaying 2.7.8.
00:25:53.360 It was time to bring in JRuby. We successfully installed the OpenJDK and JRuby, although it took a while for the download and setup to complete. It was promising! That is, until we ran it, and even with 'jruby -v', we got a segmentation fault.
00:26:24.740 But we were desperate! So could the iSH emulator on an iPhone at least run our client card using CRuby? Let’s give that a try.
00:26:49.820 I think I go across to my iPhone, and if we open up iSH and connect to the Kickboxer LAN...
00:27:15.460 return... oh, that’s perfect control! We’re going to look for the CD to the last place I went...
00:27:37.140 So, up Arrow, up Arrow, run! This is an emulator running inside of iOS. It's waiting for actuators!
00:28:01.640 Problem finding Kickboxer LAN. This is great! I am not on the right network, am I? Let’s just give this a quick set...
00:28:20.920 So, let’s put some applause in there.
00:28:55.700 Right! Now if I go back to the iSH and run it again, hopefully now it’s connected, it’s waiting for these clients.
00:29:22.600 Press enter! Something flashing? No? That’s cool, they’re on! And if I go up, oh that’s right I have to enter, so pressing enter, there we go.
00:30:32.760 Do you want to go back to the presentation?
00:30:45.900 Oh yeah! So many things! We were on the right path. But is it JRuby? No! It's not!
00:31:08.640 It took us a while, searching in the App Store, but eventually, we found this—Rubiest!
00:31:37.500 Rubiest is a Ruby scripting platform that can run and automate Ruby code. So the first thing we tried was to require the MQTT library, and no method error! This feels like a bit of a non-starter.
00:31:58.900 Looking at the documentation, we see that there are Rubiest-specific methods and MRuby-specific methods. MRuby does not implement 'require', and Rubiest is clearly built on top of MRuby.
00:32:32.000 We were getting a little bit desperate at this point, so even though it was MRuby, how far was this thing going to take us?
00:33:09.000 Reading more, we did find out you could create widgets on the home screen, add Siri actions, and create automated shortcuts triggered by various events on the phone.
00:33:36.300 So, let's try this out. Hey Siri, run 'Hit Selena'.
00:34:10.900 Obviously, we didn’t get that to work, but it was a good try!
00:34:30.130 Writing some code in the editor was actually quite nice to use, especially on long flights to and from Australia and various conferences.
00:34:56.010 Very quickly, we found we could fetch a URL, parse some JSON, and design a simple UI. But although we could read and write TCP sockets, it was still a long way from calling MQTT.
00:35:22.520 Still, after running the code and agreeing to allow a network connection, we got a preview of the widget we could add to our home screen.
00:35:49.120 Assuming it all works well, sometimes you get a syntax error. But let's do a demo! So, if I scroll to the left, we see a Kickboxer Rubiest widget!
00:36:05.940 But it's just a widget! It only gets called once on render, and in this case, it can't have any interactions.
00:36:31.920 At that stage, there was no point in trying to build an interactive client with something that was just a widget.
00:36:51.480 And you know what? At the end of it all, it still wasn’t JRuby! We are clearly suckers for punishment, though!
00:37:12.000 So we looked for yet another option to get JRuby running. Yep, we finally made the switch to Android!
00:37:50.960 Like, I literally went out and bought a new Android phone at this point.
00:38:02.960 We thought if we could use the terminal on iPhone, surely we could do that on Android and get a better result.
00:38:24.320 We looked around on the app store, and there was a terminal app. Looking around, we found Termux—an Android terminal emulator and Linux environment app!
00:38:54.460 Another terminal app for your mobile phone, and it has running versions of CRuby, JRuby, and even MRuby! This is looking very promising!
00:39:11.460 Sure enough, it even ran our client! This is plain old CRuby, and this is JRuby! We’ve got our trifecta in Ruby on the ESP32: no CRuby, because we all know that works perfectly fine.
00:39:42.340 And we didn’t need it anyway! And JRuby on the mobile client! Whoa! Yes!
00:40:16.320 But even though it’s JRuby running on a mobile client, it’s still a terminal app—not really the touchscreen button style app we were hoping for.
00:40:36.940 As good as Termux is for running Ruby and JRuby, this isn’t quite right.
00:41:05.760 On to the next idea, by now things were getting really desperate.
00:41:26.240 If we couldn't find a way of running JRuby on an existing device, we thought maybe we’d need to build our own device!
00:41:52.040 We knew that the Raspberry Pi runs Java, so if we took a battery pack, taped on a Raspberry Pi with a Wi-Fi dongle, and attached a screen...
00:42:20.280 This is sounding like a viable plan! But making our own mobile device just to get JRuby running? I think that's going too far!
00:42:43.580 So we went back to thinking about how we could use Ruboto and Arduino together to create a client that could interact with MQTT. We knew it was a long shot, but we were determined to try!
00:43:14.960 So a few weeks ago, we were at RailsConf in Atlanta. There was a talk about JRuby to see if we could get some help moving forward with Ruboto.
00:43:46.700 I’m pretty sure Charles was stringing us along. He finally revealed some secrets we needed to install some pre-compiled APKs for Ruboto Core and Ruboto IRB, built back in 2015!
00:44:12.640 We got Ruboto IRB running with 'Hello World' and a basic UI. We actually got an Android project running with some of our own JRuby code!
00:44:38.200 That was on the train three days ago on our way rolling into Matsumoto. I don't think we have any time for more half-assed demos today.
00:45:04.240 Well, we did get a little bit of time at beer o'clock yesterday!
00:45:22.480 That’s right! Nothing like some BDD—Beer-Driven Development!
00:45:29.240 Charlie helped us debug a few permission issues and threading issues when using Android with JRuby.
00:45:54.820 Here he is! You can see him pressing the button on the app we wrote together, and you can see the blue light flashing. Success!
00:46:22.840 An Android app running JRuby, talking to a server and an actuator running the MRuby!
00:46:46.300 But we promised a kickboxing robot live on stage!
00:47:00.700 All right, I’ve got one more recording here.
00:47:41.960 So while we're setting up, I’m just going to show you that we do, in fact, have an app here, JRuby—it’s starting.
00:49:26.040 Look at that! Okay, some pool noodles on that robot!
00:49:41.100 If I press 'Kickboxer,' we're hoping for two actuators!
00:50:10.300 All right! We have one and two! I'm going to move that across and get Selena in position. Are you ready?
00:50:32.860 Are you ready? Alright! Oh, come on! You gotta duck!
00:51:03.500 It's slow!
00:51:27.440 Oh!
00:51:54.200 Alright, I think we got the live robot on stage!
00:52:48.640 Alright, so let’s recap what we’ve achieved so far.
00:53:01.760 We’ve successfully built the actuator using MRuby and it's connected to our MQTT messaging service.
00:53:29.540 We did manage to control it from a mobile client. We also did run various parts of Ruby on a whole lot of different platforms.
00:53:48.420 We ran some basic scripts on iSH, a terminal on an iPhone. We ran some Ruby scripts on Rubiest, a Ruby platform on iPhone to build out widgets, Siri commands, and shortcuts.
00:54:08.960 We ran both CRuby and JRuby on the Android terminal, Termux.
00:54:26.280 But there were a few things that didn’t work out.
00:54:41.220 Like actually managing to run Ruboto against the current Android SDK... Oh, that’s what we changed this morning because we got it running on the Android SDK!
00:54:59.850 Nothing like bedroom development! So the only thing that actually didn't work out...
00:55:19.760 No, nothing! Everything worked out!
00:55:34.650 I think I don’t think these actuators are running everything in MRuby just yet!
00:55:45.740 So there’s probably a little bit of work there to make MRuby work a little bit better.
00:56:03.020 Plus, as we said, that deployment pipeline we used was complicated!
00:56:22.730 Although, to be honest, we didn’t really give Dragon Ruby a fair go. There does seem to be a lot going on in the Dragon Ruby Game Toolkit, though!
00:56:52.020 Maybe we should just write a game next time! Speaking of next time, how can we top this for RubyKaigi 2024?
00:57:07.560 Well, we could always take our MRuby project to another Ruby level!
00:57:25.620 Being learning algorithms to assist the system to personalize the training experience for different users!
00:57:45.040 Or we could do what we set out to do, and figure out how to rewrite all that C code in Ruby, as we saw Ruby was way more accessible for writing and developing!
00:58:03.920 Our friends at Ruboto need some help! Maybe someone in the audience could help out with getting that project compatible with the Android SDK!
00:58:25.040 And it sounds like there's a lot going on in the MRuby and PicoRuby communities. It would be cool to get a better understanding of how to use MRuby for IoT development!
00:59:09.960 All in all, we're really excited about the potential of this project and can't wait to see where it goes next!
00:59:41.120 That's right! We hope we’ve inspired some of you to explore the possibilities of using Ruby and IoT projects.
00:59:58.800 From the B2B fresh food ordering platform Fresh, this is Selena Small!
01:00:16.600 [Laughs] And from the payments API, Zepto, I'm Michael Malevsky. Thank you very much!
01:00:53.840 Come back! You do have to stand back, I know! I don't want to be too big.
01:01:05.600 Oh, okay. All right, now going crazy! Oh, hang on... Thank you!