update abstract and acks
[msc-thesis1617.git] / results.arch.tex
index cd9918d..e276010 100644 (file)
@@ -1,14 +1,46 @@
-\section{Architecture}
-\subsection{Devices}
-The client code 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
+\section{Overview \& Terminology}
+The goal of the architecture 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.
+
+\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 also just a program on the same
+               machine as the server.
+       \item Server, \gls{iTasks}-System
+
+               The actual executable serving the \gls{iTasks} interfaces. The system
+               will contain \glspl{Task} taking care of the communication with the
+               clients.
+       \item System
+
+               The complete ecosystem, thus containing both the server and client
+               programs.
+       \item Engine
+
+               The runtime system of the client. This system handles the communication
+               with the server and interprets the \glspl{Task}.
+\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
 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
+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.
 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.
@@ -23,52 +55,66 @@ the device software.
 
                This is tested in particular on the \texttt{STM32f7x} series \gls{ARM}
                development board.
 
                This is tested in particular on the \texttt{STM32f7x} series \gls{ARM}
                development board.
-       \item Microcontrollers programmable by the \emph{Arduino} \gls{IDE}.\\
+       \item Microcontrollers programmable by the \gls{Arduino} \gls{IDE}.\\
                
                
-               This does not only include \emph{Arduino} compatible boards but also
-               other boards capable of running \emph{Arduino} code. The code
+               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}.
                has been found working on the \texttt{ESP8266} powered \emph{NodeMCU}.
-               It is tested on devices as small as the regular \emph{Arduino UNO}
-               board that only boasts a meager \emph{2K} of \emph{RAM}.
+               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}.
 \end{itemize}
 
 \end{itemize}
 
-\subsection{Specification}
-Devices are stored in a record type and all devices in the system are stored in
-a \gls{SDS} containing all devices. From the macro settings in the interface
-file a profile is created for the device that describes the specification. When
-a connection between the server and a client is established the server will
-send a request for specification. The client will serialize his specification
-and send it to the server so that the server knows what the client is capable
-of. The exact specification is listed in Listing~\ref{lst:devicespec}
+\section{Specification}
+The server stores a description for every device available in a record type
+which are stored in a \gls{SDS}. From the macro settings in
+the interface file, a profile is created for the device that describes the
+specification. When a connection between the server and a client is established
+the server will send a request for specification. The client will serialize his
+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}
 
 
-\begin{lstlisting}[language=Clean,label={lst:devicespec},
+\begin{lstlisting}[label={lst:devicespec},
        caption={Device specification for \glspl{mTask}}]
 :: MTaskDeviceSpec =
        caption={Device specification for \glspl{mTask}}]
 :: MTaskDeviceSpec =
-       {haveLed     :: Bool
-       ,haveAio     :: Bool
-       ,haveDio     :: Bool
-       ,bytesMemory :: Int
+       { haveLed     :: Bool
+       , haveAio     :: Bool
+       , haveDio     :: Bool
+       , bytesMemory :: Int
        }
 \end{lstlisting}
 
        }
 \end{lstlisting}
 
-\subsection{Memory Management}
-\todo{Explain specification, combine task and share space}
-
-\subsection{Communication}
-The communication to and fro a device runs via a single \gls{SDS}. Every
-device has a specific resource that is used to connect to the device. The
-current system supports connecting devices via a serial connection and via a
-\gls{TCP} connection. Every device has the type \CI{MTaskDevice} and which
-is listed in Listing~\ref{lst:mtaskdevice}. When a device is added a background
-task is started that runs the \CI{synFun}. The \CI{synFun} is the task that
-synchronizes the channel \gls{SDS} with the actual device. For the \gls{TCP}
-device this is a simple \CI{tcpconnect}. The \CI{TaskId} of the background task
-is saved to be able to stop the task in the future. When the task is unable to
-connect it will set the \CI{deviceError} field to notify the user.
-\todo{netter maken}
-
-\begin{lstlisting}[language=Clean,caption={Device type},label={lst:mtaskdevice}]
+\section{Device Storage}
+All devices available in the system are stored in a big \gls{SDS} that contains
+a list of \CI{MTaskDevice}s. The exact specification is defined as in
+Listing~\ref{lst:mtaskdevice} with the accompanying classes and types.
+
+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. If the system wants to send a message to the device, it 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.
+
+\begin{lstlisting}[caption={Device type},label={lst:mtaskdevice}]
+deviceStoreNP :: Shared [MTaskDevice]
+
 :: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool)
 :: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool)
