update presentation, the body is there
[msc-thesis1617.git] / arch.example.tex
index 828e097..b8ef049 100644 (file)
@@ -1,5 +1,5 @@
 \subsection{Framework}
-Systems built with support for \gls{mTask} are often following the same design
+Systems built with support for \gls{mTask} often follow the same design
 pattern. First the devices are created --- with or without the interaction of
 the user --- and they are then connected. When all devices are registered, the
 \gls{mTask}-\glspl{Task} can be sent and \gls{iTasks}-\glspl{Task} can be
@@ -25,20 +25,21 @@ The thermostat is a classic example program for showing interactions between
 peripherals. The following program shows a system containing two devices. The
 first device --- the sensor --- contains a temperature sensor that measures the
 room temperature. The second device --- the actor --- contains a heater,
-connected to the digital pin \CI{D5}. Moreover, this device contains a led to
-indicate whether the heater is on. The following code shows an implementation
-for this. The code fully uses the framework. Note that a little bit of type
-twiddling is required to fully us the result from the \gls{SDS}. This approach
-is still type safe due to the type safety of \CI{Dynamic}s.
-
-\begin{lstlisting}[caption={Thermostat example}]
+connected to the digital pin \CI{D5}. Moreover, this device contains an
+\gls{LED} to indicate whether the heater is on. The following code shows an
+implementation for this. The code makes use of all the aspects of the
+framework. Note that a little bit of type twiddling is required to fully use
+the result from the \gls{SDS}. This approach is still type safe due to the type
+safety of \CI{Dynamic}s.
+
+\begin{lstlisting}[language=Clean,caption={Thermostat example}]
 thermos :: Task ()
 thermos =           makeDevice "nodeM" nodeMCU >>= connectDevice
        >>= \nod->      makeDevice "stm32" stm32   >>= connectDevice
        >>= \stm->      sendTaskToDevice "sensing" sensing (nod, OnInterval 1000)
        >>= \(st, [t])->sendTaskToDevice "acting" acting (stm, OnInterval 1000)
                        (\(BCValue s)->set (BCValue $ dynInt (dynamic s) > 0) (shareShare nod a))
-       >>| treturn ()
+       >>* [OnAction (Action "Shutdown") $ always $ deleteDevice nod >>| deleteDevice stm >>| shutDown 0]
 where
        dynInt :: Dynamic -> Int
        dynInt (a :: Int) = a
@@ -50,18 +51,21 @@ where
                        IF cool (ledOn LED1) (ledOff LED1) :.
                        digitalWrite D5 cool
                }
