Esta es la tercera variación del tema IP KVM, esta vez el concepto ha sido completamente revisado, comencemos a construir algo nuevo. Habrá muchas cosas interesantes, no salgas de la pantalla. Aparecerá otro dispositivo inusual, descartaremos casi todos los componentes antiguos, volveremos a nuestro arduino nativo y haremos de hacker.
Para aquellos que se acaban de unir, un resumen de episodios anteriores:
- Primer articulo
Recolectó IP KVM en Arduino y Raspberry Pi, resultó costoso y con baja calidad de video. - Segundo articulo
OrangePI y Atmega16u2, aprendieron a bajo precio, pero la calidad de imagen sigue siendo desagradable.
Y finalmente, en este artículo, se solucionarán todas las desventajas de las anteriores. Se hará especial hincapié en la reducción máxima en el costo de los componentes.
Por tradición, consideramos los componentes del dispositivo ensamblado:1. Nuestro viejo amigo Atmega16u2:
Este es el único componente que se moverá de los artículos anteriores.
2. El notorio ESP8266, en este caso ESP8266-12e:
Puede usar otra versión del ESP8266, solo debe tener en cuenta el número y la ubicación de los puertos.
3. Y, de hecho, el héroe de la ocasión LKV373A

Gracias a este dispositivo, fue posible transmitir video a través de una red local con alta
resolución hasta full-HD.
El plan de acción es el siguiente:
- Ocultar y buscar: Estamos buscando LKV373A donde se escondió en la red bajo qué dirección IP
- Juego de hackers: complete el firmware, restablezca las contraseñas y configure LKV373A
- Hacer nuevos amigos: ESP8266, Arduino IDE y fotos divertidas
- El final de la celebración. Conectamos todos los componentes y transmitimos pulsaciones de teclas a través de telnet
Fondo LKV373A
¡Entonces comencemos! Dispositivo extensor LKV373A o HDMI para capturar imágenes directamente desde el puerto hdmi y transmitir a la red local, estos dispositivos también se denominan extensores hdmi. Según lo planeado por los fabricantes, un conjunto de tales dispositivos debe consistir en un transmisor (transmisor) y un receptor (receptor), designación TX y RX, respectivamente. Deben usarse, probablemente, para brindarle al fabricante más ganancias, solo en pares. Pero había un hombre, bajo el apodo de Danman, aquí hay un
enlace a su blog, que estaba interesado en cómo funciona. Abrió Wireshark, olfateó el tráfico transmitido por el dispositivo TX, ¿qué resultó ser?
La transmisión de video se transmite sin cifrado, y con VLC Player, puede verla sin demasiado esfuerzo. Pero no se detuvo allí, "sintió": sacó la interfaz web, TTL, telnet e incluso sacó el firmware con el programador. Él habló sobre esto en detalle en su blog. El firmware que nos interesa en primer lugar también se cargó allí: IPTV_TX_PKG_v4_0_0_0_20160427.PKG. En este firmware, la interfaz web con configuraciones avanzadas, y no como la estándar, solo tiene el botón de actualización. Además, este firmware tiene un telnet con muchos comandos para configurar. Es con este firmware que reconfiguramos el extensor HDMI para nuestras tareas. Publiqué el firmware y todo lo que necesitaba en github, aquí está el
enlace , lo necesitaremos más tarde, pero por ahora terminamos con la teoría. Pasemos a practicar.
Transmisor
Estamos buscando LKV373A en la red
Caí en manos del mismo extensor que Danman (y). ¡Todo lo que se describirá a continuación es adecuado específicamente para el extensor HDMI LKV373A versión V3.0!
Conectamos el LKV373A a la red local, enciende la alimentación. Ahora intentemos asegurarnos de que el dispositivo sea visible en la red
ping 192.168.1.238
.
192.168.1.238 es la dirección IP predeterminada. Si el extensor no cambia la dirección del firmware anterior, independientemente de si hay un servidor DHCP en la red o no. Las versiones de firmware más nuevas usan IP de manera predeterminada solo si el dispositivo no pudo obtener una dirección de DHCP. Si recibió una respuesta al ping, continúe. De lo contrario, no se desespere, intente conectar el extensor directamente al puerto LAN de la computadora y use el sniffer.
Intermitente
HDMI Extender encontrado, pasar al firmware.
Vayamos al
github y descarguemos todo lo que se presenta allí. Ahora abra la interfaz web del extensor a través de un navegador y vea la siguiente imagen:

Haga clic en "Examinar ...", seleccione el firmware, un archivo llamado IPTV_TX_PKG_v4_0_0_0_20160427.PKG, y haga clic en "Actualizar". Tadam! El firmware está completo, ahora conéctese al LKV373A por telnet para restablecer la contraseña.
El comando para conectarse se parecerá a Telnet 192.168.1.238 9999, donde 9999 es el puerto para conectarse. CEP advierte: la dirección obtenida de DHCP se puede encontrar utilizando un escáner de red.
Conectarse a través de telnet
Al conectarse, debería aparecer el siguiente mensaje:
============================== ========IPTV TX Server======== ============================== input>
Escribimos
list
. En respuesta, obtenemos una lista de comandos:
============================== ========IPTV TX Server======== ============================== input>list set_group_id get_group_id set_dhcp get_dhcp set_uart_baudrate get_uart_baudrate set_static_ip get_static_ip set_mac_address get_mac_address get_lan_status get_hdcp get_video_lock get_ip_config set_session_key set_device_name get_device_name set_video_bitrate get_video_bitrate set_downscale_mode get_downscale_mode set_video_out_mode get_video_out_mode set_streaming_mode get_streaming_mode get_fw_version get_company_id factory_reset reboot list exit
Para restablecer todas las configuraciones y contraseñas, use el comando
factory_reset
. Escribimos un comando, presionamos enter y obtenemos esta imagen:
input>factory_reset Processing factory reset! System will reboot after few seconds! Connection closed by foreign host.
Interfaz web
Ahora podemos configurar el dispositivo como lo necesitemos. Vayamos a la interfaz web. Utilizamos el inicio de sesión estándar: contraseña de administrador: 123456 y aquí está, la interfaz web "codiciada" con configuraciones adicionales:

Aunque las oportunidades en la interfaz web han aumentado, aún no son suficientes para nuestros propósitos. Particularmente faltan configuraciones más libres en términos de transmisión, está codificado, lejos de ser el más conveniente, una lista de direcciones IP a las que puede transmitir. Por supuesto, hay una multidifusión, pero es mejor dejarla para televisión. Se pueden eludir las limitaciones, más sobre eso más adelante.
Entonces, encontraron el dispositivo en la red, lo enrollaron y restablecieron las contraseñas. El transmisor está casi listo para pasar al receptor.
Receptor
Decidamos el dispositivo bajo el control de qué sistema operativo transmitiremos la transmisión. No creo que experimentes el tormento de elección, solo hay dos opciones:
Ventanas
Para Windows, probé varios jugadores, pero los resultados fueron más o menos. Al capturar y luego reproducir una transmisión de video, aparece un retraso, que depende principalmente del reproductor que reproduce la transmisión. En varios jugadores, el retraso varió de un segundo a cinco o más. Lo mejor de todo, en Windows, VLC Player demostró ser.
Vayamos a los negocios. Inicie VLC Player, desde la parte superior en el menú desplegable "Medios", seleccione "Abrir URL ..." en el campo de dirección de red, escriba
udp://@:5004
, ponga un toque en la casilla de verificación "Mostrar configuración avanzada" y coloque su valor en el campo "Almacenamiento en caché", Este parámetro se determina individualmente. Cuanto menor sea el valor en este campo, menor será el retraso, pero un valor demasiado pequeño puede conducir a "artefactos" y caídas de trama, todo dependerá de la infraestructura de red local. Los mejores resultados que pude lograr fueron un retraso de aproximadamente un segundo. En Linux, los resultados fueron mucho mejores alrededor de 200-300 milisegundos.
Linux
Como muestra la práctica, los mejores resultados se obtienen utilizando una combinación de programas socat y mplayer. Ubuntu está instalado en mi computadora, por lo que el comando para instalar socat se verá así:
sudo apt-get install socat
Mplayer se instala de manera similar:
sudo apt-get install mplayer
Bueno, y sigue el consejo de Danman:
sudo iptables -t raw -A PREROUTING -p udp -m length --length 28 -j DROP
Este comando es necesario para eliminar los llamados "paquetes UDP de longitud cero" de la secuencia: paquetes de tamaño cero que "obstruyen" la secuencia.
Ir a vivir!
El receptor está listo, ¡puedes comenzar la transmisión! Tecleamos la consola de la computadora receptora
ifconfig
o
ipconfig
, dependiendo del sistema operativo, recordamos la dirección IP del receptor y regresamos a la interfaz web del transmisor. Abriremos la interfaz web, si ya la cerramos, ingrese el nombre de usuario, la contraseña y escriba directamente en la barra de direcciones del navegador:
http:
Sustituya sus direcciones IP y presione enter. Esta línea configurará el extensor HDMI para transmitir el video capturado a la dirección IP elegida y apagará la multidifusión.
Iniciamos VLC en Windows. O en el terminal de Linux escribimos:
socat UDP-RECV:5004 - | mplayer –
Abra Cadabra! Y aquí está nuestro escritorio en vivo, o no el nuestro.

