Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Puara Module

Société des Arts Technologiques (SAT)
Input Devices and Music Interaction Laboratory (IDMIL)


Overview

Puara Module is a library for ESP32 boards that provides a simplified interface for managing WiFi, a web server, and a filesystem. It facilitates the creation of distributed interactive systems, networked controllers, and similar applications, allowing users to focus on prototyping the rest of their system.


Getting Started

This documentation is divided into two main sections:

1. Building Puara Module Templates/Examples

Choose your preferred development environment. We offer almost identical templates for both Arduino IDE and PlatformIO.

EnvironmentRecommended For
Arduino IDEBeginner to intermediate programmers
PlatformIOIntermediate to advanced programmers, or users wanting more control

Once your project is running, use the Browser Pages to configure your device’s network settings and custom variables.

2. Developer Reference

Technical documentation for understanding and extending the codebase:

Puara Module for Arduino

Dependencies

⚠️ Download Arduino 2.0 IDE for build/upload of program.

⚠️ Install Arduino-LittleFS-Upload for filesystem uploading.

⚠️ ESP32 board library: Open Boards Manager icon in Arduino 2.0 IDE, type esp32 in the Boards Manager search bar and install esp32 by Espressif Systems.

⚠️ Partition size options: Select any options that offer minimal partition before building the program. These options vary depending on board capabilities and can be found here: /Tools/Partition Scheme/. A common option is Minimal SPIFFS such as: /Tools/Partition Scheme/Minimal SPIFFS. Warning: some boards simply do not have such options.

How to Use

  1. Install Arduino 2.0 IDE

  2. Download the puara-module library from Library Manager

  3. Open a puara template in Arduino IDE: Open Arduino IDE, go to File/Examples/puara-module/ and select the template of your choice.

  4. Configure the board: Ensure the board and port variables in the IDE match your board.

  5. Edit partition scheme: Allow more space for your programs. Go to:

  • Tools/Partition Scheme/ Select Minimal Spiffs or similar option. Different boards have different possibilities but generally the Minimal Spiffs:... option should be present.
  1. Edit the template: You are now ready to edit the template according to your board/needs.

  2. Edit the filesystem: To modify network configurations, add or modify the available variables in the settings, go to:

  • Sketch/Show Sketch Folder which will open your local project folder
  • Enter data/ folder:
    • Modify network name (SSID) and password (PSK) configurations in config.json;
    • Modify/Add variables in settings.json;
    • Save your modifications.
  1. Build and upload the filesystem and firmware: Once ready, you can:
  • Use Arduino IDE to build and upload the firmware to your board.
  • Use Arduino-LittleFS-Upload for the filesystem uploading: [Ctrl] + [Shift] + [P], then “Upload LittleFS to Pico/ESP8266/ESP32”.

On macOS, press [⌘] + [Shift] + [P] to open the Command Palette in the Arduino IDE, then “Upload LittleFS to Pico/ESP8266/ESP32”.

  1. Test your IoT device and validate communication between systems: At this point your board should either connect to your specified network if it can find it. In either case, if it does or doesn’t connect, your board will create an Access Point you can connect to directly. Use the board’s IP address to communicate with it when needed. More details below.
⚠️ Important detail for users

Most Arduino or embedded projects only upload the code that runs on the device. However, in this project, the device also needs a filesystem to store important data, such as configuration files, templates, or other resources that the code relies on. These two parts—code and filesystem—serve different purposes and must be built and uploaded separately. The executable code tells the device what to do, includes the logic, instructions, and behavior of the device such as how to read a sensor, process data, or send information over Wi-Fi. The filesystem is like a “hard drive” for the device, where additional files are stored and can include configuration files, templates, or other resources that the code needs to function properly. In our approach, the filesystem stores a JSON file with user settings for the network configurations and some global variables that can be modified through the browser without needing to reflash the whole system.


How It Works

⚠️ Every template related to Puara Module has a different set of options but they all generally respect the following explanation. If needed, the following sections are detailed more thoroughly in the Puara Module Book

1. Establishing WiFi

