Python-Powered Frequency Activity Logger
920 words | Posted by Scott on June 12th, 2009
Scott was 23.72 years old when he wrote this!
Filed under: General, Linux, Python, Radio
As anyone who visits this website can tell you, I’m inexplicably drawn toward inventing new ways of using Python (often in conjunction with MatPlotLib) to graphically visualize data in new ways. When I found out a fellow ham in Orlando was using his computer to stream (and serve recorded streams of) a popular local repeater frequency over the internet. I got excited because of the potential for generating [quasi-useful, and at least interesting] data from the existing setup. Since this guy already has his radio connected to his PC’s microphone jack, I figured I could write a Python app. to check the microphone input to determine if anyone is using the frequency. By recording when people start and stop talking, I can create a log of frequency activity. Later I can write software to visualize this data. I’ll talk about that in a later post. For now, here’s how I used Python and a Linux box (Ubuntu, with the python-alsaaudio package installed) to generate such logs.
We can visualize this data using some more simple Python code. Long term it would be useful to visualize frequency activity similarly to how I graphed computer usage at work over the last year but for now since I don’t have any large amount of data to work with. I’ll just write cote to visualize a QSO (conversation) with respect to time. It should be self-explanatory. This data came from data points displayed in the video (provided at the end of this post too).

And, of course, the code I used to generate the log files (seen running in video above): Briefly, this program checks the microphone many times every second to determine if its state has changed (talking/no talking) and records this data in a text file (which it updates every 10 seconds). Matplotlib can EASILY be used to graph data from such a text file.
##################################
##### UPDATED CODE IS IN A NEWER ENTRY #####
### CHECK THE PYTHON AND RADIO CATEGORIES ###
##################################
import alsaaudio, time, audioop, datetime
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE,alsaaudio.PCM_NONBLOCK)
inp.setchannels(1)
inp.setrate(4000)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(1)
squelch = False
lastLog = 0
dataToLog = ""
def logIt(nowSquelch):
global dataToLog, lastLog
timeNow = datetime.datetime.now()
epoch = time.mktime(timeNow.timetuple())
if nowSquelch==True: nowSquelch=1
else: nowSquelch=0
logLine="%s %d\n"%(timeNow, nowSquelch)
print timeNow, nowSquelch
dataToLog+=logLine
if epoch-lastLog>10:
#print "LOGGING..."
f=open('squelch.txt','a')
f.write(dataToLog)
f.close()
lastLog = epoch
dataToLog=""
while True:
l,data = inp.read()
if l:
vol = audioop.max(data,2)
#print vol #USED FOR CALIBRATION
if vol>800: nowSquelch = True
else: nowSquelch = False
if not nowSquelch == squelch:
logIt(nowSquelch)
squelch = nowSquelch
time.sleep(.01)
To use this code make sure that you’ve properly calibrated it. See the “vol>800″ line? That means that if the volume in the microphone is at least 800, it’s counted as talking, and less than it’s silence. Hopefully you can find a value that counts as silence when the squelch is active, but as talking when the squelch is broken (even if there’s silence). This is probably best achieved with the radio outputting at maximum volume. You’ll have to run the program live with that line un-commented to view the data values live. Find which values occur for squelch on/off, and pick your threshold accordingly.
After you run the code, it should output data like this:
################################## ##### UPDATED CODE IS IN A NEWER ENTRY ##### ### CHECK THE PYTHON AND RADIO CATEGORIES ### ################################## 2009-06-12 17:13:28.347551 1 2009-06-12 17:13:29.306556 0 2009-06-12 17:13:30.176076 1 2009-06-12 17:13:41.533238 0 2009-06-12 17:13:45.435846 1 2009-06-12 17:14:21.890423 0 2009-06-12 17:14:25.605424 1 2009-06-12 17:14:41.904548 0 2009-06-12 17:14:43.903870 1 2009-06-12 17:14:55.981045 0 2009-06-12 17:14:59.377337 1 2009-06-12 17:15:12.365393 0 2009-06-12 17:15:15.773681 1 2009-06-12 17:15:33.165695 0 2009-06-12 17:15:36.155376 1 2009-06-12 17:16:04.181281 0 2009-06-12 17:16:07.423343 1 2009-06-12 17:16:15.724043 0 2009-06-12 17:16:18.411122 1 2009-06-12 17:16:35.304314 0 2009-06-12 17:16:36.371054 1 2009-06-12 17:16:50.818980 0 2009-06-12 17:16:53.995472 1 2009-06-12 17:17:26.675227 0 2009-06-12 17:17:29.969474 1 2009-06-12 17:17:47.907444 0 2009-06-12 17:17:50.361119 1 2009-06-12 17:18:04.630950 0 2009-06-12 17:18:05.565729 1 2009-06-12 17:18:11.225585 0 2009-06-12 17:18:14.787122 1 2009-06-12 17:18:41.261046 0 2009-06-12 17:18:43.819297 1 2009-06-12 17:18:52.164121 0 2009-06-12 17:18:53.100013 1 2009-06-12 17:19:05.348166 0 2009-06-12 17:19:09.316964 1 2009-06-12 17:19:19.107860 0 2009-06-12 17:19:19.941314 1 2009-06-12 17:19:26.254173 0 2009-06-12 17:19:33.844900 1 2009-06-12 17:19:46.501087 0 2009-06-12 17:19:49.360008 1 2009-06-12 17:19:59.917436 0 2009-06-12 17:20:04.335205 1 2009-06-12 17:20:17.622417 0 2009-06-12 17:20:18.501208 1 2009-06-12 17:20:26.866216 0 2009-06-12 17:20:28.694763 1 2009-06-12 17:20:36.097119 0
After that you can visualize the data with the following code. Note that this is SEVERELY LIMITED and is only useful when graphing a few minutes of data. I don’t have hours/days of data to work with right now, so I won’t bother writing code to graph it. This code produced the graph seen earlier in this page. Make sure matplotlib is installed on your box.
##################################
##### UPDATED CODE IS IN A NEWER ENTRY #####
### CHECK THE PYTHON AND RADIO CATEGORIES ###
##################################
import pylab
def loadData():
#returns Xs
import time, datetime, pylab
f=open('good.txt')
raw=f.readlines()
f.close()
onTimes=[]
timeStart=None
lastOn=False
for line in raw:
if len(line)<10: continue
line = line.strip('\n').split(" ")
t=line[0]+" "+line[1]
t=t.split('.')
thisDay=time.strptime(t[0], "%Y-%m-%d %H:%M:%S")
e=time.mktime(thisDay)+float("."+t[1])
if timeStart==None: timeStart=e
if line[-1]==1: stat=True
else: stat=False
if not lastOn and line[-1]=="1":
lastOn=e
else:
onTimes.append([(lastOn-timeStart)/60.0,\
(e-timeStart)/60.0])
lastOn=False
return onTimes
times = loadData()
pylab.figure(figsize=(8,3))
for t in times:
pylab.fill([t[0],t[0],t[1],t[1]],[0,1,1,0],'k',lw=0,alpha=.5)
pylab.axis([None,None,-3,4])
pylab.title("A little QSO")
pylab.xlabel("Time (minutes)")
pylab.show()
This entry was posted on Friday, June 12th, 2009 at 5:42 pmand is filed under General, Linux, Python, Radio. You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.
One Response to “Python-Powered Frequency Activity Logger”
| David B. wrote the following at 09:35:07 PM on June 13th, 2009 |
|
In trying to understand what your plotting and refresh my skills in Python programming: Does this version get the data points correct for the pylab.fill function? http://www.kc4zvw.us/read_datalog.py 73, David |