Building Simon with Angular2-IoT
One of the exciting things about Angular 2 is the push to make Angular code more than just the web. I thought it would be fun to explore the limits of this, and see if I could make the same control/logic code for both a web application and a physical, “Internet of Things (IoT)” device.
To do this, I built a “Simon” game:
Angular2-iot is an experimental project that explores how we can stretch the limits of Angular 2 to bring the same technology to new platforms. It’s a natural extension of the angular2-universal concept, which enables Angular code to run on the back end, allowing Angular to escape the web browser and become more “universal.”
In a nutshell, angular2-iot allows you to control and interface with physical hardware using Angular.
Angular 2 advocates a component-based model, where each component can receive input and emit events. With angular2-iot, instead of representing these components as html elements on screen, the components are wired to real hardware.
For example, you could have a push-button that emits a click event into your Angular code:
Button — Code Example
HTML with Angular2:
<button (click)=”clickHandler();>Click Me</button>
IoT with Angular2:
<iot-button pin=”10" (click)=”clickHandler”></iot-button>
Or an LED that receives input from Angular code (We don’t really have an LED analogue in HTML, so we can instead compare it with showing and hiding an image):
LED — Code Example
HTML with Angular 2:
<img src=”led.png” [hidden]=”!ledOn” />
IoT with Angular 2:
<iot-led pin=”9" [state]=”ledOn”></iot-led>
For a complete blinking LED code example check out: https://github.com/urish/angular2-iot/blob/master/examples/blink.ts
Because Angular2-iot uses the johnny-five library behind the scenes, it supports a large range of devices, such as Arduino, Raspberry pi, etc., right out of the box. Universal, right?
One major advantage of using Angular 2 to develop for physical devices is that it allows you to develop the game and/or prototype and test new features without the actual hardware. This means you can develop on your computer, using familiar tools and workflows, and then once you are happy with how it works, deploy it to the actual device. This also makes it easier for 3rd-party developers work on the code and send pull requests if they don’t have the actual hardware (e.g.: https://github.com/urish/ng2-simon/pull/1).
The ng2-simon game explores the possibility of reusing the same control/logic code for the web and for IoT devices. To do this, I built a “Simon,” repeat-after-me, game and deployed it to the web as well as a physical device. You can play the web version here: https://urish.github.io/ng2-simon/
ng2-simon was presented during ng-conf 2016, as part of the Science Fair. It was played more than 180 times throughout the conference, with top score of 18 points. For presenting the game, we created a custom tailored Simon game device using 3D printing, laser cutting and custom circuit design.
One of the surprising things I saw was how kids interacted with the game — most adults played alone and only 1 to 3 times, while some kids played repeatedly, playing multiple games in series, sometimes 15 minutes or more.The top score (18 points) was actually achieved by a 12-yo child who practiced and played for about 15 games. The kids also worked cooperatively, with several children playing together and trying to help each other get a good score.
The ng2-simon code is based off the angular-webpack-starter repo by AngularClass. We added a new webpack configuration for building the IoT variation of the code.
There are two entry points:
The game logic resides in src/app/simon/game.component.ts, and is common for the web and IoT version. It uses three helper components, which also reside in the same directory:
simon-blink— Displays the blinking “Click any color to start…” message on the Web version. Does nothing on IoT version.
simon-score— Displays the word “PLAY” before the game begins, and the game score during the game. This component uses the DSEG font for the web version to achieve a 7-segment display look, and delegates to the <iot-seven-segment> component on IoT version to display the value on the actual 7-segment display.
simon-segment— Combines a button and LED. The web version renders round buttons that can highlight with a given color (simulating physical LEDs), while the IoT version uses the
<iot-button>to communicate with the actual hardware. The class also defines the mapping between the colors and the hardware pins for the respective LEDs and buttons.
In addition, the game uses a service called
SynthService for synthesizing and playing the game sounds. The Web version is implemented using Web Audio API, while the IoT version delegates to two Linux command line tools: SoX for generating sounds, and mpg123 for playing mp3 files. Both variations extend the
SynthService class. We use the Angular 2 dependency injection mechanism to instantiate the right implementation of this interface on runtime.
One of the advantages of synthesizing the button sounds in runtime instead of using prerecoded values is that they can be easily changed by modifying the frequency values on the top of the game.component.ts file. You can also modify the timbre of the sounds by modifying the oscillator waveform type (e.g., change
osc.type in WebSynthService from “sawtooth” to “sine” to make it the sound softer).
To make the game more interesting, we also displayed a leaderboard on a TV next to the game. At the conference, we split participants into four groups, by putting colored stickers on their name badges, and displayed the top score and avg. score for each of the games. The Leaderboard was another Angular 2 app, and we used Firebase for the score collection and communication.
Source code for the Leaderboard:
How We Built It: Coming Soon
In part 2, I’ll go into the hardware we gathered, built, and assembled into the final game. I’ll also go over how to deploy the angular2-iot code to the device and get everything going.