Software Architecture Overview

This page discusses the software architecture of the system. If you are trying to understand the implementation of the software, this page is a good starting place. If you are just trying to _use_ the system, check out Reflect Array User Guide. If you trying to use the data produced by the system, you may want the Moment Data Format page.

Design Principles

The goal when developing the software was to create loosely coupled components that communicate via well-defined interfaces. In order to accomplish this, the software is comprised of numerous processes, each of which is responsible for a well-defined task and which communicate with each other using a request-response approach. The scripts wni.scripts.pcpm and wni.scripts.uzpm are responsible for starting all the various processes, and the documentation of those modules describes what each process is responsible for. Each process is generally doing one thing: for example, one process controls the motor, and requests are made to that process for getting the motor’s position or asking it to move. The benefit here is that one process keeps track of one piece of hardware’s state, and other proceses communicate with that process and do not need to worry about tracking the state of the hardware.

One benefit to the modular approach is that it is theoretically straightforward to re-implement pieces of the system in different languages if it is found that there are performance issues or another language is desired for any other reason. In fact, two processes that were originally written in Python were re-written in C after it became apparent that they were critical performance bottlenecks.

Security Considerations

All the processes that are started on the radar listen on internal IP addresses, so there is no way to access them before SSHing into the radar. The radar is protected by strong passwords and uses fail2ban to disallow persistent brute-force attacks onto the computer. Additionally, the ssh server is listening on a non-standard port so that it will be less susceptible to non-directed attacks. It is assumed that only trusted users are allowed to log in to the radar, so access to the computer running the radar gives access to everything the radar can do; there is no user-level restrictions once a user is logged in. The only known issue is that the system is theoretically vulnerable to a denial of service attack from too many clients requesting the radar moment data.

Notable External Libraries

Two external libraries are used extensively in this system: NanoMsg and MessagePack The most notable use of these libraries in this code base is that the data that is made available publicly serializes data using MsgPack and sends it with NanoMsg.

NanoMsg

NanoMsg provides nice ways of doing communication between running processes using what it calls “scalability protocols”, which are implementations for common patterns of communication, e.g. request/response, publish/subscribe, and others. NanoMsg was selected because it is lightweight, easy to use, and can be used in many different programming languages. It is an alternative to ZeroMQ.

MessagePack

MessagePack is small, efficient library for serializing and deserializing data. It is similar to JSON, except it is smaller, faster, and suitable for transmitting binary data. The drawbacks compared to JSON is that it is not human-readable and it is not supported in quite as many languages. However, it is still very widely supported.

NanoClient and NanoServer

All of the processes that run in this system that control a piece of hardware open a NanoMsg socket and listen for requests using an instance of wni.util.NanoServer. The requests are serialized and deserialized using MsgPack. Some functionality of NanoClient has also been implemented in C so that the processes written in C can make requests to processes written in Python. The NanoServer and NanoClient are significant to the modularity of the system: they are how all hardware is controlled and how all information is communicated. They also allow for modularity: it would be relatively straightforward to write implementations for NanoClient and NanoServer in different languages if the language had bindings for MessagePack and NanoMsg.

User Interface Decisions

We decided to create the user interface using a Jupyter Notebook. Perhaps the largest advantage of this approach is that the user of the system does not need to install any software on their computer as long as they have a browser installed. The largest disadvantage is that there is no protection from multiple users logging in and making changes at the same time, so a team must communicate about who does what and when. The UI instantiates several NanoClient instances to control the various system hardware.

Environment Variables

The software makes extensive use of environment variables so that various processes that are running can all know the same information. The NanoMsg addresses used by the various server processes are given via environment variables. All the environment variables are defined in the software repository in the file sw/scripts/default_env.sh and sw/scripts/ip_addresses.sh. These files should be sourced by your shell before the software is run. There is no reason to change the environment variables yourself unless there is a port conflict. Remember that if you change the variables you need to change them on the MicroZed and the processing computer.