Skip to content

Network-Connected Environmental Station Demo#44

Merged
fdesbiens merged 15 commits into
eclipse-threadx:devfrom
alieissa-commits:main
Jul 21, 2026
Merged

Network-Connected Environmental Station Demo#44
fdesbiens merged 15 commits into
eclipse-threadx:devfrom
alieissa-commits:main

Conversation

@alieissa-commits

Copy link
Copy Markdown
Contributor

Network-Connected Environmental Station Demo

Summary

The Network-Connected Environmental Station demo (app/demos/network_station/) is an integrated IoT application demonstrating how to coordinate the Eclipse ThreadX RTOS, FileX FAT file system, and NetX Duo TCP/IP stack on resource-constrained microcontrollers.

The application periodically polls temperature and humidity data (supporting both a physical I2C HTS221 sensor and an automatic mathematical simulator fallback), logs the readings locally as CSV records to a virtual FAT RAM disk, and forwards them to a separate network thread. The network thread dynamically monitors Ethernet cable status, resolves an IP via DHCP, resolves the broker hostname via DNS, and publishes the logs as JSON telemetry payloads over MQTT. The threads communicate using an asynchronous, decoupled queue pipeline utilizing an Evict Oldest circular policy to prevent system blocking and preserve the newest real-time data during network outages.


Key Features

1. Environmental Station Application (app/demos/network_station/)

  • Multi-Threaded RTOS Pipeline: Wires together sensor_thread (polls data every 2s), logger_thread (writes data locally to a FAT filesystem), and network_thread (publishes JSON telemetry via MQTT).
  • I2C Sensor & Fallback: Communicates with the physical HTS221 sensor on I2C1, automatically falling back to a mathematical sine-wave simulation loop (mock_sensor.c) if no sensor is physically detected at startup.
  • FileX RAM Disk Logger: Formats and mounts a virtual 32 KB FAT RAM Disk inside the board's internal memory and logs CSV records to sensor_log.txt.
  • MQTT Telemetry & Reconnection: Configures NetX Duo DHCP/DNS clients to resolve and connect to the public Mosquitto broker (test.mosquitto.org:1883) using a client ID derived from the board's unique hardware ID. Telemetry is formatted as JSON.
  • Evict-Oldest Queue Policy: Employs an evict-oldest circular queue between the logger and network threads to handle network outages. If the link is lost, the newest data is prioritized on the wire while the full history remains safely recorded in the local FileX database.

2. Unified 256-Color Logging (ansi_colors.h)

  • Added a shared header app/ansi_colors.h containing VT100-compatible color codes to replace standard harsh terminal colors with a modern, muted color scheme.
  • Subsystem Tags: Muted Slate Gray (\x1b[38;5;243m) is used for all prefix tags (e.g. [System], [HAL], [NetX], [Logger Thread]), pushing the tags into the visual background.
  • State Colors: The message text color represents its priority:
    • Soft Green (MSG_SUCCESS) for successes.
    • Muted Gold/Orange (MSG_WARNING) for alerts/link changes.
    • Coral/Red (MSG_ERROR) for disconnections/failures.
  • Refactored board_init.c and the other demos (threadx_basic and netx_echo) to use this shared logging header for consistency.

Verification

  • The demo compiles successfully with the GNU ARM Toolchain (-Werror active) with a Flash size of ~165.9 KB and RAM size of ~415.8 KB.
  • Validated dynamic network reconnection, queue eviction logs, local RAM Disk writing, and MQTT WebSocket telemetry arrival on target hardware.
  • All commits are fully signed off in compliance with the Developer Certificate of Origin (DCO).

fdesbiens and others added 10 commits June 12, 2026 18:00
…d default to threadx_basic

Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Co-authored-by: Codex <codex@openai.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
…tion demo

Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
@fdesbiens
fdesbiens changed the base branch from main to dev July 20, 2026 15:35
Retained the environmental-station changes and incorporated the current STM32 Ethernet compatibility definition.\n\nCo-authored-by: Codex <codex@openai.com>

@fdesbiens fdesbiens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great demo, @alieissa-commits.

Please make the few changes I suggested and we can merge. Do not forget to pull my fixes (merge conflict resolutions) before you start working on this.

if (!dns_initialized)
{
ULONG dns_server = IP_ADDRESS(8, 8, 8, 8); /* Fallback to Google DNS */
UINT size;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size is passed uninitialized to nx_dhcp_user_option_retrieve(), which treats it as the destination buffer capacity.

Initialize it and check the return status:

UINT size = sizeof(dns_server);
status = nx_dhcp_user_option_retrieve(
    &dhcp_client,
    NX_DHCP_OPTION_DNS_SVR,
    (UCHAR *)&dns_server,
    &size);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size now is initialized and the status is found. If the status fails, fall back to Google DNS.

printf("[Sensor] Physical HTS221 detected (WHO_AM_I = 0x%02X).\r\n", whoamI);

/* Read humidity calibration coefficients */
hts221_hum_adc_point_0_get(&dev_ctx, &lin_hum.x0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calibration reads and configuration writes discard their return values. A transient I2C failure can leave incomplete calibration data while the driver reports successful initialisation.

Check each operation and return an error or switch to mock mode when initialisation fails.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each operation is now checked individually and if the initialisation fails at that stage, the program logs to the console and switches to mock mode.


/* Override the weak HAL_GetTick function to provide a working tick source
both before and after the ThreadX scheduler starts. */
uint32_t HAL_GetTick(void)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the scheduler starts, HAL_GetTick() returns raw ThreadX ticks. With the sample's typical 100 Hz timer rate,
timestamps and mock-sensor timing progress at one tenth of the documented rate.

Convert tx_time_get() using TX_TIMER_TICKS_PER_SECOND.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tx_time_get() is now converted using this formula: (uint32_t)(((uint64_t)tx_time_get() * 1000) / TX_TIMER_TICKS_PER_SECOND);

…build warnings

Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
… logs on link loss

Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>

@fdesbiens fdesbiens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good progress. A few small tweaks and we should be good to go.

if (!ip_resolved || !mqtt_connected)
{
/* Put the message back in the queue so it is not lost */
tx_queue_send(&network_queue, &msg, TX_NO_WAIT);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the link is lost, the oldest dequeued message is appended to the back of the queue with tx_queue_send(). This allows newer readings to be published before it after reconnection.

Use tx_queue_front_send() and check its return value.

@alieissa-commits alieissa-commits Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using tx_queue_front_send() and returning error message with queue status code if unsuccessful

{
ULONG dns_server = IP_ADDRESS(8, 8, 8, 8); /* Fallback to Google DNS */
UINT size = sizeof(dns_server);
UINT status = nx_dhcp_user_option_retrieve(&dhcp_client, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)&dns_server, &size);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new local status declaration hides the variable declared at function scope. This violates MISRA C:2012 Rule 5.3.

Reuse the existing status variable instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed UINT and reusing existing variable

ULONG dns_server = IP_ADDRESS(8, 8, 8, 8); /* Fallback to Google DNS */
UINT size = sizeof(dns_server);
UINT status = nx_dhcp_user_option_retrieve(&dhcp_client, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)&dns_server, &size);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is trailing whitespace on this line. Please remove.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

… bugs

Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>
Signed-off-by: alieissa-commits <ali.eissa.dev@gmail.com>

@fdesbiens fdesbiens left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the quick turnaround on the fixes!

@fdesbiens
fdesbiens merged commit 71f059c into eclipse-threadx:dev Jul 21, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants