Onkyo ISCP / eISCP: Verwalten von Onkyo-Geräten über das Netzwerk

Ich bin sicher, dass viele von Habrs Lesern etwas über Onkyo-Audiogeräte wissen oder zumindest gehört haben. Moderne Netzwerkplayer und A / V-Empfänger verfügen über Linux an Bord sowie über drahtgebundene / drahtlose Netzwerkverbindungen. Onkyo bietet seine proprietäre mobile Anwendung zur Fernsteuerung eines solchen Geräts - Onkyo Controller . Es gibt praktisch keine Informationen darüber, wie diese Anwendung funktioniert - es gibt Krümel in den Foren sowie mehrere Projekte auf Github.



Im Netzwerk finden Sie jedoch eine Beschreibung des eISCP-Protokolls (Integra Serial Communication Protocol over Ethernet), das dieser Anwendung zugrunde liegt. Das Protokoll ist interessant. Auf Habré konnte kein einziger Artikel zu diesem Protokoll gefunden werden. Einerseits ist daran nichts Tragisches, da dieses Eigentum nur in Onkyo verwendet zu werden scheint. Auf der anderen Seite besteht die Möglichkeit, dass es Enthusiasten gibt, die ihren eigenen Spieler oder Onkyo-Empfänger selbst steuern möchten. Der Artikel kann auch für diejenigen von Interesse sein, die aus rein theoretischer Neugier Wissen über verschiedene Netzwerkprotokolle sammeln. Bei Interesse bitte unter Katze.

Es gibt wenig offizielle Informationen zum Thema des Artikels. Daher werde ich mich nicht nur auf die gefundene Dokumentation verlassen, da sie nur Protokollbefehle beschreibt, aber nichts über die Funktionen ihrer Verwendung aussagt. Wir haben es geschafft, viele Informationen aus der Analyse des Netzwerkverkehrs mit tcpdump / wireshark sowie aus der Untersuchung der Gerätefirmware zu erhalten. Hier werde ich beginnen.

Das spezifische Modell meines Geräts ist nicht wichtig. Ich kann nur sagen, dass dies ein Netzwerk-Player ist, ähnlich dem auf dem Bild, um Aufmerksamkeit zu erregen. Es kann Musik nicht nur von externen USB-Trägern, sondern auch von einem Musikserver (DLNA) abspielen und unterstützt auch Internetradio und Streaming-Dienste wie Spotify, Deezer und andere. Natürlich sollte das Protokoll all diese Vielfalt unterstützen.

Portanalyse


Um in einer Suchmaschine die richtigen Fragen zu stellen, musste ich zunächst verstehen, welche Art von Protokoll im Allgemeinen verwendet wurde. Das heißt, der erste Schritt ist die Portanalyse. Das Gerät befindet sich also im Netzwerk. Die Adresse lautet 192.168.1.80. Scannen Sie den gesamten Bereich der Ports:

> 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 

