Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
3.4 KiB

  1. /*
  2. WEBSOCKET MODULE
  3. Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #pragma once
  6. #include "espurna.h"
  7. #include <IPAddress.h>
  8. #include <cstdint>
  9. #include <memory>
  10. #include <vector>
  11. constexpr const size_t WS_DEBUG_MSG_BUFFER = 8;
  12. // -----------------------------------------------------------------------------
  13. // WS authentication
  14. // -----------------------------------------------------------------------------
  15. struct ws_ticket_t {
  16. IPAddress ip;
  17. unsigned long timestamp = 0;
  18. };
  19. // -----------------------------------------------------------------------------
  20. // WS callbacks
  21. // -----------------------------------------------------------------------------
  22. struct ws_data_t {
  23. enum mode_t {
  24. SEQUENCE,
  25. ALL
  26. };
  27. ws_data_t(const ws_on_send_callback_f& cb) :
  28. storage(new ws_on_send_callback_list_t {cb}),
  29. client_id(0),
  30. mode(ALL),
  31. callbacks(*storage.get()),
  32. current(callbacks.begin())
  33. {}
  34. ws_data_t(uint32_t client_id, const ws_on_send_callback_f& cb) :
  35. storage(new ws_on_send_callback_list_t {cb}),
  36. client_id(client_id),
  37. mode(ALL),
  38. callbacks(*storage.get()),
  39. current(callbacks.begin())
  40. {}
  41. ws_data_t(const uint32_t client_id, ws_on_send_callback_list_t&& callbacks, mode_t mode = SEQUENCE) :
  42. storage(new ws_on_send_callback_list_t(std::move(callbacks))),
  43. client_id(client_id),
  44. mode(mode),
  45. callbacks(*storage.get()),
  46. current(callbacks.begin())
  47. {}
  48. ws_data_t(const uint32_t client_id, const ws_on_send_callback_list_t& callbacks, mode_t mode = SEQUENCE) :
  49. client_id(client_id),
  50. mode(mode),
  51. callbacks(callbacks),
  52. current(callbacks.begin())
  53. {}
  54. bool done() {
  55. return current == callbacks.end();
  56. }
  57. void sendAll(JsonObject& root) {
  58. current = callbacks.end();
  59. for (auto& callback : callbacks) {
  60. callback(root);
  61. }
  62. }
  63. void sendCurrent(JsonObject& root) {
  64. if (current == callbacks.end()) return;
  65. (*current)(root);
  66. ++current;
  67. }
  68. void send(JsonObject& root) {
  69. switch (mode) {
  70. case SEQUENCE: sendCurrent(root); break;
  71. case ALL: sendAll(root); break;
  72. }
  73. }
  74. std::unique_ptr<ws_on_send_callback_list_t> storage;
  75. const uint32_t client_id;
  76. const mode_t mode;
  77. const ws_on_send_callback_list_t& callbacks;
  78. ws_on_send_callback_list_t::const_iterator current;
  79. };
  80. // -----------------------------------------------------------------------------
  81. // Debug
  82. // -----------------------------------------------------------------------------
  83. using ws_debug_msg_t = std::pair<String, String>;
  84. struct ws_debug_t {
  85. ws_debug_t(size_t capacity) :
  86. flush(false),
  87. current(0),
  88. capacity(capacity)
  89. {
  90. messages.reserve(capacity);
  91. }
  92. void clear() {
  93. messages.clear();
  94. current = 0;
  95. flush = false;
  96. }
  97. void add(const char* prefix, const char* message) {
  98. if (current >= capacity) {
  99. flush = true;
  100. send(wsConnected());
  101. }
  102. messages.emplace(messages.begin() + current, prefix, message);
  103. flush = true;
  104. ++current;
  105. }
  106. void send(const bool connected);
  107. bool flush;
  108. size_t current;
  109. const size_t capacity;
  110. std::vector<ws_debug_msg_t> messages;
  111. };