It’s actually pretty simple: a Ruby script with three threads.
One thread listens on the TCP connection to the AVR. The format of incoming messages from the AVR is one or more letters followed by a number (or, in a few cases, a string of numbers and letters). When a message comes in, an MQTT message is issued, with topic stat/pioneer/ with message contents what follows after the initial letters. For instance, if the AVR says VOL120 (“current volume is 120”), an MQTT message to stat/pioneer/VOL with contents “120” is sent. Thereby, all status message become accessible through MQTT.
The second thread subscribes to MQTT messages for topics cmnd/pioneer/#. If a message with such a topic comes in, the third component of the topic and the contents of the message are concatenated and forwarded to the receiver. For instance, by publishing an MQTT message to cmnd/pioneer/VL with contents “100”, you can have “VL100” sent to the avr, which will set the volume level to 100.
The third thread periodically issues status requests (for audio+video status) to the avr. The thereby triggered status response messages are published by the first thread.
This direct 1:1 interface between MQTT and Pioneer’s protocol gives full access to all features. It just turned out that the Pioneer protocol design is not very clean and systematic, and sometimes it was a bit of a hassle to integrate it in OpenHab. For example, to mute the receiver you have to say “MO” (or, via MQTT, cmnd/pioneer/MO), and “MF” (or cmnd/pioneer/MF) to unmute. There is no “MUTE1”/“MUTE0”-like command which you could easily integrate via the Generic MQTT binding.
To make things a bit more convenient I added a few more MQTT topics that are generated (stat/pioneer/power, stat/pioneer/mute, stat/pioneer/volume,…) and understood (cmnd/pioneer/…).
The code is currently not very clean, and probably not production ready. It tries re-connecting quite aggressively to the avr, for instance (necessary in my case, because I turn it off completely rather than sending it to standby, and want it to respond quickly after re-powering). Not everyone might want to have it done that way in their network.
Nevertheless, I’d of course be happy to share if someone is interested and wants to give it a try.