Skip to main content
Uncategorized

CatLoggerEasy MQTT System Architecture Guide

By January 21, 2026No Comments

CatLoggerEasy – MQTT System Architecture

Complete guide to the refactored MQTT system: what each file does and what changed

📦 7 Files Modified
⭐ 3 Files Created
🚀 7+ Platforms Supported

🎯 System Overview

What Problem Does This Solve?

The original MQTT implementation was hardcoded for specific platforms and had limited flexibility. The refactored system provides:

  • Multi-platform support – 7+ IoT platforms out of the box
  • Automatic format adaptation – Each platform gets the correct JSON structure
  • Extensible architecture – Easy to add new platforms
  • Contextual help – Built-in setup guides for each platform
  • Better separation of concerns – Connection vs Publishing configuration

Key Architectural Changes

🏭

Factory Pattern

Introduced MqttPayloadFormatterFactory to create platform-specific formatters dynamically.

🔌

Interface-Based Design

IMqttPayloadFormatter defines the contract all platforms must implement.

📚

Self-Documenting

Each formatter includes setup instructions and credentials help directly in code.

⭐ New Files Created

📄 IMqttPayloadFormatter.cs

Location: Services/Mqtt/IMqttPayloadFormatter.cs

Purpose

Defines the interface (contract) that all platform-specific formatters must implement. This ensures consistency across all platform implementations.

Methods Defined

Method Purpose
FormatTelemetry() Converts Dictionary to platform-specific JSON
GetDefaultTopic() Returns platform’s default MQTT topic
ConfigureDefaultSettings() Auto-configures host, port, topic for platform
GetPlatformInstructions() Returns setup instructions for UI
GetCredentialsHelp() Returns credentials guide for UI

💡 Why It Matters: This interface is the foundation of the entire multi-platform system. Any developer can implement this interface to add support for a new IoT platform in minutes.

📄 MqttPayloadFormatters.cs

Location: Services/Mqtt/MqttPayloadFormatters.cs

Purpose

Contains the Factory and all platform-specific formatter implementations. This is the heart of the multi-platform support system.

Components

🏭 MqttPayloadFormatterFactory

What it does: Creates the appropriate formatter based on the selected platform.
Example: CreateFormatter(MqttPlatform.ThingsBoard) returns a ThingsBoardFormatter instance.

Platform Formatters Included
GenericFormatter
Standard MQTT brokers
ThingsBoardFormatter
ThingsBoard IoT platform
UbidotsFormatter
Ubidots Industrial IoT
HiveMQFormatter
HiveMQ Cloud broker
AdafruitFormatter
Adafruit IO platform
AwsIoTFormatter
AWS IoT Core
AzureIoTFormatter
Azure IoT Hub
Example: ThingsBoard vs Generic
// ThingsBoard expects:
{
  "ts": 1737456645123,
  "values": {
    "temperature": 23.5,
    "pressure": 1.2
  }
}

// Generic expects:
{
  "timestamp": "2026-01-21T15:30:45.123Z",
  "temperature": 23.5,
  "pressure": 1.2
}

💡 Why It Matters: This file makes it trivial to add new platforms. Just implement the interface, add to the factory switch statement, and you’re done. No need to modify any other code.

📄 MQTT_PLATFORMS_GUIDE.md

Location: Docs/MQTT_PLATFORMS_GUIDE.md

Purpose

Comprehensive user documentation covering setup guides for all supported platforms, troubleshooting, and best practices.

Contents

  • Step-by-step setup for each platform
  • Credential acquisition guides
  • Troubleshooting common issues
  • Performance optimization tips
  • Security best practices

📝 Modified Files

📝 MqttSettings.cs

Location: UI/UserControls/SettingsViewModule/MqttSettings.cs

What Changed

✨ Expanded MqttPlatform Enum
Before:

public enum MqttPlatform
{
    Generic,
    Ubidots,
    ThingsBoard
}
After:

public enum MqttPlatform
{
    Generic,
    Ubidots,
    ThingsBoard,
    AWSIoT,
    AzureIoTHub,
    Adafruit,
    HiveMQ,
    Custom
}
➕ New Properties Added
public string ClientId { get; set; } = string.Empty;
public Dictionary<string, string> PlatformSpecificSettings { get; set; } = new();

These properties allow for future extensibility when platforms need custom configuration beyond standard MQTT parameters.

🎯 Impact: Existing code remains compatible. The new enum values and properties are additive, not breaking changes.

📝 MqttTelemetryService.cs

Location: UI/UserControls/SettingsViewModule/MqttTelemetryService.cs

What Changed

