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 = set ([], [], False) ch
		>>| 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) @! ()
	ch = channels 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 \gls{mTask}-\glspl{Task} are of the type \CI{Task (Main
(ByteCode () Stmt))} and can thus ask for user input first if needed for
parameterized \gls{mTask}-\glspl{Task}. 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}
