OPEnSLab-OSU / Loom

Arduino library for Internet of Things Rapid Prototyping in environmental sensing
GNU General Public License v3.0
26 stars 3 forks source link

MongoDB Time format issue when using Loom Local Time #203

Open udellc opened 2 years ago

udellc commented 2 years ago

Describe the bug When using Local Time for the DS3231 module, Loom3 publishes an extra 0 in the main UTC timestamp data. 2022-006-30T15:10:28Z

When not using local time in the DS3231 module, the UTC time publishes to MongoDB like this: 2022-06-30T15:10:28Z

Notice there is only one zero for 06 month of June when correctly formatted, but 006 for June when using local time.

To be clear, enabling local time changes the formatting of the UTC timestamp.

Furthermore, the Local time timestamp is seperated into 3 seperate data fields for date, time, timezone, which is not useful for using as an X-axis plot in MongoDB and is not a standard formatting. Date:"2022/06/30" Time:"08:10:28" TimeZone:"PDT"

Hardware in Use WeatherChimes

To Reproduce Enable local time in config like so:

    {\
      'name':'DS3231',\
      'params':[10, true, true]\
    },\

Expected behavior First, enabling local time should not add an extra zero to the month of the UTC timestamp data Second, Local time needs to be formatted like UTC time to be used as a potential X axis plot source.

ino Code

///////////////////////////////////////////////////////////////////////////////

// This is a basic example that demonstrates how to log data to an SD card
// using Loom.

///////////////////////////////////////////////////////////////////////////////

#include <Loom.h>
#include "MQTT.h"

// These are default times to sleep between cycles if there is no SD_config.txt file exists on SD card for user-set time
int secs = 20;
int mins = 0;
int hours = 0;
int days = 0;

// Include configuration
const char* json_config =
#include "config.h"
;

// In Tools menu, set:
// Internet  > Disabled
// Sensors   > Enabled
// Radios    > Disabled
// Actuators > Disabled
// Max       > Disabled

using namespace Loom;

Loom::Manager Feather{};

char devName[20];
String topic = "";
String jsonSerialized = "";

DynamicJsonDocument doc(1024);

void setup()
{
  delay(3000); // Wait a bit in case we want to program the device
  pinMode(5, OUTPUT);   // Enable control of 3.3V rail 
  pinMode(6, OUTPUT);   // Enable control of 5V rail 

  //See Above
  digitalWrite(5, LOW); // Enable 3.3V rail
  digitalWrite(6, HIGH);  // Enable 5V rail
  
  Feather.begin_LED();
  Feather.begin_serial(true);
  Feather.parse_config(json_config);
  Feather.print_config();

  // Register an interrupt on the RTC alarm pin
  getInterruptManager(Feather).register_ISR(12, wakeISR_RTC, LOW, ISR_Type::IMMEDIATE);

  // Get the device name and then using the device name, instance number and site name create a topic name to publish to
  Feather.get_device_name(devName);
  topic = String(SITE_NAME) + "/" + String(devName) + String(Feather.get_instance_num());

  enable_wifi();

  LPrintln("\n ** Setup Complete ** ");
}

void loop()
{
  Feather.measure();
  Feather.package();
  Feather.display_data();

  // Log using default filename as provided in configuration
  // in this case, 'datafile.csv'
  getSD(Feather).log();

  // Or log to a specific file (does not change what default file is set to)
  // getSD(Feather)log("specific.csv");

  // SD Hard Faults and makes the MQTT json packet change topic name to Errors#
  // So we use a customized function to build the correct topic and instance name
  // Log online to MongoDB via MQTT WiFi
  connect_to_wifi();
  connect_to_broker(1);
  // Build JSON document to publish via MQTT
  doc.clear();
  jsonSerialized = "";
  doc.add(Feather.internal_json(false));
  serializeJson(doc, jsonSerialized);
  //publish_mqtt(topic, jsonSerialized);
  publish_mqtt(String(SITE_NAME)+"/Chime"+String(Feather.get_instance_num()), jsonSerialized); // Replace content in Quotes with the Topic name

  // Set RTC Timer for wake up and sample to next time interval
  getInterruptManager(Feather).RTC_alarm_duration(TimeSpan(days,hours,mins,secs));
  getInterruptManager(Feather).reconnect_interrupt(12);

  disconnect_wifi(); // Disable WiFi for power savings

  digitalWrite(5, HIGH); // Disable 3.3V rail
  digitalWrite(6, LOW);  // Disable 5V rail

  // Disable SPI pins/SD chip select to save power
  pinMode(23, INPUT);
  pinMode(24, INPUT);
  pinMode(10, INPUT);  // Needs to be correct pin for SD CS on Hypnos

  Feather.power_down();
  getSleepManager(Feather).sleep(); // Sketch pauses here until RTC alarm

  digitalWrite(5, LOW); // Enable 3.3V rail
  digitalWrite(6, HIGH);  // Enable 5V rail

  pinMode(23, OUTPUT);
  pinMode(24, OUTPUT);
  pinMode(10, OUTPUT); // Needs to be correct pin for SD CS on Hypnos

  // *** SITS Here in Sleep till p12 RTC Alarm Wake Signal ...

  Feather.power_up();
  delay(1000);        // Delay for power 
}

