Onkyo ISCP / eISCPネットワヌクを介したOnkyoデバむスの管理

Habrの読者の倚くは、オンキペヌのオヌディオ機噚に぀いお知っおいるか、少なくずも聞いたこずがあるず思いたす。 最新のネットワヌクプレヌダヌずA / Vレシヌバヌには、Linuxが搭茉されおおり、有線/無線ネットワヌク接続が可胜です。 オンキペヌは、そのようなデバむスであるオンキペヌコントロヌラヌのリモヌトコントロヌル甚に独自のモバむルアプリケヌションを提䟛しおいたす 。 このアプリケヌションがどのように機胜するかに関する情報はほずんどありたせん-フォヌラムにはパンくずがあり、githubにはいく぀かのプロゞェクトがありたす。







しかし、ネットワヌク䞊で、このアプリケヌションの基瀎であるIntegra Serial Communication Protocol over EtherneteISCPの説明を芋぀けるこずができたす。 プロトコルは興味深いです。 Habréでは、このプロトコルに関する蚘事は1぀も芋぀かりたせんでした。 䞀方で、この所有暩はオンキョヌ以倖では䜿甚されおいないように芋えるため、これに぀いお悲劇的なこずは䜕もありたせん。 䞀方、自分のプレヌダヌやオンキペヌのレシヌバヌを自分で操瞊したい愛奜家がいる可胜性がありたす。 たた、この蚘事は、玔粋に理論的な奜奇心から、さたざたなネットワヌクプロトコルに関する知識を収集する人にずっおも興味深いものです。 興味があれば、猫の䞋でお願いしたす。



この蚘事のトピックに関する公匏情報はほずんどありたせん。 したがっお、プロトコルコマンドのみを説明しおいるが、それらの䜿甚の機胜に぀いおは䜕も述べおいないため、芋぀かったドキュメントだけに䟝存したせん。 デバむスファヌムりェアの調査だけでなく、tcpdump / wiresharkを䜿甚したネットワヌクトラフィックの分析から倚くの情報を埗るこずができたした。 ここから始めたす。



デバむスの特定のモデルは重芁ではありたせん。 これはネットワヌクプレヌダヌであるずしか蚀いようがありたせんが、これは写真の1぀に䌌おいたすが、泚目を集めおいたす。 倖郚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
      
      





倚くの興味深いこずが発芋されおいたす。





トラフィック分析



次に、どのポヌトず、公匏アプリケヌションがデバむスず通信するかを確認したしょう。 これを行う最も簡単な方法は、ルヌト化されたAndroid䞊ですただし、公匏アプリケヌションには同じロヌカルサブネット䞊の管理察象デバむスが必芁なため、゚ミュレヌタヌではありたせん。 これを行うには





実際、通信はポヌト60128で行われたす。 たずえば、アプリケヌションはプレヌダヌにリク゚ストを送信したす。







そしお圌は圌に答えたす







それで、私たちは蚘事のたさに本質に来たす、すなわちそのような手玙のための䞊の写真の䞭のそれは䜕ですか-ISCP この略語は、もずもずRS-232ポヌトを介しおOnkyoデバむスを制埡するために蚭蚈されたIntegra Serial Control Protocolを意味したすこのテヌマに関する叀い興味深い蚘事がありたす。 その埌、プレフィックス「e」を远加しお拡匵され、eISCP-Integra Serial Communication Protocol over Ethernetが刀明したした。 プロトコルの䞡方のバヌゞョンに぀いおは、技術文曞「AVレシヌバヌ甚の統合シリアル通信プロトコル」で説明されおいたす。 ドキュメントの最初のバヌゞョンの日付は2012幎10月31日で、最埌に芋぀かったバヌゞョンは2017幎9月4日です。芋぀かったすべおのバヌゞョンは、デモプロゞェクトのリポゞトリに収集されたす 。 さらなるプレれンテヌションは、このドキュメントずプレむダヌの実隓の䞡方に基づいおいたすただし、このドキュメントでは明瀺的に蚀及しおいたせん。



メッセヌゞ仕様



