# Day 4: Sensing (Whiteboard)
## I/O Threads
Let's say we have a serial-based sensor, such as a GPS.
All of the I/O threads inherit from `goby::middleware::io::detail::IOThread`:
- Subscribe to outgoing data (Goby -> sensor): `protobuf::IOData`, group: `line_out_group`
- Handles sync between boost::asio and the Goby interthread transporter
- Uniform error handling (`protobuf::IOStatus` on `line_in_group`)
Implementors must:
- `open_socket()`: (Try to) open the socket
- `async_read()`: Start an asynchronous read from the socket (return a "message")
- `async_write()`: Start an asynchronous write to the socket (free function `basic_async_write`).
### Serial
```mermaid
classDiagram
IOThread <|-- detail__SerialThread
detail__SerialThread <|-- SerialThreadLineBased
class IOThread {
+initialize()
+finalize()
#write()
#handle_read_success()
#handle_write_success()
#handle_read_error()
#handle_write_error()
#mutable_socket()
#mutable_io()
#socket_is_open()
#async_read()
#open_socket() virtual
#async_read() virtual
#async_write() virtual
-loop()
}
class detail__SerialThread {
#mutable_serial_port()
-async_write() override
-open_socket() override
-publish_status()
}
class SerialThreadLineBased {
-async_read() override
}
```
Switch to becoming a user of the IOThreads.
- Each I/O thread is a Goby Thread (by default the `SimpleThread`: interthread/interprocess/intervehicle)
```mermaid
graph TD
SerialThreadLineBased-->|protobuf::IOData on gps_in|GPSDriver
GPSDriver-->|protobuf::IOData on gps_out|SerialThreadLineBased
```
### TCP
Let's say our GPS was connected to some remote server which then reserves the data as a TCP server.
## goby_gps
Is a client for the `gpsd` server.
goby_gps publications:
- TPV (**T**ime **P**osition **V**elocity)
- SKY (sky view: satellite)
## Sensor state machines
```mermaid
stateDiagram-v2
[*] --> StartLogging
StartLogging --> Logging
Logging-->StopLogging
StopLogging-->Sleep
Sleep-->StartLogging
```
Writing a simulator and a driver for a CTD (**C**onductivity/salinity, **T**emperature, **D**epth/pressure) instrument.
We're going to use `boost::statechart` along with Goby.
- Uses classes to represent states:
- constructor = entry
- destructor = exit
```mermaid
stateDiagram-v2
[*]-->StartLogging
StartLogging
Logging
StopLogging
Sleep
```
Transitions are driven by "events"
```mermaid
stateDiagram-v2
[*] --> StartLogging
StartLogging --> Logging : EvLoggingStarted
Logging-->StopLogging : EvDoStopLogging
StopLogging-->Sleep : EvEnterSleep
Sleep-->StartLogging : EvDoStartLogging
```
Each state can have a list of reactions.
```mermaid
stateDiagram-v2
[*] --> Sleep
StartLogging --> Logging : EvLoggingStarted
Logging-->StopLogging : EvDoStopLogging
StopLogging-->Sleep : EvEnterSleep
Sleep-->StartLogging : EvDoStartLogging
```
From the main thread, we might want to know what state the machine is in.
Let's look at the interface for our CTD, based on NMEA-0183:
```
RS-232, 9600 baud
> means message from the control computer to the CTD
< means message from the CTD to the control computer
*CS is the standard NMEA-0183 checksum
Wake up the CTD
> $ZCCMD,WAKE*CS\r\n
Wake received, CTD out of low power mode and ready to commence logging
< $ZCACK,WAKE*CS\r\n
Start logging
> $ZCCMD,START*CS\r\n
Logging started
< $ZCACK,START*CS\r\n
Data (streams at 1 Hz)
< $ZCDAT,<salinity>,<temp, deg C>,<depth, meters>*CS
< $ZCDAT,31.5,10.4,150*CS\r\n
< $ZCDAT,31.5,10.3,151*CS\r\n
< $ZCDAT,31.4,10.2,152*CS\r\n
Stop logging
> $ZCCMD,STOP*CS\r\n
Logging stopped
< $ZCACK,STOP*CS\r\n
Enter low power mode
> $ZCCMD,SLEEP*CS\r\n
< $ZCACK,SLEEP*CS\r\n
```
Given this, let's add a serial thread
## Simulators
Key goals
- Replicate the real behavior *and* the API of the sensor
- Start off by capturing "key behavior" and then iterate.
---
```
```