|
|
- /*
-
- BUILD INFO
-
- */
-
- #include "espurna.h"
- #include "utils.h"
-
- #include <cstring>
-
- //--------------------------------------------------------------------------------
-
- namespace espurna {
- namespace build {
- namespace {
-
- namespace sdk {
-
- espurna::StringView base() {
- // aka `const char SDK_VERSION[]`
- return system_get_sdk_version();
- }
-
- espurna::StringView core_version() {
- static const String out = ([]() {
- String out;
- #ifdef ARDUINO_ESP8266_RELEASE
- out = ESP.getCoreVersion();
- if (out.equals("00000000")) {
- out = String(ARDUINO_ESP8266_RELEASE);
- }
- out.replace('_', '.');
- #else
- #define _GET_COREVERSION_STR(X) #X
- #define GET_COREVERSION_STR(X) _GET_COREVERSION_STR(X)
- out = GET_COREVERSION_STR(ARDUINO_ESP8266_GIT_DESC);
- #undef _GET_COREVERSION_STR
- #undef GET_COREVERSION_STR
- #endif
- return out;
- })();
-
- return out;
- }
-
- espurna::StringView core_revision() {
- static const String out = ([]() {
- #ifdef ARDUINO_ESP8266_GIT_VER
- return String(ARDUINO_ESP8266_GIT_VER, 16);
- #else
- return PSTR("(unspecified)");
- #endif
- })();
-
- return out;
- }
-
- Sdk get() {
- return Sdk{
- .base = base(),
- .version = core_version(),
- .revision = core_revision(),
- };
- }
-
- } // namespace sdk
-
- namespace hardware {
- namespace internal {
-
- PROGMEM_STRING(Manufacturer, MANUFACTURER);
- PROGMEM_STRING(Device, DEVICE);
-
- } // namespace internal
-
- constexpr StringView manufacturer() {
- return internal::Manufacturer;
- }
-
- constexpr StringView device() {
- return internal::Device;
- }
-
- constexpr Hardware get() {
- return Hardware{
- .manufacturer = manufacturer(),
- .device = device(),
- };
- }
-
- } // namespace device
-
- namespace app {
- namespace internal {
-
- alignas(4) static constexpr char Modules[] PROGMEM_STRING_ATTR =
- #if ALEXA_SUPPORT
- "ALEXA "
- #endif
- #if API_SUPPORT
- "API "
- #endif
- #if BUTTON_SUPPORT
- "BUTTON "
- #endif
- #if DEBUG_SERIAL_SUPPORT
- "DEBUG_SERIAL "
- #endif
- #if DEBUG_TELNET_SUPPORT
- "DEBUG_TELNET "
- #endif
- #if DEBUG_UDP_SUPPORT
- "DEBUG_UDP "
- #endif
- #if DEBUG_WEB_SUPPORT
- "DEBUG_WEB "
- #endif
- #if DOMOTICZ_SUPPORT
- "DOMOTICZ "
- #endif
- #if ENCODER_SUPPORT
- "ENCODER "
- #endif
- #if FAN_SUPPORT
- "FAN "
- #endif
- #if HOMEASSISTANT_SUPPORT
- "HOMEASSISTANT "
- #endif
- #if I2C_SUPPORT
- "I2C "
- #endif
- #if INFLUXDB_SUPPORT
- "INFLUXDB "
- #endif
- #if IR_SUPPORT
- "IR "
- #endif
- #if LED_SUPPORT
- "LED "
- #endif
- #if LLMNR_SUPPORT
- "LLMNR "
- #endif
- #if MDNS_SERVER_SUPPORT
- "MDNS "
- #endif
- #if MQTT_SUPPORT
- "MQTT "
- #endif
- #if NETBIOS_SUPPORT
- "NETBIOS "
- #endif
- #if NOFUSS_SUPPORT
- "NOFUSS "
- #endif
- #if NTP_SUPPORT
- "NTP "
- #endif
- #if OTA_ARDUINOOTA_SUPPORT
- "ARDUINO_OTA "
- #endif
- #if OTA_WEB_SUPPORT
- "OTA_WEB "
- #endif
- #if (OTA_CLIENT != OTA_CLIENT_NONE)
- "OTA_CLIENT "
- #endif
- #if PROMETHEUS_SUPPORT
- "METRICS "
- #endif
- #if RELAY_SUPPORT
- "RELAY "
- #endif
- #if RFM69_SUPPORT
- "RFM69 "
- #endif
- #if RFB_SUPPORT
- "RFB "
- #endif
- #if RPN_RULES_SUPPORT
- "RPN_RULES "
- #endif
- #if SCHEDULER_SUPPORT
- "SCHEDULER "
- #endif
- #if SENSOR_SUPPORT
- "SENSOR "
- #endif
- #if SPIFFS_SUPPORT
- "SPIFFS "
- #endif
- #if SSDP_SUPPORT
- "SSDP "
- #endif
- #if TELNET_SUPPORT
- "TELNET "
- #endif
- #if TERMINAL_SUPPORT
- "TERMINAL "
- #endif
- #if GARLAND_SUPPORT
- "GARLAND "
- #endif
- #if THERMOSTAT_SUPPORT
- "THERMOSTAT "
- #endif
- #if THERMOSTAT_DISPLAY_SUPPORT
- "THERMOSTAT_DISPLAY "
- #endif
- #if THINGSPEAK_SUPPORT
- "THINGSPEAK "
- #endif
- #if UART_SUPPORT
- #if UART_SUPPORT_SOFTWARE
- "UART+SW "
- #else
- "UART "
- #endif
- #endif
- #if UART_MQTT_SUPPORT
- "UART_MQTT "
- #endif
- #if WEB_SUPPORT
- #if WEBUI_IMAGE == WEBUI_IMAGE_SMALL
- "WEB_SMALL "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_LIGHT
- "WEB_LIGHT "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_SENSOR
- "WEB_SENSOR "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_RFBRIDGE
- "WEB_RFBRIDGE "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_RFM69
- "WEB_RFM69 "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_LIGHTFOX
- "WEB_LIGHTFOX "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_GARLAND
- "WEB_GARLAND "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_THERMOSTAT
- "WEB_THERMOSTAT "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_CURTAIN
- "WEB_CURTAIN "
- #elif WEBUI_IMAGE == WEBUI_IMAGE_FULL
- "WEB_FULL "
- #endif
- #endif
- "";
-
- PROGMEM_STRING(Name, APP_NAME);
- PROGMEM_STRING(Version, APP_VERSION);
- PROGMEM_STRING(Author, APP_AUTHOR);
- PROGMEM_STRING(Website, APP_WEBSITE);
-
- PROGMEM_STRING(BuildDate, __DATE__);
- PROGMEM_STRING(BuildTime, __TIME__);
-
- } // namespace internal
-
- // ref. https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
- //
- // __DATE__
- // > This macro expands to a string constant that describes the date on which the preprocessor is being run.
- // > The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10,
- // > it is padded with a space on the left.
- // >
- // > If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".
- //
- // __TIME__
- // > This macro expands to a string constant that describes the time at which the preprocessor is being run.
- // > The string constant contains eight characters and looks like "23:59:01".
- // >
- // > If GCC cannot determine the current time, it will emit a warning message (once per compilation) and __TIME__ will expand to "??:??:??".
- namespace time {
-
- // "Jan 1 1970"
- // ^^^
- constexpr StringView raw_month() {
- return StringView(&internal::BuildDate[0], &internal::BuildDate[3]);
- }
- static_assert(raw_month().length() == 3, "");
-
- // "Jan 1 1970"
- // ^^ (with space, or without)
- constexpr StringView raw_day() {
- return (internal::BuildDate[4] == ' ')
- ? StringView(&internal::BuildDate[5], &internal::BuildDate[6])
- : StringView(&internal::BuildDate[4], &internal::BuildDate[6]);
- }
- static_assert(raw_day().length() < 3, "");
-
- // "Jan 1 1970"
- // ^^^^
- constexpr StringView raw_year() {
- return StringView(&internal::BuildDate[7], &internal::BuildDate[11]);
- }
- static_assert(raw_year().length() == 4, "");
-
- // "03:00:00"
- // ^^
- constexpr StringView raw_hour() {
- return StringView(&internal::BuildTime[0], &internal::BuildTime[2]);
- }
- static_assert(raw_hour().length() == 2, "");
-
- // "03:00:00"
- // ^^
- constexpr StringView raw_minute() {
- return StringView(&internal::BuildTime[3], &internal::BuildTime[5]);
- }
- static_assert(raw_minute().length() == 2, "");
-
- // "03:00:00"
- // ^^
- constexpr StringView raw_second() {
- return StringView(&internal::BuildTime[6], &internal::BuildTime[8]);
- }
- static_assert(raw_second().length() == 2, "");
-
- #define STRING_EQUALS(EXPECTED, ACTUAL)\
- (__builtin_memcmp((ACTUAL).c_str(), (EXPECTED), (ACTUAL).length()) == 0)
-
- constexpr int from_raw_month(StringView month) {
- return STRING_EQUALS("Jan", month) ? 1 :
- STRING_EQUALS("Feb", month) ? 2 :
- STRING_EQUALS("Mar", month) ? 3 :
- STRING_EQUALS("Apr", month) ? 4 :
- STRING_EQUALS("May", month) ? 5 :
- STRING_EQUALS("Jun", month) ? 6 :
- STRING_EQUALS("Jul", month) ? 7 :
- STRING_EQUALS("Aug", month) ? 8 :
- STRING_EQUALS("Sep", month) ? 9 :
- STRING_EQUALS("Oct", month) ? 10 :
- STRING_EQUALS("Nov", month) ? 11 :
- STRING_EQUALS("Dec", month) ? 12 : 0;
- }
- #undef STRING_EQUALS
-
- constexpr int month() {
- return from_raw_month(raw_month());
- }
-
- constexpr int from_one_digit(char value) {
- return ((value >= '0') && (value <= '9'))
- ? (value - '0')
- : 0;
- }
-
- constexpr int from_two_digits(StringView value) {
- return (from_one_digit(value.c_str()[0]) * 10)
- + from_one_digit(value.c_str()[1]);
- }
-
- constexpr int from_raw_day(StringView day) {
- return (day.length() == 2)
- ? from_two_digits(day)
- : from_one_digit(*day.c_str());
- }
-
- constexpr int day() {
- return from_raw_day(raw_day());
- }
-
- constexpr int hour() {
- return from_two_digits(raw_hour());
- }
-
- constexpr int minute() {
- return from_two_digits(raw_minute());
- }
-
- constexpr int second() {
- return from_two_digits(raw_second());
- }
-
- constexpr int from_raw_year(StringView year) {
- return (from_one_digit(year.c_str()[0]) * 1000)
- + (from_one_digit(year.c_str()[1]) * 100)
- + (from_one_digit(year.c_str()[2]) * 10)
- + from_one_digit(year.c_str()[3]);
- }
-
- constexpr int year() {
- return from_raw_year(raw_year());
- }
-
- } // namespace time
-
- constexpr StringView modules() {
- return internal::Modules;
- }
-
- constexpr StringView name() {
- return internal::Name;
- }
-
- constexpr StringView version() {
- return internal::Version;
- }
-
- constexpr StringView author() {
- return internal::Author;
- }
-
- constexpr StringView website() {
- return internal::Website;
- }
-
- StringView build_time() {
- // 1234-56-78 01:02:03
- static char out[20] = {0};
-
- if (out[0] == '\0') {
- // workaround for gcc4.8, explicitly mark as constexpr
- // otherwise, we will read progmem'ed string at runtime
- // (double-check the asm when changing anything here)
- constexpr int year = time::year();
- constexpr int month = time::month();
- constexpr int day = time::day();
- constexpr int hour = time::hour();
- constexpr int minute = time::minute();
- constexpr int second = time::second();
- snprintf_P(out, sizeof(out),
- PSTR("%4d-%02d-%02d %02d:%02d:%02d"),
- year, month, day,
- hour, minute, second);
- }
-
- return StringView(out, sizeof(out) - 1);
- }
-
- App get() {
- return App{
- .name = name(),
- .version = version(),
- .build_time = build_time(),
- .author = author(),
- .website = website(),
- };
- };
-
- } // namespace app
-
- Info info() {
- return Info{
- .sdk = sdk::get(),
- .hardware = hardware::get(),
- .app = app::get(),
- };
- }
-
- } // namespace
- } // namespace build
- } // namespace espurna
-
- espurna::StringView buildTime() {
- return espurna::build::app::build_time();
- }
-
- espurna::build::Sdk buildSdk() {
- return espurna::build::sdk::get();
- }
-
- espurna::build::Hardware buildHardware() {
- return espurna::build::hardware::get();
- }
-
- espurna::build::App buildApp() {
- return espurna::build::app::get();
- }
-
- espurna::build::Info buildInfo() {
- return espurna::build::info();
- }
-
- espurna::StringView buildModules() {
- return espurna::build::app::modules();
- }
|