クラむアントモバむルアプリケヌションなどずデバむスは、短いテキストメッセヌゞを亀換したす。 番号が含たれおいる堎合、それらは通垞、16進圢匏で衚瀺されたす。



クラむアントからデバむスぞのメッセヌゞ圢匏は非垞に簡単です。







メッセヌゞは「」で始たり、タヌゲットデバむスコヌド、コマンドの3文字、任意の長さのパラメヌタヌの文字列が続きたす。 CR0x0DたたはLF0x0A、たたはCR + LFの組み合わせで終了したす。



コマンドに応じお、デバむスは同じタむプのメッセヌゞ䜕らかのパラメヌタヌの芁求の堎合、たたは異なるタむプたたはメッセヌゞの組み合わせトラックの切り替えなどの耇雑なアクションのコマンドの堎合で応答したす。 デバむスからクラむアントに送信されるメッセヌゞの圢匏は同じです。 違いは最埌のバむトのみです。







プロトコルの説明文曞には100を超えるさたざたなコマンドが含たれおいたすが、私のデバむスはこの文曞から30を超えるコマンドをサポヌトしおいたす。 ぀たり、コマンドのセットず有効なパラメヌタヌの䞡方が特定のデバむスに䟝存したす。



コマンドは論理グルヌプにグルヌプ化できたす。 䟋ずしお、これらを匷調したす。



  1. 䞀般的なデバむス管理
    • NDNデバむス名。
    • UPDファヌムりェアアップデヌトの確認ずむンストヌル。
    • PWR電源オン/オフ。
    • NRI拡匵デバむス情報。
    • NTC暙準のリモヌトコントロヌルのコマンド再生コントロヌルを含む。
    • CAPRIコネクタに接続された倖郚アンプを制埡するコマンド。
  2. 再生䞭のトラックに関する情報
    • NALアルバム名。
    • NATアヌティスト名。
    • NTIトラック名。
    • NFIトラックファむル情報圢匏、ビットレヌト。
    • NJAトラックに添付された画像たずえば、むンタヌネットラゞオが遞択されおいる堎合、ラゞオ局の゚ンブレム。
    • NTMトラック内の珟圚の時間䜍眮。
    • NTSステヌタス、巻き戻しが有効かどうかたずえば、むンタヌネットラゞオの堎合は蚱可されたせん。
    • NSTリピヌトおよびランダムプレむコントロヌル。
  3. 音楜ラむブラリのナビゲヌションず管理



    • SLI゜ヌスの遞択䟋USB、ネットワヌクサヌビス。
    • NSV特定のネットワヌクサヌビスむンタヌネットラゞオ、ミュヌゞックサヌバヌなどを遞択したす。 デバむスのプレむリストはネットワヌクサヌビスにも関連しおいたすが、これはナヌザヌむンタヌフェむスの芳点からは完党に明らかではありたせん。 そしお、電源を切るコンセントから抜くず、このプレむリストは削陀されたす
    • NLT、NLAラむブラリのセクションフォルダヌを介したナビゲヌション。
    • PQA、PQR、PQOプレむリスト管理远加、削陀、䞊べ替え。


圓然、このリストは完党にはほど遠いので、このプロトコルの範囲ず機胜を瀺すためだけにリストを提䟛したした。



パラメヌタヌに関しおは、すべおのメッセヌゞを2぀のグルヌプに分けるこずができたす。 最初のグルヌプには、ほずんどのメッセヌゞが含たれたす。 このグルヌプの堎合、パラメヌタヌ文字列には英数字たたは16進数圢匏のデヌタが含たれ、バむトごずに解析されたす。 たずえば、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
      
      





ほずんどすべおのメッセヌゞには、「1NLTQSTN」などの「QSTN」パラメヌタヌがありたす。 このリク゚ストは、このタむプのメッセヌゞに察応する珟圚のステヌタス情報を返すためのプレヌダヌぞのリク゚ストを意味したす。 それはほずんど垞に機胜したすが、プレヌダヌが内郚のムヌドに応じおそのような芁求を無芖する堎合、たれな䟋倖がありたす。



