update presentation, the body is there
[msc-thesis1617.git] / arch.example.tex
index 828e097..b8ef049 100644 (file)
@@ -1,5 +1,5 @@
 \subsection{Framework}
 \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
 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,
 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))
 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
 where
        dynInt :: Dynamic -> Int
        dynInt (a :: Int) = a
@@ -50,18 +51,21 @@ where
                        IF cool (ledOn LED1) (ledOff LED1) :.
                        digitalWrite D5 cool
                }
                        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}}
 \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.
 
 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)
 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
 \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)
 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
 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
 
 \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:
 
 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)
 derive class iTask Heartbeat, SP02
 
 class hb v where
        getHb     :: (v Heartbeat Expr)
-       validHb   :: (v Bool Expr)
        getSp02   :: (v SP02 Expr)
        getSp02   :: (v SP02 Expr)
-       validSp02 :: (v Bool Expr)
 \end{lstlisting}
 
 \subsubsection{Bytecode Implementation}
 \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.
 
 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
 :: BC
        = BCNop
        | ...
        | BCGetHB
-       | BCValidHB
        | BCGetSP02
        | BCGetSP02
-       | BCValidSP02
-       | ...
 
 instance hb ByteCode where
        getHb = tell` [BCGetHB]
 
 instance hb ByteCode where
        getHb = tell` [BCGetHB]
-       validHb = tell` [BCValidHB]
        getSp02 = tell` [BCGetSP02]
        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.
 \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();
 // interface.h
 ...
 #if HAVEHB == 1
 uint16_t get_hb();
-bool     valid_hb();
 uint16_t get_spo2();
 uint16_t get_spo2();
-bool     valid_spo2();
 #endif
 ...
 
 #endif
 ...
 
@@ -169,15 +179,9 @@ bool     valid_spo2();
                case BCGETHB:
                        stack[sp++] = get_hb();
                        break;
                case BCGETHB:
                        stack[sp++] = get_hb();
                        break;
-               case BCVALIDHB:
-                       stack[sp++] = valid_hb();
-                       break;
                case BCGETSP02:
                        stack[sp++] = get_spo2();
                        break;
                case BCGETSP02:
                        stack[sp++] = get_spo2();
                        break;
-               case BCVALIDSP02:
-                       stack[sp++] = valid_spo2();
-                       break;
 #endif
                ...
 \end{lstlisting}
 #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
 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;
 
 Serial pc;
 Thread thread;
 
@@ -203,3 +210,31 @@ void real_setup(void) {
        thread.start(heartbeat_thread);
 }
 \end{lstlisting}
        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}