X-Git-Url: https://git.martlubbers.net/?a=blobdiff_plain;f=results.arch.tex;h=e276010256cde2039deb9ff02951a53837b7a54e;hb=c91e99cb9e71060f461c03d1454ad5f31e9495a1;hp=24abb0fc641b435ce09ae9a2c4e20276fa7134f7;hpb=9662cccfffecb70d621318b5f3a35e46b6029f3c;p=msc-thesis1617.git diff --git a/results.arch.tex b/results.arch.tex index 24abb0f..e276010 100644 --- a/results.arch.tex +++ b/results.arch.tex @@ -1,5 +1,38 @@ +\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 client code for the devices is compiled from one codebase. For a device to +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 @@ -32,51 +65,53 @@ the device software. \end{itemize} \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 -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} +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}[label={lst:devicespec}, 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} \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 listed in +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 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 set the \CI{deviceError} field whenever an error -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{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 listed in Listing~\ref{lst:mtaskdevice}. The definitions of the message +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}] -deviceStore :: Shared [MTaskDevice] +deviceStoreNP :: Shared [MTaskDevice] :: Channels :== ([MTaskMSGRecv], [MTaskMSGSend], Bool) :: BCState = ... // Compiler state, explained in later sections @@ -102,19 +137,26 @@ class MTaskDuplex a where \end{lstlisting} \section{Communication} -All \gls{mTask} messages are encoded following the specification given in -Appendix~\ref{app:communication-protocol}. Available messages are: -\begin{lstlisting}[caption={Available messages}] +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 Int Int | MTTaskDelAck Int - | MTSDSAck Int | MTSDSDelAck Int - | MTPub Int BCValue | MTMessage String - | MTDevSpec MTaskDeviceSpec | MTEmpty + = MTTaskAck MTaskId MTaskFreeBytes | MTTaskDelAck MTaskId + | MTSDSAck MSDSId | MTSDSDelAck MSDSId + | MTPub MSDSId BCValue | MTMessage String + | MTDevSpec MTaskDeviceSpec | MTEmpty :: MTaskMSGSend - = MTTask MTaskInterval String | MTTaskDel Int - | MTShutdown | MTSds Int BCValue - | MTUpd Int BCValue | MTSpec + = MTTask MTaskInterval String | MTTaskDel MTaskId + | MTShutdown | MTSds MSDSId BCValue + | MTUpd MSDSId BCValue | MTSpec :: MTaskInterval = OneShot | OnInterval Int | OnInterrupt Int \end{lstlisting} @@ -152,6 +194,7 @@ 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} @@ -161,6 +204,64 @@ function and the record is updated accordingly. \caption{Connect a device}\label{fig:handshake} \end{figure} -\subsection{\glspl{Task}} -\subsection{\glspl{SDS}} -\todo{Connectie, hoe gaat dat in zijn werk, andere berichtenuitwisselingen} +\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.