The goal of the system as a whole is to offer a framework of functions with
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 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}. This means that programmers can access the
\glspl{SDS} made for a device in the same way as regular \glspl{SDS} and they
can execute \gls{mTask}-\glspl{Task} as if they where normal
\gls{iTasks}-\glspl{Task}.

The following terms will be used throughout the following chapter:
\begin{itemize}
	\item Device, Client

		These terms 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

		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 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 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}
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 with
the server for the first time, 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 connected via the \gls{TCP}.

		This includes systems running \emph{Linux} and \emph{MacOS}.
	\item The \texttt{STM32} microcontrollers family supported by
		\texttt{ChibiOS} connected via serial communication.

		This is tested in particular on the \texttt{STM32f7x} series \gls{ARM}
		development board.
	\item Microcontrollers which are programmable in the \gls{Arduino} \gls{IDE}
		connected via serial communication or via \gls{TCP} over WiFi or
		ethernet.

		This does not only include \gls{Arduino} compatible boards but also
		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} \emph{RAM}. The stack size and storage available for
		devices boasting this little \emph{RAM} has to be smaller than default
		but are still suitable to hold a hand full of \glspl{Task}.
\end{itemize}

\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}. The
\CI{input\_available} function waits for input, but has a timeout set which can
be interrupted. The timeout of the function determines the amount of loops per
time interval and is a parameter that can be set during compilation for a
device.

\begin{algorithm}[H]
	\KwData{
		\textbf{list} $tasks$,
		\textbf{time} $t$
	}

	\Begin{
		\While{true}{
			\If{input\_available$()$}{
				receive\_data()\;
			}

			$t\leftarrow \text{now}()$\;
			\ForEach{$t\leftarrow tasks$}{
				\uIf{is\_interrupt$(t)$ \textbf{and} had\_interrupt$(t)$}{
					run\_task$(t)$\;
				}
				\ElseIf{$t-t.\text{lastrun} > t.\text{interval}$}{
					run\_task$(t)$\;
					\uIf{$t.\text{interval}==0$}{
						delete\_task$(t)$\;
					}\Else{
						$t.\text{lastrun}\leftarrow t$\;
					}
				}
			}
		}
	}
	\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 reserved 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} residing in higher areas of the memory are relocated in the
memory space to not leave holes. Both \glspl{Task} and \glspl{SDS} are stored
as structures that are linked in the memory space, helper functions are
available to loop through them without having to fiddle in the memory space
itself. The instances for \glspl{Task} and \glspl{SDS} are shown in
Listing~\ref{lst:structs} accompanied by the helper functions for \glspl{Task}.
\Glspl{Task} consists of the length, interval, last run time, id and the
bytecode. \Glspl{SDS} consist only 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}

\subsubsection{Interpretation}
The execution of a \gls{Task} is started by running the \CI{run\_task} function
and always starts with setting the program counter and stack
pointer 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. This code is listed in Listing~\ref{lst:interpr}. One
execution step is basically a big switch statement going over all possible
bytecode instructions. Of some instructions, the implementations are shown in
the listing. The \CI{BCPush} instruction is a little more 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}]
#define f16(p) program[pc]*265+program[pc+1]

