Last active
March 7, 2022 18:58
-
-
Save michalrud/bf9d2f2ab9cac3afed18dd3ccfdda712 to your computer and use it in GitHub Desktop.
Converters for Baofeng 1801 programming software
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!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