Control application: Difference between revisions

From Aquarium-Control
Jump to navigation Jump to search
 
(21 intermediate revisions by the same user not shown)
Line 30: Line 30:


There is a [[Release procedure|release procedure]] which is highly recommended to be followed also by anyone developing the SW further.
There is a [[Release procedure|release procedure]] which is highly recommended to be followed also by anyone developing the SW further.
= Requirements =
The requirement are structured in two levels:
* system requirements
* software requirements
The requirements coverage report is generated with the following command: <code>oft trace doc src tests -o Html > doc/req/coverage.html</code>
The linkage of the software requirements to the implementation and related test cases has been reverse engineered using the following two prompts for each function group:
<blockquote>Check all software requirements of thermal.md if you can find the matching implementations and tests.</blockquote>
<blockquote>Now do the reverse: Go through the implementation and test cases in src/sensors and the integration tests in tests/sensors and label every test case and at least every function linking to a matching software requirement from sensors.md.</blockquote>


= Architecture =
= Architecture =
Line 154: Line 168:
== Build time ==
== Build time ==
Building the release on a Raspberry Pi 4 takes around 16 minutes.
Building the release on a Raspberry Pi 4 takes around 16 minutes.
= Test strategy =
== Unit tests ==
Located within the implementation code files within <code>src</code>.
== Integration tests in test ==
Separated from implementation code to the <code>test</code> folder.
== Code coverage measurement ==
=== Using tarpaulin ===
<code>cargo tarpaulin --features "test-utils" --out Html</code>
The measurement takes app. 22 minutes.
=== Using llvm-cov ===
<code>cargo +nightly llvm-cov --features "test-utils" --html --ignore-filename-regex '(main\.rs|.*_channels\.rs|mock.*\.rs|pingable\.rs|privilege_check\.rs|recorder_data_frame\.rs)'</code>
The excluded files contain primarily debug functionality or wrappers without intrinsic logic which distorts the coverage measurement and where adding test cases would be meaningless.
The nightly compiler build needs to be used because the application uses gating to exclude the unit tests from the coverage measurement: <code>#[cfg_attr(coverage_nightly, coverage(off))]</code>
The measurements takes app. 8 minutes.
=== Comparing the results from llvm-cov and tarpaulin ===
Based on commit <code>8f557814f679c30ebd70e181f2a3f996ce0e295c</code>.
    {| class="wikitable sortable"                                                                                                                                                                         
    |+ Module Summary Comparison: llvm-cov vs. tarpaulin (Line Coverage)                                                                                                                                 
    |-                                                                                                                                                                                                   
    ! Subsystem / Module !! llvm-cov Line Coverage !! tarpaulin Line Coverage !! Difference (% pts)                                                                                                       
    |- style="font-weight:bold; background-color:#f0f0f0;"                                                                                                                                               
    | '''TOTAL (All Application Source Files)''' || 71.53% (11216/15681) || 54.48% (4929/9047) || +17.04%                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/bin/</code> || 0.00% (0/597) || 0.00% (0/457) || +0.00%                                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/database/</code> || 69.73% (1283/1840) || 52.72% (631/1197) || +17.01%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/dispatch/</code> || 46.32% (44/95) || 33.80% (24/71) || +12.51%                                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/food/</code> || 79.06% (721/912) || 58.80% (244/415) || +20.26%                                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/launch/</code> || 84.06% (944/1123) || 59.48% (411/691) || +24.58%                                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/mineral/</code> || 88.11% (467/530) || 60.33% (181/300) || +27.78%                                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/mocks/</code> || 58.82% (610/1037) || 55.57% (334/601) || +3.25%                                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/permission/</code> || 94.25% (377/400) || 81.58% (93/114) || +12.67%                                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/recorder/</code> || 77.46% (701/905) || 47.50% (304/640) || +29.96%                                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/relays/</code> || 60.22% (448/744) || 47.58% (216/454) || +12.64%                                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/sensors/</code> || 75.70% (1748/2309) || 54.76% (656/1198) || +20.95%                                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/simulator/</code> || 3.07% (10/326) || 2.05% (4/195) || +1.02%                                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/test_server/</code> || 67.93% (822/1210) || 59.67% (429/719) || +8.27%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/thermal/</code> || 88.45% (1019/1152) || 67.96% (437/643) || +20.49%                                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/utilities/</code> || 80.91% (1187/1467) || 75.10% (564/751) || +5.81%                                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/watchmen/</code> || 64.29% (135/210) || 54.69% (70/128) || +9.60%                                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/water/</code> || 86.10% (700/813) || 71.18% (331/465) || +14.92%                                                                                                                         
    |} 
    {| class="wikitable sortable"                                                                                                                                                                         
    |+ Detailed File Comparison: llvm-cov vs. tarpaulin (Line Coverage)                                                                                                                                   
    |-                                                                                                                                                                                                   
    ! File Path !! llvm-cov Line Coverage !! tarpaulin Line Coverage !! Difference (% pts)                                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/bin/aquarium_client.rs</code> || 0.00% (0/117) || 0.00% (0/98) || +0.00%                                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/bin/aquarium_commissioning.rs</code> || 0.00% (0/426) || 0.00% (0/315) || +0.00%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/bin/aquarium_test_server.rs</code> || 0.00% (0/54) || 0.00% (0/44) || +0.00%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/database/database_interface_feed_trait.rs</code> || 77.86% (102/131) || 58.06% (54/93) || +19.80%                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/database/pingable.rs</code> || 44.44% (4/9) || 33.33% (2/6) || +11.11%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface.rs</code> || 65.79% (250/380) || 48.57% (119/245) || +17.22%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_balling.rs</code> || 69.31% (140/202) || 53.91% (69/128) || +15.40%                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_data.rs</code> || 60.76% (48/79) || 59.62% (31/52) || +1.14%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_feed.rs</code> || 63.70% (186/292) || 45.00% (90/200) || +18.70%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_heating_set_vals.rs</code> || 66.12% (80/121) || 37.97% (30/79) || +28.15%                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_heating_stats.rs</code> || 77.65% (139/179) || 67.59% (73/108) || +10.06%                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_heating_stats_data_transfer.rs</code> || 100.00% (7/7) || 100.00% (2/2) || +0.00%                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_midnight.rs</code> || 100.00% (8/8) || 100.00% (4/4) || +0.00%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_refill.rs</code> || 66.94% (83/124) || 57.14% (48/84) || +9.80%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_schedule.rs</code> || 85.54% (142/166) || 69.16% (74/107) || +16.38%                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_test_utils.rs</code> || 100.00% (10/10) || 100.00% (5/5) || +0.00%                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/database/sql_interface_ventilation_set_vals.rs</code> || 63.64% (84/132) || 35.71% (30/84) || +27.92%                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/dispatch/ipc_message.rs</code> || 0.00% (0/51) || 0.00% (0/41) || +0.00%                                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/dispatch/messaging.rs</code> || 100.00% (44/44) || 80.00% (24/30) || +20.00%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/food/feed.rs</code> || 86.40% (305/353) || 62.65% (104/166) || +23.75%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/food/feed_channels.rs</code> || 71.43% (10/14) || 57.14% (4/7) || +14.29%                                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/food/feed_profile.rs</code> || 100.00% (100/100) || 100.00% (4/4) || +0.00%                                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/food/feed_schedule_entry.rs</code> || 97.62% (82/84) || 100.00% (10/10) || -2.38%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/food/food_injection.rs</code> || 62.43% (113/181) || 56.64% (64/113) || +5.79%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/food/food_injection_actuator_state.rs</code> || 61.11% (11/18) || 54.55% (6/11) || +6.57%                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/food/food_injection_signals.rs</code> || 62.50% (100/160) || 48.08% (50/104) || +14.42%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/launch/config_app.rs</code> || 82.35% (98/119) || 57.14% (44/77) || +25.21%                                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/launch/execution_config.rs</code> || 86.30% (63/73) || 72.34% (34/47) || +13.96%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/launch/pid_file.rs</code> || 96.67% (58/60) || 77.14% (27/35) || +19.52%                                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/launch/run.rs</code> || 83.40% (725/869) || 58.74% (306/521) || +24.66%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/mineral/balling.rs</code> || 88.08% (340/386) || 61.08% (135/221) || +27.00%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/mineral/balling_channels.rs</code> || 71.43% (10/14) || 57.14% (4/7) || +14.29%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/mineral/balling_profile.rs</code> || 100.00% (71/71) || 100.00% (18/18) || +0.00%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/mineral/balling_set_val.rs</code> || 77.97% (46/59) || 44.44% (24/54) || +33.53%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_dht.rs</code> || 74.07% (40/54) || 64.71% (22/34) || +9.36%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_food_injection.rs</code> || 83.33% (20/24) || 75.00% (12/16) || +8.33%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_i2c_interface.rs</code> || 32.50% (13/40) || 28.00% (7/25) || +4.50%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_peristaltic_pump.rs</code> || 85.00% (17/20) || 72.73% (8/11) || +12.27%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_relay_manager.rs</code> || 82.50% (33/40) || 75.86% (22/29) || +6.64%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_sql_interface.rs</code> || 66.21% (241/364) || 63.81% (134/210) || +2.40%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/mocks/mock_water_injection.rs</code> || 82.61% (19/23) || 75.00% (12/16) || +7.61%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/permission/process_privileges.rs</code> || 94.25% (377/400) || 81.58% (93/114) || +12.67%                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/recorder/recorder.rs</code> || 84.77% (590/696) || 54.12% (269/497) || +30.65%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/recorder/recorder_channels.rs</code> || 58.82% (10/17) || 45.45% (5/11) || +13.37%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/recorder/recorder_data_frame.rs</code> || 52.66% (101/192) || 22.31% (27/121) || +30.35%                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/relays/actuator_state.rs</code> || 74.07% (20/27) || 75.00% (15/20) || -0.93%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/relays/aquarium_device.rs</code> || 66.67% (14/21) || 68.75% (11/16) || -2.08%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/relays/relay_manager.rs</code> || 58.46% (394/674) || 45.43% (179/394) || +13.03%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/relays/relay_manager_channels.rs</code> || 90.91% (20/22) || 45.83% (11/24) || +45.08%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/sensors/atlas_scientific.rs</code> || 74.77% (329/440) || 55.42% (92/166) || +19.35%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/sensors/atlas_scientific_channels.rs</code> || 69.23% (9/13) || 50.00% (3/6) || +19.23%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/sensors/dht.rs</code> || 75.00% (105/140) || 53.64% (59/110) || +21.36%                                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/sensors/dht_channels.rs</code> || 69.23% (9/13) || 50.00% (3/6) || +19.23%                                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/sensors/ds18b20.rs</code> || 74.55% (123/165) || 51.09% (47/92) || +23.46%                                                                                                               
    |-                                                                                                                                                                                                   
    | <code>src/sensors/ds18b20_channels.rs</code> || 69.23% (9/13) || 50.00% (3/6) || +19.23%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/sensors/i2c_interface.rs</code> || 76.54% (362/473) || 57.51% (153/266) || +19.03%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/sensors/i2c_interface_channels.rs</code> || 69.23% (9/13) || 50.00% (3/6) || +19.23%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/sensors/sensor_manager.rs</code> || 76.10% (761/1000) || 54.34% (282/519) || +21.76%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/sensors/sensor_manager_channels.rs</code> || 84.62% (33/39) || 75.00% (9/12) || +9.62%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/thermal/heating.rs</code> || 90.96% (332/365) || 68.60% (148/216) || +22.36%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/thermal/heating_actuation.rs</code> || 84.47% (87/103) || 67.24% (39/58) || +17.23%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/thermal/heating_channels.rs</code> || 75.00% (15/20) || 50.00% (5/10) || +25.00%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/thermal/heating_set_vals.rs</code> || 87.50% (35/40) || 64.29% (18/28) || +23.21%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/thermal/heating_stats_entry.rs</code> || 94.67% (142/150) || 82.22% (74/90) || +12.44%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/thermal/saw_tooth_profile.rs</code> || 100.00% (64/64) || 100.00% (23/23) || +0.00%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/thermal/saw_tooth_profile_config.rs</code> || 70.83% (17/24) || 50.00% (7/14) || +20.83%                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/thermal/temperature_gradient.rs</code> || 100.00% (64/64) || 100.00% (32/32) || +0.00%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/thermal/thermal_control_status.rs</code> || 81.25% (26/32) || 58.82% (10/17) || +22.43%                                                                                                   
    |-                                                                                                                                                                                                   
    | <code>src/thermal/ventilation.rs</code> || 87.67% (192/219) || 61.16% (74/121) || +26.51%                                                                                                           
    |-                                                                                                                                                                                                   
    | <code>src/thermal/ventilation_channels.rs</code> || 75.00% (15/20) || 50.00% (5/10) || +25.00%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/thermal/ventilation_set_vals.rs</code> || 58.82% (30/51) || 58.82% (20/34) || +0.00%                                                                                                     
    |-                                                                                                                                                                                                   
    | <code>src/utilities/config.rs</code> || 76.99% (830/1078) || 72.84% (437/600) || +4.15%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/utilities/spin_sleeper.rs</code> || 79.17% (19/24) || 69.23% (9/13) || +9.94%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/utilities/thread_builder.rs</code> || 92.59% (25/27) || 78.57% (11/14) || +14.02%                                                                                                         
    |-                                                                                                                                                                                                   
    | <code>src/watchmen/monitors.rs</code> || 64.29% (135/210) || 54.69% (70/128) || +9.60%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/water/refill.rs</code> || 86.81% (447/515) || 69.45% (216/311) || +17.36%                                                                                                                 
    |-                                                                                                                                                                                                   
    | <code>src/water/refill_channels.rs</code> || 71.43% (10/14) || 57.14% (4/7) || +14.29%                                                                                                             
    |-                                                                                                                                                                                                   
    | <code>src/water/tank_level_switch.rs</code> || 84.14% (191/227) || 74.47% (105/141) || +9.67%                                                                                                       
    |-                                                                                                                                                                                                   
    | <code>src/water/tank_level_switch_signals.rs</code> || 90.36% (75/83) || 86.96% (40/46) || +3.40%                                                                                                   
    |}
