My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

WebSocketSerial.cpp 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #ifdef ARDUINO_ARCH_ESP32
  23. #include "../../inc/MarlinConfigPre.h"
  24. #if ENABLED(WIFISUPPORT)
  25. #include "WebSocketSerial.h"
  26. #include "wifi.h"
  27. #include <ESPAsyncWebServer.h>
  28. WebSocketSerial webSocketSerial;
  29. AsyncWebSocket ws("/ws"); // TODO Move inside the class.
  30. // RingBuffer impl
  31. #define NEXT_INDEX(I, SIZE) ((I + 1) & (ring_buffer_pos_t)(SIZE - 1))
  32. RingBuffer::RingBuffer(ring_buffer_pos_t size)
  33. : data(new uint8_t[size]),
  34. size(size),
  35. read_index(0),
  36. write_index(0)
  37. {}
  38. RingBuffer::~RingBuffer() { delete[] data; }
  39. ring_buffer_pos_t RingBuffer::write(const uint8_t c) {
  40. const ring_buffer_pos_t n = NEXT_INDEX(write_index, size);
  41. if (n != read_index) {
  42. this->data[write_index] = c;
  43. write_index = n;
  44. return 1;
  45. }
  46. // TODO: buffer is full, handle?
  47. return 0;
  48. }
  49. ring_buffer_pos_t RingBuffer::write(const uint8_t *buffer, ring_buffer_pos_t size) {
  50. ring_buffer_pos_t written = 0;
  51. for (ring_buffer_pos_t i = 0; i < size; i++) {
  52. written += write(buffer[i]);
  53. }
  54. return written;
  55. }
  56. int RingBuffer::available() {
  57. return (size - read_index + write_index) & (size - 1);
  58. }
  59. int RingBuffer::peek() {
  60. return available() ? data[read_index] : -1;
  61. }
  62. int RingBuffer::read() {
  63. if (available()) {
  64. const int ret = data[read_index];
  65. read_index = NEXT_INDEX(read_index, size);
  66. return ret;
  67. }
  68. return -1;
  69. }
  70. ring_buffer_pos_t RingBuffer::read(uint8_t *buffer) {
  71. ring_buffer_pos_t len = available();
  72. for(ring_buffer_pos_t i = 0; read_index != write_index; i++) {
  73. buffer[i] = data[read_index];
  74. read_index = NEXT_INDEX(read_index, size);
  75. }
  76. return len;
  77. }
  78. void RingBuffer::flush() { read_index = write_index; }
  79. // WebSocketSerial impl
  80. WebSocketSerial::WebSocketSerial()
  81. : rx_buffer(RingBuffer(RX_BUFFER_SIZE)),
  82. tx_buffer(RingBuffer(TX_BUFFER_SIZE))
  83. {}
  84. void WebSocketSerial::begin(const long baud_setting) {
  85. ws.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
  86. switch (type) {
  87. case WS_EVT_CONNECT: client->ping(); break; // client connected
  88. case WS_EVT_DISCONNECT: // client disconnected
  89. case WS_EVT_ERROR: // error was received from the other end
  90. case WS_EVT_PONG: break; // pong message was received (in response to a ping request maybe)
  91. case WS_EVT_DATA: { // data packet
  92. AwsFrameInfo * info = (AwsFrameInfo*)arg;
  93. if (info->opcode == WS_TEXT || info->message_opcode == WS_TEXT)
  94. this->rx_buffer.write(data, len);
  95. }
  96. }
  97. });
  98. server.addHandler(&ws);
  99. }
  100. void WebSocketSerial::end() { }
  101. int WebSocketSerial::peek() { return rx_buffer.peek(); }
  102. int WebSocketSerial::read() { return rx_buffer.read(); }
  103. int WebSocketSerial::available() { return rx_buffer.available(); }
  104. void WebSocketSerial::flush() { rx_buffer.flush(); }
  105. size_t WebSocketSerial::write(const uint8_t c) {
  106. size_t ret = tx_buffer.write(c);
  107. if (ret && c == '\n') {
  108. uint8_t tmp[TX_BUFFER_SIZE];
  109. ring_buffer_pos_t size = tx_buffer.read(tmp);
  110. ws.textAll(tmp, size);
  111. }
  112. return ret;
  113. }
  114. size_t WebSocketSerial::write(const uint8_t* buffer, size_t size) {
  115. size_t written = 0;
  116. for(size_t i = 0; i < size; i++) {
  117. written += write(buffer[i]);
  118. }
  119. return written;
  120. }
  121. void WebSocketSerial::flushTX() {
  122. // No need to do anything as there's no benefit to sending partial lines over the websocket connection.
  123. }
  124. #endif // WIFISUPPORT
  125. #endif // ARDUINO_ARCH_ESP32