أنا متأكد من أن العديد من قراء هبر يعرفون ، أو على الأقل سمعوا ، عن أجهزة أونكيو الصوتية. تحتوي مشغلات الشبكة الحديثة وأجهزة استقبال الصوت / الفيديو على Linux ، بالإضافة إلى القدرة على توصيلات الشبكة السلكية / اللاسلكية. توفر Onkyo تطبيق الهاتف المحمول الخاص بها للتحكم عن بعد في مثل هذا الجهاز -
Onkyo Controller . لا توجد معلومات عمليًا حول كيفية عمل هذا التطبيق - هناك فتات في المنتديات ، بالإضافة إلى العديد من المشاريع على github.

ولكن يمكنك العثور على الشبكة على وصف لبروتوكول الاتصال التسلسلي Integra عبر بروتوكول Ethernet (eISCP) ، والذي يقوم عليه هذا التطبيق. البروتوكول مثير للاهتمام. على حبري لا يمكن العثور على مقال واحد حول هذا البروتوكول. من ناحية ، لا يوجد شيء مأساوي في هذا الأمر ، حيث يبدو أن هذه الملكية لا تستخدم في أي مكان باستثناء Onkyo. من ناحية أخرى ، هناك احتمال أن يكون هناك متحمسون يرغبون في توجيه لاعبهم أو مستقبل Onkyo بمفردهم. أيضا ، قد تكون المقالة ذات أهمية لأولئك الذين ، بدافع الفضول النظري البحت ، يجمعون المعرفة حول بروتوكولات الشبكة المختلفة. إذا كانت مهتمة ، من فضلك ، تحت القط.
هناك القليل من المعلومات الرسمية حول موضوع المقالة. لذلك ، سأعتمد ليس فقط على الوثائق الموجودة ، لأنه يصف أوامر البروتوكول فقط ، ولكن لا يقول أي شيء عن ميزات استخدامها. تمكنا من الحصول على الكثير من المعلومات من تحليل حركة مرور الشبكة باستخدام tcpdump / wireshark ، بالإضافة إلى دراسة البرامج الثابتة للجهاز. هذا هو المكان الذي سأبدأ فيه.
الطراز الخاص بجهازي ليس مهمًا. لا يسعني إلا أن أقول إن هذا مشغل شبكة ، مشابه للاعب في الصورة لجذب الانتباه. يمكنه تشغيل الموسيقى ليس فقط من مشغلات USB الخارجية ، ولكن أيضًا من خادم الموسيقى (DLNA) ، كما يدعم راديو الإنترنت وخدمات البث مثل Spotify و Deezer وشيء آخر. بطبيعة الحال ، ينبغي أن يدعم البروتوكول كل هذا التنوع.
تحليل الميناء
لبدء طرح الأسئلة الصحيحة في محرك البحث ، كان عليّ أولاً أن أفهم نوع البروتوكول المستخدم بشكل عام. أي أن الخطوة الأولى هي تحليل المنفذ. لذا ، الجهاز على الشبكة ، عنوانه 192.168.1.80. افحص مجموعة المنافذ بالكامل:
> nmap -sS -p0-65535 -T5 192.168.1.80 PORT STATE SERVICE 80/tcp open http 4545/tcp open worldscores 5000/tcp open upnp 8008/tcp open http 8009/tcp open ajp13 8080/tcp open http-proxy 8888/tcp open sun-answerbook 10001/tcp open scp-config 60128/tcp open unknown
تم اكتشاف الكثير من الأشياء المثيرة للاهتمام:
- 80 / TCP واضح - هذه هي صفحة إعداد الجهاز. في نموذجي ، لا يوجد سوى إعداد الشبكة وترقية البرامج الثابتة. لا يوجد التحكم في التشغيل. من خلال الروابط الديناميكية مثل "http://192.168.1.80/album_art.cgi" ، يمكنك الوصول إلى صورة المسار الذي يتم تشغيله حاليًا.
- 4545 / TCP - ظهر بعد آخر تحديث للبرامج الثابتة. Nmap لا يعرف عنه شيئا. عند محاولة الاتصال ، يرسل على الفور json مع حالة التشغيل الحالية ويرسل تحديثًا كل ثانية
كتلة البيانات مع حالة التشغيل { "data": { "fireCast": false, "status": { "duration": 224893, "playBytes": 0 }, "error": "", "matchingMediaRoles": [], "controls": { "previous": true, "next_": true, "seekBytes": true, "seekTime": true, "pause": true, "seekTrack": true }, "mediaRoles": { "title": "", "asciiTitle": "" }, "playId": { "systemMemberId": "Onkyo NS-6130", "timestamp": 447085 }, "state": "playing", "trackRoles": { "mediaData": { "metaData": { "artist": "Ottawan", "album": "Greatest Hits", "serviceID": "Storage_usb2" } }, "title": "Shalala-Song", "flags": { "file": true }, "path": "storage_file_usb2:sda-94DB-FB8F/flac/Disco/Ottawan/Greatest Hits (2007)/05-Shalala-Song.flac", "optPlayingConentInfo": { "playingTrackTotal": 17, "playingTrackNo": 4 }, "icon": "file:///tmp/temp_data_albumArt_3c70a403584dc761cabc88ac0dfbb95c", "type": "audio" } }, "playTime": { "i64_": 139021, "type": "i64_" }, "senderVolume": {}, "senderMute": {}, "sender": "Onkyo-NS-6130-E1EE7F" }
كما قلت ، ظهر هذا المنفذ مع آخر تحديث. لا يوجد توثيق من الكلمة على الإطلاق. قد يكون من المفيد تطوير لوحة تحكم خفيفة الوزن. ولكن في هذا الاتجاه لم أحفر حتى الان. - 5000 / tcp - nmap يعرفها بأنها Apple AirTunes. يبدو أن ذلك صحيح ، حيث تم ذكر دعم هذا البروتوكول في الوثائق.
- 8008 / tcp ، 8009 / tcp - الغرض غير واضح ، nmap لا يعرف شيئًا عنها.
- 8080 / tcp - http-proxy ، والغرض منها في سياق هذا اللاعب غير واضح تمامًا.
- 8888 / TCP - بروتوكول منفذ التوصيل والتشغيل العالمي (UpnP) . باستخدام أداة gupnp-universal-cp من حزمة gupnp-tools يمكنك عرض وصفها:

في البداية كان يعتقد أن الإدارة في التطبيق الرسمي تم تنفيذها على أساس هذا البروتوكول بالذات. كما اتضح فيما بعد ، كان مخطئا. لقد جربت أيضًا العديد من عملاء UpnP ، سواء المحمول أو سطح المكتب. كلهم لا يعملون عمليا: بعض أوامر التحكم تعمل ، وبعضها لا يعمل ، وهو فوضوي تماما. - 10001 / tcp - مشابه لمنفذ تكوين SCP ، ولكن كيفية استخدامه غير واضحة.
- 60128 / tcp - وأخيرًا ، الشخصية الرئيسية في هذه المقالة ، منفذ بروتوكول eISCP. Nmap لا يعرف عنه شيئًا أيضًا. دعونا نفتح حجاب السرية.
تحليل حركة المرور
الآن دعونا نتحقق من المنفذ وكيف يتواصل التطبيق الرسمي مع الجهاز. أسهل طريقة للقيام بذلك هي على بعض أجهزة Android ذات الجذور (ولكن ليس في المحاكي ، حيث يتطلب التطبيق الرسمي جهازًا مُدارًا على نفس الشبكة الفرعية المحلية). للقيام بذلك:
- قم بتثبيت Android tcpdump على جهاز Android حيث تم تثبيت Onkyo Controller بالفعل
- نذهب إلى جهاز Android عبر ADB كجذر:
> adb root && adb shell root@fiber-bs1078:/>
- انتقل إلى أي دليل على بطاقة SD المدمجة:
root@fiber-bs1078:/> cd /sdcard/work root@fiber-bs1078:/sdcard/work>
- تشغيل tcpdump (مع الكتابة إلى الملف)
root@fiber-bs1078:/sdcard/work> tcpdump -vX -i any -w onkyo.dump host 192.168.1.80 tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 262144 bytes
- أطلقنا تطبيق Onkyo ، ومن هناك نبدأ في تشغيل الموسيقى
- عند كتابة بضع مئات من الحزم ، أوقف tcpdump بواسطة Cttl + C
- نعود إلى المحطة ، حيث أطلقنا ADB ونسخ الملف إلى جهاز كمبيوتر يعمل
root@fiber-bs1078:/sdcard/work> exit > adb pull /sdcard/work/onkyo.dump . [100%] /sdcard/work/onkyo.dump
- أطلق Wireshark وشاهد ما يحدث هناك.
> wireshark onkyo.dump &
وبالفعل ، يستمر الاتصال على المنفذ 60128. على سبيل المثال ، يرسل التطبيق طلبًا للاعب:

ويجيبه:

لذا نصل إلى جوهر المقالة ، وهو: ما هو في الصور أعلاه لمثل هذه الرسائل - ISCP؟ يعني هذا الاختصار بروتوكول التحكم التسلسلي Integra ، المصمم أصلاً للتحكم في أجهزة Onkyo عبر منفذ RS-232 (هناك مقال قديم مثير للاهتمام حول هذا الموضوع). تم توسيعه لاحقًا بإضافة البادئة "e" واتضح eISCP - Integra Serial Communication Protocol عبر Ethernet. كلا الإصدارين من البروتوكول موصوف في الوثائق التقنية: بروتوكول الاتصال التسلسلي المتكامل لمستقبل AV. النسخة الأولى من الوثيقة مؤرخة في 31 أكتوبر 2012 ، وآخر نسخة تم العثور عليها هي 4 سبتمبر 2017. جميع النسخ التي وجدتها تم جمعها في
مستودع المشروع التجريبي ، والذي سأتحدث عنه لاحقًا. سيستند العرض التقديمي الإضافي على حد سواء على هذا المستند وعلى التجارب مع المشغل الخاص بي (ومع ذلك ، لم يتم ذكرها صراحة في هذا المستند).
مواصفات الرسالة
يتبادل العميل (على سبيل المثال ، تطبيق جوال) والجهاز الرسائل النصية القصيرة. إذا كانت الأرقام موجودة فيه ، فسيتم تقديمها ، كقاعدة ، في شكل سداسي عشري.
تنسيق الرسالة من العميل إلى الجهاز بسيط للغاية:

تبدأ الرسالة بحرف "!" ، ثم رمز الجهاز الهدف ، متبوعًا بثلاثة أحرف من الأمر ، ثم سلسلة من المعلمات ذات الطول التعسفي. ينتهي بـ CR (0x0D) أو LF (0x0A) ، أو مزيج من CR + LF.
بناءً على الأمر ، يستجيب الجهاز إما بنفس نوع الرسالة (إذا كان طلبًا لبعض المعلمات) ، أو بنوع آخر أو حتى مجموعة من الرسائل (إذا كان أمرًا لإجراء معقد مثل تبديل المسار). تنسيق الرسائل المرسلة بواسطة الجهاز إلى العميل هو نفسه. الفرق فقط في البايت الأخير:

يحتوي مستند وصف البروتوكول على أكثر من مائة أمر مختلف ، ويدعم جهازي أكثر من 30 أمرًا من هذا المستند. أي أن كل من مجموعة الأوامر والمعلمات الصالحة تعتمد على الجهاز المحدد.
يمكن تجميع الأوامر في مجموعات منطقية. كمثال ، أود أن أسلط الضوء على ما يلي:
- الإدارة العامة للجهاز:
- NDN: اسم الجهاز.
- UPD: التحقق من تحديث البرامج الثابتة وتثبيته.
- PWR: تشغيل / إيقاف الطاقة.
- NRI: معلومات الجهاز الموسعة.
- NTC: أوامر جهاز التحكم عن بعد القياسي (بما في ذلك التحكم في التشغيل).
- CAP: أوامر للتحكم في مضخم خارجي متصل بموصل RI.
- معلومات حول المسار الجاري تشغيله:
- NAL: اسم الألبوم.
- نات: اسم الفنان.
- NTI: اسم المسار.
- NFI: معلومات ملف المسار (التنسيق ومعدل البت).
- NJA: صورة مرفقة بمسار (على سبيل المثال ، شعار محطة إذاعية إذا تم اختيار راديو الإنترنت).
- NTM: الموقع الحالي في المسار.
- NTS: الحالة ، الترجيع ممكّن أم لا (للإذاعة عبر الإنترنت ، على سبيل المثال ، غير مسموح به).
- NST: التكرار والتحكم في التشغيل العشوائي.
- التنقل وإدارة مكتبة الموسيقى:
- SLI: اختيار المصدر (مثل USB ، خدمات الشبكة).
- NSV: حدد خدمة شبكة معينة (مثل راديو الإنترنت ، خادم الموسيقى). ترتبط قائمة التشغيل على جهازي أيضًا بخدمات الشبكة ، على الرغم من أن هذا ليس واضحًا تمامًا من وجهة نظر واجهة المستخدم. وعند إيقاف تشغيل الطاقة (الانسحاب من المنفذ) ، يتم حذف قائمة التشغيل هذه!
- NLT، NLA: التنقل من خلال أقسام (مجلدات) المكتبة.
- PQA ، PQR ، PQO: إدارة قائمة التشغيل: إضافة أو حذف أو إعادة ترتيب.
بطبيعة الحال ، هذه القائمة أبعد ما تكون عن الاكتمال ، فأعطيتها فقط لإظهار نطاق وقدرات هذا البروتوكول.
من حيث المعلمات ، يمكن تقسيم جميع الرسائل إلى مجموعتين. تتضمن المجموعة الأولى معظم الرسائل. بالنسبة لهذه المجموعة ، تحتوي سلسلة المعلمات على بيانات في شكل أبجدي رقمي أو سداسي عشري ويتم تحليلها بواسطة بايت. على سبيل المثال ، عند التبديل إلى خدمة TuneIn Radio ، يرسل المشغل رسالة NLT - معلومات حول رأس القائمة الحالية مع المعلمة "0E01000000090100FF0E00TuneIn Radio" ، والتي يتم فك تشفيرها وفقًا للمواصفات ، وتعطي هذه المعلومات:
SERVICE=TUNEIN_RADIO; UI=LIST; LAYER=SERVICE_TOP; CURSOR=0; ITEMS=9; LAYERS=1; START=NOT_FIRST; LEFT_ICON=NONE; RIGHT_ICON=TUNEIN_RADIO; STATUS=NONE; title=TuneIn Radio
تحتوي جميع الرسائل تقريبًا على معلمة "QSTN" ، على سبيل المثال ، "! 1NLTQSTN". هذا الطلب يعني طلبًا للاعب بإعادة معلومات الحالة الحالية المقابلة لهذا النوع من الرسائل. إنه يعمل دائمًا تقريبًا ، ولكن هناك استثناءات نادرة عندما يتجاهل اللاعب ، وفقًا لمزاجه الداخلي ، هذه الطلبات.
المجموعة الثانية هي الرسائل ، حيث تكون المعلمة XML ، والتي يجب تحليلها باستخدام محلل XML. من المثال أعلاه ، أثناء وجودك في قسم TuneIn Radio ، يمكنك إرسال طلب NLA سيتم الرد على معلومات حول القائمة النشطة في XML:
<?xml version="1.0" encoding="utf-8"?> <response status="ok"> <items offset="0" totalitems="9"> <item icontype="F" iconid="29" title="My Presets" selectable="1" /> <item icontype="F" iconid="29" title="Local Radio" selectable="1" /> <item icontype="F" iconid="29" title="Music" selectable="1" /> <item icontype="F" iconid="29" title="Talk" selectable="1" /> <item icontype="F" iconid="29" title="Sports" selectable="1" /> <item icontype="F" iconid="29" title="By Location" selectable="1" /> <item icontype="F" iconid="29" title="By Language" selectable="1" /> <item icontype="F" iconid="29" title="Podcasts" selectable="1" /> <item icontype="F" iconid="29" title="Login" selectable="1" /> </items> </response>
أي أن المشغل لا يوفر فقط معلومات نصية (والتي ، بالمناسبة ، يتم عرضها حاليًا على شاشة المشغل) ، ولكنه ينصح أيضًا برمز مناسب (مجلد ، مسار موسيقي ، مسار تشغيل حاليًا).
في بعض الحالات ، يرغب المشغل في عرض رسالة نصية في تطبيق العميل أو طلب معلمات إضافية مثل اسم المستخدم. للقيام بذلك ، يرسل المشغل رسالة عالمية NCP (حوار عالمي) ، حيث يصف XML بنية ما يجب عرضه للمستخدم:
<?xml version="1.0" encoding="utf-8"?> <popup title="Try Deezer Premium+" align="center" type="custom" time="0" uri="resource:///popup"> <label title="" align="center" total="1" uri="resource:///popup/label:0"> <line text="Listening is limited to 30-second clips. Subscribe to enjoy unlimited music!" align="left" uri="resource:///popup/label/line:0" order="0" /> </label> <buttongroup title="" align="center" total="1" uri="resource:///popup/buttongroup:0"> <button text="OK" align="center" uri="/button:0" selected="false" index="0" www="" order="1" /> </buttongroup> </popup>
واستجابة لذلك ، يتوقع اللاعب نفس الرسالة مع ملء الحقول (أو الزر المضغوط).
أيضا في تنسيق XML يتم تقديم رسالة NRI مهمة إلى حد ما - معلومات عامة عن اللاعب. الرسالة كبيرة بما يكفي ، لذلك أخفيها تحت المفسد.
معلومات عامة عن اللاعب <?xml version="1.0" encoding="utf-8"?> <response status="ok"> <device id="NS-6130"> <brand>ONKYO</brand> <category>NAP-O</category> <year>2016</year> <model>NS-6130</model> <destination>xx</destination> <macaddress>0009B0E1EE7F</macaddress> <modeliconurl>http://192.168.1.80/icon/OAVR_120.jpg</modeliconurl> <friendlyname></friendlyname> <firmwareversion>2110-0000-0000-0010-0000</firmwareversion> <ecosystemversion>200</ecosystemversion> <netservicelist count="9"> <netservice id="0e" value="1" name="TuneIn Radio" account="Username" password="Password" zone="01" enable="01" /> <netservice id="0a" value="1" name="Spotify" zone="01" enable="01" /> <netservice id="12" value="1" name="Deezer" account="Email address" password="Password" zone="01" enable="01" /> <netservice id="18" value="1" name="AirPlay" zone="01" enable="01" /> <netservice id="1b" value="1" name="TIDAL" account="Username" password="Password" zone="01" enable="01" /> <netservice id="00" value="1" name="Music Server" zone="01" enable="01" addqueue="1" sort="1" /> <netservice id="43" value="1" name="FlareConnect" zone="07" enable="0e" /> <netservice id="40" value="1" name="Chromecast built-in" zone="01" enable="01" /> <netservice id="1d" value="1" name="Play Queue" zone="01" enable="01" /> </netservicelist> <zonelist count="4"> <zone id="1" value="1" name="Main" volmax="0" volstep="0" src="1" dst="1" lrselect="0" /> <zone id="2" value="0" name="Zone2" volmax="0" volstep="0" src="0" dst="0" lrselect="0" /> <zone id="3" value="0" name="Zone3" volmax="0" volstep="0" src="0" dst="0" lrselect="0" /> <zone id="4" value="0" name="Zone4" volmax="0" volstep="0" src="0" dst="0" lrselect="0" /> </zonelist> <selectorlist count="3"> <selector id="2b" value="1" name="NET" zone="01" iconid="2b" /> <selector id="29" value="1" name="USB(F)" zone="01" iconid="29" addqueue="1" /> <selector id="2a" value="1" name="USB(R)" zone="01" iconid="2a" addqueue="1" /> </selectorlist> <presetlist count="40"> <preset id="01" band="0" freq="0" name="" /> <preset id="02" band="0" freq="0" name="" /> <preset id="03" band="0" freq="0" name="" /> <preset id="04" band="0" freq="0" name="" /> <preset id="05" band="0" freq="0" name="" /> <preset id="06" band="0" freq="0" name="" /> <preset id="07" band="0" freq="0" name="" /> <preset id="08" band="0" freq="0" name="" /> <preset id="09" band="0" freq="0" name="" /> <preset id="0a" band="0" freq="0" name="" /> <preset id="0b" band="0" freq="0" name="" /> <preset id="0c" band="0" freq="0" name="" /> <preset id="0d" band="0" freq="0" name="" /> <preset id="0e" band="0" freq="0" name="" /> <preset id="0f" band="0" freq="0" name="" /> <preset id="10" band="0" freq="0" name="" /> <preset id="11" band="0" freq="0" name="" /> <preset id="12" band="0" freq="0" name="" /> <preset id="13" band="0" freq="0" name="" /> <preset id="14" band="0" freq="0" name="" /> <preset id="15" band="0" freq="0" name="" /> <preset id="16" band="0" freq="0" name="" /> <preset id="17" band="0" freq="0" name="" /> <preset id="18" band="0" freq="0" name="" /> <preset id="19" band="0" freq="0" name="" /> <preset id="1a" band="0" freq="0" name="" /> <preset id="1b" band="0" freq="0" name="" /> <preset id="1c" band="0" freq="0" name="" /> <preset id="1d" band="0" freq="0" name="" /> <preset id="1e" band="0" freq="0" name="" /> <preset id="1f" band="0" freq="0" name="" /> <preset id="20" band="0" freq="0" name="" /> <preset id="21" band="0" freq="0" name="" /> <preset id="22" band="0" freq="0" name="" /> <preset id="23" band="0" freq="0" name="" /> <preset id="24" band="0" freq="0" name="" /> <preset id="25" band="0" freq="0" name="" /> <preset id="26" band="0" freq="0" name="" /> <preset id="27" band="0" freq="0" name="" /> <preset id="28" band="0" freq="0" name="" /> </presetlist> <controllist count="61"> <control id="Bass" value="0" zone="1" min="-10" max="10" step="2" /> <control id="Treble" value="0" zone="1" min="-10" max="10" step="2" /> <control id="Center Level" value="0" zone="1" min="-12" max="12" step="1" /> <control id="Subwoofer Level" value="0" zone="1" min="-15" max="12" step="1" /> <control id="Subwoofer1 Level" value="0" zone="1" min="-15" max="12" step="1" /> <control id="Subwoofer2 Level" value="0" zone="1" min="-15" max="12" step="1" /> <control id="Phase Matching Bass" value="0" /> <control id="LMD Movie/TV" value="0" code="MOVIE" position="1" /> <control id="LMD Music" value="0" code="MUSIC" position="2" /> <control id="LMD Game" value="0" code="GAME" position="3" /> <control id="LMD THX" value="0" code="04" position="4" /> <control id="LMD Stereo" value="0" code="00" position="4" /> <control id="LMD Direct" value="0" code="01" position="1" /> <control id="LMD Pure Audio" value="0" code="11" position="2" /> <control id="LMD Pure Direct" value="0" code="11" position="1" /> <control id="LMD Auto/Direct" value="0" code="AUTO" position="2" /> <control id="LMD Stereo G" value="0" code="STEREO" position="3" /> <control id="LMD Surround" value="0" code="SURR" position="4" /> <control id="TUNER Control" value="0" /> <control id="TUNER Freq Control" value="0" /> <control id="Info" value="2" /> <control id="Cursor" value="1" /> <control id="Home" value="0" code="HOME" position="2" /> <control id="Setup" value="1" code="MENU" position="2" /> <control id="Quick" value="0" code="QUICK" position="1" /> <control id="Menu" value="0" code="MENU" position="1" /> <control id="AMP Control(RI)" value="1" /> <control id="CD Control(RI)" value="1" /> <control id="CD Control" value="0" /> <control id="BD Control(CEC)" value="0" /> <control id="TV Control(CEC)" value="0" /> <control id="NoPowerButton" value="0" /> <control id="DownSample" value="0" /> <control id="Dimmer" value="1" /> <control id="time_hhmmss" value="1" /> <control id="Zone2 Control(CEC)" value="0" /> <control id="Sub Control(CEC)" value="0" /> <control id="NoNetworkStandby" value="0" /> <control id="NJAREQ" value="1" /> <control id="Music Optimizer" value="0" /> <control id="NoVideoInfo" value="1" /> <control id="NoAudioInfo" value="1" /> <control id="AV Adjust" value="0" /> <control id="Audio Scalar" value="0" /> <control id="Hi-Bit" value="0" /> <control id="Upsampling" value="0" /> <control id="Digital Filter" value="1" /> <control id="DolbyAtmos" value="0" /> <control id="DTS:X" value="0" /> <control id="MCACC" value="0" /> <control id="Dialog Enhance" value="0" /> <control id="PQLS" value="0" /> <control id="CD Control(NewRemote)" value="0" /> <control id="NoVolume" value="1" /> <control id="Auto Sound Retriever" value="0" /> <control id="Lock Range Adjust" value="0" /> <control id="P.BASS" value="0" /> <control id="Tone Direct" value="0" /> <control id="DetailedFileInfo" value="1" /> <control id="NoDABPresetFunc" value="0" /> <control id="S.BASS" value="0" /> </controllist> <functionlist count="10"> <function id="UsbUpdate" value="0" /> <function id="NetUpdate" value="1" /> <function id="WebSetup" value="1" /> <function id="WifiSetup" value="1" /> <function id="Nettune" value="0" /> <function id="Initialize" value="0" /> <function id="Battery" value="0" /> <function id="AutoStandbySetting" value="0" /> <function id="e-onkyo" value="0" /> <function id="UsbDabDongle" value="0" /> </functionlist> <tuners count="0"></tuners> </device> </response>
مجموعة الأوامر التي يجب عليك استخدامها للتحكم في الجهاز ، تعتمد إلى حد كبير على ما هو موجود في أقسام قائمة المناطق والتحكم في هذه الرسالة.
ISCP عبر إيثرنت (eISCP)
الرسائل في النموذج ، كما كتبت أعلاه ، مخصصة للإرسال عبر كابل (RS-232). تم تجهيز أجهزة الاستقبال الأقدم لهذا موصل 9-RS RS-232. عندما بدأوا بدلاً من هذا الموصل في استخدام اتصال شبكة (سلكي أو لاسلكي) ، كان علينا أن نلف هذه الرسائل في غلاف للإرسال عبر TCP / IP. لذلك ظهر بروتوكول eISCP ، حيث يتم تغليف رسالة ISCP في مثل هذه الحزمة:

تحت المفسد هو رمز الإجراء الذي يولد مثل هذه الحزمة لرسالة برمز معين (رمز متغير) وسلسلة من المعلمات (معلمات متغيرة) وإصدار بروتوكول معين (إصدار متغير). نظرًا لأن الإجراء بسيط للغاية ، يبدو لي أن رمز Java سيقول أكثر من ألف كلمة.
إجراء لتوليد رسالة eISCP private final static int MIN_MSG_LENGTH = 22; private final static String MSG_START = "ISCP"; private final static Character START_CHAR = '!'; private final static int LF = 0x0A; ... byte[] getBytes() { if (headerSize + dataSize < MIN_MSG_LENGTH) { return null; } final byte[] bytes = new byte[headerSize + dataSize]; Arrays.fill(bytes, (byte) 0);
إذا كان أي شخص مهتمًا ،
فإليك مثال على تطبيق البروتوكول
لإصدار المواصفات 1.40 . سأقدم أيضًا رابطًا إلى
هذا المستودع . وهي تنفذ مكتبة رسائل وأداة مساعدة لسطر الأوامر في Python ، بالإضافة إلى روابط لمشاريع أخرى مماثلة.
تنفيذ تبادل المعلومات
الرسائل نفسها ، المصممة في الأصل للإرسال عبر كبل منخفض السرعة ، صغيرة جدًا. علاوة على ذلك ، فإن اللاعب نفسه متواضع تمامًا - على خلفية كمية ضخمة من الإحصائيات المرسلة في مكان ما إلى خادم Amazon المشروط ، فإن كمية المعلومات التي يقدمها اللاعب طوعًا للعميل عبر ISCP ضئيلة. في مواصفات البروتوكول ، لا توجد كلمة حول وقت وتحت أي ظروف يرسل اللاعب هذه المعلومات أو تلك. لذلك ، كان علي أن أجرب نفسي لفترة كافية بحيث يكون لدى عميل الهاتف المحمول دائمًا جميع المعلومات اللازمة حول الحالة الحالية للجهاز.
بشكل عام ، يعتمد التواصل مع اللاعب على مخطط الطلب / الاستجابة. علاوة على ذلك ، في حالات معينة ، لن يقتصر طلب واحد. هناك العديد من الأحداث الرئيسية للاعب بلادي التي يجب معالجتها:
- إنشاء اتصال. في وقت الاتصال ، قد يكون المشغل في وضع الاستعداد أو قيد التشغيل ، أو في وضع التشغيل أو الإيقاف المؤقت. من المهم أيضًا معرفة الموقف الذي يوجد فيه مفتاح قناة الإدخال على الفور - على خدمات الشبكة أو USB.
لذلك ، فور إنشاء الاتصال ، من المنطقي إرسال طلبات PWR (نشطة أو في حالة الاستعداد) ، UPD (هل يوجد تحديث للبرنامج الثابت) ، NRI (معلومات عامة عن الجهاز) ، SLI (موضع مفتاح الإدخال) ، NJA (وضع الإرسال لصورة المسار رابط أو دفق). يرسل المشغل على وجه التحديد حالة التشغيل والموضع الحالي بمبادرة منه. - ابدأ التشغيل. في هذه الحالة ، يرسل اللاعب جميع المعلومات حول المسار. ولكن عند الاتصال ، عندما يلعب اللاعب شيئًا بالفعل ، لا يرسل اللاعب أي شيء. بالإضافة إلى ذلك ، عندما يقوم اللاعب بتبديل المسار ، لا يتم إرسال جميع المعلومات.
كان الحل الشامل ، وإن كان يستهلك الموارد ، هو تتبع رسالة NST (حالة التشغيل) ، وإذا تحولت هذه الحالة إلى "تشغيل" ، فأرسل فورًا 7 طلبات: NAT (فنان) ، NAL (عنوان الألبوم) ، NTI (عنوان المسار) ، NFI (معلومات الملف) ، NTR (رقم المسار) ، NTM (وقت التشغيل الحالي) ، NMS (قائمة المسار). هناك ميزات في البرامج الثابتة للمشغل. على سبيل المثال ، عند تشغيل قائمة تشغيل ، لا يرغب اللاعب في التخلي عن رقم المسار الذي يتم تشغيله. ولكن بشكل عام ، يمكنك معرفة الحالة الحالية للتشغيل بتفاصيل كافية. - ( ) . - . , . — 14 !
10-27 16:12:20.272: NLU[00080011; 8/17] 10-27 16:12:27.338: NTI[09-Roses Are Red.flac] 10-27 16:12:27.342: NAL[] 10-27 16:12:27.342: NAT[] 10-27 16:12:27.342: NDN[] 10-27 16:12:27.343: NJA/1937[2-...; TYPE=URL; PACKET=NOT_USED; URL=http://192.168.1.80/album_art.cgi; RAW(null)] 10-27 16:12:27.649: NMS[xxxxxS1f1; TRACK_MENU=DISABLE; POS_FEED=DISABLE; NEG_FEED=DISABLE; TIME_SEEK=ENABLE; TIME_DISPLAY=ELAPSED_TOTAL; ICON=USB_REAR] 10-27 16:12:27.649: NTR[0009; 0011] 10-27 16:12:27.649: NFI[/44.1kHz/16bit; FORMAT=; FREQUENCY=44.1kHz; BITRATE=16bit] 10-27 16:12:27.649: NLT[F1020000000B060002FF00Aquarium (1997); SERVICE=USB_REAR; UI=LIST; LAYER=UNDER_2ND_LAYER; CURSOR=0; ITEMS=11; LAYERS=6; START=NOT_FIRST; LEFT_ICON=USB; RIGHT_ICON=NONE; STATUS=NONE; title=Aquarium (1997)] 10-27 16:12:27.724: NLS[C0P; INF_TYPE=CURSOR; LINE_INFO=0; PROPERTY=NO; UPD_TYPE=PAGE; LIST_DATA=null] 10-27 16:12:27.727: NLS[U0-Happy Boys & Girls; INF_TYPE=UNICODE; LINE_INFO=0; PROPERTY=NO; UPD_TYPE=NO; LIST_DATA=Happy Boys & Girls] 10-27 16:12:27.734: NLS[U1-My Oh My; INF_TYPE=UNICODE; LINE_INFO=1; PROPERTY=NO; UPD_TYPE=NO; LIST_DATA=My Oh My] 10-27 16:12:27.737: NLS[U2-Barbie Girl; INF_TYPE=UNICODE; LINE_INFO=2; PROPERTY=NO; UPD_TYPE=NO; LIST_DATA=Barbie Girl] 10-27 16:12:27.740: NLS[U3-Good Morning Sunshine; INF_TYPE=UNICODE; LINE_INFO=3; PROPERTY=NO; UPD_TYPE=NO; LIST_DATA=Good Morning Sunshine] 10-27 16:12:27.760: NLA[X0002S000...; RESP=X; SEQ_NR=2; STATUS=S; UI=LIST; XML=<?xml version="1.0" encoding="utf-8"?><response status="ok"><items offset="0" totalitems="11" ><item icontype="M" iconid="2d" title="Happy Boys & Girls" selectable="1" /><item icontype="M" iconid="2d" title="My Oh My" selectable="1" /><item icontype="M" iconid="2d" title="Barbie Girl" selectable="1" /><item icontype="M" iconid="2d" title="Good Morning Sunshine" selectable="1" /><item icontype="M" iconid="2d" title="Doctor Jones" selectable="1" /><item icontype="M" iconid="2d" title="Heat Of The Night" selectable="1" /><item icontype="M" iconid="2d" title="Be A Man" selectable="1" /><item icontype="M" iconid="2d" title="Lollipop (Candyman)" selectable="1" /><item icontype="0" iconid="36" title="Roses Are Red" selectable="1" /><item icontype="M" iconid="2d" title="Turn Back Time" selectable="1" /><item icontype="M" iconid="2d" title="Calling You" selectable="1" /></items></response>] 10-27 16:12:29.697: NTI[Roses Are Red] 10-27 16:12:29.718: NJA/1952[2-...; TYPE=URL; PACKET=NOT_USED; URL=http://192.168.1.80/album_art.cgi; RAW(null)] 10-27 16:12:30.248: NAL[Aquarium] 10-27 16:12:30.248: NAT[Aqua] 10-27 16:12:30.248: NDN[] 10-27 16:12:30.248: NMS[xxxxxS1f1; TRACK_MENU=DISABLE; POS_FEED=DISABLE; NEG_FEED=DISABLE; TIME_SEEK=ENABLE; TIME_DISPLAY=ELAPSED_TOTAL; ICON=USB_REAR] 10-27 16:12:30.248: NTR[0009; 0011] 10-27 16:12:30.248: NFI[FLAC/44.1kHz/16bit; FORMAT=FLAC; FREQUENCY=44.1kHz; BITRATE=16bit] 10-27 16:12:30.248: NLT[F1020000000B060002FF00Aquarium (1997); SERVICE=USB_REAR; UI=LIST; LAYER=UNDER_2ND_LAYER; CURSOR=0; ITEMS=11; LAYERS=6; START=NOT_FIRST; LEFT_ICON=USB; RIGHT_ICON=NONE; STATUS=NONE; title=Aquarium (1997)] 10-27 16:12:30.248: NMS[xxxxxS1f1; TRACK_MENU=DISABLE; POS_FEED=DISABLE; NEG_FEED=DISABLE; TIME_SEEK=ENABLE; TIME_DISPLAY=ELAPSED_TOTAL; ICON=USB_REAR] 10-27 16:12:30.248: NFI[FLAC/44.1kHz/16bit; FORMAT=FLAC; FREQUENCY=44.1kHz; BITRATE=16bit] 10-27 16:12:30.248: NLT[F1020000000B060002FF00Aquarium (1997); SERVICE=USB_REAR; UI=LIST; LAYER=UNDER_2ND_LAYER; CURSOR=0; ITEMS=11; LAYERS=6; START=NOT_FIRST; LEFT_ICON=USB; RIGHT_ICON=NONE; STATUS=NONE; title=Aquarium (1997)] 10-27 16:12:34.815: NMS[xxxxxS1f1; TRACK_MENU=DISABLE; POS_FEED=DISABLE; NEG_FEED=DISABLE; TIME_SEEK=ENABLE; TIME_DISPLAY=ELAPSED_TOTAL; ICON=USB_REAR] 10-27 16:12:34.819: NFI[FLAC/44.1kHz/16bit; FORMAT=FLAC; FREQUENCY=44.1kHz; BITRATE=16bit] 10-27 16:12:34.860: NLT[F1020000000B060002FF00Aquarium (1997); SERVICE=USB_REAR; UI=LIST; LAYER=UNDER_2ND_LAYER; CURSOR=0; ITEMS=11; LAYERS=6; START=NOT_FIRST; LEFT_ICON=USB; RIGHT_ICON=NONE; STATUS=NONE; title=Aquarium (1997)]
, . , , , .
كمثال ، سأعطي رابط إلى مستودع بلدي مع تطبيق Android للتحكم عن بعد لمشغل Onkyo NS-6130. هناك فرصة أنها ستعمل أيضًا مع Onkyo NS-6170. ولكن لن تتمكن من استخدامه مع أي جهاز استقبال Onkyo ، نظرًا لأن واجهة التطبيق بالكامل مصممة خصيصًا لتشغيل مكتبة الموسيقى وإدارتها ، والتي ، كقاعدة عامة ، ليست على أجهزة الاستقبال. لذلك ، ليس لدي أي خطط لتوزيع هذا التطبيق بطريقة أو بأخرى ، وهنا أكتب عنه فقط كمثال على تنفيذ هذا البروتوكول.هيكل التطبيق بسيط ، التصميم أضيق الحدود. هناك ثلاث علامات تبويب فقط:- . , . , RI Onkyo. , , , .



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