\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}[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 ()
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 = TCP
\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}[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}[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. For every value a function is
added to the new \CI{hb} class. Moreover, 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

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}
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}[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}]
// interface.h
...
#if HAVEHB == 1
uint16_t get_hb();
bool     valid_hb();
uint16_t get_spo2();
bool     valid_spo2();
#endif
...

// interpret.c
	while(pc < plen){
		switch(program[pc++]){
		...
#if HAVEHB == 1
		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}

\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. The code is then as
follows:

\begin{lstlisting}[language=C,caption={}]
Serial pc;
Thread thread;

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

void real_setup(void) {
	pc.baud(19200);
	thread.start(heartbeat_thread);
}
\end{lstlisting}
