mailto: blog -at- heyrick -dot- eu

Denver IR-135B simple control

The internet radio has a server built into it which can be used to provide some measure of remote control of the device.

My radio is at IP address, so the following examples will reflect this. Simply set the appropriate IP address and you're good to go.


Detecting the radio

It isn't advisable to open port 80 and try to fetch "/" because while that will identify the server as "esp32-httpd/0.1", I'm not sure what other ESP32 devices might use the same server code.
It might be a better positive identification to try fetching "/php/playing.php". This is discussed below.

If you only have the one ESP32 device, then it might suffice to sniff the header. It looks like this:

HTTP/1.0 200 OK
Server: esp32-httpd/0.1
Connection: close
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Content-Length: 652
Cache-Control: max-age=3600, must-revalidate

This will be followed by some gibberish that is the gzipped page content.


What's playing?

This will report the current radio station and playback state.

{ "name":"100.7 The Bay - WZBA","error":"n","chStatus":"Play state: playing","AddDelBtn":"D","result":"success"}

Or if not playing:

{ "name":"Love 80s (Manchester)","error":"n","chStatus":"Play state: stopped","AddDelBtn":"D","result":"success"}

Other play states may be "paused", and I think I once saw "buffering" which implies there may be states such as connecting to server... but the device server is slow, so there's a chance you'll actually be connected to a station before you get a response. ☺

If nothing is playing or was playing, then you may see:

{ "result":"fail"}

Note that if you are using Media Player (play from NAS) or Bluetooth mode, the internal server is disabled and there will be no response.

The radio only reports the station currently playing. There does not appear to be a way to read any information on the stream itself, so you can't see what is actually being played. Shame.


Retrieving the list of favourite stations

Annoyingly, it is listed in groups of ten stations. So you need to retrieve the stations ten at a time starting from page zero.

This will return a line like:

favListInfo = {curPage:0, total:0, favCapacity:150, itemsPerPage:10, chIndex:-1, rowIdx:-1, curPageCount:-1};

You can pretty much ignore this line as it is repeated at the end with some actual information.

Next you'll see:

myFavChannelList = [];
myFavChannelList.push(["<channel name>","<channel URL>,<user>,[[3,15,109],[2,48]]]);
myFavChannelList.push(["<channel name>","<channel URL>,<user>,[[3,15,109],[2,48]]]);

I have not yet fully decoded the numbers. I'm guessing one is the country, while the other is the genre.

If "user" is set to 0, then there will be a URL present.
If "user" is set to 1, then this is something that is looked up on Skytune, and as such the URL will read "****** Channel URL is maintained by Skytune".
There does not appear to be any method of retrieving the streaming URL actually used.

Finally, we'll see favListInfo again, this time with better data.

favListInfo = {curPage:0, total:14, favCapacity:150, itemsPerPage:10, chIndex:-1, rowIdx:-1, curPageCount:10};
"curPage" is the current page of results (starting from 0).
"total" is the total number of stations currently defined in favourites.
"favCapacity" is the maximum possible number of favourites.
"itemsPerPage" is how many stations can be shown on one page.
"chIndex" and "rowIdx" always seem to be -1.
And finally "curPageCount" is how many stations were on this page.

Note that when the messing with the number buttons messed up my favourites, some of the entries in the list were empty, so it is entirely possible to have blank entries in-line. I'm guessing they might simply have the first two fields as "" and either zeros or gibberish for the numbers?


Playing a station from favourites<station number>

This will play the specified station. Note that stations count from zero, so use '3' to play the fourth station...


Playing a station from Skytune

More work to do. It seems that the request sent to the radio is:

But how does it know the station to play? I think I might have to fire up the PC and sniff what's actually being sent. I suspect it's a POST request.

Note that you would need to scrape Skytune in order to determine what data to actually send to the radio, so this is perhaps best used in tandem with the Skytune site rather than trying to play random stations.


Controlling the volume<action>

Where action is:

  • -1 to make the sound quieter
  • 1 to make the sound louder
  • 128 to mute the sound
  • 0 to unmute the sound

Changing volume will also unmute sound if it is muted.
There doesn't appear to be a way to set a specific sound level, only to modify the current.

It will reply with something like:

or, obviously, muted as true if it is. The volume 'level' number appears to increment in groups of 8 or so, with '5' being the maximum volume.
Stepping back one from maximum returns the level as '4'.


Adding a station to your favourites

To come. It is sniffed as so I'm guessing the payload is a POST request.


Editing stations

As for adding, it'll likely be a POST request.


Deleting a station from your favourites<station number>

This will delete the specified station. Remember, it counts from zero...


Moving stations

I wouldn't recommend it. In my testing, it correctly moved the desired stations, it just didn't necessarily put them in the expected places.
It might be better to use the radio itself if you wish to set a station as one of the numbered buttons. Use "Move to top" and then, if necessary, "Move down" to put it in the wanted place.


Backing up your favourites

This will hand you a base64 encoded file of gibberish that represents your favourites. Encoding unknown. Tossing it at Squash_Decompress causes an abort, so it's not standard 12 bit LZW. An online gzip decoder also failed, so it's not gzip...


Restoring favourites

Will likely need to send the file as a POST embed. But pray you don't need to. It works (I needed to do it), but it takes forever. Is it repeatedly flashing the block entry by entry instead of, you know, doing something halfway intelligent?


Reading the country/genre list

This will return a long list of data, in the form:

mCountryList = [
   ...snip a LOT...

mGenreList  = [
,[2,88,'00s & 10s']
   ...snip more...
,[1,10,'Science & Technology']
The genre list is broken. It gives up after "Office" and doesn't have any Pop, Rock, or the like.


Anything else?

Not that I have seen. The commands provided is more or less that which is required to support the functionality of the internal server. Namely, to manage the favourites list, with some basic volume control thrown in as a bonus.

There does not appear to be a way to set an absolute volume, choose an EQ profile, or retrieve stream information. This stuff isn't really intended for remote control, it's just there to support managing the favourites list.
Which is, honestly, really really useful as the radio won't become completely useless should anything happen to Skytune.
You know, like what happened to Reciva, that did render a fair few devices inoperable.



Your comments:

Please note that while I check this page every so often, I am not able to control what users write; therefore I disclaim all liability for unpleasant and/or infringing and/or defamatory material. Undesired content will be removed as soon as it is noticed. By leaving a comment, you agree not to post material that is illegal or in bad taste, and you should be aware that the time and your IP address are both recorded, should it be necessary to find out who you are. Oh, and don't bother trying to inline HTML. I'm not that stupid! ☺ ADDING COMMENTS DOES NOT WORK IF READING TRANSLATED VERSIONS.
You can now follow comment additions with the comment RSS feed. This is distinct from the b.log RSS feed, so you can subscribe to one or both as you wish.

Anon, 11th January 2023, 20:00
A few years ago I had something called an "Audiotron" from Turtle Beach. This was a 17" wide "hi-fi separate" style unit that looked a little like a tuner. The Internet Radio function on it relied upon a "Turtle Radio" server; when Turtle Beach inevitably pulled support for it some 18 months after discontinuing the product, users were left in the same position as you mentioned with the 'Reciva' service. 
However, give Turtle Beach their credit, when they pulled the plug on Turtle Radio they did in fact release details of a previously undocumented "hidden" config option on the Audiotron which would allow it to use a local list of radio stations. 
Some time after that, an enterprising user re-registered the '' domain and set up a work-alike server on it, so the internet radio function on these devices (which are knocking on the door of 20 years old) functions once again without 'tinkering'. 
Personally I only used the Audiotron for playing back MP3 files through the local network, but I migrated to the Squeezebox platform a few years back for various reasons: 
- The Audiotron ran on WinCE, and only natively supported MP3, WAV or WMA files (unsure about WMA Lossless). There was no support for FLAC. 
- The analogue output on the Audiotron was fairly dire. Its attraction was that it had an optical digital output, which (unlike most streamers at the time) ran at 44.1kHz. This meant you could play CD rips without resampling. 
- The Ethernet interface was only 10Mbit. Fine for streaming MP3 files but not so fine when it did its initial scan for media. Even if you used a pre-cached TOC file it could take 10 minutes to load a database of around 10,000 songs. (The Squeezebox server, by comparison, can scan a database of 30,000 songs in about 7 minutes, and only needs to do this on the server.) 
Still, it was a pretty nice device for the time, at least when hooked up to a decent offboard DAC (or AV receiver) via the digital output. Did me well for about 12 years as my main music source until I switched everything to Squeezebox. 
Huge advantage with Squeezebox? Apart from that the hardware natively supports decoding FLAC (meaning that the server can just transcode any new formats into FLAC before streaming them out), the entire Squeezebox system, both server software and protocols, was open-source from the beginning. So when Logitech bought out Slim Devices, and a few years later discontinued the range, the software and players could continue to be developed. You can build a player using a Raspberry Pi for a few quid, and the software is still actively developed. 
The Audiotron? Because it ran WinCE and Turtle Beach couldn't release the operating software, the feature list of the product is stuck in the early 2000s.
Buckeye43210, 13th January 2023, 00:57
Could the last line of the export file be an encryption key?
Rick, 13th January 2023, 14:13
I would imagine if it is encrypted (why?! it's just the favourites list with most of the entries being handled by Skytune...), it's likely to be some sort of key built into the device, either hardcoded or based upon the hardware (like the MAC address). 
Lee, 20th June 2023, 08:10
I'm working on a python api for these devices and am finding similar things. The stations added via Skytune are somehow masked and perhaps indexed by a primary key, perhaps knowable from the station logo on the Skytune website. In any case being able to add our own URL's is a game changer. To unmask I'm trying to use pyradios to access the Community Radio Browser to provide an educated guess at replacing the URL that is managed by Skytune, 
Brad, 19th November 2023, 19:24
Thanks for all this. I too did a little work in python using some of the URLS. 
WIP too 
Radiolove, 29th November 2023, 01:08
Thanks. Is there an API call for pause or fast-forward /rewind (dlna)?
Radiolove, 29th November 2023, 01:51
Oh, I see the server is disabled for dlna.
Radiolove, 29th November 2023, 04:50
Ok, so I've loaded a few mp3 urls pulled from hour long podcasts into the favorites. Is there a way to get that to pause or fast-forward?
Berry, 11th December 2023, 12:12
Oh, you have been working on reverse engineering the API? Nice...

Add a comment (v0.11) [help?] . . . try the comment feed!
Your name
Your email (optional)
Validation Are you real? Please type 54912 backwards.
Your comment
French flagSpanish flagJapanese flag
«   January 2023   »

(Felicity? Marte? Find out!)

Last 5 entries

List all b.log entries

Return to the site index



Search Rick's b.log!

PS: Don't try to be clever.
It's a simple substring match.


Last read at 13:50 on 2024/05/26.

QR code

Valid HTML 4.01 Transitional
Valid CSS
Valid RSS 2.0


© 2023 Rick Murray
This web page is licenced for your personal, private, non-commercial use only. No automated processing by advertising systems is permitted.
RIPA notice: No consent is given for interception of page transmission.


Have you noticed the watermarks on pictures?
Next entry - 2023/01/11
Return to top of page