== System tests using the simulator ==
Running the application in simulator mode.

Latest revision as of 11:42, 1 August 2026

The main control application of Aquarium control implements the following features:

The control of the relays for operating the devices can use two different modes:

Additionally, the main control application implements the following supporting features:

The application is written in Rust and is automatically started using systemd.

The documentation of the software is available here.

Development for the main control application requires the setup of the development environment.

There is a release procedure which is highly recommended to be followed also by anyone developing the SW further.

Requirements

The requirement are structured in two levels:

  • system requirements
  • software requirements

The requirements coverage report is generated with the following command: oft trace doc src tests -o Html > doc/req/coverage.html

The linkage of the software requirements to the implementation and related test cases has been reverse engineered using the following two prompts for each function group:

Check all software requirements of thermal.md if you can find the matching implementations and tests.

Now do the reverse: Go through the implementation and test cases in src/sensors and the integration tests in tests/sensors and label every test case and at least every function linking to a matching software requirement from sensors.md.

Architecture

Startup of the application

The startup uses a two-layer approach:

  1. main() - Simple error handler wrapper that calls run() and exits with code 1 on errors
  2. run() - The actual initialization orchestrator that performs the major steps

Phase 1: Command Line & Configuration

  • Parses command line arguments ("help", "version", config file)
  • Sets the default config file: /etc/aquarium_control/aquarium_control.toml
  • Loads configuration and creates ExecutionConfig (boolean flags determining which modules to run)

