Merge branch 'master' of git.martlubbers.net:msc-thesis1617
[msc-thesis1617.git] / arch.communication.tex
index 4585a06..0bb3746 100644 (file)
@@ -2,13 +2,13 @@ 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
+boolean flag in the channel type 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}]
+\begin{lstlisting}[language=Clean,label={lst:avmsg},caption={Available messages}]
 :: MTaskId :== Int
 :: MSDSId :== Int
 :: MTaskFreeBytes :== Int
@@ -26,27 +26,111 @@ and according actions will be given in the following subsections.
 :: MTaskInterval = OneShot | OnInterval Int | OnInterrupt Int
 \end{lstlisting}
 
+\subsection{Device Specification}
+The server stores a description for every device available in a record type.
+From the macro settings in the client --- 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. Not all peripheral flags are shown for
+brevity.
+
+\begin{lstlisting}[language=Clean,label={lst:devicespec},
+       caption={Device specification for \gls{mTask}-\glspl{Task}}]
+:: MTaskDeviceSpec =
+       { haveLed     :: Bool
+       , haveLCD     :: Bool
+       , have...
+       , bytesMemory :: Int
+       , stackSize   :: Int
+       , aPins       :: Int
+       , dPins       :: Int
+       }
+\end{lstlisting}
+
+The code on the device generates the specification. When a device does not have
+a specific peripheral, the code will also not be on the device. In the
+interface file, the code for peripherals is always guarded by macros. Thus, if
+the peripheral is not there, the macro is set accordingly and the code will not
+be included. To illustrate this, Listings~\ref{lst:macro}-\ref{lst:macro3}
+show parts of the interface file and device specification generation function
+for the \emph{NodeMCU} microcontroller which only boasts a single analog pin
+and eight digital pins.
+
+\begin{minipage}{.49\textwidth}
+       \begin{lstlisting}[label={lst:macro},language=C,%
+               caption={Specification in the interface}]
+...
+#elif defined ARDUINO_ESP8266_NODEMCU
+#define APINS 1
+#define DPINS 8
+#define STACKSIZE 1024
+#define MEMSIZE 1024
+#define HAVELED 0
+#define HAVEHB 0
+
+#if APINS > 0
+void write_apin(uint8_t p, uint8_t v);
+uint8_t read_apin(uint8_t pin);
+#endif
+       \end{lstlisting}
+\end{minipage}
+\begin{minipage}{.49\textwidth}
+       \begin{lstlisting}[label={lst:macro3},language=C,%
+               caption={Actual generation}]
+...
+void spec_send(void) {
+       write_byte('c');
+       write_byte(0 | (HAVELED << 0)
+                    | (HAVELCD << 1)
+                    | (HAVEHB  << 2)
+                    | ...);
+       write16(MEMSIZE);
+       write16(STACKSIZE);
+       write_byte(APINS);
+       write_byte(DPINS);
+       write_byte('\n');
+}
+       \end{lstlisting}
+\end{minipage}
+
 \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},%
+possible and running the \CI{connectDevice} function. This function grabs and
+clears 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}[language=Clean,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
+process :: MTaskDevice (Shared Channels) -> Task ()
+process device ch = forever $ wait "process" (not o isEmpty o fst3) ch
+       >>= \(r,s,ss)->upd (appFst3 (const [])) ch >>| proc r
+where
+       proc :: [MTaskMSGRecv] -> Task ()
+       proc [] = treturn ()
+       proc [m:ms] = (case m of
+               MTPub i val = updateShareFromPublish device i val @! ()
+               ...
+               MTDevSpec s = deviceAddSpec device s @! ()
+               ) >>| proc ms
+
+connectDevice :: MTaskDevice -> Task MTaskDevice
+connectDevice device = set ([], [], False) ch
+       >>| appendTopLevelTask 'DM'.newMap True
+       (       process device ch -||- catchAll (getSynFun device.deviceData ch) errHdl)
+       >>= \tid->upd (\d->{d&deviceTask=Just tid,deviceError=Nothing}) (deviceShare device)
+       >>| set (r,[MTSpec],ss) ch
+       >>| treturn device
 where
        errHdl e = upd (\d->{d & deviceTask=Nothing, deviceError=Just e}) (deviceShare device) @! ()
        ch = channels device
@@ -95,10 +179,10 @@ 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
+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},%
+\begin{lstlisting}[language=Clean,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}
@@ -106,7 +190,7 @@ makeTask name ident = get currentDateTime @ \dt->{MTaskTask | name=name, ident=i
 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 :: String (Main (ByteCode a Stmt)) (MTaskDevice, MTaskInterval) -> Task (MTaskTask, [MTaskShare])
 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`]
@@ -115,7 +199,7 @@ sendTaskToDevice wta mTask (device, timeout)
        >>| makeTask wta -1
        >>= \t->upd (addTaskUpState newState t) (deviceShare device)
        >>| wait "Waiting for task to be acked" (taskAcked t) (deviceShare device)
-       >>| treturn t
+       >>| treturn (t, shares)
 where
        addTaskUpState :: BCState MTaskTask MTaskDevice -> MTaskDevice
        addTaskUpState st task device = {MTaskDevice | device & deviceState=st, deviceTasks=[task:device.deviceTasks]}
@@ -137,7 +221,7 @@ 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},%
+\begin{lstlisting}[language=Clean,caption={Starting up the devices},%
        label={lst:startupdevs}]
 startupDevices :: Task [MTaskDevice]
 startupDevices = upd (map reset) deviceStoreNP
@@ -151,14 +235,14 @@ 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]
+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}[ht]
        \centering
        \includegraphics[width=\linewidth]{manage}
        \caption{The device management interface}\label{lst:manage}