// ----------------------------------------------------------------------------- // Abstract sensor class (other sensor classes extend this class) // Copyright (C) 2017 by Xose PĂ©rez // ----------------------------------------------------------------------------- #pragma once #include #include typedef enum magnitude_t { MAGNITUDE_NONE = 0, MAGNITUDE_TEMPERATURE, MAGNITUDE_HUMIDITY, MAGNITUDE_PRESSURE, MAGNITUDE_CURRENT, MAGNITUDE_VOLTAGE, MAGNITUDE_POWER_ACTIVE, MAGNITUDE_POWER_APPARENT, MAGNITUDE_POWER_REACTIVE, MAGNITUDE_ENERGY, MAGNITUDE_ENERGY_DELTA, MAGNITUDE_POWER_FACTOR, MAGNITUDE_ANALOG, MAGNITUDE_DIGITAL, MAGNITUDE_EVENTS, MAGNITUDE_PM1dot0, MAGNITUDE_PM2dot5, MAGNITUDE_PM10, MAGNITUDE_CO2, MAGNITUDE_MAX, } magnitude_t; #define GPIO_NONE 0x99 #define SENSOR_ERROR_OK 0 // No error #define SENSOR_ERROR_OUT_OF_RANGE 1 // Result out of sensor range #define SENSOR_ERROR_WARM_UP 2 // Sensor is warming-up #define SENSOR_ERROR_TIMEOUT 3 // Response from sensor timed out #define SENSOR_ERROR_UNKNOWN_ID 4 // Sensor did not report a known ID #define SENSOR_ERROR_CRC 5 // Sensor data corrupted #define SENSOR_ERROR_I2C 6 // Wrong or locked I2C address class BaseSensor { public: // Constructor BaseSensor() {} // Destructor ~BaseSensor() {} // Initialization method, must be idempotent virtual void begin() {} // Loop-like method, call it in your main loop virtual void tick() {} // Pre-read hook (usually to populate registers with up-to-date data) virtual void pre() {} // Post-read hook (usually to reset things) virtual void post() {} // Descriptive name of the sensor virtual String description() {} // Type for slot # index virtual magnitude_t type(unsigned char index) {} // Current value for slot # index virtual double value(unsigned char index) {} // Retrieve current instance configuration virtual void getConfig(JsonObject& root) {}; // Save current instance configuration virtual void setConfig(JsonObject& root) {}; // Load the configuration manifest static void manifest(JsonArray& root) {}; // Descriptive name of the slot # index String slot(unsigned char index) { return description(); } // Sensor ID unsigned char getID() { return _sensor_id; }; // Specific for I2C sensors unsigned char lock_i2c(unsigned char address, size_t size, unsigned char * addresses) { // Check if we should release a previously locked address if (_previous_address != address) { i2cReleaseLock(_previous_address); } // If we have already an address, check it is not locked if (address && !i2cGetLock(address)) { _error = SENSOR_ERROR_I2C; // If we don't have an address... } else { // Trigger auto-discover address = i2cFindAndLock(size, addresses); // If still nothing exit with error if (address == 0) _error = SENSOR_ERROR_I2C; } _previous_address = address; return address; } // Return sensor status (true for ready) bool status() { return _error == 0; } // Return sensor last internal error int error() { return _error; } // Number of available slots unsigned char count() { return _count; } protected: // Check if valid GPIO bool _validGPIO(unsigned char gpio) { if (0 <= gpio && gpio <= 5) return true; if (12 <= gpio && gpio <= 15) return true; return false; } unsigned char _sensor_id = 0x00; int _error = 0; bool _dirty = true; unsigned char _count = 0; // I2C unsigned char _previous_address = 0; unsigned char _address = 0; };