+:: BCState = ... // Compiler state, explained in later sections
 :: MTaskResource 
        = TCPDevice TCPSettings
        | SerialDevice TTYSettings
 :: MTaskResource 
        = TCPDevice TCPSettings
        | SerialDevice TTYSettings
@@ -77,11 +123,145 @@ connect it will set the \CI{deviceError} field to notify the user.
                , deviceError :: Maybe String
                , deviceChannels :: String
                , deviceName :: String
                , deviceError :: Maybe String
                , deviceChannels :: String
                , deviceName :: String
+               , deviceState :: BCState
                , deviceTasks :: [MTaskTask]
                , deviceData :: MTaskResource
                , deviceSpec :: Maybe MTaskDeviceSpec
                , deviceTasks :: [MTaskTask]
                , deviceData :: MTaskResource
                , deviceSpec :: Maybe MTaskDeviceSpec
+               , deviceShares :: [MTaskShare]
        }
 
        }
 
+channels :: MTaskDevice -> Shared Channels
+
 class MTaskDuplex a where
        synFun :: a (Shared Channels) -> Task ()
 \end{lstlisting}
 class MTaskDuplex a where
        synFun :: a (Shared Channels) -> Task ()
 \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 specific encoding
+is visible in Appendix~\ref{app:communication-protocol}. The type holding the
+messages in Listing~\ref{lst:avmsg}. Detailed explaination about the message
+types 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}, 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 the device functionality heavily
+depends on the \CI{withDevices} function that applies a function a device in
+the \gls{SDS} when they are equal. Device equality is defined as equality on
+their channels. This allows you to give 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}]
+withDevices :: MTaskDevice (MTaskDevice -> MTaskDevice) -> Task [MTaskDevice]
+
+connectDevice :: (MTaskDevice (Shared Channels) -> Task ()) MTaskDevice -> Task Channels
+connectDevice procFun device = let ch = channels device
+       in appendTopLevelTask 'DM'.newMap True
+               (procFun device ch -||- catchAll (getSynFun d.deviceData ch) errHdl)
+               >>= \tid->withDevices device (\d->{d&deviceTask=Just tid,deviceError=Nothing})
+               >>| upd (\(r,s,ss)->(r,s++[MTSpec],ss)) ch
+       where
+               errHdl e = withDevices device (\d->{d & deviceTask=Nothing, deviceError=Just e}) @! ()
+\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 made during compilation are added to the
+deviceshares that were made during the compilation are merged with the existing
+shares on the device. Furthermore the messages are placed in the channel share
+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}.
+When the device returns an acknowledgement the \gls{Task} is updated
+accordingly.
+
+\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 [MTaskDevice]
+sendTaskToDevice wta mTask (device, timeout)
+# (msgs, newState) = toMessages timeout mTask device.deviceState
+# shares = [makeShare wta sdsi sdsval\\{sdsi,sdsval}<-newState.sdss, (MTSds sdsi` _)<-msgs | sdsi == sdsi`] 
+= updateShares device ((++) shares)
+       >>| sendMessages msgs device
+       >>| makeTask wta -1
+       >>= withDevices device o addTaskUpState newState
+       where
+               addTaskUpState :: BCState MTaskTask MTaskDevice -> MTaskDevice
+               addTaskUpState st task device = {MTaskDevice | device &
+                       deviceState=st, deviceTasks=[task:device.deviceTasks]}
+\end{lstlisting}
+
+\subsection{Miscellaneous Messages}
+There exists one special type of message that 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 his 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.