Viele interessante Dinge werden entdeckt:

  • 80 / tcp ist klar - dies ist die Geräte-Setup-Seite. In meinem Modell gibt es nur Netzwerkeinrichtung und Firmware-Aktualisierung. Es gibt keine Wiedergabesteuerung. Über dynamische Links der Form "http://192.168.1.80/album_art.cgi" können Sie auf das Bild des aktuell wiedergegebenen Titels zugreifen.
  • 4545 / tcp - erschien nach dem letzten Firmware-Update. Nmap weiß nichts über ihn. Beim Versuch, eine Verbindung herzustellen, wird sofort json mit dem aktuellen Wiedergabestatus gesendet und jede Sekunde ein Update gesendet

    Datenblock mit Wiedergabestatus
     { "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" } 


    Wie gesagt, dieser Port erschien mit dem neuesten Update. Es gibt überhaupt keine Dokumentation aus dem Wort. Dies kann nützlich sein, um ein leichtes Bedienfeld zu entwickeln. Aber in diese Richtung habe ich noch nicht gegraben.
  • 5000 / tcp - nmap definiert es als Apple AirTunes. Es scheint wahr zu sein, da die Unterstützung für dieses Protokoll in der Dokumentation angegeben ist.
  • 8008 / tcp, 8009 / tcp - der Zweck ist nicht klar, nmap weiß nichts über sie.
  • 8080 / tcp - http-proxy, dessen Zweck im Kontext dieses Players nicht ganz klar ist.
  • 8888 / tcp - Protokollanschluss Universal Plug and Play (UpnP) . Mit dem Dienstprogramm gupnp-universal-cp aus dem Paket gupnp-tools können Sie dessen Beschreibung anzeigen:

    Zunächst wurde angenommen, dass das Management in der offiziellen Anwendung auf der Grundlage dieses speziellen Protokolls implementiert wurde. Wie sich später herausstellte, täuschte er sich. Ich habe auch mehrere UpnP-Clients ausprobiert, sowohl mobile als auch Desktop-Clients. Alle funktionieren praktisch nicht: Einige Steuerbefehle funktionieren, andere nicht, und es ist völlig chaotisch.
  • 10001 / tcp - ähnlich dem SCP-Konfigurationsport, aber wie man ihn benutzt, ist nicht klar.
  • 60128 / tcp - und schließlich die Hauptfigur dieses Artikels, der eISCP-Protokollport. Nmap weiß auch nichts über ihn. Öffnen wir den Schleier der Geheimhaltung.

Verkehrsanalyse


Lassen Sie uns nun überprüfen, welcher Port und wie die offizielle Anwendung mit dem Gerät kommuniziert. Der einfachste Weg, dies zu tun, ist auf einem gerooteten Android (aber nicht im Emulator, da die offizielle Anwendung ein verwaltetes Gerät im selben lokalen Subnetz erfordert). Dafür:

  • Installieren Sie Android tcpdump auf einem Android-Gerät, auf dem Onkyo Controller bereits installiert ist
  • Wir gehen über adb als root auf das Android-Gerät:

     > adb root && adb shell root@fiber-bs1078:/> 
  • Wechseln Sie in ein beliebiges Verzeichnis auf der integrierten SD-Karte:

     root@fiber-bs1078:/> cd /sdcard/work root@fiber-bs1078:/sdcard/work> 
  • Führen Sie tcpdump aus (mit Schreiben in Datei)

     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 
  • Wir starten die Onkyo-Anwendung und beginnen von dort aus mit der Musikwiedergabe
  • Wenn einige hundert Pakete eingegeben wurden, stoppen Sie tcpdump mit Cttl + C.
  • Wir kehren zum Terminal zurück, wo wir ADB gestartet und die Datei auf einen funktionierenden Computer kopiert haben

     root@fiber-bs1078:/sdcard/work> exit > adb pull /sdcard/work/onkyo.dump . [100%] /sdcard/work/onkyo.dump 
  • Starten Sie Wireshark und sehen Sie, was dort passiert.

     > wireshark onkyo.dump & 

Tatsächlich erfolgt die Kommunikation über Port 60128. Beispielsweise sendet die Anwendung eine Anfrage an den Player:



Und er antwortet ihm:



Wir kommen also zum Kern des Artikels, nämlich: Was ist es in den obigen Bildern für solche Briefe - ISCP? Diese Abkürzung bedeutet Integra Serial Control Protocol, das ursprünglich zur Steuerung von Onkyo-Geräten über den RS-232-Port entwickelt wurde (es gibt einen alten interessanten Artikel zu diesem Thema). Später wurde es um das Präfix „e“ erweitert und es stellte sich heraus, dass eISCP - Integra Serial Communication Protocol über Ethernet. Beide Versionen des Protokolls sind in der Technischen Dokumentation: Integriertes serielles Kommunikationsprotokoll für AV-Receiver beschrieben. Die erste Version des Dokuments ist vom 31. Oktober 2012, die letzte, die gefunden wurde, ist der 4. September 2017. Alle gefundenen Versionen werden in meinem Repository des Demo-Projekts gesammelt, über das ich später sprechen werde. Die weitere Präsentation basiert sowohl auf diesem Dokument als auch auf Experimenten mit meinem Player (die in diesem Dokument jedoch nicht ausdrücklich erwähnt werden).