void wakeISR_RTC() {  
  // disable the interrupt
  detachInterrupt(12);
}

MQTT.h

#pragma once
#include <ArduinoMqttClient.h>
#include <WiFi101.h>

#include "arduino_secrets.h"

// Feather M0 Wifi Pins
#define WINC_CS   8
#define WINC_IRQ  7
#define WINC_RST  4
#define WINC_EN   2

char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;

const char broker[] = SECRET_BROKER;
int port = BROKER_PORT;

WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);

/* Disconnect from broker and WiFi*/
void disconnect_wifi(){
  mqttClient.stop();
  WiFi.disconnect();
  WiFi.end();
}

/**
 * Connect to the wifi network
 */ 
void connect_to_wifi(){

    // Try to conect to the wifi network
    Serial.print("[MQTT] Attempting to connect to SSID: ");
    Serial.println(ssid);

    // Check if there is a password for the wifi or not
    if(strlen(pass) > 0){
        // Try to connect to the Wifi network until it succeeds 
        while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
            Serial.print("[MQTT] Attempting connection to AP...");
            delay(5000);
        }
    }
    else{
        // Try to connect to the Wifi network until it succeeds 
        while (WiFi.begin(ssid) != WL_CONNECTED) {
            Serial.print("[MQTT] Attempting connection to AP...");
            delay(5000);
        }
    }

    Serial.println("Connected to network!");
}

/*
 * Enable the Wifi but don't connect to any network
 */
void enable_wifi(){
  
  // Set the pins that the WiFi module should
  WiFi.setPins(WINC_CS, WINC_IRQ, WINC_RST, WINC_EN);
  
  // Initialise the Client
  Serial.print(F("\nInit the WiFi module..."));
  
  // Check for the presence of the breakout
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WINC1500 not present");
    
    // don't continue:
    while (true);
  }

  // Set the WiFi chip into the lowest power mode to conserve energy
  WiFi.maxLowPowerMode();
  
  Serial.println("ATWINC OK!");
}

/**
 * Connect to the MQTT broker
 */ 
void connect_to_broker(int keepAliveMins){

    // Set the MQTT username and password
    mqttClient.setUsernamePassword(BROKER_USER, BROKER_PASSWORD);

    // Set keep alive time
    mqttClient.setKeepAliveInterval(1000 * 60 * keepAliveMins);

    Serial.print("[MQTT] Attempting to connect to broker: ");
    Serial.println(broker);

    // Try to connect to the broker
    if (!mqttClient.connect(broker, port)) {
        Serial.print("[MQTT] MQTT connection failed! Error code = ");
        Serial.println(mqttClient.connectError());
    }

    Serial.println("[MQTT] You're connected to the MQTT broker!");
}

/**
 * Publish the data to the correct topic
 */ 
void publish_mqtt(String topic, String data){

    // send message, the Print interface can be used to set the message contents
    mqttClient.poll();
    delay(250);         // ****** Added 6.8.22 Test if delay after poll fixes freezing
    mqttClient.beginMessage(topic);
    mqttClient.print(data);
    mqttClient.endMessage();
}

arduino_secrets


// Wifi settings
#define SECRET_SSID "Redacted" // WiFi Name
#define SECRET_PASS "redacted"  // WiFi Password

// MQTT Settings
#define BROKER_USER "redacted"
#define BROKER_PASSWORD "redacted"
#define SECRET_BROKER "cas-redacted"
#define BROKER_PORT 1883
#define SITE_NAME "WeatherChimes" // The name of the location where these nodes will be placed

Config

"{\
  'general':\
  {\
    'name':'Chime',\
    'instance':4,\
    'interval':5000,\
    'print_verbosity':2\
  },\
  'components':[\
    {\
      'name':'SD',\
      'params':[true, 1000, 10,'chimes', true]\
    },\
    {\
      'name':'InterruptManager',\
      'params':'default'\
    },\
    {\
      'name':'SleepManager',\
      'params':[true,false,1]\
    },\
    {\
      'name':'DS3231',\
      'params':[10, true, true]\
    },\
    {\
      'name':'SDIManager',\
      'params':'default'\
    },\
    {\
      'name':'TSL2591',\
      'params':[41, 255, 1, 0]\
    },\
    {\
      'name':'SHT31D',\
      'params':'default'\
    },\
    {\
      'name':'Analog',\
      'params':[\
        8,\
        12,\
        false,\
        false,\
        false,\
        false,\
        false,\
        false,\
        1,\
        1,\
        1,\
        1,\
        1,\
        1,\
        25.0\
      ]\
    }\
  ]\
}"

Additional context Add any other context about the problem here.