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.

231 lines
6.8 KiB

6 years ago
6 years ago
  1. /*
  2. WiFiTelnetToSerial - Example Transparent UART to Telnet Server for esp8266
  3. Copyright (c) 2015 Hristo Gochkov. All rights reserved.
  4. This file is part of the ESP8266WiFi library for Arduino environment.
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. */
  17. #include <ESP8266WiFi.h>
  18. #include <algorithm> // std::min
  19. #ifndef STASSID
  20. #define STASSID "AirTies_Air5343"
  21. #define STAPSK "yigit007"
  22. #endif
  23. /*
  24. SWAP_PINS:
  25. 0: use Serial1 for logging (legacy example)
  26. 1: configure Hardware Serial port on RX:GPIO13 TX:GPIO15
  27. and use SoftwareSerial for logging on
  28. standard Serial pins RX:GPIO3 and TX:GPIO1
  29. */
  30. #define SWAP_PINS 0
  31. /*
  32. SERIAL_LOOPBACK
  33. 0: normal serial operations
  34. 1: RX-TX are internally connected (loopback)
  35. */
  36. #define SERIAL_LOOPBACK 0
  37. #define BAUD_SERIAL 115200
  38. #define BAUD_LOGGER 115200
  39. #define RXBUFFERSIZE 1024
  40. #define ONE 12
  41. #define TWO 14
  42. ////////////////////////////////////////////////////////////
  43. #if SERIAL_LOOPBACK
  44. #undef BAUD_SERIAL
  45. #define BAUD_SERIAL 3000000
  46. #include <esp8266_peri.h>
  47. #endif
  48. #if SWAP_PINS
  49. #include <SoftwareSerial.h>
  50. SoftwareSerial* logger = nullptr;
  51. #else
  52. #define logger (&Serial1)
  53. #endif
  54. #define STACK_PROTECTOR 512 // bytes
  55. //how many clients should be able to telnet to this ESP8266
  56. #define MAX_SRV_CLIENTS 2
  57. const char* ssid = STASSID;
  58. const char* password = STAPSK;
  59. const int port = 23;
  60. int led_one = 0;
  61. int led_two = 0;
  62. WiFiServer server(port);
  63. WiFiClient serverClients[MAX_SRV_CLIENTS];
  64. void setup() {
  65. Serial.begin(BAUD_SERIAL);
  66. Serial.setRxBufferSize(RXBUFFERSIZE);
  67. #if SWAP_PINS
  68. Serial.swap();
  69. // Hardware serial is now on RX:GPIO13 TX:GPIO15
  70. // use SoftwareSerial on regular RX(3)/TX(1) for logging
  71. logger = new SoftwareSerial(3, 1);
  72. logger->begin(BAUD_LOGGER);
  73. logger->println("\n\nUsing SoftwareSerial for logging");
  74. #else
  75. logger->begin(BAUD_LOGGER);
  76. logger->println("\n\nUsing Serial1 for logging");
  77. #endif
  78. logger->println(ESP.getFullVersion());
  79. logger->printf("Serial baud: %d (8n1: %d KB/s)\n", BAUD_SERIAL, BAUD_SERIAL * 8 / 10 / 1024);
  80. logger->printf("Serial receive buffer size: %d bytes\n", RXBUFFERSIZE);
  81. #if SERIAL_LOOPBACK
  82. USC0(0) |= (1 << UCLBE); // incomplete HardwareSerial API
  83. logger->println("Serial Internal Loopback enabled");
  84. #endif
  85. WiFi.mode(WIFI_STA);
  86. WiFi.begin(ssid, password);
  87. logger->print("\nConnecting to ");
  88. logger->println(ssid);
  89. while (WiFi.status() != WL_CONNECTED) {
  90. logger->print('.');
  91. delay(500);
  92. }
  93. logger->println();
  94. logger->print("connected, address=");
  95. logger->println(WiFi.localIP());
  96. //start server
  97. server.begin();
  98. server.setNoDelay(true);
  99. logger->print("Ready! Use 'telnet ");
  100. logger->print(WiFi.localIP());
  101. logger->printf(" %d' to connect\n", port);
  102. }
  103. void loop() {
  104. //check if there are any new clients
  105. if (server.hasClient()) {
  106. //find free/disconnected spot
  107. int i;
  108. for (i = 0; i < MAX_SRV_CLIENTS; i++)
  109. if (!serverClients[i]) { // equivalent to !serverClients[i].connected()
  110. serverClients[i] = server.available();
  111. logger->print("New client: index ");
  112. logger->print(i);
  113. break;
  114. }
  115. //no free/disconnected spot so reject
  116. if (i == MAX_SRV_CLIENTS) {
  117. server.available().println("busy");
  118. // hints: server.available() is a WiFiClient with short-term scope
  119. // when out of scope, a WiFiClient will
  120. // - flush() - all data will be sent
  121. // - stop() - automatically too
  122. logger->printf("server is busy with %d active connections\n", MAX_SRV_CLIENTS);
  123. }
  124. }
  125. //check TCP clients for data
  126. #if 1
  127. // Incredibly, this code is faster than the bufferred one below - #4620 is needed
  128. // loopback/3000000baud average 348KB/s
  129. int val = 0;
  130. for (int i = 0; i < MAX_SRV_CLIENTS; i++)
  131. while (serverClients[i].available() && Serial.availableForWrite() > 0) {
  132. // working char by char is not very efficient
  133. char telnet_val = serverClients[i].read();
  134. if (telnet_val == 48) { // 0
  135. if (val++ == 0) {
  136. led_one = 0;
  137. } else {
  138. led_two = 0;
  139. }
  140. } else if (telnet_val == 49) { // 1
  141. if (val++ == 0) {
  142. led_one = 1;
  143. } else {
  144. led_two = 1;
  145. }
  146. }
  147. Serial.write(telnet_val);
  148. }
  149. #else
  150. // loopback/3000000baud average: 312KB/s
  151. for (int i = 0; i < MAX_SRV_CLIENTS; i++)
  152. while (serverClients[i].available() && Serial.availableForWrite() > 0) {
  153. size_t maxToSerial = std::min(serverClients[i].available(), Serial.availableForWrite());
  154. maxToSerial = std::min(maxToSerial, (size_t)STACK_PROTECTOR);
  155. uint8_t buf[maxToSerial];
  156. size_t tcp_got = serverClients[i].read(buf, maxToSerial);
  157. size_t serial_sent = Serial.write(buf, tcp_got);
  158. if (serial_sent != maxToSerial) {
  159. logger->printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxToSerial, tcp_got, serial_sent);
  160. }
  161. }
  162. #endif
  163. digitalWrite(ONE, led_one);
  164. digitalWrite(TWO, led_two);
  165. // determine maximum output size "fair TCP use"
  166. // client.availableForWrite() returns 0 when !client.connected()
  167. size_t maxToTcp = 0;
  168. for (int i = 0; i < MAX_SRV_CLIENTS; i++)
  169. if (serverClients[i]) {
  170. size_t afw = serverClients[i].availableForWrite();
  171. if (afw) {
  172. if (!maxToTcp) {
  173. maxToTcp = afw;
  174. } else {
  175. maxToTcp = std::min(maxToTcp, afw);
  176. }
  177. } else {
  178. // warn but ignore congested clients
  179. logger->println("one client is congested");
  180. }
  181. }
  182. //check UART for data
  183. size_t len = std::min((size_t)Serial.available(), maxToTcp);
  184. len = std::min(len, (size_t)STACK_PROTECTOR);
  185. if (len) {
  186. uint8_t sbuf[len];
  187. size_t serial_got = Serial.readBytes(sbuf, len);
  188. // push UART data to all connected telnet clients
  189. for (int i = 0; i < MAX_SRV_CLIENTS; i++)
  190. // if client.availableForWrite() was 0 (congested)
  191. // and increased since then,
  192. // ensure write space is sufficient:
  193. if (serverClients[i].availableForWrite() >= serial_got) {
  194. size_t tcp_sent = serverClients[i].write(sbuf, serial_got);
  195. if (tcp_sent != len) {
  196. logger->printf("len mismatch: available:%zd serial-read:%zd tcp-write:%zd\n", len, serial_got, tcp_sent);
  197. }
  198. }
  199. }
  200. }