Skip to content

File core.cpp

Location: src/core.cpp

Includes

graph LR
10["core.h"]
click 10 "core_8h.md#core_8h"

12["mqtt.h"]
click 12 "mqtt_8h.md#mqtt_8h"
12 --> 2

11["network.h"]
click 11 "network_8h.md#network_8h"
11 --> 2

2["platform.h"]
click 2 "platform_8h.md#platform_8h"
2 --> 3
2 --> 4
2 --> 5
2 --> 6
2 --> 7
2 --> 8
2 --> 9

13["sensor.h"]
click 13 "sensor_8h.md#sensor_8h"
13 --> 2

14["storage.h"]
click 14 "storage_8h.md#storage_8h"
14 --> 2
14 --> 15

1["src/core.cpp"]
click 1 "core_8cpp.md#core_8cpp"
1 --> 2
1 --> 10
1 --> 11
1 --> 12
1 --> 13
1 --> 14
1 --> 16

7["Adafruit_ADT7410.h"]

3["Arduino.h"]

8["ArduinoJson.h"]

9["ArduinoMqttClient.h"]

6["RTClib.h"]

5["SdFat.h"]

4["Wire.h"]

15["cstdio"]

16["secrets.h"]

Variables

Variable rtc

Definition: src/core.cpp (line 17)

RTC_DS3231 rtc

Type: RTC_DS3231

Variable tempsensor

Definition: src/core.cpp (line 18)

Adafruit_ADT7410 tempsensor

Type: Adafruit_ADT7410

Variable sd

Definition: src/core.cpp (line 19)

SdFat sd

Type: SdFat

Variable wifiClient


Definition: src/core.cpp (line 20)

WiFiClient wifiClient

Type: WiFiClient

Variable CHIP_SELECT


Definition: src/core.cpp (line 29)

const uint8_t CHIP_SELECT = 4

SD card chip select pin.

Type: const uint8_t

Variable SENSOR_ID_ONE


Definition: src/core.cpp (line 30)

const char* SENSOR_ID_ONE = "Sensor_One"

Type: const char *

Variable SENSOR_ID_IN_USE


Definition: src/core.cpp (line 31)

