Imagine being able to listen in on your scanner from any location with internet access, or “on the go” on your mobile device.
This article explains how you can turn your scanner into a web radio, for broadcasting online. In this tutorial we will implement the following features:
- continous 24/7 streaming
- voice activated recording on external USB stick
- daily log with timestamped entries of logged frequencies
- management of Icecast / monit / webmin through web interfaces
Since we will be picking up more than just one frequency, it will be good to know which that frequency is. We need some way to communicate with the scanner, that’s why the serial port is very useful.
There is a simple communications protocol used by Uniden to interact with their radios. A very useful feature is the radio’s ability to inform us whenever the squelch has broken. This will save us from having to poll the radio during regular intervals! And our python script will be event triggered basically by the radio itself to query the radio about the current frequency. This information will then be passed to Icecast’s server metadata information. Streaming players that can handle this information will then display this metadata which is normally used for the current playing song title. We will instead send the currently reported frequency!
When selecting a device for a streamer, keep in mind that you will need a integrated sound card, or you will need an external “add on” USB sound card. A serial port is also recommended if possible for reasons that will be explained above.
As a streaming device I chose the DreamPlug from Globalscale, but any other Linux single board computer will do. Here you can see how it compares to other boards out there. DreamPlug has a single core 1.2 GHz ARM processor with a half GB of RAM. As you can see from the pictures below it offers a lot of connectors but of most importance to us is the microphone input and the LAN port.
Since our device will be online 24/7 its important to keep power consumption as low as possible, not only for the electrical bill, but also since we want our setup to be environmentally friendly! Power consumption is an incredible 5 Watt! (1 A @ 5V)
The software we will use is freely available online from open source projects. Configuration does require some more fiddling on your part and doesn’t work straight “out of the box”, but that is also the fun part of putting all the pieces together.
On my setup, audio streaming is performed with the following software:
Icecast2 – streaming server software for streaming multimedia clients to connect to
DarkIce – a live audio streamer. It records audio from an audio interface (e.g. sound card), encodes it and delivers it to a streaming server.
Two programs are therefore involved in audio streaming. The streaming server (IceCast2) accepts connections from two entities. The audio streamer (DarkIce) which provides the source of the audio. And the clients (VLC/Winamp) who connect to the server to access this audio stream. In a home setup, these two usually coexist in the same machine. If you intend to have a large scale deployment though you could outsource the server part (which puts higher demands on hardware and especially bandwidth).
The Icecast service is configured through an XML formatted file /etc/icecast2/icecast.xml
Here you have to pass critical information, such as the credentials for
- optional password for the audio feeds
- required password for the sources providing the streams (darkice)
- required password for the administrator login in through the web interface In my setup the mountpoint is called “/live”.
I noticed that you can totally omit the mountpoint information, in that case it will be created with whatever information is supplied by darkice (assuming the souce password is correct)
The Darkice client is configured through a normal configuration file. If you don’t find it in /etc/darkice.cfg , create it with contents similar to:
[general] duration = 0 # duration of encoding, in seconds. 0 means forever bufferSecs = 5 # size of internal slip buffer, in seconds reconnect = yes # reconnect to the server(s) if disconnected # this section describes the audio input that will be streamed [input] device = default sampleRate = 8000 bitsPerSample = 16 channel = 1 # channels. 1 = mono, 2 = stereo # this section describes a streaming connection to an IceCast2 server # there may be up to 8 of these sections, named [icecast2-0] ... [icecast2-7] # these can be mixed with [icecast-x] and [shoutcast-x] sections [icecast2-0] bitrateMode = cbr # average bit rate format = mp3 # format of the stream bitrate = 32 # bitrate of the stream sent to the server server = localhost # host name of the server port = 8000 # port of the IceCast2 server, usually 8000 password = hackme # source password to the IceCast2 server mountPoint = live # mount point of this stream on the IceCast2 server name = GerakiATC # name of the stream description = Live Air Traffic Control # description of the stream url = http://www.tekmanoid.com # URL related to the stream genre = scanner # genre of the stream public = no # advertise this stream?a
Additional programs used
Monit is program that monitors the “health” of deamon processes / servers by keeping an eye on CPU / memory usage, response or the lack of it to a service port. In my configuration its used to monitor the IceCast / DarkIce processes.
- Icecast: check that port 8000 responds to HTTP request and that process is up and running -else, report and restart process.
- DarkIce: check that process is up and running. DarkIce is configured as a process that depends on IceCast and restarts BOTH if one has failed.
Additionally I added the option to be informed by email whenever the state of these programs change. You have to know the SMTP server settings for this.
screen is a “window manager”. In this project it is used to start the Python scripts and let them output to stdout. It allows the user to execute the program and then “detach” from the screen while the program is still running in the background.
serproxy is a program that redirects serial ports to network ports. Most programming languages have well defined ways of creating sockets for connecting to network interfaces. Serial ports can be more challenging. That is where serproxy comes in to simplify things. Configuration file /etc/serproxy.cfg
root@dreamplug:~# cat /etc/serproxy.cfg # Config file for serproxy # See serproxy 's README file for documentation # Comm ports used comm_ports=1 # Default settings comm_baud=19200 comm_databits=8 comm_stopbits=1 comm_parity=none # Idle time out in seconds timeout=300 # Port 1 settings (ttyS0) net_port1=5331
ddclient is a deamon program used to update DNS entries whenever it detects a change in the assigned public IP. Most home routers allow this configuration through their own interface, and you can select that option if you want.
# Configuration file for ddclient generated by debconf # # /etc/ddclient.conf protocol=dyndns2 use=web, web=checkip.dyndns.com/, web-skip='IP Address' server=dynupdate.no-ip.com login=yourusername password='hackme' myregistered-dns-name.com
usbmount used to automatically and safely mount and unmount pen-drives, used here as external media for storing our voice activated recordings. USB devices will be assigned the following mountpoints /media/usbX where X is a digit from 0 to 7.
Free serial port connected to console, for connection to radio’s COM port
The COM port is already internally “wired” to the linux console, as a last resort connection mechanism in case the SSH service should fail for some reason, ban you, or any other reason. NOTE: For communicating with Dreamplug (or any other “plug PC” for that matter) using another PC port, you will have to connect the two using a null-modem cable, and not a classic serial port extension cable.
Lets assume now that nothing will ever go wrong with our SSH connections and “disconnect” our COM port from the console and use it like we please.
First check the current settings of the COM port:
stty < /dev/ttyS0
Check also whether a process is already using the COM port:
ps -ef | grep tty root 2061 ttyS0 00:00:00 /sbin/getty -L ttyS0 115200 linux
This process is started during system startup from the /etc/inittab file. In it we find indeed the following line:
# Example how to put a getty on a serial line (for a terminal) T0:23:respawn:/sbin/getty -L ttyS0 115200 linux
All we need to do now is comment out this line and reboot.
Running automatically on startup
The sole purpose of this device will be to act as an streaming server. This device should be purely “plug and play”, therefore we have to fire all required services right after startup in an automated fashion. We will use: /etc/rc.local As it says in the comment section, “this file is executed at the end of each multiuser runlevel”. We will add a call to our startup bash script located in /root/scripts/startup.sh that will initiate all necessary services and programs for our streaming server.
startup.sh #icecast auto started by init.d #start darkice
/usr/bin/screen -S darkice -d -m /usr/local/bin/darkice#seems to be required for serial port /bin/stty -F /dev/ttyS0 19200 time 5 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke #start serproxy /usr/bin/screen -S serproxy -d -m /usr/local/bin/serproxy #start python script /usr/bin/screen -S ubc780 -d -m python /root/scripts/ubc780.py #set blue LED on Dreamplug to indicate all services running echo 1 >
IceCast & Darkice
Alternatively, these services can be set to run automatically on startup by setting their configuration file in /etc/default
root@dreamplug:~# cat /etc/default/darkice # Defaults for darkice initscript # sourced by /etc/init.d/darkice # installed at /etc/default/darkice by the maintainer scripts # # This is a POSIX shell fragment # RUN=yes # Additional options that are passed to the Daemon. DAEMON_OPTS="" USER=root GROUP=staff
The Icecast / Darkice init scripts did not seem to work with the start/stop/status commands. For some reason the init scripts darkice.pid and icecast2.pid did not the pid files with the current process IDs. To fix I added the “–make-pidfile” flag to the start-stop-deamon command below
start-stop-daemon --start --quiet --pidfile $PIDFILE \ --background --chuid $USER:$GROUP --exec $DAEMON --make-pidfile
and similarly for Icecast
# Defaults for icecast2 initscript # sourced by /etc/init.d/icecast2 # installed at /etc/default/icecast2 by the maintainer scripts # This is a POSIX shell fragment # Full path to the server configuration file CONFIGFILE="/etc/icecast2/icecast.xml" # Name or ID of the user and group the daemon should run under USERID=icecast2 GROUPID=icecast # Edit /etc/icecast2/icecast.xml and change at least the passwords. # Change this to true when done to enable the init.d script ENABLE=true
Open ports on router
The result of the netstat -ntlp command gives us a quick look at what services are running and on which ports. This is no guarantee that they are running correctly, but still a first indication.
As you can see, a number of ports are used, that need to be port-forwarded correctly through the router in order for our services to be visible and available to the “outside world”.
- 8000 – IceCast2
- 2812 – Monit
- 5331 – Serproxy
- 10000 – Webmin
You will have to port forward the streaming port 8000 to the same or another external port of your choice in the routers application / port configuration page. Besides the 8000 port you might want to forward also other services.
Set static IP on streaming device
By default these devices have DHCP enabled in /etc/network/interfaces configuration file. It would be a good advice to alter these settings and use a static IP like in the example below, were IP 192.168.1.100 is used.
auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 192.168.1.100 netmask 255.255.255.0 network 192.168.1.0 broadcast 192.168.1.255 gateway 192.168.1.254 auto eth1 iface eth1 inet dhcp
Register a domain name on a Dynamic DNS service
Since anyone running a similar setup will most likely be behind a dynamic IP assignment by the Internet provider, we need a domain name with which the service can be reached. There are a number of dynamic IP registers out there, some of them are free and might require the host-name to be confirmed during regular (monthly) periods. You will have to set the appropriate information in /etc/ddclient.conf configuration file! See section above on ddclient.
Python script automation
- looprecorder.py – Voice Activated (VOX) recorder. Records audio that surpasses a minimal threshold. The recordings are saved to an external USB device. I would recommend getting one with a LED indicator, to have visual feedback of whenever a “read/write” is taking place. The recording are saved as raw WAV files. At midnight these files are re-encoded to MP3 files and the process terminates. This script has been added to a daily crontab at 00.00 every night for automatic startup. At the end of the day you end up with a daily recording with the date stamp as the filename.
- bc780.py – Radio interface. Connects to the serial port of the radio. Activates the “Squelch report” option (QUN command) that sends (asynchronously) a “+” character whenever the squelch on the radio is broken, which means that a reception is being made.
Run alsamixer to set the microphone levels to an adequate amount around 30% on my system and with the “autogain” set to disabled (press M)
There are a number of players out there that support streaming audio, but we should prefer the ones that have metadata support so we can see the tuned frequency baked into the stream!
A personal favourite that dates back to the Napster era is Winamp. Enter your server’s URL as such:
Hopefully you should see the player starting to buffer and connecting to the stream successfully.
Listening behind a proxy
If you plan to connect with your client from a corporate environment you will most likely be sitting behind a proxy. You will have to know the proxy IP address and configure this in the client player’s configuration.
That’s all folks! Enjoy listening to your scanner online!