About a week ago, I was doing some refactoring and all of a sudden I get a huge number of C++ compiler errors that don’t make any sense. They occurred in a collection of classes connected thru inheritance. Ever since, I’ve been unable to install this code on my ESP8266. I’ve gone thru all the suggestions about my build environment that I have found with no solution. I’m getting 180 errors on code that is clean. Here is some of the code that is offending. I checks fine on ChatGPT. I haven’t figured out how to compile if using C++ compiler from the command line, but all classes in the project have Clion green arrows in the upper right corner. I’m getting a little desperate now. Any further ideas? The project is private, but I have no problem sharing the entire thing here. Thanks.
#pragma once
#include "BumperDigitalState.h"
#include "BumperState.h"
#include "DetectModeState.h"
#include "EventPublisher.h"
#include "PinConfig.h"
#include "RailState.h"
#include "SharedState.h"
#include "SimpleUncouplerState.h"
#include "TrackPowerMonitor.h"
#include "TurnoutPositionState.h"
#include "TurnoutState.h"
#include "TurnoutTrackState.h"
#include "UncouplerState.h"
#include <cstdint>
#include <map>
#include <chrono>
using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
using std::chrono::microseconds;
using std::chrono::seconds;
using std::chrono::system_clock;
using std::chrono::time_point;
class AppState {
public:
AppState();
explicit AppState(PinConfig *analogPinConfig);
virtual ~AppState();
virtual void activate();
virtual void adjust();
virtual void addDigitalPinConfig(PinConfig *pinConfig);
virtual void bumpServoCount();
static AppState *createAppState(PinConfig *analogPinConfig);
[[nodiscard]] uint16_t getOnWidth() const;
void setDigitalPinConfig(PinConfig *pinConfig);
virtual void processMessage(const char* string, const char* message);
virtual void publishChanges(EventPublisher *publisher, TrackPowerMonitor *trackPowerMonitor);
virtual void publishCurrentState(EventPublisher *publisher, TrackPowerMonitor *trackPowerMonitor);
void setOnWidth(uint16_t onWidth);
virtual void updateStatus(long long currentTime, SharedState *sharedState);
protected:
enum TrackState {
EMPTY,
CAR_OCCUPIED,
ENGINE_OCCUPIED
};
const char* emptyMessage = "EMPTY";
const char* carMessage = "CAR";
const char* engineMessage = "ENGINE";
const char* activeMessage = "ACTIVE";
const char* inactiveMessage = "INACTIVE";
const char* unknownMessage = "UNKNOWN";
const char* blockTopic = "trains/blockTopic";
const char* sensorTopic = "trains/sensorTopic";
const long long DEBOUNCE_TIME {5000};
const long long PULSE_PERIOD {50000};
TrackState trackState = EMPTY;
bool trackStateChanged = true;
long long stableTime {};
bool pendingDebounce = false;
PinConfig* analogPinConfig {};
PinConfig* digitalPinConfig {};
uint16_t servoCount {0};
char id[10] = {0};
char *actuatorId {};
bool hasReported {false};
const char* concatIdToTopic(char* buffer, const char* topic);
static bool isCarPresent(SharedState *sharedState, uint16_t mask);
static bool isEmpty(SharedState *sharedState, uint16_t mask);
static bool isEnginePresent(SharedState *sharedState, uint16_t mask);
void setTrackState(TrackState state, long long currentTime);
void updateTrackStatus(long long currentTime, SharedState* sharedState, uint16_t mask);
};
#include "AppState.h"
AppState::AppState() = default;
AppState::AppState(PinConfig *analogPinConfig) :
analogPinConfig{analogPinConfig} {
}
void AppState::activate() {
}
void AppState::adjust() {
}
void AppState::addDigitalPinConfig(PinConfig *pinConfig) {
}
AppState::~AppState() = default;
void AppState::bumpServoCount() {
}
const char *AppState::concatIdToTopic(char* messageBuffer, const char *topic) {
strcat(messageBuffer, topic);
strcat(messageBuffer, "/");
strcat(messageBuffer, id);
return messageBuffer;
}
AppState * AppState::createAppState(PinConfig *analogPinConfig) {
switch (analogPinConfig->pinType) {
case bumperAnalog:
return new BumperState(analogPinConfig);
case bumperDigital:
return new BumperDigitalState(analogPinConfig);
case detectModeDigital:
return new DetectModeState(analogPinConfig);
case railAnalog:
return new RailState(analogPinConfig);
case simpleUncouplerAnalog:
return new SimpleUncouplerState(analogPinConfig);
case simpleUncouplerDigital:
return new SimpleUncouplerState(analogPinConfig);
case turnoutAnalog:
return new TurnoutState(analogPinConfig);
case turnoutDigital:
return new TurnoutState(analogPinConfig);
case turnoutPosition:
return new TurnoutPositionState(analogPinConfig);
case turnoutTrack:
return new TurnoutTrackState(analogPinConfig);
case uncouplerAnalog:
return new UncouplerState(analogPinConfig);
case uncouplerDigital:
return new UncouplerState(analogPinConfig);
default:
Serial.print("Error creating AppState object of type: ");
Serial.println(analogPinConfig->pinType);
}
return nullptr;
}
uint16_t AppState::getOnWidth() const {
return analogPinConfig->onWidth;
}
bool AppState::isCarPresent(SharedState *sharedState, uint16_t mask) {
return sharedState->getLowAnalogValues(mask) != 0;
}
bool AppState::isEmpty(SharedState *sharedState, uint16_t mask) {
return sharedState->getLowAnalogValues(mask) == 0 &&
sharedState->getHighAnalogValues(mask) == 0;
}
bool AppState::isEnginePresent(SharedState *sharedState, uint16_t mask) {
return sharedState->getHighAnalogValues(mask) != 0;
}
void AppState::processMessage(const char* string, const char* message) {
}
void AppState::setOnWidth(uint16_t value) {
analogPinConfig->onWidth = value;
}
void AppState::publishChanges(EventPublisher *publisher, TrackPowerMonitor *trackPowerMonitor) {
if (!hasReported || (trackStateChanged && !trackPowerMonitor->isShutdown())) {
char messageBuffer[64] {0};
switch (trackState) {
case EMPTY:
publisher->publishEvent(concatIdToTopic(messageBuffer, blockTopic), emptyMessage);
break;
case CAR_OCCUPIED:
publisher->publishEvent(concatIdToTopic(messageBuffer, blockTopic), carMessage);
break;
case ENGINE_OCCUPIED:
publisher->publishEvent(concatIdToTopic(messageBuffer, blockTopic), engineMessage);
break;
}
trackStateChanged = false;
}
hasReported = true;
}
void AppState::publishCurrentState(EventPublisher *publisher, TrackPowerMonitor *trackPowerMonitor) {
char messageBuffer[64] {0};
switch (trackState) {
case EMPTY:
publisher->publishEvent(concatIdToTopic(messageBuffer, blockTopic), emptyMessage);
break;
case CAR_OCCUPIED:
publisher->publishEvent(concatIdToTopic(messageBuffer, blockTopic), carMessage);
break;
case ENGINE_OCCUPIED:
publisher->publishEvent(concatIdToTopic(messageBuffer, blockTopic), engineMessage);
break;
}
}
void AppState::setDigitalPinConfig(PinConfig *pinConfig) {
digitalPinConfig = pinConfig;
}
void AppState::setTrackState(TrackState state, long long currentTime) {
trackState = state;
stableTime = currentTime;
pendingDebounce = true;
}
void AppState::updateStatus(long long currentTime, SharedState *sharedState) {
}
void AppState::updateTrackStatus(long long currentTime, SharedState* sharedState, uint16_t mask) {
if (sharedState->hasInputChanged(mask)) {
switch (trackState) {
case EMPTY:
if (isEnginePresent(sharedState, mask)) {
setTrackState(ENGINE_OCCUPIED, currentTime);
} else if (isCarPresent(sharedState, mask)) {
setTrackState(CAR_OCCUPIED, currentTime);
}
break;
case CAR_OCCUPIED:
if (isEnginePresent(sharedState, mask)) {
setTrackState(ENGINE_OCCUPIED, currentTime);
} else if (isEmpty(sharedState, mask)) {
setTrackState(EMPTY, currentTime);
}
break;
case ENGINE_OCCUPIED:
if (!isEnginePresent(sharedState, mask)) {
if (isCarPresent(sharedState, mask)) {
setTrackState(CAR_OCCUPIED, currentTime);
} else {
setTrackState(EMPTY, currentTime);
}
}
break;
}
}
if (pendingDebounce && (currentTime - stableTime) > DEBOUNCE_TIME.count()) {
pendingDebounce = false;
trackStateChanged = true;
}
}
#pragma once
#include "AppState.h"
class BumperDigitalState final : public AppState {
public:
explicit BumperDigitalState(PinConfig *analogPinConfig);
void updateStatus(long long currentTime, SharedState *sharedState) override;
private:
enum BumperState {
UNKNOWN,
EMPTY,
OCCUPIED
};
BumperState currentState = UNKNOWN;
bool isEmpty(SharedState *sharedState);
bool isOccupied(SharedState *sharedState);
void setCurrentState(BumperState newState);
};
#include "BumperState.h"
BumperState::BumperState(PinConfig *analogPinConfig) : AppState(analogPinConfig) {
}
void BumperState::updateStatus(long long currentTime, SharedState* sharedState) {
uint16_t mask = 1 << analogPinConfig->firstPin;
updateTrackStatus(currentTime, sharedState, mask);
}