X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;f=arch.communication.tex;h=0bb3746e00a855b8100ae5364d5058370884a661;hb=20ea9da4247313e4ce6e3a385e2975424c62ebfe;hp=18bc076174071a538cd0a7e1aad3acb9871fe1db;hpb=d098cf66624230390d762e9995e8fd61b0d3c71d;p=msc-thesis1617.git diff --git a/arch.communication.tex b/arch.communication.tex index 18bc076..0bb3746 100644 --- a/arch.communication.tex +++ b/arch.communication.tex @@ -8,7 +8,7 @@ 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 @@ -38,7 +38,7 @@ 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}[label={lst:devicespec}, +\begin{lstlisting}[language=Clean,label={lst:devicespec}, caption={Device specification for \gls{mTask}-\glspl{Task}}] :: MTaskDeviceSpec = { haveLed :: Bool @@ -51,27 +51,86 @@ brevity. } \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 @@ -120,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} @@ -131,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`] @@ -140,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]} @@ -162,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 @@ -176,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}