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.