DIY KVM IP 3.0

هذا هو الاختلاف الثالث في موضوع IP KVM ، هذه المرة تمت مراجعة المفهوم بالكامل ، فلنبدأ في إنشاء شيء جديد. سيكون هناك العديد من الأشياء المثيرة للاهتمام ، لا تترك الشاشة. سيظهر جهاز آخر غير عادي ، سنتخلص من جميع المكونات القديمة تقريبًا ، ونعود إلى أردوينو الأصلي ونلعب القليل من المتسللين.

بالنسبة لأولئك الذين انضموا للتو ، ملخص الحلقات السابقة:

  • المقال الأول
    جمعت IP KVM على Arduino و Raspberry Pi ، وتبين أنها باهظة الثمن وذات جودة فيديو رديئة.
  • المقال الثاني
    تم تعلم OrangePI و Atmega16u2 بثمن بخس ، لكن جودة الصورة لا تزال مثيرة للاشمئزاز.

وأخيرًا ، في هذه المقالة ، سيتم إصلاح جميع عيوب السابقة. سيتم التركيز بشكل خاص على الحد الأقصى من تكلفة المكونات.

بالتقليد ، نعتبر مكونات الجهاز المجمع:

1. صديقنا القديم Atmega16u2:

هذا هو المكون الوحيد الذي سينتقل من المقالات السابقة.

2. ESP8266 سيئ السمعة ، في هذه الحالة ESP8266-12e:

يمكنك استخدام إصدار آخر من ESP8266 ، ما عليك سوى التفكير في عدد وموقع المنافذ.

3. وفي الواقع ، بطل المناسبة LKV373A



بفضل هذا الجهاز ، أصبح من الممكن نقل الفيديو عبر شبكة محلية عالية
دقة تصل إلى Full HD.

خطة العمل هي كما يلي:


  1. الاختباء والبحث: نحن نبحث عن LKV373A حيث اختبأ على الشبكة تحت عنوان IP
  2. لعبة هاكر: املأ البرنامج الثابت وأعد تعيين كلمات المرور وقم بتهيئة LKV373A
  3. تكوين صداقات جديدة: ESP8266 و Arduino IDE وصور مضحكة
  4. خاتمة الاحتفال. نقوم بتوصيل جميع المكونات وإرسال ضغطات المفاتيح عبر telnet

LKV373A الخلفية


لذلك دعونا نبدأ! LKV373A أو جهاز موسع HDMI لالتقاط الصور مباشرة من منفذ hdmi والبث إلى الشبكة المحلية ، وتسمى هذه الأجهزة أيضًا موسعات hdmi. كما هو مخطط من قبل الشركات المصنعة ، يجب أن تتكون مجموعة من هذه الأجهزة من جهاز إرسال (جهاز إرسال) وجهاز استقبال (جهاز استقبال) ، وتعيين TX و RX ، على التوالي. يجب استخدامها ، على الأرجح ، لتحقيق المزيد من الأرباح للشركة المصنعة ، فقط في أزواج. ولكن كان هناك رجل ، تحت اسم Danman ، هنا رابط لمدونته ، كان مهتمًا بكيفية عملها. قام بفتح Wireshark ، استنشق حركة المرور التي تم إرسالها بواسطة جهاز TX ، ما الذي تبين أنه؟

يتم بث دفق الفيديو دون أي تشفير ، وباستخدام مشغل VLC ، يمكنك مشاهدته دون بذل الكثير من الجهد. لكنه لم يتوقف عند هذا الحد ، "شعر": لقد سحب واجهة الويب ، TTL ، telnet ، وحتى سحب البرنامج الثابت مع المبرمج. تحدث عن هذا بالتفصيل في مدونته. تم أيضًا تحميل البرامج الثابتة التي تهمنا في المقام الأول هناك: IPTV_TX_PKG_v4_0_0_0_20160427.PKG. في هذا البرنامج الثابت ، تحتوي واجهة الويب ذات الإعدادات المتقدمة ، وليس مثل الإعداد القياسي ، على زر التحديث فقط. بالإضافة إلى ذلك ، يحتوي هذا البرنامج الثابت على telnet مع العديد من الأوامر لتكوينها. من خلال هذه البرامج الثابتة ، نعيد تكوين موسع HDMI لمهامنا. لقد قمت بنشر البرامج الثابتة وكل ما أحتاجه على github ، وهنا هو الرابط ، سنحتاج إليه لاحقًا ، ولكن الآن ننتهي بالنظرية. دعنا ننتقل إلى الممارسة.

