def _create_dmr_data(self): dmr_id_file = RadioWriter.input_writer('dmr_id.csv', '\n') dmr_id = DmrIdDefault({ 'radio_id': '00000', 'name': 'DMR', }) dmr_id_file.writerow(dmr_id.headers()) dmr_id_file.writerow(dmr_id.output(1)) dmr_id_file.close() digital_contacts_file = RadioWriter.input_writer( 'digital_contacts.csv', '\n') analog_contact = DmrContactDefault({ 'digital_id': dmr_id.radio_id.fmt_val(), 'name': 'Analog', 'call_type': 'all', }) group_contact = DmrContactDefault({ 'digital_id': 99999, 'name': 'Some Repeater', 'call_type': 'group', }) digital_contacts_file.writerow(analog_contact.headers()) digital_contacts_file.writerow(analog_contact.output(1)) digital_contacts_file.writerow(group_contact.output(2)) digital_contacts_file.close()
def _create_zone_data(self): zone_id_file = RadioWriter.input_writer('zones.csv', '\n') zone = RadioZoneDefault({ 'number': 1, 'name': 'Zone 1', }) zone_id_file.writerow(zone.headers()) zone_id_file.writerow(zone.output()) zone_id_file.close()
def _create_dmr_user_data(self): user_file = RadioWriter.input_writer('user.csv', '\n') dmr_user = DmrUserDefault({ 'RADIO_ID': '00000', 'CALLSIGN': 'N0CALL', 'FIRST_NAME': 'Sample', 'LAST_NAME': 'User', 'CITY': 'Somewhere', 'STATE': 'Stateville', 'COUNTRY': 'Theremany', 'REMARKS': 'Sample Entry', }) user_file.writerow(dmr_user.headers()) user_file.writerow(dmr_user.output(None)) user_file.close() return
def channels_to_file(self, channels): logging.info('Writing imported files.') headers = RadioChannelDefault.create_empty().headers() writer = RadioWriter.output_writer('import_result.csv', '\r\n') writer.writerow(headers) channel_num = 1 for chan in channels: # who is this for chan channel_default = RadioChannelBuilder.casted( chan, radio_types.DEFAULT) writer.writerow(channel_default.output(channel_num)) channel_num += 1 writer.close() result_path = PathManager.get_output_path('import_result.csv') logging.info( f'Import complete! Your imported file is in `{result_path}`')
def _output_radioids(self): logging.info(f"Writing {radio_types.D878} radio IDs") if self._dmr_ids is None: logging.error(f"No DMR ids found for {radio_types.D878}.") return radio_id_file = RadioWriter.output_writer( f'{radio_types.D878}/{radio_types.D878}_radioid.csv', '\r\n') headers = DmrIdD878.create_empty() radio_id_file.writerow(headers.headers()) number = 1 for dmr_id in self._dmr_ids.values(): casted_id = DmrIdBuilder.casted(dmr_id, radio_types.D878) radio_id_file.writerow(casted_id.output(number)) number += 1 radio_id_file.close() return
def _output_zones(self): logging.info(f"Writing {radio_types.D878} zones") if self._zones is None: logging.error(f"No zones list found for {radio_types.D878}.") return zone_file = RadioWriter.output_writer( f'{radio_types.D878}/{radio_types.D878}_zone.csv', '\r\n') headers = RadioZoneD878.create_empty() zone_file.writerow(headers.headers()) for zone in self._zones.values(): if not zone.has_channels(): continue casted_zone = RadioZoneBuilder.casted(zone.cols, zone._associated_channels, radio_types.D878) zone_file.writerow(casted_zone.output()) zone_file.close()
def _output_contacts(self): logging.info(f"Writing {radio_types.D878} contacts") if self._digital_contacts is None: logging.error(f"No digital contacts found for {radio_types.D878}.") return dmr_contact_file = RadioWriter.output_writer( f'{radio_types.D878}/{radio_types.D878}_talkgroup.csv', '\r\n') headers = DmrContactD878.create_empty() dmr_contact_file.writerow(headers.headers()) number = 1 for dmr_contact in self._digital_contacts.values(): casted_contact = DmrContactBuilder.casted(dmr_contact, radio_types.D878) row_data = casted_contact.output(number) dmr_contact_file.writerow(row_data) number += 1 dmr_contact_file.close()
def output(self): gpx = gpxpy.gpx.GPX() gpx.name = 'Ham Radio Stations' gpx.description = 'Ham radio station locations generated by Ham Radio Sync' for channel in self._channels: if channel.latitude.fmt_val() is None or channel.longitude.fmt_val( ) is None: continue gpx_waypoint = gpxpy.gpx.GPXWaypoint() gpx_waypoint.latitude = channel.latitude.fmt_val() gpx_waypoint.longitude = channel.longitude.fmt_val() gpx_waypoint.name = channel.name.fmt_val() gpx_waypoint.description = self._get_description(channel) gpx.waypoints.append(gpx_waypoint) xml = gpx.to_xml() writer = RadioWriter.output_writer( f'{radio_types.GPX}/ham_radio_sync.gpx', '\r\n') writer.write_raw(xml) writer.close()
def _output_user(self): logging.info(f"Writing {radio_types.D878} users") if self._users is None: logging.error(f"No zones list found for {radio_types.D878}.") return users_file = RadioWriter.output_writer( f'{radio_types.D878}/{radio_types.D878}_digital_contacts.csv', '\n') headers = DmrUserD878.create_empty() users_file.writerow(headers.headers()) rows_processed = 1 for user in self._users.values(): casted_user = DmrUserBuilder.casted(user.cols, radio_types.D878) users_file.writerow(casted_user.output(None)) rows_processed += 1 logging.debug(f"Writing user row {rows_processed}") if rows_processed % file_util.USER_LINE_LOG_INTERVAL == 0: logging.info(f"Writing user row {rows_processed}") users_file.close()
def _create_channel_file(self): channel_file = RadioWriter.input_writer('input.csv', '\n') first_channel = RadioChannelDefault( { 'name': 'National 2m', 'medium_name': 'Natl 2m', 'short_name': 'NATL 2M', 'zone_id': '', 'rx_freq': '146.520', 'rx_ctcss': '', 'rx_dcs': '', 'rx_dcs_invert': '', 'tx_power': 'Low', 'tx_offset': '', 'tx_ctcss': '', 'tx_dcs': '', 'tx_dcs_invert': '', 'digital_timeslot': '', 'digital_color': '', 'digital_contact_id': '', 'latitude': '', 'longitude': '', }, digital_contacts=None, dmr_ids=None) second_channel = RadioChannelDefault( { 'name': 'Basic Repeater', 'medium_name': 'BasicRpt', 'short_name': 'BASRPTR', 'zone_id': '1', 'rx_freq': '145.310', 'rx_ctcss': '', 'rx_dcs': '', 'rx_dcs_invert': '', 'tx_power': 'High', 'tx_offset': '-0.600', 'tx_ctcss': '88.5', 'tx_dcs': '', 'tx_dcs_invert': '', 'digital_timeslot': '', 'digital_color': '', 'digital_contact_id': '', 'latitude': '', 'longitude': '', }, digital_contacts=None, dmr_ids=None) third_channel = RadioChannelDefault( { 'name': 'DMR Repeater', 'medium_name': 'DMR Rpt', 'short_name': 'DMR RPT', 'zone_id': '1', 'rx_freq': '144.310', 'rx_ctcss': '', 'rx_dcs': '', 'rx_dcs_invert': '', 'tx_power': 'High', 'tx_offset': '-0.600', 'tx_ctcss': '', 'tx_dcs': '', 'tx_dcs_invert': '', 'digital_timeslot': '1', 'digital_color': '4', 'digital_contact_id': '99999', 'latitude': '', 'longitude': '', }, digital_contacts=None, dmr_ids=None) fourth_channel = RadioChannelDefault( { 'name': 'Has lat and long', 'medium_name': 'lat long', 'short_name': 'latlong', 'zone_id': '', 'rx_freq': '146.520', 'rx_ctcss': '', 'rx_dcs': '', 'rx_dcs_invert': '', 'tx_power': 'Low', 'tx_offset': '', 'tx_ctcss': '', 'tx_dcs': '', 'tx_dcs_invert': '', 'digital_timeslot': '', 'digital_color': '', 'digital_contact_id': '', 'latitude': '38.903450', 'longitude': '-77.007470', }, digital_contacts=None, dmr_ids=None) channel_file.writerow(first_channel.headers()) channel_file.writerow( RadioChannelBuilder.casted(first_channel, radio_types.DEFAULT).output(1)) channel_file.writerow( RadioChannelBuilder.casted(second_channel, radio_types.DEFAULT).output(2)) channel_file.writerow( RadioChannelBuilder.casted(third_channel, radio_types.DEFAULT).output(3)) channel_file.writerow( RadioChannelBuilder.casted(fourth_channel, radio_types.DEFAULT).output(4)) channel_file.close()
def generate_all_declared(self): file_errors = self._validator.validate_files_exist() self._validator.flush_names() if len(file_errors) > 0: return False results = self._migrations.check_migrations_needed() if len(results.keys()) > 0: logging.warning( 'You may be using an old version of the input files. Have you run migrations?' ) logging.warning("Migrations check is under the 'File' menu.") sleep(1) for radio in radio_types.radio_choices(): radio_folder = PathManager.get_output_path(radio) if not os.path.exists(radio_folder): continue logging.info(f'Deleting old output folder `{radio}`') FileUtil.safe_delete_dir(radio_folder) digital_contacts, digi_contact_errors = self._generate_digital_contact_data( ) dmr_ids, dmr_id_errors = self._generate_dmr_id_data() zones, zone_errors = self._generate_zone_data() user, user_data_errors = self._generate_user_data() preload_errors = digi_contact_errors + dmr_id_errors + zone_errors + user_data_errors feed = PathManager.open_input_file('input.csv', 'r') csv_reader = csv.DictReader(feed) radio_channel_errors = [] radio_channels = [] line_num = 1 for line in csv_reader: line_errors = self._validator.validate_radio_channel( line, line_num, feed.name, digital_contacts, zones) radio_channel_errors += line_errors line_num += 1 if len(line_errors) > 0: continue radio_channel = RadioChannel(line, digital_contacts, dmr_ids) radio_channels.append(radio_channel) if radio_channel.zone_id.fmt_val(None) is not None: zones[radio_channel.zone_id.fmt_val()].add_channel( radio_channel) feed.close() all_errors = preload_errors + radio_channel_errors if len(all_errors) > 0: logging.error('--- VALIDATION ERRORS, CANNOT CONTINUE ---') for err in all_errors: logging.error( f'\t\tfile: `{err.file_name}` line:{err.line_num} validation error: {err.message}' ) return False else: logging.info( 'File validation complete, no obvious formatting errors found') radio_files = dict() headers_gen = RadioChannel.create_empty() FileUtil.safe_create_dir('out') channel_numbers = dict() for radio in self.radio_list: radio_casted = RadioChannelBuilder.casted(headers_gen, radio) FileUtil.safe_create_dir(f'out/{radio}') logging.info(f'Generating for radio type `{radio}`') if radio_casted.skip_radio_csv(): logging.info( f'`{radio}` uses special output style. Skipping channels csv' ) continue output = RadioWriter.output_writer(f'{radio}/{radio}_channels.csv', '\r\n') file_headers = radio_casted.headers() output.writerow(file_headers) radio_files[radio] = output channel_numbers[radio] = 1 logging.info('Processing radio channels') line = 1 for radio_channel in radio_channels: logging.debug(f'Processing radio line {line}') if line % file_util.RADIO_LINE_LOG_INTERVAL == 0: logging.info(f'Processing radio line {line}') line += 1 for radio in self.radio_list: if radio not in radio_files.keys(): continue if not radio_types.supports_dmr( radio) and radio_channel.is_digital(): continue casted_channel = RadioChannelBuilder.casted( radio_channel, radio) input_data = casted_channel.output(channel_numbers[radio]) radio_files[radio].writerow(input_data) channel_numbers[radio] += 1 additional_data = RadioAdditional(radio_channels, dmr_ids, digital_contacts, zones, user) for radio in self.radio_list: if radio in radio_files.keys(): radio_files[radio].close() casted_additional_data = RadioAdditionalBuilder.casted( additional_data, radio) casted_additional_data.output() logging.info(f'''Radio generator complete. Your output files are in `{os.path.abspath('out')}` The next step is to import these files into your radio programming application. (e.g. CHiRP)''' ) return True