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 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #ifdef ARDUINO_ARCH_ESP32
  23. #include "../../inc/MarlinConfig.h"
  24. #if ENABLED(WIFISUPPORT)
  25. #include "WebSocketSerial.h"
  26. #include "wifi.h"
  27. #include <AsyncTCP.h>
  28. #include <ESPAsyncWebServer.h>
  29. struct ring_buffer_r {
  30. unsigned char buffer[RX_BUFFER_SIZE];
  31. volatile ring_buffer_pos_t head, tail;
  32. };
  33. struct ring_buffer_t {
  34. unsigned char buffer[256];
  35. volatile uint8_t head, tail;
  36. };
  37. ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
  38. ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
  39. static bool _written;
  40. #if ENABLED(EMERGENCY_PARSER)
  41. static EmergencyParser::State emergency_state; // = EP_RESET
  42. #endif
  43. AsyncWebSocket ws("/ws"); // access at ws://[esp ip]/ws
  44. FORCE_INLINE int next_rx_index(const int i) { return (ring_buffer_pos_t)(i + 1) & (ring_buffer_pos_t)(RX_BUFFER_SIZE - 1); }
  45. FORCE_INLINE int next_tx_index(const int i) { return (ring_buffer_pos_t)(i + 1) & (ring_buffer_pos_t)(TX_BUFFER_SIZE - 1); }
  46. static void addToBuffer(uint8_t * const data, const size_t len) {
  47. for (size_t i = 0; i < len; i++) {
  48. ring_buffer_pos_t h = rx_buffer.head;
  49. const ring_buffer_pos_t t = rx_buffer.tail, n = next_rx_index(h);
  50. if (n != t) { rx_buffer.buffer[h] = data[i]; h = n; }
  51. // TODO: buffer is full, handle?
  52. rx_buffer.head = h;
  53. }
  54. }
  55. // Handle WebSocket event
  56. static void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
  57. switch (type) {
  58. case WS_EVT_CONNECT: client->ping(); break; // client connected
  59. case WS_EVT_DISCONNECT: // client disconnected
  60. case WS_EVT_ERROR: // error was received from the other end
  61. case WS_EVT_PONG: break; // pong message was received (in response to a ping request maybe)
  62. case WS_EVT_DATA: { // data packet
  63. AwsFrameInfo * info = (AwsFrameInfo*)arg;
  64. if (info->opcode == WS_TEXT || info->message_opcode == WS_TEXT)
  65. addToBuffer(data, len);
  66. }
  67. }
  68. }
  69. // Public Methods
  70. void WebSocketSerial::begin(const long baud_setting) {
  71. ws.onEvent(onEvent);
  72. server.addHandler(&ws); // attach AsyncWebSocket
  73. }
  74. void WebSocketSerial::end() { }
  75. int WebSocketSerial::peek(void) {
  76. const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
  77. return v;
  78. }
  79. int WebSocketSerial::read(void) {
  80. const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
  81. if (h == t) return -1; // Nothing to read? Return now
  82. const int v = rx_buffer.buffer[t];
  83. rx_buffer.tail = (ring_buffer_pos_t)(t + 1) & (RX_BUFFER_SIZE - 1); // Advance tail
  84. return v;
  85. }
  86. bool WebSocketSerial::available(void) {
  87. const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
  88. return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
  89. }
  90. void WebSocketSerial::flush(void) {
  91. ws.textAll("flush");
  92. rx_buffer.tail = rx_buffer.head;
  93. }
  94. #if TX_BUFFER_SIZE
  95. void WebSocketSerial::write(const uint8_t c) {
  96. _written = true;
  97. const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
  98. // Store new char. head is always safe to move
  99. tx_buffer.buffer[tx_buffer.head] = c;
  100. tx_buffer.head = i;
  101. if (c == '\n') {
  102. ws.textAll(tx_buffer.buffer, tx_buffer.head);
  103. tx_buffer.head = 0;
  104. }
  105. }
  106. void WebSocketSerial::flushTx(void) {
  107. ws.textAll("flushTx");
  108. if (!_written) return;
  109. }
  110. #else
  111. //void WebSocketSerial::write(const uint8_t c) { _written = true; }
  112. //void WebSocketSerial::flushTx(void) { if (!_written) return; }
  113. #endif
  114. /**
  115. * Imports from print.h
  116. */
  117. void WebSocketSerial::print(char c, int base) { print((long)c, base); }
  118. void WebSocketSerial::print(unsigned char b, int base) { print((unsigned long)b, base); }
  119. void WebSocketSerial::print(int n, int base) { print((long)n, base); }
  120. void WebSocketSerial::print(unsigned int n, int base) { print((unsigned long)n, base); }
  121. void WebSocketSerial::print(long n, int base) {
  122. if (base == 0)
  123. write(n);
  124. else if (base == 10) {
  125. if (n < 0) { print('-'); n = -n; }
  126. printNumber(n, 10);
  127. }
  128. else
  129. printNumber(n, base);
  130. }
  131. void WebSocketSerial::print(unsigned long n, int base) {
  132. if (base == 0) write(n); else printNumber(n, base);
  133. }
  134. void WebSocketSerial::print(double n, int digits) { printFloat(n, digits); }
  135. void WebSocketSerial::println(void) { print('\r'); print('\n'); }
  136. void WebSocketSerial::println(const String& s) { print(s); println(); }
  137. void WebSocketSerial::println(const char c[]) { print(c); println(); }
  138. void WebSocketSerial::println(char c, int base) { print(c, base); println(); }
  139. void WebSocketSerial::println(unsigned char b, int base) { print(b, base); println(); }
  140. void WebSocketSerial::println(int n, int base) { print(n, base); println(); }
  141. void WebSocketSerial::println(unsigned int n, int base) { print(n, base); println(); }
  142. void WebSocketSerial::println(long n, int base) { print(n, base); println(); }
  143. void WebSocketSerial::println(unsigned long n, int base) { print(n, base); println(); }
  144. void WebSocketSerial::println(double n, int digits) { print(n, digits); println(); }
  145. // Private Methods
  146. void WebSocketSerial::printNumber(unsigned long n, uint8_t base) {
  147. if (n) {
  148. unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
  149. int8_t i = 0;
  150. while (n) {
  151. buf[i++] = n % base;
  152. n /= base;
  153. }
  154. while (i--)
  155. print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
  156. }
  157. else
  158. print('0');
  159. }
  160. void WebSocketSerial::printFloat(double number, uint8_t digits) {
  161. // Handle negative numbers
  162. if (number < 0.0) { print('-'); number = -number; }
  163. // Round correctly so that print(1.999, 2) prints as "2.00"
  164. // Use a lookup table for performance
  165. constexpr double rounds[] = { 0.5, 0.05, 0.005, 0.0005, 0.00005, 0.000005, 0.0000005, 0.00000005 };
  166. number += rounds[digits];
  167. //number += pow(10, -(digits + 1)); // slower single-line equivalent
  168. // Extract the integer part of the number and print it
  169. unsigned long int_part = (unsigned long)number;
  170. print(int_part);
  171. // Print the decimal point, but only if there are digits beyond
  172. double remainder = number - (double)int_part;
  173. if (digits) {
  174. print('.');
  175. // Extract digits from the remainder one at a time
  176. while (digits--) {
  177. remainder *= 10.0;
  178. const int toPrint = int(remainder);
  179. print(toPrint);
  180. remainder -= toPrint;
  181. }
  182. }
  183. }
  184. #endif // WIFISUPPORT
  185. #endif // ARDUINO_ARCH_ESP32