Nachrichtenspezifikation


Der Client (z. B. eine mobile Anwendung) und das Gerät tauschen kurze Textnachrichten aus. Wenn Zahlen darin vorhanden sind, werden sie in der Regel in hexadezimaler Form dargestellt.

Das Nachrichtenformat vom Client zum Gerät ist sehr einfach:



Die Nachricht beginnt mit einem "!" - Zeichen, dann dem Zielgerätecode, gefolgt von drei Buchstaben des Befehls und einer Folge von Parametern beliebiger Länge. Endet mit einem CR (0x0D) oder LF (0x0A) oder einer Kombination von CR + LF.

Abhängig vom Befehl antwortet das Gerät entweder mit demselben Nachrichtentyp (wenn es sich um eine Anforderung für einen Parameter handelt) oder mit einem anderen Typ oder sogar einer Kombination von Nachrichten (wenn es sich um einen Befehl für eine komplexe Aktion handelt, z. B. das Wechseln einer Spur). Das Format der vom Gerät an den Client gesendeten Nachrichten ist dasselbe. Der Unterschied liegt nur im letzten Byte:



Das Protokollbeschreibungsdokument enthält mehr als hundert verschiedene Befehle. Mein Gerät unterstützt etwas mehr als 30 Befehle aus diesem Dokument. Das heißt, sowohl der Befehlssatz als auch die gültigen Parameter hängen vom jeweiligen Gerät ab.

Befehle können in logische Gruppen gruppiert werden. Als Beispiel möchte ich Folgendes hervorheben:

  1. Allgemeine Geräteverwaltung:
    • NDN: Gerätename.
    • UPD: Überprüfen und Installieren eines Firmware-Updates.
    • PWR: Ein- / Ausschalten.
    • NRI: Erweiterte Geräteinformationen.
    • NTC: Befehle einer Standardfernbedienung (einschließlich Wiedergabesteuerung).
    • CAP: Befehle zur Steuerung eines externen Verstärkers, der an den RI-Anschluss angeschlossen ist.
  2. Informationen zum gespielten Titel:
    • NAL: Albumname.
    • NAT: Künstlername.
    • NTI: Titelname.
    • NFI: Verfolgen von Dateiinformationen (Format, Bitrate).
    • NJA: Ein Bild, das an eine Spur angehängt ist (z. B. das Emblem eines Radiosenders, wenn Internetradio ausgewählt ist).
    • NTM: aktuelle Zeitposition in der Spur.
    • NTS: Status, Rücklauf aktiviert oder nicht (für Internetradio beispielsweise nicht zulässig).
    • NST: Wiederholungs- und Zufallswiedergabesteuerung.
  3. Navigation und Verwaltung der Musikbibliothek:

    • SLI: Quellenauswahl (z. B. USB, Netzwerkdienste).
    • NSV: Wählen Sie einen bestimmten Netzwerkdienst aus (z. B. Internetradio, Musikserver). Die Wiedergabeliste auf meinem Gerät bezieht sich auch auf Netzwerkdienste, obwohl dies aus Sicht der Benutzeroberfläche nicht ganz offensichtlich ist. Und wenn Sie den Strom ausschalten (aus der Steckdose ziehen), wird diese Wiedergabeliste gelöscht!
    • NLT, NLA: Navigation durch Abschnitte (Ordner) der Bibliothek.
    • PQA, PQR, PQO: Wiedergabelistenverwaltung: Hinzufügen, Löschen, Neuordnen.

Natürlich ist diese Liste bei weitem nicht vollständig. Ich habe sie nur gegeben, um den Umfang und die Fähigkeiten dieses Protokolls aufzuzeigen.