Phase 2: System Setup

  • Initializes the logging system
  • Logs version information and executable hash
  • Verifies root privileges (required for hardware access)
  • Publishes process ID to file for client communication

Phase 3: Database & Hardware

  • Connects to database (MariaDB)
  • Creates component-specific SQL interfaces (Schedule, Balling, Refill, Heating, Feed, Data)
  • Validates database schema and version compatibility
  • Initializes hardware components if configured:
    • RGB LEDs
    • GPIO handlers
    • Tank level switch
    • I2C interface
    • Atlas Scientific sensors
    • DHT temperature/humidity sensors
    • Relay actuator (Controllino)

Phase 4: Communication Channels

  • Creates the Channels struct containing ~30+ inter-thread communication channels
  • Uses custom AquaSender/AquaReceiver wrappers for MPSC channels
  • Establishes bidirectional and unidirectional message paths between all modules

Phase 5: Component Initialization

Instantiates all high-level control components:

  • data logger
  • sensor manager
  • relay manager
  • food injection
  • mineral dosing (balling)
  • water injection/refill
  • heating control
  • ventilation control
  • monitors
  • watchdog
  • schedule checker
  • temperature gradient calculation
  • IPC messaging system

Phase 6: Thread Spawning

  • Uses std::thread::scope for guaranteed cleanup
  • Spawns threads conditionally based on ExecutionConfig flags
  • Critical: A 3-second startup delay allows sensors to acquire first data before control loops activate