void run_task(struct task *t){
	uint8_t *program = t->bc;
	int plen = t->tasklength;
	int pc = 0;
	int sp = 0;
	while(pc < plen){
		switch(program[pc++]){
		case BCNOP:
			break;
		case BCPUSH:
			stack[sp++] = pc++ //Simplified
			break;
		case BCPOP:
			sp--;
			break;
		case BCSDSSTORE:
			sds_store(f16(pc), stack[--sp]);
			pc+=2;
			break;
		// ...
		case BCADD: trace("add");
			stack[sp-2] = stack[sp-2] + stack[sp-1];
			sp -= 1;
			break;
		// ...
		case BCJMPT: trace("jmpt to %d", program[pc]);
			pc = stack[--sp] ? program[pc]-1 : pc+1;
			break;
}
\end{lstlisting}

\subsection{Specification}
The server stores a description for every device available in a record type.
From the macro settings in the interface file, a profile is created that
describes the specification of the device. When the connection between the
server and a client is established, the server will send a request for
specification. The client serializes its specification and send it to the
server so that the server knows what the client is capable of.  The exact
specification is shown in Listing~\ref{lst:devicespec} and stores the
peripheral availability, the memory available for storing \glspl{Task} and
\glspl{SDS} and the size of the stack.

\begin{lstlisting}[label={lst:devicespec},
	caption={Device specification for \glspl{mTask}}]
:: MTaskDeviceSpec =
	{ haveLed     :: Bool
	, haveLCD     :: Bool
	, have...
	, bytesMemory :: Int
	, stackSize   :: Int
	, aPins       :: Int
	, dPins       :: Int
	}
\end{lstlisting}

\section{iTasks}
The server part of the system is written in \gls{iTasks}. Functions for
managing devices, \glspl{Task} and \glspl{SDS} have been created to support the
functionality. An interactive web application has been created that provides an
interactive management console for the \gls{mTask} system. This interface
provides functionality to list \glspl{SDS}, add and remove \glspl{Task},
administrate devices and view the state of the system.

\subsection{Device Storage}
Everything that a device encompasses is stored in the \CI{MTaskDevice} record
type. This includes management for the \glspl{SDS} and \glspl{Task} stored on
the device. The \CI{MTaskDevice} definition is shown in
Listing~\ref{lst:mtaskdevice} accompanied with the necessary classes and sub
types.

\begin{lstlisting}[caption={Device type},label={lst:mtaskdevice}]
:: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool)
:: BCState = ... // Compiler state, explained in later sections
:: MTaskResource
	= TCPDevice TCPSettings
	| SerialDevice TTYSettings
	| ...
:: MTaskDevice =
		{ deviceTask :: Maybe TaskId
		, deviceError :: Maybe String
		, deviceChannels :: String
		, deviceName :: String
		, deviceState :: BCState
		, deviceTasks :: [MTaskTask]
		, deviceData :: MTaskResource
		, deviceSpec :: Maybe MTaskDeviceSpec
		, deviceShares :: [MTaskShare]
	}

channels :: MTaskDevice -> Shared Channels

class MTaskDuplex a where
	synFun :: a (Shared Channels) -> Task ()
\end{lstlisting}

The \CI{deviceResource} component of the record must implement the
\CI{MTaskDuplex} interface that provides a function that launches a \gls{Task}
used for synchronizing the channels. The \CI{deviceTask} stores the
\gls{Task}-id for this \gls{Task} when active so that it can be checked upon.
This top-level task has the duty to report exceptions and errors as they are
thrown by setting the \CI{deviceError} field. All communication goes via these
channels. To send a message to the device, the system just puts it
in the channels. Messages sent from the client to the server are also placed
in there. In the case of the \gls{TCP} device type, the \gls{Task} is just a
simple wrapper around the existing \CI{tcpconnect} function in \gls{iTasks}. In
case of a device connected by a serial connection, it uses the newly developed
serial port library of \gls{Clean}\footnote{\url{%
https://gitlab.science.ru.nl/mlubbers/CleanSerial}}.

Besides all the communication information, the record also keeps track of the
\glspl{Task} currently on the device, the compiler state (see
Section~\ref{sec:compiler}) and the according \glspl{SDS}. Finally, it stores
the specification of the device that is received when connecting. All of this
is given in Listing~\ref{lst:mtaskdevice}. The definitions of the message
format are explained in the following section.

\subsection{Shares}
The system keeps track of the \glspl{SDS} stored on
the client in a big \gls{SDS} containing a list of devices. Client-\glspl{SDS}
can be stored on one device at the same time. This means that if a \gls{SDS}
updates, everyone watching it will be notified. This would result in a lot
of notifications that are not meant for the watcher. Moreover, when a client
updates the \gls{SDS} this is processed by the connection handler and results
in an update of the real \gls{SDS}. Finally, the \gls{SDS} of a client must be
synchronized with the actual device. Thus, when an \gls{iTasks}-\gls{Task}
writes the client-\gls{SDS}, it must be propagated to the real device. There
are several ways of tackling this problem each with their own level of
granularity.

First an actual \gls{iTasks}-\gls{SDS} for every \gls{SDS} used in a client can
be instantiated with one \gls{iTasks}-\gls{Task} listening to the \gls{SDS} and
synchronizing it with the device when an update occurred. This approach is very
expensive as it requires a lot of listening \glspl{Task}.

Improved on this, a single \gls{iTasks}-\gls{SDS} can be created for every
devices that stores the respective \glspl{SDS}. Using the \CI{mapReadWrite}
functions, a single \gls{SDS} per device can be created as a lens that allows
mapping on a single client-\gls{SDS}. However, this approach still requires
\glspl{Task} listening to the \gls{SDS} and when a \gls{SDS} is written,
everyone is notified, even if the \gls{Task} only uses the value of a single
different \gls{SDS}.

Finally, the current approach --- a single \gls{SDS} for the entire system
--- was explored. To create \glspl{SDS} per device or per client-\glspl{SDS} a
\CI{mapReadWrite} can be used but it suffers from the same problem as mentioned
before. Moreover, a \gls{Task} still has to watch the \gls{SDS} and communicate
the client-\gls{SDS} updates to the actual device. Both of these problems can
be solved by using a tailor made share that heavily depends on parametric
lenses.

\subsection{Parametric Lenses}
The type for the parametric lens of the big \gls{SDS} is \CI{Maybe
(MTaskDevice, Int)}. The \gls{SDS} is responsible for storing the entire list
of devices, from now on global.  Moreover, the \gls{SDS} can focus on a single
device, from now on local. A local \gls{SDS} can also specifically focus on a
single \gls{SDS} on a single device, from now on called local-share. The
implementation of the real \gls{SDS} is given in Listing~\ref{lst:actualdev}.
The \gls{SDS} is a lens on an actual \gls{SDS} that writes to a file or memory.
Reading the \gls{SDS} is nothing more than reading the real \gls{SDS}. Writing
the \gls{SDS} is a little bit more involved. If the write operation originated
from a \gls{SDS} focussed on a single client-\gls{SDS}, the write action must
also be relayed to the actual device. If the write originated from a \gls{SDS}
focussed the devices or on one device only, nothing needs to be done. The
notification predicate determines whether a watcher gets a notification update.

\begin{lstlisting}[label={lst:actualdev},%
	caption={Device \gls{SDS}}]
deviceStore :: RWShared (Maybe (MTaskDevice, Int)) [MTaskDevice] [MTaskDevice]
deviceStore = SDSSource {SDSSource | name="deviceStore", read = realRead, write= realWrite}
where
	realRead :: (Maybe (MTaskDevice,Int)) *IWorld -> (MaybeError TaskException [MTaskDevice], *IWorld)
	realRead p iw = read realDeviceStore iw

	realWrite :: (Maybe (MTaskDevice,Int)) [MTaskDevice] *IWorld -> (MaybeError TaskException (SDSNotifyPred (Maybe (MTaskDevice,Int))), *IWorld)
	realWrite mi w iw
	# (merr, iw) = write w realDeviceStore iw
	| isError merr || isNothing mi = (merr $> notifyPred mi, iw)
	# (Just (dev, ident)) = mi
	| ident == -1 = (merr $> notifyPred mi, iw)
	= case find ((==)dev) w of
		Nothing = (Error $ exception "Device lost", iw)
		Just {deviceShares} = case find (\d->d.identifier == ident) deviceShares of
			Nothing = (Error $ exception "Share lost", iw)
			Just s = case sendMessagesIW [MTUpd ident s.MTaskShare.value] dev iw of
				(Error e, iw) = (Error e, iw)
				(Ok _, iw) = (Ok $ notifyPred mi, iw)

	notifyPred :: (Maybe (MTaskDevice, Int)) (Maybe (MTaskDevice, Int)) -> Bool
	notifyPred Nothing Nothing = True    // Global watcher looking at a global event
	notifyPred Nothing (Just _) = False  // Global watcher looking at a local event
	notifyPred (Just _) Nothing = False  // Local watcher looking at a global event
	// Local device watcher looking at a local event
	notifyPred (Just (d1, -1)) (Just (d2, _)) = d1 == d2
	// Local share watcher looking at a local share event
	notifyPred (Just (d1, i1)) (Just (d2, i2)) = d1 == d2 && i1 == i2

	realDeviceStore :: Shared [MTaskDevice]
	realDeviceStore = sharedStore "mTaskDevices" []
\end{lstlisting}

\subsubsection{Global \glspl{SDS}}
Accessing the global \gls{SDS} is just a matter of focussing the
\CI{deviceStore} with the \CI{Nothing} parameter as follows:

\begin{lstlisting}[caption={Global \gls{SDS}}]
deviceStoreNP :: Shared [MTaskDevice]
deviceStoreNP = sdsFocus Nothing deviceStore
\end{lstlisting}

\subsubsection{Local \glspl{SDS}}
Accessing a single device can be done using the \CI{mapReadWrite} function.
Since device comparison is shallow, the device that is given is allowed to be
an old version. The identification of devices is solely done on the name of the
channels and is unique throughout the system. The implementation is as follows:

\begin{lstlisting}[caption={Local \gls{SDS}}]
deviceShare :: MTaskDevice -> Shared MTaskDevice
deviceShare d = mapReadWriteError
	( \ds->case find ((==)d) of
		Nothing = exception "Device lost"
		Just d = Ok d)
	, \w ds->case splitWith ((==)d) ds of
		([], _) = Error $ exception "Device lost"
		([_:_], ds) = Ok $ Just [w:ds])
	$ sdsFocus (Just (d, -1)) deviceStore
\end{lstlisting}

\subsubsection{Local-share specific \glspl{SDS}}
A single \gls{SDS} on a single device can be accessed using the \CI{shareShare}
function. This function focusses the real big \gls{SDS} on a single share and
uses the \CI{mapReadWrite} functions to serve the correct part of the
information.

\begin{lstlisting}[caption={Local \gls{SDS}}]
shareShare :: MTaskDevice MTaskShare -> Shared BCValue
shareShare dev share = sdsFocus ()
	$ mapReadWriteError (read, write)
	$ sdsFocus (Just (dev, share.identifier))
	$ deviceStore
where
	read :: [MTaskDevice] -> MaybeError TaskException BCValue
	read devs = case find ((==)dev) devs of
		Nothing = exception "Device lost"
		Just d = case find ((==)share) d.deviceShares of
			Nothing = exception "Share lost"
			Just s = Ok s.MTaskShare.value
	
	write :: BCValue [MTaskDevice] -> MaybeError TaskException (Maybe [MTaskDevice])
	write val devs = case partition ((==)dev) devs of
		([], _) = Error $ exception "Device doesn't exist anymore"
		([_,_:_], _) = Error $ exception "Multiple matching devices"
		([d=:{deviceShares}], devs) = case partition ((==)share) deviceShares of
			([], _) = Error $ exception "Share doesn't exist anymore"
			([_,_:_], _) = Error $ exception "Multiple matching shares"
			([s], shares) = Ok $ Just [{MTaskDevice | d & 
				deviceShares=[{MTaskShare | s & value=val}:shares]}:devs]
\end{lstlisting}

\section{Communication}
The communication from the server to the client and vice versa is just a
character stream containing encoded \gls{mTask} messages. The \CI{synFun}
belonging to the device is responsible for sending the content in the left
channel and putting received messages in the right channel. Moreover, the
boolean value should be set to \CI{True} when the connection is terminated. The
specific encoding of the messages is visible in
Appendix~\ref{app:communication-protocol}. The type holding the messages is
shown in Listing~\ref{lst:avmsg}. Detailed explanation about the message types
and according actions will be given in the following subsections.

\begin{lstlisting}[label={lst:avmsg},caption={Available messages}]
:: MTaskId :== Int
:: MSDSId :== Int
:: MTaskFreeBytes :== Int
:: MTaskMSGRecv
	= MTTaskAck MTaskId MTaskFreeBytes | MTTaskDelAck MTaskId
	| MTSDSAck MSDSId                  | MTSDSDelAck MSDSId
	| MTPub MSDSId BCValue             | MTMessage String
	| MTDevSpec MTaskDeviceSpec        | MTEmpty

:: MTaskMSGSend
	= MTTask MTaskInterval String | MTTaskDel MTaskId
	| MTShutdown                  | MTSds MSDSId BCValue
	| MTUpd MSDSId BCValue        | MTSpec

:: MTaskInterval = OneShot | OnInterval Int | OnInterrupt Int
\end{lstlisting}

\subsection{Add a device}
A device can be added by filling in the \CI{MTaskDevice} record as much as
possible and running the \CI{connectDevice} function. This function grabs the
channels, starts the synchronization \gls{Task} (\CI{synFun}), makes sure the
errors are handled when needed and runs a processing function in parallel to
react on the incoming messages. Moreover, it sends a specification request to
the device in question to determine the details of the device and updates the
record to contain the top-level \gls{Task}-id. All device functionality
heavily depends on the specific \CI{deviceShare} function that generates an
\gls{SDS} for a specific device. This allows giving an old device record to the
function and still update the latest instance. Listing~\ref{lst:connectDevice}
shows the connection function.

\begin{lstlisting}[label={lst:connectDevice},%
	caption={Connect a device}]
connectDevice :: (MTaskDevice (Shared Channels) -> Task ()) MTaskDevice -> Task Channels
connectDevice procFun device = let ch = channels device
	in traceValue "connectDevice" >>| appendTopLevelTask 'DM'.newMap True
		(	procFun device ch -||- catchAll (getSynFun device.deviceData ch) errHdl)
		>>= \tid->upd (\d->{d&deviceTask=Just tid,deviceError=Nothing}) (deviceShare device)
		>>| upd (\(r,s,ss)->(r,s++[MTSpec],ss)) ch
where
	errHdl e = upd (\d->{d & deviceTask=Nothing, deviceError=Just e}) (deviceShare device) @! ()
\end{lstlisting}

Figure~\ref{fig:handshake} shows the connection diagram. The client responds to
the server with their device specification. This is detected by the processing
function and the record is updated accordingly.

\begin{figure}[H]
	\centering
	\begin{sequencediagram}
		\newthread{s}{Server}
		\newinst[4]{c}{Client}
		\begin{call}{s}{MTSpec}{c}{MTDevSpec}
		\end{call}
	\end{sequencediagram}
	\caption{Connect a device}\label{fig:handshake}
\end{figure}

\subsection{\glspl{Task} \& \glspl{SDS}}
When a \gls{Task} is sent to the device it is added to the device record
without an identifier. The actual identifier is added to the record when the
acknowledgement of the \gls{Task} by the device is received. The connection
diagram is shown in Figure~\ref{fig:tasksend}.

\begin{figure}[H]
	\centering
	\begin{sequencediagram}
		\newthread{s}{Server}
		\newinst[4]{c}{Client}
		\begin{call}{s}{MTSDS}{c}{MTSDSAck}
		\end{call}
		\begin{call}{s}{MTTask}{c}{MTTaskAck}
		\end{call}
	\end{sequencediagram}
	\caption{Sending a \gls{Task} to a device}\label{fig:tasksend}
\end{figure}

The function for sending a \gls{Task} to the device is shown in
Listing~\ref{lst:sendtask}. First the \gls{Task} is compiled into messages. The
details of the compilation process are given in Section~\ref{sec:compiler}.
The new \glspl{SDS} that were generated during compilation are merged with the
existing device's \glspl{SDS}. Furthermore the messages are placed in the
channel \gls{SDS} of the device. This will result in sending the actual \gls{SDS}
specification and \gls{Task} specifications to the device. A \gls{Task} record
is created with the identifier $-1$ to denote a \gls{Task} not yet
acknowledged. Finally the device itself is updated with the new state and with
the new \gls{Task}.  After waiting for the acknowledgement the device is
updated again and the \gls{Task} returns.

\begin{lstlisting}[label={lst:sendtask},%
	caption={Sending a \gls{Task} to a device}]
makeTask :: String Int -> Task MTaskTask
makeTask name ident = get currentDateTime @ \dt->{MTaskTask | name=name, ident=ident, dateAdded=dt}

makeShare :: String Int BCValue -> MTaskShare
makeShare withTask identifier value = {MTaskShare | withTask=[withTask], identifier=identifier, value=value}

sendTaskToDevice :: String (Main (ByteCode a Stmt)) (MTaskDevice, MTaskInterval) -> Task MTaskTask
sendTaskToDevice wta mTask (device, timeout)
# (msgs, newState=:{sdss}) = toMessages timeout mTask device.deviceState
# shares = [makeShare wta "" sdsi sdsval\\{sdsi,sdsval}<-sdss, (MTSds sdsi` _)<-msgs | sdsi == sdsi`]
= updateShares device ((++) shares)
	>>| sendMessages msgs device
	>>| makeTask wta -1
	>>= \t->upd (addTaskUpState newState t) (deviceShare device)
	>>| wait "Waiting for task to be acked" (taskAcked t) (deviceShare device)
	>>| treturn t
where
	addTaskUpState :: BCState MTaskTask MTaskDevice -> MTaskDevice
	addTaskUpState st task device = {MTaskDevice | device & deviceState=st, deviceTasks=[task:device.deviceTasks]}
	taskAcked t d = maybe True (\t->t.ident <> -1) $ find (eq t) d.deviceTasks
	eq t1 t2 = t1.dateAdded == t2.dateAdded && t1.MTaskTask.name == t2.MTaskTask.name
\end{lstlisting}

\subsection{Miscellaneous Messages}
One special type of message is available which is sent to the device only when
it needs to reboot. When the server wants to stop the bond with the device it
sends the \CI{MTShutdown} message. The device will then clear its memory, thus
losing all the \glspl{SDS} and \glspl{Task} that were stored and reset itself.
Shortly after the shutdown message a new server can connect to the device
because the device is back in listening mode.

\subsection{Integration}
When the system starts up, the devices from the previous execution still
residing in the \gls{SDS} must be cleaned up. It might be the case that they
contain \glspl{Task}, \glspl{SDS} or errors that are no longer applicable in
this run. A user or programmer can later choose to reconnect to some devices.

\begin{lstlisting}[caption={Starting up the devices},%
	label={lst:startupdevs}]
startupDevices :: Task [MTaskDevice]
startupDevices = upd (map reset) deviceStoreNP
	where reset d = {d & deviceTask=Nothing, deviceTasks=[], deviceError=Nothing}
\end{lstlisting}

The system's management is done through the interface of a single \gls{Task}
called \CI{mTaskManager}. To manage the system, a couple of different
functionalities are necessary and are launched. An image of the management
interface is shown in Figure~\ref{lst:manage}. The left sidebar of the
interface shows the list of example \glspl{Task} that are present in the
system. When clicking a \gls{Task}, a dialog opens in which a device can be
selected to send the \gls{Task} to. The dialog might contain user specified
variables. All example \glspl{mTask} are of the type \CI{Task (Main (ByteCode
() Stmt))} and can thus ask for user input first if needed for parameterized
\glspl{mTask}. The bottom panel shows the device information. In this panel,
the devices can be created and modified. Moreover, this panel allows the user
to reconnect with a device after a restart of the server application.

\begin{figure}[H]
	\centering
	\includegraphics[width=\linewidth]{manage}
	\caption{The device management interface}\label{lst:manage}
\end{figure}

\section[Lifting mTasks to iTasks-Tasks]%
	{Lifting \glspl{mTask} to \gls{iTasks}-\glspl{Task}}
If the user does not want to know where and when a \gls{mTask} is actually
executed and is just interested in the results it can lift the \gls{mTask} to
an \gls{iTasks}-\glspl{Task}. The function is called with a name, \gls{mTask},
device and interval specification and it will return a \gls{Task} that finishes
if and only if the \gls{mTask} has returned.

\begin{lstlisting}[caption={Starting up the devices}]
liftmTask :: String (Main (ByteCode () Stmt)) (MTaskDevice, MTaskInterval) -> Task ()
liftmTask wta mTask c=:(dev, _)= sendTaskToDevice wta mTask c
	>>= \t->wait "Waiting for mTask to return" (taskRemoved t) (deviceShare dev)
	>>| viewInformation "Done!" [] ()
where
	taskRemoved t d = isNothing $ find (\t1->t1.ident==t.ident) d.deviceTasks
\end{lstlisting}

\section{Examples}
\todo{example program (demo)}
