Skip to content

Instantly share code, notes, and snippets.

@michalrud
Last active March 7, 2022 18:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save michalrud/bf9d2f2ab9cac3afed18dd3ccfdda712 to your computer and use it in GitHub Desktop.
Save michalrud/bf9d2f2ab9cac3afed18dd3ccfdda712 to your computer and use it in GitHub Desktop.
Converters for Baofeng 1801 programming software
#!python
"""
Converts BrandMeister's CSV contact export to what Baofeng 1801
programming software expects.
Also does some filtration to get the number of contacts under 1024.
Baofeng seems not to handle more than that.
Contact list can be downloaded from: https://brandmeister.network/?page=contactsexport
"""
import csv
PRIVATE_CALL="Private Call"
GROUP_ALL="Group All"
hardcoded = [
[0,"Local","9", GROUP_ALL, "On", "None"],
[0,"TG Poland","260",GROUP_ALL,"On","None"],
[0,"SP Echo","260097",PRIVATE_CALL,"On","None"],
[0,"TG SP6","2606",GROUP_ALL,"On","None"],
[0,"TG DASR","26061",GROUP_ALL,"On","None"],
[0,"TG WiresX","260080",GROUP_ALL,"On","None"],
[0,"TG FusionPL","260042",GROUP_ALL,"On","None"],
[0,"TG SP Test","260019",GROUP_ALL,"On","None"],
[0,"TG Worldwide","91",GROUP_ALL,"On","None"],
[0,"TG Europe","92",GROUP_ALL,"On","None"],
[0,"TG EuroEng","923",GROUP_ALL,"On","None"],
[0,"TG Reddit","98003",GROUP_ALL,"On","None"],
[0, "Ref Check", "5000", PRIVATE_CALL, "On", "None"],
[0, "Ref Unlink", "4000", PRIVATE_CALL, "On", "None"]
]
with open('bm_ce.csv', 'r') as inputfile, open('output.csv', 'w') as outputfile:
reader = csv.reader(inputfile, delimiter=',', quotechar='"')
writer = csv.writer(outputfile, delimiter=',')
first = False
counter = 0
writer.writerow(["Number", "Name", "Call ID", "Type", "Ring Style", "Call Receive Tone"])
for row in hardcoded:
row[0] = counter
writer.writerow(row)
counter += 1
for row in reader:
if row[0].startswith("260") and int(row[4]) > 20:
writer.writerow([counter, row[1], row[0], PRIVATE_CALL, "On", "None"])
counter += 1
#!python3
"""
Fetches the repeater list from przemienniki.net and converts it
into the channel list in CSV for Baofeng 1801.
Adjust COUNTRY to get repeaters from your country.
Thanks to SQ5IRS for fixes!
"""
from xml.dom.minidom import parseString
import requests
import csv
COUNTRY = 'pl'
DMR_NAME = 'MOTOTRBO' # przemienniki.net treats MOTOTRBO as DMR
MODE = '{},FM'.format(DMR_NAME)
OUTFILE = 'channels.csv'
DIGITAL_MODE = 'Digital'
ANALOG_MODE = 'Analog'
OUTPUT_CSV_HEADER = ["Number", "Name", "Rx Freq", "Tx Freq", "Ch Mode", "Power", "Rx Tone", "Tx Tone", "Color Code",
"Rx Group List", "Contact", "Repeater Slot", "Bandwidth", "Squelch Level"]
HARDCODED = [
["0", "DMR 2m", "144.55000", "144.55000", "Digital", "High", "None", "None", "1", "0", "2", "2", "12.5", "0"],
["0", "DMR 70cm", "433.55000", "433.55000", "Digital", "High", "None", "None", "1", "0", "2", "2", "12.5", "0"],
]
channel_counter = 0
def getType(repeater):
for element in repeater.getElementsByTagName("mode"):
if element.firstChild.nodeValue == DMR_NAME:
return DIGITAL_MODE
return ANALOG_MODE # there may be multiple modes. Select digital if DMR is one of them, else default to analog
def getValueGetter(repeater):
def getValue(paramName, attr=None):
for element in repeater.getElementsByTagName(paramName):
if attr is None:
return element.firstChild.nodeValue
if element.attributes[attr[0]].value == attr[1]:
return element.firstChild.nodeValue
return ""
return getValue
def getRepeaterEntry(repeater, timeSlot='1', namePostfix=""):
global channel_counter
getValue = getValueGetter(repeater)
retval = [
channel_counter,
getValue('qra') + namePostfix,
getValue('qrg', ("type", "tx")),
getValue('qrg', ("type", "rx")),
getType(repeater),
'High',
getValue('ctcss', ("type", "tx")),
getValue('ctcss', ("type", "rx")),
'1', # Color Code isn't unfortunately included in przemienniki.net database
'1', # Rx Group List is radio specific
'1', # Contact is radio specific
timeSlot,
'12.5',
'0'
]
channel_counter += 1
return retval
def getRepeaterEntries(repeater):
if getType(repeater) == DIGITAL_MODE:
return [
getRepeaterEntry(repeater, '1', " TS1"),
getRepeaterEntry(repeater, '2', " TS2")
]
else:
return [getRepeaterEntry(repeater, '1')]
def main():
url = 'https://przemienniki.net/export/rxf.xml?country={}&onlyworking&mode={}'.format(COUNTRY, MODE)
r = requests.get(url)
response = r.text
indata = parseString(response.encode("ASCII", 'ignore'))
with open(OUTFILE, 'w') as outputfile:
writer = csv.writer(outputfile, delimiter=',')
writer.writerow(OUTPUT_CSV_HEADER)
for item in HARDCODED:
global channel_counter
item[0] = channel_counter
writer.writerow(item)
channel_counter += 1
repeaters = indata.getElementsByTagName('repeater')
for repeater in repeaters:
writer.writerows(getRepeaterEntries(repeater))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment