Advertisement
Astranome

NetTermESP32_9341

Jul 27th, 2020
327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.78 KB | None | 0 0
  1. /*
  2.   Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - www.fabgl.com
  3.   Copyright (c) 2019-2020 Fabrizio Di Vittorio.
  4.   All rights reserved.
  5.  
  6.   This file is part of FabGL Library.
  7.  
  8.   FabGL 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.   FabGL 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 FabGL.  If not, see <http://www.gnu.org/licenses/>.
  20.  */
  21.  
  22.  
  23. #include "fabgl.h"
  24.  
  25. #include <WiFi.h>
  26.  
  27. #include "network/ICMP.h"
  28.  
  29.  
  30.  
  31.  
  32. char const * AUTOEXEC = "info\r"
  33.                         "scan\r";
  34.  
  35.  
  36. enum class State { Prompt, PromptInput, UnknownCommand, Help, Info, Wifi, TelnetInit, Telnet, Scan, Ping, Reset };
  37.  
  38.  
  39. State        state = State::Prompt;
  40. WiFiClient   client;
  41. char const * currentScript = nullptr;
  42. bool         error = false;
  43.  
  44. fabgl::ILI9341Controller DisplayController;
  45. //fabgl::VGATextController DisplayController;
  46. fabgl::PS2Controller     PS2Controller;
  47. fabgl::Terminal          Terminal;
  48. fabgl::LineEditor        LineEditor(&Terminal);
  49.  
  50. #define TFT_SCK    18
  51. #define TFT_MOSI   23
  52. #define TFT_CS     5
  53. #define TFT_DC     22
  54. #define TFT_RESET  21
  55. #define TFT_SPIBUS VSPI_HOST
  56.  
  57.  
  58. void exe_info()
  59. {
  60.   Terminal.write("\e[37m* * FabGL - Network VT/ANSI Terminal\r\n");
  61.   Terminal.write("\e[34m* * 2019-2020 by Fabrizio Di Vittorio - www.fabgl.com\e[32m\r\n\n");
  62.   Terminal.printf("\e[32mScreen Size        :\e[33m %d x %d\r\n", DisplayController.getScreenWidth(), DisplayController.getScreenHeight());
  63.   Terminal.printf("\e[32mTerminal Size      :\e[33m %d x %d\r\n", Terminal.getColumns(), Terminal.getRows());
  64.   Terminal.printf("\e[32mKeyboard           :\e[33m %s\r\n", PS2Controller.keyboard()->isKeyboardAvailable() ? "OK" : "Error");
  65.   Terminal.printf("\e[32mFree DMA Memory    :\e[33m %d\r\n", heap_caps_get_free_size(MALLOC_CAP_DMA));
  66.   Terminal.printf("\e[32mFree 32 bit Memory :\e[33m %d\r\n", heap_caps_get_free_size(MALLOC_CAP_32BIT));
  67.   if (WiFi.status() == WL_CONNECTED) {
  68.     Terminal.printf("\e[32mWiFi SSID          :\e[33m %s\r\n", WiFi.SSID().c_str());
  69.     Terminal.printf("\e[32mCurrent IP         :\e[33m %s\r\n", WiFi.localIP().toString().c_str());
  70.   }
  71.   Terminal.write("\n\e[32mType \e[33mhelp\e[32m to print all available commands.\r\n");
  72.   error = false;
  73.   state = State::Prompt;
  74. }
  75.  
  76.  
  77. void exe_help()
  78. {
  79.   Terminal.write("\e[33mhelp\e[92m\r\n");
  80.   Terminal.write("\e[37m  Shows this help.\r\n");
  81.   Terminal.write("\e[33minfo\r\n");
  82.   Terminal.write("\e[37m  Shows system info.\r\n");
  83.   Terminal.write("\e[33mscan\r\n");
  84.   Terminal.write("\e[37m  Scan for WiFi networks.\r\n");
  85.   Terminal.write("\e[33mwifi [SSID PASSWORD]\r\n");
  86.   Terminal.write("\e[37m  Connect to SSID using PASSWORD.\r\n");
  87.   Terminal.write("\e[37m  Example:\r\n");
  88.   Terminal.write("\e[37m    wifi MyWifi MyPassword\r\n");
  89.   Terminal.write("\e[33mtelnet HOST [PORT]\r\n");
  90.   Terminal.write("\e[37m  Open telnet session with HOST (IP or host name) using PORT.\r\n");
  91.   Terminal.write("\e[37m  Example:\r\n");
  92.   Terminal.write("\e[37m    telnet towel.blinkenlights.nl\e[32m\r\n");
  93.   Terminal.write("\e[33mreboot\r\n");
  94.   Terminal.write("\e[37m  Restart the system.\e[32m\r\n");
  95.   error = false;
  96.   state = State::Prompt;
  97. }
  98.  
  99.  
  100. void decode_command()
  101. {
  102.   auto inputLine = LineEditor.get();
  103.   if (*inputLine == 0)
  104.     state = State::Prompt;
  105.   else if (strncmp(inputLine, "help", 4) == 0)
  106.     state = State::Help;
  107.   else if (strncmp(inputLine, "info", 4) == 0)
  108.     state = State::Info;
  109.   else if (strncmp(inputLine, "wifi", 4) == 0)
  110.     state = State::Wifi;
  111.   else if (strncmp(inputLine, "telnet", 6) == 0)
  112.     state = State::TelnetInit;
  113.   else if (strncmp(inputLine, "scan", 4) == 0)
  114.     state = State::Scan;
  115.   else if (strncmp(inputLine, "ping", 4) == 0)
  116.     state = State::Ping;
  117.   else if (strncmp(inputLine, "reboot", 4) == 0)
  118.     state = State::Reset;
  119.   else
  120.     state = State::UnknownCommand;
  121. }
  122.  
  123.  
  124. void exe_prompt()
  125. {
  126.   if (currentScript) {
  127.     // process commands from script
  128.     if (*currentScript == 0 || error) {
  129.       // end of script, return to prompt
  130.       currentScript = nullptr;
  131.       state = State::Prompt;
  132.     } else {
  133.       // execute current line and move to the next one
  134.       int linelen = strchr(currentScript, '\r') - currentScript;
  135.       LineEditor.setText(currentScript, linelen);
  136.       currentScript += linelen + 1;
  137.       decode_command();
  138.     }
  139.   } else {
  140.     // process commands from keyboard
  141.     Terminal.write(">");
  142.     state = State::PromptInput;
  143.   }
  144. }
  145.  
  146.  
  147. void exe_promptInput()
  148. {
  149.   LineEditor.setText("");
  150.   LineEditor.edit();
  151.   decode_command();
  152. }
  153.  
  154.  
  155. void exe_scan()
  156. {
  157.   static char const * ENC2STR[] = { "Open", "WEP", "WPA-PSK", "WPA2-PSK", "WPA/WPA2-PSK", "WPA-ENTERPRISE" };
  158.   Terminal.write("Scanning...");
  159.   Terminal.flush();
  160.   fabgl::suspendInterrupts();
  161.   int networksCount = WiFi.scanNetworks();
  162.   fabgl::resumeInterrupts();
  163.   Terminal.printf("%d network(s) found\r\n", networksCount);
  164.   if (networksCount) {
  165.     Terminal.write   ("\e[90m #\e[4GSSID\e[45GRSSI\e[55GCh\e[60GEncryption\e[32m\r\n");
  166.     for (int i = 0; i < networksCount; ++i)
  167.       Terminal.printf("\e[33m %d\e[4G%s\e[33m\e[45G%d dBm\e[55G%d\e[60G%s\e[32m\r\n", i + 1, WiFi.SSID(i).c_str(), WiFi.RSSI(i), WiFi.channel(i), ENC2STR[WiFi.encryptionType(i)]);
  168.   }
  169.   WiFi.scanDelete();
  170.   error = false;
  171.   state = State::Prompt;
  172. }
  173.  
  174.  
  175. void exe_wifi()
  176. {
  177.   static const int MAX_SSID_SIZE = 32;
  178.   static const int MAX_PSW_SIZE  = 32;
  179.   char ssid[MAX_SSID_SIZE + 1];
  180.   char psw[MAX_PSW_SIZE + 1] = {0};
  181.   error = true;
  182.   auto inputLine = LineEditor.get();
  183.   if (sscanf(inputLine, "wifi %32s %32s", ssid, psw) >= 1) {
  184.     Terminal.write("Connecting WiFi...");
  185.     Terminal.flush();
  186.     AutoSuspendInterrupts autoInt;
  187.     WiFi.disconnect(true, true);
  188.     for (int i = 0; i < 2; ++i) {
  189.       WiFi.begin(ssid, psw);
  190.       if (WiFi.waitForConnectResult() == WL_CONNECTED)
  191.         break;
  192.       WiFi.disconnect(true, true);
  193.     }
  194.     if (WiFi.status() == WL_CONNECTED) {
  195.       Terminal.printf("connected to %s, IP is %s\r\n", WiFi.SSID().c_str(), WiFi.localIP().toString().c_str());
  196.       error = false;
  197.     } else {
  198.       Terminal.write("failed!\r\n");
  199.     }
  200.   }
  201.   state = State::Prompt;
  202. }
  203.  
  204.  
  205. void exe_telnetInit()
  206. {
  207.   static const int MAX_HOST_SIZE = 32;
  208.   char host[MAX_HOST_SIZE + 1];
  209.   int port;
  210.   error = true;
  211.   auto inputLine = LineEditor.get();
  212.   int pCount = sscanf(inputLine, "telnet %32s %d", host, &port);
  213.   if (pCount > 0) {
  214.     if (pCount == 1)
  215.       port = 23;
  216.     Terminal.printf("Trying %s...\r\n", host);
  217.     if (client.connect(host, port)) {
  218.       Terminal.printf("Connected to %s\r\n", host);
  219.       error = false;
  220.       state = State::Telnet;
  221.     } else {
  222.       Terminal.write("Unable to connect to remote host\r\n");
  223.       state = State::Prompt;
  224.     }
  225.   } else {
  226.     Terminal.write("Mistake\r\n");
  227.     state = State::Prompt;
  228.   }
  229. }
  230.  
  231.  
  232. int clientWaitForChar()
  233. {
  234.   // not so good...:-)
  235.   while (!client.available())
  236.     ;
  237.   return client.read();
  238. }
  239.  
  240.  
  241. void exe_telnet()
  242. {
  243.   // process data from remote host (up to 1024 codes at the time)
  244.   for (int i = 0; client.available() && i < 1024; ++i) {
  245.     int c = client.read();
  246.     if (c == 0xFF) {
  247.       // IAC (Interpret As Command)
  248.       uint8_t cmd = clientWaitForChar();
  249.       uint8_t opt = clientWaitForChar();
  250.       if (cmd == 0xFD && opt == 0x1F) {
  251.         // DO WINDOWSIZE
  252.         client.write("\xFF\xFB\x1F", 3); // IAC WILL WINDOWSIZE
  253.         client.write("\xFF\xFA\x1F" "\x00\x50\x00\x19" "\xFF\xF0", 9);  // IAC SB WINDOWSIZE 0 80 0 25 IAC SE
  254.       } else if (cmd == 0xFD && opt == 0x18) {
  255.         // DO TERMINALTYPE
  256.         client.write("\xFF\xFB\x18", 3); // IAC WILL TERMINALTYPE
  257.       } else if (cmd == 0xFA && opt == 0x18) {
  258.         // SB TERMINALTYPE
  259.         c = clientWaitForChar();  // bypass '1'
  260.         c = clientWaitForChar();  // bypass IAC
  261.         c = clientWaitForChar();  // bypass SE
  262.         client.write("\xFF\xFA\x18\x00" "wsvt25" "\xFF\xF0", 12); // IAC SB TERMINALTYPE 0 "...." IAC SE
  263.       } else {
  264.         uint8_t pck[3] = {0xFF, 0, opt};
  265.         if (cmd == 0xFD)  // DO -> WONT
  266.           pck[1] = 0xFC;
  267.         else if (cmd == 0xFB) // WILL -> DO
  268.           pck[1] = 0xFD;
  269.         client.write(pck, 3);
  270.       }
  271.     } else {
  272.       Terminal.write(c);
  273.     }
  274.   }
  275.   // process data from terminal (keyboard)
  276.   while (Terminal.available()) {
  277.     client.write( Terminal.read() );
  278.   }
  279.   // return to prompt?
  280.   if (!client.connected()) {
  281.     client.stop();
  282.     state = State::Prompt;
  283.   }
  284. }
  285.  
  286.  
  287. void exe_ping()
  288. {
  289.   char host[64];
  290.   auto inputLine = LineEditor.get();
  291.   int pcount = sscanf(inputLine, "ping %s", host);
  292.   if (pcount > 0) {
  293.     int sent = 0, recv = 0;
  294.     fabgl::ICMP icmp;
  295.     while (true) {
  296.  
  297.       // CTRL-C ?
  298.       if (Terminal.available() && Terminal.read() == 0x03)
  299.         break;
  300.  
  301.       int t = icmp.ping(host);
  302.       if (t >= 0) {
  303.         Terminal.printf("%d bytes from %s: icmp_seq=%d ttl=%d time=%.3f ms\r\n", icmp.receivedBytes(), icmp.hostIP().toString().c_str(), icmp.receivedSeq(), icmp.receivedTTL(), (double)t/1000.0);
  304.         delay(1000);
  305.         ++recv;
  306.       } else if (t == -2) {
  307.         Terminal.printf("Cannot resolve %s: Unknown host\r\n", host);
  308.         break;
  309.       } else {
  310.         Terminal.printf("Request timeout for icmp_seq %d\r\n", icmp.receivedSeq());
  311.       }
  312.       ++sent;
  313.  
  314.     }
  315.     if (sent > 0) {
  316.       Terminal.printf("--- %s ping statistics ---\r\n", host);
  317.       Terminal.printf("%d packets transmitted, %d packets received, %.1f%% packet loss\r\n", sent, recv, (double)(sent - recv) / sent * 100.0);
  318.     }
  319.   }
  320.   state = State::Prompt;
  321. }
  322.  
  323.  
  324. void setup()
  325. {
  326.   //Serial.begin(115200); // DEBUG ONLY
  327.  
  328.   PS2Controller.begin(PS2Preset::KeyboardPort0);
  329.  
  330.  // DisplayController.begin();
  331.  // DisplayController.setResolution();
  332.   DisplayController.begin(TFT_SCK, TFT_MOSI, TFT_DC, TFT_RESET, TFT_CS, TFT_SPIBUS);
  333.   DisplayController.setResolution(TFT_240x320);
  334.   DisplayController.setOrientation(fabgl::TFTOrientation::Rotate90);
  335.  
  336.   Terminal.begin(&DisplayController);
  337.   Terminal.connectLocally();      // to use Terminal.read(), available(), etc..
  338.   //Terminal.setLogStream(Serial);  // DEBUG ONLY
  339.  
  340.   Terminal.loadFont(&fabgl::FONT_6x10);
  341.  
  342.   Terminal.setBackgroundColor(Color::Black);
  343.   Terminal.setForegroundColor(Color::BrightGreen);
  344.   Terminal.clear();
  345.  
  346.   // just to align the screen
  347.   //Terminal.write("1234567890123456789012345678901234567890123456789012345678901234567890123456789X\r\n");
  348.  
  349.   Terminal.enableCursor(true);
  350.  
  351.   currentScript = AUTOEXEC;
  352. }
  353.  
  354.  
  355. void loop()
  356. {
  357.   switch (state) {
  358.  
  359.     case State::Prompt:
  360.       exe_prompt();
  361.       break;
  362.  
  363.     case State::PromptInput:
  364.       exe_promptInput();
  365.       break;
  366.  
  367.     case State::Help:
  368.       exe_help();
  369.       break;
  370.  
  371.     case State::Info:
  372.       exe_info();
  373.       break;
  374.  
  375.     case State::Wifi:
  376.       exe_wifi();
  377.       break;
  378.  
  379.     case State::TelnetInit:
  380.       exe_telnetInit();
  381.       break;
  382.  
  383.     case State::Telnet:
  384.       exe_telnet();
  385.       break;
  386.  
  387.     case State::Scan:
  388.       exe_scan();
  389.       break;
  390.  
  391.     case State::Ping:
  392.       exe_ping();
  393.       break;
  394.  
  395.     case State::Reset:
  396.       ESP.restart();
  397.       break;
  398.  
  399.     case State::UnknownCommand:
  400.       Terminal.write("\r\nMistake\r\n");
  401.       state = State::Prompt;
  402.       break;
  403.  
  404.     default:
  405.       Terminal.write("\r\nNot Implemeted\r\n");
  406.       state = State::Prompt;
  407.       break;
  408.  
  409.   }
  410. }
  411.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement