From 21396736c0902fc77242acd07e32017fecaf43bd Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Thu, 6 Mar 2025 16:04:48 -0500 Subject: [PATCH 01/32] feat: attempt to add hub support with backend abstraction. --- Platformio/.gitignore | 1 + .../hardware/ESP32/espnow_hal_esp32.cpp | 122 ++++++++++++++++++ Platformio/hardware/ESP32/espnow_hal_esp32.h | 14 ++ Platformio/hardware/ESP32/include_hal_esp32.h | 1 + .../espnow_hal_windows_linux.cpp | 26 ++++ .../windows_linux/espnow_hal_windows_linux.h | 14 ++ .../windows_linux/include_hal_windows_linux.h | 1 + Platformio/platformio.ini | 8 +- .../applicationInternal/commandHandler.cpp | 77 +++++++++++ .../src/applicationInternal/commandHandler.h | 9 ++ .../hardware/hardwarePresenter.cpp | 21 +++ .../hardware/hardwarePresenter.h | 12 ++ .../applicationInternal/hub/espnowBackend.cpp | 39 ++++++ .../applicationInternal/hub/espnowBackend.h | 20 +++ .../applicationInternal/hub/hubInterface.h | 33 +++++ .../applicationInternal/hub/hubManager.cpp | 109 ++++++++++++++++ .../src/applicationInternal/hub/hubManager.h | 39 ++++++ .../applicationInternal/hub/mqttBackend.cpp | 44 +++++++ .../src/applicationInternal/hub/mqttBackend.h | 25 ++++ .../device_appleTV/device_appleTV.cpp | 28 ++++ .../src/devices/misc/device_hub_helper.h | 24 ++++ Platformio/src/guis/gui_irReceiver.cpp | 6 + Platformio/src/guis/gui_irReceiver.h | 5 +- Platformio/src/main.cpp | 23 ++++ Platformio/src/secrets_override_example.h | 17 +++ 25 files changed, 714 insertions(+), 4 deletions(-) create mode 100644 Platformio/hardware/ESP32/espnow_hal_esp32.cpp create mode 100644 Platformio/hardware/ESP32/espnow_hal_esp32.h create mode 100644 Platformio/hardware/windows_linux/espnow_hal_windows_linux.cpp create mode 100644 Platformio/hardware/windows_linux/espnow_hal_windows_linux.h create mode 100644 Platformio/src/applicationInternal/hub/espnowBackend.cpp create mode 100644 Platformio/src/applicationInternal/hub/espnowBackend.h create mode 100644 Platformio/src/applicationInternal/hub/hubInterface.h create mode 100644 Platformio/src/applicationInternal/hub/hubManager.cpp create mode 100644 Platformio/src/applicationInternal/hub/hubManager.h create mode 100644 Platformio/src/applicationInternal/hub/mqttBackend.cpp create mode 100644 Platformio/src/applicationInternal/hub/mqttBackend.h create mode 100644 Platformio/src/devices/misc/device_hub_helper.h diff --git a/Platformio/.gitignore b/Platformio/.gitignore index 9a696bd73..85f1deeea 100644 --- a/Platformio/.gitignore +++ b/Platformio/.gitignore @@ -5,3 +5,4 @@ .vscode/launch.json .vscode/ipch src/secrets_override.h +**/.DS_Store diff --git a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp new file mode 100644 index 000000000..0e8087919 --- /dev/null +++ b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include "espnow_hal_esp32.h" +#include +#include "secrets.h" + +using json = nlohmann::json; + +// Define the MAC address of the Raspberry Pi hub +// This should be defined in secrets.h as ESPNOW_HUB_MAC +// Example: #define ESPNOW_HUB_MAC {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} +uint8_t hub_mac[6] = ESPNOW_HUB_MAC; +esp_now_peer_info_t hub_peer; + +// Callback for ESP-NOW send status +void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { + if (status == ESP_NOW_SEND_SUCCESS) { + Serial.println("ESP-NOW message sent successfully"); + } else { + Serial.println("ESP-NOW message failed to send"); + } +} + +// Callback for ESP-NOW received data +tAnnounceEspNowMessage_cb thisAnnounceEspNowMessage_cb = NULL; +void OnDataReceived(const uint8_t *mac_addr, const uint8_t *data, int data_len) { + if (thisAnnounceEspNowMessage_cb == NULL) return; + + // Convert MAC to string for logging + char macStr[18]; + snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + + Serial.printf("ESP-NOW message received from %s\n", macStr); + + try { + // Try to parse the received data as MessagePack + auto unpacked_json = json::from_msgpack(data, data + data_len); + + // Forward to callback + thisAnnounceEspNowMessage_cb(unpacked_json); + } catch (const std::exception& e) { + Serial.printf("Error parsing ESP-NOW message: %s\n", e.what()); + } +} + +void set_announceEspNowMessage_cb_HAL(tAnnounceEspNowMessage_cb pAnnounceEspNowMessage_cb) { + thisAnnounceEspNowMessage_cb = pAnnounceEspNowMessage_cb; +} + +void init_espnow_HAL(void) { + // Set WiFi mode to station (required for ESP-NOW) + Serial.println("Starting ESP-NOW"); + WiFi.mode(WIFI_STA); + esp_wifi_set_channel(8, WIFI_SECOND_CHAN_NONE); + + + // Initialize ESP-NOW + if (esp_now_init() != ESP_OK) { + Serial.println("Error initializing ESP-NOW"); + return; + } + + // Register callbacks + esp_now_register_send_cb(OnDataSent); + esp_now_register_recv_cb(OnDataReceived); + + // Register hub as peer + memcpy(hub_peer.peer_addr, hub_mac, 6); + hub_peer.channel = 0; + hub_peer.encrypt = false; + + // Add peer + if (esp_now_add_peer(&hub_peer) != ESP_OK) { + Serial.println("Failed to add hub peer"); + return; + } + + Serial.println("ESP-NOW initialized successfully"); +} + +void espnow_loop_HAL() { + // Nothing to do in the loop for ESP-NOW + // ESP-NOW callbacks are handled by the ESP32 in the background +} + +bool publishEspNowMessage_HAL(json payload) { + // Add remote ID to the payload + payload["remoteId"] = WiFi.macAddress(); + + // Pack the JSON into MessagePack format + std::vector packed_json = json::to_msgpack(payload); + + if (packed_json.size() > 250) { + Serial.printf("Error: Message exceeds ESP-NOW maximum size"); + return false; + } + + // Send the message + esp_err_t result = esp_now_send(hub_peer.peer_addr, packed_json.data(), packed_json.size()); + + if (result == ESP_OK) { + Serial.printf("ESP-NOW sent message with success\n"); + return true; + } + + Serial.printf("ESP-NOW failed to send message\n"); + return false; +} + +void espnow_shutdown_HAL() { + // Unregister peer + esp_now_del_peer(hub_peer.peer_addr); + + // Deinitialize ESP-NOW + esp_now_deinit(); + + Serial.println("ESP-NOW shutdown complete"); +} \ No newline at end of file diff --git a/Platformio/hardware/ESP32/espnow_hal_esp32.h b/Platformio/hardware/ESP32/espnow_hal_esp32.h new file mode 100644 index 000000000..805e3d26a --- /dev/null +++ b/Platformio/hardware/ESP32/espnow_hal_esp32.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +using json = nlohmann::json; + +void init_espnow_HAL(void); +void espnow_loop_HAL(); +bool publishEspNowMessage_HAL(json payload); +void espnow_shutdown_HAL(); + +typedef void (*tAnnounceEspNowMessage_cb)(json payload); +void set_announceEspNowMessage_cb_HAL(tAnnounceEspNowMessage_cb pAnnounceEspNowMessage_cb); \ No newline at end of file diff --git a/Platformio/hardware/ESP32/include_hal_esp32.h b/Platformio/hardware/ESP32/include_hal_esp32.h index 780e3fa12..ec640f0a9 100644 --- a/Platformio/hardware/ESP32/include_hal_esp32.h +++ b/Platformio/hardware/ESP32/include_hal_esp32.h @@ -14,3 +14,4 @@ #include "ESP32/sleep_hal_esp32.h" #include "ESP32/tft_hal_esp32.h" #include "ESP32/user_led_hal_esp32.h" +#include "espnow_hal_esp32.h" diff --git a/Platformio/hardware/windows_linux/espnow_hal_windows_linux.cpp b/Platformio/hardware/windows_linux/espnow_hal_windows_linux.cpp new file mode 100644 index 000000000..d51b6677b --- /dev/null +++ b/Platformio/hardware/windows_linux/espnow_hal_windows_linux.cpp @@ -0,0 +1,26 @@ +#include "espnow_hal_windows_linux.h" + +// Callback function pointer +static EspNowMessageCallback espNowMessageCallback = nullptr; + +void set_announceEspNowMessage_cb_HAL(EspNowMessageCallback callback) { + espNowMessageCallback = callback; + printf("ESP-NOW callback registered (stub implementation)"); +} + +void init_espnow_HAL() { + printf("ESP-NOW initialized (stub implementation)"); +} + +void espnow_loop_HAL() { + // Nothing to do in the stub implementation +} + +bool publishEspNowMessage_HAL(json payload) { + printf("ESP-NOW message published (stub implementation): %s", payload.dump().c_str()); + return true; // Always return success in the stub implementation +} + +void espnow_shutdown_HAL() { + printf("ESP-NOW shutdown (stub implementation)"); +} \ No newline at end of file diff --git a/Platformio/hardware/windows_linux/espnow_hal_windows_linux.h b/Platformio/hardware/windows_linux/espnow_hal_windows_linux.h new file mode 100644 index 000000000..95af948c0 --- /dev/null +++ b/Platformio/hardware/windows_linux/espnow_hal_windows_linux.h @@ -0,0 +1,14 @@ +#pragma once + +#include +using json = nlohmann::json; + +// Callback type definition +typedef void (*EspNowMessageCallback)(json); + +// Function declarations +void set_announceEspNowMessage_cb_HAL(EspNowMessageCallback callback); +void init_espnow_HAL(); +void espnow_loop_HAL(); +bool publishEspNowMessage_HAL(json payload); +void espnow_shutdown_HAL(); \ No newline at end of file diff --git a/Platformio/hardware/windows_linux/include_hal_windows_linux.h b/Platformio/hardware/windows_linux/include_hal_windows_linux.h index 277a5335c..35b316624 100644 --- a/Platformio/hardware/windows_linux/include_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/include_hal_windows_linux.h @@ -14,3 +14,4 @@ #include "windows_linux/sleep_hal_windows_linux.h" #include "windows_linux/tft_hal_windows_linux.h" #include "windows_linux/user_led_hal_windows_linux.h" +#include "espnow_hal_windows_linux.h" diff --git a/Platformio/platformio.ini b/Platformio/platformio.ini index 2e1e36ca3..7e8c40f00 100644 --- a/Platformio/platformio.ini +++ b/Platformio/platformio.ini @@ -20,10 +20,11 @@ lib_deps = lvgl/lvgl@^8.3.11 build_flags = ;-- OMOTE ----------------------------------------------------------------- - -D ENABLE_WIFI_AND_MQTT=1 + -D ENABLE_WIFI_AND_MQTT=0 -D ENABLE_KEYBOARD_MQTT=0 - -D ENABLE_BLUETOOTH=1 - -D ENABLE_KEYBOARD_BLE=1 + -D ENABLE_BLUETOOTH=0 + -D ENABLE_KEYBOARD_BLE=0 + -D ENABLE_ESPNOW=1 -D USE_SCENE_SPECIFIC_GUI_LIST=1 -D SCR_WIDTH=${env.custom_screen_width} -D SCR_HEIGHT=${env.custom_screen_height} @@ -96,6 +97,7 @@ lib_deps = ;https://github.com/h2zero/NimBLE-Arduino#master sparkfun/SparkFun MAX1704x Fuel Gauge Arduino Library@^1.0.4 ;t-vk/ESP32 BLE Keyboard@^0.3.2 + johboh/nlohmann-json@^3.11.3 build_flags = ${env.build_flags} ;-- Arduino log ----------------------------------------------------------- diff --git a/Platformio/src/applicationInternal/commandHandler.cpp b/Platformio/src/applicationInternal/commandHandler.cpp index 2ffc0f0f7..961d5bd6a 100644 --- a/Platformio/src/applicationInternal/commandHandler.cpp +++ b/Platformio/src/applicationInternal/commandHandler.cpp @@ -14,6 +14,7 @@ #include "guis/gui_irReceiver.h" // show received BLE connection messages #include "guis/gui_BLEpairing.h" +#include "hub/hubManager.h" uint16_t COMMAND_UNKNOWN; @@ -239,6 +240,63 @@ void executeCommandWithData(uint16_t command, commandData commandData, std::stri } break; } + + #if (ENABLE_HUB_COMMUNICATION == 1) + case HUB: { + auto current = commandData.commandPayloads.begin(); + + // Extract device and command + std::string device = *current; + current = std::next(current, 1); + + std::string command = *current; + current = std::next(current, 1); + + // Create JSON payload + json payload; + + // Process any additional parameters (key-value pairs) + while (current != commandData.commandPayloads.end()) { + std::string key = *current; + current = std::next(current, 1); + + if (current != commandData.commandPayloads.end()) { + payload[key] = *current; + current = std::next(current, 1); + } + } + + // If additionalPayload is provided, it can be used as a JSON string + // that overrides or extends the payload + if (additionalPayload != "") { + try { + // Try to parse additionalPayload as JSON + json additionalJson = json::parse(additionalPayload); + + // Merge with the existing payload + for (auto& [key, value] : additionalJson.items()) { + payload[key] = value; + } + } catch (json::parse_error& e) { + // If not valid JSON, use it as a parameter value + payload["value"] = additionalPayload; + } + } + + // Add command type if not already present + if (!payload.contains("commandType")) { + // Default to "short" press + payload["commandType"] = "short"; + } + + omote_log_d("execute: will send hub message for device '%s', command '%s'\r\n", + device.c_str(), command.c_str()); + + // Send using the hub manager + HubManager::getInstance().sendMessage(device.c_str(), command.c_str(), payload); + break; + } + #endif } } @@ -287,5 +345,24 @@ void receiveWiFiConnected_cb(bool connected) { void receiveMQTTmessage_cb(std::string topic, std::string payload) { showMQTTmessage(topic, payload); } +#endif +#if (ENABLE_ESPNOW == 1) +void receiveEspNowMessage_cb(json payload) { + // Extract device and command from the payload + std::string device, command, jsonStr; + + if (payload.contains("device") && payload.contains("command")) { + device = payload["device"]; + command = payload["command"]; + + // Serialize the payload to a string + std::string jsonStr = payload.dump(); + + // Show the message in the UI + showEspNowMessage(jsonStr); + + // TODO: Process the command based on device and command + } +} #endif diff --git a/Platformio/src/applicationInternal/commandHandler.h b/Platformio/src/applicationInternal/commandHandler.h index debd67dc1..31a4f3228 100644 --- a/Platformio/src/applicationInternal/commandHandler.h +++ b/Platformio/src/applicationInternal/commandHandler.h @@ -3,6 +3,9 @@ #include #include #include +#include + +using json = nlohmann::json; #include "devices/keyboard/device_keyboard_mqtt/device_keyboard_mqtt.h" #include "devices/keyboard/device_keyboard_ble/device_keyboard_ble.h" @@ -102,6 +105,9 @@ enum commandHandlers { #if (ENABLE_KEYBOARD_BLE == 1) BLE_KEYBOARD, #endif + #if (ENABLE_HUB_COMMUNICATION == 1) + HUB, + #endif }; struct commandData { @@ -128,3 +134,6 @@ void receiveBLEmessage_cb(std::string message); void receiveWiFiConnected_cb(bool connected); void receiveMQTTmessage_cb(std::string topic, std::string payload); #endif +#if (ENABLE_ESPNOW == 1) +void receiveEspNowMessage_cb(json payload); +#endif diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp index cea2499c5..6f0daf19a 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp @@ -269,3 +269,24 @@ void wifiStop() { void get_heapUsage(unsigned long *heapSize, unsigned long *freeHeap, unsigned long *maxAllocHeap, unsigned long *minFreeHeap) { get_heapUsage_HAL(heapSize, freeHeap, maxAllocHeap, minFreeHeap); } + +// --- ESP-NOW ---------------------------------------------------------------- +#if (ENABLE_ESPNOW == 1) +// ESP-NOW hardware presenter functions +void init_espnow() { + set_announceEspNowMessage_cb_HAL(&receiveEspNowMessage_cb); + init_espnow_HAL(); +} + +void espnow_loop() { + espnow_loop_HAL(); +} + +bool publishEspNowMessage(json payload) { + return publishEspNowMessage_HAL(payload); +} + +void espnow_shutdown() { + espnow_shutdown_HAL(); +} +#endif diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h index 09f2ac033..ae16b81ff 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h @@ -3,6 +3,9 @@ #include #include #include "applicationInternal/hardware/arduinoLayer.h" +#include + +using json = nlohmann::json; // --- hardware general ------------------------------------------------------- void init_hardware_general(void); @@ -144,3 +147,12 @@ void wifiStop(); // --- memory usage ----------------------------------------------------------- void get_heapUsage(unsigned long *heapSize, unsigned long *freeHeap, unsigned long *maxAllocHeap, unsigned long *minFreeHeap); + +// --- ESP-NOW ---------------------------------------------------------------- +#if (ENABLE_ESPNOW == 1) +// ESP-NOW hardware presenter functions +void init_espnow(); +void espnow_loop(); +bool publishEspNowMessage(json payload); +void espnow_shutdown(); +#endif diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.cpp b/Platformio/src/applicationInternal/hub/espnowBackend.cpp new file mode 100644 index 000000000..1dd6e275f --- /dev/null +++ b/Platformio/src/applicationInternal/hub/espnowBackend.cpp @@ -0,0 +1,39 @@ +#include "espnowBackend.h" +#include "applicationInternal/hardware/hardwarePresenter.h" +#include "applicationInternal/omote_log.h" + +#if (ENABLE_ESPNOW == 1) +EspNowBackend::EspNowBackend() { +} + +EspNowBackend::~EspNowBackend() { + shutdown(); +} + +bool EspNowBackend::init() { + init_espnow(); + return true; +} + +void EspNowBackend::process() { + espnow_loop(); +} + +bool EspNowBackend::sendMessage(const char* device, const char* command, json payload) { + // Add device and command to payload + payload["device"] = device; + payload["command"] = command; + + omote_log_d("ESP-NOW: Sending message for device %s, command %s\n", device, command); + return publishEspNowMessage(payload); +} + +bool EspNowBackend::isReady() { + // ESP-NOW is always ready once initialized + return true; +} + +void EspNowBackend::shutdown() { + espnow_shutdown(); +} +#endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.h b/Platformio/src/applicationInternal/hub/espnowBackend.h new file mode 100644 index 000000000..7c8eec2ee --- /dev/null +++ b/Platformio/src/applicationInternal/hub/espnowBackend.h @@ -0,0 +1,20 @@ +#pragma once + +#include "hubInterface.h" +#include + +using json = nlohmann::json; + +#if (ENABLE_ESPNOW == 1) +class EspNowBackend : public HubInterface { +public: + EspNowBackend(); + virtual ~EspNowBackend(); + + bool init() override; + void process() override; + bool sendMessage(const char* device, const char* command, json payload) override; + bool isReady() override; + void shutdown() override; +}; +#endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/hubInterface.h b/Platformio/src/applicationInternal/hub/hubInterface.h new file mode 100644 index 000000000..f6aca4065 --- /dev/null +++ b/Platformio/src/applicationInternal/hub/hubInterface.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +using json = nlohmann::json; + +// Define the hub backend types +enum class HubBackend { + ESPNOW, + MQTT +}; + +// Abstract interface for hub communication +class HubInterface { +public: + virtual ~HubInterface() = default; + + // Initialize the hub communication backend + virtual bool init() = 0; + + // Process hub communication tasks (called in loop) + virtual void process() = 0; + + // Send a message to the hub + virtual bool sendMessage(const char* device, const char* command, json payload) = 0; + + // Check if connected/ready + virtual bool isReady() = 0; + + // Shutdown the communication + virtual void shutdown() = 0; +}; \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/hubManager.cpp b/Platformio/src/applicationInternal/hub/hubManager.cpp new file mode 100644 index 000000000..05697ebc1 --- /dev/null +++ b/Platformio/src/applicationInternal/hub/hubManager.cpp @@ -0,0 +1,109 @@ +#include "hubManager.h" +#include "hubInterface.h" +#include "applicationInternal/omote_log.h" +#include +#include "espnowBackend.h" + +#if (ENABLE_WIFI_AND_MQTT == 1) +#include "mqttBackend.h" +#endif + +HubManager& HubManager::getInstance() { + static HubManager instance; + return instance; +} + +HubManager::HubManager() : currentBackend(HubBackend::ESPNOW), activeBackend(nullptr) { + // Initialize with default backend +} + +HubManager::~HubManager() { + if (activeBackend != nullptr) { + activeBackend->shutdown(); + delete activeBackend; + activeBackend = nullptr; + } +} + +bool HubManager::init(HubBackend backend) { + // Clean up any existing backend + if (activeBackend != nullptr) { + activeBackend->shutdown(); + delete activeBackend; + activeBackend = nullptr; + } + + // Store the selected backend type + currentBackend = backend; + + // Initialize the selected backend + switch (backend) { + case HubBackend::ESPNOW: + activeBackend = new EspNowBackend(); + break; + case HubBackend::MQTT: + #if (ENABLE_WIFI_AND_MQTT == 1) + activeBackend = new MqttBackend(); + #else + omote_log_e("MQTT backend is not available in this build\n"); + return false; + #endif + break; + default: + omote_log_e("Invalid hub backend selected\n"); + return false; + } + + // Initialize the backend + if (!activeBackend->init()) { + omote_log_e("Failed to initialize hub backend\n"); + delete activeBackend; + activeBackend = nullptr; + return false; + } + + return true; +} + +void HubManager::process() { + if (activeBackend != nullptr) { + activeBackend->process(); + } +} + +bool HubManager::sendMessage(const char* device, const char* command, json payload) { + if (activeBackend == nullptr) { + omote_log_w("Cannot send message: no hub backend initialized\n"); + return false; + } + + if (!activeBackend->isReady()) { + omote_log_w("Cannot send message: hub backend not ready\n"); + return false; + } + + return activeBackend->sendMessage(device, command, payload); +} + +bool HubManager::isInitialized() const { + return activeBackend != nullptr; +} + +bool HubManager::isReady() const { + if (activeBackend == nullptr) { + return false; + } + return activeBackend->isReady(); +} + +void HubManager::shutdown() { + if (activeBackend != nullptr) { + activeBackend->shutdown(); + delete activeBackend; + activeBackend = nullptr; + } +} + +HubBackend HubManager::getCurrentBackend() const { + return currentBackend; +} \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/hubManager.h b/Platformio/src/applicationInternal/hub/hubManager.h new file mode 100644 index 000000000..97766bc24 --- /dev/null +++ b/Platformio/src/applicationInternal/hub/hubManager.h @@ -0,0 +1,39 @@ +#pragma once + +#include "hubInterface.h" +#include + +using json = nlohmann::json; + +class HubManager { +private: + HubInterface* activeBackend = nullptr; + HubBackend currentBackend; // Store the current backend type + +public: + static HubManager& getInstance(); + + HubManager(); + ~HubManager(); + + // Initialize with the preferred backend + bool init(HubBackend backend); + + // Process communication tasks + void process(); + + // Send a message using the active backend + bool sendMessage(const char* device, const char* command, json payload); + + // Check if communication is ready + bool isReady() const; + + // Shutdown communication + void shutdown(); + + // Check if the hub is initialized + bool isInitialized() const; + + // Get the current backend type + HubBackend getCurrentBackend() const; +}; \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.cpp b/Platformio/src/applicationInternal/hub/mqttBackend.cpp new file mode 100644 index 000000000..10a7f153a --- /dev/null +++ b/Platformio/src/applicationInternal/hub/mqttBackend.cpp @@ -0,0 +1,44 @@ +#include "mqttBackend.h" +#include "applicationInternal/hardware/hardwarePresenter.h" +#include "applicationInternal/omote_log.h" + +#if (ENABLE_WIFI_AND_MQTT == 1) +MqttBackend::MqttBackend() : baseTopic("OMOTE/") { +} + +MqttBackend::~MqttBackend() { + shutdown(); +} + +bool MqttBackend::init() { + init_mqtt(); + return true; +} + +void MqttBackend::process() { + mqtt_loop(); +} + +bool MqttBackend::sendMessage(const char* device, const char* command, json payload) { + // Create MQTT topic from device and command + std::string topic = baseTopic + device + "/" + command; + + // Add device and command to payload for consistency + payload["device"] = device; + payload["command"] = command; + + // Convert payload to string + std::string payloadStr = payload.dump(); + + omote_log_d("MQTT: Sending to topic %s: %s\n", topic.c_str(), payloadStr.c_str()); + return publishMQTTMessage(topic.c_str(), payloadStr.c_str()); +} + +bool MqttBackend::isReady() { + return getIsWifiConnected(); +} + +void MqttBackend::shutdown() { + wifiStop(); +} +#endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.h b/Platformio/src/applicationInternal/hub/mqttBackend.h new file mode 100644 index 000000000..d9c77b730 --- /dev/null +++ b/Platformio/src/applicationInternal/hub/mqttBackend.h @@ -0,0 +1,25 @@ +#pragma once + +#include "hubInterface.h" +#include + +using json = nlohmann::json; + +#if (ENABLE_WIFI_AND_MQTT == 1) +class MqttBackend : public HubInterface { +public: + MqttBackend(); + virtual ~MqttBackend(); + + bool init() override; + void process() override; + bool sendMessage(const char* device, const char* command, json payload) override; + bool isReady() override; + void shutdown() override; + +private: + // MQTT-specific members + bool mqttConnected; + std::string baseTopic; +}; +#endif \ No newline at end of file diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp index e5abf2d6d..802a1fae3 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp @@ -2,9 +2,37 @@ #include "applicationInternal/commandHandler.h" #include "applicationInternal/hardware/hardwarePresenter.h" #include "device_appleTV.h" +#if (ENABLE_HUB_COMMUNICATION == 1) +#include "devices/misc/device_hub_helper.h" +#endif uint16_t APPLETV_GUI_EVENT_USER_DATA; //"AppleTV_gui_event_user_data"; +// Command IDs for Apple TV +uint16_t APPLETV_UP; +uint16_t APPLETV_DOWN; +uint16_t APPLETV_LEFT; +uint16_t APPLETV_RIGHT; +uint16_t APPLETV_SELECT; +// ... other commands + void register_device_appleTV() { register_command(&APPLETV_GUI_EVENT_USER_DATA , makeCommandData(IR, {std::to_string(IR_PROTOCOL_SONY)})); // payload must be set when calling commandHandler + +#if (ENABLE_HUB_COMMUNICATION == 1) + // Register hub commands for Apple TV + register_hub_command(&APPLETV_UP, "AppleTV", "up"); + register_hub_command(&APPLETV_DOWN, "AppleTV", "down"); + register_hub_command(&APPLETV_LEFT, "AppleTV", "left"); + register_hub_command(&APPLETV_RIGHT, "AppleTV", "right"); + register_hub_command(&APPLETV_SELECT, "AppleTV", "select"); + + // Example with additional parameters + register_hub_command_with_params( + &APPLETV_VOLUME_UP, + "AppleTV", + "volume", + {"action", "up", "increment", "5"} + ); +#endif } diff --git a/Platformio/src/devices/misc/device_hub_helper.h b/Platformio/src/devices/misc/device_hub_helper.h new file mode 100644 index 000000000..e2a8917be --- /dev/null +++ b/Platformio/src/devices/misc/device_hub_helper.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include "applicationInternal/commandHandler.h" + +#if (ENABLE_HUB_COMMUNICATION == 1) +// Helper function to register hub commands for devices +void register_hub_command(uint16_t *command, const char *device, const char *cmd) { + std::list commandPayload = {device, cmd}; + register_command(command, makeCommandData(HUB, commandPayload)); +} + +// Helper function to register hub commands with additional parameters +void register_hub_command_with_params(uint16_t *command, const char *device, + const char *cmd, std::list params) { + std::list commandPayload = {device, cmd}; + + // Add all parameters to the command payload + commandPayload.insert(commandPayload.end(), params.begin(), params.end()); + + register_command(command, makeCommandData(HUB, commandPayload)); +} +#endif \ No newline at end of file diff --git a/Platformio/src/guis/gui_irReceiver.cpp b/Platformio/src/guis/gui_irReceiver.cpp index 8e2a5935a..54ddf7cc5 100644 --- a/Platformio/src/guis/gui_irReceiver.cpp +++ b/Platformio/src/guis/gui_irReceiver.cpp @@ -182,3 +182,9 @@ void notify_tab_before_delete_irReceiver(void) { void register_gui_irReceiver(void){ register_gui(std::string(tabName_irReceiver), & create_tab_content_irReceiver, & notify_tab_before_delete_irReceiver); } + +void showEspNowMessage(std::string payload) { + lastTopic = "ESP-NOW"; + lastPayload = payload; + printMQTTmessage(); +} diff --git a/Platformio/src/guis/gui_irReceiver.h b/Platformio/src/guis/gui_irReceiver.h index 13ce12442..62f9575fa 100644 --- a/Platformio/src/guis/gui_irReceiver.h +++ b/Platformio/src/guis/gui_irReceiver.h @@ -8,4 +8,7 @@ void register_gui_irReceiver(void); // used by commandHandler to show WiFi status void showNewIRmessage(std::string); -void showMQTTmessage(std::string topic, std::string payload); \ No newline at end of file +void showMQTTmessage(std::string topic, std::string payload); + +// used by commandHandler to show ESP-NOW messages +void showEspNowMessage(std::string payload); \ No newline at end of file diff --git a/Platformio/src/main.cpp b/Platformio/src/main.cpp index 521f49621..29c5904b9 100644 --- a/Platformio/src/main.cpp +++ b/Platformio/src/main.cpp @@ -48,6 +48,8 @@ #include "scenes/scene_chromecast.h" #include "scenes/scene_appleTV.h" #include "applicationInternal/scenes/sceneHandler.h" +#include "applicationInternal/hub/hubManager.h" +#include "secrets.h" #if defined(ARDUINO) // in case of Arduino we have a setup() and a loop() @@ -162,6 +164,22 @@ int main(int argc, char *argv[]) { init_mqtt(); #endif + // Initialize hub communication with preferred backend from settings + #if (ENABLE_HUB_COMMUNICATION == 1) + HubBackend preferredBackend; + + #if defined(PREFERRED_HUB_BACKEND) + preferredBackend = static_cast(PREFERRED_HUB_BACKEND); + #elif (ENABLE_ESPNOW == 1) + preferredBackend = HUB_ESPNOW; // Default to ESP-NOW when available + #elif (ENABLE_WIFI_AND_MQTT == 1) + preferredBackend = HUB_MQTT; // Fall back to MQTT if ESP-NOW not available + #endif + + // Initialize the hub manager with the preferred backend + HubManager::getInstance().init(preferredBackend); + #endif + omote_log_i("Setup finished in %lu ms.\r\n", millis()); #if defined(WIN32) || defined(__linux__) || defined(__APPLE__) @@ -222,4 +240,9 @@ void loop(unsigned long *pIMUTaskTimer, unsigned long *pUpdateStatusTimer) { updateHardwareStatusAndShowOnGUI(); } + // Process hub communication + #if (ENABLE_HUB_COMMUNICATION == 1) + HubManager::getInstance().process(); + #endif + } diff --git a/Platformio/src/secrets_override_example.h b/Platformio/src/secrets_override_example.h index 857b643c4..18d8e0328 100644 --- a/Platformio/src/secrets_override_example.h +++ b/Platformio/src/secrets_override_example.h @@ -10,3 +10,20 @@ #define WIFI_SSID "YourWifiSSID" // override here #define WIFI_PASSWORD "YourWifiPassword" // override here #define MQTT_SERVER "IPAddressOfYourBroker" // override here + +// Hub Communication Configuration +#define ENABLE_HUB_COMMUNICATION 1 + +// Hub Backend Configuration +// 0 = MQTT, 1 = ESP-NOW +#define PREFERRED_HUB_BACKEND 1 // Default to ESP-NOW + +// MQTT Configuration (if using MQTT backend) +#define MQTT_SERVER "192.168.1.100" +#define MQTT_SERVER_PORT 1883 +#define MQTT_USER "username" +#define MQTT_PASS "password" +#define MQTT_CLIENTNAME "OMOTE" + +// ESP-NOW Configuration (if using ESP-NOW backend) +#define ESPNOW_HUB_MAC {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} From 99b20427dbdce9aeeda0f5e98f5ad659dec987b6 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Fri, 7 Mar 2025 15:29:15 -0500 Subject: [PATCH 02/32] feat: adds commandType which indicates key press action like short of long. --- Platformio/.vscode/settings.json | 18 ++- .../hardware/ESP32/espnow_hal_esp32.cpp | 14 +- .../hardware/ESP32/keyboard_ble_hal_esp32.cpp | 2 +- .../hardware/ESP32/keyboard_ble_hal_esp32.h | 2 +- Platformio/hardware/ESP32/mqtt_hal_esp32.cpp | 2 +- Platformio/hardware/ESP32/mqtt_hal_esp32.h | 2 +- Platformio/hardware/ESP32/sleep_hal_esp32.cpp | 4 +- .../keyboard_ble_hal_windows_linux.cpp | 2 +- .../keyboard_ble_hal_windows_linux.h | 2 +- .../windows_linux/mqtt_hal_windows_linux.cpp | 2 +- .../windows_linux/mqtt_hal_windows_linux.h | 2 +- Platformio/platformio.ini | 6 +- .../applicationInternal/commandHandler.cpp | 128 ++++++++++-------- .../src/applicationInternal/commandHandler.h | 25 ++++ .../hardware/hardwarePresenter.cpp | 8 +- .../hardware/hardwarePresenter.h | 4 +- .../applicationInternal/hub/espnowBackend.cpp | 10 +- .../applicationInternal/hub/espnowBackend.h | 8 +- .../hub/{hubInterface.h => hubBackendBase.h} | 8 +- .../applicationInternal/hub/hubManager.cpp | 77 +++++------ .../src/applicationInternal/hub/hubManager.h | 20 ++- .../applicationInternal/hub/mqttBackend.cpp | 14 +- .../src/applicationInternal/hub/mqttBackend.h | 8 +- Platformio/src/applicationInternal/keys.cpp | 10 +- .../device_appleTV/device_appleTV.cpp | 8 -- .../device_appleTV/device_appleTV.h | 8 ++ Platformio/src/scenes/scene_appleTV.cpp | 35 ++--- Platformio/src/secrets.h | 3 + Platformio/src/secrets_override_example.h | 18 +-- 29 files changed, 243 insertions(+), 207 deletions(-) rename Platformio/src/applicationInternal/hub/{hubInterface.h => hubBackendBase.h} (72%) diff --git a/Platformio/.vscode/settings.json b/Platformio/.vscode/settings.json index 466b91b5f..7f5f1f80c 100644 --- a/Platformio/.vscode/settings.json +++ b/Platformio/.vscode/settings.json @@ -49,7 +49,23 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "any": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "condition_variable": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "forward_list": "cpp", + "unordered_set": "cpp", + "ratio": "cpp", + "set": "cpp", + "fstream": "cpp", + "iomanip": "cpp", + "iostream": "cpp", + "mutex": "cpp", + "thread": "cpp", + "valarray": "cpp" }, "cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO" } \ No newline at end of file diff --git a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp index 0e8087919..04870ece9 100644 --- a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp @@ -15,18 +15,9 @@ using json = nlohmann::json; uint8_t hub_mac[6] = ESPNOW_HUB_MAC; esp_now_peer_info_t hub_peer; -// Callback for ESP-NOW send status -void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { - if (status == ESP_NOW_SEND_SUCCESS) { - Serial.println("ESP-NOW message sent successfully"); - } else { - Serial.println("ESP-NOW message failed to send"); - } -} - // Callback for ESP-NOW received data tAnnounceEspNowMessage_cb thisAnnounceEspNowMessage_cb = NULL; -void OnDataReceived(const uint8_t *mac_addr, const uint8_t *data, int data_len) { +void onDataReceived(const uint8_t *mac_addr, const uint8_t *data, int data_len) { if (thisAnnounceEspNowMessage_cb == NULL) return; // Convert MAC to string for logging @@ -65,8 +56,7 @@ void init_espnow_HAL(void) { } // Register callbacks - esp_now_register_send_cb(OnDataSent); - esp_now_register_recv_cb(OnDataReceived); + esp_now_register_recv_cb(onDataReceived); // Register hub as peer memcpy(hub_peer.peer_addr, hub_mac, 6); diff --git a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp index cfe91b350..5080ebde3 100644 --- a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp @@ -173,7 +173,7 @@ bool keyboardBLE_isConnected_HAL() { return bleKeyboard.isConnected(); } -void keyboardBLE_end_HAL() { +void keyboard_ble_shutdown_HAL() { bleKeyboard.end(); } diff --git a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h index abb0f43a8..86b66481b 100644 --- a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h +++ b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h @@ -21,7 +21,7 @@ void set_announceBLEmessage_cb_HAL(tAnnounceBLEmessage_cb pAnnounceBLEmessage_cb void init_keyboardBLE_HAL(); bool keyboardBLE_isAdvertising_HAL(); bool keyboardBLE_isConnected_HAL(); -void keyboardBLE_end_HAL(); +void keyboard_ble_shutdown_HAL(); void keyboardBLE_write_HAL(uint8_t c); void keyboardBLE_longpress_HAL(uint8_t c); void keyboardBLE_home_HAL(); diff --git a/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp b/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp index a8542c1b6..4ccb46df5 100644 --- a/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp @@ -213,7 +213,7 @@ bool publishMQTTMessage_HAL(const char *topic, const char *payload){ return false; } -void wifiStop_HAL() { +void wifi_shutdown_HAL() { WiFi.disconnect(); WiFi.mode(WIFI_OFF); } diff --git a/Platformio/hardware/ESP32/mqtt_hal_esp32.h b/Platformio/hardware/ESP32/mqtt_hal_esp32.h index 116ae6015..c1dea2707 100644 --- a/Platformio/hardware/ESP32/mqtt_hal_esp32.h +++ b/Platformio/hardware/ESP32/mqtt_hal_esp32.h @@ -6,7 +6,7 @@ void init_mqtt_HAL(void); bool getIsWifiConnected_HAL(); void mqtt_loop_HAL(); bool publishMQTTMessage_HAL(const char *topic, const char *payload); -void wifiStop_HAL(); +void wifi_shutdown_HAL(); typedef void (*tAnnounceWiFiconnected_cb)(bool connected); void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); diff --git a/Platformio/hardware/ESP32/sleep_hal_esp32.cpp b/Platformio/hardware/ESP32/sleep_hal_esp32.cpp index 0da9367ea..b6d1db88c 100644 --- a/Platformio/hardware/ESP32/sleep_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/sleep_hal_esp32.cpp @@ -146,11 +146,11 @@ void enterSleep(){ #if (ENABLE_WIFI_AND_MQTT == 1) // Power down modem - wifiStop_HAL(); + wifi_shutdown_HAL(); #endif #if (ENABLE_KEYBOARD_BLE == 1) - keyboardBLE_end_HAL(); + keyboard_ble_shutdown_HAL(); #endif // Prepare IO states diff --git a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp index b6fc3a1b4..78591350f 100644 --- a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp +++ b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp @@ -29,7 +29,7 @@ void set_announceBLEmessage_cb_HAL(tAnnounceBLEmessage_cb pAnnounceBLEmessage_cb void init_keyboardBLE_HAL() {}; bool keyboardBLE_isAdvertising_HAL() {return false;}; bool keyboardBLE_isConnected_HAL() {return false;}; -void keyboardBLE_end_HAL() {}; +void keyboard_ble_shutdown_HAL() {}; void keyboardBLE_write_HAL(uint8_t c) {}; void keyboardBLE_longpress_HAL(uint8_t c) {}; void keyboardBLE_home_HAL() {}; diff --git a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h index 8a76a985a..3a046fa0c 100644 --- a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h @@ -39,7 +39,7 @@ void set_announceBLEmessage_cb_HAL(tAnnounceBLEmessage_cb pAnnounceBLEmessage_cb void init_keyboardBLE_HAL(); bool keyboardBLE_isAdvertising_HAL(); bool keyboardBLE_isConnected_HAL(); -void keyboardBLE_end_HAL(); +void keyboard_ble_shutdown_HAL(); void keyboardBLE_write_HAL(uint8_t c); void keyboardBLE_longpress_HAL(uint8_t c); void keyboardBLE_home_HAL(); diff --git a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp index 48997ab78..5a003cef3 100644 --- a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp +++ b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp @@ -211,7 +211,7 @@ bool publishMQTTMessage_HAL(const char *topic, const char *payload) { return true; } -void wifiStop_HAL() { +void wifi_shutdown_HAL() { /* disconnect */ if (sockfd != -1) { mqtt_disconnect(&mqttClient); diff --git a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h index 116ae6015..c1dea2707 100644 --- a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h @@ -6,7 +6,7 @@ void init_mqtt_HAL(void); bool getIsWifiConnected_HAL(); void mqtt_loop_HAL(); bool publishMQTTMessage_HAL(const char *topic, const char *payload); -void wifiStop_HAL(); +void wifi_shutdown_HAL(); typedef void (*tAnnounceWiFiconnected_cb)(bool connected); void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); diff --git a/Platformio/platformio.ini b/Platformio/platformio.ini index 7e8c40f00..d29274d87 100644 --- a/Platformio/platformio.ini +++ b/Platformio/platformio.ini @@ -20,11 +20,13 @@ lib_deps = lvgl/lvgl@^8.3.11 build_flags = ;-- OMOTE ----------------------------------------------------------------- - -D ENABLE_WIFI_AND_MQTT=0 + -D ENABLE_WIFI_AND_MQTT=1 -D ENABLE_KEYBOARD_MQTT=0 -D ENABLE_BLUETOOTH=0 -D ENABLE_KEYBOARD_BLE=0 - -D ENABLE_ESPNOW=1 + -D ENABLE_HUB_COMMUNICATION=1 + -D ENABLE_ESPNOW=0 + -D PREFERRED_HUB_BACKEND=1 ; 0 = ESP-NOW, 1 = MQTT -D USE_SCENE_SPECIFIC_GUI_LIST=1 -D SCR_WIDTH=${env.custom_screen_width} -D SCR_HEIGHT=${env.custom_screen_height} diff --git a/Platformio/src/applicationInternal/commandHandler.cpp b/Platformio/src/applicationInternal/commandHandler.cpp index 961d5bd6a..fc80cafe0 100644 --- a/Platformio/src/applicationInternal/commandHandler.cpp +++ b/Platformio/src/applicationInternal/commandHandler.cpp @@ -176,7 +176,7 @@ std::string convertStringListToString(std::list listOfStrings) { return result; } -void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload = "") { +void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload) { switch (commandData.commandHandler) { case IR: { omote_log_v(" generic IR, payloads %s\r\n", convertStringListToString(commandData.commandPayloads).c_str()); @@ -241,69 +241,71 @@ void executeCommandWithData(uint16_t command, commandData commandData, std::stri break; } - #if (ENABLE_HUB_COMMUNICATION == 1) case HUB: { - auto current = commandData.commandPayloads.begin(); - - // Extract device and command - std::string device = *current; - current = std::next(current, 1); - - std::string command = *current; - current = std::next(current, 1); - - // Create JSON payload - json payload; - - // Process any additional parameters (key-value pairs) - while (current != commandData.commandPayloads.end()) { - std::string key = *current; - current = std::next(current, 1); - - if (current != commandData.commandPayloads.end()) { - payload[key] = *current; - current = std::next(current, 1); - } - } - - // If additionalPayload is provided, it can be used as a JSON string - // that overrides or extends the payload - if (additionalPayload != "") { - try { - // Try to parse additionalPayload as JSON - json additionalJson = json::parse(additionalPayload); - - // Merge with the existing payload - for (auto& [key, value] : additionalJson.items()) { - payload[key] = value; - } - } catch (json::parse_error& e) { - // If not valid JSON, use it as a parameter value - payload["value"] = additionalPayload; - } - } - - // Add command type if not already present - if (!payload.contains("commandType")) { - // Default to "short" press - payload["commandType"] = "short"; - } - - omote_log_d("execute: will send hub message for device '%s', command '%s'\r\n", - device.c_str(), command.c_str()); - - // Send using the hub manager - HubManager::getInstance().sendMessage(device.c_str(), command.c_str(), payload); + omote_log_w("HUB commands should be handled using the CommandExecutionParams struct\r\n"); break; } - #endif } } +void executeCommandWithData(const CommandExecutionParams& params, commandData commandData) { + if (commandData.commandHandler != HUB) { + // For non-HUB commands, pass through to the original function + omote_log_d("command: will execute command '%u'%s%s\r\n", + params.commandId, + params.additionalPayload.empty() ? "" : " with additionalPayload '", + params.additionalPayload.empty() ? "" : (params.additionalPayload + "'").c_str()); + + executeCommandWithData(params.commandId, commandData, params.additionalPayload); + return; + } + + auto current = commandData.commandPayloads.begin(); + + // Extract device and command + std::string device = *current; + current = std::next(current, 1); + + std::string hubCommand = *current; + current = std::next(current, 1); + + // Create JSON payload + json payload; + payload["device"] = device; + payload["command"] = hubCommand; + payload["commandType"] = params.commandType; + + // Create a data array if we have any additional data + json dataArray = json::array(); + + // Add all remaining items from commandPayloads to the data array + while (current != commandData.commandPayloads.end()) { + dataArray.push_back(*current); + current = std::next(current, 1); + } + + // If additionalPayload is provided, add it to the data array + if (!params.additionalPayload.empty()) { + dataArray.push_back(params.additionalPayload); + } + + // Only add the data array if it has any content + if (!dataArray.empty()) { + payload["data"] = dataArray; + } + + omote_log_d("execute: will send hub message for device '%s', command '%s'\r\n", + device.c_str(), hubCommand.c_str()); + + // Send using the hub manager + HubManager::getInstance().sendMessage(payload); +} + void executeCommand(uint16_t command, std::string additionalPayload) { try { if (commands.count(command) > 0) { - omote_log_d("command: will execute command '%u' with additionalPayload '%s'\r\n", command, additionalPayload.c_str()); + omote_log_d("command: will execute command '%u' with additionalPayload '%s'\r\n", + command, additionalPayload.c_str()); executeCommandWithData(command, commands.at(command), additionalPayload); } else { omote_log_w("command: command '%u' not found\r\n", command); @@ -314,6 +316,22 @@ void executeCommand(uint16_t command, std::string additionalPayload) { } } +void executeCommand(const CommandExecutionParams& params) { + try { + // Early return if command not found + if (commands.count(params.commandId) == 0) { + omote_log_w("command: command '%u' not found\r\n", params.commandId); + return; + } + + commandData cmdData = commands.at(params.commandId); + executeCommandWithData(params, cmdData); + } + catch (const std::out_of_range& oor) { + omote_log_e("executeCommand: internal error, command not registered\r\n"); + } +} + void receiveNewIRmessage_cb(std::string message) { showNewIRmessage(message); } diff --git a/Platformio/src/applicationInternal/commandHandler.h b/Platformio/src/applicationInternal/commandHandler.h index 31a4f3228..95ccd0ee1 100644 --- a/Platformio/src/applicationInternal/commandHandler.h +++ b/Platformio/src/applicationInternal/commandHandler.h @@ -9,6 +9,7 @@ using json = nlohmann::json; #include "devices/keyboard/device_keyboard_mqtt/device_keyboard_mqtt.h" #include "devices/keyboard/device_keyboard_ble/device_keyboard_ble.h" +#include "applicationInternal/keys.h" extern uint16_t COMMAND_UNKNOWN; @@ -124,6 +125,30 @@ void register_keyboardCommands(); commandData makeCommandData(commandHandlers a, std::list b); void executeCommand(uint16_t command, std::string additionalPayload = ""); +enum CommandExecutionType { + CMD_SHORT, + CMD_LONG +}; + +NLOHMANN_JSON_SERIALIZE_ENUM(CommandExecutionType, { + {CMD_SHORT, "short"}, + {CMD_LONG, "long"} +}) + +struct CommandExecutionParams { + uint16_t commandId; + std::string additionalPayload = ""; + CommandExecutionType commandType = CMD_SHORT; +}; + +// Version that takes a parameter struct +void executeCommand(const CommandExecutionParams& params); + +// Original executeCommandWithData +void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload = ""); +// New overload that takes CommandExecutionParams +void executeCommandWithData(const CommandExecutionParams& params, commandData commandData); + void receiveNewIRmessage_cb(std::string message); #if (ENABLE_KEYBOARD_BLE == 1) // used as callback from hardware diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp index 6f0daf19a..6bb3dd371 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp @@ -204,8 +204,8 @@ bool keyboardBLE_isAdvertising() { bool keyboardBLE_isConnected() { return keyboardBLE_isConnected_HAL(); } -void keyboardBLE_end() { - keyboardBLE_end_HAL(); +void keyboard_ble_shutdown() { + keyboard_ble_shutdown_HAL(); } void keyboardBLE_write(uint8_t c) { keyboardBLE_write_HAL(c); @@ -260,8 +260,8 @@ void mqtt_loop() { bool publishMQTTMessage(const char *topic, const char *payload) { return publishMQTTMessage_HAL(topic, payload); } -void wifiStop() { - wifiStop_HAL(); +void wifi_shutdown() { + wifi_shutdown_HAL(); } #endif diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h index ae16b81ff..3879e8529 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h @@ -118,7 +118,7 @@ void keyboardBLE_deleteBonds(); bool keyboardBLE_forceConnectionToAddress(std::string peerAddress); bool keyboardBLE_isAdvertising(); bool keyboardBLE_isConnected(); -void keyboardBLE_end(); +void keyboard_ble_shutdown(); void keyboardBLE_write(uint8_t c); void keyboardBLE_longpress(uint8_t c); void keyboardBLE_home(); @@ -142,7 +142,7 @@ void init_mqtt(void); bool getIsWifiConnected(); void mqtt_loop(); bool publishMQTTMessage(const char *topic, const char *payload); -void wifiStop(); +void wifi_shutdown(); #endif // --- memory usage ----------------------------------------------------------- diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.cpp b/Platformio/src/applicationInternal/hub/espnowBackend.cpp index 1dd6e275f..baf68d1a1 100644 --- a/Platformio/src/applicationInternal/hub/espnowBackend.cpp +++ b/Platformio/src/applicationInternal/hub/espnowBackend.cpp @@ -19,12 +19,12 @@ void EspNowBackend::process() { espnow_loop(); } -bool EspNowBackend::sendMessage(const char* device, const char* command, json payload) { - // Add device and command to payload - payload["device"] = device; - payload["command"] = command; +bool EspNowBackend::sendMessage(const json& payload) { + // Extract device and command for logging + std::string device = payload["device"]; + std::string command = payload["command"]; - omote_log_d("ESP-NOW: Sending message for device %s, command %s\n", device, command); + omote_log_d("ESP-NOW: Sending message for device %s, command %s\n", device.c_str(), command.c_str()); return publishEspNowMessage(payload); } diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.h b/Platformio/src/applicationInternal/hub/espnowBackend.h index 7c8eec2ee..99f98c60a 100644 --- a/Platformio/src/applicationInternal/hub/espnowBackend.h +++ b/Platformio/src/applicationInternal/hub/espnowBackend.h @@ -1,19 +1,19 @@ #pragma once -#include "hubInterface.h" +#include "hubBackendBase.h" #include using json = nlohmann::json; #if (ENABLE_ESPNOW == 1) -class EspNowBackend : public HubInterface { +class EspNowBackend : public HubBackendBase { public: EspNowBackend(); - virtual ~EspNowBackend(); + ~EspNowBackend() override; bool init() override; void process() override; - bool sendMessage(const char* device, const char* command, json payload) override; + bool sendMessage(const json& payload) override; bool isReady() override; void shutdown() override; }; diff --git a/Platformio/src/applicationInternal/hub/hubInterface.h b/Platformio/src/applicationInternal/hub/hubBackendBase.h similarity index 72% rename from Platformio/src/applicationInternal/hub/hubInterface.h rename to Platformio/src/applicationInternal/hub/hubBackendBase.h index f6aca4065..350a79cc5 100644 --- a/Platformio/src/applicationInternal/hub/hubInterface.h +++ b/Platformio/src/applicationInternal/hub/hubBackendBase.h @@ -11,10 +11,10 @@ enum class HubBackend { MQTT }; -// Abstract interface for hub communication -class HubInterface { +// Abstract interface for hub communication backends +class HubBackendBase { public: - virtual ~HubInterface() = default; + virtual ~HubBackendBase() = default; // Initialize the hub communication backend virtual bool init() = 0; @@ -23,7 +23,7 @@ class HubInterface { virtual void process() = 0; // Send a message to the hub - virtual bool sendMessage(const char* device, const char* command, json payload) = 0; + virtual bool sendMessage(const json& payload) = 0; // Check if connected/ready virtual bool isReady() = 0; diff --git a/Platformio/src/applicationInternal/hub/hubManager.cpp b/Platformio/src/applicationInternal/hub/hubManager.cpp index 05697ebc1..0d6e610c2 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.cpp +++ b/Platformio/src/applicationInternal/hub/hubManager.cpp @@ -1,5 +1,5 @@ #include "hubManager.h" -#include "hubInterface.h" +#include "hubBackendBase.h" #include "applicationInternal/omote_log.h" #include #include "espnowBackend.h" @@ -13,66 +13,61 @@ HubManager& HubManager::getInstance() { return instance; } -HubManager::HubManager() : currentBackend(HubBackend::ESPNOW), activeBackend(nullptr) { - // Initialize with default backend +HubManager::HubManager() : currentBackend(HubBackend::ESPNOW) { + // Initialize with default backend type only } -HubManager::~HubManager() { - if (activeBackend != nullptr) { - activeBackend->shutdown(); - delete activeBackend; - activeBackend = nullptr; - } -} - -bool HubManager::init(HubBackend backend) { - // Clean up any existing backend - if (activeBackend != nullptr) { - activeBackend->shutdown(); - delete activeBackend; - activeBackend = nullptr; - } - - // Store the selected backend type - currentBackend = backend; - - // Initialize the selected backend +std::unique_ptr HubManager::createBackend(HubBackend backend) { switch (backend) { case HubBackend::ESPNOW: - activeBackend = new EspNowBackend(); - break; + #if (ENABLE_ESPNOW == 1) + return std::unique_ptr(new EspNowBackend()); + #else + omote_log_e("ESP-NOW backend is not available in this build\n"); + return nullptr; + #endif case HubBackend::MQTT: #if (ENABLE_WIFI_AND_MQTT == 1) - activeBackend = new MqttBackend(); + return std::unique_ptr(new MqttBackend()); #else omote_log_e("MQTT backend is not available in this build\n"); - return false; + return nullptr; #endif - break; default: omote_log_e("Invalid hub backend selected\n"); - return false; + return nullptr; + } +} + +bool HubManager::init(HubBackend backend) { + // Store the selected backend type + currentBackend = backend; + + // Create the new backend + auto newBackend = createBackend(backend); + if (!newBackend) { + return false; } // Initialize the backend - if (!activeBackend->init()) { + if (!newBackend->init()) { omote_log_e("Failed to initialize hub backend\n"); - delete activeBackend; - activeBackend = nullptr; return false; } + // If everything succeeded, replace the active backend + activeBackend = std::move(newBackend); return true; } void HubManager::process() { - if (activeBackend != nullptr) { + if (activeBackend) { activeBackend->process(); } } -bool HubManager::sendMessage(const char* device, const char* command, json payload) { - if (activeBackend == nullptr) { +bool HubManager::sendMessage(const json& payload) { + if (!activeBackend) { omote_log_w("Cannot send message: no hub backend initialized\n"); return false; } @@ -82,7 +77,7 @@ bool HubManager::sendMessage(const char* device, const char* command, json paylo return false; } - return activeBackend->sendMessage(device, command, payload); + return activeBackend->sendMessage(payload); } bool HubManager::isInitialized() const { @@ -90,17 +85,13 @@ bool HubManager::isInitialized() const { } bool HubManager::isReady() const { - if (activeBackend == nullptr) { - return false; - } - return activeBackend->isReady(); + return activeBackend && activeBackend->isReady(); } void HubManager::shutdown() { - if (activeBackend != nullptr) { + if (activeBackend) { activeBackend->shutdown(); - delete activeBackend; - activeBackend = nullptr; + activeBackend.reset(); } } diff --git a/Platformio/src/applicationInternal/hub/hubManager.h b/Platformio/src/applicationInternal/hub/hubManager.h index 97766bc24..b1b9b9efa 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.h +++ b/Platformio/src/applicationInternal/hub/hubManager.h @@ -1,20 +1,30 @@ #pragma once -#include "hubInterface.h" +#include "hubBackendBase.h" #include +#include using json = nlohmann::json; class HubManager { private: - HubInterface* activeBackend = nullptr; + std::unique_ptr activeBackend; HubBackend currentBackend; // Store the current backend type + // Private constructor for singleton + HubManager(); + + // Factory method for creating backends + static std::unique_ptr createBackend(HubBackend backend); + public: static HubManager& getInstance(); - HubManager(); - ~HubManager(); + // Delete copy constructor and assignment operator + HubManager(const HubManager&) = delete; + HubManager& operator=(const HubManager&) = delete; + + ~HubManager() = default; // Smart pointer handles cleanup // Initialize with the preferred backend bool init(HubBackend backend); @@ -23,7 +33,7 @@ class HubManager { void process(); // Send a message using the active backend - bool sendMessage(const char* device, const char* command, json payload); + bool sendMessage(const json& payload); // Check if communication is ready bool isReady() const; diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.cpp b/Platformio/src/applicationInternal/hub/mqttBackend.cpp index 10a7f153a..55904edbb 100644 --- a/Platformio/src/applicationInternal/hub/mqttBackend.cpp +++ b/Platformio/src/applicationInternal/hub/mqttBackend.cpp @@ -3,7 +3,7 @@ #include "applicationInternal/omote_log.h" #if (ENABLE_WIFI_AND_MQTT == 1) -MqttBackend::MqttBackend() : baseTopic("OMOTE/") { +MqttBackend::MqttBackend() : baseTopic("omote/") { } MqttBackend::~MqttBackend() { @@ -19,14 +19,14 @@ void MqttBackend::process() { mqtt_loop(); } -bool MqttBackend::sendMessage(const char* device, const char* command, json payload) { +bool MqttBackend::sendMessage(const json& payload) { + // Extract device and command from the payload + std::string device = payload["device"]; + std::string command = payload["command"]; + // Create MQTT topic from device and command std::string topic = baseTopic + device + "/" + command; - // Add device and command to payload for consistency - payload["device"] = device; - payload["command"] = command; - // Convert payload to string std::string payloadStr = payload.dump(); @@ -39,6 +39,6 @@ bool MqttBackend::isReady() { } void MqttBackend::shutdown() { - wifiStop(); + wifi_shutdown(); } #endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.h b/Platformio/src/applicationInternal/hub/mqttBackend.h index d9c77b730..3e2972913 100644 --- a/Platformio/src/applicationInternal/hub/mqttBackend.h +++ b/Platformio/src/applicationInternal/hub/mqttBackend.h @@ -1,19 +1,19 @@ #pragma once -#include "hubInterface.h" +#include "hubBackendBase.h" #include using json = nlohmann::json; #if (ENABLE_WIFI_AND_MQTT == 1) -class MqttBackend : public HubInterface { +class MqttBackend : public HubBackendBase { public: MqttBackend(); - virtual ~MqttBackend(); + ~MqttBackend() override; bool init() override; void process() override; - bool sendMessage(const char* device, const char* command, json payload) override; + bool sendMessage(const json& payload) override; bool isReady() override; void shutdown() override; diff --git a/Platformio/src/applicationInternal/keys.cpp b/Platformio/src/applicationInternal/keys.cpp index 73f6fb809..279416dbf 100644 --- a/Platformio/src/applicationInternal/keys.cpp +++ b/Platformio/src/applicationInternal/keys.cpp @@ -48,7 +48,10 @@ void doShortPress(char keyChar, int keyCode){ uint16_t command = get_command_short(gui_memoryOptimizer_getActiveSceneName(), keyChar); if (command != COMMAND_UNKNOWN) { omote_log_d("key: key '%c', will use command '%u'\r\n", keyChar, command); - executeCommand(command); + CommandExecutionParams params; + params.commandId = command; + params.commandType = CMD_SHORT; + executeCommand(params); } else { omote_log_w("key: key '%c', but no command defined\r\n", keyChar); } @@ -59,7 +62,10 @@ void doLongPress(char keyChar, int keyCode){ uint16_t command = get_command_long(gui_memoryOptimizer_getActiveSceneName(), keyChar); if (command != COMMAND_UNKNOWN) { omote_log_d("key: key '%c' (long press), will use command '%u'\r\n", keyChar, command); - executeCommand(command); + CommandExecutionParams params; + params.commandId = command; + params.commandType = CMD_LONG; + executeCommand(params); } else { omote_log_w("key: key '%c' (long press), but no command defined\r\n", keyChar); } diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp index 802a1fae3..da22da484 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp @@ -26,13 +26,5 @@ void register_device_appleTV() { register_hub_command(&APPLETV_LEFT, "AppleTV", "left"); register_hub_command(&APPLETV_RIGHT, "AppleTV", "right"); register_hub_command(&APPLETV_SELECT, "AppleTV", "select"); - - // Example with additional parameters - register_hub_command_with_params( - &APPLETV_VOLUME_UP, - "AppleTV", - "volume", - {"action", "up", "increment", "5"} - ); #endif } diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.h b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.h index 12fab3766..b77e19c1d 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.h +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.h @@ -1,5 +1,13 @@ #pragma once +#include + + extern uint16_t APPLETV_GUI_EVENT_USER_DATA; +extern uint16_t APPLETV_UP; +extern uint16_t APPLETV_DOWN; +extern uint16_t APPLETV_RIGHT; +extern uint16_t APPLETV_LEFT; +extern uint16_t APPLETV_SELECT; void register_device_appleTV(); diff --git a/Platformio/src/scenes/scene_appleTV.cpp b/Platformio/src/scenes/scene_appleTV.cpp index 686ea5e3a..8b1e195ab 100644 --- a/Platformio/src/scenes/scene_appleTV.cpp +++ b/Platformio/src/scenes/scene_appleTV.cpp @@ -7,6 +7,7 @@ #include "devices/TV/device_samsungTV/device_samsungTV.h" #include "devices/AVreceiver/device_yamahaAmp/device_yamahaAmp.h" #include "applicationInternal/commandHandler.h" +#include "devices/mediaPlayer/device_appleTV/device_appleTV.h" // guis #include "devices/mediaPlayer/device_appleTV/gui_appleTV.h" @@ -19,34 +20,20 @@ std::map key_commands_long_appleTV; void scene_setKeys_appleTV() { key_repeatModes_appleTV = { - - - - - - - - - - }; - + key_commands_short_appleTV = { - - - - - - - - - - + {KEY_STOP, COMMAND_UNKNOWN}, {KEY_REWI, COMMAND_UNKNOWN}, + {KEY_PLAY, COMMAND_UNKNOWN}, {KEY_FORW, COMMAND_UNKNOWN}, + {KEY_CONF, COMMAND_UNKNOWN}, {KEY_INFO, COMMAND_UNKNOWN}, + {KEY_UP, APPLETV_UP}, {KEY_LEFT, APPLETV_LEFT}, + {KEY_OK, APPLETV_SELECT}, {KEY_RIGHT, APPLETV_RIGHT}, + {KEY_DOWN, APPLETV_DOWN}, {KEY_BACK, COMMAND_UNKNOWN}, + {KEY_CHUP, COMMAND_UNKNOWN}, {KEY_REC, COMMAND_UNKNOWN}, + {KEY_CHDOW, COMMAND_UNKNOWN}, }; - + key_commands_long_appleTV = { - - }; } diff --git a/Platformio/src/secrets.h b/Platformio/src/secrets.h index 6aeac2879..0d79a5796 100644 --- a/Platformio/src/secrets.h +++ b/Platformio/src/secrets.h @@ -13,6 +13,9 @@ #define MQTT_PASS "" // override it in file "secrets_override.h" #define MQTT_CLIENTNAME "OMOTE" // override it in file "secrets_override.h" +// ESP-NOW Configuration +#define ESPNOW_HUB_MAC {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} // override it in file "secrets_override.h" + // --- include override settings from seperate file --------------------------------------------------------------------------------------------------------------- #if __has_include("secrets_override.h") #include "secrets_override.h" diff --git a/Platformio/src/secrets_override_example.h b/Platformio/src/secrets_override_example.h index 18d8e0328..416d368eb 100644 --- a/Platformio/src/secrets_override_example.h +++ b/Platformio/src/secrets_override_example.h @@ -6,24 +6,12 @@ #undef WIFI_SSID #undef WIFI_PASSWORD #undef MQTT_SERVER +#undef ESPNOW_HUB_MAC #define WIFI_SSID "YourWifiSSID" // override here #define WIFI_PASSWORD "YourWifiPassword" // override here #define MQTT_SERVER "IPAddressOfYourBroker" // override here -// Hub Communication Configuration -#define ENABLE_HUB_COMMUNICATION 1 - -// Hub Backend Configuration -// 0 = MQTT, 1 = ESP-NOW -#define PREFERRED_HUB_BACKEND 1 // Default to ESP-NOW - -// MQTT Configuration (if using MQTT backend) -#define MQTT_SERVER "192.168.1.100" -#define MQTT_SERVER_PORT 1883 -#define MQTT_USER "username" -#define MQTT_PASS "password" -#define MQTT_CLIENTNAME "OMOTE" - -// ESP-NOW Configuration (if using ESP-NOW backend) +// MAC address of the hub (replace with your actual hub's MAC) #define ESPNOW_HUB_MAC {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} + From 00fde234224ee169cdbc44bda769221a47a44e3f Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Fri, 7 Mar 2025 15:50:58 -0500 Subject: [PATCH 03/32] chore: fix espnow serial prints to be more consistent. --- Platformio/hardware/ESP32/espnow_hal_esp32.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp index 04870ece9..90805b0b4 100644 --- a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp @@ -43,12 +43,11 @@ void set_announceEspNowMessage_cb_HAL(tAnnounceEspNowMessage_cb pAnnounceEspNowM } void init_espnow_HAL(void) { - // Set WiFi mode to station (required for ESP-NOW) Serial.println("Starting ESP-NOW"); + // Set WiFi mode to station (required for ESP-NOW) WiFi.mode(WIFI_STA); esp_wifi_set_channel(8, WIFI_SECOND_CHAN_NONE); - // Initialize ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); @@ -85,7 +84,7 @@ bool publishEspNowMessage_HAL(json payload) { std::vector packed_json = json::to_msgpack(payload); if (packed_json.size() > 250) { - Serial.printf("Error: Message exceeds ESP-NOW maximum size"); + Serial.println("Error: Message exceeds ESP-NOW maximum size"); return false; } @@ -93,11 +92,11 @@ bool publishEspNowMessage_HAL(json payload) { esp_err_t result = esp_now_send(hub_peer.peer_addr, packed_json.data(), packed_json.size()); if (result == ESP_OK) { - Serial.printf("ESP-NOW sent message with success\n"); + Serial.println("ESP-NOW sent message with success"); return true; } - Serial.printf("ESP-NOW failed to send message\n"); + Serial.println("ESP-NOW failed to send message"); return false; } From 82289f592eeefe8e0ee0c2ee50074b6bc9bf14da Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Fri, 7 Mar 2025 15:53:07 -0500 Subject: [PATCH 04/32] chore: update include_hal_esp32 import to match. --- Platformio/hardware/ESP32/include_hal_esp32.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Platformio/hardware/ESP32/include_hal_esp32.h b/Platformio/hardware/ESP32/include_hal_esp32.h index ec640f0a9..1d0510fad 100644 --- a/Platformio/hardware/ESP32/include_hal_esp32.h +++ b/Platformio/hardware/ESP32/include_hal_esp32.h @@ -14,4 +14,4 @@ #include "ESP32/sleep_hal_esp32.h" #include "ESP32/tft_hal_esp32.h" #include "ESP32/user_led_hal_esp32.h" -#include "espnow_hal_esp32.h" +#include "ESP32/espnow_hal_esp32.h" From ad9bed52eb040310af3fbd99297be2094d496ad7 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Fri, 7 Mar 2025 15:53:41 -0500 Subject: [PATCH 05/32] chore: update include_hal_windows_linux import to match. --- Platformio/hardware/windows_linux/include_hal_windows_linux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Platformio/hardware/windows_linux/include_hal_windows_linux.h b/Platformio/hardware/windows_linux/include_hal_windows_linux.h index 35b316624..e2c43a868 100644 --- a/Platformio/hardware/windows_linux/include_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/include_hal_windows_linux.h @@ -14,4 +14,4 @@ #include "windows_linux/sleep_hal_windows_linux.h" #include "windows_linux/tft_hal_windows_linux.h" #include "windows_linux/user_led_hal_windows_linux.h" -#include "espnow_hal_windows_linux.h" +#include "windows_linux/espnow_hal_windows_linux.h" From 246a4bc6fd3fe1e687ef0f99c22af302d8585049 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Fri, 7 Mar 2025 16:29:31 -0500 Subject: [PATCH 06/32] chore: wrap espnowBackend include so it isn't included if disabled. --- Platformio/src/applicationInternal/hub/hubManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Platformio/src/applicationInternal/hub/hubManager.cpp b/Platformio/src/applicationInternal/hub/hubManager.cpp index 0d6e610c2..59b1621fa 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.cpp +++ b/Platformio/src/applicationInternal/hub/hubManager.cpp @@ -2,7 +2,10 @@ #include "hubBackendBase.h" #include "applicationInternal/omote_log.h" #include + +#if (ENABLE_ESPNOW == 1) #include "espnowBackend.h" +#endif #if (ENABLE_WIFI_AND_MQTT == 1) #include "mqttBackend.h" From 2be69f1f1d717f348a145d6652784f656dbf8d47 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Fri, 7 Mar 2025 16:41:34 -0500 Subject: [PATCH 07/32] feat: add different key command modes to appleTV scene. --- Platformio/src/scenes/scene_appleTV.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Platformio/src/scenes/scene_appleTV.cpp b/Platformio/src/scenes/scene_appleTV.cpp index 8b1e195ab..f39857d8f 100644 --- a/Platformio/src/scenes/scene_appleTV.cpp +++ b/Platformio/src/scenes/scene_appleTV.cpp @@ -20,6 +20,9 @@ std::map key_commands_long_appleTV; void scene_setKeys_appleTV() { key_repeatModes_appleTV = { + {KEY_UP, SHORT_REPEATED}, {KEY_LEFT, SHORT_REPEATED}, + {KEY_OK, SHORTorLONG}, {KEY_RIGHT, SHORT_REPEATED}, + {KEY_DOWN, SHORT_REPEATED}, }; key_commands_short_appleTV = { @@ -34,6 +37,7 @@ void scene_setKeys_appleTV() { }; key_commands_long_appleTV = { + {KEY_OK, APPLETV_SELECT}, }; } From 5c9cb716604ea98478507b524079fcf2c24144da Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 08:30:13 -0400 Subject: [PATCH 08/32] chore: adds conditional to device_appleTV, so we don't try to register commands twice. --- .../device_appleTV/device_appleTV.cpp | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp index da22da484..faa644bb5 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp @@ -17,14 +17,17 @@ uint16_t APPLETV_SELECT; // ... other commands void register_device_appleTV() { - register_command(&APPLETV_GUI_EVENT_USER_DATA , makeCommandData(IR, {std::to_string(IR_PROTOCOL_SONY)})); // payload must be set when calling commandHandler -#if (ENABLE_HUB_COMMUNICATION == 1) - // Register hub commands for Apple TV - register_hub_command(&APPLETV_UP, "AppleTV", "up"); - register_hub_command(&APPLETV_DOWN, "AppleTV", "down"); - register_hub_command(&APPLETV_LEFT, "AppleTV", "left"); - register_hub_command(&APPLETV_RIGHT, "AppleTV", "right"); - register_hub_command(&APPLETV_SELECT, "AppleTV", "select"); -#endif + #if (ENABLE_HUB_COMMUNICATION == 1) + // Register hub commands for Apple TV when Hub is enabled + register_hub_command(&APPLETV_UP, "AppleTV", "up"); + register_hub_command(&APPLETV_DOWN, "AppleTV", "down"); + register_hub_command(&APPLETV_LEFT, "AppleTV", "left"); + register_hub_command(&APPLETV_RIGHT, "AppleTV", "right"); + register_hub_command(&APPLETV_SELECT, "AppleTV", "select"); + #else + // Register IR commands for Apple TV when Hub is not enabled + register_command(&APPLETV_GUI_EVENT_USER_DATA, makeCommandData(IR, {std::to_string(IR_PROTOCOL_SONY)})); // payload must be set when calling commandHandler + #endif + } From 9a4e96a287d1660fb7bdf33be124668503c0000a Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 08:32:37 -0400 Subject: [PATCH 09/32] chore: restores settings.json. --- Platformio/.vscode/settings.json | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/Platformio/.vscode/settings.json b/Platformio/.vscode/settings.json index 7f5f1f80c..466b91b5f 100644 --- a/Platformio/.vscode/settings.json +++ b/Platformio/.vscode/settings.json @@ -49,23 +49,7 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp", - "any": "cpp", - "chrono": "cpp", - "codecvt": "cpp", - "condition_variable": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "forward_list": "cpp", - "unordered_set": "cpp", - "ratio": "cpp", - "set": "cpp", - "fstream": "cpp", - "iomanip": "cpp", - "iostream": "cpp", - "mutex": "cpp", - "thread": "cpp", - "valarray": "cpp" + "typeinfo": "cpp" }, "cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO" } \ No newline at end of file From baa3f331b341f1f86f6daf39cc52037380f33d9a Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 09:15:00 -0400 Subject: [PATCH 10/32] chore: moves naming consistency changes to another branch. --- .../hardware/ESP32/keyboard_ble_hal_esp32.cpp | 2 +- .../hardware/ESP32/keyboard_ble_hal_esp32.h | 2 +- Platformio/hardware/ESP32/mqtt_hal_esp32.cpp | 209 +++++++++--------- Platformio/hardware/ESP32/mqtt_hal_esp32.h | 18 +- Platformio/hardware/ESP32/sleep_hal_esp32.cpp | 12 +- .../keyboard_ble_hal_windows_linux.cpp | 2 +- .../keyboard_ble_hal_windows_linux.h | 2 +- .../windows_linux/mqtt_hal_windows_linux.cpp | 202 ++++++++--------- .../windows_linux/mqtt_hal_windows_linux.h | 18 +- .../hardware/hardwarePresenter.cpp | 8 +- .../hardware/hardwarePresenter.h | 4 +- .../applicationInternal/hub/mqttBackend.cpp | 2 +- 12 files changed, 239 insertions(+), 242 deletions(-) diff --git a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp index 5080ebde3..cfe91b350 100644 --- a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.cpp @@ -173,7 +173,7 @@ bool keyboardBLE_isConnected_HAL() { return bleKeyboard.isConnected(); } -void keyboard_ble_shutdown_HAL() { +void keyboardBLE_end_HAL() { bleKeyboard.end(); } diff --git a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h index 86b66481b..abb0f43a8 100644 --- a/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h +++ b/Platformio/hardware/ESP32/keyboard_ble_hal_esp32.h @@ -21,7 +21,7 @@ void set_announceBLEmessage_cb_HAL(tAnnounceBLEmessage_cb pAnnounceBLEmessage_cb void init_keyboardBLE_HAL(); bool keyboardBLE_isAdvertising_HAL(); bool keyboardBLE_isConnected_HAL(); -void keyboard_ble_shutdown_HAL(); +void keyboardBLE_end_HAL(); void keyboardBLE_write_HAL(uint8_t c); void keyboardBLE_longpress_HAL(uint8_t c); void keyboardBLE_home_HAL(); diff --git a/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp b/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp index 4ccb46df5..63ae5b489 100644 --- a/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp @@ -1,46 +1,53 @@ -#include -#include "WiFi.h" -#include #include "mqtt_hal_esp32.h" -#if (ENABLE_KEYBOARD_BLE == 1) -#include "keyboard_ble_hal_esp32.h" -#endif +#include "WiFi.h" #include "secrets.h" +#include #if (ENABLE_WIFI_AND_MQTT == 1) WiFiClient espClient; PubSubClient mqttClient(espClient); bool isWifiConnected = false; +std::string id = ""; tAnnounceWiFiconnected_cb thisAnnounceWiFiconnected_cb = NULL; -void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { - thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; +void set_announceWiFiconnected_cb_HAL( + tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { + thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; } tAnnounceSubscribedTopics_cb thisAnnounceSubscribedTopics_cb = NULL; -void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { - thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; +void set_announceSubscribedTopics_cb_HAL( + tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { + thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; } -bool getIsWifiConnected_HAL() { - return isWifiConnected; +bool getIsWifiConnected_HAL() { return isWifiConnected; } + +std::string platform_create_id_string(void) { + uint8_t mac[6]; + char id_string[32]; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + sprintf(id_string, "ESP32_%02x%02X%02X", mac[3], mac[4], mac[5]); + return std::string(id_string); } // WiFi status event -void WiFiEvent(WiFiEvent_t event){ - //Serial.printf("[WiFi-event] event: %d\r\n", event); - if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP){ +void WiFiEvent(WiFiEvent_t event) { + // Serial.printf("[WiFi-event] event: %d\r\n", event); + if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) { // connection to MQTT server will be done in checkMQTTconnection() // mqttClient.setServer(MQTT_SERVER, 1883); // MQTT initialization // mqttClient.connect("OMOTE"); // Connect using a client id - } // Set status bar icon based on WiFi status - if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP || event == ARDUINO_EVENT_WIFI_STA_GOT_IP6) { + if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP || + event == ARDUINO_EVENT_WIFI_STA_GOT_IP6) { isWifiConnected = true; thisAnnounceWiFiconnected_cb(true); - Serial.printf("WiFi connected, IP address: %s\r\n", WiFi.localIP().toString().c_str()); + + Serial.printf("[OMOTE][%8lu]: WiFi connected, IP address: %s\r\n", + (unsigned long)millis(), WiFi.localIP().toString().c_str()); } else if (event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { isWifiConnected = false; @@ -54,80 +61,67 @@ void WiFiEvent(WiFiEvent_t event){ // connected is not enough, will wait for IP isWifiConnected = false; thisAnnounceWiFiconnected_cb(false); - } } void init_mqtt_HAL(void) { + Serial.printf("[OMOTE][%8lu]: Starting wifi\r\n", (unsigned long)millis()); + // Setup WiFi - WiFi.setHostname("OMOTE"); //define hostname + WiFi.setHostname("OMOTE"); // define hostname WiFi.onEvent(WiFiEvent); + + // 10.64.0.208 + IPAddress ip(10, 64, 0, 208); + // 10.64.0.1 + IPAddress gateway(10, 64, 0, 1); + // 255.255.254.0 + IPAddress subnet(255, 255, 254, 0); + + // TODO: This prevents NVR lookup + // WiFi.persistent(false); + // WiFi.mode(WIFI_STA); + + // TODO: Apply static IP settings + WiFi.config(ip, gateway, subnet); + + // uint8_t MAC[6] = {0xE4, 0x38, 0x83, 0x3E, 0xE2, 0x3D}; + + // WiFi.begin(WIFI_SSID, WIFI_PASSWORD, 1, MAC, true); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); WiFi.setSleep(true); + + id = platform_create_id_string(); } std::string subscribeTopicOMOTEtest = "OMOTE/test"; // For connecting to one or several BLE clients -std::string subscribeTopicOMOTE_BLEstartAdvertisingForAll = "OMOTE/BLE/startAdvertisingForAll"; -std::string subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist = "OMOTE/BLE/startAdvertisingWithWhitelist"; -std::string subscribeTopicOMOTE_BLEstartAdvertisingDirected = "OMOTE/BLE/startAdvertisingDirected"; -std::string subscribeTopicOMOTE_BLEstopAdvertising = "OMOTE/BLE/stopAdvertising"; -std::string subscribeTopicOMOTE_BLEprintConnectedClients = "OMOTE/BLE/printConnectedClients"; -std::string subscribeTopicOMOTE_BLEdisconnectAllClients = "OMOTE/BLE/disconnectAllClients"; -std::string subscribeTopicOMOTE_BLEprintBonds = "OMOTE/BLE/printBonds"; -std::string subscribeTopicOMOTE_BLEdeleteBonds = "OMOTE/BLE/deleteBonds"; - -void callback(char* topic, byte* payload, unsigned int length) { +std::string subscribeTopicOMOTE_BLEstartAdvertisingForAll = + "OMOTE/BLE/startAdvertisingForAll"; +std::string subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist = + "OMOTE/BLE/startAdvertisingWithWhitelist"; +std::string subscribeTopicOMOTE_BLEstartAdvertisingDirected = + "OMOTE/BLE/startAdvertisingDirected"; +std::string subscribeTopicOMOTE_BLEstopAdvertising = + "OMOTE/BLE/stopAdvertising"; +std::string subscribeTopicOMOTE_BLEprintConnectedClients = + "OMOTE/BLE/printConnectedClients"; +std::string subscribeTopicOMOTE_BLEdisconnectAllClients = + "OMOTE/BLE/disconnectAllClients"; +std::string subscribeTopicOMOTE_BLEprintBonds = "OMOTE/BLE/printBonds"; +std::string subscribeTopicOMOTE_BLEdeleteBonds = "OMOTE/BLE/deleteBonds"; + +void callback(char *topic, byte *payload, unsigned int length) { // handle message arrived std::string topicReceived(topic); std::string strPayload(reinterpret_cast(payload), length); - Serial.printf("MQTT: received topic %s with payload %s\r\n", topicReceived.c_str(), strPayload.c_str()); + Serial.printf("MQTT: received topic %s with payload %s\r\n", + topicReceived.c_str(), strPayload.c_str()); if (topicReceived == subscribeTopicOMOTEtest) { - // Do whatever you want here, if it is ESP32 hardware related. - // ... - - // Or forward the topic to "void receiveMQTTmessage_cb" in the "commandHandler.cpp", if it is not ESP32 hardware related - thisAnnounceSubscribedTopics_cb(topicReceived, strPayload); - - #if (ENABLE_KEYBOARD_BLE == 1) - } else if (topicReceived == subscribeTopicOMOTE_BLEstartAdvertisingForAll) { - keyboardBLE_startAdvertisingForAll_HAL(); - } else if (topicReceived == subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist) { - keyboardBLE_startAdvertisingWithWhitelist_HAL(strPayload); - } else if (topicReceived == subscribeTopicOMOTE_BLEstartAdvertisingDirected) { - // the payload are two values, separated by comma: peerAddress and isRandomAddress - std::stringstream ss(strPayload); - if (ss.good()) { - std::string peerAddress; - std::getline(ss, peerAddress, ','); - - if (ss.good()) { - std::string isRandomAddressStr; - std::getline(ss, isRandomAddressStr, ','); - bool isRandomAddress = false; - if (isRandomAddressStr == "true") { - isRandomAddress = true; - } - keyboardBLE_startAdvertisingDirected_HAL(peerAddress, isRandomAddress); - } - } - } else if (topicReceived == subscribeTopicOMOTE_BLEstopAdvertising) { - keyboardBLE_stopAdvertising_HAL(); - } else if (topicReceived == subscribeTopicOMOTE_BLEprintConnectedClients) { - keyboardBLE_printConnectedClients_HAL(); - } else if (topicReceived == subscribeTopicOMOTE_BLEdisconnectAllClients) { - keyboardBLE_disconnectAllClients_HAL(); - } else if (topicReceived == subscribeTopicOMOTE_BLEprintBonds) { - keyboardBLE_printBonds_HAL(); - } else if (topicReceived == subscribeTopicOMOTE_BLEdeleteBonds) { - keyboardBLE_deleteBonds_HAL(); - #endif - - } else { - // forward all other topics to the commandHandler - thisAnnounceSubscribedTopics_cb(topicReceived, strPayload); - + Serial.printf("MQTT: received topic %s with payload %s\r\n", + subscribeTopicOMOTEtest.c_str(), strPayload.c_str()); } } @@ -135,16 +129,8 @@ void mqtt_subscribeTopics() { mqttClient.setCallback(&callback); mqttClient.subscribe(subscribeTopicOMOTEtest.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEstartAdvertisingForAll.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEstartAdvertisingDirected.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEstopAdvertising.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEprintConnectedClients.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEdisconnectAllClients.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEprintBonds.c_str()); - mqttClient.subscribe(subscribeTopicOMOTE_BLEdeleteBonds.c_str()); - Serial.printf(" Successfully subscribed to MQTT topics\r\n"); - + Serial.printf(" Successfully subscribed to MQTT topic %s\r\n", + subscribeTopicOMOTEtest.c_str()); } bool checkMQTTconnection() { @@ -154,27 +140,36 @@ bool checkMQTTconnection() { return true; } else { // try to connect to mqtt server - mqttClient.setBufferSize(512); // default is 256 - //mqttClient.setKeepAlive(15); // default is 15 Client will send MQTTPINGREQ to keep connection alive - //mqttClient.setSocketTimeout(15); // default is 15 This determines how long the client will wait for incoming data when it expects data to arrive - for example, whilst it is in the middle of reading an MQTT packet. - mqttClient.setServer(MQTT_SERVER, MQTT_SERVER_PORT); // MQTT initialization - - std::string mqttClientName = std::string(MQTT_CLIENTNAME) + "_esp32_" + std::string(WiFi.macAddress().c_str()); + mqttClient.setBufferSize(512); // default is 256 + // mqttClient.setKeepAlive(15); // default is 15 Client will send + // MQTTPINGREQ to keep connection alive mqttClient.setSocketTimeout(15); + // // default is 15 This determines how long the client will wait for + // incoming data when it expects data to arrive - for example, whilst it + // is in the middle of reading an MQTT packet. + mqttClient.setServer(MQTT_SERVER, + MQTT_SERVER_PORT); // MQTT initialization + + std::string mqttClientName = std::string(MQTT_CLIENTNAME) + "_esp32_" + + std::string(WiFi.macAddress().c_str()); if (mqttClient.connect(mqttClientName.c_str(), MQTT_USER, MQTT_PASS)) { - Serial.printf(" Successfully connected to MQTT broker\r\n"); - + + Serial.printf( + "[OMOTE][%8lu]: Successfully connected to MQTT broker\r\n", + (unsigned long)millis()); + mqtt_subscribeTopics(); } else { - Serial.printf(" MQTT connection failed (but WiFi is available). Will try later ...\r\n"); - + Serial.printf(" MQTT connection failed (but WiFi is available). Will " + "try later ...\r\n"); } return mqttClient.connected(); } } else { - // Serial.printf(" No connection to MQTT server, because WiFi ist not connected.\r\n"); + // Serial.printf(" No connection to MQTT server, because WiFi ist not + // connected.\r\n"); return false; - } + } } unsigned long reconnectInterval = 100; @@ -188,32 +183,34 @@ void mqtt_loop_HAL() { // Attempt to reconnect checkMQTTconnection(); } - } + } if (mqttClient.connected()) { mqttClient.loop(); } } -bool publishMQTTMessage_HAL(const char *topic, const char *payload){ +bool publishMQTTMessage_HAL(const char *topic, json payload) { if (checkMQTTconnection()) { - // Serial.printf("Sending mqtt payload to topic \"%s\": %s\r\n", topic, payload); - - if (mqttClient.publish(topic, payload)) { + // Serial.printf("Sending mqtt payload to topic \"%s\": %s\r\n", topic, + // payload); + payload["remoteId"] = id; + + if (mqttClient.publish(topic, payload.dump().c_str())) { // Serial.printf("Publish ok\r\n"); return true; - } - else { + } else { Serial.printf("Publish failed\r\n"); } } else { - Serial.printf(" Cannot publish mqtt message, because checkMQTTconnection failed (WiFi or mqtt is not connected)\r\n"); + Serial.printf(" Cannot publish mqtt message, because checkMQTTconnection " + "failed (WiFi or mqtt is not connected)\r\n"); } return false; } -void wifi_shutdown_HAL() { +void wifiStop_HAL() { WiFi.disconnect(); WiFi.mode(WIFI_OFF); } diff --git a/Platformio/hardware/ESP32/mqtt_hal_esp32.h b/Platformio/hardware/ESP32/mqtt_hal_esp32.h index c1dea2707..44a60a7b4 100644 --- a/Platformio/hardware/ESP32/mqtt_hal_esp32.h +++ b/Platformio/hardware/ESP32/mqtt_hal_esp32.h @@ -1,16 +1,24 @@ #pragma once +#include +#include + +using json = nlohmann::json; + #if (ENABLE_WIFI_AND_MQTT == 1) void init_mqtt_HAL(void); bool getIsWifiConnected_HAL(); void mqtt_loop_HAL(); -bool publishMQTTMessage_HAL(const char *topic, const char *payload); -void wifi_shutdown_HAL(); +bool publishMQTTMessage_HAL(const char *topic, json payload); +void wifiStop_HAL(); typedef void (*tAnnounceWiFiconnected_cb)(bool connected); -void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); -typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, std::string payload); -void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); +void set_announceWiFiconnected_cb_HAL( + tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); +typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, + std::string payload); +void set_announceSubscribedTopics_cb_HAL( + tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); #endif diff --git a/Platformio/hardware/ESP32/sleep_hal_esp32.cpp b/Platformio/hardware/ESP32/sleep_hal_esp32.cpp index b6d1db88c..36eba1872 100644 --- a/Platformio/hardware/ESP32/sleep_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/sleep_hal_esp32.cpp @@ -14,6 +14,8 @@ #include "mqtt_hal_esp32.h" // disconnect BLE keyboard #include "keyboard_ble_hal_esp32.h" +// disconnect ESP-NOW +#include "espnow_hal_esp32.h" // prepare keypad keys to wakeup #include "keypad_keys_hal_esp32.h" @@ -146,11 +148,15 @@ void enterSleep(){ #if (ENABLE_WIFI_AND_MQTT == 1) // Power down modem - wifi_shutdown_HAL(); + wifiStop_HAL(); #endif #if (ENABLE_KEYBOARD_BLE == 1) - keyboard_ble_shutdown_HAL(); + keyboardBLE_end_HAL(); + #endif + + #if (ENABLE_ESPNOW == 1) + espnow_shutdown_HAL(); #endif // Prepare IO states @@ -290,4 +296,4 @@ void set_wakeupByIMUEnabled_HAL(bool aWakeupByIMUEnabled) { } uint32_t get_lastActivityTimestamp() { return lastActivityTimestamp; -} +} \ No newline at end of file diff --git a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp index 78591350f..b6fc3a1b4 100644 --- a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp +++ b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.cpp @@ -29,7 +29,7 @@ void set_announceBLEmessage_cb_HAL(tAnnounceBLEmessage_cb pAnnounceBLEmessage_cb void init_keyboardBLE_HAL() {}; bool keyboardBLE_isAdvertising_HAL() {return false;}; bool keyboardBLE_isConnected_HAL() {return false;}; -void keyboard_ble_shutdown_HAL() {}; +void keyboardBLE_end_HAL() {}; void keyboardBLE_write_HAL(uint8_t c) {}; void keyboardBLE_longpress_HAL(uint8_t c) {}; void keyboardBLE_home_HAL() {}; diff --git a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h index 3a046fa0c..8a76a985a 100644 --- a/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/keyboard_ble_hal_windows_linux.h @@ -39,7 +39,7 @@ void set_announceBLEmessage_cb_HAL(tAnnounceBLEmessage_cb pAnnounceBLEmessage_cb void init_keyboardBLE_HAL(); bool keyboardBLE_isAdvertising_HAL(); bool keyboardBLE_isConnected_HAL(); -void keyboard_ble_shutdown_HAL(); +void keyboardBLE_end_HAL(); void keyboardBLE_write_HAL(uint8_t c); void keyboardBLE_longpress_HAL(uint8_t c); void keyboardBLE_home_HAL(); diff --git a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp index 5a003cef3..0999909c0 100644 --- a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp +++ b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp @@ -1,34 +1,35 @@ -#include #include "mqtt_hal_windows_linux.h" #include "secrets.h" +#include #if (ENABLE_WIFI_AND_MQTT == 1) +#include +#include +#include +#include #include #include -#include #include #include -#include -#include #include #include -#include #include -// example is mainly taken from .pio/libdeps/windows_linux_64bit/MQTT-C/tests.c, TEST__api__publish_subscribe__single +// example is mainly taken from .pio/libdeps/windows_linux_64bit/MQTT-C/tests.c, +// TEST__api__publish_subscribe__single #if !defined(WIN32) -#include -#include -#include -#include #include +#include +#include +#include #include +#include #else #include /* Some shortcuts to call winapi in a posix-like way */ -#define close(sock) closesocket(sock) -#define usleep(usec) Sleep((usec) / 1000) +#define close(sock) closesocket(sock) +#define usleep(usec) Sleep((usec) / 1000) #endif #include "lib/MQTT-C/include/mqtt.h" @@ -42,76 +43,51 @@ std::string uniqueClientSuffix = ""; int state = 0; tAnnounceWiFiconnected_cb thisAnnounceWiFiconnected_cb = NULL; -void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { - thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; +void set_announceWiFiconnected_cb_HAL( + tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { + thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; } tAnnounceSubscribedTopics_cb thisAnnounceSubscribedTopics_cb = NULL; -void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { - thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; +void set_announceSubscribedTopics_cb_HAL( + tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { + thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; } -bool getIsWifiConnected_HAL() { - return (sockfd != -1); -} +bool getIsWifiConnected_HAL() { return (sockfd != -1); } -std::string subscribeTopicOMOTEtest = "OMOTE/test"; -// For connecting to one or several BLE clients -std::string subscribeTopicOMOTE_BLEstartAdvertisingForAll = "OMOTE/BLE/startAdvertisingForAll"; -std::string subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist = "OMOTE/BLE/startAdvertisingWithWhitelist"; -std::string subscribeTopicOMOTE_BLEstartAdvertisingDirected = "OMOTE/BLE/startAdvertisingDirected"; -std::string subscribeTopicOMOTE_BLEstopAdvertising = "OMOTE/BLE/stopAdvertising"; -std::string subscribeTopicOMOTE_BLEprintConnectedClients = "OMOTE/BLE/printConnectedClients"; -std::string subscribeTopicOMOTE_BLEdisconnectAllClients = "OMOTE/BLE/disconnectAllClients"; -std::string subscribeTopicOMOTE_BLEprintBonds = "OMOTE/BLE/printBonds"; -std::string subscribeTopicOMOTE_BLEdeleteBonds = "OMOTE/BLE/deleteBonds"; - -void publish_callback(void** state, struct mqtt_response_publish *publish) { - **(int**)state += 1; - printf("message nr %d received\r\n", **(int**)state); - - std::string topic((const char*) (publish->topic_name), publish->topic_name_size); - std::string payload((const char*) (publish->application_message), publish->application_message_size); - - printf("Received a PUBLISH(topic=%s, DUP=%d, QOS=%d, RETAIN=%d, pid=%d) from the broker. Data='%s'\r\n", - topic.c_str(), publish->dup_flag, publish->qos_level, publish->retain_flag, publish->packet_id, - payload.c_str() - ); - - if (topic == subscribeTopicOMOTEtest) { - // Do whatever you want here, if it is Windows/Linux hardware related. - // ... - - // Or forward the topic to "void receiveMQTTmessage_cb" in the "commandHandler.cpp", if it is not Windows/Linux hardware related - thisAnnounceSubscribedTopics_cb(topic, payload); - - } else { - // forward all other topics to the commandHandler - thisAnnounceSubscribedTopics_cb(topic, payload); - } -} +void publish_callback(void **state, struct mqtt_response_publish *publish) { + **(int **)state += 1; + printf("message nr %d received\r\n", **(int **)state); + + std::string topic((const char *)(publish->topic_name), + publish->topic_name_size); + std::string payload((const char *)(publish->application_message), + publish->application_message_size); -void mqtt_subscribeTopics() { - mqtt_subscribe(&mqttClient, subscribeTopicOMOTEtest.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstartAdvertisingForAll.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstartAdvertisingDirected.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstopAdvertising.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEprintConnectedClients.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEdisconnectAllClients.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEprintBonds.c_str(), 2); - mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEdeleteBonds.c_str(), 2); + printf("Received a PUBLISH(topic=%s, DUP=%d, QOS=%d, RETAIN=%d, pid=%d) from " + "the broker. Data='%s'\r\n", + topic.c_str(), publish->dup_flag, publish->qos_level, + publish->retain_flag, publish->packet_id, payload.c_str()); + thisAnnounceSubscribedTopics_cb(topic, payload); } -void reconnect_mqtt(struct mqtt_client *mqttClient, void**) { +void mqtt_subscribeTopics() { mqtt_subscribe(&mqttClient, "OMOTE/test", 2); } + +void reconnect_mqtt(struct mqtt_client *mqttClient, void **) { printf("MQTT: will reconnect ...\r\n"); - mqtt_reinit(mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, sizeof(recvmem1)); + mqtt_reinit(mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, + sizeof(recvmem1)); - std::string mqttClientName = std::string(MQTT_CLIENTNAME) + uniqueClientSuffix; - // client_id, will_topic, will_message, will_message_size, user_name, password, connect_flags, keep_alive - mqtt_connect(mqttClient, mqttClientName.c_str(), NULL, NULL, 0, MQTT_USER, MQTT_PASS, 0, 30); + std::string mqttClientName = + std::string(MQTT_CLIENTNAME) + uniqueClientSuffix; + // client_id, will_topic, will_message, + // will_message_size, user_name, password, + // connect_flags, keep_alive + mqtt_connect(mqttClient, mqttClientName.c_str(), NULL, NULL, 0, MQTT_USER, + MQTT_PASS, 0, 30); if (mqttClient->error != MQTT_OK) { printf("MQTT: connect error: %s\r\n", mqtt_error_str(mqttClient->error)); // sockfd = -1; @@ -126,13 +102,13 @@ std::string getMACaddress() { strcpy(s.ifr_name, "eth0"); if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) { - char buffer[6*3]; + char buffer[6 * 3]; int i; for (i = 0; i < 6; ++i) { - sprintf(&buffer[i*3], "%02x:", (unsigned char) s.ifr_addr.sa_data[i]); + sprintf(&buffer[i * 3], "%02x:", (unsigned char)s.ifr_addr.sa_data[i]); // printf(" %02x", (unsigned char) s.ifr_addr.sa_data[i]); } - //printf("\r\n"); + // printf("\r\n"); std::string MACaddress = std::string(buffer, 17); printf(" result in MACaddress(): %s\r\n", MACaddress.c_str()); @@ -143,40 +119,44 @@ std::string getMACaddress() { #endif void init_mqtt_HAL(void) { - #if defined(WIN32) - WSADATA wsaData; - int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != NO_ERROR) { - printf("Failed to init sockets: %i\r\n", iResult); - return; // return iResult; - } - #endif +#if defined(WIN32) + WSADATA wsaData; + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != NO_ERROR) { + printf("Failed to init sockets: %i\r\n", iResult); + return; // return iResult; + } +#endif - char MACaddress[6*3]; - sockfd = open_nb_socket(MQTT_SERVER, std::to_string(MQTT_SERVER_PORT).c_str(), MACaddress); + char MACaddress[6 * 3]; + sockfd = open_nb_socket(MQTT_SERVER, std::to_string(MQTT_SERVER_PORT).c_str(), + MACaddress); if (sockfd == -1) { printf("MQTT: Failed to open socket\r\n"); return; } - #if !defined(WIN32) - // MAC address is not the best. You cannot start more than one instance like that, otherwise the MQTT broker will only keep the last connection. - // printf("MQTT: received MAC address from posix_sockets.h is %s\r\n", MACaddress); - // uniqueClientSuffix = std::string(MACaddress, 18); - // simply use a random number - srand(time(NULL)); // Initialization, should only be called once. - int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. +#if !defined(WIN32) + // MAC address is not the best. You cannot start more than one instance like + // that, otherwise the MQTT broker will only keep the last connection. + // printf("MQTT: received MAC address from posix_sockets.h is %s\r\n", + // MACaddress); uniqueClientSuffix = std::string(MACaddress, 18); simply use a + // random number + srand(time(NULL)); // Initialization, should only be called once. + int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. uniqueClientSuffix = "_linux_" + std::to_string(r); - #else - srand(time(NULL)); // Initialization, should only be called once. - int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. +#else + srand(time(NULL)); // Initialization, should only be called once. + int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. uniqueClientSuffix = "_windows_" + std::to_string(r); - #endif +#endif - // printf("MQTT: MAC address from getMACaddress() in mqtt_hal_windows_linux.cpp is %s\r\n", getMACaddress().c_str()); + // printf("MQTT: MAC address from getMACaddress() in + // mqtt_hal_windows_linux.cpp is %s\r\n", getMACaddress().c_str()); // printf("MQTT: will init ...\r\n"); - // mqtt_init(&mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, sizeof(recvmem1), publish_callback); + // mqtt_init(&mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, + // sizeof(recvmem1), publish_callback); printf("MQTT: will init with reconnect ...\r\n"); mqtt_init_reconnect(&mqttClient, reconnect_mqtt, NULL, publish_callback); reconnect_mqtt(&mqttClient, NULL); @@ -185,43 +165,41 @@ void init_mqtt_HAL(void) { mqtt_subscribeTopics(); thisAnnounceWiFiconnected_cb(true); - } void mqtt_loop_HAL() { if (sockfd != -1) { mqtt_sync(&mqttClient); } - } -bool publishMQTTMessage_HAL(const char *topic, const char *payload) { +bool publishMQTTMessage_HAL(const char *topic, json payload) { - if (sockfd == -1) { - init_mqtt_HAL(); - } - - mqtt_publish(&mqttClient, topic, payload, strlen(payload), MQTT_PUBLISH_QOS_0); - if (mqttClient.error != MQTT_OK) { - printf("MQTT: publish error %s\r\n", mqtt_error_str(mqttClient.error)); - sockfd = -1; - return false; - } + if (sockfd == -1) { + init_mqtt_HAL(); + } + + mqtt_publish(&mqttClient, topic, payload.dump().c_str(), strlen(payload), + MQTT_PUBLISH_QOS_0); + if (mqttClient.error != MQTT_OK) { + printf("MQTT: publish error %s\r\n", mqtt_error_str(mqttClient.error)); + sockfd = -1; + return false; + } return true; } -void wifi_shutdown_HAL() { +void wifiStop_HAL() { /* disconnect */ if (sockfd != -1) { mqtt_disconnect(&mqttClient); mqtt_sync(&mqttClient); } - #if defined(WIN32) +#if defined(WIN32) WSACleanup(); - #endif - +#endif } #endif diff --git a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h index c1dea2707..44a60a7b4 100644 --- a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h @@ -1,16 +1,24 @@ #pragma once +#include +#include + +using json = nlohmann::json; + #if (ENABLE_WIFI_AND_MQTT == 1) void init_mqtt_HAL(void); bool getIsWifiConnected_HAL(); void mqtt_loop_HAL(); -bool publishMQTTMessage_HAL(const char *topic, const char *payload); -void wifi_shutdown_HAL(); +bool publishMQTTMessage_HAL(const char *topic, json payload); +void wifiStop_HAL(); typedef void (*tAnnounceWiFiconnected_cb)(bool connected); -void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); -typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, std::string payload); -void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); +void set_announceWiFiconnected_cb_HAL( + tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); +typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, + std::string payload); +void set_announceSubscribedTopics_cb_HAL( + tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); #endif diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp index 6bb3dd371..6f0daf19a 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp @@ -204,8 +204,8 @@ bool keyboardBLE_isAdvertising() { bool keyboardBLE_isConnected() { return keyboardBLE_isConnected_HAL(); } -void keyboard_ble_shutdown() { - keyboard_ble_shutdown_HAL(); +void keyboardBLE_end() { + keyboardBLE_end_HAL(); } void keyboardBLE_write(uint8_t c) { keyboardBLE_write_HAL(c); @@ -260,8 +260,8 @@ void mqtt_loop() { bool publishMQTTMessage(const char *topic, const char *payload) { return publishMQTTMessage_HAL(topic, payload); } -void wifi_shutdown() { - wifi_shutdown_HAL(); +void wifiStop() { + wifiStop_HAL(); } #endif diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h index 3879e8529..ae16b81ff 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h @@ -118,7 +118,7 @@ void keyboardBLE_deleteBonds(); bool keyboardBLE_forceConnectionToAddress(std::string peerAddress); bool keyboardBLE_isAdvertising(); bool keyboardBLE_isConnected(); -void keyboard_ble_shutdown(); +void keyboardBLE_end(); void keyboardBLE_write(uint8_t c); void keyboardBLE_longpress(uint8_t c); void keyboardBLE_home(); @@ -142,7 +142,7 @@ void init_mqtt(void); bool getIsWifiConnected(); void mqtt_loop(); bool publishMQTTMessage(const char *topic, const char *payload); -void wifi_shutdown(); +void wifiStop(); #endif // --- memory usage ----------------------------------------------------------- diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.cpp b/Platformio/src/applicationInternal/hub/mqttBackend.cpp index 55904edbb..36f260ce2 100644 --- a/Platformio/src/applicationInternal/hub/mqttBackend.cpp +++ b/Platformio/src/applicationInternal/hub/mqttBackend.cpp @@ -39,6 +39,6 @@ bool MqttBackend::isReady() { } void MqttBackend::shutdown() { - wifi_shutdown(); + wifiStop(); } #endif \ No newline at end of file From 162ddc1dc6a90b4e1195dba22a870e34faba1274 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 09:24:03 -0400 Subject: [PATCH 11/32] chore: reverts old mqtt restore. --- Platformio/hardware/ESP32/mqtt_hal_esp32.cpp | 207 +++++++++--------- Platformio/hardware/ESP32/mqtt_hal_esp32.h | 16 +- .../windows_linux/mqtt_hal_windows_linux.cpp | 200 +++++++++-------- .../windows_linux/mqtt_hal_windows_linux.h | 16 +- 4 files changed, 224 insertions(+), 215 deletions(-) diff --git a/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp b/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp index 63ae5b489..a8542c1b6 100644 --- a/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/mqtt_hal_esp32.cpp @@ -1,53 +1,46 @@ -#include "mqtt_hal_esp32.h" +#include #include "WiFi.h" -#include "secrets.h" #include +#include "mqtt_hal_esp32.h" +#if (ENABLE_KEYBOARD_BLE == 1) +#include "keyboard_ble_hal_esp32.h" +#endif +#include "secrets.h" #if (ENABLE_WIFI_AND_MQTT == 1) WiFiClient espClient; PubSubClient mqttClient(espClient); bool isWifiConnected = false; -std::string id = ""; tAnnounceWiFiconnected_cb thisAnnounceWiFiconnected_cb = NULL; -void set_announceWiFiconnected_cb_HAL( - tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { - thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; +void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { + thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; } tAnnounceSubscribedTopics_cb thisAnnounceSubscribedTopics_cb = NULL; -void set_announceSubscribedTopics_cb_HAL( - tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { - thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; +void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { + thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; } -bool getIsWifiConnected_HAL() { return isWifiConnected; } - -std::string platform_create_id_string(void) { - uint8_t mac[6]; - char id_string[32]; - esp_read_mac(mac, ESP_MAC_WIFI_STA); - sprintf(id_string, "ESP32_%02x%02X%02X", mac[3], mac[4], mac[5]); - return std::string(id_string); +bool getIsWifiConnected_HAL() { + return isWifiConnected; } // WiFi status event -void WiFiEvent(WiFiEvent_t event) { - // Serial.printf("[WiFi-event] event: %d\r\n", event); - if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) { +void WiFiEvent(WiFiEvent_t event){ + //Serial.printf("[WiFi-event] event: %d\r\n", event); + if(event == ARDUINO_EVENT_WIFI_STA_GOT_IP){ // connection to MQTT server will be done in checkMQTTconnection() // mqttClient.setServer(MQTT_SERVER, 1883); // MQTT initialization // mqttClient.connect("OMOTE"); // Connect using a client id + } // Set status bar icon based on WiFi status - if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP || - event == ARDUINO_EVENT_WIFI_STA_GOT_IP6) { + if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP || event == ARDUINO_EVENT_WIFI_STA_GOT_IP6) { isWifiConnected = true; thisAnnounceWiFiconnected_cb(true); - - Serial.printf("[OMOTE][%8lu]: WiFi connected, IP address: %s\r\n", - (unsigned long)millis(), WiFi.localIP().toString().c_str()); + Serial.printf("WiFi connected, IP address: %s\r\n", WiFi.localIP().toString().c_str()); } else if (event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { isWifiConnected = false; @@ -61,67 +54,80 @@ void WiFiEvent(WiFiEvent_t event) { // connected is not enough, will wait for IP isWifiConnected = false; thisAnnounceWiFiconnected_cb(false); + } } void init_mqtt_HAL(void) { - Serial.printf("[OMOTE][%8lu]: Starting wifi\r\n", (unsigned long)millis()); - // Setup WiFi - WiFi.setHostname("OMOTE"); // define hostname + WiFi.setHostname("OMOTE"); //define hostname WiFi.onEvent(WiFiEvent); - - // 10.64.0.208 - IPAddress ip(10, 64, 0, 208); - // 10.64.0.1 - IPAddress gateway(10, 64, 0, 1); - // 255.255.254.0 - IPAddress subnet(255, 255, 254, 0); - - // TODO: This prevents NVR lookup - // WiFi.persistent(false); - // WiFi.mode(WIFI_STA); - - // TODO: Apply static IP settings - WiFi.config(ip, gateway, subnet); - - // uint8_t MAC[6] = {0xE4, 0x38, 0x83, 0x3E, 0xE2, 0x3D}; - - // WiFi.begin(WIFI_SSID, WIFI_PASSWORD, 1, MAC, true); - WiFi.begin(WIFI_SSID, WIFI_PASSWORD); WiFi.setSleep(true); - - id = platform_create_id_string(); } std::string subscribeTopicOMOTEtest = "OMOTE/test"; // For connecting to one or several BLE clients -std::string subscribeTopicOMOTE_BLEstartAdvertisingForAll = - "OMOTE/BLE/startAdvertisingForAll"; -std::string subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist = - "OMOTE/BLE/startAdvertisingWithWhitelist"; -std::string subscribeTopicOMOTE_BLEstartAdvertisingDirected = - "OMOTE/BLE/startAdvertisingDirected"; -std::string subscribeTopicOMOTE_BLEstopAdvertising = - "OMOTE/BLE/stopAdvertising"; -std::string subscribeTopicOMOTE_BLEprintConnectedClients = - "OMOTE/BLE/printConnectedClients"; -std::string subscribeTopicOMOTE_BLEdisconnectAllClients = - "OMOTE/BLE/disconnectAllClients"; -std::string subscribeTopicOMOTE_BLEprintBonds = "OMOTE/BLE/printBonds"; -std::string subscribeTopicOMOTE_BLEdeleteBonds = "OMOTE/BLE/deleteBonds"; - -void callback(char *topic, byte *payload, unsigned int length) { +std::string subscribeTopicOMOTE_BLEstartAdvertisingForAll = "OMOTE/BLE/startAdvertisingForAll"; +std::string subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist = "OMOTE/BLE/startAdvertisingWithWhitelist"; +std::string subscribeTopicOMOTE_BLEstartAdvertisingDirected = "OMOTE/BLE/startAdvertisingDirected"; +std::string subscribeTopicOMOTE_BLEstopAdvertising = "OMOTE/BLE/stopAdvertising"; +std::string subscribeTopicOMOTE_BLEprintConnectedClients = "OMOTE/BLE/printConnectedClients"; +std::string subscribeTopicOMOTE_BLEdisconnectAllClients = "OMOTE/BLE/disconnectAllClients"; +std::string subscribeTopicOMOTE_BLEprintBonds = "OMOTE/BLE/printBonds"; +std::string subscribeTopicOMOTE_BLEdeleteBonds = "OMOTE/BLE/deleteBonds"; + +void callback(char* topic, byte* payload, unsigned int length) { // handle message arrived std::string topicReceived(topic); std::string strPayload(reinterpret_cast(payload), length); - Serial.printf("MQTT: received topic %s with payload %s\r\n", - topicReceived.c_str(), strPayload.c_str()); + Serial.printf("MQTT: received topic %s with payload %s\r\n", topicReceived.c_str(), strPayload.c_str()); if (topicReceived == subscribeTopicOMOTEtest) { - Serial.printf("MQTT: received topic %s with payload %s\r\n", - subscribeTopicOMOTEtest.c_str(), strPayload.c_str()); + // Do whatever you want here, if it is ESP32 hardware related. + // ... + + // Or forward the topic to "void receiveMQTTmessage_cb" in the "commandHandler.cpp", if it is not ESP32 hardware related + thisAnnounceSubscribedTopics_cb(topicReceived, strPayload); + + #if (ENABLE_KEYBOARD_BLE == 1) + } else if (topicReceived == subscribeTopicOMOTE_BLEstartAdvertisingForAll) { + keyboardBLE_startAdvertisingForAll_HAL(); + } else if (topicReceived == subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist) { + keyboardBLE_startAdvertisingWithWhitelist_HAL(strPayload); + } else if (topicReceived == subscribeTopicOMOTE_BLEstartAdvertisingDirected) { + // the payload are two values, separated by comma: peerAddress and isRandomAddress + std::stringstream ss(strPayload); + if (ss.good()) { + std::string peerAddress; + std::getline(ss, peerAddress, ','); + + if (ss.good()) { + std::string isRandomAddressStr; + std::getline(ss, isRandomAddressStr, ','); + bool isRandomAddress = false; + if (isRandomAddressStr == "true") { + isRandomAddress = true; + } + keyboardBLE_startAdvertisingDirected_HAL(peerAddress, isRandomAddress); + } + } + } else if (topicReceived == subscribeTopicOMOTE_BLEstopAdvertising) { + keyboardBLE_stopAdvertising_HAL(); + } else if (topicReceived == subscribeTopicOMOTE_BLEprintConnectedClients) { + keyboardBLE_printConnectedClients_HAL(); + } else if (topicReceived == subscribeTopicOMOTE_BLEdisconnectAllClients) { + keyboardBLE_disconnectAllClients_HAL(); + } else if (topicReceived == subscribeTopicOMOTE_BLEprintBonds) { + keyboardBLE_printBonds_HAL(); + } else if (topicReceived == subscribeTopicOMOTE_BLEdeleteBonds) { + keyboardBLE_deleteBonds_HAL(); + #endif + + } else { + // forward all other topics to the commandHandler + thisAnnounceSubscribedTopics_cb(topicReceived, strPayload); + } } @@ -129,8 +135,16 @@ void mqtt_subscribeTopics() { mqttClient.setCallback(&callback); mqttClient.subscribe(subscribeTopicOMOTEtest.c_str()); - Serial.printf(" Successfully subscribed to MQTT topic %s\r\n", - subscribeTopicOMOTEtest.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEstartAdvertisingForAll.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEstartAdvertisingDirected.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEstopAdvertising.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEprintConnectedClients.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEdisconnectAllClients.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEprintBonds.c_str()); + mqttClient.subscribe(subscribeTopicOMOTE_BLEdeleteBonds.c_str()); + Serial.printf(" Successfully subscribed to MQTT topics\r\n"); + } bool checkMQTTconnection() { @@ -140,36 +154,27 @@ bool checkMQTTconnection() { return true; } else { // try to connect to mqtt server - mqttClient.setBufferSize(512); // default is 256 - // mqttClient.setKeepAlive(15); // default is 15 Client will send - // MQTTPINGREQ to keep connection alive mqttClient.setSocketTimeout(15); - // // default is 15 This determines how long the client will wait for - // incoming data when it expects data to arrive - for example, whilst it - // is in the middle of reading an MQTT packet. - mqttClient.setServer(MQTT_SERVER, - MQTT_SERVER_PORT); // MQTT initialization - - std::string mqttClientName = std::string(MQTT_CLIENTNAME) + "_esp32_" + - std::string(WiFi.macAddress().c_str()); + mqttClient.setBufferSize(512); // default is 256 + //mqttClient.setKeepAlive(15); // default is 15 Client will send MQTTPINGREQ to keep connection alive + //mqttClient.setSocketTimeout(15); // default is 15 This determines how long the client will wait for incoming data when it expects data to arrive - for example, whilst it is in the middle of reading an MQTT packet. + mqttClient.setServer(MQTT_SERVER, MQTT_SERVER_PORT); // MQTT initialization + + std::string mqttClientName = std::string(MQTT_CLIENTNAME) + "_esp32_" + std::string(WiFi.macAddress().c_str()); if (mqttClient.connect(mqttClientName.c_str(), MQTT_USER, MQTT_PASS)) { - - Serial.printf( - "[OMOTE][%8lu]: Successfully connected to MQTT broker\r\n", - (unsigned long)millis()); - + Serial.printf(" Successfully connected to MQTT broker\r\n"); + mqtt_subscribeTopics(); } else { - Serial.printf(" MQTT connection failed (but WiFi is available). Will " - "try later ...\r\n"); + Serial.printf(" MQTT connection failed (but WiFi is available). Will try later ...\r\n"); + } return mqttClient.connected(); } } else { - // Serial.printf(" No connection to MQTT server, because WiFi ist not - // connected.\r\n"); + // Serial.printf(" No connection to MQTT server, because WiFi ist not connected.\r\n"); return false; - } + } } unsigned long reconnectInterval = 100; @@ -183,29 +188,27 @@ void mqtt_loop_HAL() { // Attempt to reconnect checkMQTTconnection(); } - } + } if (mqttClient.connected()) { mqttClient.loop(); } } -bool publishMQTTMessage_HAL(const char *topic, json payload) { +bool publishMQTTMessage_HAL(const char *topic, const char *payload){ if (checkMQTTconnection()) { - // Serial.printf("Sending mqtt payload to topic \"%s\": %s\r\n", topic, - // payload); - payload["remoteId"] = id; - - if (mqttClient.publish(topic, payload.dump().c_str())) { + // Serial.printf("Sending mqtt payload to topic \"%s\": %s\r\n", topic, payload); + + if (mqttClient.publish(topic, payload)) { // Serial.printf("Publish ok\r\n"); return true; - } else { + } + else { Serial.printf("Publish failed\r\n"); } } else { - Serial.printf(" Cannot publish mqtt message, because checkMQTTconnection " - "failed (WiFi or mqtt is not connected)\r\n"); + Serial.printf(" Cannot publish mqtt message, because checkMQTTconnection failed (WiFi or mqtt is not connected)\r\n"); } return false; } diff --git a/Platformio/hardware/ESP32/mqtt_hal_esp32.h b/Platformio/hardware/ESP32/mqtt_hal_esp32.h index 44a60a7b4..116ae6015 100644 --- a/Platformio/hardware/ESP32/mqtt_hal_esp32.h +++ b/Platformio/hardware/ESP32/mqtt_hal_esp32.h @@ -1,24 +1,16 @@ #pragma once -#include -#include - -using json = nlohmann::json; - #if (ENABLE_WIFI_AND_MQTT == 1) void init_mqtt_HAL(void); bool getIsWifiConnected_HAL(); void mqtt_loop_HAL(); -bool publishMQTTMessage_HAL(const char *topic, json payload); +bool publishMQTTMessage_HAL(const char *topic, const char *payload); void wifiStop_HAL(); typedef void (*tAnnounceWiFiconnected_cb)(bool connected); -void set_announceWiFiconnected_cb_HAL( - tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); -typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, - std::string payload); -void set_announceSubscribedTopics_cb_HAL( - tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); +void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); +typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, std::string payload); +void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); #endif diff --git a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp index 0999909c0..48997ab78 100644 --- a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp +++ b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.cpp @@ -1,35 +1,34 @@ +#include #include "mqtt_hal_windows_linux.h" #include "secrets.h" -#include #if (ENABLE_WIFI_AND_MQTT == 1) -#include -#include -#include -#include #include #include +#include #include #include +#include +#include #include #include +#include #include -// example is mainly taken from .pio/libdeps/windows_linux_64bit/MQTT-C/tests.c, -// TEST__api__publish_subscribe__single +// example is mainly taken from .pio/libdeps/windows_linux_64bit/MQTT-C/tests.c, TEST__api__publish_subscribe__single #if !defined(WIN32) -#include -#include -#include +#include #include +#include +#include +#include #include -#include #else #include /* Some shortcuts to call winapi in a posix-like way */ -#define close(sock) closesocket(sock) -#define usleep(usec) Sleep((usec) / 1000) +#define close(sock) closesocket(sock) +#define usleep(usec) Sleep((usec) / 1000) #endif #include "lib/MQTT-C/include/mqtt.h" @@ -43,51 +42,76 @@ std::string uniqueClientSuffix = ""; int state = 0; tAnnounceWiFiconnected_cb thisAnnounceWiFiconnected_cb = NULL; -void set_announceWiFiconnected_cb_HAL( - tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { - thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; +void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb) { + thisAnnounceWiFiconnected_cb = pAnnounceWiFiconnected_cb; } tAnnounceSubscribedTopics_cb thisAnnounceSubscribedTopics_cb = NULL; -void set_announceSubscribedTopics_cb_HAL( - tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { - thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; +void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb) { + thisAnnounceSubscribedTopics_cb = pAnnounceSubscribedTopics_cb; } -bool getIsWifiConnected_HAL() { return (sockfd != -1); } - -void publish_callback(void **state, struct mqtt_response_publish *publish) { - **(int **)state += 1; - printf("message nr %d received\r\n", **(int **)state); +bool getIsWifiConnected_HAL() { + return (sockfd != -1); +} - std::string topic((const char *)(publish->topic_name), - publish->topic_name_size); - std::string payload((const char *)(publish->application_message), - publish->application_message_size); +std::string subscribeTopicOMOTEtest = "OMOTE/test"; +// For connecting to one or several BLE clients +std::string subscribeTopicOMOTE_BLEstartAdvertisingForAll = "OMOTE/BLE/startAdvertisingForAll"; +std::string subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist = "OMOTE/BLE/startAdvertisingWithWhitelist"; +std::string subscribeTopicOMOTE_BLEstartAdvertisingDirected = "OMOTE/BLE/startAdvertisingDirected"; +std::string subscribeTopicOMOTE_BLEstopAdvertising = "OMOTE/BLE/stopAdvertising"; +std::string subscribeTopicOMOTE_BLEprintConnectedClients = "OMOTE/BLE/printConnectedClients"; +std::string subscribeTopicOMOTE_BLEdisconnectAllClients = "OMOTE/BLE/disconnectAllClients"; +std::string subscribeTopicOMOTE_BLEprintBonds = "OMOTE/BLE/printBonds"; +std::string subscribeTopicOMOTE_BLEdeleteBonds = "OMOTE/BLE/deleteBonds"; + +void publish_callback(void** state, struct mqtt_response_publish *publish) { + **(int**)state += 1; + printf("message nr %d received\r\n", **(int**)state); + + std::string topic((const char*) (publish->topic_name), publish->topic_name_size); + std::string payload((const char*) (publish->application_message), publish->application_message_size); + + printf("Received a PUBLISH(topic=%s, DUP=%d, QOS=%d, RETAIN=%d, pid=%d) from the broker. Data='%s'\r\n", + topic.c_str(), publish->dup_flag, publish->qos_level, publish->retain_flag, publish->packet_id, + payload.c_str() + ); + + if (topic == subscribeTopicOMOTEtest) { + // Do whatever you want here, if it is Windows/Linux hardware related. + // ... + + // Or forward the topic to "void receiveMQTTmessage_cb" in the "commandHandler.cpp", if it is not Windows/Linux hardware related + thisAnnounceSubscribedTopics_cb(topic, payload); + + } else { + // forward all other topics to the commandHandler + thisAnnounceSubscribedTopics_cb(topic, payload); + } +} - printf("Received a PUBLISH(topic=%s, DUP=%d, QOS=%d, RETAIN=%d, pid=%d) from " - "the broker. Data='%s'\r\n", - topic.c_str(), publish->dup_flag, publish->qos_level, - publish->retain_flag, publish->packet_id, payload.c_str()); +void mqtt_subscribeTopics() { + mqtt_subscribe(&mqttClient, subscribeTopicOMOTEtest.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstartAdvertisingForAll.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstartAdvertisingWithWhitelist.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstartAdvertisingDirected.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEstopAdvertising.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEprintConnectedClients.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEdisconnectAllClients.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEprintBonds.c_str(), 2); + mqtt_subscribe(&mqttClient, subscribeTopicOMOTE_BLEdeleteBonds.c_str(), 2); - thisAnnounceSubscribedTopics_cb(topic, payload); } -void mqtt_subscribeTopics() { mqtt_subscribe(&mqttClient, "OMOTE/test", 2); } - -void reconnect_mqtt(struct mqtt_client *mqttClient, void **) { +void reconnect_mqtt(struct mqtt_client *mqttClient, void**) { printf("MQTT: will reconnect ...\r\n"); - mqtt_reinit(mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, - sizeof(recvmem1)); + mqtt_reinit(mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, sizeof(recvmem1)); - std::string mqttClientName = - std::string(MQTT_CLIENTNAME) + uniqueClientSuffix; - // client_id, will_topic, will_message, - // will_message_size, user_name, password, - // connect_flags, keep_alive - mqtt_connect(mqttClient, mqttClientName.c_str(), NULL, NULL, 0, MQTT_USER, - MQTT_PASS, 0, 30); + std::string mqttClientName = std::string(MQTT_CLIENTNAME) + uniqueClientSuffix; + // client_id, will_topic, will_message, will_message_size, user_name, password, connect_flags, keep_alive + mqtt_connect(mqttClient, mqttClientName.c_str(), NULL, NULL, 0, MQTT_USER, MQTT_PASS, 0, 30); if (mqttClient->error != MQTT_OK) { printf("MQTT: connect error: %s\r\n", mqtt_error_str(mqttClient->error)); // sockfd = -1; @@ -102,13 +126,13 @@ std::string getMACaddress() { strcpy(s.ifr_name, "eth0"); if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) { - char buffer[6 * 3]; + char buffer[6*3]; int i; for (i = 0; i < 6; ++i) { - sprintf(&buffer[i * 3], "%02x:", (unsigned char)s.ifr_addr.sa_data[i]); + sprintf(&buffer[i*3], "%02x:", (unsigned char) s.ifr_addr.sa_data[i]); // printf(" %02x", (unsigned char) s.ifr_addr.sa_data[i]); } - // printf("\r\n"); + //printf("\r\n"); std::string MACaddress = std::string(buffer, 17); printf(" result in MACaddress(): %s\r\n", MACaddress.c_str()); @@ -119,44 +143,40 @@ std::string getMACaddress() { #endif void init_mqtt_HAL(void) { -#if defined(WIN32) - WSADATA wsaData; - int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != NO_ERROR) { - printf("Failed to init sockets: %i\r\n", iResult); - return; // return iResult; - } -#endif + #if defined(WIN32) + WSADATA wsaData; + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (iResult != NO_ERROR) { + printf("Failed to init sockets: %i\r\n", iResult); + return; // return iResult; + } + #endif - char MACaddress[6 * 3]; - sockfd = open_nb_socket(MQTT_SERVER, std::to_string(MQTT_SERVER_PORT).c_str(), - MACaddress); + char MACaddress[6*3]; + sockfd = open_nb_socket(MQTT_SERVER, std::to_string(MQTT_SERVER_PORT).c_str(), MACaddress); if (sockfd == -1) { printf("MQTT: Failed to open socket\r\n"); return; } -#if !defined(WIN32) - // MAC address is not the best. You cannot start more than one instance like - // that, otherwise the MQTT broker will only keep the last connection. - // printf("MQTT: received MAC address from posix_sockets.h is %s\r\n", - // MACaddress); uniqueClientSuffix = std::string(MACaddress, 18); simply use a - // random number - srand(time(NULL)); // Initialization, should only be called once. - int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. + #if !defined(WIN32) + // MAC address is not the best. You cannot start more than one instance like that, otherwise the MQTT broker will only keep the last connection. + // printf("MQTT: received MAC address from posix_sockets.h is %s\r\n", MACaddress); + // uniqueClientSuffix = std::string(MACaddress, 18); + // simply use a random number + srand(time(NULL)); // Initialization, should only be called once. + int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. uniqueClientSuffix = "_linux_" + std::to_string(r); -#else - srand(time(NULL)); // Initialization, should only be called once. - int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. + #else + srand(time(NULL)); // Initialization, should only be called once. + int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX. uniqueClientSuffix = "_windows_" + std::to_string(r); -#endif + #endif - // printf("MQTT: MAC address from getMACaddress() in - // mqtt_hal_windows_linux.cpp is %s\r\n", getMACaddress().c_str()); + // printf("MQTT: MAC address from getMACaddress() in mqtt_hal_windows_linux.cpp is %s\r\n", getMACaddress().c_str()); // printf("MQTT: will init ...\r\n"); - // mqtt_init(&mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, - // sizeof(recvmem1), publish_callback); + // mqtt_init(&mqttClient, sockfd, sendmem1, sizeof(sendmem1), recvmem1, sizeof(recvmem1), publish_callback); printf("MQTT: will init with reconnect ...\r\n"); mqtt_init_reconnect(&mqttClient, reconnect_mqtt, NULL, publish_callback); reconnect_mqtt(&mqttClient, NULL); @@ -165,27 +185,28 @@ void init_mqtt_HAL(void) { mqtt_subscribeTopics(); thisAnnounceWiFiconnected_cb(true); + } void mqtt_loop_HAL() { if (sockfd != -1) { mqtt_sync(&mqttClient); } + } -bool publishMQTTMessage_HAL(const char *topic, json payload) { +bool publishMQTTMessage_HAL(const char *topic, const char *payload) { - if (sockfd == -1) { - init_mqtt_HAL(); - } - - mqtt_publish(&mqttClient, topic, payload.dump().c_str(), strlen(payload), - MQTT_PUBLISH_QOS_0); - if (mqttClient.error != MQTT_OK) { - printf("MQTT: publish error %s\r\n", mqtt_error_str(mqttClient.error)); - sockfd = -1; - return false; - } + if (sockfd == -1) { + init_mqtt_HAL(); + } + + mqtt_publish(&mqttClient, topic, payload, strlen(payload), MQTT_PUBLISH_QOS_0); + if (mqttClient.error != MQTT_OK) { + printf("MQTT: publish error %s\r\n", mqtt_error_str(mqttClient.error)); + sockfd = -1; + return false; + } return true; } @@ -197,9 +218,10 @@ void wifiStop_HAL() { mqtt_sync(&mqttClient); } -#if defined(WIN32) + #if defined(WIN32) WSACleanup(); -#endif + #endif + } #endif diff --git a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h index 44a60a7b4..116ae6015 100644 --- a/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h +++ b/Platformio/hardware/windows_linux/mqtt_hal_windows_linux.h @@ -1,24 +1,16 @@ #pragma once -#include -#include - -using json = nlohmann::json; - #if (ENABLE_WIFI_AND_MQTT == 1) void init_mqtt_HAL(void); bool getIsWifiConnected_HAL(); void mqtt_loop_HAL(); -bool publishMQTTMessage_HAL(const char *topic, json payload); +bool publishMQTTMessage_HAL(const char *topic, const char *payload); void wifiStop_HAL(); typedef void (*tAnnounceWiFiconnected_cb)(bool connected); -void set_announceWiFiconnected_cb_HAL( - tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); -typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, - std::string payload); -void set_announceSubscribedTopics_cb_HAL( - tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); +void set_announceWiFiconnected_cb_HAL(tAnnounceWiFiconnected_cb pAnnounceWiFiconnected_cb); +typedef void (*tAnnounceSubscribedTopics_cb)(std::string topic, std::string payload); +void set_announceSubscribedTopics_cb_HAL(tAnnounceSubscribedTopics_cb pAnnounceSubscribedTopics_cb); #endif From 714c2006a019ee35df7601cd9a335afd6ee93e42 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 19:16:42 -0400 Subject: [PATCH 12/32] feat: adds hub support to some other devices for testing. --- .../hardware/ESP32/espnow_hal_esp32.cpp | 8 ++-- .../applicationInternal/commandHandler.cpp | 12 ++--- .../src/applicationInternal/commandHandler.h | 6 +-- .../applicationInternal/hub/espnowBackend.cpp | 3 +- .../applicationInternal/hub/hubManager.cpp | 14 +++--- .../device_appleTV/device_appleTV.cpp | 31 +++++++++--- .../device_sonyAvr/device_sonyAvr.cpp | 27 +++++++++++ .../device_sonyAvr/device_sonyAvr.h | 12 +++++ .../TV/device_lgTV/device_lgTV.cpp | 48 +++++++++++++++++++ Platformio/src/secrets_override_example.h | 2 +- 10 files changed, 133 insertions(+), 30 deletions(-) create mode 100644 Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.cpp create mode 100644 Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.h diff --git a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp index 90805b0b4..bd0a38b1f 100644 --- a/Platformio/hardware/ESP32/espnow_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/espnow_hal_esp32.cpp @@ -25,7 +25,7 @@ void onDataReceived(const uint8_t *mac_addr, const uint8_t *data, int data_len) snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); - Serial.printf("ESP-NOW message received from %s\n", macStr); +// Serial.printf("ESP-NOW message received from %s\n", macStr); try { // Try to parse the received data as MessagePack @@ -59,6 +59,7 @@ void init_espnow_HAL(void) { // Register hub as peer memcpy(hub_peer.peer_addr, hub_mac, 6); + // Setting channel0 defaults to existing channel setting hub_peer.channel = 0; hub_peer.encrypt = false; @@ -77,9 +78,6 @@ void espnow_loop_HAL() { } bool publishEspNowMessage_HAL(json payload) { - // Add remote ID to the payload - payload["remoteId"] = WiFi.macAddress(); - // Pack the JSON into MessagePack format std::vector packed_json = json::to_msgpack(payload); @@ -92,7 +90,7 @@ bool publishEspNowMessage_HAL(json payload) { esp_err_t result = esp_now_send(hub_peer.peer_addr, packed_json.data(), packed_json.size()); if (result == ESP_OK) { - Serial.println("ESP-NOW sent message with success"); + // Serial.println("ESP-NOW sent message with success"); return true; } diff --git a/Platformio/src/applicationInternal/commandHandler.cpp b/Platformio/src/applicationInternal/commandHandler.cpp index fc80cafe0..68178d7f5 100644 --- a/Platformio/src/applicationInternal/commandHandler.cpp +++ b/Platformio/src/applicationInternal/commandHandler.cpp @@ -263,17 +263,17 @@ void executeCommandWithData(const CommandExecutionParams& params, commandData co auto current = commandData.commandPayloads.begin(); // Extract device and command - std::string device = *current; + std::string deviceName = *current; current = std::next(current, 1); - std::string hubCommand = *current; + std::string commandName = *current; current = std::next(current, 1); // Create JSON payload json payload; - payload["device"] = device; - payload["command"] = hubCommand; - payload["commandType"] = params.commandType; + payload["device"] = deviceName; + payload["command"] = commandName; + payload["type"] = params.commandType; // Create a data array if we have any additional data json dataArray = json::array(); @@ -295,7 +295,7 @@ void executeCommandWithData(const CommandExecutionParams& params, commandData co } omote_log_d("execute: will send hub message for device '%s', command '%s'\r\n", - device.c_str(), hubCommand.c_str()); + deviceName.c_str(), commandName.c_str()); // Send using the hub manager HubManager::getInstance().sendMessage(payload); diff --git a/Platformio/src/applicationInternal/commandHandler.h b/Platformio/src/applicationInternal/commandHandler.h index 95ccd0ee1..385e49d31 100644 --- a/Platformio/src/applicationInternal/commandHandler.h +++ b/Platformio/src/applicationInternal/commandHandler.h @@ -131,14 +131,14 @@ enum CommandExecutionType { }; NLOHMANN_JSON_SERIALIZE_ENUM(CommandExecutionType, { - {CMD_SHORT, "short"}, - {CMD_LONG, "long"} + {CMD_SHORT, "SHORT"}, + {CMD_LONG, "LONG"} }) struct CommandExecutionParams { uint16_t commandId; - std::string additionalPayload = ""; CommandExecutionType commandType = CMD_SHORT; + std::string additionalPayload = ""; }; // Version that takes a parameter struct diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.cpp b/Platformio/src/applicationInternal/hub/espnowBackend.cpp index baf68d1a1..428eef662 100644 --- a/Platformio/src/applicationInternal/hub/espnowBackend.cpp +++ b/Platformio/src/applicationInternal/hub/espnowBackend.cpp @@ -3,8 +3,7 @@ #include "applicationInternal/omote_log.h" #if (ENABLE_ESPNOW == 1) -EspNowBackend::EspNowBackend() { -} +EspNowBackend::EspNowBackend() = default; EspNowBackend::~EspNowBackend() { shutdown(); diff --git a/Platformio/src/applicationInternal/hub/hubManager.cpp b/Platformio/src/applicationInternal/hub/hubManager.cpp index 59b1621fa..d667e313f 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.cpp +++ b/Platformio/src/applicationInternal/hub/hubManager.cpp @@ -23,19 +23,21 @@ HubManager::HubManager() : currentBackend(HubBackend::ESPNOW) { std::unique_ptr HubManager::createBackend(HubBackend backend) { switch (backend) { case HubBackend::ESPNOW: - #if (ENABLE_ESPNOW == 1) - return std::unique_ptr(new EspNowBackend()); - #else + #if (ENABLE_ESPNOW != 1) omote_log_e("ESP-NOW backend is not available in this build\n"); return nullptr; + #else + return std::unique_ptr(new EspNowBackend()); #endif + case HubBackend::MQTT: - #if (ENABLE_WIFI_AND_MQTT == 1) - return std::unique_ptr(new MqttBackend()); - #else + #if (ENABLE_WIFI_AND_MQTT != 1) omote_log_e("MQTT backend is not available in this build\n"); return nullptr; + #else + return std::unique_ptr(new MqttBackend()); #endif + default: omote_log_e("Invalid hub backend selected\n"); return nullptr; diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp index faa644bb5..f76de420e 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp @@ -2,6 +2,7 @@ #include "applicationInternal/commandHandler.h" #include "applicationInternal/hardware/hardwarePresenter.h" #include "device_appleTV.h" + #if (ENABLE_HUB_COMMUNICATION == 1) #include "devices/misc/device_hub_helper.h" #endif @@ -9,22 +10,38 @@ uint16_t APPLETV_GUI_EVENT_USER_DATA; //"AppleTV_gui_event_user_data"; // Command IDs for Apple TV +uint16_t APPLETV_POWER_ON; +uint16_t APPLETV_POWER_OFF; +uint16_t APPLETV_PLAY_PAUSE; +uint16_t APPLETV_SKIP_FORWARD; +uint16_t APPLETV_SKIP_BACKWARD; +uint16_t APPLETV_STOP; uint16_t APPLETV_UP; uint16_t APPLETV_DOWN; -uint16_t APPLETV_LEFT; uint16_t APPLETV_RIGHT; +uint16_t APPLETV_LEFT; uint16_t APPLETV_SELECT; -// ... other commands +uint16_t APPLETV_MENU; +uint16_t APPLETV_HOME; void register_device_appleTV() { #if (ENABLE_HUB_COMMUNICATION == 1) // Register hub commands for Apple TV when Hub is enabled - register_hub_command(&APPLETV_UP, "AppleTV", "up"); - register_hub_command(&APPLETV_DOWN, "AppleTV", "down"); - register_hub_command(&APPLETV_LEFT, "AppleTV", "left"); - register_hub_command(&APPLETV_RIGHT, "AppleTV", "right"); - register_hub_command(&APPLETV_SELECT, "AppleTV", "select"); + register_hub_command(&APPLETV_POWER_ON, "AppleTV", "POWER_ON"); + register_hub_command(&APPLETV_POWER_OFF, "AppleTV", "POWER_OFF"); + register_hub_command(&APPLETV_PLAY_PAUSE, "AppleTV", "PLAY_PAUSE"); + register_hub_command(&APPLETV_SKIP_FORWARD, "AppleTV", "SKIP_FORWARD"); + register_hub_command(&APPLETV_SKIP_BACKWARD, "AppleTV", "SKIP_BACKWARD"); + register_hub_command(&APPLETV_STOP, "AppleTV", "STOP"); + register_hub_command(&APPLETV_UP, "AppleTV", "UP"); + register_hub_command(&APPLETV_DOWN, "AppleTV", "DOWN"); + register_hub_command(&APPLETV_RIGHT, "AppleTV", "RIGHT"); + register_hub_command(&APPLETV_LEFT, "AppleTV", "LEFT"); + register_hub_command(&APPLETV_SELECT, "AppleTV", "SELECT"); + register_hub_command(&APPLETV_MENU, "AppleTV", "MENU"); + register_hub_command(&APPLETV_HOME, "AppleTV", "HOME"); + #else // Register IR commands for Apple TV when Hub is not enabled register_command(&APPLETV_GUI_EVENT_USER_DATA, makeCommandData(IR, {std::to_string(IR_PROTOCOL_SONY)})); // payload must be set when calling commandHandler diff --git a/Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.cpp b/Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.cpp new file mode 100644 index 000000000..325236e10 --- /dev/null +++ b/Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.cpp @@ -0,0 +1,27 @@ +#include "device_sonyAvr.h" +#include "applicationInternal/commandHandler.h" +#include "applicationInternal/hardware/hardwarePresenter.h" +#include + +#if (ENABLE_HUB_COMMUNICATION == 1) +#include "devices/misc/device_hub_helper.h" +#endif + +// Only activate the commands that are used. Every command takes 100 bytes. +uint16_t SONY_POWER_ON; +uint16_t SONY_POWER_OFF; +uint16_t SONY_VOL_MINUS; +uint16_t SONY_VOL_PLUS; +uint16_t SONY_VOL_MUTE; + +void register_device_sonyAvr() { + + #if (ENABLE_HUB_COMMUNICATION == 1) + register_hub_command(&SONY_POWER_ON, "SONY_AVR", "POWER_ON"); + register_hub_command(&SONY_POWER_OFF, "SONY_AVR", "POWER_OFF"); + register_hub_command(&SONY_VOL_MINUS, "SONY_AVR", "VOL_MINUS"); + register_hub_command(&SONY_VOL_PLUS, "SONY_AVR", "VOL_PLUS"); + register_hub_command(&SONY_VOL_MUTE, "SONY_AVR", "VOL_MUTE"); + #endif + +} diff --git a/Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.h b/Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.h new file mode 100644 index 000000000..21c93efe5 --- /dev/null +++ b/Platformio/src/devices_pool/AVreceiver/device_sonyAvr/device_sonyAvr.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +// Only activate the commands that are used. Every command takes 100 bytes. +extern uint16_t SONY_POWER_ON; +extern uint16_t SONY_POWER_OFF; +extern uint16_t SONY_VOL_MINUS; +extern uint16_t SONY_VOL_PLUS; +extern uint16_t SONY_VOL_MUTE; + +void register_device_sonyAvr(); \ No newline at end of file diff --git a/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp b/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp index 84037b751..6e6064ad5 100644 --- a/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp +++ b/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp @@ -3,6 +3,10 @@ #include "applicationInternal/hardware/hardwarePresenter.h" #include "device_lgTV.h" +#if (ENABLE_HUB_COMMUNICATION == 1) +#include "devices/misc/device_hub_helper.h" +#endif + // Only activate the commands that are used. Every command takes 100 bytes, wether used or not uint16_t LGTV_POWER_ON; uint16_t LGTV_POWER_OFF; @@ -122,4 +126,48 @@ void register_device_lgTV() //register_command(&LGTV_SLEEP , makeCommandData(IR, {std::to_string(IR_PROTOCOL_NEC), "0x20DF58A7"})); register_command(&LGTV_3D , makeCommandData(IR, {std::to_string(IR_PROTOCOL_NEC), "0x20DF3BC4"})); register_command(&LGTV_HOME , makeCommandData(IR, {std::to_string(IR_PROTOCOL_NEC), "0x20DF3EC1"})); + + #if (ENABLE_HUB_COMMUNICATION == 1) + register_hub_command(&LGTV_POWER_OFF, "LGTV", "POWER_OFF"); + register_hub_command(&LGTV_POWER_ON, "LGTV", "POWER_ON"); + register_hub_command(&LGTV_SOURCE, "LGTV", "SOURCE"); + register_hub_command(&LGTV_NUM_1, "LGTV", "NUM_1"); + register_hub_command(&LGTV_NUM_2, "LGTV", "NUM_2"); + register_hub_command(&LGTV_NUM_3, "LGTV", "NUM_3"); + register_hub_command(&LGTV_NUM_4, "LGTV", "NUM_4"); + register_hub_command(&LGTV_NUM_5, "LGTV", "NUM_5"); + register_hub_command(&LGTV_NUM_6, "LGTV", "NUM_6"); + register_hub_command(&LGTV_NUM_7, "LGTV", "NUM_7"); + register_hub_command(&LGTV_NUM_8, "LGTV", "NUM_8"); + register_hub_command(&LGTV_NUM_9, "LGTV", "NUM_9"); + register_hub_command(&LGTV_NUM_0, "LGTV", "NUM_0"); + register_hub_command(&LGTV_PRECH, "LGTV", "PRECH"); + register_hub_command(&LGTV_VOL_MINUS, "LGTV", "VOL_MINUS"); + register_hub_command(&LGTV_VOL_PLUS, "LGTV", "VOL_PLUS"); + register_hub_command(&LGTV_MUTE_TOGGLE, "LGTV", "MUTE_TOGGLE"); + register_hub_command(&LGTV_CHANNEL_UP, "LGTV", "CHANNEL_UP"); + register_hub_command(&LGTV_CHANNEL_DOWN, "LGTV", "CHANNEL_DOWN"); + register_hub_command(&LGTV_MENU, "LGTV", "MENU"); + register_hub_command(&LGTV_GUIDE, "LGTV", "GUIDE"); + register_hub_command(&LGTV_SETUP, "LGTV", "SETUP"); + register_hub_command(&LGTV_INFO, "LGTV", "INFO"); + register_hub_command(&LGTV_UP, "LGTV", "UP"); + register_hub_command(&LGTV_DOWN, "LGTV", "DOWN"); + register_hub_command(&LGTV_LEFT, "LGTV", "LEFT"); + register_hub_command(&LGTV_RIGHT, "LGTV", "RIGHT"); + register_hub_command(&LGTV_OK, "LGTV", "OK"); + register_hub_command(&LGTV_RETURN, "LGTV", "RETURN"); + register_hub_command(&LGTV_EXIT, "LGTV", "EXIT"); + register_hub_command(&LGTV_KEY_A, "LGTV", "KEY_A"); + register_hub_command(&LGTV_KEY_B, "LGTV", "KEY_B"); + register_hub_command(&LGTV_KEY_C, "LGTV", "KEY_C"); + register_hub_command(&LGTV_KEY_D, "LGTV", "KEY_D"); + register_hub_command(&LGTV_INPUT_HDMI_1, "LGTV", "INPUT_HDMI_1"); + register_hub_command(&LGTV_INPUT_HDMI_2, "LGTV", "INPUT_HDMI_2"); + register_hub_command(&LGTV_INPUT_HDMI_3, "LGTV", "INPUT_HDMI_3"); + register_hub_command(&LGTV_INPUT_HDMI_4, "LGTV", "INPUT_HDMI_4"); + register_hub_command(&LGTV_INPUT_TV, "LGTV", "INPUT_TV"); + register_hub_command(&LGTV_3D, "LGTV", "3D"); + register_hub_command(&LGTV_HOME, "LGTV", "HOME"); + #endif } \ No newline at end of file diff --git a/Platformio/src/secrets_override_example.h b/Platformio/src/secrets_override_example.h index 416d368eb..b388ad9cd 100644 --- a/Platformio/src/secrets_override_example.h +++ b/Platformio/src/secrets_override_example.h @@ -13,5 +13,5 @@ #define MQTT_SERVER "IPAddressOfYourBroker" // override here // MAC address of the hub (replace with your actual hub's MAC) -#define ESPNOW_HUB_MAC {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} +#define ESPNOW_HUB_MAC {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} From 8cc787b26346e8aa174d8e0c8c9f70efa3cc3673 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 21:31:11 -0400 Subject: [PATCH 13/32] chore: fixes formatting and adds helper. --- .../applicationInternal/hub/mqttBackend.cpp | 9 +- .../device_appleTV/device_appleTV.cpp | 28 ++++--- .../device_appleTV/gui_appleTV.cpp | 8 +- .../src/devices/misc/device_hub_helper.h | 35 ++++---- .../TV/device_lgTV/device_lgTV.cpp | 82 +++++++++---------- 5 files changed, 84 insertions(+), 78 deletions(-) diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.cpp b/Platformio/src/applicationInternal/hub/mqttBackend.cpp index 36f260ce2..91e7b3f99 100644 --- a/Platformio/src/applicationInternal/hub/mqttBackend.cpp +++ b/Platformio/src/applicationInternal/hub/mqttBackend.cpp @@ -20,14 +20,7 @@ void MqttBackend::process() { } bool MqttBackend::sendMessage(const json& payload) { - // Extract device and command from the payload - std::string device = payload["device"]; - std::string command = payload["command"]; - - // Create MQTT topic from device and command - std::string topic = baseTopic + device + "/" + command; - - // Convert payload to string + std::string topic = baseTopic + "remote_commands"; std::string payloadStr = payload.dump(); omote_log_d("MQTT: Sending to topic %s: %s\n", topic.c_str(), payloadStr.c_str()); diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp index f76de420e..761d4b8c4 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/device_appleTV.cpp @@ -28,19 +28,21 @@ void register_device_appleTV() { #if (ENABLE_HUB_COMMUNICATION == 1) // Register hub commands for Apple TV when Hub is enabled - register_hub_command(&APPLETV_POWER_ON, "AppleTV", "POWER_ON"); - register_hub_command(&APPLETV_POWER_OFF, "AppleTV", "POWER_OFF"); - register_hub_command(&APPLETV_PLAY_PAUSE, "AppleTV", "PLAY_PAUSE"); - register_hub_command(&APPLETV_SKIP_FORWARD, "AppleTV", "SKIP_FORWARD"); - register_hub_command(&APPLETV_SKIP_BACKWARD, "AppleTV", "SKIP_BACKWARD"); - register_hub_command(&APPLETV_STOP, "AppleTV", "STOP"); - register_hub_command(&APPLETV_UP, "AppleTV", "UP"); - register_hub_command(&APPLETV_DOWN, "AppleTV", "DOWN"); - register_hub_command(&APPLETV_RIGHT, "AppleTV", "RIGHT"); - register_hub_command(&APPLETV_LEFT, "AppleTV", "LEFT"); - register_hub_command(&APPLETV_SELECT, "AppleTV", "SELECT"); - register_hub_command(&APPLETV_MENU, "AppleTV", "MENU"); - register_hub_command(&APPLETV_HOME, "AppleTV", "HOME"); + register_hub_command(&APPLETV_GUI_EVENT_USER_DATA, "APPLE_TV", "GUI_EVENT"); + + register_hub_command(&APPLETV_POWER_ON, "APPLE_TV", "POWER_ON"); + register_hub_command(&APPLETV_POWER_OFF, "APPLE_TV", "POWER_OFF"); + register_hub_command(&APPLETV_PLAY_PAUSE, "APPLE_TV", "PLAY_PAUSE"); + register_hub_command(&APPLETV_SKIP_FORWARD, "APPLE_TV", "SKIP_FORWARD"); + register_hub_command(&APPLETV_SKIP_BACKWARD, "APPLE_TV", "SKIP_BACKWARD"); + register_hub_command(&APPLETV_STOP, "APPLE_TV", "STOP"); + register_hub_command(&APPLETV_UP, "APPLE_TV", "UP"); + register_hub_command(&APPLETV_DOWN, "APPLE_TV", "DOWN"); + register_hub_command(&APPLETV_RIGHT, "APPLE_TV", "RIGHT"); + register_hub_command(&APPLETV_LEFT, "APPLE_TV", "LEFT"); + register_hub_command(&APPLETV_SELECT, "APPLE_TV", "SELECT"); + register_hub_command(&APPLETV_MENU, "APPLE_TV", "MENU"); + register_hub_command(&APPLETV_HOME, "APPLE_TV", "HOME"); #else // Register IR commands for Apple TV when Hub is not enabled diff --git a/Platformio/src/devices/mediaPlayer/device_appleTV/gui_appleTV.cpp b/Platformio/src/devices/mediaPlayer/device_appleTV/gui_appleTV.cpp index cbe633459..67aec083e 100644 --- a/Platformio/src/devices/mediaPlayer/device_appleTV/gui_appleTV.cpp +++ b/Platformio/src/devices/mediaPlayer/device_appleTV/gui_appleTV.cpp @@ -17,7 +17,13 @@ LV_IMG_DECLARE(appleBackIcon); static void appleKey_event_cb(lv_event_t* e) { // Send IR command based on the event user data int user_data = *((int*)(&(e->user_data))); - executeCommand(APPLETV_GUI_EVENT_USER_DATA, std::to_string(50 + user_data)); + + CommandExecutionParams params; + params.commandId = APPLETV_GUI_EVENT_USER_DATA; + params.commandType = CMD_SHORT; + params.additionalPayload = std::to_string(50 + user_data); + executeCommand(params); + omote_log_v("%d\r\n", 50 + user_data); } diff --git a/Platformio/src/devices/misc/device_hub_helper.h b/Platformio/src/devices/misc/device_hub_helper.h index e2a8917be..836af3c23 100644 --- a/Platformio/src/devices/misc/device_hub_helper.h +++ b/Platformio/src/devices/misc/device_hub_helper.h @@ -5,20 +5,25 @@ #include "applicationInternal/commandHandler.h" #if (ENABLE_HUB_COMMUNICATION == 1) -// Helper function to register hub commands for devices -void register_hub_command(uint16_t *command, const char *device, const char *cmd) { - std::list commandPayload = {device, cmd}; - register_command(command, makeCommandData(HUB, commandPayload)); -} + inline void register_hub_command(uint16_t *command, const char *device, const char *cmd) { + std::list commandPayload = {device, cmd}; + register_command(command, makeCommandData(HUB, commandPayload)); + } -// Helper function to register hub commands with additional parameters -void register_hub_command_with_params(uint16_t *command, const char *device, - const char *cmd, std::list params) { - std::list commandPayload = {device, cmd}; - - // Add all parameters to the command payload - commandPayload.insert(commandPayload.end(), params.begin(), params.end()); - - register_command(command, makeCommandData(HUB, commandPayload)); -} + inline void register_hub_command_with_params(uint16_t *command, const char *device, + const char *cmd, std::list params) { + std::list commandPayload = {device, cmd}; + + commandPayload.insert(commandPayload.end(), params.begin(), params.end()); + + register_command(command, makeCommandData(HUB, commandPayload)); + } + + inline void execute_hub_command(uint16_t command, CommandExecutionType type = CMD_SHORT, const std::string& additionalPayload = "") { + CommandExecutionParams params; + params.commandId = command; + params.commandType = type; + params.additionalPayload = additionalPayload; + executeCommand(params); + } #endif \ No newline at end of file diff --git a/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp b/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp index 6e6064ad5..6b34ce313 100644 --- a/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp +++ b/Platformio/src/devices_pool/TV/device_lgTV/device_lgTV.cpp @@ -128,46 +128,46 @@ void register_device_lgTV() register_command(&LGTV_HOME , makeCommandData(IR, {std::to_string(IR_PROTOCOL_NEC), "0x20DF3EC1"})); #if (ENABLE_HUB_COMMUNICATION == 1) - register_hub_command(&LGTV_POWER_OFF, "LGTV", "POWER_OFF"); - register_hub_command(&LGTV_POWER_ON, "LGTV", "POWER_ON"); - register_hub_command(&LGTV_SOURCE, "LGTV", "SOURCE"); - register_hub_command(&LGTV_NUM_1, "LGTV", "NUM_1"); - register_hub_command(&LGTV_NUM_2, "LGTV", "NUM_2"); - register_hub_command(&LGTV_NUM_3, "LGTV", "NUM_3"); - register_hub_command(&LGTV_NUM_4, "LGTV", "NUM_4"); - register_hub_command(&LGTV_NUM_5, "LGTV", "NUM_5"); - register_hub_command(&LGTV_NUM_6, "LGTV", "NUM_6"); - register_hub_command(&LGTV_NUM_7, "LGTV", "NUM_7"); - register_hub_command(&LGTV_NUM_8, "LGTV", "NUM_8"); - register_hub_command(&LGTV_NUM_9, "LGTV", "NUM_9"); - register_hub_command(&LGTV_NUM_0, "LGTV", "NUM_0"); - register_hub_command(&LGTV_PRECH, "LGTV", "PRECH"); - register_hub_command(&LGTV_VOL_MINUS, "LGTV", "VOL_MINUS"); - register_hub_command(&LGTV_VOL_PLUS, "LGTV", "VOL_PLUS"); - register_hub_command(&LGTV_MUTE_TOGGLE, "LGTV", "MUTE_TOGGLE"); - register_hub_command(&LGTV_CHANNEL_UP, "LGTV", "CHANNEL_UP"); - register_hub_command(&LGTV_CHANNEL_DOWN, "LGTV", "CHANNEL_DOWN"); - register_hub_command(&LGTV_MENU, "LGTV", "MENU"); - register_hub_command(&LGTV_GUIDE, "LGTV", "GUIDE"); - register_hub_command(&LGTV_SETUP, "LGTV", "SETUP"); - register_hub_command(&LGTV_INFO, "LGTV", "INFO"); - register_hub_command(&LGTV_UP, "LGTV", "UP"); - register_hub_command(&LGTV_DOWN, "LGTV", "DOWN"); - register_hub_command(&LGTV_LEFT, "LGTV", "LEFT"); - register_hub_command(&LGTV_RIGHT, "LGTV", "RIGHT"); - register_hub_command(&LGTV_OK, "LGTV", "OK"); - register_hub_command(&LGTV_RETURN, "LGTV", "RETURN"); - register_hub_command(&LGTV_EXIT, "LGTV", "EXIT"); - register_hub_command(&LGTV_KEY_A, "LGTV", "KEY_A"); - register_hub_command(&LGTV_KEY_B, "LGTV", "KEY_B"); - register_hub_command(&LGTV_KEY_C, "LGTV", "KEY_C"); - register_hub_command(&LGTV_KEY_D, "LGTV", "KEY_D"); - register_hub_command(&LGTV_INPUT_HDMI_1, "LGTV", "INPUT_HDMI_1"); - register_hub_command(&LGTV_INPUT_HDMI_2, "LGTV", "INPUT_HDMI_2"); - register_hub_command(&LGTV_INPUT_HDMI_3, "LGTV", "INPUT_HDMI_3"); - register_hub_command(&LGTV_INPUT_HDMI_4, "LGTV", "INPUT_HDMI_4"); - register_hub_command(&LGTV_INPUT_TV, "LGTV", "INPUT_TV"); - register_hub_command(&LGTV_3D, "LGTV", "3D"); - register_hub_command(&LGTV_HOME, "LGTV", "HOME"); + register_hub_command(&LGTV_POWER_OFF, "LG_TV", "POWER_OFF"); + register_hub_command(&LGTV_POWER_ON, "LG_TV", "POWER_ON"); + register_hub_command(&LGTV_SOURCE, "LG_TV", "SOURCE"); + register_hub_command(&LGTV_NUM_1, "LG_TV", "NUM_1"); + register_hub_command(&LGTV_NUM_2, "LG_TV", "NUM_2"); + register_hub_command(&LGTV_NUM_3, "LG_TV", "NUM_3"); + register_hub_command(&LGTV_NUM_4, "LG_TV", "NUM_4"); + register_hub_command(&LGTV_NUM_5, "LG_TV", "NUM_5"); + register_hub_command(&LGTV_NUM_6, "LG_TV", "NUM_6"); + register_hub_command(&LGTV_NUM_7, "LG_TV", "NUM_7"); + register_hub_command(&LGTV_NUM_8, "LG_TV", "NUM_8"); + register_hub_command(&LGTV_NUM_9, "LG_TV", "NUM_9"); + register_hub_command(&LGTV_NUM_0, "LG_TV", "NUM_0"); + register_hub_command(&LGTV_PRECH, "LG_TV", "PRECH"); + register_hub_command(&LGTV_VOL_MINUS, "LG_TV", "VOL_MINUS"); + register_hub_command(&LGTV_VOL_PLUS, "LG_TV", "VOL_PLUS"); + register_hub_command(&LGTV_MUTE_TOGGLE, "LG_TV", "MUTE_TOGGLE"); + register_hub_command(&LGTV_CHANNEL_UP, "LG_TV", "CHANNEL_UP"); + register_hub_command(&LGTV_CHANNEL_DOWN, "LG_TV", "CHANNEL_DOWN"); + register_hub_command(&LGTV_MENU, "LG_TV", "MENU"); + register_hub_command(&LGTV_GUIDE, "LG_TV", "GUIDE"); + register_hub_command(&LGTV_SETUP, "LG_TV", "SETUP"); + register_hub_command(&LGTV_INFO, "LG_TV", "INFO"); + register_hub_command(&LGTV_UP, "LG_TV", "UP"); + register_hub_command(&LGTV_DOWN, "LG_TV", "DOWN"); + register_hub_command(&LGTV_LEFT, "LG_TV", "LEFT"); + register_hub_command(&LGTV_RIGHT, "LG_TV", "RIGHT"); + register_hub_command(&LGTV_OK, "LG_TV", "OK"); + register_hub_command(&LGTV_RETURN, "LG_TV", "RETURN"); + register_hub_command(&LGTV_EXIT, "LG_TV", "EXIT"); + register_hub_command(&LGTV_KEY_A, "LG_TV", "KEY_A"); + register_hub_command(&LGTV_KEY_B, "LG_TV", "KEY_B"); + register_hub_command(&LGTV_KEY_C, "LG_TV", "KEY_C"); + register_hub_command(&LGTV_KEY_D, "LG_TV", "KEY_D"); + register_hub_command(&LGTV_INPUT_HDMI_1, "LG_TV", "INPUT_HDMI_1"); + register_hub_command(&LGTV_INPUT_HDMI_2, "LG_TV", "INPUT_HDMI_2"); + register_hub_command(&LGTV_INPUT_HDMI_3, "LG_TV", "INPUT_HDMI_3"); + register_hub_command(&LGTV_INPUT_HDMI_4, "LG_TV", "INPUT_HDMI_4"); + register_hub_command(&LGTV_INPUT_TV, "LG_TV", "INPUT_TV"); + register_hub_command(&LGTV_3D, "LG_TV", "3D"); + register_hub_command(&LGTV_HOME, "LG_TV", "HOME"); #endif } \ No newline at end of file From e85984ffa5db287bf823b905929dd6990b16f3a5 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 21:32:39 -0400 Subject: [PATCH 14/32] chore: replaces mac address in secrets. --- Platformio/src/secrets.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Platformio/src/secrets.h b/Platformio/src/secrets.h index 0d79a5796..333e5cf34 100644 --- a/Platformio/src/secrets.h +++ b/Platformio/src/secrets.h @@ -14,7 +14,7 @@ #define MQTT_CLIENTNAME "OMOTE" // override it in file "secrets_override.h" // ESP-NOW Configuration -#define ESPNOW_HUB_MAC {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC} // override it in file "secrets_override.h" +#define ESPNOW_HUB_MAC {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // override it in file "secrets_override.h" // --- include override settings from seperate file --------------------------------------------------------------------------------------------------------------- #if __has_include("secrets_override.h") From 4334a050132759b3b734619641c2a8c0fecc2018 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 21:51:59 -0400 Subject: [PATCH 15/32] chore: renames backend to transport to be consistent with hub domain. --- Platformio/platformio.ini | 2 +- ...pnowBackend.cpp => espNowHubTransport.cpp} | 16 ++-- .../{espnowBackend.h => espNowHubTransport.h} | 8 +- .../applicationInternal/hub/hubManager.cpp | 78 +++++++++---------- .../src/applicationInternal/hub/hubManager.h | 24 +++--- .../{hubBackendBase.h => hubTransportBase.h} | 12 +-- .../applicationInternal/hub/mqttBackend.cpp | 37 --------- .../hub/mqttHubTransport.cpp | 41 ++++++++++ .../hub/{mqttBackend.h => mqttHubTransport.h} | 8 +- Platformio/src/main.cpp | 16 ++-- 10 files changed, 120 insertions(+), 122 deletions(-) rename Platformio/src/applicationInternal/hub/{espnowBackend.cpp => espNowHubTransport.cpp} (63%) rename Platformio/src/applicationInternal/hub/{espnowBackend.h => espNowHubTransport.h} (66%) rename Platformio/src/applicationInternal/hub/{hubBackendBase.h => hubTransportBase.h} (66%) delete mode 100644 Platformio/src/applicationInternal/hub/mqttBackend.cpp create mode 100644 Platformio/src/applicationInternal/hub/mqttHubTransport.cpp rename Platformio/src/applicationInternal/hub/{mqttBackend.h => mqttHubTransport.h} (73%) diff --git a/Platformio/platformio.ini b/Platformio/platformio.ini index d29274d87..42ebd70e2 100644 --- a/Platformio/platformio.ini +++ b/Platformio/platformio.ini @@ -26,7 +26,7 @@ build_flags = -D ENABLE_KEYBOARD_BLE=0 -D ENABLE_HUB_COMMUNICATION=1 -D ENABLE_ESPNOW=0 - -D PREFERRED_HUB_BACKEND=1 ; 0 = ESP-NOW, 1 = MQTT + -D PREFERRED_HUB_TRANSPORT=1 ; 0 = ESP-NOW, 1 = MQTT -D USE_SCENE_SPECIFIC_GUI_LIST=1 -D SCR_WIDTH=${env.custom_screen_width} -D SCR_HEIGHT=${env.custom_screen_height} diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.cpp b/Platformio/src/applicationInternal/hub/espNowHubTransport.cpp similarity index 63% rename from Platformio/src/applicationInternal/hub/espnowBackend.cpp rename to Platformio/src/applicationInternal/hub/espNowHubTransport.cpp index 428eef662..8bb591411 100644 --- a/Platformio/src/applicationInternal/hub/espnowBackend.cpp +++ b/Platformio/src/applicationInternal/hub/espNowHubTransport.cpp @@ -1,24 +1,24 @@ -#include "espnowBackend.h" +#include "espNowHubTransport.h" #include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/omote_log.h" #if (ENABLE_ESPNOW == 1) -EspNowBackend::EspNowBackend() = default; +EspNowHubTransport::EspNowHubTransport() = default; -EspNowBackend::~EspNowBackend() { +EspNowHubTransport::~EspNowHubTransport() { shutdown(); } -bool EspNowBackend::init() { +bool EspNowHubTransport::init() { init_espnow(); return true; } -void EspNowBackend::process() { +void EspNowHubTransport::process() { espnow_loop(); } -bool EspNowBackend::sendMessage(const json& payload) { +bool EspNowHubTransport::sendMessage(const json& payload) { // Extract device and command for logging std::string device = payload["device"]; std::string command = payload["command"]; @@ -27,12 +27,12 @@ bool EspNowBackend::sendMessage(const json& payload) { return publishEspNowMessage(payload); } -bool EspNowBackend::isReady() { +bool EspNowHubTransport::isReady() { // ESP-NOW is always ready once initialized return true; } -void EspNowBackend::shutdown() { +void EspNowHubTransport::shutdown() { espnow_shutdown(); } #endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/espnowBackend.h b/Platformio/src/applicationInternal/hub/espNowHubTransport.h similarity index 66% rename from Platformio/src/applicationInternal/hub/espnowBackend.h rename to Platformio/src/applicationInternal/hub/espNowHubTransport.h index 99f98c60a..0dda9f17a 100644 --- a/Platformio/src/applicationInternal/hub/espnowBackend.h +++ b/Platformio/src/applicationInternal/hub/espNowHubTransport.h @@ -1,15 +1,15 @@ #pragma once -#include "hubBackendBase.h" +#include "hubTransportBase.h" #include using json = nlohmann::json; #if (ENABLE_ESPNOW == 1) -class EspNowBackend : public HubBackendBase { +class EspNowHubTransport : public HubTransportBase { public: - EspNowBackend(); - ~EspNowBackend() override; + EspNowHubTransport(); + ~EspNowHubTransport() override; bool init() override; void process() override; diff --git a/Platformio/src/applicationInternal/hub/hubManager.cpp b/Platformio/src/applicationInternal/hub/hubManager.cpp index d667e313f..b8870c8db 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.cpp +++ b/Platformio/src/applicationInternal/hub/hubManager.cpp @@ -1,14 +1,14 @@ #include "hubManager.h" -#include "hubBackendBase.h" +#include "hubTransportBase.h" #include "applicationInternal/omote_log.h" #include #if (ENABLE_ESPNOW == 1) -#include "espnowBackend.h" +#include "espNowHubTransport.h" #endif #if (ENABLE_WIFI_AND_MQTT == 1) -#include "mqttBackend.h" +#include "mqttHubTransport.h" #endif HubManager& HubManager::getInstance() { @@ -16,90 +16,90 @@ HubManager& HubManager::getInstance() { return instance; } -HubManager::HubManager() : currentBackend(HubBackend::ESPNOW) { - // Initialize with default backend type only +HubManager::HubManager() : currentTransport(HubTransport::ESPNOW) { + // Initialize with default transport type only } -std::unique_ptr HubManager::createBackend(HubBackend backend) { - switch (backend) { - case HubBackend::ESPNOW: +std::unique_ptr HubManager::createTransport(HubTransport transport) { + switch (transport) { + case HubTransport::ESPNOW: #if (ENABLE_ESPNOW != 1) - omote_log_e("ESP-NOW backend is not available in this build\n"); + omote_log_e("ESP-NOW transport is not available in this build\n"); return nullptr; #else - return std::unique_ptr(new EspNowBackend()); + return std::unique_ptr(new EspNowHubTransport()); #endif - case HubBackend::MQTT: + case HubTransport::MQTT: #if (ENABLE_WIFI_AND_MQTT != 1) - omote_log_e("MQTT backend is not available in this build\n"); + omote_log_e("MQTT transport is not available in this build\n"); return nullptr; #else - return std::unique_ptr(new MqttBackend()); + return std::unique_ptr(new MqttHubTransport()); #endif default: - omote_log_e("Invalid hub backend selected\n"); + omote_log_e("Invalid hub transport selected\n"); return nullptr; } } -bool HubManager::init(HubBackend backend) { - // Store the selected backend type - currentBackend = backend; +bool HubManager::init(HubTransport transport) { + // Store the selected transport type + currentTransport = transport; - // Create the new backend - auto newBackend = createBackend(backend); - if (!newBackend) { + // Create the new transport + auto newTransport = createTransport(transport); + if (!newTransport) { return false; } - // Initialize the backend - if (!newBackend->init()) { - omote_log_e("Failed to initialize hub backend\n"); + // Initialize the transport + if (!newTransport->init()) { + omote_log_e("Failed to initialize hub transport\n"); return false; } - // If everything succeeded, replace the active backend - activeBackend = std::move(newBackend); + // If everything succeeded, replace the active transport + activeTransport = std::move(newTransport); return true; } void HubManager::process() { - if (activeBackend) { - activeBackend->process(); + if (activeTransport) { + activeTransport->process(); } } bool HubManager::sendMessage(const json& payload) { - if (!activeBackend) { - omote_log_w("Cannot send message: no hub backend initialized\n"); + if (!activeTransport) { + omote_log_w("Cannot send message: no hub transport initialized\n"); return false; } - if (!activeBackend->isReady()) { - omote_log_w("Cannot send message: hub backend not ready\n"); + if (!activeTransport->isReady()) { + omote_log_w("Cannot send message: hub transport not ready\n"); return false; } - return activeBackend->sendMessage(payload); + return activeTransport->sendMessage(payload); } bool HubManager::isInitialized() const { - return activeBackend != nullptr; + return activeTransport != nullptr; } bool HubManager::isReady() const { - return activeBackend && activeBackend->isReady(); + return activeTransport && activeTransport->isReady(); } void HubManager::shutdown() { - if (activeBackend) { - activeBackend->shutdown(); - activeBackend.reset(); + if (activeTransport) { + activeTransport->shutdown(); + activeTransport.reset(); } } -HubBackend HubManager::getCurrentBackend() const { - return currentBackend; +HubTransport HubManager::getCurrentTransport() const { + return currentTransport; } \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/hubManager.h b/Platformio/src/applicationInternal/hub/hubManager.h index b1b9b9efa..e9980c937 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.h +++ b/Platformio/src/applicationInternal/hub/hubManager.h @@ -1,6 +1,6 @@ #pragma once -#include "hubBackendBase.h" +#include "hubTransportBase.h" #include #include @@ -8,14 +8,14 @@ using json = nlohmann::json; class HubManager { private: - std::unique_ptr activeBackend; - HubBackend currentBackend; // Store the current backend type + std::unique_ptractiveTransport; + HubTransport currentTransport; // Private constructor for singleton HubManager(); - // Factory method for creating backends - static std::unique_ptr createBackend(HubBackend backend); + // Factory method for creating transports + static std::unique_ptr createTransport(HubTransport transport); public: static HubManager& getInstance(); @@ -24,26 +24,20 @@ class HubManager { HubManager(const HubManager&) = delete; HubManager& operator=(const HubManager&) = delete; - ~HubManager() = default; // Smart pointer handles cleanup + ~HubManager() = default; - // Initialize with the preferred backend - bool init(HubBackend backend); + // Initialize with the preferred transport + bool init(HubTransport transport); - // Process communication tasks void process(); - // Send a message using the active backend bool sendMessage(const json& payload); - // Check if communication is ready bool isReady() const; - // Shutdown communication void shutdown(); - // Check if the hub is initialized bool isInitialized() const; - // Get the current backend type - HubBackend getCurrentBackend() const; + HubTransport getCurrentTransport() const; }; \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/hubBackendBase.h b/Platformio/src/applicationInternal/hub/hubTransportBase.h similarity index 66% rename from Platformio/src/applicationInternal/hub/hubBackendBase.h rename to Platformio/src/applicationInternal/hub/hubTransportBase.h index 350a79cc5..ce70ed764 100644 --- a/Platformio/src/applicationInternal/hub/hubBackendBase.h +++ b/Platformio/src/applicationInternal/hub/hubTransportBase.h @@ -5,18 +5,18 @@ using json = nlohmann::json; -// Define the hub backend types -enum class HubBackend { +// Define the hub transport types +enum class HubTransport { ESPNOW, MQTT }; -// Abstract interface for hub communication backends -class HubBackendBase { +// Abstract interface for hub communication transports +class HubTransportBase { public: - virtual ~HubBackendBase() = default; + virtual ~HubTransportBase() = default; - // Initialize the hub communication backend + // Initialize the hub communication transport virtual bool init() = 0; // Process hub communication tasks (called in loop) diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.cpp b/Platformio/src/applicationInternal/hub/mqttBackend.cpp deleted file mode 100644 index 91e7b3f99..000000000 --- a/Platformio/src/applicationInternal/hub/mqttBackend.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "mqttBackend.h" -#include "applicationInternal/hardware/hardwarePresenter.h" -#include "applicationInternal/omote_log.h" - -#if (ENABLE_WIFI_AND_MQTT == 1) -MqttBackend::MqttBackend() : baseTopic("omote/") { -} - -MqttBackend::~MqttBackend() { - shutdown(); -} - -bool MqttBackend::init() { - init_mqtt(); - return true; -} - -void MqttBackend::process() { - mqtt_loop(); -} - -bool MqttBackend::sendMessage(const json& payload) { - std::string topic = baseTopic + "remote_commands"; - std::string payloadStr = payload.dump(); - - omote_log_d("MQTT: Sending to topic %s: %s\n", topic.c_str(), payloadStr.c_str()); - return publishMQTTMessage(topic.c_str(), payloadStr.c_str()); -} - -bool MqttBackend::isReady() { - return getIsWifiConnected(); -} - -void MqttBackend::shutdown() { - wifiStop(); -} -#endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/mqttHubTransport.cpp b/Platformio/src/applicationInternal/hub/mqttHubTransport.cpp new file mode 100644 index 000000000..3641d4586 --- /dev/null +++ b/Platformio/src/applicationInternal/hub/mqttHubTransport.cpp @@ -0,0 +1,41 @@ +#include "mqttHubTransport.h" +#include "applicationInternal/hardware/hardwarePresenter.h" +#include "applicationInternal/omote_log.h" + +#if (ENABLE_WIFI_AND_MQTT == 1) +MqttHubTransport::MqttHubTransport() : baseTopic("omote/") { +} + +MqttHubTransport::~MqttHubTransport() { + shutdown(); +} + +bool MqttHubTransport::init() { + init_mqtt(); + return true; +} + +void MqttHubTransport::process() { + mqtt_loop(); +} + +bool MqttHubTransport::sendMessage(const json& payload) { + std::string topic = baseTopic + "remote_commands"; + std::string payloadStr = payload.dump(); + + // Extract device and command for logging + std::string device = payload["device"]; + std::string command = payload["command"]; + + omote_log_d("MQTT: Sending message for device %s, command %s\n", device.c_str(), command.c_str()); + return publishMQTTMessage(topic.c_str(), payloadStr.c_str()); +} + +bool MqttHubTransport::isReady() { + return getIsWifiConnected(); +} + +void MqttHubTransport::shutdown() { + wifiStop(); +} +#endif \ No newline at end of file diff --git a/Platformio/src/applicationInternal/hub/mqttBackend.h b/Platformio/src/applicationInternal/hub/mqttHubTransport.h similarity index 73% rename from Platformio/src/applicationInternal/hub/mqttBackend.h rename to Platformio/src/applicationInternal/hub/mqttHubTransport.h index 3e2972913..448deb178 100644 --- a/Platformio/src/applicationInternal/hub/mqttBackend.h +++ b/Platformio/src/applicationInternal/hub/mqttHubTransport.h @@ -1,15 +1,15 @@ #pragma once -#include "hubBackendBase.h" +#include "hubTransportBase.h" #include using json = nlohmann::json; #if (ENABLE_WIFI_AND_MQTT == 1) -class MqttBackend : public HubBackendBase { +class MqttHubTransport : public HubTransportBase { public: - MqttBackend(); - ~MqttBackend() override; + MqttHubTransport(); + ~MqttHubTransport() override; bool init() override; void process() override; diff --git a/Platformio/src/main.cpp b/Platformio/src/main.cpp index 29c5904b9..1157de83c 100644 --- a/Platformio/src/main.cpp +++ b/Platformio/src/main.cpp @@ -164,20 +164,20 @@ int main(int argc, char *argv[]) { init_mqtt(); #endif - // Initialize hub communication with preferred backend from settings + // Initialize hub communication with preferred transport from settings #if (ENABLE_HUB_COMMUNICATION == 1) - HubBackend preferredBackend; + HubTransport preferredTransport; - #if defined(PREFERRED_HUB_BACKEND) - preferredBackend = static_cast(PREFERRED_HUB_BACKEND); + #if defined(PREFERRED_HUB_TRANSPORT) + preferredTransport = static_cast(PREFERRED_HUB_TRANSPORT); #elif (ENABLE_ESPNOW == 1) - preferredBackend = HUB_ESPNOW; // Default to ESP-NOW when available + preferredTransport = HUB_TRANSPORT_ESPNOW; // Default to ESP-NOW when available #elif (ENABLE_WIFI_AND_MQTT == 1) - preferredBackend = HUB_MQTT; // Fall back to MQTT if ESP-NOW not available + preferredTransport = HUB_TRANSPORT_MQTT; // Fall back to MQTT if ESP-NOW not available #endif - // Initialize the hub manager with the preferred backend - HubManager::getInstance().init(preferredBackend); + // Initialize the hub manager with the preferred transport + HubManager::getInstance().init(preferredTransport); #endif omote_log_i("Setup finished in %lu ms.\r\n", millis()); From a1840c1b3587247e899cae7794956b1f382a4274 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 22:17:09 -0400 Subject: [PATCH 16/32] chore: fixes compiler bug when hub functionality is disabled. --- Platformio/platformio.ini | 8 ++++---- Platformio/src/applicationInternal/commandHandler.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Platformio/platformio.ini b/Platformio/platformio.ini index 42ebd70e2..be152892b 100644 --- a/Platformio/platformio.ini +++ b/Platformio/platformio.ini @@ -22,11 +22,11 @@ build_flags = ;-- OMOTE ----------------------------------------------------------------- -D ENABLE_WIFI_AND_MQTT=1 -D ENABLE_KEYBOARD_MQTT=0 - -D ENABLE_BLUETOOTH=0 - -D ENABLE_KEYBOARD_BLE=0 - -D ENABLE_HUB_COMMUNICATION=1 + -D ENABLE_BLUETOOTH=1 + -D ENABLE_KEYBOARD_BLE=1 + -D ENABLE_HUB_COMMUNICATION=0 -D ENABLE_ESPNOW=0 - -D PREFERRED_HUB_TRANSPORT=1 ; 0 = ESP-NOW, 1 = MQTT + -D PREFERRED_HUB_TRANSPORT=0 ; 0 = ESP-NOW, 1 = MQTT -D USE_SCENE_SPECIFIC_GUI_LIST=1 -D SCR_WIDTH=${env.custom_screen_width} -D SCR_HEIGHT=${env.custom_screen_height} diff --git a/Platformio/src/applicationInternal/commandHandler.cpp b/Platformio/src/applicationInternal/commandHandler.cpp index 68178d7f5..9edd56e05 100644 --- a/Platformio/src/applicationInternal/commandHandler.cpp +++ b/Platformio/src/applicationInternal/commandHandler.cpp @@ -241,14 +241,17 @@ void executeCommandWithData(uint16_t command, commandData commandData, std::stri break; } +#if (ENABLE_HUB_COMMUNICATION == 1) case HUB: { omote_log_w("HUB commands should be handled using the CommandExecutionParams struct\r\n"); break; } +#endif } } void executeCommandWithData(const CommandExecutionParams& params, commandData commandData) { +#if (ENABLE_HUB_COMMUNICATION == 1) if (commandData.commandHandler != HUB) { // For non-HUB commands, pass through to the original function omote_log_d("command: will execute command '%u'%s%s\r\n", @@ -299,6 +302,7 @@ void executeCommandWithData(const CommandExecutionParams& params, commandData co // Send using the hub manager HubManager::getInstance().sendMessage(payload); +#endif } void executeCommand(uint16_t command, std::string additionalPayload) { From a879e08257ed0c77e3ec8fe38fe8aa82da87459a Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Mon, 10 Mar 2025 22:32:40 -0400 Subject: [PATCH 17/32] chore: adds empty string back to executeCommandWithData. --- Platformio/src/applicationInternal/commandHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Platformio/src/applicationInternal/commandHandler.cpp b/Platformio/src/applicationInternal/commandHandler.cpp index 9edd56e05..3118012a3 100644 --- a/Platformio/src/applicationInternal/commandHandler.cpp +++ b/Platformio/src/applicationInternal/commandHandler.cpp @@ -176,7 +176,7 @@ std::string convertStringListToString(std::list listOfStrings) { return result; } -void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload) { +void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload = "") { switch (commandData.commandHandler) { case IR: { omote_log_v(" generic IR, payloads %s\r\n", convertStringListToString(commandData.commandPayloads).c_str()); From 84f15a86b0f8319403be62b8b0d9dd390ab93a36 Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Thu, 13 Mar 2025 21:41:56 -0400 Subject: [PATCH 18/32] feat: simplify hub build flag. --- Platformio/hardware/ESP32/sleep_hal_esp32.cpp | 2 +- Platformio/platformio.ini | 4 +--- .../src/applicationInternal/commandHandler.cpp | 8 ++++---- .../src/applicationInternal/commandHandler.h | 6 +++--- .../hardware/hardwarePresenter.cpp | 2 +- .../hardware/hardwarePresenter.h | 2 +- .../applicationInternal/hub/espNowHubTransport.cpp | 2 +- .../applicationInternal/hub/espNowHubTransport.h | 2 +- .../src/applicationInternal/hub/hubManager.cpp | 8 ++++---- Platformio/src/main.cpp | 14 ++++++-------- 10 files changed, 23 insertions(+), 27 deletions(-) diff --git a/Platformio/hardware/ESP32/sleep_hal_esp32.cpp b/Platformio/hardware/ESP32/sleep_hal_esp32.cpp index 36eba1872..6d7ed2be9 100644 --- a/Platformio/hardware/ESP32/sleep_hal_esp32.cpp +++ b/Platformio/hardware/ESP32/sleep_hal_esp32.cpp @@ -155,7 +155,7 @@ void enterSleep(){ keyboardBLE_end_HAL(); #endif - #if (ENABLE_ESPNOW == 1) + #if (ENABLE_HUB_COMMUNICATION == 1) espnow_shutdown_HAL(); #endif diff --git a/Platformio/platformio.ini b/Platformio/platformio.ini index be152892b..729c93842 100644 --- a/Platformio/platformio.ini +++ b/Platformio/platformio.ini @@ -24,9 +24,7 @@ build_flags = -D ENABLE_KEYBOARD_MQTT=0 -D ENABLE_BLUETOOTH=1 -D ENABLE_KEYBOARD_BLE=1 - -D ENABLE_HUB_COMMUNICATION=0 - -D ENABLE_ESPNOW=0 - -D PREFERRED_HUB_TRANSPORT=0 ; 0 = ESP-NOW, 1 = MQTT + -D ENABLE_HUB_COMMUNICATION=0 ; 0=DISABLED, 1=ESP-NOW, 2=MQTT -D USE_SCENE_SPECIFIC_GUI_LIST=1 -D SCR_WIDTH=${env.custom_screen_width} -D SCR_HEIGHT=${env.custom_screen_height} diff --git a/Platformio/src/applicationInternal/commandHandler.cpp b/Platformio/src/applicationInternal/commandHandler.cpp index 3118012a3..10351e7d1 100644 --- a/Platformio/src/applicationInternal/commandHandler.cpp +++ b/Platformio/src/applicationInternal/commandHandler.cpp @@ -176,7 +176,7 @@ std::string convertStringListToString(std::list listOfStrings) { return result; } -void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload = "") { +void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload) { switch (commandData.commandHandler) { case IR: { omote_log_v(" generic IR, payloads %s\r\n", convertStringListToString(commandData.commandPayloads).c_str()); @@ -241,7 +241,7 @@ void executeCommandWithData(uint16_t command, commandData commandData, std::stri break; } -#if (ENABLE_HUB_COMMUNICATION == 1) +#if (ENABLE_HUB_COMMUNICATION > 0) case HUB: { omote_log_w("HUB commands should be handled using the CommandExecutionParams struct\r\n"); break; @@ -251,7 +251,7 @@ void executeCommandWithData(uint16_t command, commandData commandData, std::stri } void executeCommandWithData(const CommandExecutionParams& params, commandData commandData) { -#if (ENABLE_HUB_COMMUNICATION == 1) +#if (ENABLE_HUB_COMMUNICATION > 0) if (commandData.commandHandler != HUB) { // For non-HUB commands, pass through to the original function omote_log_d("command: will execute command '%u'%s%s\r\n", @@ -369,7 +369,7 @@ void receiveMQTTmessage_cb(std::string topic, std::string payload) { } #endif -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) void receiveEspNowMessage_cb(json payload) { // Extract device and command from the payload std::string device, command, jsonStr; diff --git a/Platformio/src/applicationInternal/commandHandler.h b/Platformio/src/applicationInternal/commandHandler.h index 385e49d31..346d5e69e 100644 --- a/Platformio/src/applicationInternal/commandHandler.h +++ b/Platformio/src/applicationInternal/commandHandler.h @@ -106,7 +106,7 @@ enum commandHandlers { #if (ENABLE_KEYBOARD_BLE == 1) BLE_KEYBOARD, #endif - #if (ENABLE_HUB_COMMUNICATION == 1) + #if (ENABLE_HUB_COMMUNICATION > 0) HUB, #endif }; @@ -145,7 +145,7 @@ struct CommandExecutionParams { void executeCommand(const CommandExecutionParams& params); // Original executeCommandWithData -void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload = ""); +void executeCommandWithData(uint16_t command, commandData commandData, std::string additionalPayload); // New overload that takes CommandExecutionParams void executeCommandWithData(const CommandExecutionParams& params, commandData commandData); @@ -159,6 +159,6 @@ void receiveBLEmessage_cb(std::string message); void receiveWiFiConnected_cb(bool connected); void receiveMQTTmessage_cb(std::string topic, std::string payload); #endif -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) void receiveEspNowMessage_cb(json payload); #endif diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp index 6f0daf19a..626f09551 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.cpp @@ -271,7 +271,7 @@ void get_heapUsage(unsigned long *heapSize, unsigned long *freeHeap, unsigned lo } // --- ESP-NOW ---------------------------------------------------------------- -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) // ESP-NOW hardware presenter functions void init_espnow() { set_announceEspNowMessage_cb_HAL(&receiveEspNowMessage_cb); diff --git a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h index ae16b81ff..657825eab 100644 --- a/Platformio/src/applicationInternal/hardware/hardwarePresenter.h +++ b/Platformio/src/applicationInternal/hardware/hardwarePresenter.h @@ -149,7 +149,7 @@ void wifiStop(); void get_heapUsage(unsigned long *heapSize, unsigned long *freeHeap, unsigned long *maxAllocHeap, unsigned long *minFreeHeap); // --- ESP-NOW ---------------------------------------------------------------- -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) // ESP-NOW hardware presenter functions void init_espnow(); void espnow_loop(); diff --git a/Platformio/src/applicationInternal/hub/espNowHubTransport.cpp b/Platformio/src/applicationInternal/hub/espNowHubTransport.cpp index 8bb591411..f24e9ad81 100644 --- a/Platformio/src/applicationInternal/hub/espNowHubTransport.cpp +++ b/Platformio/src/applicationInternal/hub/espNowHubTransport.cpp @@ -2,7 +2,7 @@ #include "applicationInternal/hardware/hardwarePresenter.h" #include "applicationInternal/omote_log.h" -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) EspNowHubTransport::EspNowHubTransport() = default; EspNowHubTransport::~EspNowHubTransport() { diff --git a/Platformio/src/applicationInternal/hub/espNowHubTransport.h b/Platformio/src/applicationInternal/hub/espNowHubTransport.h index 0dda9f17a..5b56235fd 100644 --- a/Platformio/src/applicationInternal/hub/espNowHubTransport.h +++ b/Platformio/src/applicationInternal/hub/espNowHubTransport.h @@ -5,7 +5,7 @@ using json = nlohmann::json; -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) class EspNowHubTransport : public HubTransportBase { public: EspNowHubTransport(); diff --git a/Platformio/src/applicationInternal/hub/hubManager.cpp b/Platformio/src/applicationInternal/hub/hubManager.cpp index b8870c8db..7eccfed79 100644 --- a/Platformio/src/applicationInternal/hub/hubManager.cpp +++ b/Platformio/src/applicationInternal/hub/hubManager.cpp @@ -3,11 +3,11 @@ #include "applicationInternal/omote_log.h" #include -#if (ENABLE_ESPNOW == 1) +#if (ENABLE_HUB_COMMUNICATION == 1) #include "espNowHubTransport.h" #endif -#if (ENABLE_WIFI_AND_MQTT == 1) +#if (ENABLE_WIFI_AND_MQTT == 1 && ENABLE_HUB_COMMUNICATION == 2) #include "mqttHubTransport.h" #endif @@ -23,7 +23,7 @@ HubManager::HubManager() : currentTransport(HubTransport::ESPNOW) { std::unique_ptr HubManager::createTransport(HubTransport transport) { switch (transport) { case HubTransport::ESPNOW: - #if (ENABLE_ESPNOW != 1) + #if (ENABLE_HUB_COMMUNICATION != 1) omote_log_e("ESP-NOW transport is not available in this build\n"); return nullptr; #else @@ -31,7 +31,7 @@ std::unique_ptr HubManager::createTransport(HubTransport trans #endif case HubTransport::MQTT: - #if (ENABLE_WIFI_AND_MQTT != 1) + #if (ENABLE_WIFI_AND_MQTT != 1 || ENABLE_HUB_COMMUNICATION != 2) omote_log_e("MQTT transport is not available in this build\n"); return nullptr; #else diff --git a/Platformio/src/main.cpp b/Platformio/src/main.cpp index 1157de83c..0ba2571ba 100644 --- a/Platformio/src/main.cpp +++ b/Platformio/src/main.cpp @@ -165,15 +165,13 @@ int main(int argc, char *argv[]) { #endif // Initialize hub communication with preferred transport from settings - #if (ENABLE_HUB_COMMUNICATION == 1) + #if (ENABLE_HUB_COMMUNICATION > 0) HubTransport preferredTransport; - #if defined(PREFERRED_HUB_TRANSPORT) - preferredTransport = static_cast(PREFERRED_HUB_TRANSPORT); - #elif (ENABLE_ESPNOW == 1) - preferredTransport = HUB_TRANSPORT_ESPNOW; // Default to ESP-NOW when available - #elif (ENABLE_WIFI_AND_MQTT == 1) - preferredTransport = HUB_TRANSPORT_MQTT; // Fall back to MQTT if ESP-NOW not available + #if (ENABLE_HUB_COMMUNICATION == 1) + preferredTransport = HubTransport::ESPNOW; // ESP-NOW transport + #elif (ENABLE_HUB_COMMUNICATION == 2) + preferredTransport = HubTransport::MQTT; // MQTT transport #endif // Initialize the hub manager with the preferred transport @@ -241,7 +239,7 @@ void loop(unsigned long *pIMUTaskTimer, unsigned long *pUpdateStatusTimer) { } // Process hub communication - #if (ENABLE_HUB_COMMUNICATION == 1) + #if (ENABLE_HUB_COMMUNICATION > 0) HubManager::getInstance().process(); #endif From 38fa0b8e03966fd48b68e3a835542df6931c3d5f Mon Sep 17 00:00:00 2001 From: Andrew Stucky Date: Thu, 13 Mar 2025 22:04:26 -0400 Subject: [PATCH 19/32] chore: remove duplicate library include. --- .../windows_linux/keypad_gui/key_map.cpp | 2 +- .../hardware/windows_linux/lib/json/json.hpp | 24765 ---------------- .../src/applicationInternal/commandHandler.h | 2 +- 3 files changed, 2 insertions(+), 24767 deletions(-) delete mode 100644 Platformio/hardware/windows_linux/lib/json/json.hpp diff --git a/Platformio/hardware/windows_linux/keypad_gui/key_map.cpp b/Platformio/hardware/windows_linux/keypad_gui/key_map.cpp index 27c778a6a..8737bf155 100644 --- a/Platformio/hardware/windows_linux/keypad_gui/key_map.cpp +++ b/Platformio/hardware/windows_linux/keypad_gui/key_map.cpp @@ -1,7 +1,7 @@ #include #include -#include "../lib/json/json.hpp" +#include using json = nlohmann::json; diff --git a/Platformio/hardware/windows_linux/lib/json/json.hpp b/Platformio/hardware/windows_linux/lib/json/json.hpp deleted file mode 100644 index 8b72ea653..000000000 --- a/Platformio/hardware/windows_linux/lib/json/json.hpp +++ /dev/null @@ -1,24765 +0,0 @@ -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - -/****************************************************************************\ - * Note on documentation: The source files contain links to the online * - * documentation of the public API at https://json.nlohmann.me. This URL * - * contains the most recent documentation and should also be applicable to * - * previous versions; documentation for deprecated functions is not * - * removed, but marked deprecated. See "Generate documentation" section in * - * file docs/README.md. * -\****************************************************************************/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#ifndef JSON_NO_IO - #include // istream, ostream -#endif // JSON_NO_IO -#include // random_access_iterator_tag -#include // unique_ptr -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// This file contains all macro definitions affecting or depending on the ABI - -#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK - #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 - #warning "Already included a different version of the library!" - #endif - #endif -#endif - -#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) - -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 -#endif - -#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 -#endif - -#if JSON_DIAGNOSTICS - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag -#else - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS -#endif - -#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp -#else - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION - #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 -#endif - -// Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) - -#define NLOHMANN_JSON_ABI_TAGS \ - NLOHMANN_JSON_ABI_TAGS_CONCAT( \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) - -// Construct the namespace version component -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ - _v ## major ## _ ## minor ## _ ## patch -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) - -#if NLOHMANN_JSON_NAMESPACE_NO_VERSION -#define NLOHMANN_JSON_NAMESPACE_VERSION -#else -#define NLOHMANN_JSON_NAMESPACE_VERSION \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ - NLOHMANN_JSON_VERSION_MINOR, \ - NLOHMANN_JSON_VERSION_PATCH) -#endif - -// Combine namespace components -#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b -#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ - NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) - -#ifndef NLOHMANN_JSON_NAMESPACE -#define NLOHMANN_JSON_NAMESPACE \ - nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN -#define NLOHMANN_JSON_NAMESPACE_BEGIN \ - namespace nlohmann \ - { \ - inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) \ - { -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_END -#define NLOHMANN_JSON_NAMESPACE_END \ - } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ - } // namespace nlohmann -#endif - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // nullptr_t -#include // exception -#if JSON_DIAGNOSTICS - #include // accumulate -#endif -#include // runtime_error -#include // to_string -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // declval, pair -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -// https://en.cppreference.com/w/cpp/experimental/is_detected -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -struct is_detected_lazy : is_detected { }; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - - -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson -// SPDX-License-Identifier: MIT - -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 15 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #undef JSON_HEDLEY_MCST_LCC_VERSION -#endif -#if defined(__LCC__) && defined(__LCC_MINOR__) - #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) - #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_CRAY_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) && \ - !defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if \ - defined(__has_attribute) && \ - ( \ - (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ - ) -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions (except those affecting ABI) -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// #include - - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -// if the user manually specified the used c++ version this is skipped -#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) - #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 - #endif - // the cpp 11 flag is always specified because it is the minimal required version - #define JSON_HAS_CPP_11 -#endif - -#ifdef __has_include - #if __has_include() - #include - #endif -#endif - -#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) - #ifdef JSON_HAS_CPP_17 - #if defined(__cpp_lib_filesystem) - #define JSON_HAS_FILESYSTEM 1 - #elif defined(__cpp_lib_experimental_filesystem) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif !defined(__has_include) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #endif - - // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ - #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__clang_major__) && __clang_major__ < 7 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support - #if defined(_MSC_VER) && _MSC_VER < 1914 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before iOS 13 - #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before macOS Catalina - #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - #endif -#endif - -#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_FILESYSTEM - #define JSON_HAS_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_THREE_WAY_COMPARISON - #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ - && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L - #define JSON_HAS_THREE_WAY_COMPARISON 1 - #else - #define JSON_HAS_THREE_WAY_COMPARISON 0 - #endif -#endif - -#ifndef JSON_HAS_RANGES - // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error - #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 - #define JSON_HAS_RANGES 0 - #elif defined(__cpp_lib_ranges) - #define JSON_HAS_RANGES 1 - #else - #define JSON_HAS_RANGES 0 - #endif -#endif - -#ifndef JSON_HAS_STATIC_RTTI - #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 - #define JSON_HAS_STATIC_RTTI 1 - #else - #define JSON_HAS_STATIC_RTTI 0 - #endif -#endif - -#ifdef JSON_HAS_CPP_17 - #define JSON_INLINE_VARIABLE inline -#else - #define JSON_INLINE_VARIABLE -#endif - -#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) - #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] -#else - #define JSON_NO_UNIQUE_ADDRESS -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdocumentation" - #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" -#endif - -// allow disabling exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow overriding assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType, \ - class CustomBaseClass> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); -#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -// inspired from https://stackoverflow.com/a/26745591 -// allows to call any std function as if (e.g. with begin): -// using std::begin; begin(x); -// -// it allows using the detected idiom to retrieve the return type -// of such an expression -#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ - namespace detail { \ - using std::std_name; \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - } \ - \ - namespace detail2 { \ - struct std_name##_tag \ - { \ - }; \ - \ - template \ - std_name##_tag std_name(T&&...); \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - \ - template \ - struct would_call_std_##std_name \ - { \ - static constexpr auto const value = ::nlohmann::detail:: \ - is_detected_exact::value; \ - }; \ - } /* namespace detail2 */ \ - \ - template \ - struct would_call_std_##std_name : detail2::would_call_std_##std_name \ - { \ - } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - -#ifndef JSON_DISABLE_ENUM_SERIALIZATION - #define JSON_DISABLE_ENUM_SERIALIZATION 0 -#endif - -#ifndef JSON_USE_GLOBAL_UDLS - #define JSON_USE_GLOBAL_UDLS 1 -#endif - -#if JSON_HAS_THREE_WAY_COMPARISON - #include // partial_ordering -#endif - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -#if JSON_HAS_THREE_WAY_COMPARISON - inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* -#else - inline bool operator<(const value_t lhs, const value_t rhs) noexcept -#endif -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); -#if JSON_HAS_THREE_WAY_COMPARISON - if (l_index < order.size() && r_index < order.size()) - { - return order[l_index] <=> order[r_index]; // *NOPAD* - } - return std::partial_ordering::unordered; -#else - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -#endif -} - -// GCC selects the built-in operator< over an operator rewritten from -// a user-defined spaceship operator -// Clang, MSVC, and ICC select the rewritten candidate -// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) -#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - return std::is_lt(lhs <=> rhs); // *NOPAD* -} -#endif - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/*! -@brief replace all occurrences of a substring by another string - -@param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t -@param[in] f the substring to replace with @a t -@param[in] t the string to replace @a f - -@pre The search string @a f must not be empty. **This precondition is -enforced with an assertion.** - -@since version 2.0.0 -*/ -template -inline void replace_substring(StringType& s, const StringType& f, - const StringType& t) -{ - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != StringType::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -template -inline StringType escape(StringType s) -{ - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -static void unescape(StringType& s) -{ - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // size_t - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static JSON_INLINE_VARIABLE constexpr T value{}; -}; - -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -inline constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval -#include // tuple -#include // char_traits - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // random_access_iterator_tag - -// #include - -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); - -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); - -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - #include // int64_t, uint64_t - #include // map - #include // allocator - #include // string - #include // vector - - // #include - - - /*! - @brief namespace for Niels Lohmann - @see https://github.com/nlohmann - @since version 1.0.0 - */ - NLOHMANN_JSON_NAMESPACE_BEGIN - - /*! - @brief default JSONSerializer template argument - - This serializer ignores the template arguments and uses ADL - ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) - for serialization. - */ - template - struct adl_serializer; - - /// a class to store JSON values - /// @sa https://json.nlohmann.me/api/basic_json/ - template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> - class basic_json; - - /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document - /// @sa https://json.nlohmann.me/api/json_pointer/ - template - class json_pointer; - - /*! - @brief default specialization - @sa https://json.nlohmann.me/api/json/ - */ - using json = basic_json<>; - - /// @brief a minimal map-like container that preserves insertion order - /// @sa https://json.nlohmann.me/api/ordered_map/ - template - struct ordered_map; - - /// @brief specialization that maintains the insertion order of object keys - /// @sa https://json.nlohmann.me/api/ordered_json/ - using ordered_json = basic_json; - - NLOHMANN_JSON_NAMESPACE_END - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ - -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -// used by exceptions create() member functions -// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t -// false_type otherwise -template -struct is_basic_json_context : - std::integral_constant < bool, - is_basic_json::type>::type>::value - || std::is_same::value > -{}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -template -using detect_key_compare = typename T::key_compare; - -template -struct has_key_compare : std::integral_constant::value> {}; - -// obtains the actual object key comparator -template -struct actual_object_comparator -{ - using object_t = typename BasicJsonType::object_t; - using object_comparator_t = typename BasicJsonType::default_object_comparator_t; - using type = typename std::conditional < has_key_compare::value, - typename object_t::key_compare, object_comparator_t>::type; -}; - -template -using actual_object_comparator_t = typename actual_object_comparator::type; - -///////////////// -// char_traits // -///////////////// - -// Primary template of char_traits calls std char_traits -template -struct char_traits : std::char_traits -{}; - -// Explicitly define char traits for unsigned char since it is not standard -template<> -struct char_traits : std::char_traits -{ - using char_type = unsigned char; - using int_type = uint64_t; - - // Redefine to_int_type function - static int_type to_int_type(char_type c) noexcept - { - return static_cast(c); - } - - static char_type to_char_type(int_type i) noexcept - { - return static_cast(i); - } - - static constexpr int_type eof() noexcept - { - return static_cast(EOF); - } -}; - -// Explicitly define char traits for signed char since it is not standard -template<> -struct char_traits : std::char_traits -{ - using char_type = signed char; - using int_type = uint64_t; - - // Redefine to_int_type function - static int_type to_int_type(char_type c) noexcept - { - return static_cast(c); - } - - static char_type to_char_type(int_type i) noexcept - { - return static_cast(i); - } - - static constexpr int_type eof() noexcept - { - return static_cast(EOF); - } -}; - -/////////////////// -// is_ functions // -/////////////////// - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B { }; -template -struct conjunction -: std::conditional(B::value), conjunction, B>::type {}; - -// https://en.cppreference.com/w/cpp/types/negation -template struct negation : std::integral_constant < bool, !B::value > { }; - -// Reimplementation of is_constructible and is_default_constructible, due to them being broken for -// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). -// This causes compile errors in e.g. clang 3.5 or gcc 4.9. -template -struct is_default_constructible : std::is_default_constructible {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_constructible : std::is_constructible {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -template -struct is_range -{ - private: - using t_ref = typename std::add_lvalue_reference::type; - - using iterator = detected_t; - using sentinel = detected_t; - - // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator - // and https://en.cppreference.com/w/cpp/iterator/sentinel_for - // but reimplementing these would be too much work, as a lot of other concepts are used underneath - static constexpr auto is_iterator_begin = - is_iterator_traits>::value; - - public: - static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; -}; - -template -using iterator_t = enable_if_t::value, result_of_begin())>>; - -template -using range_value_t = value_type_t>>; - -// The following implementation of is_complete_type is taken from -// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ -// and is written by Xiang Fan who agreed to using it in this library. - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - is_constructible::value && - is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type -{ - static constexpr auto value = - is_constructible::value; -}; - -template -struct is_constructible_string_type -{ - // launder type through decltype() to fix compilation failure on ICPC -#ifdef __INTEL_COMPILER - using laundered_type = decltype(std::declval()); -#else - using laundered_type = ConstructibleStringType; -#endif - - static constexpr auto value = - conjunction < - is_constructible, - is_detected_exact>::value; -}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < - is_detected::value&& - is_iterator_traits>>::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 - !std::is_same>::value >> -{ - static constexpr bool value = - is_constructible>::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - !is_compatible_string_type::value&& - is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_iterator_traits>>::value&& -is_detected::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 -!std::is_same>::value&& - is_complete_type < - detected_t>::value >> -{ - using value_type = range_value_t; - - static constexpr bool value = - std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, - value_type >::value; -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; - -template -struct is_json_iterator_of : std::false_type {}; - -template -struct is_json_iterator_of : std::true_type {}; - -template -struct is_json_iterator_of : std::true_type -{}; - -// checks if a given type T is a template specialization of Primary -template