Architecture of thread configuration

  • The Channels module (src/launch/channels.rs) acts as a central wiring diagram, with the Signal Handler serving as the main event coordinator.
  • The ExecutionConfig decouples configuration from execution - threads only receive flags about which modules are active, not the full config - this also avoids ownership issues.

The application makes use of an asynchronous runtime for the main application.

Measurement using Atlas Scientific circuits

The core Abstraction (AtlasScientificDriver Trait) is defined in src/sensors/atlas_scientific_driver.rs, this trait serves as the common interface for all sensor types. It enforces three key behaviors:

  • send_request_to_i2c_interface: Encapsulates how to trigger a measurement (e.g., constructing specific I2C commands).
  • receive_response_from_i2c_interface: Handles parsing the raw byte response from the I2C bus into a normalized floating-point value.
  • device_init: Performs hardware-specific setup (crucial for OEM type sensor circuit).

Circuit-type-specific implementations

  • OEM Driver (AtlasScientificOem):
    • Protocol: Uses a binary, register-based protocol.
    • Initialization: Requires an explicit "Wake Up" command (writing to REG_WAKEUP) and verifies the hardware by reading the REG_DEVICE_TYPE.
    • Read Cycle: Writes a register address (e.g., REG_DATA_MSB_PH), waits for a short processing time, and reads 4 bytes.
    • Parsing: Decodes the 4-byte response as a Big Endian unsigned integer and divides it by a specific scale factor (e.g., 1000.0) to get the float value.
  • EZO Driver (AtlasScientificEzo):
    • Protocol: Uses a text-based (ASCII) command protocol.
    • Initialization: Minimal or no-op (these devices are typically always ready or auto-on).
    • Read Cycle: Sends the ASCII character 'R', waits for a longer processing time, and reads a fixed 8-byte response.
    • Parsing: Validates "magic" start/end bytes (1 and 0), converts the inner ASCII string (e.g., "23.50") to a float.