-       nodeMCU = TCP
+       nodeMCU = makeDevice "NodeMCU"
+               (TCPDevice {host="192.168.0.12", port=8888})
+       stm32   = makeDevice "Stm32"
+               (SerialDevice {devicePath="/dev/ttyUSB0", baudrate=B9600, ...}
 \end{lstlisting}
 
 \subsection[Lifting mTasks to iTasks-Tasks]%
        {Lifting \gls{mTask}-\glspl{Task} to \gls{iTasks}-\glspl{Task}}
-If the user does not want to know where and when a \gls{mTask} is actually
-executed and is just interested in the results it can lift the \gls{mTask} to
+If the user does not want to know where and when an \gls{mTask} is actually
+executed and is just interested in the results, it can lift the \gls{mTask} to
 an \gls{iTasks}-\gls{Task}. The function is called with a name, \gls{mTask},
 device and interval specification and it will return a \gls{Task} that finishes
 if and only if the \gls{mTask} has returned.
 
-\begin{lstlisting}[caption={Lifting \gls{mTask}-\glspl{Task} to \gls{iTasks}}]
+\begin{lstlisting}[language=Clean,caption={Lifting \gls{mTask}-\glspl{Task} to \gls{iTasks}}]
 liftmTask :: String (Main (ByteCode () Stmt)) (MTaskDevice, MTaskInterval) -> Task [MTaskShare]
 liftmTask wta mTask c=:(dev, _)= sendTaskToDevice wta mTask c
        >>= \(t, shs)->wait "Waiting for mTask to return" (taskRemoved t) (deviceShare dev)
@@ -72,8 +76,8 @@ where
 \end{lstlisting}
 
 The factorial function example from Chapter~\ref{chp:mtaskcont} can then be
-lifted to a real \gls{iTasks}-\gls{mTask} with the following code:
-\begin{lstlisting}[caption={Lifting the factorial \gls{Task} to \gls{iTasks}}]
+lifted to a real \gls{iTasks}-\gls{Task} with the following code:
+\begin{lstlisting}[language=Clean,caption={Lifting the factorial \gls{Task} to \gls{iTasks}}]
 factorial :: MTaskDevice -> Task BCValue
 factorial dev = enterInformation "Factorial of ?" []
        >>= \fac->liftmTask "fact" (fact fac) (dev, OnInterval 100)
@@ -92,33 +96,41 @@ As an example, the addition of a new sensor will be demonstrated. The heartbeat
 and oxygen saturation sensor add-on is a \textsc{PCB} the size of a fingernail
 with a red \gls{LED} and a light sensor on it. Moreover, it contains an
 \textsc{I2C} chip to communicate. The company producing the chip provides the
-programmer with example code for \gls{Arduino} and \textsc{mbed}. The sensor
-emits red light and measures the returning light intensity. The microcontroller
-hosting the device has to keep track of four seconds of samples to determine
-the heartbeat. In the \gls{mTask}-system, an abstraction is made. The current
-implementation runs on \textsc{mbed} supported devices.
+programmer with example code for \gls{Arduino} and \gls{mbed}. The sensor
+emits red light and measures the intensity of the light returned. The
+microcontroller hosting the device has to keep track of four seconds of samples
+to determine the heartbeat. In the \gls{mTask}-system, an abstraction is made.
+The current implementation runs on \gls{mbed} supported devices.
 
 \subsubsection{\gls{mTask} Classes}
 First, a class has to be devised to store the functionality of the sensor. The
 heartbeat sensor updates four values continuously, namely the heartbeat, the
-validity of the reading, the oxygen saturation and the validity of it. For
-every value a function is added to the new \CI{hb} class. Moreover, the
+oxygen saturation and the validity of the two. The real value and the validity
+are combined in an \gls{ADT} and functions are added for both of them in the
+new \CI{hb} class. The values are combined in such a way that they fit in a 16
+bit integer with the last bit representing the validity of the reading. The
 introduced datatype housing the values should implement the \CI{mTaskType}
 classes. The definition is as follows:
 
-\begin{lstlisting}[caption={The \texttt{hb} class}]
-:: Heartbeat = HB Int
-:: SP02      = SP02 Int
+\begin{lstlisting}[language=Clean,%
+       caption={The \texttt{hb} class and class implementations}]
+:: Heartbeat = HB Int Bool
+:: SP02      = SP02 Int Bool
+
+instance toByteCode Heartbeat
+       where toByteCode (HB i b) = "h" +++ (to16bit $ (i << 1) bitand (if b 1 0))
+instance toByteCode SP02 where ...
+
+instance fromByteCode Heartbeat
+       where fromByteCode s = let i = fromByteCode s //The Int from bytecode
+               in HB (i >> 1) (i bitand 1 > 0)
+instance fromByteCode SP02 where ...
 
-instance toByteCode Heartbeat, SP02
-instance fromByteCode Heartbeat, SP02
 derive class iTask Heartbeat, SP02
 
 class hb v where
        getHb     :: (v Heartbeat Expr)
-       validHb   :: (v Bool Expr)
        getSp02   :: (v SP02 Expr)
-       validSp02 :: (v Bool Expr)
 \end{lstlisting}
 
 \subsubsection{Bytecode Implementation}
@@ -128,36 +140,34 @@ single values and no assignment is possible. The following code shows the
 implementation. Dedicated bytecode instructions have been added to support the
 functionality.
 
-\begin{lstlisting}[caption={The \texttt{hb} bytecode instance}]
+\begin{lstlisting}[language=Clean,caption={The \texttt{hb} bytecode instance}]
 :: BC
        = BCNop
        | ...
        | BCGetHB
-       | BCValidHB
        | BCGetSP02
-       | BCValidSP02
-       | ...
 
 instance hb ByteCode where
        getHb = tell` [BCGetHB]
-       validHb = tell` [BCValidHB]
        getSp02 = tell` [BCGetSP02]
-       validSp02 = tell` [BCValidSP02]
 \end{lstlisting}
 
 \subsubsection{Device Interface}
 The bytecode instructions are added but still the functionality needs to be
 added to the device interface to be implemented by clients. The following
 addition to \CI{interface.h} and the interpreter shows the added instructions.
+When adding a peripheral, the devices not having the peripheral do not need to
+have their code recompiled. New instructions always get a higher bytecode
+number if added correctly. The peripheral byte in the device specification by
+default shows a negative flag for every peripheral. Only the peripherals added
+will be flagged positive.
 
-\begin{lstlisting}[caption={Adding the device interface}]
+\begin{lstlisting}[language=Clean,caption={Adding the device interface}]
 // interface.h
 ...
 #if HAVEHB == 1
 uint16_t get_hb();
-bool     valid_hb();
 uint16_t get_spo2();
-bool     valid_spo2();
 #endif
 ...
 
@@ -169,15 +179,9 @@ bool     valid_spo2();
                case BCGETHB:
                        stack[sp++] = get_hb();
                        break;
-               case BCVALIDHB:
-                       stack[sp++] = valid_hb();
-                       break;
                case BCGETSP02:
                        stack[sp++] = get_spo2();
                        break;
-               case BCVALIDSP02:
-                       stack[sp++] = valid_spo2();
-                       break;
 #endif
                ...
 \end{lstlisting}
@@ -187,10 +191,13 @@ The device client software always executes the \CI{real\_setup} in which the
 client software can setup the connection and peripherals. In the case of the
 heartbeat peripheral it starts a thread running the calculations. The thread
 started in the setup will set the global heartbeat and oxygen level variables
-so that the interface functions for it can access it. The code is then as
-follows:
+so that the interface functions for it can access it. This is listed in
+Listing~\ref{lst:hbding}. If interrupts were implemented, the \glspl{Task}
+using the heartbeat sensor could be executed on interrupt. The heartbeat thread
+can fire an interrupt everytime it calculated a new heartbeat.
 
-\begin{lstlisting}[language=C,caption={}]
+\begin{lstlisting}[label={lst:hbding},language=C,%
+       caption={Heartbeat code in the client}]
 Serial pc;
 Thread thread;
 
@@ -203,3 +210,31 @@ void real_setup(void) {
        thread.start(heartbeat_thread);
 }
 \end{lstlisting}
+
+\subsubsection{Example}
+The following code shows a complete example of a \gls{Task} controlling an
+\emph{STM} microcontroller containing a heartbeat sensor. The web application
+belonging to the server shows the heartbeat value and starts an alert
+\gls{Task} when it exceeds the value given or is no longer valid.
+This example also shows how named \gls{SDS} are handled.
+
+\begin{lstlisting}[language=Clean,caption={Heartbeat example}]
+hbwatch :: (Task a) Int -> Task ()
+hbwatch alert lim
+         =           makeDevice "stm32" stm32
+       >>=           connectDevice
+       >>= \stm    ->sendTaskToDevice "monitor" monitor (stm, OnInterval 200)
+       >>= \(t, sh)->mon (fromJust $ find (\x->x.name == "hb") sh)
+       >>* [OnAction (Action "Shutdown") $ always $ deleteDevice stm >>| shutDown 0]
+where
+       mon :: (Shared BCValue) -> Task ()
+       mon b = whileUnchanged (mapRead dynHB b)
+               \hb=:(HB i valid)->if (not valid || i > lim)
+                       alert (viewInformation "HB Okay" [] hb)
+
+       dynHB :: Dynamic -> HeartBeat
+       dynHB (a :: HeartBeat) = a
+
+       monitor = namedsds \hb=(0 Named hb) In
+               {main= hb = getHB :.  pub hb }
+\end{lstlisting}