جهاز الإرسال


نحن نبحث عن LKV373A في الشبكة


وقعت في يد نفس الموسع مثل Danman (y). كل ما سيتم وصفه أدناه مناسب بشكل خاص لإصدار HDMI Extender LKV373A V3.0!

نقوم بتوصيل LKV373A بالشبكة المحلية ، قم بتشغيل الطاقة. الآن دعنا نحاول التأكد من أن الجهاز مرئي على شبكة ping 192.168.1.238 .

192.168.1.238 هو عنوان IP الافتراضي. إذا لم يقم الموسع بتغيير عنوان البرنامج الثابت القديم ، بغض النظر عما إذا كان هناك خادم DHCP على الشبكة أم لا. تستخدم إصدارات البرامج الثابتة الأحدث IP بشكل افتراضي فقط إذا كان الجهاز غير قادر على الحصول على عنوان من DHCP. إذا تلقيت ردًا على ping ، فتابع. إذا لم يكن الأمر كذلك ، فلا تيأس ، حاول توصيل الموسع مباشرة بمنفذ LAN بالكمبيوتر واستخدم الشم.

امض


تم العثور على موسع HDMI ، انتقل إلى البرنامج الثابت. دعنا نذهب إلى github ونقوم بتنزيل كل ما هو موجود هناك. الآن افتح واجهة الويب الخاصة بالموسع من خلال متصفح وشاهد الصورة التالية:



انقر فوق "تصفح ..." ، وحدد البرنامج الثابت ، ملف يسمى IPTV_TX_PKG_v4_0_0_0_20160427.PKG ، وانقر فوق "ترقية". تضامن! اكتمل البرنامج الثابت ، اتصل الآن بـ LKV373A عن طريق telnet لإعادة تعيين كلمة المرور.

سيبدو الأمر للاتصال مثل Telnet 192.168.1.238 9999 ، حيث يمثل 9999 المنفذ للاتصال. يحذر CEP: يمكن العثور على العنوان الذي تم الحصول عليه من DHCP باستخدام ماسح ضوئي للشبكة.

الاتصال عبر التلنت


عند الاتصال ، يجب أن تظهر الرسالة التالية:

 ============================== ========IPTV TX Server======== ============================== input> 

نكتب list . ردًا على ذلك ، نحصل على قائمة بالأوامر:

 ============================== ========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 

لإعادة ضبط جميع الإعدادات وكلمة المرور ، استخدم الأمر factory_reset . نكتب الأمر ، اضغط على Enter والحصول على هذه الصورة:

 input>factory_reset Processing factory reset! System will reboot after few seconds! Connection closed by foreign host. 

واجهة الويب


الآن يمكننا تكوين الجهاز حسب الحاجة. دعنا نذهب إلى واجهة الويب. نستخدم تسجيل الدخول القياسي: كلمة مرور المسؤول: 123456 وهنا واجهة الويب "المرغوبة" مع إعدادات إضافية:



على الرغم من زيادة الفرص في واجهة الويب ، إلا أنها لا تزال غير كافية لأغراضنا. تفتقر بشكل خاص إلى المزيد من الإعدادات المجانية من حيث البث ، فهي مشفرة بشدة ، بعيدة عن الأكثر ملاءمة ، قائمة بعناوين IP التي يمكنك البث إليها. هناك بالطبع بث متعدد ، ولكن من الأفضل تركه للتلفزيون. يمكن التحايل على القيود ، المزيد عن ذلك لاحقًا.

لذلك ، وجدوا الجهاز على الشبكة ، ولفه ، وأعد تعيين كلمات المرور. جهاز الإرسال جاهز تقريبًا للانتقال إلى جهاز الاستقبال.

المتلقي


دعنا نقرر الجهاز تحت سيطرة نظام التشغيل الذي سننقل الدفق. لا أعتقد أنك ستختبر خيبات الاختيار ، هناك خياران فقط:

نوافذ


بالنسبة لنظام التشغيل Windows ، جربت عدة لاعبين ، لكن النتائج كانت كذلك. عند التقاط دفق فيديو ثم تشغيله ، يظهر تأخير ، والذي يعتمد في المقام الأول على المشغل الذي يقوم بتشغيل الدفق. تراوحت التأخيرات على لاعبين مختلفين من ثانية واحدة إلى خمس أو أكثر. أفضل ما في الأمر ، على Windows ، أثبت VLC Player أنه كذلك.

دعنا نبدأ العمل. قم بتشغيل VLC Player ، من الأعلى في القائمة المنسدلة "الوسائط" ، حدد "فتح عنوان URL ..." في حقل عنوان الشبكة ، واكتب udp://@:5004 ، وضع داو في مربع الاختيار "إظهار الإعدادات المتقدمة" وضع قيمته في حقل "التخزين المؤقت" ، يتم تحديد هذه المعلمة بشكل فردي. كلما كانت القيمة أصغر في هذا المجال ، انخفض التأخير ، ولكن القيمة الصغيرة جدًا يمكن أن تؤدي إلى "التحف" وإسقاط الإطار ، كل شيء سيعتمد على البنية التحتية للشبكة المحلية. أفضل النتائج التي استطعت تحقيقها هي تأخير حوالي ثانية واحدة. على لينكس ، كانت النتائج أفضل بكثير حوالي 200-300 مللي ثانية.

لينكس


كما تظهر الممارسة ، يتم الحصول على أفضل النتائج باستخدام مزيج من برامج socat و mplayer. تم تثبيت Ubuntu على جهاز الكمبيوتر الخاص بي ، لذا سيبدو الأمر لتثبيت socat كما يلي:

 sudo apt-get install socat 

يتم تثبيت Mplayer بالمثل:

 sudo apt-get install mplayer 

حسنًا ، واتبع نصيحة دانمان:

 sudo iptables -t raw -A PREROUTING -p udp -m length --length 28 -j DROP 

هذا الأمر مطلوب لإزالة ما يسمى بـ "حزم UDP ذات طول صفري" من الدفق - حزم ذات حجم صفري "تسد" الدفق.

انطلق!


جهاز الاستقبال جاهز ، يمكنك بدء البث! نكتب في وحدة تحكم الكمبيوتر المتلقي ifconfig أو ipconfig ، اعتمادًا على نظام التشغيل ، نتذكر عنوان IP الخاص بجهاز الاستقبال والعودة إلى واجهة الويب الخاصة بجهاز الإرسال. سنفتح واجهة الويب ، إذا قمنا بإغلاقها بالفعل ، فأدخل اسم المستخدم وكلمة المرور واكتب مباشرة في شريط عنوان المتصفح:

 http:///dev/info.cgi?action=streaminfo&udp=n&rtp=y&multicast=n&unicast=y&mcastaddr=&port=5004 

استبدل عناوين IP الخاصة بك واضغط على Enter. سيقوم هذا الخط بتكوين HDMI Extender لبث الفيديو الملتقط إلى عنوان IP الذي اخترته وإيقاف البث المتعدد.

نبدأ VLC في Windows. أو في محطة لينكس نكتب:

 socat UDP-RECV:5004 - | mplayer – 

العبرة كادابرا! وهنا سطح مكتبنا المباشر ، أو ليس لدينا.



لذا ، مع بعض طرق القرصنة ، أجبرنا الجهاز على القيام بما نحتاجه.

بعد نقل الفيديو ، انتقل إلى جهاز التحكم عن بُعد.

نقل التحكم


اختيار المكون


لأن تكلفة HDMI Extender منخفضة ، حوالي 1800 روبل ، وأيضًا بسبب التعليقات التي يقولون أنها باهظة الثمن ، طرحت الشعار: "Give IP KVM لـ 2000 روبل!". سيؤثر سعر صرف الروبل بشكل كبير على دقة هذا البيان ، لكن دعونا لا نتحدث عن الأشياء المحزنة ، أريد أن أؤمن بمستقبل مشرق. لتحقيق الهدف سنحتاج إلى عناصر رخيصة للغاية ، وقع اختياري على ESP8266 كوحدة تحكم ، وكل نفس Atmega (8/16/32) u2 كمشغل.

يمكنك بالطبع التفكير في المرشحين الآخرين لدور الجهاز التنفيذي (لوحة المفاتيح). تتم كتابة البرامج الثابتة التي تحاكي لوحة المفاتيح في مكتبة LUFA (نوعًا ما). يمكن استخدام هذه المكتبة لجميع أفراد عائلة AVR مع اتصال USB. يتبع ذلك أنه كمحاكي لوحة مفاتيح ، يمكنك التقاط ، وربما أرخص ، متحكمًا. هذه معلومات للنظر فيها ، لكننا الآن نواصل.

يمكنك شراء ESP8266 لحوالي 90 روبل ، Atmega (8/16/32) u2 لحوالي 100 روبل ، وحتى أرخص إذا كنت تأخذ دفعات صغيرة من 5 أو أكثر من القطع. بالطبع ، ستكون هناك حاجة إلى المواد الاستهلاكية لربط وحدات التحكم الدقيقة ، لكن تكلفتها صغيرة للغاية ، لذلك لن أعتبرها.

ESP8266


هذه المعجزة للصناعة الصينية لا تحتاج إلى مقدمة ، لذلك سأقول فقط أنني استخدمت في هذا المشروع نسخة ESP8266-12e. بالطبع ، يمكنك استخدام إصدارات أخرى ، أنت فقط تحتاج إلى النظر في موقع المنافذ ، لأنه في هذا الإصدار ، يتم استخدام أحد منافذ ESP8266 لتشغيل Atmega (8/16/32) u2 ، وسيتم الإشارة إليه في الرسم البياني أدناه.

البرامج الثابتة


تم كتابة البرنامج الثابت لـ ESP8266 في بيئة ArduinoIDE ، لذلك دعونا ننزّل أحدث إصدار من موقع المطور . بعد ذلك تحتاج إلى إضافة دعم لـ ESP8266 - يمكن العثور على أسهل طريقة على هذا الرابط . في نفس الصفحة ، يمكنك العثور على الكثير من المعلومات المفيدة ، مثل اتصال الطاقة و TTL. بالنسبة لأولئك الذين ليسوا محدثين ، يستخدم ESP8266 3.3 فولت بدقة! إذا لم تكن واثقًا من قدراتك الخاصة ، فمن الأفضل استخدام خيار لوحة مخصص لـ USB ، مثل NodeMCU:



إذا كان كل شيء جاهزًا ، فافتح ArduinoIDE وانسخ رسومي:

رسم
 #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); } } } } } 


قم بتوصيل المكتبة المطلوبة:

حدد علامة التبويب "Sketch" → "Connect library" → "Add .ZIP library". حدد المكتبة التي تسمى "UNO-HIDKeyboard-Library-Library (mod) .zip" ، التي تم تنزيلها من github. نحن نجمع ونملأ البرامج الثابتة. لتنزيل البرنامج الثابت ، قم بتوصيل ESP8266 TTL ، وقم بتعيين المنفذ المطلوب في ArduinoIDE. يجب أن تبدو الإعدادات على النحو التالي:



لتنزيل البرنامج الثابت ، تحتاج إلى تقصير منفذ GPIO0 إلى الأرض ، وإعادة تشغيل وحدة التحكم الدقيقة عن طريق تقصير منفذ إعادة الضبط على الأرض أيضًا. لن أرسم بالتفصيل ، حتى لا تضخم المقالة ، ستساعدك Google.

يكون منطق ESP8266 كما يلي: عند تطبيق الطاقة ، يحاول المتحكم الاتصال بنقطة وصول Wi-Fi لمدة ثلاثين ثانية تقريبًا:

إذا نجح الاتصال : يفتح المنفذ 23 ، والذي يمكنك الاتصال باستخدام Telnet ونقل ضغطات المفاتيح. بالإضافة إلى المفاتيح ، يمكنك نقل مجموعات مبنية على "مفتاح Ctrl +" والتي ستضغط على تركيبات معينة. على سبيل المثال ، إذا نجحت في تمرير "Ctrl + d" ، فسيتم الضغط على مجموعة CTRL + ALT + DELETE على الكمبيوتر المُدار.

هناك أيضًا مجموعات للتحكم في منافذ ESP8266 ، على سبيل المثال ، يمكنك توصيل مرحل واستخدام تركيبة "Ctrl + q" لتشغيل التتابع وإيقاف تشغيله ، وبالتالي تشغيل وإيقاف تشغيل الكمبيوتر المُدار عن بُعد. يمكنك مشاهدة هذه المجموعات وغيرها في المصدر.

إذا فشلت : ينتقل ESP8266 إلى وضع نقطة الوصول باسم "TD" ، كلمة المرور "اختبار" ويفتح واجهة ويب صغيرة ، يمكن الوصول إليها على 192.168.4.1 ، حيث يمكنك تكوين الإعدادات للاتصال عبر WI-FI.



وبالتالي ، يمكن توصيل الجهاز بسهولة بنقطة وصول أخرى. نعم ، تم إخفاء ذبابة في المرهم هنا ، لتشغيل IP KVM الخاص بنا ، سنحتاج إلى كبل LAN و Wi-Fi. هذه ستكون تكلفة رخص الجهاز.

تعاملنا مع ESP8266 ، مع Atmega16u2 كل شيء كما هو الحال في المقالات السابقة ، نقوم بوميض برنامج Flip ، البرنامج الثابت في الأرشيف الذي تم تنزيله من github.

