Implementation Guide for pouring Tea via an API

Pieter Geelen
𝐀𝐈 𝐦𝐨𝐧𝐤𝐬.𝐢𝐨
6 min readJan 23, 2024

This is a follow-up article on the “Improving Quality of Life: A Tea Pouring Solution for Anton”. This project is a collaboration between Anton and myself. Special thanks also goes out to Arseny Starostin, who supported the setting up process, settings up CI and reviewing PRs. The scope of the project is to leverage a microcontroller and a pump to pour tea. This pouring is done via an API endpoint. This article follows up on the requirements that have been set and the shopping list that has been defined, and highlights the hardware and software implementation.

Wiring up the Hardware

source: imgflip

Software is little without the hardware to run it on. For this reason we start with the schema of the solution. The components include:

  • Arduino R4 Wifi microcontroller
  • A Motor Hat that is connected to the pump and the Arduino
  • A DC jack that accepts 12 Volts barrel-jack PSU
  • Tea Pump, that runs on 12 Volts
  • On/Off Switch with LED
The overall circuit in which the red wires are 12 Volts +, the black wires are ground and the blue wires are non-rail wiring.

In the schematic, we can see how the power comes in via the barrel jack. The switch and LED belong together as a component, and the LED switches on when the power is being switched on, too. The Arduino Motor Hat accepts the 12 Volts and can modulate this current and provide it for Channels A and B. Channel A is being used to control the pump. In the current implementation we use the modulation merely as a switch, meaning that we provide the current, or we don't, but do not modulate it further with PWM.

Writing the Software

The software has been implemented using Platform.IO. This is a VS Code extension that has many quality of life features for developing with Embedded Devices. One of the foremost features is the project and package management, in which the entire project and all it files are managed and packages can be added and are managed within the project. Features like building, uploading, monitoring and testing the code further enhance the developer experience. So let’s take a look at the different components of the controller firmware. The controller can do three things:

  • connect to WiFi
  • accept HTTP GET requests
  • pour tea (duh)

Quickstart

  1. The first thing you’ll do with the controller is connect it to your network. For that, modify the secrets.h accordingly. For the expected format, refer to secrets.h.example.
  2. Once you flash the controller firmware to the arduino module, it will connect to WiFi, create a route for your HTTP requests, and print out information about the connection.
  3. Let’s take a closer look at the individual pieces. When connecting to WiFi, we will show the SSID, signal strength and the IP address where you can send requests to.
  4. We set up one route, /pour_tea that has one query parameter, milliseconds, that regulates how long the pump will run. The process will validate that the query parameter is of the expected format (an integer bigger than zero).

Where to find what

All the code can be found in the repository. Just remember, RTFM!

source: imgflip

In the Arduino project, the RemoteControl module, found in the lib/Arduino directory, is responsible for managing WiFi connections. It handles the display of network information and incorporates a mechanism for automatic reconnection.

Similarly, the WaterPumpController module, also located in lib/Arduino/, provides direct control over the water pump. Users can initiate both start and stop actions through this component.

Within the CommandProcessor module, situated in the lib/ directory, various tasks are performed. It ensures the validation of input to the HTTP endpoint, retrieves the current status of the water pump, and facilitates the pouring of tea. This pouring action is achieved by invoking both the water pump and checking its status concurrently.

The main.cpp file, residing in the src/ directory, serves as a central orchestrator. It establishes the route for handling HTTP requests and configures the overall application setup. Specifically, when a request is received, it triggers the pour_tea function, initiating the process defined in the CommandProcessor module.

Testing Software

source: mailtrap

Next, we’ll explore how to effectively unit test the Water Pump Scheduler System using Google Test, a popular C++ testing framework. We used the PlatformIO Native environment (check platformio.ini for the exact configuration) to be able to run the test locally, without requiring the embedded device. Then tests can easily be triggered within the PlatformIO ecosystem and are also part of the CI, as implemented in the Repository.

Note that not all testing frameworks are compatible with the Arduino, meaning that if you want to run unit-tests on specific hardware, you need to assure compatibility of that framework beforehand. Our focus will be on two sets of tests: WaterPumpScheduler_test.h and CommandProcessor_test.h. We'll also discuss the use of mock classes like FakeWaterPump and FakeWaterPumpSchedulerAPI for simulating real components.

Testing the Water Pump Scheduler (WaterPumpScheduler_test.h)

Test 1: Pump Stops After Given Time

  • Objective: Ensure the water pump stops after a specified duration.
  • Step 1: Setup a WaterPumpScheduler with a FakeWaterPump.
  • Step 2: Start the pump and confirm it’s running and the stop time is correctly set.
  • Step 3: Simulate time passing and check if the pump stops as expected.

Test 2: Periodic Forced Stop of Pump

  • Objective: Verify the pump is forced to stop periodically.
  • Step 1: Setup with a FakeWaterPump and a forced stop interval.
  • Step 2: Start the pump and validate it stops after 1 millisecond.
  • Step 3: Simulate repeated starts and time passage, ensuring the pump stops each time.

Testing the Command Processor (CommandProcessor_test.h)

Test 1: Pour Tea with Invalid Milliseconds

  • Objective: Check the pour_tea method for errors with invalid inputs.
  • Step 1: Test various invalid inputs like too high numbers, negative numbers, empty strings, and non-numeric strings.

Test 2: Pour Tea Operation

  • Objective: Ensure tea pouring starts and stops correctly.
  • Step 1: Use FakeEnvironment and FakeWaterPumpSchedulerAPI to simulate operations.

Test 3: Stop Method

  • Objective: Confirm the stop method halts tea pouring.
  • Step 1: Use mock classes to test the stopping functionality.

Test 4: Status Method

  • Objective: Verify the status method returns correct pump status.
  • Step 1: Check both idle and running states of the pump for accurate status reporting.

Mock Implementations for Testing

FakeWaterPumpSimulates a real water pump. It implements start and stop methods to change its running state and is useful for testing scenarios involving pump operations without needing a physical pump.

FakeWaterPumpSchedulerAPIMimics the behavior of a real water pump scheduler. It implements methods to start and stop the pump, including logging calls for verification. The status method provides the current state of the pump, aiding in testing the scheduler's functionality.

Next Steps

The implementation of a reasonable workflow for managing the pouring of tea has been achieved. The use of a scheduler enables to manage the state of the device at all times, and the suite of tests ensures that the code itself can be validated and code-changes can be better understood. The next step is to package these functionalities and electronic hardware into something that we can put on a desk somewhere. The design should be simple and accessible. Apart from an intuitive design, we will also consider the cost and efficiency of 3D printing for this use-case.

Resources

--

--

Pieter Geelen
𝐀𝐈 𝐦𝐨𝐧𝐤𝐬.𝐢𝐨

I'm an experienced tech leader proficient in ML, data engineering, and project management. Let's connect for success!