[chirp_devel] [PATCH] Add query/import from DMR-MARC repeater database. #4411
Tom Hayward
Sat Jan 14 10:02:36 PST 2017
# HG changeset patch
# User Tom Hayward <tom at tomh.us>
# Date 1484416953 28800
# Sat Jan 14 10:02:33 2017 -0800
# Node ID 2474f7b23e9123f4c76be4daaecd37d2284eaabf
# Parent bcac2670345cfd5c1ea3cfb3e3b1022f5dac5f2d
Add query/import from DMR-MARC repeater database. #4411
diff -r bcac2670345c -r 2474f7b23e91 chirp/chirp_common.py
--- a/chirp/chirp_common.py Fri Jan 13 16:15:46 2017 -0800
+++ b/chirp/chirp_common.py Sat Jan 14 10:02:33 2017 -0800
@@ -70,7 +70,7 @@
MODES = ["WFM", "FM", "NFM", "AM", "NAM", "DV", "USB", "LSB", "CW", "RTTY",
"DIG", "PKT", "NCW", "NCWR", "CWR", "P25", "Auto", "RTTYR",
- "FSK", "FSKR"]
+ "FSK", "FSKR", "DMR"]
TONE_MODES = [
"",
diff -r bcac2670345c -r 2474f7b23e91 chirp/dmrmarc.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/chirp/dmrmarc.py Sat Jan 14 10:02:33 2017 -0800
@@ -0,0 +1,139 @@
+# Copyright 2016 Tom Hayward <tom at tomh.us>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import json
+import logging
+import tempfile
+import urllib
+from chirp import chirp_common, errors
+from chirp.settings import RadioSetting, RadioSettingGroup, \
+ RadioSettingValueList
+
+LOG = logging.getLogger(__name__)
+
+
+def list_filter(haystack, attr, needles):
+ if not needles or not needles[0]:
+ return haystack
+ return [x for x in haystack if x[attr] in needles]
+
+
+class DMRMARCRadio(chirp_common.NetworkSourceRadio):
+ """DMR-MARC data source"""
+ VENDOR = "DMR-MARC"
+ MODEL = "Repeater database"
+
+ URL = "http://www.dmr-marc.net/cgi-bin/trbo-database/datadump.cgi?" \
+ "table=repeaters&format=json"
+
+ def __init__(self, *args, **kwargs):
+ chirp_common.NetworkSourceRadio.__init__(self, *args, **kwargs)
+ self._repeaters = None
+
+ def set_params(self, city, state, country):
+ """Set the parameters to be used for a query"""
+ self._city = city and [x.strip() for x in city.split(",")] or ['']
+ self._state = state and [x.strip() for x in state.split(",")] or ['']
+ self._country = country and [x.strip() for x in country.split(",")] \
+ or ['']
+
+ def do_fetch(self):
+ fn = tempfile.mktemp(".json")
+ filename, headers = urllib.urlretrieve(self.URL, fn)
+ with open(fn, 'r') as f:
+ try:
+ self._repeaters = json.load(f)['repeaters']
+ except AttributeError:
+ raise errors.RadioError(
+ "Unexpected response from %s" % self.URL)
+ except ValueError as e:
+ raise errors.RadioError(
+ "Invalid JSON from %s. %s" % (self.URL, str(e)))
+
+ self._repeaters = list_filter(self._repeaters, "city", self._city)
+ self._repeaters = list_filter(self._repeaters, "state", self._state)
+ self._repeaters = list_filter(self._repeaters, "country",
+ self._country)
+
+ def get_features(self):
+ if not self._repeaters:
+ self.do_fetch()
+
+ rf = chirp_common.RadioFeatures()
+ rf.memory_bounds = (0, len(self._repeaters)-1)
+ rf.has_bank = False
+ rf.has_comment = True
+ rf.has_ctone = False
+ rf.valid_tmodes = [""]
+ return rf
+
+ def get_raw_memory(self, number):
+ return repr(self._repeaters[number])
+
+ def get_memory(self, number):
+ if not self._repeaters:
+ self.do_fetch()
+
+ repeater = self._repeaters[number]
+
+ mem = chirp_common.Memory()
+ mem.number = number
+
+ mem.name = repeater.get('city')
+ mem.freq = chirp_common.parse_freq(repeater.get('frequency'))
+ offset = chirp_common.parse_freq(repeater.get('offset', '0'))
+ if offset > 0:
+ mem.duplex = "+"
+ elif offset < 0:
+ mem.duplex = "-"
+ else:
+ mem.duplex = ""
+ mem.offset = abs(offset)
+ mem.mode = 'DMR'
+ mem.comment = repeater.get('map_info')
+
+ mem.extra = RadioSettingGroup("Extra", "extra")
+
+ rs = RadioSetting(
+ "color_code", "Color Code", RadioSettingValueList(
+ range(16), int(repeater.get('color_code', 0))))
+ mem.extra.append(rs)
+
+ return mem
+
+
+def main():
+ import argparse
+ from pprint import PrettyPrinter
+
+ parser = argparse.ArgumentParser(description="Fetch DMR-MARC repeater "
+ "database and filter by city, state, and/or country. Multiple items "
+ "combined with a , will be filtered with logical OR.")
+ parser.add_argument("-c", "--city",
+ help="Comma-separated list of cities to include in output.")
+ parser.add_argument("-s", "--state",
+ help="Comma-separated list of states to include in output.")
+ parser.add_argument("--country",
+ help="Comma-separated list of countries to include in output.")
+ args = parser.parse_args()
+
+ dmrmarc = DMRMARCRadio(None)
+ dmrmarc.set_params(**vars(args))
+ dmrmarc.do_fetch()
+ pp = PrettyPrinter(indent=2)
+ pp.pprint(dmrmarc._repeaters)
+
+if __name__ == "__main__":
+ main()
diff -r bcac2670345c -r 2474f7b23e91 chirp/ui/mainapp.py
--- a/chirp/ui/mainapp.py Fri Jan 13 16:15:46 2017 -0800
+++ b/chirp/ui/mainapp.py Sat Jan 14 10:02:33 2017 -0800
@@ -809,6 +809,65 @@
count = eset.do_import(filen)
reporting.report_model_usage(eset.rthread.radio, "import", count > 0)
+ def do_dmrmarc_prompt(self):
+ fields = {"1City": (gtk.Entry(), lambda x: x),
+ "2State": (gtk.Entry(), lambda x: x),
+ "3Country": (gtk.Entry(), lambda x: x),
+ }
+
+ d = inputdialog.FieldDialog(title=_("DMR-MARC Repeater Database Dump"),
+ parent=self)
+ for k in sorted(fields.keys()):
+ d.add_field(k[1:], fields[k][0])
+ fields[k][0].set_text(CONF.get(k[1:], "dmrmarc") or "")
+
+ while d.run() == gtk.RESPONSE_OK:
+ for k in sorted(fields.keys()):
+ widget, validator = fields[k]
+ try:
+ if validator(widget.get_text()):
+ CONF.set(k[1:], widget.get_text(), "dmrmarc")
+ continue
+ except Exception:
+ pass
+
+ d.destroy()
+ return True
+
+ d.destroy()
+ return False
+
+ def do_dmrmarc(self, do_import):
+ self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
+ if not self.do_dmrmarc_prompt():
+ self.window.set_cursor(None)
+ return
+
+ city = CONF.get("city", "dmrmarc")
+ state = CONF.get("state", "dmrmarc")
+ country = CONF.get("country", "dmrmarc")
+
+ # Do this in case the import process is going to take a while
+ # to make sure we process events leading up to this
+ gtk.gdk.window_process_all_updates()
+ while gtk.events_pending():
+ gtk.main_iteration(False)
+
+ if do_import:
+ eset = self.get_current_editorset()
+ dmrmarcstr = "dmrmarc://%s/%s/%s" % (city, state, country)
+ eset.do_import(dmrmarcstr)
+ else:
+ try:
+ from chirp import dmrmarc
+ radio = dmrmarc.DMRMARCRadio(None)
+ radio.set_params(city, state, country)
+ self.do_open_live(radio, read_only=True)
+ except errors.RadioError, e:
+ common.show_error(e)
+
+ self.window.set_cursor(None)
+
def do_repeaterbook_prompt(self):
if not CONF.get_bool("has_seen_credit", "repeaterbook"):
d = gtk.MessageDialog(parent=self, buttons=gtk.BUTTONS_OK)
@@ -1439,6 +1498,8 @@
self.do_close()
elif action == "import":
self.do_import()
+ elif action in ["qdmrmarc", "idmrmarc"]:
+ self.do_dmrmarc(action[0] == "i")
elif action in ["qrfinder", "irfinder"]:
self.do_rfinder(action[0] == "i")
elif action in ["qradioreference", "iradioreference"]:
@@ -1534,12 +1595,14 @@
<menuitem action="download"/>
<menuitem action="upload"/>
<menu action="importsrc" name="importsrc">
+ <menuitem action="idmrmarc"/>
<menuitem action="iradioreference"/>
<menuitem action="irbook"/>
<menuitem action="ipr"/>
<menuitem action="irfinder"/>
</menu>
<menu action="querysrc" name="querysrc">
+ <menuitem action="qdmrmarc"/>
<menuitem action="qradioreference"/>
<menuitem action="qrbook"/>
<menuitem action="qpr"/>
@@ -1612,12 +1675,14 @@
('export', None, _("Export"), "%se" % ALT_KEY, None, self.mh),
('importsrc', None, _("Import from data source"),
None, None, self.mh),
+ ('idmrmarc', None, _("DMR-MARC Repeaters"), None, None, self.mh),
('iradioreference', None, _("RadioReference.com"),
None, None, self.mh),
('irfinder', None, _("RFinder"), None, None, self.mh),
('irbook', None, _("RepeaterBook"), None, None, self.mh),
('ipr', None, _("przemienniki.net"), None, None, self.mh),
('querysrc', None, _("Query data source"), None, None, self.mh),
+ ('qdmrmarc', None, _("DMR-MARC Repeaters"), None, None, self.mh),
('qradioreference', None, _("RadioReference.com"),
None, None, self.mh),
('qrfinder', None, _("RFinder"), None, None, self.mh),
More information about the chirp_devel
mailing list