When initiating the program, the module manager will try to connect to the WiFi Network (SSID) defined in config.json. The puara-module supports three modes of operation:

  1. Station - Access Point (STA-AP) Mode (Default):

    • The device connects to an existing WiFi network (station).
    • The device creates its own WiFi network (access point).
    • User has two ways to communicate with the board.
  2. Access Point (AP) Mode:

    • The device does not connect to an existing WiFi network.
    • The device creates its own WiFi network (access point).
  3. Station (STA) Mode:

    • The device connects to an existing WiFi network.
    • The Access Point is turned off with persistent_AP=0
    • Useful to limit WiFi pollution and secure the device.

2. Making the Web Server Accessible

Browser-accessible pages available for configuring, scanning, and managing settings on your device are made available through Puara Module.

Once the web server is running, you can access it in two ways:

  1. Via IP Address: Navigate to the device’s IP address in your web browser (e.g., http://192.168.4.1 for AP mode, or the assigned IP in STA/STA-AP modes which can be retrieved using puara.staIP()).

  2. Via mDNS Hostname: If mDNS is enabled, you can access the device using its hostname (e.g., http://your-device-name.local). Default config.jsonvalues enable mDNS with the Puara_001, and browser is accessible with puara_001.local.

Using the web browser, users can modify variables that keep their value after reboot/shutdown of device without needing to rebuild/upload their program. Access these values in the program by using:

// For text fields
std::string my_string = puara.getVarText("variable_name");

// For number fields (all numbers are `doubles` -- see JSON documentation for explanation)
double my_number = puara.getVarNumber("variable_name");

Making of Custom Variables in settings.json

The /data/settings.json file stores custom application settings as an array of name-value pairs:

{
    "settings": [
        {
            "name": "user_defined_text",
            "value": "user defined value"
        },
        {
            "name": "variable3",
            "value": 12.345
        }
    ]
}

User may add/modify fields in this file and then upload the new filesystem in order to have a more custom device.


For more detailed documentation, please refer to the Puara Module developer documents


Examples

The puara-arduino repository includes five Arduino sketches that demonstrate different use cases and functionalities. All examples are identical to the PlatformIO templates available in puara-module-templates.

Each example includes a data/ folder containing configuration files (config.json, settings.json) and web interface files (HTML and CSS).

⚠️ After building and uploading the firmware to your board, you must also upload the filesystem.


1. Basic Example

File: examples/basic/basic.ino

A minimal example demonstrating core Puara Module functionality. This example:

  • Initializes the Puara module manager
  • Reads custom settings from the JSON configuration files
  • Outputs dummy sensor data to the serial monitor
  • Demonstrates how to access custom configuration variables using getVarText() and getVarNumber()

This is the best starting point for learning how to use the Puara framework.


2. OSC-Send Example

File: examples/OSC-Send/OSC-Send.ino

Demonstrates how to set up a basic OSC transmitter. This example:

  • Sends dummy sensor data as OSC messages to a specified IP address and port
  • Configurable OSC IP/port via the web interface without rebuilding/reflashing
  • Shows how to use the onSettingsChanged() callback to update parameters dynamically
  • Includes example code for reading analog sensors and digital signals

Note: Please refer to CNMAT’s OSC repository on GitHub for more details on OSC.


3. OSC-Receive Example

File: examples/OSC-Receive/OSC-Receive.ino

Demonstrates how to receive and process OSC messages. This example:

  • Listens for incoming OSC messages on a configurable UDP port
  • Parses OSC messages and extracts data from them
  • Demonstrates example processing of float values to control device outputs (e.g., LED brightness)
  • Shows how to use the onSettingsChanged() callback for dynamic configuration

The example expects a float between [0,1] on the OSC address /led/brightness with the format: /led/brightness f 0.34

Note: Please refer to CNMAT’s OSC repository on GitHub for more details on OSC.


4. OSC-Duplex Example

File: examples/OSC-Duplex/OSC-Duplex.ino

Combines both OSC-Send and OSC-Receive functionality in a single sketch. This example:

  • Sends dummy sensor data to a remote OSC address
  • Simultaneously receives OSC messages from remote sources
  • Demonstrates full duplex OSC communication patterns
  • Useful for bidirectional device communication scenarios

Note: Please refer to CNMAT’s OSC repository on GitHub for more details on OSC.


5. BLE Advertising Example

File: examples/ble-advertising/ble-advertising.ino

Demonstrates BLE (Bluetooth Low Energy) advertising without requiring device connections. This template:

  • Uses BLE advertising to broadcast device information
  • Encodes sensor data as CBOR payloads in BLE manufacturer data packets
  • Broadcasts at configurable frequency (default 50Hz)
  • Works seamlessly with the BLE-CBOR-to-OSC script

Key Features:

  • Broadcast without connection: Receive data from hundreds of BLE devices simultaneously without establishing individual connections
  • Range: Tested with ~120 devices in a 0-150 metre range with updates every 500ms
  • CBOR encoding: Efficient binary encoding for minimal payload
  • Device identification: Each device can be assigned a unique ID via config.json for easy tracking

Use Case: Ideal for IoT scenarios where you need to monitor many sensor devices simultaneously (e.g., distributed sensor networks, interactive installations) and is well-suited for lower data-rate transmission.

Getting Started with BLE Advertising

  1. Build and Upload: Build and upload the firmware to your ESP32 board
  2. Configure Device: Optionally modify the device name and ID in config.json
  3. Upload Filesystem: Upload the data folder using the LittleFS upload tool
  4. Run BLE-CBOR-to-OSC Script:
    • Clone the BLE-CBOR-to-OSC repository
    • Create a Python virtual environment : python -m venv venv
    • Activate the venv : source ./venv/bin/activate
    • Install Python dependencies: pip install -r requirements.txt
    • Run: python ble-cbor-to-osc.py
  5. Receive OSC Messages: The script forwards BLE advertising data as OSC messages to 127.0.0.1:9001 (configurable)

BLE Configuration

You can customize the BLE advertising behavior:

  • Frequency: Modify target_frequency variable (default 50Hz)
  • Sensor Data: Replace dummy sensor1 and sensor2 with actual pin readings

For more information, see the BLE-CBOR-to-OSC script documentation.


Puara Module Template (Module Manager)

This repository contains several templates to be used as a base to create devices that can be controlled over the network.

How to Use Puara Module Templates with PlatformIO

  1. Install VSCode and PlatformIO: Use Visual Studio Code as code editor with the PlatformIO IDE extension.

  2. Clone the puara-module-templates repository locally: git clone https://github.com/Puara/puara-module-templates.git

  3. Open a puara template in VS Code: Open VS Code, and select the platformIO extension on the left side. This will open the PLATFORMIO panel. From there select “Pick a folder”, and navigate to one of the puara-module-templates subfolders, e.g., puara-module-templates/basic/ (see below for a list of available templates). Click the “Select Folder” button. Wait for a bit while PlatformIO configures your project.

  1. Configure the board: Ensure the board variable in the platformio.ini file matches your board’s name. If needed you can find valid board IDs in Boards catalog, Boards Explorer or by using the pio boards terminal command.

  2. Edit the template: You are now ready to edit the template according to your board/needs.

  3. Build and upload the filesystem and firmware: Once ready, you can use PlatformIO to build and upload the filesystem and firmware to your board. You can access the PLATFORMIO Project Tasks by clicking on the extension button on the left. Make sure you upload both the filesystem (Build/Upload Filesystem Image under the Platform icon) and the firmware (Build/Upload under the General icon).

⚠️ Important detail for users

Most embedded projects only upload the code that runs on the device. However, in this project, the device also needs a filesystem to store important data, such as configuration files, templates, or other resources that the code relies on. These two parts—code and filesystem—serve different purposes and must be built and uploaded separately. The executable code tells the device what to do, includes the logic, instructions, and behavior of the device such as how to read a sensor, process data, or send information over Wi-Fi. The filesystem is like a “hard drive” for the device, where additional files are stored and can include configuration files, templates, or other resources that the code needs to function properly. In our approach, the filesystem stores a JSON file with user settings for the network configurations and some global variables that can be modified through the browser without needing to reflash the whole system.


How It Works

Every template related to Puara Module has a different set of options but they all generally respect the following explanation. The following sections are detailed more thoroughly in the Puara Module Book.

1. Establishing WiFi

When initiating the program, the module manager will try to connect to the WiFi Network (SSID) defined in config.json. The puara-module supports three modes of operation:

  1. Station - Access Point (STA-AP) Mode (Default):

    • The device connects to an existing WiFi network (station).
    • The device creates its own WiFi network (access point).
    • User has two ways to communicate with the board.
  2. Access Point (AP) Mode:

    • The device does not connect to an existing WiFi network.
    • The device creates its own WiFi network (access point).
  3. Station (STA) Mode:

    • The device connects to an existing WiFi network.
    • The Access Point is turned off with persistent_AP=0
    • Useful to limit WiFi pollution and secure the device.

2. Making the Web Server Accessible

Browser-accessible pages available for configuring, scanning, and managing settings on your device are made available through Puara Module.

Once the web server is running, you can access it in two ways:

  1. Via IP Address: Navigate to the device’s IP address in your web browser (e.g., http://192.168.4.1 for AP mode, or the assigned IP in STA/STA-AP modes which can be retrieved using puara.staIP()).

  2. Via mDNS Hostname: If mDNS is enabled, you can access the device using its hostname (e.g., http://your-device-name.local). Default config.jsonvalues enable mDNS with the Puara_001, and browser is accessible with puara_001.local.

Using the web browser, users can modify variables that keep their value after reboot/shutdown of device without needing to rebuild/upload their program. Access these values in the program by using:

// For text fields
std::string my_string = puara.getVarText("variable_name");

// For number fields (all numbers are `doubles` -- see JSON documentation for explanation)
double my_number = puara.getVarNumber("variable_name");

Making of Custom Variables in settings.json

The /data/settings.json file stores custom application settings as an array of name-value pairs:

{
    "settings": [
        {
            "name": "user_defined_text",
            "value": "user defined value"
        },
        {
            "name": "variable3",
            "value": 12.345
        }
    ]
}

User may add/modify fields in this file and then upload the new filesystem in order to have a more custom device.


Available Templates

The puara-module-templates repository includes multiple examples demonstrating different use cases and functionalities. Each example includes a data/ folder containing configuration files (config.json, settings.json) and web interface files (HTML and CSS).

⚠️ After building and uploading the firmware to your board, you must also upload the filesystem.


1. Basic Example

A minimal example demonstrating core Puara Module functionality. This template:

  • Initializes the Puara module manager
  • Reads custom settings from the JSON configuration files
  • Outputs dummy sensor data to the serial monitor
  • Demonstrates how to access custom configuration variables using getVarText() and getVarNumber()

This is the best starting point for learning how to use the Puara framework.


2. OSC-Send Example

Demonstrates how to set up a basic OSC transmitter. This template:

  • Sends dummy sensor data as OSC messages to a specified IP address and port
  • Configurable OSC IP/port via the web interface without rebuilding/reflashing
  • Shows how to use the onSettingsChanged() callback to update parameters dynamically
  • Includes example code for reading analog sensors and digital signals

Note: Please refer to CNMAT’s OSC repository on GitHub for more details on OSC.


3. OSC-Receive Example

Demonstrates how to receive and process OSC messages. This template:

  • Listens for incoming OSC messages on a configurable UDP port
  • Parses OSC messages and extracts data from them
  • Demonstrates example processing of float values to control device outputs (e.g., LED brightness)
  • Shows how to use the onSettingsChanged() callback for dynamic configuration

The example expects a float between [0,1] on the OSC address /led/brightness with the format: /led/brightness f 0.34

Note: Please refer to CNMAT’s OSC repository on GitHub for more details on OSC.


4. OSC-Duplex Example

Combines both OSC-Send and OSC-Receive functionality in a single sketch. This template:

  • Sends dummy sensor data to a remote OSC address
  • Simultaneously receives OSC messages from remote sources
  • Demonstrates full duplex OSC communication patterns
  • Useful for bidirectional device communication scenarios

Note: Please refer to CNMAT’s OSC repository on GitHub for more details on OSC.


5. BLE Advertising Example

Demonstrates BLE (Bluetooth Low Energy) advertising without requiring device connections. This template:

  • Uses BLE advertising to broadcast device information
  • Encodes sensor data as CBOR payloads in BLE manufacturer data packets
  • Broadcasts at configurable frequency (default 50Hz)
  • Works seamlessly with the BLE-CBOR-to-OSC script

For detailed setup instructions and configuration options, refer to the template’s README file.


6. Basic Gestures Example

Extends the basic template with gesture recognition capabilities using an IMU (Inertial Measurement Unit). This template:

  • Demonstrates how to read and process IMU sensor data
  • Includes gesture detection logic
  • Shows integration with the Puara module system

7. Button OSC Example

Demonstrates how to use button inputs with Puara gestures and OSC messaging. This template:

  • Reads digital button inputs (simulated button in template can be replaced with a real button)
  • Shows event-driven communication patterns
  • Evaluates the user interaction with the button to determine if it is being held, pressed once, twice, or three times in a row, and so on
  • Sends button state changes as OSC messages

8. Libmapper OSC Example

Demonstrates integration with libmapper, a distributed signal mapping system. This template:

  • Uses libmapper to register signals that can be mapped remotely
  • Combines libmapper with OSC messaging capabilities
  • Shows how to use the Puara framework with advanced mapping scenarios

Browser Pages

This document explains the browser-accessible pages available for configuring, scanning, and managing settings on your device. For technical details on the web server itself, see Web Server.


Config Page

The Config Page is the main page of the web interface, allowing you to manage network and device configuration parameters.

Config Page

Key Parameters

ParameterDescription
Network SSIDThe external WiFi network name you want to connect to.
Network PasswordThe password for the external WiFi network.
Puara PasswordThe password for your device’s own WiFi access point.

Important Notes

  • After making changes, click “Close and Reboot” to restart the device and apply the changes.
  • See the config.json file for all available parameters.

config.json

You can modify configuration values directly in the source file, then build and upload the filesystem. The /data/config.json file stores the main configuration of your device:

{
    "device": "Puara",
    "id": 1,
    "author": "Edu Meneses",
    "institution": "SAT/IDMIL (2025)",
    "APpasswd": "mappings",
    "wifiSSID": "SSID",
    "wifiPSK": "AP_PASSWORD",
    "persistentAP": 1
}
FieldDescription
deviceUser-defined name for the device.
idUser-defined device ID (useful when using multiple devices).
authorProject author name.
institutionInstitution or organization name.
APpasswdPassword for your device’s WiFi access point.
wifiSSIDName of the external WiFi network to connect to.
wifiPSKPassword for the external WiFi network.
persistentAPIf 1 (true), the device always creates its own access point. Set to 0 to disable and reduce radio interference.

Scan Page

The Scan Page displays WiFi networks detected by your device, helping you identify available networks to connect to.

Scan Page

Features

  • View a list of available WiFi networks with signal strength.
  • Use this information to select a network for the Config Page.
  • After updating the configuration, reboot the device to apply changes.

Settings Page

The Settings Page allows you to view and modify custom application variables defined in your project.

Settings Page

Features

  • View variables: See all user-defined settings from settings.json.
  • Modify values: Change values directly via the web interface. Changes persist after reboot.
  • Add/remove fields: Edit the settings.json file directly, maintaining the name:value structure, then rebuild and upload the filesystem.

Accessing Variables in Code

Use the following methods to retrieve variable values in your program:

// For text fields
std::string my_string = puara.getVarText("variable_name");

// For number fields (integers or floats)
int my_int = puara.getVarNumber("variable_name");
float my_float = puara.getVarNumber("variable_name");

settings.json

The /data/settings.json file stores custom application settings as an array of name-value pairs:

{
    "settings": [
        {
            "name": "user_defined_text",
            "value": "user defined value"
        },
        {
            "name": "user_defined_variable",
            "value": 42
        },
        {
            "name": "variable3",
            "value": 12.345
        }
    ]
}

Example: OSC Settings

For projects using OSC communication, the settings page can be used to configure IP addresses and ports:

OSC Settings Page

Puara API Documentation

The Puara object is the main entry point for using the puara-module library. It provides a simple interface for managing the different modules of the library, including WiFi, filesystem, web server, and more.


Initialization

To use the Puara object, you first need to include the puara.h header file and create an instance of the Puara class:

#include <puara.h>

Puara puara;

Then, in your setup() function, call the start() method:

void setup() {
    puara.start();
}

The start() method initializes the following:

  • Filesystem
  • Configuration and settings (from the JSON files)
  • WiFi (in STA-AP, AP or STA mode)
  • Web server
  • Serial listening
  • mDNS service
  • WiFi network scanning

Public Methods

Initialization & Core

start()

void start(PuaraAPI::Monitors monitor = PuaraAPI::UART_MONITOR, esp_log_level_t debug_level = ESP_LOG_WARN);

Initializes the Puara module and all its subsystems. This is the main entry point and should be called in your setup() function.

Parameters:

  • monitor: Specifies the serial monitor type. Options are:
    • PuaraAPI::UART_MONITOR (default) - Standard UART serial monitor
    • PuaraAPI::JTAG_MONITOR - JTAG-based debugging monitor
    • PuaraAPI::USB_MONITOR - USB serial monitor (not currently functional)
  • debug_level: Sets the ESP-IDF logging level. Default is ESP_LOG_WARN. Other options include ESP_LOG_NONE, ESP_LOG_ERROR, ESP_LOG_INFO, ESP_LOG_DEBUG, ESP_LOG_VERBOSE.

Web Server

start_webserver()

httpd_handle_t start_webserver(void);

Starts the built-in HTTP web server for device configuration and monitoring.

Returns: A handle to the HTTP server instance (httpd_handle_t).

stop_webserver()

void stop_webserver(void);

Stops the HTTP web server.


Device Information

dmi_name()

std::string dmi_name();

Returns the DMI (Device/Module Identifier) name of the device, which is a combination of the device type and ID.

Returns: The device’s DMI name as a std::string.

version()

unsigned int version();

Returns the current firmware version number.

Returns: The version as an unsigned int.

set_version()

void set_version(unsigned int user_version);

Sets a custom firmware version number.

Parameters:

  • user_version: The version number to set.

Filesystem

mount()

void mount();

Mounts the device’s filesystem (LittleFS or SPIFFS). This is automatically called by start(), but can be used manually if needed.

unmount()

void unmount();

Unmounts the device’s filesystem. Useful before deep sleep or when filesystem access is no longer needed.


Configuration Management

read_config_json()

void read_config_json();

Reads the device configuration from the config.json file stored in the filesystem. This includes device name, ID, author, institution, and WiFi credentials.

write_config_json()

void write_config_json();

Writes the current device configuration to the config.json file in the filesystem.

read_settings_json()

void read_settings_json();

Reads user-defined settings from the settings.json file stored in the filesystem.

write_settings_json()

void write_settings_json();

Writes the current user-defined settings to the settings.json file in the filesystem.

set_settings_changed_handler()

void set_settings_changed_handler(std::function<void()>);

Registers a callback function that will be called whenever settings are modified (e.g., through the web interface).

Parameters:

  • A std::function<void()> callback that takes no arguments and returns nothing.

Example:

puara.set_settings_changed_handler([]() {
    Serial.println("Settings have been updated!");
    // Reload or apply new settings here
});

Serial Communication

start_serial_listening()

bool start_serial_listening();

Starts listening for serial commands. This allows configuration and control via serial terminal.

Returns: true if serial listening was successfully started, false otherwise.

send_serial_data()

void send_serial_data(std::string data);

Sends data through the serial interface.

Parameters:

  • data: The string data to send.

mDNS Service

start_mdns_service()

void start_mdns_service(std::string_view device_name, std::string_view instance_name);

Starts the mDNS (multicast DNS) service, allowing the device to be discovered on the local network by its hostname.

Parameters:

  • device_name: The hostname for mDNS discovery (e.g., “puara-device”).
  • instance_name: A human-readable instance name for the service.

WiFi Management

start_wifi()

void start_wifi();

Starts the WiFi subsystem based on the configuration. The device can operate in:

  • STA mode: Connects to an existing WiFi network
  • AP mode: Creates its own access point
  • STA-AP mode: Both simultaneously

wifi_scan()

void wifi_scan(void);

Initiates a scan for available WiFi networks. Results can be viewed through the web interface.

get_StaIsConnected()

bool get_StaIsConnected();

Checks if the device is connected to a WiFi network in station (STA) mode.

Returns: true if connected to a WiFi access point, false otherwise.

staIP()

std::string staIP();

Returns the device’s IP address when connected to an external WiFi access point.

Returns: The IP address as a std::string (e.g., “192.168.1.100”).


Variable Access

getVarNumber()

double getVarNumber(std::string varName);

Retrieves the value of a numeric setting variable by name from the settings.

Parameters:

  • varName: The name of the variable to retrieve.

Returns: The value of the variable as a double.

getVarText()

std::string getVarText(std::string varName);

Retrieves the value of a text setting variable by name from the settings.

Parameters:

  • varName: The name of the variable to retrieve.

Returns: The value of the variable as a std::string.

Filesystem

The puara-module library provides a simple interface for working with the filesystem. It supports both LittleFS (default) and SPIFFS, though the available options depend on your development environment.


Mounting the Filesystem

The filesystem is mounted automatically when you call the puara.start() method. You can also mount and unmount it manually using the mount() and unmount() methods:

puara.mount();
puara.unmount();

Reading and Writing Files

You can read and write configuration files using the following methods:

  • read_config_json() / write_config_json() - Manage the config.json file (device configuration)
  • read_settings_json() / write_settings_json() - Manage the settings.json file (user settings)

For working with other files, you can use the standard LittleFS or SPIFFS APIs directly.


LittleFS vs SPIFFS

By default, the puara-module library uses LittleFS, which offers better performance and wear leveling compared to SPIFFS.

Arduino IDE

When using the Arduino IDE, only LittleFS is supported. You must use the arduino-littlefs uploader tool to upload the filesystem data to your device.

PlatformIO

When using PlatformIO, you have the flexibility to choose between LittleFS (default) and SPIFFS.

Default Configuration (LittleFS)

By default, PlatformIO projects are configured to use LittleFS. No changes are required.

Switching to SPIFFS

To use SPIFFS instead of LittleFS, you need to modify two settings in your platformio.ini file:

1. Change the filesystem type:

; to use spiffs, comment out "board_build.filesystem = littlefs", 
; uncomment "board_build.filesystem = spiffs" and "-DPUARA_SPIFFS"
;board_build.filesystem = littlefs
board_build.filesystem = spiffs

2. Add the SPIFFS build flag:

build_flags =
    -DBOARD_HAS_PSRAM
    -DPUARA_SPIFFS    ; compilation flag to indicate the usage of spiffs lib instead of littlefs

Note: Make sure both settings are changed together. The board_build.filesystem setting determines how PlatformIO uploads the filesystem data, while the -DPUARA_SPIFFS build flag tells the puara-module library to use the SPIFFS API at compile time.

Web Server

The puara-module library includes an integrated web server that allows you to configure your device from a web browser. For more details on the browser pages from a user perspective, see Browser Pages.


Starting the Web Server

The web server is started automatically when you call the puara.start() method. You can also start and stop it manually:

httpd_handle_t server = puara.start_webserver();
puara.stop_webserver();

Accessing the Web Interface

Once the web server is running, you can access it in two ways:

  1. Via IP Address: Navigate to the device’s IP address in your web browser (e.g., http://192.168.4.1 for AP mode, or the assigned IP in STA mode which can be retrieved using puara.staIP()).

  2. Via mDNS Hostname: If mDNS is enabled, you can access the device using its hostname (e.g., http://your-device-name.local).


Web Pages

The web pages are stored in the data directory of your project. The puara-module library provides a set of default web pages that you can customize to suit your needs.

Default Pages

FileDescription
index.htmlThe main page of the web interface where users can configure WiFi SSID and device settings.
scan.htmlDisplays available WiFi networks for connection.
settings.htmlAllows users to configure custom variable values for the device.
update.htmlReserved for future Over-The-Air (OTA) update functionality.
reboot.htmlConfirmation page displayed when the device is rebooting.
saved.htmlConfirmation page displayed after settings are saved. This triggers the callback registered via puara.set_settings_changed_handler().

Styling

The style.css file in the data directory controls the appearance of all web pages. You can modify this file to customize the look and feel of the web interface.


Customizing Web Pages

You can edit the HTML files in the data directory to change the appearance and functionality of the web interface. The web pages use a simple template system that allows you to insert dynamic values from your device into the HTML.

Note: After modifying files in the data directory, you need to re-upload the filesystem to your device. See Filesystem for instructions on uploading filesystem data.

WiFi Considerations

The puara-module library provides a simple and flexible interface for managing WiFi connections. This document outlines the key WiFi-related features, modes, and public API functions available in the library.

WiFi Modes

The puara-module supports three modes of operation:

  1. Station - Access Point (STA-AP) Mode:

    • The device connects to an existing WiFi network (station).
    • The device creates its own WiFi network (access point).
  2. Access Point (AP) Mode:

    • The device does not connect to an existing WiFi network.

    • The device creates its own WiFi network (access point).

    • Useful for initial configuration or when no external WiFi network is available.

  3. Station (STA) Mode:

    • The device connects to an existing WiFi network.
    • The Access Point is turned off with persistent_AP=0
    • Useful to limit WiFi pollution and secure the device.

Default Behavior

Device is STA-AP by default:

  • The puara-module will attempt to connect to a known WiFi network. If the connection succeeds or fails, the device will then activate it’s AP mode.

To deactivate STA, leave useless connection information (SSID, PSK) in config.json. To deactivate AP mode, set the persistent_AP option to 0 in the config.json file or access the config page through the web server and tick the proper option about AP mode.


Public API Functions

The puara-module exposes the following public API functions for managing WiFi:

void start_wifi()

  • Description: Initializes the WiFi configuration and starts the WiFi service.

  • Behavior:

    • Configures the device to operate in either STA-AP, STA or AP mode based on the config.json settings.
    • Ensures default values for SSID and passwords if they are missing or invalid.

    void wifi_scan()

  • Description: Scans for available WiFi networks and stores the results.

  • Behavior:

    • The scan results include SSID, RSSI (signal strength), and channel information for each network.
    • Results are displayed on the scan.html page of the web interface.

bool get_StaIsConnected()

  • Description: Checks whether the device is connected to an external WiFi network in STA mode.
  • Returns: Returns true if the device is connected, false otherwise.

std::string staIP()

  • Description: Retrieves the current IP address of the device when connected to an external WiFi network in STA-IP or STA modes.

  • Returns: The IP address as a string.

Serial and Debug Logging

The puara-module library provides a simple interface for serial communication, allowing you to send data and receive commands via the serial port.


Starting Serial Listening

Serial listening is started automatically when you call puara.start(). You can also start it manually:

bool success = puara.start_serial_listening();

Returns: true if serial listening was successfully started, false otherwise.

When serial listening is active, the device will listen for incoming commands on the serial port, allowing you to interact with and configure the device via a serial terminal.


Sending Serial Data

You can send data over the serial port using the send_serial_data() method:

puara.send_serial_data("Hello, world!");

Monitor Types

You can specify the serial monitor type when calling the start() method:

// Use JTAG monitor with debug-level logging
puara.start(PuaraAPI::JTAG_MONITOR, ESP_LOG_DEBUG);

Available Monitors

MonitorDescription
PuaraAPI::UART_MONITORStandard UART serial monitor (default).
PuaraAPI::JTAG_MONITORJTAG-based debugging monitor.
PuaraAPI::USB_MONITORUSB serial monitor.

Debug Levels

The second parameter of start() sets the ESP-IDF logging level:

LevelDescription
ESP_LOG_NONENo logging output.
ESP_LOG_ERROROnly error messages.
ESP_LOG_WARNWarnings and errors (default).
ESP_LOG_INFOInformational messages, warnings, and errors.
ESP_LOG_DEBUGDebug messages and all above.
ESP_LOG_VERBOSEAll messages including verbose output.

mDNS

The puara-module library includes built-in support for mDNS (multicast DNS), allowing your device to be discovered and accessed on the local network using a human-readable hostname instead of an IP address.


What is mDNS?

mDNS is a protocol that resolves hostnames to IP addresses within small networks without requiring a dedicated DNS server. It enables you to access your device using a .local domain name, making it much easier to connect to your device without needing to know its IP address.


Automatic Configuration

When you call puara.start(), the mDNS service is started automatically using the device’s DMI name (a combination of device and id from your config.json).

For example, with this configuration:

{
    "device": "Puara",
    "id": 1
}

The device will be accessible at: http://puara_001.local/


Manual Configuration

If you need to start the mDNS service manually with a custom name, use the start_mdns_service() method:

puara.start_mdns_service("my-device", "My Device Instance");

Parameters

ParameterDescription
device_nameThe hostname for mDNS discovery. This becomes the .local address (e.g., my-devicehttp://my-device.local/).
instance_nameA human-readable name for the service instance, visible in network discovery tools.

Accessing Your Device

Once mDNS is running, you can access your device’s web interface by typing the hostname followed by .local in your browser:

http://<device_name>.local/

For example:

  • http://puara_001.local/
  • http://my-sensor.local/

Troubleshooting

Device not found via .local address?

  • Same network: Ensure your computer and the device are on the same network.
  • mDNS support: Some networks (especially corporate/enterprise) block mDNS traffic. Try using the IP address directly instead.
  • Windows: Older Windows versions may require Bonjour to be installed for .local resolution.
  • Firewall: Check that your firewall allows mDNS traffic (UDP port 5353).

Tip: If you’re having trouble with mDNS, you can always access the device via its IP address. Use puara.staIP() to retrieve the IP address in your code, or check your router’s connected devices list.