🔄 Complete Rewrite with Factory Pattern

The service was completely refactored to use the formatter factory pattern instead of hardcoded platform logic.

Key Changes:

  • Dynamic Formatter Selection: Uses MqttPayloadFormatterFactory to get the right formatter
  • Formatter Caching: Stores current formatter to avoid recreating on every publish
  • Platform Detection: Automatically switches formatter when platform changes
  • New Methods: Added PublishSessionEventAsync() and PublishAlertAsync()
🆕 New Methods
Method Purpose
PublishSessionEventAsync() Publish session start/stop events
PublishAlertAsync() Publish alerts and errors
PublishProcessDataAsync() Simplified method for batch data publishing

📝 SettingsMqttViewModel.cs

Location: UI/UserControls/SettingsViewModule/SettingsMqttViewModel.cs

What Changed

🎨 Added Contextual Help Properties

New properties that display platform-specific instructions directly in the UI:

  • PlatformInstructions – Setup guide for selected platform
  • CredentialsHelp – How to obtain credentials
  • ShowPlatformHelp – Toggle visibility of help panel
  • IsAdvancedPlatform – Warning flag for AWS/Azure
🆕 New Commands
Command Action
TogglePlatformHelpCommand Shows/hides the help panel
ApplyPlatformDefaultsCommand Auto-configures settings for platform
🔄 Updated Methods
  • ApplyPlatformDefaults() – Now uses formatter to get platform-specific config
  • UpdatePlatformHelp() – NEW – Fetches help text from formatter
  • PublishTestMessageAsync() – Uses formatter for correct format

📝 SettingsMqttView.axaml

Location: UI/UserControls/SettingsViewModule/SettingsMqttView.axaml

What Changed

🎨 Major UI/UX Improvements
📘 Platform Help Panel
Expandable panel with setup instructions
⚠️ Advanced Warning
Shows warning for AWS/Azure
💡 Quick Tips
Best practices section
📊 Topic Examples
Platform-specific topic formats
🔘 New UI Elements
  • “?” Button – Toggle help panel visibility
  • “Apply Defaults” Button – Auto-configure for platform
  • Connection Status Badge – Visual connection indicator
  • Platform Selector – Dropdown with all platforms

🔍 ProcessDataViewViewModel.cs – Deep Dive

⚠️ Most Important File

This file is the core data publishing engine. It bridges EtherCAT data with MQTT telemetry. Understanding this file is critical for any developer working on the MQTT system.

📝 ProcessDataViewViewModel.cs

Location: ProcessDataViewModule/ProcessDataViewViewModel.cs

File Purpose

This ViewModel manages the ProcessData table (the table showing all EtherCAT variables in real-time) and handles automatic MQTT publishing of that data to cloud platforms.

What Was Changed

1. Service Initialization (Constructor)
Before:

// Old: No formatter integration
_mqtt = MqttService.Instance;
After:

// New: Uses improved service
_telemetryService = new MqttTelemetryService(
    MqttService.Instance
);

Impact: Now uses the refactored telemetry service that handles platform formatting automatically.

2. Publishing Method (PublishMqttRealtimeTelemetryAsync)

This is the method that runs every X milliseconds to publish data to MQTT.

Key Changes:

  • Better error handling: Wrapped in try-catch, non-fatal errors
  • Improved logging: Debug statements show exactly what’s being published
  • Uses new service: Calls _telemetryService.PublishTelemetryAsync()
  • Automatic formatting: Platform-specific formatting handled automatically
  • Chunking logic intact: Still splits large payloads into 50-variable chunks
// Simplified flow
1. Check if gate is available (prevent concurrent publishing)
2. Load configuration
3. Apply publish interval from config
4. Build snapshot of current data (BuildTelemetrySnapshot)
5. Chunk data if > 50 variables
6. For each chunk: call _telemetryService.PublishTelemetryAsync()
7. Release gate

3. Data Snapshot Building (BuildTelemetrySnapshot)

This method decides WHAT data gets published.

Logic Flow:

1. Create dictionary with metadata (source, timestamp)
2. For each channel in UiChannels:
   a. Check if PublishAllVariables is enabled
      - If YES: include variable
      - If NO: check if variable name matches filters
   b. Sanitize variable name (remove special chars)
   c. Add to dictionary
3. Return dictionary

What stayed the same:

  • Filter logic (PublishAllVariables, VariableFilter)
  • Name sanitization
  • Value extraction from UiChannels

What’s new:

  • Better debug logging
  • More comments explaining each step

4. New Public Methods (for external use)

Three new methods were added to allow other parts of the application to publish specific events:

Method When to Call What It Publishes
PublishSessionStartedAsync() When EtherCAT logging starts Session ID, device info, slave count
PublishSessionStoppedAsync() When EtherCAT logging stops Session ID, stop timestamp
PublishAlertAsync() When errors/warnings occur Severity, message, context
// Example usage (you need to implement these calls)
// In your EtherCAT start handler:
await ProcessDataViewModel.PublishSessionStartedAsync(sessionId);

// In your EtherCAT stop handler:
await ProcessDataViewModel.PublishSessionStoppedAsync(sessionId);

// In your error handler:
await ProcessDataViewModel.PublishAlertAsync("error", "Slave disconnected");

✅ What Stayed the Same

The following were NOT changed (backward compatible):

  • UiChannels – ObservableCollection of channels
  • ReadProcessData() – Method to read from DataRepo
  • SanitizeTelemetryKey() – Name cleaning logic
  • OnTimerElapsed() – UI update timer
  • ApplySystemConfig() – EtherCAT config application
  • Plotting functionality – Completely independent

📊 Data Flow in ProcessDataViewViewModel

┌─────────────────────────────────────────────────────────────┐
│  EtherCAT System                                            │
│  (Physical devices sending data)                            │
└────────────────┬────────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────────────┐
│  DataRepo.ReadKey()                                         │
│  (Read current values from data repository)                 │
└────────────────┬────────────────────────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────────────────────────┐
│  ReadProcessData()                                          │
│  Updates UiChannels every 500ms                             │
└────────────────┬────────────────────────────────────────────┘
                 │
                 ├─────────────────┐
                 │                 │
                 ▼                 ▼
    ┌────────────────────┐  ┌──────────────────────┐
    │  UI Display        │  │  MQTT Publishing     │
    │  (DataGrid shows   │  │  (Timer triggers     │
    │   real-time data)  │  │   every N ms)        │
    └────────────────────┘  └──────┬───────────────┘
                                   │
                                   ▼
                    ┌──────────────────────────────┐
                    │  BuildTelemetrySnapshot()    │
                    │  • Apply filters             │
                    │  • Sanitize names            │
                    │  • Build Dictionary          │
                    └──────┬───────────────────────┘
                           │
                           ▼
                    ┌──────────────────────────────┐
                    │  _telemetryService           │
                    │    .PublishTelemetryAsync()  │
                    └──────┬───────────────────────┘
                           │
                           ▼
                    ┌──────────────────────────────┐
                    │  MqttPayloadFormatterFactory │
                    │  Creates platform formatter  │
                    └──────┬───────────────────────┘
                           │
                           ▼
                    ┌──────────────────────────────┐
                    │  Platform Formatter          │
                    │  (ThingsBoard, Ubidots, etc) │
                    │  Formats to platform JSON    │
                    └──────┬───────────────────────┘
                           │
                           ▼
                    ┌──────────────────────────────┐
                    │  MqttService                 │
                    │  Publishes to broker         │
                    └──────┬───────────────────────┘
                           │
                           ▼
                    ┌──────────────────────────────┐
                    │  MQTT Broker                 │
                    │  (ThingsBoard, Ubidots, etc) │
                    └──────────────────────────────┘

🏗️ System Architecture Diagram

