\subsection{Framework}
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
started to monitor the output. When everything is finished, the devices are
removed and the system is shut down.

\begin{lstlisting}[language=Clean,label={lst:framework},
	caption={\gls{mTask} framework for building applications}]
w :: Task ()
w =         makeDevice "dev1" (...) >>= connectDevice
	>>= \dev1->makeDevice "dev2" (...) >>= connectDevice
	>>= \dev2->...
	...
	>>* [OnAction (Action "Shutdown") $ always
		$   deleteDevice dev1 >>| deleteDevice dev2
		>>| ...
		>>| shutDown 0
	]
\end{lstlisting}

\subsection{Thermostat}
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 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))
	>>* [OnAction (Action "Shutdown") $ always $ deleteDevice nod >>| deleteDevice stm >>| shutDown 0]
where
	dynInt :: Dynamic -> Int
	dynInt (a :: Int) = a

	sensing = sds \x=0 In {main=
			x =. analogRead A0 :. pub x
		}
	acting = sds \cool=False In {main=
			IF cool (ledOn LED1) (ledOff LED1) :.
			digitalWrite D5 cool
		}
	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 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}[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)
	>>| viewInformation "Done!" [] ()
	>>| treturn shs
where
	taskRemoved t d = isNothing $ find (\t1->t1.ident==t.ident) d.deviceTasks
\end{lstlisting}

The factorial function example from Chapter~\ref{chp:mtaskcont} can then be
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)
	@         fromJust o find (\x->x.humanName == "result")
	@         \s->s.MTaskShare.value
where
	fact i = sds \y=i
		In namedsds \x=(1 Named "result")
		In {main = IF (y <=. lit 1)
			( pub x :. retrn                  )
			( x =. x *. y :.  y =. y -. lit 1 )}
\end{lstlisting}

\subsection{Heartbeat \& Oxygen Saturation Sensor}
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 \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
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}[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 ...

derive class iTask Heartbeat, SP02

class hb v where
	getHb     :: (v Heartbeat Expr)
	getSp02   :: (v SP02 Expr)
\end{lstlisting}

\subsubsection{Bytecode Implementation}
The class is available now, and the implementation can be created. The
implementation is trivial since the functionality is limited to retrieving
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}[language=Clean,caption={The \texttt{hb} bytecode instance}]
:: BC
	= BCNop
	| ...
	| BCGetHB
	| BCGetSP02

instance hb ByteCode where
	getHb = tell` [BCGetHB]
	getSp02 = tell` [BCGetSP02]
\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}[language=Clean,caption={Adding the device interface}]
// interface.h
...
#if HAVEHB == 1
uint16_t get_hb();
uint16_t get_spo2();
#endif
...

// interpret.c
	while(pc < plen){
		switch(program[pc++]){
		...
#if HAVEHB == 1
		case BCGETHB:
			stack[sp++] = get_hb();
			break;
		case BCGETSP02:
			stack[sp++] = get_spo2();
			break;
#endif
		...
\end{lstlisting}

\subsubsection{Client Software}
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. 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}[label={lst:hbding},language=C,%
	caption={Heartbeat code in the client}]
Serial pc;
Thread thread;

void heartbeat_thread(void) {
	// Constant heartbeat calculations
}

void real_setup(void) {
	pc.baud(19200);
	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}
