#pragma once #ifdef ESP32 #include typedef HardwareSerial SerialType; #define SERIAL_TYPE HardwareSerial #elif defined(ESP8266) #include typedef SoftwareSerial SerialType; #define SERIAL_TYPE SoftwareSerial #else #error "Unsupported platform. Only ESP32 and ESP8266 are supported." #endif #include #include #include "hardware.pb.h" // Define the role of this device // Uncomment one of the following defines to set the role //#define HARDWARE_SERIAL_ROLE_CONTROL #define HARDWARE_SERIAL_ROLE_SENSOR // Based on role, define the message types #if defined(HARDWARE_SERIAL_ROLE_CONTROL) typedef hardware_SensorToControlMessage IncomingMessage; typedef hardware_ControlToSensorMessage OutgoingMessage; #define INCOMING_MESSAGE_SIZE hardware_SensorToControlMessage_size #define OUTGOING_MESSAGE_SIZE hardware_ControlToSensorMessage_size #define INCOMING_MESSAGE_FIELDS hardware_SensorToControlMessage_fields #define OUTGOING_MESSAGE_FIELDS hardware_ControlToSensorMessage_fields #define INCOMING_MESSAGE_INIT hardware_SensorToControlMessage_init_default #define OUTGOING_MESSAGE_INIT hardware_ControlToSensorMessage_init_default #elif defined(HARDWARE_SERIAL_ROLE_SENSOR) typedef hardware_ControlToSensorMessage IncomingMessage; typedef hardware_SensorToControlMessage OutgoingMessage; #define INCOMING_MESSAGE_SIZE hardware_ControlToSensorMessage_size #define OUTGOING_MESSAGE_SIZE hardware_SensorToControlMessage_size #define INCOMING_MESSAGE_FIELDS hardware_ControlToSensorMessage_fields #define OUTGOING_MESSAGE_FIELDS hardware_SensorToControlMessage_fields #define INCOMING_MESSAGE_INIT hardware_ControlToSensorMessage_init_default #define OUTGOING_MESSAGE_INIT hardware_SensorToControlMessage_init_default #else #error "Must define either HARDWARE_SERIAL_ROLE_CONTROL or HARDWARE_SERIAL_ROLE_SENSOR" #endif class ProtoSerial { public: ProtoSerial(); ~ProtoSerial(); // Initialize with RX and TX pins void begin(int rxPin, int txPin, long baud = 9600); // Send a message bool sendMessage(const OutgoingMessage& message); // Check for incoming messages (non-blocking) void update(); // Check if a message has been received bool hasMessage() const; // Get the received message (only valid if hasMessage() returns true) const IncomingMessage& getMessage() const; // Clear the received message void clearMessage(); private: SerialType* serial; bool initialized; // Receive state machine enum RxState { WAITING_FOR_LENGTH, READING_PAYLOAD }; RxState currentState; uint16_t payloadLength; uint8_t payloadBuffer[64]; // Max message size + some buffer IncomingMessage receivedMessage; bool messageAvailable; // Helper methods void processReceivedMessage(uint8_t* buffer, uint16_t length); };