┌────────────────────────────────────────────────────────────────────────┐
│                     CatLoggerEasy Application                          │
├────────────────────────────────────────────────────────────────────────┤
│                                                                        │
│  ┌──────────────────────┐          ┌──────────────────────┐          │
│  │  SettingsMqttView    │          │ SettingsCloudPublish │          │
│  │  (MQTT Connection)   │          │  (Publishing Config) │          │
│  └──────────┬───────────┘          └──────────┬───────────┘          │
│             │                                  │                       │
│             ├──────────────┬───────────────────┤                       │
│             │              │                   │                       │
│  ┌──────────▼──────────┐  │    ┌──────────────▼──────────┐           │
│  │ SettingsMqttViewModel│  │    │SettingsCloudPublishVM  │           │
│  └──────────┬───────────┘  │    └──────────────┬──────────┘           │
│             │              │                   │                       │
│  ┌──────────▼──────────────▼───────────────────▼──────────┐           │
│  │              MqttSettingsManager                        │           │
│  │         (Loads/Saves Settings.json)                     │           │
│  └──────────────────────────┬──────────────────────────────┘           │
│                             │                                          │
│  ┌──────────────────────────▼──────────────────────────────┐           │
│  │           ProcessDataViewViewModel                      │           │
│  │  • Manages UiChannels (ProcessData table)               │           │
│  │  • Reads EtherCAT data via DataRepo                     │           │
│  │  • Builds telemetry snapshots                           │           │
│  │  • Triggers MQTT publishing                             │           │
│  └──────────────────────────┬──────────────────────────────┘           │
│                             │                                          │
│                             ▼                                          │
│  ┌─────────────────────────────────────────────────────────┐           │
│  │         MqttTelemetryService                            │           │
│  │  • Manages formatter instances                          │           │
│  │  • Handles connections                                  │           │
│  │  • Publishes telemetry, events, alerts                  │           │
│  └──────────────────────────┬──────────────────────────────┘           │
│                             │                                          │
│                             ▼                                          │
│  ┌─────────────────────────────────────────────────────────┐           │
│  │      MqttPayloadFormatterFactory                        │           │
│  │   CreateFormatter(MqttPlatform) → IMqttPayloadFormatter │           │
│  └──────────────────────────┬──────────────────────────────┘           │
│                             │                                          │
│              ┌──────────────┼──────────────┐                           │
│              │              │              │                           │
│    ┌─────────▼───────┐  ┌──▼──────────┐ ┌─▼──────────────┐            │
│    │ ThingsBoard     │  │   Ubidots   │ │   Generic      │            │
│    │ Formatter       │  │   Formatter │ │   Formatter    │   ...      │
│    └─────────┬───────┘  └──┬──────────┘ └─┬──────────────┘            │
│              │             │              │                            │
│              └─────────────┼──────────────┘                            │
│                            │                                           │
│              ┌─────────────▼──────────────┐                            │
│              │     MqttService            │                            │
│              │  (MQTTnet client wrapper)  │                            │
│              └─────────────┬──────────────┘                            │
│                            │                                           │
└────────────────────────────┼───────────────────────────────────────────┘
                             │
                             ▼
        ┌────────────────────────────────────────┐
        │         MQTT Broker / IoT Platform     │
        │  • ThingsBoard Cloud                   │
        │  • Ubidots Industrial                  │
        │  • HiveMQ Cloud                        │
        │  • Public brokers (broker.emqx.io)     │
        │  • Custom brokers                      │
        └────────────────────────────────────────┘

👨‍💻 Developer Onboarding Checklist

If you’re new to this codebase…

Here’s the recommended path to understanding the MQTT system:

Step 1: Understand the Core Concepts (30 minutes)

  1. Read IMqttPayloadFormatter.cs – Understand the interface
  2. Look at GenericFormatter in MqttPayloadFormatters.cs – Simplest implementation
  3. Compare with ThingsBoardFormatter – See how formats differ
  4. Review MqttPayloadFormatterFactory – See how formatters are created

Step 2: Trace a Publish Flow (45 minutes)

  1. Open ProcessDataViewViewModel.cs
  2. Find OnMqttTelemetryTimerElapsed() – Entry point
  3. Follow to PublishMqttRealtimeTelemetryAsync()
  4. See how BuildTelemetrySnapshot() creates data
  5. Follow the call to _telemetryService.PublishTelemetryAsync()
  6. See how formatter is selected and used

Step 3: Run and Debug (30 minutes)

  1. Set breakpoint in BuildTelemetrySnapshot()
  2. Run application with EtherCAT simulation
  3. Enable Cloud Publishing
  4. Watch the debugger hit your breakpoint
  5. Step through to see data flow
  6. Use MQTT Explorer to see actual published messages

Step 4: Make a Small Change (1 hour)

Practice Task: Add a new platform (e.g., “MQTT.fx Broker”)

  1. Add MQTTfx to MqttPlatform enum
  2. Create MqttfxFormatter class implementing IMqttPayloadFormatter
  3. Add case to MqttPayloadFormatterFactory switch
  4. Test connection and publishing

Key Files Reference Card

File When to Modify
IMqttPayloadFormatter.cs Adding new methods all formatters need
MqttPayloadFormatters.cs Adding new platform support
MqttSettings.cs Adding new platform to enum
MqttTelemetryService.cs Adding new publishing features
ProcessDataViewViewModel.cs Changing what/how data is published
SettingsMqttView.axaml Modifying connection UI

✅ Summary

The MQTT system refactor transformed a rigid, platform-specific implementation into a flexible, extensible architecture supporting 7+ IoT platforms with minimal code changes.

3

New Files

5

Modified Files

7+

Platforms Supported

100%

Backward Compatible

Document Version: 1.0.0 | Last Updated: January 2026

CatLoggerEasy MQTT System Architecture Guide

📘 Platform Setup Guides |
🔧 Data Control Guide |
🚀 Implementation Steps

“`

🛒 View Cart (0)