Context and factory (AtlasScientific struct)

  • The main AtlasScientific struct acts as the context. It holds a HashMap<AquariumSignal, Box<dyn AtlasScientificDriver>>.
  • Factory Logic: The create_drivers method functions as a factory. It reads the aquarium_control.toml configuration (specifically fields like sensor_type_ph = "oem" or "ezo") and

instantiates the correct driver implementation for each sensor (temperature, pH, conductivity).

  • Execution: The main thread loop calls driver.send_request... and driver.receive_response... on the active driver, unaware of whether it is communicating via binary registers or ASCII commands.

Communication Flow

The architecture decouples protocol logic from bus I/O:

  1. Driver creates an abstraction-specific I2cRequest (containing address, write buffer, read length, delay).
  2. AtlasScientific thread sends this request via a channel to the I2cInterface thread.
  3. I2cInterface thread performs the physical I2C transaction.
  4. AtlasScientific thread receives the raw bytes and passes them back to the driver for parsing.
  5. Additionally, AtlasScientific performs measurement value checks informing deviations to Monitors.

This design enables the system to mix and match sensor types (e.g., an OEM type pH sensor circuit with an EZO type temperature sensor circuit) purely through configuration changes.

Monitors

The Monitors module (src/watchmen/monitors.rs) is a dedicated thread that aggregates and stores historical system state information. It interacts with the following modules:

  • Refill
  • Signal handler

The Monitors thread receives data from the other thread by polling the channels.

The data is transferred in specific structs ("Views"), e.g. RefillView.

Monitors contains a deduplication logic: Data is only stored when it differs from previous sample.

The number of samples is also limited (rolling window), to avoid overflow.

Commissioning

For the commissioning of the aquarium control, there is a separate binary which resides in src/bin/commissioning.rs.

Development environment

Install Rust

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Install additional development libraries

sudo apt-get install -y libudev-dev pkg-config

Build time

Building the release on a Raspberry Pi 4 takes around 16 minutes.

Test strategy

Unit tests

Located within the implementation code files within src.

Integration tests in test

Separated from implementation code to the test folder.

Code coverage measurement

Using tarpaulin

cargo tarpaulin --features "test-utils" --out Html

The measurement takes app. 22 minutes.

Using llvm-cov

cargo +nightly llvm-cov --features "test-utils" --html --ignore-filename-regex '(main\.rs|.*_channels\.rs|mock.*\.rs|pingable\.rs|privilege_check\.rs|recorder_data_frame\.rs)'

The excluded files contain primarily debug functionality or wrappers without intrinsic logic which distorts the coverage measurement and where adding test cases would be meaningless.

The nightly compiler build needs to be used because the application uses gating to exclude the unit tests from the coverage measurement: #[cfg_attr(coverage_nightly, coverage(off))]

The measurements takes app. 8 minutes.

Comparing the results from llvm-cov and tarpaulin

Based on commit 8f557814f679c30ebd70e181f2a3f996ce0e295c.

