The aim of the project is to build a remote system capable of aspects of Command, Control, Communications, Computers, Intelligence, Surveillance and Reconnaissance (C4ISR) of a home facility.
My family has a beach house, and unfortunately for us it's not possible to be there every day and time, but we like to have the things secure and organized, and we try to have some degree of monitoring and control in order to keep the place safe when we are there or when we are not there. Also we try to take our pets with us as always as we can, and in very hot days it is good to know if the water levels are ok, if their room has adequate temperature, if the food is near to finish or even if the food feeder has a malfunction (it was the origin of the project's name). Knowing these things allows us to take measures, and sometimes we require fast actions which could be better provided with an automatic and/or remote controller. So, first we got a permanent internet connection, some IP cameras installed, made after some reports made by a Raspberry Pi, and the project gave birth with some new ideas, and evolved.
Regarding the amount of possibilities the project has, it is intended to keep as simple as possible to be fast deployed, and some funcions will be kept out from scope or will be kept in our further improvements list. For example, we actually do not need to control the IP cameras Pan/Tilt motors, so it will be out of scope.
The project is implemented in two modules with a client-server architecture using Sockets to provide the communication between them. The first module
MOD_RPI is a Ada application running in a Raspberry Pi 1B+ from Raspbian OS, responsible for the embedded tasks. This is the remote system. The second module
MOD_WIN is also an Ada application, now running on a Windows 10 machine, with a Control Room HMI submodule. Other applications made in another languages could also be included, as a report generator and e-mail sender made in Bash script from Raspberry Pi. In the present state, the project is composed solely by the sofware design and development, testbenched with a Raspberry Pi, a laptop and an oscilloscope.
The project was developed entirely from scratch without the use of 3rd-party libraries. The only libraries used were available in the GNAT compiler package. The Sockets framework was based on an example from GNAT.Sockets documentation.
Finally, DogRobot project is licensed under GNU General Public License v3.0, and the source code is available from GitHub repository and managed by DogRobot GitHub Issue Tracking System.System Rationality
-  Why Raspberry Pi.The choices were Among Texas Tiva ARM Cortex M4, Arduino Uno, Arduino Mega, or Raspberry Pi. - For the
Atmel's Arduinofamily, a couple of years ago I wrote a paper in Ada Users Journal about how to use with Ada (take a look if you are interested Integrating 8-bit AVR Micro-Controllers in Ada) for them, so it would be piece of cake. But it certainly would lack hardware resources, memory, the Ada run-time is ZFP thus I could not use tasking features, the wifi/Ethernet would have to external. So, not a good choice, at least for this project;- The
Texas Tiva ARM Cortex M4is an amazing board which I am very close while implementing an UAV station some time ago. It would lack some hardware gadgets, the Ethernet module is not integrated for example. But I bet it could be an excelent choice because it is really powerful. Regarding the Ada part, check it out the article Ada and SPARK on ARM Cortex-M (thanks M. Sobczak) and the GitHub cortex-gnat-rts (thanks S. Wright), they would be a very good help for sure. Well, but Tiva was not the chosen board.- Finally, I had a free
Raspberry Pi 1B+. No doubt it is a great board. Certainly the integrated Ethernet (I will probably add an external Wifi bundle, so it's just a Linux setup) would spare me a couple of hours configuring the Ethernet modules. Also, Raspbian OS has a GNAT 6.3.0 available in apt-get, so I can build the code from command line, upload the same code using svn or git and obviouly use all Linux facilities into the project. And Ada is all there, multi tasking, exception handling, I really can't see limitations. Finally I can also switch over between making low priorities tasks by using sysfs, and running top-priority tasks from memory-mapped objects. In short, this is the chosen one because I can begin to make the end application in a very short time. Currently there is only a sysfs implementation, but the possibilities are open.
-  Why Ada.First, Ada has several built-in features which enables to make Safety-Critical software inherently to the application. Also, it makes easier to develop contract models, there is the tasking models set, it is strong typing. Thought I will not start a discussion here on all Ada features. Other choices would be C++ (I actually started this project by testing some RPi timing features in C++), Python which is almost native in RPi, but I think making it in Ada would be more fun.
-  Why Sockets.The choices were: Named Pipes, shared memory, REST, and Sockets.
Shared memorywould be the faster to communicate between each module, I would have to implement some ssh library to make the remote communication; it would be interesting I think, but I will reserve to the next home project.
RESTcould be a good choice too, but I actually didn't even try for this project.
Named Pipeswas the first choice (probably I would use this if the project would be done in C++), but I could not find a suitable ready-to-use Ada library, and I really wouldn't want to reinvent the wheels. And I probably would have to implement the network communication part. Finally,
Socketslooked the most suitable tech, because it would solve the communication problem need between modules, and also would solve the remote network communication requirement. And GNAT.Sockets is a built-in Ada library with all I need to integrate this.
Fig. 1 shows the system overview. The Windows and the Raspberry Pi components are the systems representing the MOD_WIN and MOD_RPI respectively. The External Devices component represents the array of relays and current drivers attached to the Raspberry Pi boards which will provide environmental actuation and monitoring.
Thus, the entire system is composed by a dual MOD_WIN and MOD_RPI end-to-end open Datagram Sockets application communicating from Internet.
The basic application framework is prepared to control the activation state of 3 digital outputs, read the state of those 3 digital outputs plus 2 digital inputs, control a PWM pin and read measurements from 2 analogs. In the current implementation state, the application is capable of handling the 3 digital outputs, and the lasting features are available as provision.Software Architecture
Fig. 2 shows a Composition Diagram for the system. Despite of UML does not have an specific diagram for representing packages, a such diagram may be usefull for expressing Ada packages because of the inherent Oriented Objects characteristics of those packages. In the figure, the subsystems packages are represented in blue, their direct children in a slightly graduated blue, and the second-level children in a stronger graduating blue. The main application is represented in a marked box, and the aggregated tasks are represented in blue.
The presented packages are given the following responsibilites:
COMM: Responsible for the communication modules.
COMM.CODING: Responsible for encoding and decoding features of the communication protocol, as string from/to command types.
COMM.PROCESS: Responsible for the management of input messages decodification, and the output buffering commands.
COMM.SOCKETS: Implements the sockets layers for the client/server application. Contains the Socket Manager task.
CORE: Responsible for the high-level functions.
CORE.BUFFER: Responsible for buffering of commands to be executable.
CORE.UI: Responsible for handling the User Interfaces. The Basic UI task is contained in this package.
DEVS: Responsible for low-level devices configuration and management.
DEVS.SYSFS: Responsible for SYSFS setups and management.
DEVS.SYSFS.STATIC: Database of static objects for DEVS.SYSFS.
DOGROBOT: Contains the main application.
TESTS: To include tests and use cases.
UTILS: Set of utility functions.
Both MOD_WIN and MOD_RPI projects are comprised in the same GNAT GPS project dogrobot.gpr. The specific code from each module is segregated by the use of compilation directives, and the builder is already configured to construct the proper main application executable for each one of those systems. In short,
- Project dogrobot.gpr with the proper MOD_WIN will generate executable client_win.exe when build in Windows from GNAT Programming Studio.
- Project dogrobot.gpr with the proper MOD_RPI will generate executable server_rpi when build in Raspbian OS from the Raspberry Pi SSH command-line. In addition, the bash script build-run_rpi is provided as aid to executable generation.
This is a very practical way of handling segregating-related projects, since we do not need to manage different GPS files for both projects.MOD_RPI and MOD_WIN Application Aspects
Main MOD_RPIApplication : The MOD_RPI main application is built in
bin/server_rpi. On the Raspbian command-line, it has to run with sudo privileges, because it makes high privileges access from sysfs devices. The application runs on a continuous loop and may inform the user from the ssh terminal of reception of messages or event messages. But no further action is required besides the command-line invocation.
Main MOD_WIN Application : Currently the MOD_WIN main application is controlled by direct input/output response provided by the command-line terminal. No administrative privileges on Windows are needed. In present state, the system will ask the user which information should be provided, or which action should be accomplished, take action, and report the results.Typical Execution Scenario
- Both applications are started. In Raspberry, server_rpi is run with sudo privilege. In Windows, client_win.exe is also running. At initialization, some messages are presented to show success of configuration of devices. Also, an initial message is sent from client_win to server_rpi in order to check the connection is ready.
- Fig. 3 shows a typical execution terminal from Raspbian SSH.
- Fig. 4 shows a typical execution terminal from Windows.
- Finally, Fig.5 shows a Sequence Diagram for a request/response exchange of messages.
- After both main applications are running, the main task from client_win activates both its tasks Basic UI, and Socket Manager. The main task from server_rpi activates the MOD_RPI Socket Manager task. In this case, Basic UI is not activated for MOD_RPI.
- In MOD_WIN, the Basic UI task waits for an user input so this will trigger a command to be put in the buffer of commands and processed by the Socket Manager lists. After processed, the command is sent to Sockets channel as a request. The task will also wait for a response, which will be processed after validation.
- In MOD_RPI, the Socket Manager waits for incoming messages. When a message arrives, it is validated and processed. The response is also sent back to Sockets channel.
The Communication Protocol is composed of 1 type of message to be exchanged from the Sockets channels.
Fig. 6 details the protocol. For a message to be parsed to devices mechanisms, it has to begin with a char "#", and finish with a string "/#". These fields are identified by the Header and the Footer.
Id_Type specificationThe field Id identifies the subsystem related to the message.
## System Devices, reserved for ping, status and acknoledgement SYSTEM_RPI SYSTEM_WIN ## Output Device drivers DEVICE_OUT_LAMP0 DEVICE_OUT_LAMP1 DEVICE_OUT_LAMP2 DEVICE_OUT_MOTOR0 ## Input Device Drivers DEVICE_IN_CHECKFLAG0 DEVICE_IN_CHECKFLAG1 DEVICE_IN_ANALOG0 DEVICE_IN_ANALOG1
Category_Type specificationThe Category field identities the nature of the message.
Message Parsing Sequence1. After receiving the message container, check the its size.2. If one size matches, validate the first char, and the last 2 chars with header and footer.3. If validation is ok, proceed with activation protocol.4. The message handler is then segregated according to each category. Typically REQUEST messages are sent from MOD_WIN to MOD_RPI, and RESPONSE messages are sent from MOD_RPI to MOD_WIN.Implementation Aspects
Fig. 7 shows the Call Tree generated from MOD_WIN code. The MOD_RPI is similar. The purpose of showing this is to recall the implementation difficulty of this project, and to illustrate the effort in designing and developing it. An very good point is, despite of the implementation complexy, the project may considered to be low-risk as its average cyclomatic complexity is far below 10 as observed by those metrics below generated by GPS.
Some metrics regarding the project
Practical DemonstrationFurther Improvements
Line metrics summed over 22 units all lines : 1312 code lines : 860 comment lines : 191 end-of-line comments : 7 comment percentage : 18.83 blank lines : 261 Average lines in body: 22.65 Average cyclomatic complexity: 3.54
- Implement end-activation state for the provision features.
- Include a new data container in the communication protocol to split decisions for ask/response and supply/response mechanisms.
- Provide a graphical interface to respond as the control center.