اتصال المكون


للتوصيل الصحيح للمكونات ، أرفق الدائرة. فقط ضع في اعتبارك ، هذا مخطط مشروط ، إنه يعمل على الوضوح ولا يدعي أنه مثالي. الجميع أحرار في "تأثيثها" كما يحلو لها.



دعني أشرح بعض النقاط: يلزم وجود الترانزستور في الدائرة لتشغيل Atmega16u2 بعد تحميل ESP8266 ، لأنه عند تشغيل ESP8266 ، يتم نقل معلومات التصحيح إلى جميع منافذ TX ، وإذا تم تشغيل Atmega16u2 وتوصيله بالكمبيوتر ، يتم نقل دفق البيانات مع حجمه السائق لا يستطيع التأقلم. من غير المعروف على وجه اليقين ما يحدث في هذه اللحظة ، ومن المفترض أن المخزن المؤقت للسائق يفيض ، والتأثير غير سار للغاية: يتم الضغط على مئات المفاتيح ، إذا تم فتح محرر نص ، فإنه يسكب مجموعة من الثرثرة ، ونتيجة لذلك ، تتعطل جميع مفاتيح الخدمة ، ونتيجة لذلك ، يصبح العمل مع لوحة المفاتيح مستحيلًا . لتجنب هذا ، يجب تشغيل Atmega16u2 بعد تحميل ESP8266. في البرامج الثابتة يتم أخذ هذه اللحظة بعين الاعتبار.

بالطبع ، هناك بديل للمخطط ، لكن هذا خيار للأغنياء أو الكسولين. وبالمناسبة ، هذا الخيار لا يلغي ما سبق:



في الصورة ، اردوينو UNO بدون شريحة Atmega328p متصل بالنظير الصيني لـ NodeMCU. يتم توصيل خط 3.3 فولت بخط نفس مستوى الجهد على Arduino ، بالإضافة إلى توصيل الأرض ودبوس GPIO2 (ESP8266) بمسمار TX على Arduino.

الاختيار النهائي


نقوم بالاتصال عن طريق telnet بالمنفذ 23 والتحقق من الأداء. يمكنك القيام بذلك: في نظام التشغيل Windows باستخدام الأمر telnet [ip- ESP8266] .

على لينكس سيكون الأمر أكثر تعقيدًا:

أمر telnet [ip- ESP8266] ثم تحتاج إلى الضغط على حرف التحكم ، الافتراضي هو "Ctrl +]" ، يجب أن ينتقل telnet إلى وضع الأوامر ، ثم اضغط على "l" و "Enter". مع هذه الإجراءات ، سنقوم بتبديل التلنت إلى وضع الرمز.

 $ telnet 192.168.***.*** Trying 192.168.***.***... Connected to 192.168.***.***. Escape character is '^]'. ^] telnet> l 

كل شيء جاهز ، يمكننا التحقق من تشغيل الجهاز الذي أنشأناه. دعني أذكرك بالتركيبات الممكنة للضغط على "Alt + Tab" و "Ctrl + Alt + Del" وما إلى ذلك. يمكن رؤيته في الرسم. هذا كل شيء ، التجسد الثالث لـ KVM DIY IP جاهز.

لتلخيص


الإيجابيات:


  • ربما يكون أهم شيء هو السعر ، فقد تبين أنه يتناسب مع 2000 روبل
  • لا يجب أن تكون هناك أي شكاوى حول جودة الفيديو ، يمكنك البث بدقة عالية كاملة دون مشاكل
  • القدرة على توسيع الوظائف بإضافة ما يصل إلى أربع مرحلات أو مشغلات أخرى.

السلبيات:


  • تحتاج إلى الاتصال عبر Wi-Fi وكابل Lan
  • عند استخدامها مع VGA ، يلزم وجود محول ، مما سيؤثر بشكل طبيعي على التكلفة

بشكل عام ، تحول الجهاز إلى اهتمام ، بالطبع ، فهو ليس منافسًا لـ KVMs IP التسلسلية بكل "الأشياء الجيدة" ، ولكنه يفوز كثيرًا في السعر. وبالنسبة للاستخدام المنزلي ، وربما ليس فقط ، فهو مناسب تمامًا.

أود أن أغتنم هذه الفرصة لأشكر المستخدم DaylightIsBurning ! اقترح هذا الرجل الطيب الاتجاه الصحيح للتنقيب.

شكرا لكم على اهتمامكم. اراك قريبا!

Source: https://habr.com/ru/post/ar406059/


All Articles