diff --git a/code/build.sh b/code/build.sh index deb5f930..e0c09644 100755 --- a/code/build.sh +++ b/code/build.sh @@ -19,14 +19,25 @@ stat_bytes() { # Script settings destination=../firmware -version=$(grep APP_VERSION espurna/config/version.h | awk '{print $3}' | sed 's/"//g') +version_file=espurna/config/version.h +version=$(grep -E '^#define APP_VERSION' $version_file | awk '{print $3}' | sed 's/"//g') -if is_git; then +if ${TRAVIS:-false}; then + git_revision=${TRAVIS_COMMIT::7} + git_tag=${TRAVIS_TAG} +elif is_git; then git_revision=$(git rev-parse --short HEAD) - git_version=${version}-${git_revision} + git_tag=$(git tag --contains HEAD) else - git_revision= - git_version=$version + git_revision=unknown + git_tag= +fi + +if [[ -n $git_tag ]]; then + new_version=${version/-*} + sed -i -e "s@$version@$new_version@" $version_file + version=$new_version + trap "git checkout -- $version_file" EXIT fi par_build=false @@ -139,7 +150,7 @@ shift $((OPTIND-1)) # Welcome echo "--------------------------------------------------------------" echo "ESPURNA FIRMWARE BUILDER" -echo "Building for version ${git_version}" +echo "Building for version ${version}" ${git_revision:+($git_revision)} # Environments to build environments=$@ diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index a790d825..735894ce 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -185,23 +185,74 @@ #define UPTIME_OVERFLOW 4294967295 // Uptime overflow value -// Topics that will be reported in heartbeat +// Values that will be reported in heartbeat +#ifndef HEARTBEAT_REPORT_STATUS #define HEARTBEAT_REPORT_STATUS 1 +#endif + +#ifndef HEARTBEAT_REPORT_SSID #define HEARTBEAT_REPORT_SSID 1 +#endif + +#ifndef HEARTBEAT_REPORT_IP #define HEARTBEAT_REPORT_IP 1 +#endif + +#ifndef HEARTBEAT_REPORT_MAC #define HEARTBEAT_REPORT_MAC 1 +#endif + +#ifndef HEARTBEAT_REPORT_RSSI #define HEARTBEAT_REPORT_RSSI 1 +#endif + +#ifndef HEARTBEAT_REPORT_UPTIME #define HEARTBEAT_REPORT_UPTIME 1 +#endif + +#ifndef HEARTBEAT_REPORT_DATETIME #define HEARTBEAT_REPORT_DATETIME 1 +#endif + +#ifndef HEARTBEAT_REPORT_FREEHEAP #define HEARTBEAT_REPORT_FREEHEAP 1 +#endif + +#ifndef HEARTBEAT_REPORT_VCC #define HEARTBEAT_REPORT_VCC 1 +#endif + +#ifndef HEARTBEAT_REPORT_RELAY #define HEARTBEAT_REPORT_RELAY 1 +#endif + +#ifndef HEARTBEAT_REPORT_LIGHT #define HEARTBEAT_REPORT_LIGHT 1 +#endif + +#ifndef HEARTBEAT_REPORT_HOSTNAME #define HEARTBEAT_REPORT_HOSTNAME 1 +#endif + +#ifndef HEARTBEAT_REPORT_APP #define HEARTBEAT_REPORT_APP 1 +#endif + +#ifndef HEARTBEAT_REPORT_VERSION #define HEARTBEAT_REPORT_VERSION 1 +#endif + +#ifndef HEARTBEAT_REPORT_BOARD #define HEARTBEAT_REPORT_BOARD 1 +#endif + +#ifndef HEARTBEAT_REPORT_LOADAVG +#define HEARTBEAT_REPORT_LOADAVG 1 +#endif + +#ifndef HEARTBEAT_REPORT_INTERVAL #define HEARTBEAT_REPORT_INTERVAL 0 +#endif //------------------------------------------------------------------------------ // Load average @@ -211,10 +262,6 @@ #define LOADAVG_INTERVAL 30000 // Interval between calculating load average (in ms) #endif -#ifndef LOADAVG_REPORT -#define LOADAVG_REPORT 1 // Should we report Load average over MQTT? -#endif - //------------------------------------------------------------------------------ // BUTTON //------------------------------------------------------------------------------ @@ -537,6 +584,10 @@ #define OTA_PORT 8266 // OTA port #endif +#ifndef OTA_MQTT_SUPPORT +#define OTA_MQTT_SUPPORT 0 // No support by default +#endif + #define OTA_GITHUB_FP "D7:9F:07:61:10:B3:92:93:E3:49:AC:89:84:5B:03:80:C1:9E:2F:8B" // ----------------------------------------------------------------------------- @@ -763,6 +814,7 @@ #define MQTT_TOPIC_SPEED "speed" #define MQTT_TOPIC_IRIN "irin" #define MQTT_TOPIC_IROUT "irout" +#define MQTT_TOPIC_OTA "ota" // Light module #define MQTT_TOPIC_CHANNEL "channel" diff --git a/code/espurna/config/version.h b/code/espurna/config/version.h index 7f3c064f..f9697a4d 100644 --- a/code/espurna/config/version.h +++ b/code/espurna/config/version.h @@ -1,5 +1,5 @@ #define APP_NAME "ESPURNA" -#define APP_VERSION "1.13.4" +#define APP_VERSION "1.13.4-dev" #define APP_AUTHOR "xose.perez@gmail.com" #define APP_WEBSITE "http://tinkerman.cat" #define CFG_VERSION 3 diff --git a/code/espurna/ota.ino b/code/espurna/ota.ino index c1370d53..4dc015a9 100644 --- a/code/espurna/ota.ino +++ b/code/espurna/ota.ino @@ -158,6 +158,10 @@ void _otaFrom(const char * host, unsigned int port, const char * url) { } void _otaFrom(String url) { + if (!url.startsWith("http://") && !url.startsWith("https://")) { + DEBUG_MSG_P(PSTR("[OTA] Incorrect URL specified\n")); + return; + } // Port from protocol unsigned int port = 80; @@ -197,6 +201,25 @@ void _otaInitCommands() { #endif // TERMINAL_SUPPORT +#if OTA_MQTT_SUPPORT + +void _otaMQTTCallback(unsigned int type, const char * topic, const char * payload) { + if (type == MQTT_CONNECT_EVENT) { + mqttSubscribe(MQTT_TOPIC_OTA); + } + + if (type == MQTT_MESSAGE_EVENT) { + // Match topic + String t = mqttMagnitude((char *) topic); + if (t.equals(MQTT_TOPIC_OTA)) { + DEBUG_MSG_P(PSTR("[OTA] Initiating from URL: %s\n"), payload); + _otaFrom(payload); + } + } +} + +#endif // OTA_MQTT_SUPPORT + // ----------------------------------------------------------------------------- void otaSetup() { @@ -207,6 +230,10 @@ void otaSetup() { _otaInitCommands(); #endif + #if OTA_MQTT_SUPPORT + mqttRegister(_otaMQTTCallback); + #endif + // Main callbacks espurnaRegisterLoop(_otaLoop); espurnaRegisterReload(_otaConfigure); diff --git a/code/espurna/rf.ino b/code/espurna/rf.ino index dfa97c2b..65e50dc9 100644 --- a/code/espurna/rf.ino +++ b/code/espurna/rf.ino @@ -164,7 +164,7 @@ void _rfWebSocketOnSend(JsonObject& root) { char buffer[20]; root["rfbVisible"] = 1; root["rfbCount"] = relayCount(); - _rf_sendcodes.once_ms(1000, _rfWebSocketSendCodes); + _rfb_sendcodes.once_ms(1000, _rfWebSocketSendCodes); } void _rfWebSocketOnAction(uint32_t client_id, const char * action, JsonObject& data) { diff --git a/code/espurna/rfbridge.ino b/code/espurna/rfbridge.ino index c9bdb9b8..f85babbd 100644 --- a/code/espurna/rfbridge.ino +++ b/code/espurna/rfbridge.ino @@ -102,7 +102,7 @@ static bool _rfbToChar(byte * in, char * out, int n = RF_MESSAGE_SIZE) { #if WEB_SUPPORT void _rfbWebSocketSendCode(unsigned char id, bool status, const char * code) { - char wsb[100]; + char wsb[192]; // (32 * 5): 46 bytes for json , 116 bytes raw code, reserve snprintf_P(wsb, sizeof(wsb), PSTR("{\"rfb\":[{\"id\": %d, \"status\": %d, \"data\": \"%s\"}]}"), id, status ? 1 : 0, code); wsSend(wsb); } diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index 5d085534..620588d9 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -137,6 +137,59 @@ unsigned long getUptime() { #if HEARTBEAT_MODE != HEARTBEAT_NONE +// ----------------------------------------------------------------------------- +// Heartbeat helper +// ----------------------------------------------------------------------------- +namespace Heartbeat { + enum Report : uint32_t { + Status = 1 << 1, + Ssid = 1 << 2, + Ip = 1 << 3, + Mac = 1 << 4, + Rssi = 1 << 5, + Uptime = 1 << 6, + Datetime = 1 << 7, + Freeheap = 1 << 8, + Vcc = 1 << 9, + Relay = 1 << 10, + Light = 1 << 11, + Hostname = 1 << 12, + App = 1 << 13, + Version = 1 << 14, + Board = 1 << 15, + Loadavg = 1 << 16, + Interval = 1 << 17 + }; + + constexpr uint32_t defaultValue() { + return (Status * (HEARTBEAT_REPORT_STATUS)) | \ + (Ssid * (HEARTBEAT_REPORT_SSID)) | \ + (Ip * (HEARTBEAT_REPORT_IP)) | \ + (Mac * (HEARTBEAT_REPORT_MAC)) | \ + (Rssi * (HEARTBEAT_REPORT_RSSI)) | \ + (Uptime * (HEARTBEAT_REPORT_UPTIME)) | \ + (Datetime * (HEARTBEAT_REPORT_DATETIME)) | \ + (Freeheap * (HEARTBEAT_REPORT_FREEHEAP)) | \ + (Vcc * (HEARTBEAT_REPORT_VCC)) | \ + (Relay * (HEARTBEAT_REPORT_RELAY)) | \ + (Light * (HEARTBEAT_REPORT_LIGHT)) | \ + (Hostname * (HEARTBEAT_REPORT_HOSTNAME)) | \ + (App * (HEARTBEAT_REPORT_APP)) | \ + (Version * (HEARTBEAT_REPORT_VERSION)) | \ + (Board * (HEARTBEAT_REPORT_BOARD)) | \ + (Loadavg * (HEARTBEAT_REPORT_LOADAVG)) | \ + (Interval * (HEARTBEAT_REPORT_INTERVAL)); + } + + uint32_t currentValue() { + const String cfg = getSetting("hbReport"); + if (!cfg.length()) return defaultValue(); + + return strtoul(cfg.c_str(), NULL, 10); + } + +} + void heartbeat() { unsigned long uptime_seconds = getUptime(); @@ -163,65 +216,70 @@ void heartbeat() { #endif } + const uint32_t hb_cfg = Heartbeat::currentValue(); + if (!hb_cfg) return; + // ------------------------------------------------------------------------- // MQTT // ------------------------------------------------------------------------- #if MQTT_SUPPORT if (!serial) { - #if (HEARTBEAT_REPORT_INTERVAL) - mqttSend(MQTT_TOPIC_INTERVAL, HEARTBEAT_INTERVAL / 1000); - #endif - #if (HEARTBEAT_REPORT_APP) + if (hb_cfg & Heartbeat::Interval) + mqttSend(MQTT_TOPIC_INTERVAL, String(HEARTBEAT_INTERVAL / 1000).c_str()); + + if (hb_cfg & Heartbeat::App) mqttSend(MQTT_TOPIC_APP, APP_NAME); - #endif - #if (HEARTBEAT_REPORT_VERSION) + + if (hb_cfg & Heartbeat::Version) mqttSend(MQTT_TOPIC_VERSION, APP_VERSION); - #endif - #if (HEARTBEAT_REPORT_BOARD) + + if (hb_cfg & Heartbeat::Board) mqttSend(MQTT_TOPIC_BOARD, getBoardName().c_str()); - #endif - #if (HEARTBEAT_REPORT_HOSTNAME) - mqttSend(MQTT_TOPIC_HOSTNAME, getSetting("hostname").c_str()); - #endif - #if (HEARTBEAT_REPORT_SSID) + + if (hb_cfg & Heartbeat::Hostname) + mqttSend(MQTT_TOPIC_HOSTNAME, getSetting("hostname", getIdentifier()).c_str()); + + if (hb_cfg & Heartbeat::Ssid) mqttSend(MQTT_TOPIC_SSID, WiFi.SSID().c_str()); - #endif - #if (HEARTBEAT_REPORT_IP) + + if (hb_cfg & Heartbeat::Ip) mqttSend(MQTT_TOPIC_IP, getIP().c_str()); - #endif - #if (HEARTBEAT_REPORT_MAC) + + if (hb_cfg & Heartbeat::Mac) mqttSend(MQTT_TOPIC_MAC, WiFi.macAddress().c_str()); - #endif - #if (HEARTBEAT_REPORT_RSSI) + + if (hb_cfg & Heartbeat::Rssi) mqttSend(MQTT_TOPIC_RSSI, String(WiFi.RSSI()).c_str()); - #endif - #if (HEARTBEAT_REPORT_UPTIME) + + if (hb_cfg & Heartbeat::Uptime) mqttSend(MQTT_TOPIC_UPTIME, String(uptime_seconds).c_str()); + + #if NTP_SUPPORT + if ((hb_cfg & Heartbeat::Datetime) && (ntpSynced())) + mqttSend(MQTT_TOPIC_DATETIME, ntpDateTime().c_str()); #endif - #if (HEARTBEAT_REPORT_DATETIME) && (NTP_SUPPORT) - if (ntpSynced()) mqttSend(MQTT_TOPIC_DATETIME, ntpDateTime().c_str()); - #endif - #if (HEARTBEAT_REPORT_FREEHEAP) + + if (hb_cfg & Heartbeat::Freeheap) mqttSend(MQTT_TOPIC_FREEHEAP, String(free_heap).c_str()); - #endif - #if (HEARTBEAT_REPORT_RELAY) + + if (hb_cfg & Heartbeat::Relay) relayMQTT(); + + #if (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE) + if (hb_cfg & Heartbeat::Light) + lightMQTT(); #endif - #if (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE) & (HEARTBEAT_REPORT_LIGHT) - lightMQTT(); - #endif - #if (HEARTBEAT_REPORT_VCC) - #if ADC_MODE_VALUE == ADC_VCC + + if ((hb_cfg & Heartbeat::Vcc) && (ADC_MODE_VALUE == ADC_VCC)) mqttSend(MQTT_TOPIC_VCC, String(ESP.getVcc()).c_str()); - #endif - #endif - #if (HEARTBEAT_REPORT_STATUS) + + if (hb_cfg & Heartbeat::Status) mqttSend(MQTT_TOPIC_STATUS, MQTT_STATUS_ONLINE, true); - #endif - #if (LOADAVG_REPORT) + + if (hb_cfg & Heartbeat::Loadavg) mqttSend(MQTT_TOPIC_LOADAVG, String(systemLoadAverage()).c_str()); - #endif + } #endif @@ -230,15 +288,14 @@ void heartbeat() { // ------------------------------------------------------------------------- #if INFLUXDB_SUPPORT - #if (HEARTBEAT_REPORT_UPTIME) + if (hb_cfg & Heartbeat::Uptime) idbSend(MQTT_TOPIC_UPTIME, String(uptime_seconds).c_str()); - #endif - #if (HEARTBEAT_REPORT_FREEHEAP) + + if (hb_cfg & Heartbeat::Freeheap) idbSend(MQTT_TOPIC_FREEHEAP, String(free_heap).c_str()); - #endif - #if (HEARTBEAT_REPORT_RSSI) + + if (hb_cfg & Heartbeat::Rssi) idbSend(MQTT_TOPIC_RSSI, String(WiFi.RSSI()).c_str()); - #endif #endif }