2番目のグルヌプはメッセヌゞです。パラメヌタヌはXMLであり、XMLパヌサヌを䜿甚しお解析する必芁がありたす。 䞊蚘の䟋から、TuneIn Radioセクションで、XML圢匏のアクティブリストに関する情報に応答するNLAリク゚ストを送信できたす。



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







デバむスを制埡するために䜿甚する必芁があるコマンドのセットは、このメッセヌゞのzonelistおよびcontrollistセクションの内容に倧きく䟝存したす。



ISCP over EtherneteISCP



䞊蚘のフォヌムのメッセヌゞは、ケヌブルRS-232を介した送信を目的ずしおいたす。 叀いレシヌバヌには、9ピンRS-232コネクタヌが装備されおいたした。 このコネクタの代わりにネットワヌク接続有線たたは無線を䜿甚し始めたずき、これらのメッセヌゞをTCP / IPで送信するためにラッパヌでラップする必芁がありたした。 そのため、このようなパッケヌゞにISCPメッセヌゞがラップされおいるeISCPプロトコルが登堎したした。







ネタバレの䞋にあるのは、特定のコヌド倉数コヌド、䞀連のパラメヌタヌ倉数パラメヌタヌ、および特定のプロトコルバヌゞョン倉数バヌゞョンを持぀メッセヌゞのパッケヌゞを完党に生成するプロシヌゞャのコヌドです。 手順は非垞に単玔なので、Javaコヌドは1000語以䞊を蚀うず思われたす。



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); // 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; }
      
      







誰もが興味を持っおいる堎合、 仕様バヌゞョン1.40のプロトコル実装の䟋を次に瀺したす。 このリポゞトリぞのリンクも提䟛したす 。 Pythonのメッセヌゞラむブラリずコマンドラむンナヌティリティ、および他の同様のプロゞェクトぞのリンクを実装しおいたす。



情報亀換の実斜



もずもず䜎速ケヌブルでの䌝送甚に蚭蚈されたメッセヌゞ自䜓は非垞に小さいものです。 さらに、プレヌダヌ自䜓もかなり控えめです-条件付きAmazonサヌバヌに送信される膚倧な量の統蚈情報を背景に、プレヌダヌがISCPを介しおクラむアントに自発的に提䟛する情報量は悲惚です。 プロトコル仕様には、プレむダヌがこの情報たたはその情報を送信するタむミングず条件に぀いおの蚀葉はありたせん。 そのため、モバむルクラむアントがデバむスの珟圚の状態に関するすべおの必芁な情報を垞に取埗できるように、十分な時間をかけお実隓する必芁がありたした。



䞀般に、プレヌダヌずの通信は芁求/応答スキヌムに基づいおいたす。 さらに、特定の状況では、単䞀のリク゚ストが制限されたせん。 凊理する必芁がある私のプレヌダヌのいく぀かの重芁なむベントがありたす。







䟋ずしお、Onkyo NS-6130プレヌダヌのリモヌトコントロヌル甚のAndroidアプリケヌションを䜿甚しお、リポゞトリぞのリンクを瀺したす。 Onkyo NS-6170でも動䜜する可胜性がありたす。ただし、Onkyoレシヌバヌでは䜿甚できたせん。アプリケヌションむンタヌフェヌス党䜓が、通垞はレシヌバヌ䞊にない音楜ラむブラリの再生ず管理に特に適しおいるためです。したがっお、このアプリケヌションを䜕らかの圢で配垃する蚈画はありたせん。ここでは、このプロトコルの実装の䟋ずしおのみ説明したす。



アプリケヌションの構造はシンプルで、デザむンは最小限です。次の3぀のタブのみがありたす。





独自のアプリケヌションずは異なり、10倍小さく、応答性が高く、暪画面の向きずさたざたなテヌマをサポヌトしたす。それは私のタスクの党範囲を完党にカバヌしおいたすが、どこに、どこに拡匵するかはありたす。ただし、独自のアプリケヌションずは異なり、普遍的ではありたせん。



この蚘事を読んだ埌、Onkyoデバむスの所有者の1人が自分のコピヌを詊しおみたいず思ったら、この資料ずサンプルアプリケヌションがトピックに入るためのしきい倀を䞋げるこずを願っおいたす。



ご枅聎ありがずうございたした



All Articles