Module Summary Comparison: llvm-cov vs. tarpaulin (Line Coverage)
Subsystem / Module llvm-cov Line Coverage tarpaulin Line Coverage Difference (% pts)
TOTAL (All Application Source Files) 71.53% (11216/15681) 54.48% (4929/9047) +17.04%
src/bin/ 0.00% (0/597) 0.00% (0/457) +0.00%
src/database/ 69.73% (1283/1840) 52.72% (631/1197) +17.01%
src/dispatch/ 46.32% (44/95) 33.80% (24/71) +12.51%
src/food/ 79.06% (721/912) 58.80% (244/415) +20.26%
src/launch/ 84.06% (944/1123) 59.48% (411/691) +24.58%
src/mineral/ 88.11% (467/530) 60.33% (181/300) +27.78%
src/mocks/ 58.82% (610/1037) 55.57% (334/601) +3.25%
src/permission/ 94.25% (377/400) 81.58% (93/114) +12.67%
src/recorder/ 77.46% (701/905) 47.50% (304/640) +29.96%
src/relays/ 60.22% (448/744) 47.58% (216/454) +12.64%
src/sensors/ 75.70% (1748/2309) 54.76% (656/1198) +20.95%
src/simulator/ 3.07% (10/326) 2.05% (4/195) +1.02%
src/test_server/ 67.93% (822/1210) 59.67% (429/719) +8.27%
src/thermal/ 88.45% (1019/1152) 67.96% (437/643) +20.49%
src/utilities/ 80.91% (1187/1467) 75.10% (564/751) +5.81%
src/watchmen/ 64.29% (135/210) 54.69% (70/128) +9.60%
src/water/ 86.10% (700/813) 71.18% (331/465) +14.92%
Detailed File Comparison: llvm-cov vs. tarpaulin (Line Coverage)
File Path llvm-cov Line Coverage tarpaulin Line Coverage Difference (% pts)
src/bin/aquarium_client.rs 0.00% (0/117) 0.00% (0/98) +0.00%
src/bin/aquarium_commissioning.rs 0.00% (0/426) 0.00% (0/315) +0.00%
src/bin/aquarium_test_server.rs 0.00% (0/54) 0.00% (0/44) +0.00%
src/database/database_interface_feed_trait.rs 77.86% (102/131) 58.06% (54/93) +19.80%
src/database/pingable.rs 44.44% (4/9) 33.33% (2/6) +11.11%
src/database/sql_interface.rs 65.79% (250/380) 48.57% (119/245) +17.22%
src/database/sql_interface_balling.rs 69.31% (140/202) 53.91% (69/128) +15.40%
src/database/sql_interface_data.rs 60.76% (48/79) 59.62% (31/52) +1.14%
src/database/sql_interface_feed.rs 63.70% (186/292) 45.00% (90/200) +18.70%
src/database/sql_interface_heating_set_vals.rs 66.12% (80/121) 37.97% (30/79) +28.15%
src/database/sql_interface_heating_stats.rs 77.65% (139/179) 67.59% (73/108) +10.06%
src/database/sql_interface_heating_stats_data_transfer.rs 100.00% (7/7) 100.00% (2/2) +0.00%
src/database/sql_interface_midnight.rs 100.00% (8/8) 100.00% (4/4) +0.00%
src/database/sql_interface_refill.rs 66.94% (83/124) 57.14% (48/84) +9.80%
src/database/sql_interface_schedule.rs 85.54% (142/166) 69.16% (74/107) +16.38%
src/database/sql_interface_test_utils.rs 100.00% (10/10) 100.00% (5/5) +0.00%
src/database/sql_interface_ventilation_set_vals.rs 63.64% (84/132) 35.71% (30/84) +27.92%
src/dispatch/ipc_message.rs 0.00% (0/51) 0.00% (0/41) +0.00%
src/dispatch/messaging.rs 100.00% (44/44) 80.00% (24/30) +20.00%
src/food/feed.rs 86.40% (305/353) 62.65% (104/166) +23.75%
src/food/feed_channels.rs 71.43% (10/14) 57.14% (4/7) +14.29%
src/food/feed_profile.rs 100.00% (100/100) 100.00% (4/4) +0.00%
src/food/feed_schedule_entry.rs 97.62% (82/84) 100.00% (10/10) -2.38%
src/food/food_injection.rs 62.43% (113/181) 56.64% (64/113) +5.79%
src/food/food_injection_actuator_state.rs 61.11% (11/18) 54.55% (6/11) +6.57%
src/food/food_injection_signals.rs 62.50% (100/160) 48.08% (50/104) +14.42%
src/launch/config_app.rs 82.35% (98/119) 57.14% (44/77) +25.21%
src/launch/execution_config.rs 86.30% (63/73) 72.34% (34/47) +13.96%
src/launch/pid_file.rs 96.67% (58/60) 77.14% (27/35) +19.52%
src/launch/run.rs 83.40% (725/869) 58.74% (306/521) +24.66%
src/mineral/balling.rs 88.08% (340/386) 61.08% (135/221) +27.00%
src/mineral/balling_channels.rs 71.43% (10/14) 57.14% (4/7) +14.29%
src/mineral/balling_profile.rs 100.00% (71/71) 100.00% (18/18) +0.00%
src/mineral/balling_set_val.rs 77.97% (46/59) 44.44% (24/54) +33.53%
src/mocks/mock_dht.rs 74.07% (40/54) 64.71% (22/34) +9.36%
src/mocks/mock_food_injection.rs 83.33% (20/24) 75.00% (12/16) +8.33%
src/mocks/mock_i2c_interface.rs 32.50% (13/40) 28.00% (7/25) +4.50%
src/mocks/mock_peristaltic_pump.rs 85.00% (17/20) 72.73% (8/11) +12.27%
src/mocks/mock_relay_manager.rs 82.50% (33/40) 75.86% (22/29) +6.64%
src/mocks/mock_sql_interface.rs 66.21% (241/364) 63.81% (134/210) +2.40%
src/mocks/mock_water_injection.rs 82.61% (19/23) 75.00% (12/16) +7.61%
src/permission/process_privileges.rs 94.25% (377/400) 81.58% (93/114) +12.67%
src/recorder/recorder.rs 84.77% (590/696) 54.12% (269/497) +30.65%
src/recorder/recorder_channels.rs 58.82% (10/17) 45.45% (5/11) +13.37%
src/recorder/recorder_data_frame.rs 52.66% (101/192) 22.31% (27/121) +30.35%
src/relays/actuator_state.rs 74.07% (20/27) 75.00% (15/20) -0.93%
src/relays/aquarium_device.rs 66.67% (14/21) 68.75% (11/16) -2.08%
src/relays/relay_manager.rs 58.46% (394/674) 45.43% (179/394) +13.03%
src/relays/relay_manager_channels.rs 90.91% (20/22) 45.83% (11/24) +45.08%
src/sensors/atlas_scientific.rs 74.77% (329/440) 55.42% (92/166) +19.35%
src/sensors/atlas_scientific_channels.rs 69.23% (9/13) 50.00% (3/6) +19.23%
src/sensors/dht.rs 75.00% (105/140) 53.64% (59/110) +21.36%
src/sensors/dht_channels.rs 69.23% (9/13) 50.00% (3/6) +19.23%
src/sensors/ds18b20.rs 74.55% (123/165) 51.09% (47/92) +23.46%
src/sensors/ds18b20_channels.rs 69.23% (9/13) 50.00% (3/6) +19.23%
src/sensors/i2c_interface.rs 76.54% (362/473) 57.51% (153/266) +19.03%
src/sensors/i2c_interface_channels.rs 69.23% (9/13) 50.00% (3/6) +19.23%
src/sensors/sensor_manager.rs 76.10% (761/1000) 54.34% (282/519) +21.76%
src/sensors/sensor_manager_channels.rs 84.62% (33/39) 75.00% (9/12) +9.62%
src/thermal/heating.rs 90.96% (332/365) 68.60% (148/216) +22.36%
src/thermal/heating_actuation.rs 84.47% (87/103) 67.24% (39/58) +17.23%
src/thermal/heating_channels.rs 75.00% (15/20) 50.00% (5/10) +25.00%
src/thermal/heating_set_vals.rs 87.50% (35/40) 64.29% (18/28) +23.21%
src/thermal/heating_stats_entry.rs 94.67% (142/150) 82.22% (74/90) +12.44%
src/thermal/saw_tooth_profile.rs 100.00% (64/64) 100.00% (23/23) +0.00%
src/thermal/saw_tooth_profile_config.rs 70.83% (17/24) 50.00% (7/14) +20.83%
src/thermal/temperature_gradient.rs 100.00% (64/64) 100.00% (32/32) +0.00%
src/thermal/thermal_control_status.rs 81.25% (26/32) 58.82% (10/17) +22.43%
src/thermal/ventilation.rs 87.67% (192/219) 61.16% (74/121) +26.51%
src/thermal/ventilation_channels.rs 75.00% (15/20) 50.00% (5/10) +25.00%
src/thermal/ventilation_set_vals.rs 58.82% (30/51) 58.82% (20/34) +0.00%
src/utilities/config.rs 76.99% (830/1078) 72.84% (437/600) +4.15%
src/utilities/spin_sleeper.rs 79.17% (19/24) 69.23% (9/13) +9.94%
src/utilities/thread_builder.rs 92.59% (25/27) 78.57% (11/14) +14.02%
src/watchmen/monitors.rs 64.29% (135/210) 54.69% (70/128) +9.60%
src/water/refill.rs 86.81% (447/515) 69.45% (216/311) +17.36%
src/water/refill_channels.rs 71.43% (10/14) 57.14% (4/7) +14.29%
src/water/tank_level_switch.rs 84.14% (191/227) 74.47% (105/141) +9.67%
src/water/tank_level_switch_signals.rs 90.36% (75/83) 86.96% (40/46) +3.40%

System tests using the simulator

Running the application in simulator mode.