\begin{chapterabstract}
This chapter shows the integration of \gls{MTASK} with \gls{ITASK} by showing:
\begin{itemize}
- \item an architectural overview of \gls{MTASK};
+ \item an architectural overview \gls{MTASK} applications;
\item on the interface for connecting devices;
\item the interface for lifting \gls{MTASK} tasks to \gls{ITASK} tasks;
\item and interface for lifting \gls{ITASK} \glspl{SDS} to \gls{MTASK} \glspl{SDS}.
The \gls{MTASK} language is a multi-view \gls{DSL}, i.e.\ there are multiple interpretations possible for a single \gls{MTASK} term.
Using the byte code compiler (\cleaninline{BCInterpret}) \gls{DSL} interpretation, \gls{MTASK} tasks can be fully integrated in \gls{ITASK}.
They are executed as if they are regular \gls{ITASK} tasks and they communicate may access \glspl{SDS} from \gls{ITASK} as well.
-\Gls{MTASK} devices contain a domain-specific \gls{OS} (\gls{RTS}) and are little \gls{TOP} engines in their own respect, being able to execute tasks.
+\Gls{MTASK} devices contain a domain-specific \gls{OS} and are little \gls{TOP} engines in their own respect, being able to execute tasks.
\Cref{fig:mtask_integration} shows the architectural layout of a typical \gls{IOT} system created with \gls{ITASK} and \gls{MTASK}.
The entire system is written as a single \gls{CLEAN} specification where multiple tasks are executed at the same time.
Tasks can access \glspl{SDS} according to many-to-many communication and multiple clients can work on the same task.
\label{fig:mtask_integration}
\end{figure}
-\section{Devices}\label{sec:withdevice}
+\section{Connecting edge devices}\label{sec:withdevice}
When interpreted by the byte code compiler view, an \gls{MTASK} task produces a compiler.
This compiler is exceuted at run time so that the resulting byte code can be sent to an edge device.
All communication with this device happens through a so-called \emph{channels} \gls{SDS}.
The channels contain three fields, a queue of messages that are received, a queue of messages to send and a stop flag.
Every communication method that implements the \cleaninline{channelSync} class can provide the communication with an \gls{MTASK} device.
-As of now, serial port communication, direct \gls{TCP} communication and \gls{MQTT} over \gls{TCP} are supported as communication providers.
-The \cleaninline{withDevice} function transforms a communication provider and a task that does something with this device to an \gls{ITASK} task.
-Internally, the task sets up the communication, exchanges specifications, executes the inner task while handling errors, and finally cleans up after closing.
+As of now, serial port communication, direct \gls{TCP} communication and \gls{MQTT} over \gls{TCP} are supported as communication providers (see \cref{lst:connection_types}).
+The \cleaninline{withDevice} function transforms such a communication provider and a task that does something with this device to an \gls{ITASK} task.
+Internally, the task sets up the communication, exchanges specifications with the device, executes the inner task while handling errors, and finally cleans up after closing.
\Cref{lst:mtask_device} shows the types and interface to connecting devices.
\begin{lstClean}[label={lst:mtask_device},caption={Device communication interface in \gls{MTASK}.}]
class channelSync a :: a (Shared sds Channels) -> Task () | RWShared sds
-withDevice :: a (MTDevice -> Task b) -> Task b | iTask b & channelSync, iTask a
+withDevice :: a (MTDevice -> Task b)
+ -> Task b | iTask b & channelSync, iTask a
\end{lstClean}
-\section{Lifting tasks}\label{sec:liftmtask}
+\subsection{Implementation}
+The \cleaninline{MTDevice} abstract type is internally represented as three \gls{ITASK} \gls{SDS} that contain all the current information about the tasks.
+The first \gls{SDS} is the information about the \gls{RTS} of the device, i.e.\ metadata on the tasks that are executing, the hardware specification and capabilities, and a list of fresh task identifiers.
+The second \gls{SDS} is a map storing downstream \gls{SDS} updates.
+When a lifted \gls{SDS} is updated on the device, a message is sent to the server.
+This message is initially queued in the map to allow for asynchronous handling of multiple updates.
+Finally, the \cleaninline{MTDevices} type contains the communication channels.
+
+The \cleaninline{withDevice} task itself first constructs the \glspl{SDS} using the \gls{ITASK} function \cleaninline{withShared} to create anonymous local \glspl{SDS}.
+Then, it performs the following four tasks in parallel to monitor the edge device.
+\begin{enumerate}
+ \item It synchronises the channels using the \cleaninline{channelSync} overloaded function.
+ Errors that occur here are converted to the proper \gls{MTASK} exception.
+ \item Watches the channels for the shutdown flag.
+ If the connection is lost with the device unexpectedly, an \gls{MTASK} exception is thrown.
+ \item Watches the channels for messages and processes them accordingly by changing the device information \gls{SDS} or adding the lifted \gls{SDS} updates to the corresponding \gls{SDS} update queue.
+ \item Sends a request for a specification. Once the specification is received, the device task is run.
+ The task value of this device task is then used as the task value of the \cleaninline{withDevice} task.
+\end{enumerate}
+
+If at any stage an unrecoverable device error occurs, an \gls{ITASK} exception is thrown on the \cleaninline{withDevice} task.
+This exception can be caught in order to device some kind of fail-safe mechanism.
+For example, when a device fails, the tasks can be sent to another device.
+\todo[inline]{Example of failsafe?}
+
+%withDevice spec deviceTask
+% withShared newMap \sdsupdates->
+% withShared ([], [MTTSpecRequest], False) \channels->
+% withShared default \dev->parallel
+% [ channelSync spec // unexpected disconnect
+% , watchForShutdown // unexpected disconnect
+% , watchChannels // process messages
+% , waitForSpecification
+% >>| deviceTask
+% >>* [ifStable: issueShutdown]
+% ]
+
+\section{Lifting \texorpdfstring{\gls{MTASK}}{mTask} tasks}\label{sec:liftmtask}
Once the connection with the device is established, \gls{MTASK} tasks can be lifted to \gls{MTASK} tasks using the \cleaninline{liftmTask} family of functions (see \cref{lst:liftmtask}).
Given an \gls{MTASK} task in the \cleaninline{BCInterpret} view and a device obtained from \cleaninline{withDevice}, an \gls{ITASK} task is returned.
This \gls{ITASK} task tethers the \gls{MTASK} task that is executed on the microcontroller.
liftmTask :: (Main (MTask BCInterpret u)) MTDevice -> Task u | iTask u
\end{lstClean}
-Under the hood, \cleaninline{liftmTask} compiler the \gls{MTASK} task to byte code, gathers the initial values for the lifted \glspl{SDS} and sends the data to the device.
-Once acknowledged, the \gls{MTASK} task value and the \glspl{SDS} are monitored.
-If the \gls{ITASK} server updates the value of a lifted \gls{SDS}, the appropriate message is sent to the \gls{MTASK} to notify it of the change.
-Furthermore, the \gls{MTASK} device may update the \gls{SDS}, and in that case the message is picked up by the \cleaninline{liftmTask} task and the \gls{SDS} on the \gls{ITASK} server updated accordingly.
+Under the hood, \cleaninline{liftmTask}:
+\begin{itemize}
+ \item Generates a fresh task identifier for the device.
+ \item Compiles the task and fetches the values for the tethered \glspl{SDS}.
+ \item Sends the task to the device
+ \item Watches, in parallel: the tethered \glspl{SDS} in \gls{ITASK}, if they are updated, a message is sent to the device; the \gls{SDS} update queue, if there is a downstream update, the \gls{ITASK} \gls{SDS} it references is updated as well; and the task value.
+\end{itemize}
+
+The task value of the \cleaninline{liftmTask} task is the task value of the task on the edge device.
+
+\section{Lifting \texorpdfstring{\gls{ITASK}}{iTask} \texorpdfstring{\glsxtrlongpl{SDS}}{shared data sources}}\label{sec:liftsds}
+Lifting \gls{ITASK} \glspl{SDS} to \gls{MTASK} \glspl{SDS} is something that mostly happens at the compiler level using the \cleaninline{liftsds} function (see \cref{lst:mtask_itasksds}).
+\Glspl{SDS} in \gls{MTASK} must always have an initial value.
+For regular \gls{SDS} this value is given in the source code, for lifted \gls{ITASK} \glspl{SDS} this value is obtained by reading the values once just before sending the task to the edge device.
+On the device itself, there is just one difference between lifted \glspl{SDS} and regular \glspl{SDS}: after changing \pgls{SDS}, a message is sent to the server containing this new value.
+The \cleaninline{withDevice} task (see \cref{sec:withdevice}) receives and processes this message by writing to the \gls{ITASK} \gls{SDS}.
+Tasks watching this \gls{SDS} get notified then through the normal notification mechanism of \gls{ITASK}.
-\section{Lifting \texorpdfstring{\glsxtrlongpl{SDS}}{shared data sources}}\label{sec:liftsds}
\begin{lstClean}[label={lst:mtask_itasksds},caption={Lifted \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
class liftsds v where
liftsds :: ((v (Sds t)) -> In (Shared sds t) (Main (MTask v u)))
-> Main (MTask v u) | RWShared sds
\end{lstClean}
+The compilation of the code and the serialisation of the data throws away all typing information.
+\Cref{lst:mtask_itasksds_lens} shows a pseudocode implementation of \cleaninline{liftsds}.
+\Glspl{SDS} are stored in the compiler state as a map from identifiers to either an initial value or an \cleaninline{MTLens}.
+The \cleaninline{MTLens} is a type synonym for a \gls{SDS} that represents the typeless serialised value of the underlying \gls{SDS}.
+Such a \gls{SDS} is created by using the \cleaninline{mapReadWriteError} which, given a pair of read and write functions with error handling, produces a \gls{SDS} with the lens embedded.
+The read function transforms, the function that converts a typed value to a typeless serialised value, just applies the serialisation.
+The write function, the function that, given the new serialised value and the old typed value, produces a new typed value tries do deserialise the value.
+
+First, in similar fashion to how functions are implemented, using fixed points, the \glspl{SDS} is
+
+% VimTeX: SynIgnore on
+\begin{lstClean}[label={lst:mtask_itasksds_lens},caption={Lens applied to lifted \gls{ITASK} \glspl{SDS} in \gls{MTASK}.}]
+instance liftsds BCInterpret where
+ liftsds def = {main =
+ let (t In e) = def (abort "liftsds: expression too strict")
+ in addSdsIfNotExist (Right $ lens t)
+ >>= \sdsi-> let (t In e) = def (pure (Sds sdsi))
+ in e.main
+ }
+ where
+ lens :: ((Shared sds a) -> MTLens) | type, iTask a & RWShared sds
+ lens = mapReadWriteError
+ ( \r->Ok (fromString (toByteCode{|*|} r)
+ , \w r-> ?Just <$> iTasksDecode (toString w)
+ ) ?None
+\end{lstClean}
+% VimTeX: SynIgnore off
+
+
\section{Conclusion}