diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index ea573e28..6d14aeb5 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -71,7 +71,7 @@ //#define DOMOTICZ_SUPPORT 0 //#define HOMEASSISTANT_SUPPORT 0 //#define I2C_SUPPORT 1 -//#define INFLUXDB_SUPPORT 0 +//#define INFLUXDB_SUPPORT 1 //#define IR_SUPPORT 1 //#define LLMNR_SUPPORT 1 // Only with Arduino Core 2.4.0 //#define MDNS_SUPPORT 0 diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index ab17451d..5723b7b5 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -15,6 +15,21 @@ #define ARRAYINIT(type, name, ...) \ type name[] = {__VA_ARGS__}; +//------------------------------------------------------------------------------ +// ESPURNA CORE +//------------------------------------------------------------------------------ + +#ifdef ESPURNA_CORE + #define ALEXA_SUPPORT 0 + #define DOMOTICZ_SUPPORT 0 + #define HOMEASSISTANT_SUPPORT 0 + #define MQTT_SUPPORT 0 + #define NTP_SUPPORT 0 + #define WEB_SUPPORT 0 + #define SENSOR_SUPPORT 0 + #define I2C_SUPPORT 0 +#endif + //------------------------------------------------------------------------------ // TELNET //------------------------------------------------------------------------------ diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index fe177e53..f842d6a7 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -36,6 +36,9 @@ #define HUMIDITY_DRY 2 #define HUMIDITY_WET 3 +#define SENSOR_PUBLISH_ADDRESSES 0 // Publish sensor addresses +#define SENSOR_ADDRESS_TOPIC "address" // Topic to publish sensor addresses + //-------------------------------------------------------------------------------- // Sensor ID // These should remain over time, do not modify them, only add new ones at the end @@ -161,8 +164,8 @@ #define DALLAS_PIN 14 #endif -#define DALLAS_RESOLUTION 9 // Not used atm -#define DALLAS_READ_INTERVAL 2000 // Force sensor read & cache every 2 seconds +#define DALLAS_RESOLUTION 9 // Not used atm +#define DALLAS_READ_INTERVAL 2000 // Force sensor read & cache every 2 seconds //------------------------------------------------------------------------------ // DHTXX temperature/humidity sensor @@ -438,15 +441,17 @@ // Sensor helpers configuration // ============================================================================= +#ifndef SENSOR_SUPPORT #if ANALOG_SUPPORT || BH1750_SUPPORT || BMX280_SUPPORT || DALLAS_SUPPORT \ || DHT_SUPPORT || DIGITAL_SUPPORT || ECH1560_SUPPORT \ || EMON_ADC121_SUPPORT || EMON_ADS1X15_SUPPORT \ || EMON_ANALOG_SUPPORT || EVENTS_SUPPORT || HLW8012_SUPPORT \ || MHZ19_SUPPORT || PMSX003_SUPPORT || SHT3X_I2C_SUPPORT \ || SI7021_SUPPORT || V9261F_SUPPORT - #define SENSOR_SUPPORT 1 - +#else +#define SENSOR_SUPPORT 0 +#endif #endif // ----------------------------------------------------------------------------- diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index b88cdb8f..68708e9b 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -128,8 +128,7 @@ void welcome() { // ------------------------------------------------------------------------- - DEBUG_MSG_P(PSTR("[INIT] MANUFACTURER: %s\n"), MANUFACTURER); - DEBUG_MSG_P(PSTR("[INIT] DEVICE: %s\n"), DEVICE); + DEBUG_MSG_P(PSTR("[INIT] BOARD: %s\n"), getBoardName().c_str()); DEBUG_MSG_P(PSTR("[INIT] SUPPORT:")); #if ALEXA_SUPPORT @@ -289,6 +288,7 @@ void setup() { if (getSetting("hostname").length() == 0) { setSetting("hostname", getIdentifier()); } + setBoardName(); // Cache loop delay value to speed things (recommended max 250ms) _loopDelay = atol(getSetting("loopDelay", LOOP_DELAY_TIME).c_str()); diff --git a/code/espurna/mdns.ino b/code/espurna/mdns.ino index 90fce569..018c2e38 100644 --- a/code/espurna/mdns.ino +++ b/code/espurna/mdns.ino @@ -45,7 +45,7 @@ void mdnsSetup() { // Public ESPurna related txt for OTA discovery MDNS.addServiceTxt("arduino", "tcp", "app_name", APP_NAME); MDNS.addServiceTxt("arduino", "tcp", "app_version", APP_VERSION); - MDNS.addServiceTxt("arduino", "tcp", "target_board", DEVICE_NAME); + MDNS.addServiceTxt("arduino", "tcp", "target_board", getBoardName()); { char buffer[6]; itoa(ESP.getFlashChipRealSize() / 1024, buffer, 10); @@ -56,6 +56,11 @@ void mdnsSetup() { itoa(ESP.getFlashChipSize() / 1024, buffer, 10); MDNS.addServiceTxt("arduino", "tcp", "sdk_size", (const char *) buffer); } + { + char buffer[6]; + itoa(ESP.getFreeSketchSpace(), buffer, 10); + MDNS.addServiceTxt("arduino", "tcp", "free_space", (const char *) buffer); + } _mdns_wifi_onSTA = WiFi.onStationModeGotIP([](WiFiEventStationModeGotIP ipInfo) { _mdnsStart(); diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 54f50f7a..4643874e 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -203,6 +203,19 @@ void _sensorPost() { void _sensorInit() { + /* + + This is temporal, in the future sensors will be initialized based on + soft configuration (data stored in EEPROM config) so you will be able + to define and configure new sensors on the fly + + At the time being, only enabled sensors (those with *_SUPPORT to 1) are being + loaded and initialized here. If you want to add new sensors of the same type + just duplicate the block and change the arguments for the set* methods. + Check the DHT block below for an example + + */ + #if ANALOG_SUPPORT { AnalogSensor * sensor = new AnalogSensor(); @@ -244,6 +257,19 @@ void _sensorInit() { } #endif + /* + // Example on how to add a second DHT sensor + // DHT2_PIN and DHT2_TYPE should be defined in sensors.h file + #if DHT_SUPPORT + { + DHTSensor * sensor = new DHTSensor(); + sensor->setGPIO(DHT2_PIN); + sensor->setType(DHT2_TYPE); + _sensors.push_back(sensor); + } + #endif + */ + #if DIGITAL_SUPPORT { DigitalSensor * sensor = new DigitalSensor(); @@ -634,11 +660,23 @@ void sensorLoop() { dtostrf(filtered, 1-sizeof(buffer), decimals, buffer); #if MQTT_SUPPORT + if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) { mqttSend(_magnitudeTopic(magnitude.type).c_str(), magnitude.global, buffer); } else { mqttSend(_magnitudeTopic(magnitude.type).c_str(), buffer); } + + #if SENSOR_PUBLISH_ADDRESSES + char topic[32]; + snprintf(topic, sizeof(topic), "%s/%s", SENSOR_ADDRESS_TOPIC, _magnitudeTopic(magnitude.type).c_str()); + if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) { + mqttSend(topic, magnitude.global, magnitude.sensor->address(magnitude.local).c_str()); + } else { + mqttSend(topic, magnitude.sensor->address(magnitude.local).c_str()); + } + #endif // SENSOR_PUBLISH_ADDRESSES + #endif // MQTT_SUPPORT #if INFLUXDB_SUPPORT diff --git a/code/espurna/sensors/AnalogSensor.h b/code/espurna/sensors/AnalogSensor.h index abf23460..0742e2bb 100644 --- a/code/espurna/sensors/AnalogSensor.h +++ b/code/espurna/sensors/AnalogSensor.h @@ -37,6 +37,16 @@ class AnalogSensor : public BaseSensor { return String("ANALOG @ GPIO0"); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String("0"); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/BMX280Sensor.h b/code/espurna/sensors/BMX280Sensor.h index af585629..d34bcb8e 100644 --- a/code/espurna/sensors/BMX280Sensor.h +++ b/code/espurna/sensors/BMX280Sensor.h @@ -150,7 +150,7 @@ class BMX280Sensor : public I2CSensor { void getConfig(JsonObject& root) { root["sensor_id"] = _sensor_id; - root["address"] = getAddress(); + root["address"] = _address; }; void setConfig(JsonObject& root) { diff --git a/code/espurna/sensors/BaseSensor.h b/code/espurna/sensors/BaseSensor.h index 04840d1c..1daf41f3 100644 --- a/code/espurna/sensors/BaseSensor.h +++ b/code/espurna/sensors/BaseSensor.h @@ -46,6 +46,12 @@ class BaseSensor { // Descriptive name of the sensor virtual String description() {} + // Address of the sensor (it could be the GPIO or I2C address) + virtual String address(unsigned char index) {} + + // Descriptive name of the slot # index + virtual String slot(unsigned char index) {}; + // Type for slot # index virtual unsigned char type(unsigned char index) {} @@ -61,9 +67,6 @@ class BaseSensor { // 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; }; diff --git a/code/espurna/sensors/DHTSensor.h b/code/espurna/sensors/DHTSensor.h index 8fa295ba..4fce7e1a 100644 --- a/code/espurna/sensors/DHTSensor.h +++ b/code/espurna/sensors/DHTSensor.h @@ -90,6 +90,16 @@ class DHTSensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String(_gpio); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/DallasSensor.h b/code/espurna/sensors/DallasSensor.h index 985fa0f9..ed934605 100644 --- a/code/espurna/sensors/DallasSensor.h +++ b/code/espurna/sensors/DallasSensor.h @@ -170,6 +170,19 @@ class DallasSensor : public BaseSensor { return String(buffer); } + // Address of the device + String address(unsigned char index) { + char buffer[20] = {0}; + if (index < _count) { + uint8_t * address = _devices[index].address; + snprintf(buffer, sizeof(buffer), "%02X%02X%02X%02X%02X%02X%02X%02X", + address[0], address[1], address[2], address[3], + address[4], address[5], address[6], address[7] + ); + } + return String(buffer); + } + // Descriptive name of the slot # index String slot(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/DigitalSensor.h b/code/espurna/sensors/DigitalSensor.h index 39205cc4..0ec848b9 100644 --- a/code/espurna/sensors/DigitalSensor.h +++ b/code/espurna/sensors/DigitalSensor.h @@ -67,6 +67,16 @@ class DigitalSensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String(_gpio); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/ECH1560Sensor.h b/code/espurna/sensors/ECH1560Sensor.h index c5b40946..de200811 100644 --- a/code/espurna/sensors/ECH1560Sensor.h +++ b/code/espurna/sensors/ECH1560Sensor.h @@ -82,6 +82,18 @@ class ECH1560Sensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + char buffer[6]; + snprintf(buffer, sizeof(buffer), "%i:%i", _clk, _miso); + return String(buffer); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/EmonADS1X15Sensor.h b/code/espurna/sensors/EmonADS1X15Sensor.h index e355b88e..3ad437df 100644 --- a/code/espurna/sensors/EmonADS1X15Sensor.h +++ b/code/espurna/sensors/EmonADS1X15Sensor.h @@ -203,6 +203,14 @@ class EmonADS1X15Sensor : public EmonSensor { return String(buffer); } + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + char buffer[10]; + unsigned char channel = getChannel(index % _ports); + snprintf(buffer, sizeof(buffer), "0x%02X:%i", _address, channel); + return String(buffer); + } + // Type for slot # index unsigned char type(unsigned char index) { if (index < _count) { diff --git a/code/espurna/sensors/EmonAnalogSensor.h b/code/espurna/sensors/EmonAnalogSensor.h index bbabbe26..6461cef2 100644 --- a/code/espurna/sensors/EmonAnalogSensor.h +++ b/code/espurna/sensors/EmonAnalogSensor.h @@ -59,6 +59,11 @@ class EmonAnalogSensor : public EmonSensor { return String("EMON @ ANALOG @ GPIO0"); } + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String("0"); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/EventSensor.h b/code/espurna/sensors/EventSensor.h index e10b4bb8..c83c2091 100644 --- a/code/espurna/sensors/EventSensor.h +++ b/code/espurna/sensors/EventSensor.h @@ -81,6 +81,16 @@ class EventSensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String(_gpio); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/HLW8012Sensor.h b/code/espurna/sensors/HLW8012Sensor.h index e20cc83b..c3cd3fcb 100644 --- a/code/espurna/sensors/HLW8012Sensor.h +++ b/code/espurna/sensors/HLW8012Sensor.h @@ -162,6 +162,18 @@ class HLW8012Sensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + char buffer[10]; + snprintf(buffer, sizeof(buffer), "%i:%i:%i", _sel, _cf, _cf1); + return String(buffer); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/I2CSensor.h b/code/espurna/sensors/I2CSensor.h index 1d6cebc6..5a01971e 100644 --- a/code/espurna/sensors/I2CSensor.h +++ b/code/espurna/sensors/I2CSensor.h @@ -23,6 +23,18 @@ class I2CSensor : public BaseSensor { return _address; } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + char buffer[5]; + snprintf(buffer, sizeof(buffer), "0x%02X", _address); + return String(buffer); + } + protected: // Specific for I2C sensors diff --git a/code/espurna/sensors/MHZ19Sensor.h b/code/espurna/sensors/MHZ19Sensor.h index fc08fb9b..2fcc1b85 100644 --- a/code/espurna/sensors/MHZ19Sensor.h +++ b/code/espurna/sensors/MHZ19Sensor.h @@ -89,6 +89,18 @@ class MHZ19Sensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + char buffer[6]; + snprintf(buffer, sizeof(buffer), "%i:%i", _pin_rx, _pin_tx); + return String(buffer); + } + // Type for slot # index unsigned char type(unsigned char index) { _error = SENSOR_ERROR_OK; diff --git a/code/espurna/sensors/PMSX003Sensor.h b/code/espurna/sensors/PMSX003Sensor.h index e6a3aada..f5662292 100644 --- a/code/espurna/sensors/PMSX003Sensor.h +++ b/code/espurna/sensors/PMSX003Sensor.h @@ -97,6 +97,13 @@ class PMSX003Sensor : public BaseSensor { return String(); } + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + char buffer[6]; + snprintf(buffer, sizeof(buffer), "%i:%i", _pin_rx, _pin_tx); + return String(buffer); + } + // Type for slot # index unsigned char type(unsigned char index) { if (index < _count) { diff --git a/code/espurna/sensors/SI7021Sensor.h b/code/espurna/sensors/SI7021Sensor.h index 04d75775..b69f60a0 100644 --- a/code/espurna/sensors/SI7021Sensor.h +++ b/code/espurna/sensors/SI7021Sensor.h @@ -85,6 +85,11 @@ class SI7021Sensor : public I2CSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + // Type for slot # index unsigned char type(unsigned char index) { if (index < _count) { diff --git a/code/espurna/sensors/V9261FSensor.h b/code/espurna/sensors/V9261FSensor.h index b38a36b5..928dfcdd 100644 --- a/code/espurna/sensors/V9261FSensor.h +++ b/code/espurna/sensors/V9261FSensor.h @@ -77,6 +77,16 @@ class V9261FSensor : public BaseSensor { return String(buffer); } + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return String(_pin_rx); + } + // Loop-like method, call it in your main loop void tick() { _read(); diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index c28f4a34..04fa9fc2 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -15,6 +15,16 @@ String getIdentifier() { return String(buffer); } +void setBoardName() { + #ifndef ESPURNA_CORE + setSetting("boardName", DEVICE_NAME); + #endif +} + +String getBoardName() { + return getSetting("boardName", DEVICE_NAME); +} + String getCoreVersion() { String version = ESP.getCoreVersion(); #ifdef ARDUINO_ESP8266_RELEASE diff --git a/code/extra_scripts.py b/code/extra_scripts.py index 2a0a42f1..c981db86 100644 --- a/code/extra_scripts.py +++ b/code/extra_scripts.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +import time Import("env") # ------------------------------------------------------------------------------ @@ -31,11 +32,12 @@ def clr(color, text): # ------------------------------------------------------------------------------ def check_size(source, target, env): + time.sleep(1) size = target[0].get_size() print clr(Color.LIGHT_BLUE, "Binary size: %s bytes" % size) - if size > 512000: - print clr(Color.LIGHT_RED, "File too large for OTA!") - Exit(1) + #if size > 512000: + # print clr(Color.LIGHT_RED, "File too large for OTA!") + # Exit(1) # ------------------------------------------------------------------------------ # Hooks diff --git a/code/ota.py b/code/ota.py index 8e5a4bc6..e66cc7f5 100644 --- a/code/ota.py +++ b/code/ota.py @@ -38,15 +38,19 @@ def on_service_state_change(zeroconf, service_type, name, state_change): device['app'] = info.properties.get('app_name', '') device['version'] = info.properties.get('app_version', '') device['device'] = info.properties.get('target_board', '') - device['mem_size'] = info.properties.get('mem_size', '') - device['sdk_size'] = info.properties.get('sdk_size', '') + if 'mem_size' in info.properties: + device['mem_size'] = info.properties.get('mem_size') + if 'sdk_size' in info.properties: + device['sdk_size'] = info.properties.get('sdk_size') + if 'free_space' in info.properties: + device['free_space'] = info.properties.get('free_space') devices.append(device) def list(): ''' Shows the list of discovered devices ''' - output_format="{:>3} {:<25}{:<25}{:<15}{:<15}{:<30}{:<10}{:<10}" + output_format="{:>3} {:<25}{:<25}{:<15}{:<15}{:<30}{:<10}{:<10}{:<10}" print(output_format.format( "#", "HOSTNAME", @@ -56,8 +60,9 @@ def list(): "DEVICE", "MEM_SIZE", "SDK_SIZE", + "FREE_SPACE" )) - print "-" * 135 + print "-" * 146 index = 0 for device in devices: @@ -71,6 +76,7 @@ def list(): device.get('device', ''), device.get('mem_size', ''), device.get('sdk_size', ''), + device.get('free_space', ''), )) print @@ -161,6 +167,7 @@ if __name__ == '__main__': # Parse command line options parser = argparse.ArgumentParser(description=description) #parser.add_argument("-v", "--verbose", help="show verbose output", default=0, action='count') + parser.add_argument("-c", "--core", help="flash ESPurna core", default=0, action='count') parser.add_argument("-f", "--flash", help="flash device", default=0, action='count') parser.add_argument("-s", "--sort", help="sort devices list by field", default='hostname') args = parser.parse_args() @@ -194,6 +201,10 @@ if __name__ == '__main__': device = flash() if device: + # Flash core version? + if args.core > 0: + device['flags'] = "-DESPURNA_CORE " + device['flags'] + env = "esp8266-%sm-ota" % device['size'] # Summary