I’ve been working on an Angular project that uses remote IOT sensors for scientific research. A tiny Linux server running on a single chip computer — the Intel Edison — serves the Angular web app for users to control and log data from the remote IOT sensor. We could have used node.js, but we already had code in .NET from another application. So, we ported the backend part of the server from .NET in Windows to Mono with minimal effort.
There are three main tiers to the project,
- The web app in Angular for user interface and data visualization
- The backend in C# with Mono on Linux, and
- A thin C++ layer for hardware integration
The beautiful thing is that these are all cross-platform. Only the C++ layer is specific to the Linux distribution and BSP (board support platform). But even this layer was implemented with libmraa, so it works on many platforms.
Main Function of the App
To provide a responsive user interface that allows users to easily configure the sensor and to download data logs. The device is usually installed remotely, far from the internet, so users approach the sensor and connect to its Wi-Fi hotspot to interact with it.
We started with a prototype C++ service running on Linux that listened to serial ports, connected to the internal sensor, and had a simple web server serving basic 1998 style web pages that allowed the download of the logs.
What we wanted was a premium user experience with expanded functionality to allow complete control of the remote device, and to integrate more hardware features (LED indicators, and battery-level tracking).
While sending single character commands to the sensor was easy for our app to do, interpreting the responses was a bit trickier. We had a Windows desktop application that could be ported to do this.
The Windows application was well-structured so we could replace the view layer with Nancy FX, a web service, that handled REST commands and streamed data to the clients via WebSockets. It also spoke to the C++ layer via TCP sockets for interacting with the hardware. The port to Mono went incredibly smoothly, and it was easy to install on the Edison. There were a few incompatibilities, mostly syntactic sugar that had to be regressed.
The application is pretty complex, so we wanted a snappy iterative process on the user experience design. Angular’s ability to create the code in a highly organized manner with components and services that could be re-used in different configurations was key to doing this. The app has 5 pages and over 60 custom components. The special graphs and data visualizations fit naturally into Angular components.
We needed to do some pretty fancy visualization for this scientific data. Even d3.js couldn’t make the kind of graph we needed. So, we made it from scratch, drawing directly to the canvas. The nice thing about this, at least, was that instead of having an all-singing-all-dancing library, we could keep it small and optimized. Performance is essential as data is coming fast.
Performance was surprisingly good; 12 traces are drawing at least 4Hz with a geographical plot running at 10hz.
Angular gave us a fabulous user interface that has evolved significantly. It’s allowed us to try out different designs quickly, and keep a well-structured app as features were added. It’s a great tool for embedded systems for the Internet of Things. This was a fascinating project with many layers, and interesting problems. Let me know if you’d like to hear a blog going deeper into one of the issues dealt with in this blog. I’d be happy to expand on it.