added user settings, added speed and course
This commit is contained in:
parent
00e3ea840c
commit
d7afa94a5a
19
README.md
19
README.md
@ -44,6 +44,25 @@ A user should configure their radio for the DMR ID of the application and privat
|
|||||||
|
|
||||||
For example, N0CALL has a DMR ID of 1234567. N0CALL's radio sends a position to the application. The application will query the subscriber_ids file for DMR ID 1234567. The result will be N0CALL. An APRS location pack is created and uploaded to APRS-IS.
|
For example, N0CALL has a DMR ID of 1234567. N0CALL's radio sends a position to the application. The application will query the subscriber_ids file for DMR ID 1234567. The result will be N0CALL. An APRS location pack is created and uploaded to APRS-IS.
|
||||||
|
|
||||||
|
## Individual user/DMR ID APRS settings
|
||||||
|
|
||||||
|
By default, all APRS positions will have an SSID of 15, a default comment, and the callsign of the DMR user. These default settings can be changed.
|
||||||
|
|
||||||
|
The comment, SSID, and icon can be set for each individual user/DMR ID the application sees. The application stores all the setting in a file. You may have different SSIDs, icons, and comments for different DMR IDs. This is done via DMR SMS using the following commands:
|
||||||
|
|
||||||
|
* `
|
||||||
|
@SSID` - Change SSID of user callsign.
|
||||||
|
|
||||||
|
* `
|
||||||
|
@ICON` - Change the icon of the APRS position. *See [http://aprs.net/vm/DOS/SYMBOLS.HTM](http://aprs.net/vm/DOS/SYMBOLS.HTM) for icon list.
|
||||||
|
*
|
||||||
|
* `
|
||||||
|
@COM` - Change the comment of the APRS
|
||||||
|
|
||||||
|
Send a DMR SMS to the configured dmr_data_id in the application with the desired command followed by the value. For example, to change your icon to a dog, the command would be `@ICON /p` (see the icon table for values). Changing your SSID is as simple as `@SSID 7`, and `@COM Testing 123` will change the comment.
|
||||||
|
|
||||||
|
To remove any of the stored values, just send the appropriate command without any input. `@COM` will remove the stored comment, `@ICON` will remove the stored icon, and `@COM` will remove the strored comment. Any position now reports sent will have the default settings.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
See hblink_SAMPLE.cfg, rules_SAMPLE.py, and gps_data_SAMPLE.cfg for examples.
|
See hblink_SAMPLE.cfg, rules_SAMPLE.py, and gps_data_SAMPLE.cfg for examples.
|
||||||
|
77
gps_data.py
77
gps_data.py
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Copyright (C) 2020 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
# HBLink - Copyright (C) 2020 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||||
|
# GPS/Data - Copyright (C) 2020 Eric Craw, KF7EEL <kf7eel@qsl.net>
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@ -65,6 +66,11 @@ import pynmea2
|
|||||||
import os
|
import os
|
||||||
from gps_functions import cmd_list
|
from gps_functions import cmd_list
|
||||||
|
|
||||||
|
#Modules for APRS settings
|
||||||
|
import ast
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||||
__author__ = 'Cortney T. Buffington, N0MJS; Eric Craw, KF7EEL'
|
__author__ = 'Cortney T. Buffington, N0MJS; Eric Craw, KF7EEL'
|
||||||
__copyright__ = 'Copyright (c) 2020 Cortney T. Buffington'
|
__copyright__ = 'Copyright (c) 2020 Cortney T. Buffington'
|
||||||
@ -97,6 +103,7 @@ def decode_full(_data):
|
|||||||
binlc.extend([_data[36], _data[21], _data[6], _data[187],_data[172],_data[157],_data[142],_data[127],_data[112],_data[97], _data[82] ])
|
binlc.extend([_data[36], _data[21], _data[6], _data[187],_data[172],_data[157],_data[142],_data[127],_data[112],_data[97], _data[82] ])
|
||||||
binlc.extend([_data[7], _data[188],_data[173],_data[158],_data[143],_data[128],_data[113],_data[98], _data[83]])
|
binlc.extend([_data[7], _data[188],_data[173],_data[158],_data[143],_data[128],_data[113],_data[98], _data[83]])
|
||||||
#This is the rest of the Full LC data -- the RS1293 FEC that we don't need
|
#This is the rest of the Full LC data -- the RS1293 FEC that we don't need
|
||||||
|
# This is extremely important for SMS and GPS though.
|
||||||
binlc.extend([_data[68],_data[53],_data[174],_data[159],_data[144],_data[129],_data[114],_data[99],_data[84],_data[69],_data[54],_data[39]])
|
binlc.extend([_data[68],_data[53],_data[174],_data[159],_data[144],_data[129],_data[114],_data[99],_data[84],_data[69],_data[54],_data[39]])
|
||||||
binlc.extend([_data[24],_data[145],_data[130],_data[115],_data[100],_data[85],_data[70],_data[55],_data[40],_data[25],_data[10],_data[191]])
|
binlc.extend([_data[24],_data[145],_data[130],_data[115],_data[100],_data[85],_data[70],_data[55],_data[40],_data[25],_data[10],_data[191]])
|
||||||
return binlc
|
return binlc
|
||||||
@ -120,6 +127,32 @@ def header_ID(_data):
|
|||||||
# Work in progress, used to determine data format
|
# Work in progress, used to determine data format
|
||||||
## pass
|
## pass
|
||||||
|
|
||||||
|
def user_setting_write(dmr_id, setting, value):
|
||||||
|
## try:
|
||||||
|
# Open file and load as dict for modification
|
||||||
|
with open("./user_settings.txt", 'r') as f:
|
||||||
|
## if f.read() == '{}':
|
||||||
|
## user_dict = {}
|
||||||
|
user_dict = ast.literal_eval(f.read())
|
||||||
|
if dmr_id not in user_dict:
|
||||||
|
user_dict[dmr_id] = [{'call': str(get_alias((dmr_id), subscriber_ids))}, {'ssid': ''}, {'icon': ''}, {'comment': ''}]
|
||||||
|
|
||||||
|
if setting.upper() == 'ICON':
|
||||||
|
user_dict[dmr_id][2]['icon'] = value
|
||||||
|
if setting.upper() == 'SSID':
|
||||||
|
user_dict[dmr_id][1]['ssid'] = value
|
||||||
|
if setting.upper() == 'COM':
|
||||||
|
user_comment = user_dict[dmr_id][3]['comment'] = value[0:35]
|
||||||
|
# Write modified dict to file
|
||||||
|
with open("./user_settings.txt", 'w') as user_dict_file:
|
||||||
|
user_dict_file.write(str(user_dict))
|
||||||
|
user_dict_file.close()
|
||||||
|
## except:
|
||||||
|
## logger.info('No data file found, creating one.')
|
||||||
|
## #Path('./user_settings.txt').mkdir(parents=True, exist_ok=True)
|
||||||
|
## Path('./user_settings.txt').touch()
|
||||||
|
|
||||||
|
|
||||||
# Process SMS, do something bases on message
|
# Process SMS, do something bases on message
|
||||||
|
|
||||||
def process_sms(from_id, sms):
|
def process_sms(from_id, sms):
|
||||||
@ -127,6 +160,12 @@ def process_sms(from_id, sms):
|
|||||||
logger.info(str(get_alias(int_id(from_id), subscriber_ids)) + ' - ' + str(int_id(from_id)))
|
logger.info(str(get_alias(int_id(from_id), subscriber_ids)) + ' - ' + str(int_id(from_id)))
|
||||||
if sms == 'TEST':
|
if sms == 'TEST':
|
||||||
logger.info('It works!')
|
logger.info('It works!')
|
||||||
|
if '@ICON' in sms:
|
||||||
|
user_setting_write(int_id(from_id), re.sub(' .*|@','',sms), re.sub('@ICON| ','',sms))
|
||||||
|
if '@SSID' in sms:
|
||||||
|
user_setting_write(int_id(from_id), re.sub(' .*|@','',sms), re.sub('@SSID| ','',sms))
|
||||||
|
if '@COM' in sms:
|
||||||
|
user_setting_write(int_id(from_id), re.sub(' .*|@','',sms), re.sub('@COM |@COM','',sms))
|
||||||
try:
|
try:
|
||||||
if sms in cmd_list:
|
if sms in cmd_list:
|
||||||
logger.info('Executing command/script.')
|
logger.info('Executing command/script.')
|
||||||
@ -193,8 +232,33 @@ class DATA_SYSTEM(HBSYSTEM):
|
|||||||
logger.info('Latitude: ' + str(loc.lat) + str(loc.lat_dir) + ' Longitude: ' + str(loc.lon) + str(loc.lon_dir) + ' Direction: ' + str(loc.true_course) + ' Speed: ' + str(loc.spd_over_grnd) + '\n')
|
logger.info('Latitude: ' + str(loc.lat) + str(loc.lat_dir) + ' Longitude: ' + str(loc.lon) + str(loc.lon_dir) + ' Direction: ' + str(loc.true_course) + ' Speed: ' + str(loc.spd_over_grnd) + '\n')
|
||||||
# Begin APRS format and upload
|
# Begin APRS format and upload
|
||||||
## aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + str(user_ssid) + '>APRS,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(final_packet[29:36]) + str(final_packet[39]) + '/' + str(re.sub(',', '', final_packet[41:49])) + str(final_packet[52]) + '[/' + aprs_comment + ' DMR ID: ' + str(int_id(_rf_src))
|
## aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + str(user_ssid) + '>APRS,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(final_packet[29:36]) + str(final_packet[39]) + '/' + str(re.sub(',', '', final_packet[41:49])) + str(final_packet[52]) + '[/' + aprs_comment + ' DMR ID: ' + str(int_id(_rf_src))
|
||||||
aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + str(user_ssid) + '>APRS,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(loc.lat[0:7]) + str(loc.lat_dir) + '/' + str(loc.lon[0:8]) + str(loc.lon_dir) + '[/' + aprs_comment + ' DMR ID: ' + str(int_id(_rf_src))
|
try:
|
||||||
|
with open("./user_settings.txt", 'r') as f:
|
||||||
|
user_settings = ast.literal_eval(f.read())
|
||||||
|
if int_id(_rf_src) not in user_settings:
|
||||||
|
aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + str(user_ssid) + '>APRS,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(loc.lat[0:7]) + str(loc.lat_dir) + '/' + str(loc.lon[0:8]) + str(loc.lon_dir) + '[' + str(round(loc.true_course)).zfill(3) + '/' + str(round(loc.spd_over_grnd)).zfill(3) + '/' + aprs_comment + ' DMR ID: ' + str(int_id(_rf_src))
|
||||||
|
else:
|
||||||
|
if user_settings[int_id(_rf_src)][1]['ssid'] == '':
|
||||||
|
ssid = user_ssid
|
||||||
|
if user_settings[int_id(_rf_src)][3]['comment'] == '':
|
||||||
|
comment = aprs_comment + ' DMR ID: ' + str(int_id(_rf_src))
|
||||||
|
if user_settings[int_id(_rf_src)][2]['icon'] == '':
|
||||||
|
icon_table = '/'
|
||||||
|
icon_icon = '['
|
||||||
|
if user_settings[int_id(_rf_src)][2]['icon'] != '':
|
||||||
|
icon_table = user_settings[int_id(_rf_src)][2]['icon'][0]
|
||||||
|
icon_icon = user_settings[int_id(_rf_src)][2]['icon'][1]
|
||||||
|
if user_settings[int_id(_rf_src)][1]['ssid'] != '':
|
||||||
|
ssid = user_settings[int_id(_rf_src)][1]['ssid']
|
||||||
|
if user_settings[int_id(_rf_src)][3]['comment'] != '':
|
||||||
|
comment = user_settings[int_id(_rf_src)][3]['comment']
|
||||||
|
aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + ssid + '>APRS,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(loc.lat[0:7]) + str(loc.lat_dir) + icon_table + str(loc.lon[0:8]) + str(loc.lon_dir) + icon_icon + str(round(loc.true_course)).zfill(3) + '/' + str(round(loc.spd_over_grnd)).zfill(3) + '/' + str(comment)
|
||||||
logger.info(aprs_loc_packet)
|
logger.info(aprs_loc_packet)
|
||||||
|
logger.info(comment)
|
||||||
|
f.close()
|
||||||
|
except:
|
||||||
|
logger.info('Error or user settings file not found, proceeding with default settings.')
|
||||||
|
aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + str(user_ssid) + '>APRS,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(loc.lat[0:7]) + str(loc.lat_dir) + '/' + str(loc.lon[0:8]) + str(loc.lon_dir) + '[' + str(round(loc.true_course)).zfill(3) + '/' + str(round(loc.spd_over_grnd)).zfill(3) + '/' + aprs_comment + ' DMR ID: ' + str(int_id(_rf_src))
|
||||||
try:
|
try:
|
||||||
# Try parse of APRS packet. If it fails, it will not upload to APRS-IS
|
# Try parse of APRS packet. If it fails, it will not upload to APRS-IS
|
||||||
aprslib.parse(aprs_loc_packet)
|
aprslib.parse(aprs_loc_packet)
|
||||||
@ -251,6 +315,15 @@ if __name__ == '__main__':
|
|||||||
# Change the current directory to the location of the application
|
# Change the current directory to the location of the application
|
||||||
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
|
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
|
||||||
|
|
||||||
|
# Check if user_settings (for APRS settings of users) exists. Creat it if not.
|
||||||
|
if Path('./user_settings.txt').is_file():
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
Path('./user_settings.txt').touch()
|
||||||
|
with open("./user_settings.txt", 'w') as user_dict_file:
|
||||||
|
user_dict_file.write("{1: [{'call': 'N0CALL'}, {'ssid': ''}, {'icon': ''}, {'comment': ''}]}")
|
||||||
|
user_dict_file.close()
|
||||||
|
|
||||||
# CLI argument parser - handles picking up the config file from the command line, and sending a "help" message
|
# CLI argument parser - handles picking up the config file from the command line, and sending a "help" message
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('-c', '--config', action='store', dest='CONFIG_FILE', help='/full/path/to/config.file (usually hblink.cfg)')
|
parser.add_argument('-c', '--config', action='store', dest='CONFIG_FILE', help='/full/path/to/config.file (usually hblink.cfg)')
|
||||||
|
Loading…
Reference in New Issue
Block a user