-\section{Overview \& Terminology}
-The goal of the architecture is to facilitate an ecosystem in which an
+The goal of the total system is to facilitate an ecosystem in which an
\gls{iTasks}-system can add, change and remove devices at runtime. Moreover,
the \gls{iTasks}-system can send \glspl{mTask} --- compiled at runtime to
-bytecode --- to the device. The device runs an interpreter which can execute
-the \gls{Task}'s bytecode. Devices are persistent during reboots of the
-\gls{iTasks}-system. The methods of interacting with \glspl{mTask} is analogous
-to interacting with \gls{iTasks}-\glspl{Task} and programmers can access the
-\glspl{SDS} made for a device in the same way as a regular \glspl{SDS}. The
-following terms will be used throughout the architecture description.
-
+bytecode by the \gls{mTask}-view --- to the device. The device runs an
+interpreter which can execute the \gls{Task}'s bytecode. Device profiles should
+be persistent during reboots of the \gls{iTasks}-system. The methods of
+interacting with \glspl{mTask} should be analogous to interacting with
+\gls{iTasks}-\glspl{Task}. Meaning that programmers can access the \glspl{SDS}
+made for a device in the same way as a regular \gls{SDS} and they can execute
+\glspl{mTask} as if it where a normal \gls{iTasks}-\gls{Task}.
+
+The following terms will be used throughout the following chapter:
\begin{itemize}
\item Device, Client
- This is the actual device connected to the system. This can be a real
- device such as a microcontroller but it can also just be a program on
- the same machine as the server.
+ This denotes the actual device connected to the system. This can be a
+ real device such as a microcontroller but it can also just be a program
+ on the same machine as the server functioning as a client.
\item Server, \gls{iTasks}-System
- The actual executable serving the \gls{iTasks} application. The system
- will contain \glspl{Task} taking care of the communication with the
+ This is the actual executable serving the \gls{iTasks} application. The
+ system contains \glspl{Task} taking care of the communication with the
clients.
\item System
- The complete ecosystem, thus containing both the server and client
- programs.
+ The system describes the complete ecosystem, containing both the server
+ and the clients including the communication between them.
\item Engine
- The runtime system of the client. This program handles the
- communication with the server and interprets the \glspl{Task}.
+ The runtime system of the client is called the engine. This program
+ handles communicating with the server and runs the interpreter for the
+ \glspl{Task} on the client.
\end{itemize}
\section{Devices}
-The engine for the devices is compiled from one codebase. For a device to
-be eligible for \glspl{mTask}, it must be able to compile the shared codebase
-and implement (part of) the device specific interface. The shared codebase only
-uses standard \gls{C} and no special libraries or tricks are used. Therefore
-the code is compilable for almost any device or system. Note that it is not
-needed to implement a full interface. The full interface --- excluding the
-device specific settings --- is listed in Appendix~\ref{app:device-interface}.
-The interface works in a similar fashion as the \gls{EDSL}. Devices do not have
-to implement all functionality, this is analogous to the fact that views do not
-have to implement all type classes in the \gls{EDSL}. When the device connects
-for the first time with a server the specifications of what is implemented is
+A device is suitable for the system if it can run the engine.
+The engine is compiled from one codebase and devices implement (part of) the
+device specific interface. The shared codebase only uses standard \gls{C} and
+no special libraries or tricks are used. Therefore, the code is compilable for
+almost any device or system. Note that it is not needed to implement a full
+interface. The full interface --- excluding the device specific settings --- is
+listed in Appendix~\ref{app:device-interface}. The interface works in a
+similar fashion as the \gls{EDSL}. Devices do not have to implement all
+functionality, this is analogous to the fact that views do not have to
+implement all type classes in the \gls{EDSL}. When the device connects for the
+first time with a server the specifications of what is implemented is
communicated.
At the time of writing the following device families are supported and can run
the device software.
\begin{itemize}
- \item \texttt{POSIX} compatible systems
+ \item \texttt{POSIX} compatible systems connected via \gls{TCP}.
This includes systems running \emph{Linux} and \emph{MacOS}.
- \item \texttt{STM32} family microcontrollers supported by \texttt{ChibiOS}.
+ \item \texttt{STM32} family microcontrollers supported by \texttt{ChibiOS}
+ connected via serial communication.
This is tested in particular on the \texttt{STM32f7x} series \gls{ARM}
development board.
- \item Microcontrollers who are programmable in the \gls{Arduino} \gls{IDE}.\\
+ \item Microcontrollers who are programmable in the \gls{Arduino} \gls{IDE}
+ connected via serial communication or via \gls{TCP} over WiFi.
This does not only include \gls{Arduino} compatible boards but also
- other boards capable of running \gls{Arduino} code. The code
- has been found working on the \texttt{ESP8266} powered \emph{NodeMCU}.
- It is tested on devices as small as the regular \gls{Arduino}
- \emph{UNO} board that only boasts a meager \emph{2K} of \emph{RAM}.
+ other boards capable of running \gls{Arduino} code. A port of the
+ client has been made for the \texttt{ESP8266} powered \emph{NodeMCU}
+ that is connected via \gls{TCP} over WiFi. A port also has been made
+ for the regular \gls{Arduino} \emph{UNO} board which only boasts a
+ meager \emph{2K} of \emph{RAM}. The stack size and storage for such
+ small amount of \emph{RAM} have to be smaller than default but it still
+ suitable to hold a hand full of \glspl{Task}.
\end{itemize}
-\subsection{Interpreter}
-\todo{Structuur}
-The client contains an interpreter to execute a \gls{Task}'s bytecode.
+\subsection{Client}
+\subsubsection*{Engine}
+The client is in a constant loop listening for input and waiting to execute
+\gls{Task}. The pseudocode for this is shown in Algorithm~\ref{alg:client}.
+
+\todo{make algorithm}
+\begin{algorithm}[H]
+ \KwData{\textbf{stack} stack, \textbf{time} $t, t_p$}
+
+ $t\leftarrow\text{now}()$\;
+ \Begin{
+ \While{true}{
+ $t_p\leftarrow t$\;
+ $t\leftarrow\text{now}()$\;
+ \If{notEmpty$($queue$)$}{
+ $task\leftarrow \text{queue.pop}()$\;
+ $task$.wait $\leftarrow task$.wait $-(t-t_p)$\;
+ \eIf{$task.wait>t_0$}{
+ queue.append$(task)$\;
+ }{
+ run\_task$(task)$\;
+ }
+ }
+ }
+ }
+ \caption{Engine pseudocode}\label{alg:client}
+\end{algorithm}
+
+\subsubsection*{Storage}
+\glspl{Task} and \glspl{SDS} are stored on the client in one big memory space
+that is fully allocated at the start of the program. The space could also have
+been dynamically allocated but that would require using the heap which is
+unwanted in small memory environments. \Glspl{Task} grow from the bottom up
+and \glspl{SDS} grow from the top down. When a \gls{Task} or \gls{SDS} is
+removed, all \glspl{Task} are relocated in the memory space to not leave
+holes. Both \glspl{Task} and \glspl{SDS} are stored as structs and helper
+functions are available to loop through them without having to fiddle in the
+memory space. The instance for \glspl{Task} and \glspl{SDS} are shown in
+Listing~\ref{lst:structs} accompanied by the helper functions for \glspl{Task}.
+\Glspl{Task} consist the length, interval, last run time, id and the bytecode.
+\Glspl{SDS} consist just of an id, value and type. The pointer to the bytecode
+of the \gls{Task} always points to the location in the memory space.
+
+\begin{lstlisting}[language=C,label={lst:structs},%
+ caption={The data type storing the \glspl{Task}}]
+struct task {
+ uint16_t tasklength;
+ uint16_t interval;
+ unsigned long lastrun;
+ uint8_t taskid;
+ uint8_t *bc;
+};
+
+struct task *task_head(void);
+struct task *task_next(struct task *t);
+
+struct sds {
+ int id;
+ int value;
+ char type;
+};
+
+struct sds *sds_head(void);
+struct sds *sds_next(struct sds *s);
+\end{lstlisting}
-Before execution some preparatory work is done. The stack will be initialized
-and the program counter and stack pointer are set to zero and the bottom
-respectively. Then, the interpreter executes one step at the time while the
-program counter is smaller than the program length. The code for this is listed
-in Listing~\ref{lst:interpr}. One execution step is basically a big switch
+\subsubsection*{Interpretation}
+Execution of a \gls{Task} always start with prepared the stack and the program
+counter and stack pointer are set to zero and the bottom respectively. When
+finished, the interpreter executes one step at the time while the program
+counter is smaller than the program length. The code for this is listed in
+Listing~\ref{lst:interpr}. One execution step is basically a big switch
statement going over all possible bytecode instructions. Some instructions are
detailed upon in the listing. The \CI{BCPush} instruction is a little more
-complicated in real life because some decoding will take place as not all
-\CI{BCValue}'s are of the same length.
+complicated in the real code because some decoding will take place as not all
+\CI{BCValue}'s are of the same length and are encoded.
\begin{lstlisting}[language=C,label={lst:interpr},%
caption={Rough code outline for interpretation}]