Using Python to Update Icecast Scanner Audio Feeds with a Raspberry Pi

Status
Not open for further replies.

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
Quite a few people have been using a Raspberry Pi to feed audio to Icecast and RR using Darkice. I wanted to go one step further and make it so both the audio and scanner metadata (alpha tags) could both be fed from the Raspberry Pi. I wrote a Python script to get data from Uniden scanners via serial and send this data to an Icecast server to update alpha tags in real time.

The script works with Uniden scanners. I haven't pursued GRE/RS scanners since they require a different device to connect. There's as yet a driver for the Radio Shack programming interface for the Raspberry Pi (perhaps someone with more Linux skills than mine could help write one.)

A special thanks to Uplink for helping me test and implement the script! His Raspberry Pi feed with alpha tags can be heard here: Los Angeles County Sheriff, Fire, and Aircraft - Santa Clarita Valley

The script and instructions can be found here:
http://www.k7bbr.net/projects/metapy.htm

Let me know if you have issues/need help implementing it. The data format can be changed to suit your needs/wants. Feel free to modify the script to fit your needs, or let me know, and I'd be glad to help you get the formatting right. I've also been working on other ideas to implement a basic logging function into the script. I'll post updates to the script if anyone is interested in this as well.
 

Uplink

Member
Joined
Feb 17, 2006
Messages
444
Location
Los Angeles County
Thanks so much Brandon! Your Python script has been running perfectly, and sending the alpha tags from my BCD996XT to the Raspberry PI. Very handy being able to see the freqs/names on Gordon's Scanner Radio app too! :D
 

Uplink

Member
Joined
Feb 17, 2006
Messages
444
Location
Los Angeles County
Just tested bbrasmussen's python script for my Uniden BC898T last night. Used the Uniden MetaPy8.py script - for the BCT8 model, and it works great! Plugged in a serial cable and now it can tag frequencies on the stream. An old scanner can be made into a nice streaming machine with alpha tags using the Raspberry Pi.

:D
 

aliby19

Member
Feed Provider
Joined
Mar 10, 2005
Messages
147
Location
Indianapolis, IN
Hello! I am trying to use the metapy script with my BCD996XT, but can't seem to get it to work. I have configured everything according to the instructions, but when I launch the script, I get the following error:

Code:
Traceback (most recent call last):
  File "metaPy.py", line 80, in <module>
    parseData(serBuffer)
  File "metaPy.py", line 52, in parseData
    if (TGID != TGIDold) and (TGID != ''): #check if group change or scanner not receiving
NameError: global name 'TGID' is not defined

Any ideas on what the issue might be? I've used this scanner with a Windows system before (and the same USB to Serial adapter) connected to the front port of the scanner and it works fine.

Thanks!
 

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
Hello! I am trying to use the metapy script with my BCD996XT, but can't seem to get it to work. I have configured everything according to the instructions, but when I launch the script, I get the following error:

Code:
Traceback (most recent call last):
  File "metaPy.py", line 80, in <module>
    parseData(serBuffer)
  File "metaPy.py", line 52, in parseData
    if (TGID != TGIDold) and (TGID != ''): #check if group change or scanner not receiving
NameError: global name 'TGID' is not defined

Any ideas on what the issue might be? I've used this scanner with a Windows system before (and the same USB to Serial adapter) connected to the front port of the scanner and it works fine.

Thanks!

Sorry for the late reply. I apologize for not fixing the downloadable script on my webpage. Uplink helped me resolve this exact same issue. It has to do with the 996 giving more data via the serial connection than the BCT15 does (which is what I own, and what I used to write the script.)

I'll update the script and you can re-download it and make the USER CONFIGURATION changes again and it should run. Or you can use go into the script yourself and change an = sign to a > and it will work.

There is a section of code -a function- in the middle of the script:

Code:
def parseData(pserBuffer):
    parsed = pserBuffer.split(",")
    stringtest = parsed[0]
    global TGIDold, TGID, metadata
    if stringtest == "GLG":
        length = len(parsed) 
        if (length == 10): #check list length so we don't get exception
            TGID = parsed[1]
            SYSNAME = parsed[5]
            TG = parsed[7]

        if (TGID != TGIDold) and (TGID != ''): #check if group change or scanner not receiving
            metadata = ((SYSNAME) + " " + (TGID) + " " + (TG))
        else:
            metadata = ''
In the middle of that section there is a line that reads:
Code:
        if (length == 10): #check list length so we don't get exception
Change that line to read:
Code:
        if (length >= 10): #check list length so we don't get exception
Now the script should work with your 996. Sorry for the confusion. Thanks for trying out the script. Let me know how it works.
 
Last edited:

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
One other thing to point out. The formatting of the Icecast updates is totally configurable. So you can modify it to fit your tastes. It's set to print out the scanner's system name, Talkgroup ID number, and Talkgroup in that order. But you can leave any of that out and/or change the order fairly easily
 

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
I've updated the script to add functionality for lookup tables when using a BCT8 or BCT898. Now the user can create a csv file with frequency/tagging information. When either of these scanners see those frequencies they can pull the tag information from the csv file and use that to update a scanner feed. If you're monitoring a system or frequencies that the BCT8 or BCT 898 are capable of receiving, you could use one of these older scanners to run your feed. This would allow you to free up a newer scanner to monitor for personal use without it being tied to an online feed.
 

scanmorgan

Member
Joined
Apr 7, 2006
Messages
29
Location
Lake of the Ozarks
Got your script working pretty quick with a BR330T, thanks! I am having an issue with the TG not displaying though, its showing the frequency instead(Morgan County 01557000 Police). I only have conventional systems programmed.

In this case:
System = Morgan County
Group = Laurie
Channel = Police

Also is there a way for the metadata to reset after 30 seconds or so to something like "Scanning.."?
 
Last edited:

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
Got your script working pretty quick with a BR330T, thanks! I am having an issue with the TG not displaying though, its showing the frequency instead(Morgan County 01557000 Police). I only have conventional systems programmed.

In this case:
System = Morgan County
Group = Laurie
Channel = Police

Also is there a way for the metadata to reset after 30 seconds or so to something like "Scanning.."?

Glad you got it working! As far as frequencies and talkgroups go, the scanner returns different values depending on whether you're scanning a conventional or trunked system. As is, the script returns the frequency as you're seeing if it is scanning a conventional system. We can modify the script to display the group or can make a lookup table to return a tag based on the frequency. For example if the scanner was on 155.700, the script would return whatever name you'd like for the tag like "Laurie Police" etc.

The reset to say scanning is a good idea! It shouldn't be too hard to implement. We just need to start a timer when the frequency is changed, and then if it hits 30 seconds or whatever value you'd like, change the metadata to say "Scanning".

Let me work on it and get back to you.
 

scanmorgan

Member
Joined
Apr 7, 2006
Messages
29
Location
Lake of the Ozarks
Ok thanks for looking into it. All my programming is very organized, so just showing the talk group is perfect. But I can definitely see the advantage of a frequency based lookup table.

Sent from my SAMSUNG-SGH-I337 using Tapatalk
 

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
OK. So I looked at the script again. There's a couple of pieces to add, and I think we'll have it without having to do a lookup table.

Just to verify - In your example you have
System = Morgan County
Group = Laurie
Channel = Police
So the update would say, "Morgan County Laurie Police" ?
"[System] [Group] [Channel]"
Do I have it correct?

If so we just need to pull the group name from the string and add that to the update. Easy to do. I'll work on it and see if we can fix that. Once that's working I'll work on the timer.
-Brandon
 

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
Python is quite interesting. I have some experience in C, and Python isn't anything like it. It's quite robust and you can do so many things in very little syntax. I'm learning, and am liking its capabilities. It also plays well with the Raspberry Pi.

As for the metaPy.py script, I updated it and loaded it back to the same location as the first one. You can download it and reenter your user information, or you can cut and paste the section of code under the function:

Code:
def parseData(pserBuffer):

up to but not including the beginning of the next function:

Code:
def updateData(pMetadata):

In that function, the third line of text from the bottom is the string of data to send to the Icecast server. It reads:
Code:
metadata = ((FREQ) + " " + (SYSNAME) + " " + (GROUP) + " " + (TG)) #User can delete/rearrange items to update

I left the (FREQ) in and added the (GROUP) data. You can play around with the formatting and order to get it how you want. If you want to delete the (FREQ) just remove that text along with the '+ " " '.The line would read:

Code:
metadata = ((SYSNAME) + " " + (GROUP) + " " + (TG)) #User can delete/rearrange items to update

Give it a try and let me know how it works. In the meantime, I'll start on the timer.
 

scanmorgan

Member
Joined
Apr 7, 2006
Messages
29
Location
Lake of the Ozarks
Thanks for the quick reply. Unfortunately there doesn't seem to be any change.
6j35.png
 

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
Thanks for the screenshot. I see what's happening. The other Unidens (346, 15, 996) when scanning conventional systems return the frequency with a decimal after the MHz. It appears the 330 returns the frequency without a decimal in a straight integer form ie: 01556400. I was using the decimal as a check of whether or not it was a conventional or trunked system. I'll have to come up with another way to check.

I'll add a test script below. Can you save it as a .py file and run it and give another screenshot of the output? It will printout the data that the scanner is returning after it is queried by the "GLG" string. If you can run it for both a conventional and trunked systems and let me know the output, I'll come up with something.

If you're only going to need the script for conventional systems you can disregard running the test script and let me know. It's easy to force the script to assume that it will be a conventional system, so it will output the correct format.

Code:
import serial
import time

port = "/dev/ttyUSB0"


serialFromScanner = serial.Serial(port, 115200, timeout=.1)
serialFromScanner.flushInput()

test = "GLG"
print (test)
serialFromScanner.write(test +'\r\n')
serBuffer = ''
nextChar = ''

while True:
    if (serialFromScanner.inWaiting() > 0):
        while nextChar != '\r': #continue filling serBuffer until carriage return
            nextChar = serialFromScanner.read(1) #read one character
            serBuffer += nextChar
        print(serBuffer)
    nextChar = ''
    serBuffer = ''
    serialFromScanner.write(test + '\r\n')
    time.sleep(.1)
 

scanmorgan

Member
Joined
Apr 7, 2006
Messages
29
Location
Lake of the Ozarks
I'd love to run the test script, but the only trunked system in range is the MOSWIN P25 system and of course the 330T wont decode it.

Edit: I am running it anyway, but its a slow night all the sudden so may take a while to get the screenshot....
 
Last edited:

bbrasmussen

Member
Joined
Dec 14, 2007
Messages
140
Location
Woods Cross, UT
Thanks for the screenshot. That confirms my suspicion that the 330 gives the frequency in a different format.

Since you're going to just be using it on conventional systems, I wrote a version that will only work for conventional systems and should do the trick.

I also added a timer capability to the script. You can specify in the USER CONFIGURATION section how long you want to wait in between updates. You can also specify a message other than "Scanning" if you like.

You can find it here:
http://www.k7bbr.net/files/metaPyConventional.py

Let me know how it works.
 

scanmorgan

Member
Joined
Apr 7, 2006
Messages
29
Location
Lake of the Ozarks
Solved

Working great. Thank you! I'm probably the only one running a feed through a 330T though, lol.

gb04.png


Now just have to work on getting rid of the serial polling feedback in the audio. :) Probably just a inferior cable.
 
Status
Not open for further replies.
Top