Entonces, con algunos métodos de hackers, forzamos al dispositivo a hacer lo que necesitábamos.
Con la transferencia de video resuelta, vaya al control remoto.
Transferencia de control
Selección de componentes
Porque El costo de HDMI Extender es bajo, alrededor de 1800 rublos, y también debido a los comentarios que, dicen, un poco caros, presenté el eslogan: "¡Dale IP KVM por 2000 rublos!". El tipo de cambio del rublo afectará en gran medida la fidelidad de esta declaración, pero no hablemos de cosas tristes, quiero creer en un futuro brillante. Para lograr el objetivo necesitaremos elementos muy baratos, mi elección recayó en el ESP8266 como controlador, y de todos modos Atmega (16/8/32) u2 como actuador.
Por supuesto, puede considerar a otros candidatos para el papel de un dispositivo ejecutivo (teclado). El firmware que emula el teclado está escrito en la biblioteca LUFA (más o menos). Esta biblioteca se puede utilizar para toda la familia AVR con conectividad USB. De ello se deduce que, como un emulador de teclado, puede recoger, posiblemente más barato, microcontrolador. Esta es información para consideración, pero ahora continuamos.
Puede comprar el ESP8266 por aproximadamente 90 rublos, Atmega (16/8/32) u2 por aproximadamente 100 rublos, e incluso más barato si toma pequeños lotes de 5 o más piezas. Por supuesto, se necesitarán consumibles para flejar microcontroladores, pero su costo es extremadamente pequeño, por lo que no los consideraré.
ESP8266
Este milagro de la industria china no necesita presentación, por lo tanto, solo diré que en este proyecto utilicé la versión de ESP8266-12e. Por supuesto, puede usar otras versiones, solo necesita considerar la ubicación de los puertos, porque en esta versión, uno de los puertos ESP8266 se usa para encender el Atmega (8/16/32) u2, se indicará en el siguiente diagrama.
Firmware
El firmware para ESP8266 está escrito en el entorno ArduinoIDE, así que descarguemos la última versión
del sitio del desarrollador . A continuación, agregue soporte para ESP8266: la forma más fácil se puede encontrar en este
enlace . En la misma página, puede encontrar mucha información útil, como la conexión de alimentación y TTL. Para aquellos que no están actualizados, ¡el ESP8266 usa
estrictamente 3.3 voltios! Si no confía en sus propias habilidades, es mejor usar una opción de placa adaptada para USB, como NodeMCU:

Si todo está listo, abra ArduinoIDE y copie mi boceto:
Bosquejo #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <SoftwareSerial.h> #include <HIDKeyboard.h> #define MAX_SRV_CLIENTS 3 HIDKeyboard keyboard; const char* host = "esp8266"; const char* ssid = ""; const char* pass = ""; int rebootdev = 0; int modeswitch = 0; // , ESP8266 #define Port1 15 #define Port2 14 #define Port3 12 #define Port4 4 #define Port5 5 // String ColorB1; String ColorB2; String ColorB3; String ColorB4; String ColorB5; ESP8266WebServer server(80); WiFiClient serverClients[MAX_SRV_CLIENTS]; const char* serverIndex = "<form method='POST' action='/update' enctype='multipart/form-data'><input type='file' name='update'><input type='submit' value='Update'></form><a href='/'>BACK</a>";//Update // void handleRedirect(){ String content = "<html><head><meta http-equiv='refresh' content='0;/'><head></html>"; server.send(200, "text/html", content); } // WI-FI void handleLogin(){ String msg = ""; if (server.hasArg("SSID") && server.hasArg("PASSAP")){ if ((server.arg("SSID") != NULL) && (server.arg("PASSAP") != NULL)){ String header = "HTTP/1.1 301 OK\r\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n"; server.sendContent(header); String web_ssid = server.arg("SSID"); String web_pass = server.arg("PASSAP"); ssid = web_ssid.c_str();// C pass = web_pass.c_str(); Serial.println(); Serial.print("SSID "); Serial.println(ssid); Serial.print("Pass "); Serial.println(pass); WiFi.begin(ssid, pass); digitalWrite(LED_BUILTIN, LOW); ESP.reset(); return; } msg = "Wrong ssid/password! try again."; Serial.println("Login Failed"); } String content = "<html><body><form action='/' method='POST'>Enter the access point name and password <br>";// SSID content += "Name AP:<input type='text' name='SSID' placeholder='SSID'><br>"; content += "Password:<input type='password' name='PASSAP' placeholder='password'><br><br>"; content += "<input type='submit' name='SUBMIT' value='Connect to WI-FI'></form><b><font color='red'>" + msg + "</font></b><br>"; content += "Firmware update <a href='/upload'>UPDATE</a></body></html>"; server.send(200, "text/html", content); } void handleNotFound(){ String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET)?"GET":"POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i=0; i<server.args(); i++){ message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); } // int controlPin(int UsePin){ if (UsePin > 0){ int StPort; if (digitalRead(UsePin) == 1) {// digitalWrite(UsePin, LOW); StPort = 0; } else { digitalWrite(UsePin, HIGH); StPort = 1; } digitalWrite(LED_BUILTIN, HIGH);// Serial.print("Port "); Serial.print(UsePin); Serial.print("="); Serial.println(StPort); delay(500); digitalWrite(LED_BUILTIN, LOW); return(StPort); } return(-1); } // int clientConnect(int Seconds){ Serial.print("connection "); for (int i=0; i <= Seconds; i++){ WiFi.begin(ssid, pass); digitalWrite(LED_BUILTIN, LOW); delay(250); digitalWrite(LED_BUILTIN, HIGH); delay(250); Serial.print(" "); Serial.print("."); if (WiFi.status() == WL_CONNECTED) return(0); } return(1); Serial.println(); } void setup(void){ Serial.begin(115200); delay(1000); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); //uint8_t i = 0; if (modeswitch == 0) WiFi.mode(WIFI_STA);// modeswitch = 0 Serial.println(); Serial.println(); if (clientConnect(30) != 0) modeswitch = 1;// if (modeswitch == 1){ Serial.println(""); Serial.println("WiFi switch AP mode"); //WiFi.mode(WIFI_AP_STA); + . WiFi.mode(WIFI_AP); WiFi.softAP("TD", "testtest"); Serial.print("AP mode ip adress "); Serial.println(WiFi.softAPIP()); digitalWrite(LED_BUILTIN, LOW); } if (modeswitch != 1){ WiFiServer server(23); Serial.println(); Serial.print("Client mod ip address: "); Serial.println(WiFi.localIP()); digitalWrite(LED_BUILTIN, LOW); } MDNS.begin(host); pinMode(Port1, OUTPUT); pinMode(Port2, OUTPUT); pinMode(Port3, OUTPUT); pinMode(Port4, OUTPUT); pinMode(Port5, OUTPUT); if (modeswitch == 1){ // server.on("/", handleLogin);// (SSID) // server.on("/upload", HTTP_GET, [](){ server.sendHeader("Connection", "close"); server.send(200, "text/html", serverIndex); }); server.on("/update", HTTP_POST, [](){ server.sendHeader("Connection", "close"); int uperror = Update.hasError(); Serial.printf("UPERR %u\nRebooting...\n",Update.hasError()); if (uperror == 0) server.send(200, "text/html", "Firmware update successfully <a href='/'>BACK</a>"); else server.send(200, "text/html", "Update error <a href='/'>BACK</a>"); ESP.restart(); },[](){ HTTPUpload& upload = server.upload(); if(upload.status == UPLOAD_FILE_START){ Serial.setDebugOutput(true); WiFiUDP::stopAll(); Serial.printf("Update: %s\n", upload.filename.c_str()); if (upload.filename == NULL) { Serial.printf("ERROR: zero file size"); server.send(200, "text/html", "<html> zero file size <a href='/upload'>BACK</a></html>"); return(-1); } uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; if(!Update.begin(maxSketchSpace)){//start with max available size Update.printError(Serial); } } else if(upload.status == UPLOAD_FILE_WRITE){ if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){ Update.printError(Serial); } } else if(upload.status == UPLOAD_FILE_END){ if(Update.end(true)){ //true to set the size to the current progress Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); } else { Update.printError(Serial); } Serial.setDebugOutput(false); } yield(); }); // server.on("/PoRt1", [] { controlPin(Port1); handleRedirect();// }); server.on("/PoRt2", [] { controlPin(Port2); handleRedirect(); }); server.on("/PoRt3", [] { controlPin(Port3); handleRedirect(); }); server.on("/PoRt4", [] { controlPin(Port4); handleRedirect(); }); server.on("/PoRt5", [] { controlPin(Port5); handleRedirect(); }); server.on("/reboot", [] { rebootdev = 1;// handleRedirect(); }); server.onNotFound(handleNotFound);// //server.begin(); MDNS.addService("http", "tcp", 80); Serial.println(); Serial.println("HTTP server started"); } server.begin(); } void loop(void){ uint8_t i; if (modeswitch == 1) server.handleClient(); delay(100); if (modeswitch != 1){ if (WiFi.status() != WL_CONNECTED) clientConnect(30); else { digitalWrite(5, HIGH);// ATMEGA16U2 digitalWrite(LED_BUILTIN, LOW); } } WiFiServer server(23); server.setNoDelay(true); server.begin(); keyboard.begin(); while(WiFi.status() == WL_CONNECTED) { if (server.hasClient()){ for(i = 0; i < MAX_SRV_CLIENTS; i++){ //find free/disconnected spot if (!serverClients[i] || !serverClients[i].connected()){ if(serverClients[i]) serverClients[i].stop(); serverClients[i] = server.available(); Serial.println("New client: "); Serial.print(i); continue; } } //no free/disconnected spot so reject WiFiClient serverClient = server.available(); serverClient.stop(); } //check clients for data for(i = 0; i < MAX_SRV_CLIENTS; i++){ if (serverClients[i] && serverClients[i].connected()){ if(serverClients[i].available()){ //get data from the telnet client and push it to the UART String bufkey; while(serverClients[i].available()) bufkey += (serverClients[i].read());// if (bufkey != 0) { bufkey = bufkey.substring(0, 8);// int key = bufkey.toInt();// switch (key){ case 277980: keyboard.pressSpecialKey(F1); break; case 277981: keyboard.pressSpecialKey(F2); break; case 277982: keyboard.pressSpecialKey(F3); break; case 277983: keyboard.pressSpecialKey(F4); break; case 27914953: keyboard.pressSpecialKey(F5); break; case 27914955: keyboard.pressSpecialKey(F6); break; case 27914956: keyboard.pressSpecialKey(F7); break; case 27914957: keyboard.pressSpecialKey(F8); break; case 27915048: keyboard.pressSpecialKey(F9); break; case 27915049: keyboard.pressSpecialKey(F10); break; case 27915051: keyboard.pressSpecialKey(F11); break; case 27915052: keyboard.pressSpecialKey(F12); break; case 1310: keyboard.pressSpecialKey(ENTER); break; case 130: keyboard.pressSpecialKey(ENTER); break; case 27: keyboard.pressSpecialKey(ESCAPE); break; case 8: keyboard.pressSpecialKey(BACKSPACE); break; case 9: keyboard.pressSpecialKey(TAB); break; case 32: keyboard.pressSpecialKey(SPACEBAR); break; case 27915012: keyboard.pressSpecialKey(INSERT); break; case 27914912: keyboard.pressSpecialKey(HOME); break; case 27915312: keyboard.pressSpecialKey(PAGEUP); break; case 27915212: keyboard.pressSpecialKey(END); break; case 27915412: keyboard.pressSpecialKey(PAGEDOWN); break; case 279167: keyboard.pressSpecialKey(RIGHTARROW); break; case 279168: keyboard.pressSpecialKey(LEFTARROW); break; case 279166: keyboard.pressSpecialKey(DOWNARROW); break; case 279165: keyboard.pressSpecialKey(UPARROW); break; case 127: keyboard.pressSpecialKey(DELETE); break; case 27915112: keyboard.pressSpecialKey(DELETE); break; case 4: keyboard.pressSpecialKey((LCTRL | ALT), DELETE); break; //CTRL+ALT+DELETE Ctrl + d case 6: keyboard.pressSpecialKey(ALT, F4); break; //alt+f4 Ctrl + f case 19: keyboard.pressSpecialKey(ALT | SHIFT); break;// Ctrl+s case 2: keyboard.pressSpecialKey(LCTRL | SHIFT); break;// Ctrl+b // case 17: controlPin(Port1); break;//Ctrl+q case 23: controlPin(Port2); break;//Ctrl+w case 5: controlPin(Port3); break;//Ctrl+e case 18: controlPin(Port4); break;//Ctrl+r case 20: controlPin(Port5); break;//Ctrl+t default: keyboard.pressKey(key); break;// } keyboard.releaseKey();// Serial.print(" string: "); Serial.print(key);// Serial.print(" KEY: "); Serial.write(bufkey.toInt()); bufkey = '0';// } } } } //check UART for data if(Serial.available()){ size_t len = Serial.available(); uint8_t sbuf[len]; Serial.readBytes(sbuf, len); //push UART data to all connected telnet clients for(i = 0; i < MAX_SRV_CLIENTS; i++){ if (serverClients[i] && serverClients[i].connected()){ serverClients[i].write(sbuf, len); delay(1); } } } } }
Conecte la biblioteca deseada:
Seleccione la pestaña "Boceto" → "Conectar biblioteca" → "Agregar biblioteca .ZIP". Seleccione la biblioteca llamada "UNO-HIDKeyboard-Library-master (mod) .zip", que se descargó del github. Compilamos y completamos el firmware. Para descargar el firmware, conecte el ESP8266 TTL, configure el puerto deseado en ArduinoIDE. La configuración debería verse así:

Para descargar el firmware, debe cortocircuitar el puerto GPIO0 a tierra y reiniciar el microcontrolador haciendo un cortocircuito en el puerto de restablecimiento a tierra también. No pintaré en detalle, para no inflar el artículo, Google lo ayudará.
La lógica del ESP8266 es la siguiente: cuando se aplica energía, el microcontrolador intenta conectarse a un punto de acceso Wi-Fi durante unos treinta segundos:
Si la conexión se realiza correctamente : abre el puerto 23, al que puede conectarse mediante telnet y transmitir pulsaciones de teclas. Además de las teclas, puede transferir combinaciones basadas en "Ctrl + tecla" que presionarán ciertas combinaciones. Por ejemplo, si pasa "Ctrl + d", la combinación CTRL + ALT + SUPR se presionará en la computadora administrada.
También hay combinaciones para controlar los puertos ESP8266, por ejemplo, puede conectar un relé y usar la combinación "Ctrl + q" para encender y apagar el relé, y así encender y apagar de forma remota la computadora administrada. Puede ver estas y otras combinaciones en la fuente.
Si falla : ESP8266 cambia al modo de punto de acceso con el nombre "TD", Contraseña "testtest" y abre una pequeña interfaz web, accesible en 192.168.4.1, donde puede configurar los ajustes para conectarse a través de WI-FI.

Por lo tanto, el dispositivo se puede conectar fácilmente a otro punto de acceso. Sí, aquí se esconde una mosca en la pomada, para el funcionamiento de nuestro IP KVM, necesitaremos un cable LAN y Wi-Fi. Tal será el costo de la baratura del dispositivo.
Tratamos con ESP8266, con Atmega16u2 todo está como en los artículos anteriores, flasheamos el programa Flip, el firmware está en el archivo descargado del github.
Conexión de componentes
Para la correcta conexión de los componentes, adjunto el circuito. Solo tenga en cuenta que este es un esquema condicional, sirve para mayor claridad y no pretende ser ideal. Todos son libres de "amueblarla" como quiera.

Permítanme explicar algunos puntos: el transistor en el diagrama es necesario para encender Atmega16u2 después de cargar el ESP8266, porque cuando enciende el ESP8266, la información de depuración se transmite a todos los puertos TX, y si Atmega16u2 está encendido y conectado a la computadora, se transmite un flujo de datos con el volumen del cual El conductor no puede hacer frente. No se sabe con certeza qué sucede en este momento, el búfer del controlador se desborda presumiblemente, el efecto es extremadamente desagradable: se presionan cientos de teclas, si se abre un editor de texto, se derrama un montón de galimatías, y todas las teclas de servicio se atascan y, como resultado, el trabajo con el teclado se vuelve imposible . Para evitar esto, el Atmega16u2 necesita ser encendido después de cargar el ESP8266. En el firmware se tiene en cuenta este momento.
Existe, por supuesto, una alternativa al esquema, pero esta es una opción para los ricos o los perezosos. Y, por cierto, esta opción no cancela lo anterior:

En la imagen, el Arduino UNO sin el chip Atmega328p está conectado a la contraparte china de NodeMCU. La línea de 3.3 voltios está conectada a la línea del mismo nivel de voltaje en el Arduino, así como la tierra y el pin GPIO2 (ESP8266) están conectados al pin TX en el Arduino.
Control final
Nos conectamos por telnet al puerto 23 y verificamos el rendimiento. Puede hacer esto: en Windows con el comando
telnet [ip- ESP8266]
.
En Linux será un poco más complicado:
El comando
telnet [ip- ESP8266]
luego debe presionar el carácter de control, el valor predeterminado es "Ctrl +]", el telnet debe pasar al modo de comando, luego presione "l" y "Enter". Con estas acciones, cambiaremos el telnet al modo de símbolo.
$ telnet 192.168.***.*** Trying 192.168.***.***... Connected to 192.168.***.***. Escape character is '^]'. ^] telnet> l
Todo está listo, podemos verificar el funcionamiento del dispositivo que creamos. Permítame recordarle las posibles combinaciones para presionar "Alt + Tab", "Ctrl + Alt + Supr" y etc. Se puede ver en el boceto. Eso es todo, la tercera encarnación KVM DIY IP está lista.
Para resumir
Pros:
- Probablemente la ventaja más importante es el precio, que resultó en 2000 rublos
- No debería haber ninguna queja sobre la calidad del video, puede transmitir hasta Full HD sin problemas
- La capacidad de ampliar la funcionalidad al agregar hasta cuatro relés u otros actuadores.
Contras:
- Necesita conectarse a través de Wi-Fi y cable LAN
- Cuando se usa con VGA, se requiere un adaptador, lo que naturalmente afectará el costo
En general, el dispositivo resultó ser digno de atención, por supuesto, no es un competidor para serializar KVM IP con todas sus "ventajas", pero gana mucho en precio. Y para uso doméstico, y tal vez no solo, es bastante adecuado.¡Me gustaría aprovechar esta oportunidad para agradecer al usuario DaylightIsBurning ! Este amable hombre sugirió la dirección correcta para excavar.Gracias por su atencion
Hasta pronto!