In Bezug auf die Parameter können alle Nachrichten in zwei Gruppen unterteilt werden. Die erste Gruppe enthält die meisten Nachrichten. Für diese Gruppe enthält die Parameterzeichenfolge Daten in alphanumerischer oder hexadezimaler Form und wird byteweise analysiert. Wenn der Player beispielsweise zum TuneIn Radio-Dienst wechselt, sendet er eine NLT-Nachricht - Informationen zum Header der aktuellen Liste mit dem Parameter "0E01000000090100FF0E00TuneIn Radio", die gemäß der Spezifikation folgende Informationen dekodiert:

 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 

Fast alle Nachrichten haben den Parameter "QSTN", zum Beispiel "! 1NLTQSTN". Diese Anforderung bedeutet eine Anforderung an den Spieler, die aktuellen Statusinformationen zurückzugeben, die diesem Nachrichtentyp entsprechen. Es funktioniert fast immer, aber es gibt seltene Ausnahmen, wenn der Spieler abhängig von seiner internen Stimmung solche Anfragen ignoriert.

Die zweite Gruppe sind Nachrichten, bei denen der Parameter XML ist, die mit einem XML-Parser analysiert werden müssen. Im obigen Beispiel können Sie im Abschnitt TuneIn Radio eine NLA-Anfrage senden, an die Informationen zur aktiven Liste in XML beantwortet werden:

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

Das heißt, der Player stellt nicht nur Textinformationen bereit (die übrigens derzeit auf dem Display des Players selbst angezeigt werden), sondern weist auch auf ein geeignetes Symbol hin (Ordner, Musiktitel, aktuell abgespielter Titel).

In einigen Fällen möchte der Player eine Textnachricht in der Clientanwendung anzeigen oder zusätzliche Parameter wie den Benutzernamen anfordern. Zu diesem Zweck sendet der Player eine universelle Nachricht NCP (Universal Dialog), in der das XML die Struktur dessen beschreibt, was dem Benutzer angezeigt werden muss:

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

Als Antwort erwartet der Spieler dieselbe Nachricht mit den ausgefüllten Feldern (oder der gedrückten Taste).

Auch im XML-Format wird eine ziemlich wichtige NRI-Nachricht angezeigt - allgemeine Informationen zum Player. Die Nachricht ist groß genug, also verstecke ich sie unter dem Spoiler.

Allgemeine Informationen zum Spieler
 <?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> 


Der Befehlssatz, den Sie zur Steuerung des Geräts verwenden müssen, hängt weitgehend davon ab, was sich in den Abschnitten zonelist und controllerist dieser Nachricht befindet.

ISCP über Ethernet (eISCP)


Nachrichten in der Form, wie ich oben geschrieben habe, sind für die Übertragung über Kabel (RS-232) vorgesehen. Ältere Empfänger wurden dafür mit einem 9-poligen RS-232-Stecker ausgestattet. Als anstelle dieses Anschlusses eine Netzwerkverbindung (verkabelt oder drahtlos) verwendet wurde, mussten diese Nachrichten für die Übertragung über TCP / IP in einen Wrapper verpackt werden. So erschien das eISCP-Protokoll, in dem die ISCP-Nachricht in ein solches Paket eingeschlossen ist:



Unter dem Spoiler befindet sich der Code der Prozedur, die ein solches Paket für eine Nachricht mit einem bestimmten Code (variabler Code), einer Zeichenfolge von Parametern (variable Parameter) und einer bestimmten Protokollversion (variable Version) vollständig generiert. Da das Verfahren recht einfach ist, scheint mir Java-Code viel mehr als tausend Wörter zu sagen.

Verfahren zum Generieren einer eISCP-Nachricht
 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); // Message header for (int i = 0; i < MSG_START.length(); i++) { bytes[i] = (byte) MSG_START.charAt(i); } // Header size byte[] size = ByteBuffer.allocate(4).putInt(headerSize).array(); System.arraycopy(size, 0, bytes, 4, size.length); // Data size size = ByteBuffer.allocate(4).putInt(dataSize).array(); System.arraycopy(size, 0, bytes, 8, size.length); // Version bytes[12] = (byte) version; // CMD bytes[16] = (byte) START_CHAR.charValue(); bytes[17] = (byte) '1'; for (int i = 0; i < code.length(); i++) { bytes[i + 18] = (byte) code.charAt(i); } // Parameters for (int i = 0; i < parameters.length(); i++) { bytes[i + 21] = (byte) parameters.charAt(i); } // End char bytes[21 + parameters.length()] = (byte) LF; return bytes; } 


