Go to repeaterbook.com, open the repeater listing for whatever category you want (I usually go by bands, as the script automatically sorts out all the modes) and then Export > CSV. If you want to put together multiple listings, just combine the files, but remember to only have one header. Also check that the downloaded CSV file doesn't have any PHP errors (stuff like <br>) at the top. If it does, just delete those lines.
Usage is pretty simple, albeit only tested on Linux. Just mark it as executable (chmod +x convert.py) and then run it and give the path of your Repeaterbook CSV. My command would be: ./convert.py repeaterbookfull.csv while Windows would probably look like python convert.py repeaterbook.csv
Take the two output files, Channels.csv and Zones.csv, don't rename them, and put them in a directory. In the CPS, press Ctrl-I and it'll ask you to point it at the folder you put the files into. Hit OK and it'll pull them in and give you a summary of what it did to your codeplug. From here, make whatever modifications you like, and upload it normally.
See you on the air :). 73 KJ5DFL
Script (just copy-paste this into a file. i saved mine as convert.py) (please don't bully me lol, i know this is awful):
Code: Select all
#!/usr/bin/python
import sys
def shorten(string):
return string.replace("a", "").replace("e", "").replace("i", "").replace("o", "").replace("u", "").replace(" ", "").replace("-", " ")
#print(sys.argv)
chanfile = open(sys.argv[1])
chanfiledata = chanfile.read()
chanfile.close()
chans = chanfiledata.split("\n")
splitchans = []
for i in chans:
if ((("DMR" not in i) and ("Analog" not in i) and ("analog" not in i)) or ("On-Air" not in i) or ("OPEN" not in i)):
continue
toapp = i.split(",")
toapp[5] = toapp[5].replace('"', "")
splitchans.append(toapp)
#print(chans[0])
#print(splitchans)
#print(splitchans[1])
outchan = open("Channels.csv", "w")
outzones = open("Zones.csv", "w")
counties = {}
channum = 1
outchan.write("Channel Number,Channel Name,Channel Type,Rx Frequency,Tx Frequency,Bandwidth (kHz),Colour Code,Timeslot,Contact,TG List,DMR ID,TS1_TA_Tx,TS2_TA_Tx ID,RX Tone,TX Tone,Squelch,Power,Rx Only,Zone Skip,All Skip,TOT,VOX,No Beep,No Eco,APRS,Latitude,Longitude\n")
for i in splitchans:
if "analog" in i[12]:
# Channel number
outchan.write(str(channum) + ",")
channum += 1
# Channel name.
channame = str(i[9] + "-" + shorten(i[5]))
channame = channame[:14]
channame = channame.strip()
outchan.write(channame + ",")
# Assign the channel to a zone, and check if there's a zone for its county.
countyname = i[6].replace(" ","")
countyname = countyname[:14]
#print(countyname,channame)
try:
counties[countyname].append(channame)
except KeyError:
counties[countyname] = []
counties[countyname].append(channame)
# Channel type. We've already checked the type if we're running this codeblock.
outchan.write("Analogue,")
# Channel frequencies, RX then TX
outchan.write(str(i[0]) + "," + str(i[1]) + ",")
# Channel bandwidth. Should always be 25khz.
outchan.write("25,")
# Color code, Timeslot, Contact, Talkgroup, DMR ID, and some other nonsense that doesn't matter here.
outchan.write(",,,,,,,")
# Tones. We have to make sure an uplink tone is set, and I just don't use downlink tones.
if i[3] == "" or i[3] == "CSQ":
uptone = "None"
else:
uptone = i[3]
outchan.write(f"None,{uptone},")
# Squelch. "Disabled" just means to use the default setting.
outchan.write("Disabled,")
# Power. Master just means to use default.
outchan.write("Master,")
# Some other stuff like RX only, Scan skips, TOT, VOX. I turn it all off, but set TOT to 180s.
outchan.write("No,No,No,180,Off,No,No,None,")
# Coordinates and end.
outchan.write(f"{i[7]},{i[8]}\n")
if "DMR" in i[12]:
# Channel number
outchan.write(str(channum) + ",")
channum += 1
# Channel name.
channame = str(i[9] + "-" + shorten(i[5]))
channame = channame[:15]
channame = channame.strip()
outchan.write(channame + ",")
# Assign the channel to a zone, and check if there's a zone for its county.
countyname = i[6].replace(" ","")
countyname = countyname[:14]
#print(countyname,channame)
try:
counties[countyname].append(channame)
except KeyError:
counties[countyname] = []
counties[countyname].append(channame)
# Channel type. We've already checked the type if we're running this codeblock.
outchan.write("Digital,")
# Channel frequencies, RX then TX
outchan.write(str(i[0]) + "," + str(i[1]) + ",")
# Channel bandwidth. Not set on digital stations.
outchan.write(",")
# All the DMR stuff. Color code to TS2_TA_Tx ID. Don't ask me.
outchan.write(f"{i[13]},1,None,None,None,Off,Off,")
# Tones, Squelch.
outchan.write(",,,")
# Power. Master just means to use default.
outchan.write("Master,")
# Some other stuff like RX only, Scan skips, TOT, VOX. I turn it all off, but set TOT to 180s.
outchan.write("No,No,No,180,Off,No,No,None,")
# Coordinates and end.
outchan.write(f"{i[7]},{i[8]}\n")
# Let's set up zones. Unlike the last part that was awful because I'm awful at programming, this
# is awful because I'm bad at programming _and_ the format is awful. Yay.
outzones.write("Zone Name,Channel1,Channel2,Channel3,Channel4,Channel5,Channel6,Channel7,Channel8,Channel9,Channel10,Channel11,Channel12,Channel13,Channel14,Channel15,Channel16,Channel17,Channel18,Channel19,Channel20,Channel21,Channel22,Channel23,Channel24,Channel25,Channel26,Channel27,Channel28,Channel29,Channel30,Channel31,Channel32,Channel33,Channel34,Channel35,Channel36,Channel37,Channel38,Channel39,Channel40,Channel41,Channel42,Channel43,Channel44,Channel45,Channel46,Channel47,Channel48,Channel49,Channel50,Channel51,Channel52,Channel53,Channel54,Channel55,Channel56,Channel57,Channel58,Channel59,Channel60,Channel61,Channel62,Channel63,Channel64,Channel65,Channel66,Channel67,Channel68,Channel69,Channel70,Channel71,Channel72,Channel73,Channel74,Channel75,Channel76,Channel77,Channel78,Channel79,Channel80\n")
for i in counties:
print(f"{i} {len(counties[i])}")
outzones.write(f"{i},")
print(i)
counter = 0
print(counties[i])
for b in counties[i]:
print(b)
outzones.write(f"{b},")
counter += 1
for b in range(79 - counter):
outzones.write(",")
outzones.write("\n")