elaborate on communication
[msc-thesis1617.git] / results.arch.tex
index 626f0a4..c4c2b22 100644 (file)
@@ -1,4 +1,4 @@
-\section{Devices}
+/section{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
 and implement (part of) the device specific interface. The shared codebase only
@@ -34,13 +34,13 @@ the device software.
 \section{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
+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}
 
-\begin{lstlisting}[language=Clean,label={lst:devicespec},
+\begin{lstlisting}[label={lst:devicespec},
        caption={Device specification for \glspl{mTask}}]
 :: MTaskDeviceSpec =
        {haveLed     :: Bool
@@ -64,17 +64,22 @@ occurs. 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 the serial device type
-it uses the newly developed serial port library of \gls{Clean}\footnote{\url{%
+\CI{tcpconnect} function in \gls{iTasks}. In case of the serial device type 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 and the according \glspl{SDS}. Finally it
-stores the specification of the device that is received when connecting.
-All of this is listed in Listing~\ref{lst:mtaskdevice}.
+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 listed 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}]
+deviceStore :: Shared [MTaskDevice]
 
-\begin{lstlisting}[language=Clean,caption={Device type},label={lst:mtaskdevice}]
 :: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool)
+:: BCState = ... // Compiler state, explained in later sections
 :: MTaskResource 
        = TCPDevice TCPSettings
        | SerialDevice TTYSettings
@@ -83,6 +88,7 @@ All of this is listed in Listing~\ref{lst:mtaskdevice}.
                , deviceError :: Maybe String
                , deviceChannels :: String
                , deviceName :: String
+               , deviceState :: BCState
                , deviceTasks :: [MTaskTask]
                , deviceData :: MTaskResource
                , deviceSpec :: Maybe MTaskDeviceSpec
@@ -96,4 +102,123 @@ class MTaskDuplex a where
 \end{lstlisting}
 
 \section{Communication}
-\todo{Connectie, hoe gaat dat in zijn werk}
+All \gls{mTask} messages are encoded following the specification given in
+Appendix~\ref{app:communication-protocol}. Available messages are:
+\begin{lstlisting}[caption={Available messages}]
+:: MTaskMSGRecv
+       = MTTaskAck Int Int           | MTTaskDelAck Int
+       | MTSDSAck Int                | MTSDSDelAck Int
+       | MTPub Int BCValue           | MTMessage String
+       | MTDevSpec MTaskDeviceSpec   | MTEmpty
+
+:: MTaskMSGSend
+       = MTTask MTaskInterval String | MTTaskDel Int
+       | MTShutdown                  | MTSds Int BCValue
+       | MTUpd Int 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 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 task to the device is shown in
+Listing~\ref{lst:sendtask}. First the task is compiled into messages. The
+details of the compilation process are given in Section~\ref{sec:compiler}.
+The new shares 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} 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.