ESP32 Universal Project Questions/Opinions

Hello im fairly beginner of the whole coding world but i always "wished" to make a universal project that can be easly reused

im working on a project i initally started to automate my homegrow, tho i figured out that the usecase/base can be used for many other projects too, for me the main thing would be to integrate devices into homeassistant trough mqtt

i mainly want that some "pros" look over this and what could be improved from a organization standpoint (i am pretty sure im not doing things like "in the book", since such project just cant be realized in a simple class)

i attached my platformio project, its compiling but far from finished, but you can see the main structure (mainly namespaces that interact with eachother) + "EzAddons" which are optional annd can be included by the user if needed

To get a bit more into the project:

i wanna build a "core" containing of
Serial
WebSerial
WebServer
Wifi
Ota
Telnet
Mqtt
StatusLed
1 Button
and such, all basic functionalitys i would say to basicly get a working project that can send mqtt messages and which can be monitored trough various ways (Serial, Telnet, Mqtt, WebSerial, Webserver)

then the easy part, the projects themself which the user does, that include this library and add for example an Sensor + Display, for these additional use cases i wanna include some "addons" that can help

Now the big thing im really worried about is maintanence, the projects and addons i will build will be probably still be build around home growing, i will probably just provide pretty specific addons but still.... its alot of namespaces/classes, im specially worried about backwards combatibility since this is my first library basicly.... any tips?

Yes.

Learn to crawl before trying to run.

That is learn to program before embarking on something so nebulous that it will changeling your none existent programming skills.

This is a mistake it seems a lot of beginners make, doing too much too soon.

1 Like

I don't click on links to unknown upload/download services.

Have you took a look at the code? its not like i never coded...
overall the sketch seems to work beside specific functions having some flaws i still wanna fix but these are not my point to ask here....

  1. the usecase of namespaces in that form seems to work the best for my usecase.... is this true or am i on the wrong path?
  2. if i wanna keep the library backwards combatible then i guess i only can actually remove functions only with major versions? atleast the function headers cant change

No. I don't download Zip files from 3rd party sites.

Well you did say:-

So were you telling the truth here or being overly modest.

We only know what you tell us and we can only react to what you actually say.

I would say so yes, it should not matter at all what the names are.

I don't understand that, major versions of what?

If you want to keep things compatible just do not update the functions you want to keep as your core functions. Versions of functions do not update automatically unless you have the IDE 2.0.x and you have set them to update automatically, you have a choice of not doing.

I can remember when some professor told the world that at most 15 different computer programs was all that were needed to do all the data processing that would ever be needed.
I still have my business card as part of the IBM plan that 5 very large data centers would serve the country for all the processing needs of the USA. Only one man committed suicide when the whole project crumbled.
So, anything approaching any universal solution makes me wonder how often this scheme will reappear.

2 Likes

well it would be great if someone actually takes a look at the code, or i might need to upload the project to github

i definitely struggled with this already, there were like 3-4 iteration, the first a project which was mainly altered trough defines

my current approach is much more flexible i belief, tho i wonder if i could still improve on this architecture, or for example how i can still squeeze defines into a library

but one "huge" library containing in the end 20-30 different classes is definitely another beast, thats why i wanna design the ground work as best as possible in the current stage

You could do what others have done. Write a program to generate the library on the fly as part of the compile process.

this comes with its own sets on drawbacks and why i actually dont wanna use esphome with homeassistant.... kind of unflexible and if you wanna do custom stuff its imo far more complicated than writing in C++ itself

Why don't you post your code like everyone else does?

If you don't know how then:-
You might want to look at this How to get the best out of this forum before you proceed any further.

At the moment you seem like a Schrodinger expert!

i dont think you get a whole picture from a few snippets

for example, the Serial Part:

#define CORE_COMPILE_SERIAL 1
#if CORE_COMPILE_SERIAL == 1
// ################################################################################################# INCLUDE

#include "EzSerial.h"

#include "EzCom.h"
#include "EzDebug.h"
#include "EzSettings.h"

// ################################################################################################# NAMESPACE core_serial

namespace EzSerial {

// ################################################################################################# PRIVATE

namespace {

  Stream *_serial = NULL;

  bool _comState = false;
  unsigned long _comStateStartMs = 0;

  void readSerial()
  {
    const char serialTerminator = '\n';
    const char stringTerminator = '\0';
    static char message[160] = "";
    static int messageLen = 0;
    
    if (_serial->available() > 0)
    {
      bool newMessage = false;
      while (_serial->available() > 0)
      {
        message[messageLen] = Serial.read();
        if (message[messageLen] == serialTerminator) {
          message[messageLen - 1] = stringTerminator;
          newMessage = true;
          break; 
        }
        messageLen++;
      }
    
      if (newMessage == true)
      {
        _comStateStartMs = millis();
        if (_comState == false)
        {
          _comState = true;
          EzDebug::debug(EzDebug::DEBUG_LEVEL::DEBUG, "[Serial] Communication Enabled!\n");
          _serial->print("[Serial] Welcome to the Terminal of ");
          _serial->println(EzPreferences::settings.deviceName);
          _serial->print("[Serial] Useful Commands: help, stats, reboot\n");
        } else { 
          EzDebug::debug(EzDebug::DEBUG_LEVEL::DEBUG, "[Serial] Input Received: \"%s\"\n", message);
          EzIntercom::input(message);
          message[0] = stringTerminator;
          messageLen = 0;
        }
      }
    }
  }
} 

// ################################################################################################# PRIVATE END

void comOutput(const char* message)
{
  if (_comState == true) { _serial->print(message); }
}

bool getComStatus()
{
  return _comState;
}

void setup(Stream *serial)
{
  _serial = serial;
  _comState = true;
  EzDebug::debug(EzDebug::DEBUG_LEVEL::INFO, "[Serial] Setup Complete\n");
}

void loop()
{
  readSerial();

  if(millis() - _comStateStartMs >= 30000)
  {
    static bool done;
    if (_comState == true) { done = false; }
    if (done == false)
    {
      EzDebug::debug(EzDebug::DEBUG_LEVEL::INFO, "[Serial] Good Bye!\n");
      EzDebug::debug(EzDebug::DEBUG_LEVEL::INFO, "[Serial] Communication Disabled\n");
      _comState = false;
      done = true;
    }
  }
}

} // ############################################################################################### NAMESPACE END core_serial
#endif // COMPILE_CORE_SERIAL

header:

#pragma once

#include <Arduino.h>

namespace EzSerial
{
  void comOutput(const char* message);
  bool getComStatus();

  void setup(Stream *serial);
  void loop();
} 

Correct!

What is wrong with posting all of your code?

Why will you not cooperate?