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.

167 lines
3.7 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 <IPAddress.h>
  7. #include <cstdint>
  8. #include <memory>
  9. #include <vector>
  10. constexpr const size_t WS_DEBUG_MSG_BUFFER = 8;
  11. // -----------------------------------------------------------------------------
  12. // WS authentication
  13. // -----------------------------------------------------------------------------
  14. struct ws_ticket_t {
  15. IPAddress ip;
  16. unsigned long timestamp = 0;
  17. };
  18. // -----------------------------------------------------------------------------
  19. // WS callbacks
  20. // -----------------------------------------------------------------------------
  21. struct ws_counter_t {
  22. ws_counter_t() : current(0), start(0), stop(0) {}
  23. ws_counter_t(uint32_t start, uint32_t stop) :
  24. current(start), start(start), stop(stop) {}
  25. void reset() {
  26. current = start;
  27. }
  28. void next() {
  29. if (current < stop) {
  30. ++current;
  31. }
  32. }
  33. bool done() {
  34. return (current >= stop);
  35. }
  36. uint32_t current;
  37. uint32_t start;
  38. uint32_t stop;
  39. };
  40. struct ws_data_t {
  41. enum mode_t {
  42. SEQUENCE,
  43. ALL
  44. };
  45. ws_data_t(const ws_on_send_callback_f& cb) :
  46. storage(new ws_on_send_callback_list_t {cb}),
  47. client_id(0),
  48. mode(ALL),
  49. callbacks(*storage.get()),
  50. counter(0, 1)
  51. {}
  52. ws_data_t(uint32_t client_id, const ws_on_send_callback_f& cb) :
  53. storage(new ws_on_send_callback_list_t {cb}),
  54. client_id(client_id),
  55. mode(ALL),
  56. callbacks(*storage.get()),
  57. counter(0, 1)
  58. {}
  59. ws_data_t(const uint32_t client_id, ws_on_send_callback_list_t&& callbacks, mode_t mode = SEQUENCE) :
  60. storage(new ws_on_send_callback_list_t(std::move(callbacks))),
  61. client_id(client_id),
  62. mode(mode),
  63. callbacks(*storage.get()),
  64. counter(0, (storage.get())->size())
  65. {}
  66. ws_data_t(const uint32_t client_id, const ws_on_send_callback_list_t& callbacks, mode_t mode = SEQUENCE) :
  67. client_id(client_id),
  68. mode(mode),
  69. callbacks(callbacks),
  70. counter(0, callbacks.size())
  71. {}
  72. bool done() {
  73. return counter.done();
  74. }
  75. void sendAll(JsonObject& root) {
  76. while (!counter.done()) counter.next();
  77. for (auto& callback : callbacks) {
  78. callback(root);
  79. }
  80. }
  81. void sendCurrent(JsonObject& root) {
  82. callbacks[counter.current](root);
  83. counter.next();
  84. }
  85. void send(JsonObject& root) {
  86. switch (mode) {
  87. case SEQUENCE: sendCurrent(root); break;
  88. case ALL: sendAll(root); break;
  89. }
  90. }
  91. std::unique_ptr<ws_on_send_callback_list_t> storage;
  92. const uint32_t client_id;
  93. const mode_t mode;
  94. const ws_on_send_callback_list_t& callbacks;
  95. ws_counter_t counter;
  96. };
  97. // -----------------------------------------------------------------------------
  98. // Debug
  99. // -----------------------------------------------------------------------------
  100. using ws_debug_msg_t = std::pair<String, String>;
  101. struct ws_debug_t {
  102. ws_debug_t(size_t capacity) :
  103. flush(false),
  104. current(0),
  105. capacity(capacity)
  106. {
  107. messages.reserve(capacity);
  108. }
  109. void clear() {
  110. messages.clear();
  111. current = 0;
  112. flush = false;
  113. }
  114. void add(const char* prefix, const char* message) {
  115. if (current >= capacity) {
  116. flush = true;
  117. send(wsConnected());
  118. }
  119. messages.emplace(messages.begin() + current, prefix, message);
  120. flush = true;
  121. ++current;
  122. }
  123. void send(const bool connected);
  124. bool flush;
  125. size_t current;
  126. const size_t capacity;
  127. std::vector<ws_debug_msg_t> messages;
  128. };