const char* SENSOR_ID_IN_USE = [SENSOR\_ID\_ONE](core_8cpp.md#core_8cpp_1adfea6785b2b85c4960d78d8c64a1af5d)

Type: const char *

Variable SENSOR_TYPE


Definition: src/core.cpp (line 34)

const char* SENSOR_TYPE = "temp"

Type: const char *

Variable MQTT_TOPIC


Definition: src/core.cpp (line 35)

const char* MQTT_TOPIC = "dhbw/ai/si2023/2/"

Type: const char *

Variable WIFI_CONNECT_TIMEOUT_MS


Definition: src/core.cpp (line 41)

const unsigned long WIFI_CONNECT_TIMEOUT_MS = 15000

Type: const unsigned long

Variable LOOP_DELAY_MS


Definition: src/core.cpp (line 42)

const unsigned long LOOP_DELAY_MS = 1000

Type: const unsigned long

Variable CLIENT_ID_BUFFER_SIZE


Definition: src/core.cpp (line 43)

const size_t CLIENT_ID_BUFFER_SIZE = 64

Type: const size_t

Variable SD_SCK_FREQUENCY_MHZ


Definition: src/core.cpp (line 45)

const uint8_t SD_SCK_FREQUENCY_MHZ = 25

Type: const uint8_t

Variable RECONNECT_INTERVAL_MS


Definition: src/core.cpp (line 47)

const int RECONNECT_INTERVAL_MS = 2000

Type: const int

Variable lastLoggedMinute


Definition: src/core.cpp (line 53)

int lastLoggedMinute = -1

Type: int

Variable seqCount


Definition: src/core.cpp (line 54)

int seqCount = 0

Type: int

Variable recoverySent


Definition: src/core.cpp (line 55)

bool recoverySent = false

Type: bool

Variable lastReconnectAttempt


Definition: src/core.cpp (line 56)

unsigned long lastReconnectAttempt = 0

Type: unsigned long

Functions

Function mqttClient

MqttClient mqttClient(wifiClient)

Parameters:

Return type: MqttClient

Function IsWifiConnected

bool IsWifiConnected()

Return type: bool

Function IsMqttConnected

bool IsMqttConnected()

Return type: bool

Function FatDateTime

void FatDateTime(uint16_t *date, uint16_t *time)

Callback function for FAT file system timestamp generation.

This function is used by the SdFat library to obtain current date and time for file system operations. It retrieves the time from the RTC and converts it to the FAT file system format using the appropriate macros.

Parameters:

  • date: Pointer to store the encoded FAT date (year, month, day)
  • time: Pointer to store the encoded FAT time (hour, minute, second)

?> This function is registered as a callback with SdFile::dateTimeCallback()

See also: FAT_DATE, FAT_TIME macros for encoding format details

Parameters:

  • uint16_t * date
  • uint16_t * time

Return type: void

Function CoreSetup

void CoreSetup()

Initializes all core system components and peripherals.

This function performs comprehensive system initialization including:

Network Setup:
* Establishes WiFi connection with timeout handling

  • Configures MQTT client with unique sensor-based ID

  • Attempts initial MQTT broker connection

Hardware Initialization:
* Initializes DS3231 real-time clock module

  • Adjusts RTC time if power was lost (uses compilation timestamp)

  • Sets up SD card with SPI communication

  • Initializes ADT7410 temperature sensor

Data Recovery:
* Registers FAT file system timestamp callback

!> Warning \
This function will halt program execution (infinite loop) if any critical component fails to initialize (RTC, SD card, or temperature sensor)

?> The function uses compile-time constants for timeouts and configuration

See also: WIFI_CONNECT_TIMEOUT_MS, CLIENT_ID_BUFFER_SIZE, SD_SCK_FREQUENCY_MHZ

Return type: void

Function CoreLoop

void CoreLoop()

Main operational loop for continuous sensor monitoring, MQTT transmission, and robust data recovery.

This function implements the primary logic for the temperature monitoring system, including:
* Real-time sensor measurement and transmission via MQTT with QoS 1

  • Intelligent WiFi and MQTT connection management with automatic reconnection

  • Fallback to CSV batch storage during connectivity outages

  • Recovery and transmission of offline data after successful reconnection

  • Comprehensive error handling and status reporting

Operational Flow: 1. Time Management: Reads current time from RTC, tracks minute changes to avoid duplicate measurements. 2. WiFi Connection: Monitors status, attempts reconnection, falls back to CSV logging if offline. 3. MQTT Connection: Verifies broker connectivity, reconnects as needed, falls back to CSV logging if offline. 4. Data Recovery: Sends pending CSV data after reconnection, ensures recovery only once per cycle. 5. Normal Operation: Measures temperature, transmits via MQTT, polls for incoming messages.

Error Handling:
* Network or broker failures trigger CSV fallback storage for all measurements.

  • Connection attempts are rate-limited to prevent resource exhaustion.

  • All measurement data is preserved and recovered after connectivity is restored.

?> Maintains a fixed loop delay for consistent timing and system stability.

See also: RECONNECT_INTERVAL_MS, LOOP_DELAY_MS for timing configuration, saveToCsvBatch() for offline data storage, sendPendingData() for data recovery and MQTT retransmission

Return type: void

Source

#include "platform.h"
#include "core.h"
#include "network.h"
#include "mqtt.h"
#include "sensor.h"
#include "storage.h"

#ifdef UNIT_TEST
#include "secrets_example.h"
#else
#include "secrets.h"
#endif


#ifndef UNIT_TEST
// Global hardware objects for real hardware only
RTC_DS3231 rtc;
Adafruit_ADT7410 tempsensor;   
SdFat sd;
static WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
#endif

// =============================================================================
// SYSTEM CONFIGURATION CONSTANTS
// =============================================================================

static const uint8_t CHIP_SELECT = 4;
static const char* SENSOR_ID_ONE = "Sensor_One";
static const char* SENSOR_ID_IN_USE = SENSOR_ID_ONE; 
// static const char* SENSOR_ID_TWO = "Sensor_Two";
// static const char* SENSOR_ID_IN_USE = SENSOR_ID_TWO; // Uncomment to use the second
static const char* SENSOR_TYPE = "temp";
static const char* MQTT_TOPIC = "dhbw/ai/si2023/2/";

// =============================================================================
// TIMING AND CONNECTION CONSTANTS
// =============================================================================

static const unsigned long WIFI_CONNECT_TIMEOUT_MS = 15000;
static const unsigned long LOOP_DELAY_MS = 1000;
static const size_t CLIENT_ID_BUFFER_SIZE = 64;
#ifndef UNIT_TEST
static const uint8_t SD_SCK_FREQUENCY_MHZ = 25;
#endif
static const int RECONNECT_INTERVAL_MS = 2000;

// =============================================================================
// SYSTEM STATE VARIABLES
// =============================================================================

static int lastLoggedMinute = -1;
static int seqCount = 0;
static bool recoverySent = false;
static unsigned long lastReconnectAttempt = 0;

// =============================================================================
// CONNECTION STATUS FUNCTIONS
// =============================================================================

bool IsWifiConnected() {
  return WiFi.status() == WL_CONNECTED;
}

bool IsMqttConnected() {
  return mqttClient.connected();
}

// =============================================================================
// FAT FILE SYSTEM CALLBACK FUNCTIONS
// =============================================================================

void FatDateTime(uint16_t* date, uint16_t* time) {
  DateTime now = rtc.now();
  *date = FAT_DATE(now.year(), now.month(), now.day());
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}

// =============================================================================
// SYSTEM INITIALIZATION FUNCTIONS
// =============================================================================

void CoreSetup() {
  ConnectToWiFi(WIFI_CONNECT_TIMEOUT_MS);

  char clientId[CLIENT_ID_BUFFER_SIZE];
  snprintf(clientId, sizeof(clientId), "IsoPruefi_%s", SENSOR_ID_IN_USE);
  mqttClient.setId(clientId);

  if (IsWifiConnected()) {
    ConnectToMQTT(mqttClient);
  }

  if (!rtc.begin()) {
    Serial.println("RTC not found!");
    while (1);
  }

  // Set RTC time if power was lost (uses compilation timestamp)
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  // Register callback for SD file timestamps and initialize SD card
  SdFile::dateTimeCallback(FatDateTime);
  if (!sd.begin(CHIP_SELECT, SD_SCK_MHZ(SD_SCK_FREQUENCY_MHZ))) {
    Serial.println("SD card failed.");
    while (1);
  }

  if (!InitSensor(tempsensor)) {
    Serial.println("ADT7410 init failed!");
    while (1);
  }

  DateTime now = rtc.now();
  Serial.print("Current time: ");
  Serial.println(now.timestamp(DateTime::TIMESTAMP_FULL));
  Serial.print("Lost Power? "); 
  Serial.println(rtc.lostPower() ? "YES" : "NO");

  Serial.println("Setup complete.");
}

// =============================================================================
// MAIN OPERATIONAL LOOP
// =============================================================================

void CoreLoop() {
  DateTime now = rtc.now();
  static bool alreadyLoggedThisMinute = false;

  if (now.minute() != lastLoggedMinute) {
    lastLoggedMinute = now.minute();
    alreadyLoggedThisMinute = false;
  }

  // Step 1: Check WiFi connection
  if (!IsWifiConnected()) {
    if (millis() - lastReconnectAttempt > RECONNECT_INTERVAL_MS) {
      lastReconnectAttempt = millis();
      Serial.println("WiFi not connected. Trying to reconnect...");
      ConnectToWiFi(WIFI_CONNECT_TIMEOUT_MS);
    }

    if (!IsWifiConnected()) {
      Serial.println("WiFi reconnect failed. Skipping loop.");
      if (!alreadyLoggedThisMinute) {
        float c = ReadTemperatureInCelsius();
        SaveTempToBatchCsv(now, c, seqCount);
        alreadyLoggedThisMinute = true;
        seqCount++;
      }
      delay(LOOP_DELAY_MS);
      return;
    }
  }

  // Step 2: Check MQTT connection
  if (!IsMqttConnected()) {
    Serial.println("MQTT not connected. Trying to reconnect...");
    if (!ConnectToMQTT(mqttClient)) {
      Serial.println("MQTT reconnect failed. Skipping loop.");
      if (!alreadyLoggedThisMinute) {
        float c = ReadTemperatureInCelsius();
        SaveTempToBatchCsv(now, c, seqCount);
        alreadyLoggedThisMinute = true;
        seqCount++;
      }
      delay(LOOP_DELAY_MS);
      return;
    }

    Serial.println("MQTT reconnected successfully.");
    recoverySent = false; // Allow recovery again
  }

  // Step 3: After successful MQTT reconnect → send old CSVs
  if (!recoverySent && IsConnectedToServer(mqttClient)) {
    if (SendPendingDataToMqtt(mqttClient, MQTT_TOPIC, SENSOR_TYPE, SENSOR_ID_IN_USE, now)) {
      recoverySent = true;
    }
  }

  // Step 4: Normal measurement and MQTT transmission
  if (!alreadyLoggedThisMinute && IsConnectedToServer(mqttClient)) {
    float c = ReadTemperatureInCelsius();
    SendTempToMqtt(mqttClient, MQTT_TOPIC, SENSOR_TYPE, SENSOR_ID_IN_USE, c, now, seqCount);
    alreadyLoggedThisMinute = true;
    seqCount++;
  }

  // Step 5: MQTT loop and wait time
  mqttClient.poll();
  delay(LOOP_DELAY_MS);
}