Wenn jemand interessiert ist, hier ist meine Beispielprotokollimplementierung für die Spezifikation Version 1.40 . Ich werde auch einen Link zu diesem Repository geben . Es implementiert eine Nachrichtenbibliothek und ein Befehlszeilenprogramm in Python sowie Links zu anderen ähnlichen Projekten.

Informationsaustausch implementieren


Die Nachrichten selbst, die ursprünglich für die Übertragung über ein Kabel mit niedriger Geschwindigkeit entwickelt wurden, sind recht klein. Darüber hinaus ist der Spieler selbst auch eher bescheiden - vor dem Hintergrund einer großen Menge von Statistiken, die irgendwo an den bedingten Amazon-Server gesendet werden, ist die Menge an Informationen, die der Spieler dem Client freiwillig über ISCP gibt, nur spärlich. In der Protokollspezifikation gibt es kein Wort darüber, wann und unter welchen Bedingungen der Spieler diese oder jene Informationen sendet. Daher musste ich mich hier lange genug experimentieren, damit der mobile Client immer alle notwendigen Informationen über den aktuellen Status des Geräts hatte.

Im Allgemeinen basiert die Kommunikation mit dem Spieler auf einem Anforderungs- / Antwortschema. Darüber hinaus ist in bestimmten Situationen eine einzelne Anforderung nicht beschränkt. Es gibt mehrere wichtige Ereignisse für meinen Spieler, die behandelt werden müssen:

  • Stellen Sie eine Verbindung her. Zum Zeitpunkt der Verbindung befindet sich der Player möglicherweise im Standby-Modus oder ist eingeschaltet, befindet sich möglicherweise im Wiedergabemodus oder pausiert. Es ist auch wichtig, sofort herauszufinden, in welcher Position sich der Eingangskanalschalter befindet - bei Netzwerkdiensten oder USB.

    Daher ist es unmittelbar nach dem Herstellen der Verbindung sinnvoll, PWR-Anforderungen (aktiv oder im Standby-Zustand), UPD (gibt es ein Firmware-Update), NRI (allgemeine Informationen zum Gerät), SLI (Position des Eingangsschalters), NJA (Übertragungsmodus des Bildes des Track-by) zu senden Link oder Stream). Mein Player sendet den Wiedergabestatus und die aktuelle Position von sich aus.
  • Starten Sie die Wiedergabe. In dieser Situation sendet der Spieler alle Informationen über die Strecke. Aber wenn der Spieler eine Verbindung herstellt und bereits etwas spielt, sendet er nichts. Wenn der Player den Titel wechselt, werden nicht alle Informationen gesendet.

    Eine universelle, wenn auch ressourcenintensive Lösung bestand darin, die NST-Nachricht (Wiedergabestatus) zu verfolgen. Wenn dieser Status auf „Wiedergabe“ umgeschaltet wurde, senden Sie sofort 7 Anfragen: NAT (Künstler), NAL (Albumtitel), NTI (Titeltitel), NFI (Dateiinformationen), NTR (Titelnummer), NTM (aktuelle Wiedergabezeit), NMS (Titelmenü). Es gibt Funktionen in der Firmware des Players. Wenn Sie beispielsweise eine Wiedergabeliste abspielen, möchte der Spieler die Nummer des abgespielten Titels nicht preisgeben. Im Allgemeinen können Sie jedoch den aktuellen Status der Wiedergabe ausreichend detailliert kennenlernen.
  • ( ) . - . , . — 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)] 


    , . , , , .


- Onkyo NS-6130. , Onkyo NS-6170. - Onkyo , , , , . - , .

, . :

  • . , . , RI Onkyo. , , , .









, 10 , , . , , . , , .

- Onkyo , , .

Vielen Dank für Ihre Aufmerksamkeit!

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


All Articles