add SMS capture

This commit is contained in:
KF7EEL 2021-05-02 09:09:20 -07:00
parent 11a296252d
commit 979fedb218
4 changed files with 243 additions and 148 deletions

View File

@ -112,7 +112,7 @@ __copyright__ = 'Copyright (c) 2016-2019 Cortney T. Buffington, N0MJS and the K
__credits__ = 'Colin Durbridge, G4EML, Steve Zingman, N4IRS; Mike Zingman, N4IRR; Jonathan Naylor, G4KLX; Hans Barthen, DL5DI; Torsten Shultze, DG1HT, Xavier FRS2013' __credits__ = 'Colin Durbridge, G4EML, Steve Zingman, N4IRS; Mike Zingman, N4IRR; Jonathan Naylor, G4KLX; Hans Barthen, DL5DI; Torsten Shultze, DG1HT, Xavier FRS2013'
__license__ = 'GNU GPLv3' __license__ = 'GNU GPLv3'
__maintainer__ = 'Eric Craw, KF7EEL' __maintainer__ = 'Eric Craw, KF7EEL'
__email__ = 'n0mjs@me.com' __email__ = 'kf7eel@qsl.net'
# Module gobal varaibles # Module gobal varaibles
@ -206,6 +206,18 @@ def dashboard_bb_write(call, dmr_id, time, bulletin):
logger.info('User bulletin entry saved.') logger.info('User bulletin entry saved.')
#logger.info(dash_bb) #logger.info(dash_bb)
def dashboard_sms_write(snd_call, rcv_call, rcv_dmr_id, snd_dmr_id, sms, time):
#try:
dash_sms = ast.literal_eval(os.popen('cat ' + sms_file).read())
# except:
# dash_entries = []
dash_sms.insert(0, {'snd_call': snd_call, 'rcv_call':rcv_call, 'snd_dmr_id': snd_dmr_id, 'rcv_dmr_id':rcv_dmr_id, 'time': time, 'sms':sms})
with open(sms_file, 'w') as user_sms_file:
user_sms_file.write(str(dash_sms[:25]))
user_sms_file.close()
logger.info('User SMS entry saved.')
def mailbox_write(call, dmr_id, time, message, recipient): def mailbox_write(call, dmr_id, time, message, recipient):
#try: #try:
mail_file = ast.literal_eval(os.popen('cat ' + the_mailbox_file).read()) mail_file = ast.literal_eval(os.popen('cat ' + the_mailbox_file).read())
@ -2343,80 +2355,81 @@ class routerHBP(HBSYSTEM):
#logger.info(_rf_src) #logger.info(_rf_src)
#logger.info((ba2num(bptc_decode(_data)[8:12]))) #logger.info((ba2num(bptc_decode(_data)[8:12])))
################################################################3###### CHNGED ######### ################################################################3###### CHNGED #########
if int_id(_dst_id) == data_id: ## if int_id(_dst_id) == data_id:
#logger.info(type(_seq)) #logger.info(type(_seq))
if type(_seq) is bytes: if type(_seq) is bytes:
pckt_seq = int.from_bytes(_seq, 'big') pckt_seq = int.from_bytes(_seq, 'big')
else: else:
pckt_seq = _seq pckt_seq = _seq
# Try to classify header # Try to classify header
# UDT header has DPF of 0101, which is 5. # UDT header has DPF of 0101, which is 5.
# If 5 is at position 3, then this should be a UDT header for MD-380 type radios. # If 5 is at position 3, then this should be a UDT header for MD-380 type radios.
# Coordinates are usually in the very next block after the header, we will discard the rest. # Coordinates are usually in the very next block after the header, we will discard the rest.
#logger.info(ahex(bptc_decode(_data)[0:10])) #logger.info(ahex(bptc_decode(_data)[0:10]))
if _call_type == call_type and header_ID(_data)[3] == '5' and ba2num(bptc_decode(_data)[69:72]) == 0 and ba2num(bptc_decode(_data)[8:12]) == 0 or (_call_type == 'vcsbk' and header_ID(_data)[3] == '5' and ba2num(bptc_decode(_data)[69:72]) == 0 and ba2num(bptc_decode(_data)[8:12]) == 0): if _call_type == call_type and header_ID(_data)[3] == '5' and ba2num(bptc_decode(_data)[69:72]) == 0 and ba2num(bptc_decode(_data)[8:12]) == 0 or (_call_type == 'vcsbk' and header_ID(_data)[3] == '5' and ba2num(bptc_decode(_data)[69:72]) == 0 and ba2num(bptc_decode(_data)[8:12]) == 0):
global udt_block global udt_block
logger.info('MD-380 type UDT header detected. Very next packet should be location.') logger.info('MD-380 type UDT header detected. Very next packet should be location.')
hdr_type = '380' hdr_type = '380'
if _dtype_vseq == 6 and hdr_type == '380' or _dtype_vseq == 'group' and hdr_type == '380': if _dtype_vseq == 6 and hdr_type == '380' or _dtype_vseq == 'group' and hdr_type == '380':
udt_block = 1 udt_block = 1
if _dtype_vseq == 7 and hdr_type == '380': if _dtype_vseq == 7 and hdr_type == '380':
udt_block = udt_block - 1 udt_block = udt_block - 1
if udt_block == 0: if udt_block == 0:
logger.info('MD-380 type packet. This should contain the GPS location.') logger.info('MD-380 type packet. This should contain the GPS location.')
logger.info('Packet: ' + str(ahex(bptc_decode(_data)))) logger.info('Packet: ' + str(ahex(bptc_decode(_data))))
if ba2num(bptc_decode(_data)[1:2]) == 1: if ba2num(bptc_decode(_data)[1:2]) == 1:
lat_dir = 'N' lat_dir = 'N'
if ba2num(bptc_decode(_data)[1:2]) == 0: if ba2num(bptc_decode(_data)[1:2]) == 0:
lat_dir = 'S' lat_dir = 'S'
if ba2num(bptc_decode(_data)[2:3]) == 1: if ba2num(bptc_decode(_data)[2:3]) == 1:
lon_dir = 'E' lon_dir = 'E'
if ba2num(bptc_decode(_data)[2:3]) == 0: if ba2num(bptc_decode(_data)[2:3]) == 0:
lon_dir = 'W' lon_dir = 'W'
lat_deg = ba2num(bptc_decode(_data)[11:18]) lat_deg = ba2num(bptc_decode(_data)[11:18])
lon_deg = ba2num(bptc_decode(_data)[38:46]) lon_deg = ba2num(bptc_decode(_data)[38:46])
lat_min = ba2num(bptc_decode(_data)[18:24]) lat_min = ba2num(bptc_decode(_data)[18:24])
lon_min = ba2num(bptc_decode(_data)[46:52]) lon_min = ba2num(bptc_decode(_data)[46:52])
lat_min_dec = str(ba2num(bptc_decode(_data)[24:38])).zfill(4) lat_min_dec = str(ba2num(bptc_decode(_data)[24:38])).zfill(4)
lon_min_dec = str(ba2num(bptc_decode(_data)[52:66])).zfill(4) lon_min_dec = str(ba2num(bptc_decode(_data)[52:66])).zfill(4)
# Old MD-380 coordinate format, keep here until new is confirmed working. # Old MD-380 coordinate format, keep here until new is confirmed working.
#aprs_lat = str(str(lat_deg) + str(lat_min) + '.' + str(lat_min_dec)[0:2]).zfill(7) + lat_dir #aprs_lat = str(str(lat_deg) + str(lat_min) + '.' + str(lat_min_dec)[0:2]).zfill(7) + lat_dir
#aprs_lon = str(str(lon_deg) + str(lon_min) + '.' + str(lon_min_dec)[0:2]).zfill(8) + lon_dir #aprs_lon = str(str(lon_deg) + str(lon_min) + '.' + str(lon_min_dec)[0:2]).zfill(8) + lon_dir
# Fix for MD-380 by G7HIF # Fix for MD-380 by G7HIF
aprs_lat = str(str(lat_deg) + str(lat_min).zfill(2) + '.' + str(lat_min_dec)[0:2]).zfill(7) + lat_dir aprs_lat = str(str(lat_deg) + str(lat_min).zfill(2) + '.' + str(lat_min_dec)[0:2]).zfill(7) + lat_dir
aprs_lon = str(str(lon_deg) + str(lon_min).zfill(2) + '.' + str(lon_min_dec)[0:2]).zfill(8) + lon_dir aprs_lon = str(str(lon_deg) + str(lon_min).zfill(2) + '.' + str(lon_min_dec)[0:2]).zfill(8) + lon_dir
# Form APRS packet # Form APRS packet
#logger.info(aprs_loc_packet) #logger.info(aprs_loc_packet)
logger.info('Lat: ' + str(aprs_lat) + ' Lon: ' + str(aprs_lon)) logger.info('Lat: ' + str(aprs_lat) + ' Lon: ' + str(aprs_lon))
# 14FRS2013 simplified and moved settings retrieval # 14FRS2013 simplified and moved settings retrieval
user_settings = ast.literal_eval(os.popen('cat ' + user_settings_file).read()) user_settings = ast.literal_eval(os.popen('cat ' + user_settings_file).read())
if int_id(_rf_src) not in user_settings: if int_id(_rf_src) not in user_settings:
ssid = str(user_ssid) ssid = str(user_ssid)
icon_table = '/'
icon_icon = '['
comment = 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_table = '/'
icon_icon = '[' icon_icon = '['
comment = aprs_comment + ' DMR ID: ' + str(int_id(_rf_src)) if user_settings[int_id(_rf_src)][2]['icon'] != '':
else: icon_table = user_settings[int_id(_rf_src)][2]['icon'][0]
if user_settings[int_id(_rf_src)][1]['ssid'] == '': icon_icon = user_settings[int_id(_rf_src)][2]['icon'][1]
ssid = user_ssid if user_settings[int_id(_rf_src)][1]['ssid'] != '':
if user_settings[int_id(_rf_src)][3]['comment'] == '': ssid = user_settings[int_id(_rf_src)][1]['ssid']
comment = aprs_comment + ' DMR ID: ' + str(int_id(_rf_src)) if user_settings[int_id(_rf_src)][3]['comment'] != '':
if user_settings[int_id(_rf_src)][2]['icon'] == '': comment = user_settings[int_id(_rf_src)][3]['comment']
icon_table = '/' aprs_loc_packet = str(get_alias(int_id(_rf_src), subscriber_ids)) + '-' + ssid + '>APHBL3,TCPIP*:@' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(aprs_lat) + icon_table + str(aprs_lon) + icon_icon + '/' + str(comment)
icon_icon = '[' logger.info(aprs_loc_packet)
if user_settings[int_id(_rf_src)][2]['icon'] != '': logger.info('User comment: ' + comment)
icon_table = user_settings[int_id(_rf_src)][2]['icon'][0] logger.info('User SSID: ' + ssid)
icon_icon = user_settings[int_id(_rf_src)][2]['icon'][1] logger.info('User icon: ' + icon_table + icon_icon)
if user_settings[int_id(_rf_src)][1]['ssid'] != '': # Attempt to prevent malformed packets from being uploaded.
ssid = user_settings[int_id(_rf_src)][1]['ssid'] if int_id(_dst_id) == data_id:
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 + '>APHBL3,TCPIP*:@' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(aprs_lat) + icon_table + str(aprs_lon) + icon_icon + '/' + str(comment)
logger.info(aprs_loc_packet)
logger.info('User comment: ' + comment)
logger.info('User SSID: ' + ssid)
logger.info('User icon: ' + icon_table + icon_icon)
# Attempt to prevent malformed packets from being uploaded.
try: try:
aprslib.parse(aprs_loc_packet) aprslib.parse(aprs_loc_packet)
float(lat_deg) < 91 float(lat_deg) < 91
@ -2428,60 +2441,61 @@ class routerHBP(HBSYSTEM):
logger.info('Error. Failed to send packet. Packet may be malformed.') logger.info('Error. Failed to send packet. Packet may be malformed.')
logger.info(error_exception) logger.info(error_exception)
logger.info(str(traceback.extract_tb(error_exception.__traceback__))) logger.info(str(traceback.extract_tb(error_exception.__traceback__)))
udt_block = 1 udt_block = 1
hdr_type = '' hdr_type = ''
else: else:
pass pass
#NMEA type packets for Anytone like radios. #NMEA type packets for Anytone like radios.
#if _call_type == call_type or (_call_type == 'vcsbk' and pckt_seq > 3): #int.from_bytes(_seq, 'big') > 3 ): #if _call_type == call_type or (_call_type == 'vcsbk' and pckt_seq > 3): #int.from_bytes(_seq, 'big') > 3 ):
# 14FRS2013 contributed improved header filtering, KF7EEL added conditions to allow both call types at the same time # 14FRS2013 contributed improved header filtering, KF7EEL added conditions to allow both call types at the same time
if _call_type == call_type or (_call_type == 'vcsbk' and pckt_seq > 3 and call_type != 'unit') or (_call_type == 'group' and pckt_seq > 3 and call_type != 'unit') or (_call_type == 'group' and pckt_seq > 3 and call_type == 'both') or (_call_type == 'vcsbk' and pckt_seq > 3 and call_type == 'both') or (_call_type == 'unit' and pckt_seq > 3 and call_type == 'both'): #int.from_bytes(_seq, 'big') > 3 ): if _call_type == call_type or (_call_type == 'vcsbk' and pckt_seq > 3 and call_type != 'unit') or (_call_type == 'group' and pckt_seq > 3 and call_type != 'unit') or (_call_type == 'group' and pckt_seq > 3 and call_type == 'both') or (_call_type == 'vcsbk' and pckt_seq > 3 and call_type == 'both') or (_call_type == 'unit' and pckt_seq > 3 and call_type == 'both'): #int.from_bytes(_seq, 'big') > 3 ):
global packet_assembly, btf global packet_assembly, btf
if _dtype_vseq == 6 or _dtype_vseq == 'group': if _dtype_vseq == 6 or _dtype_vseq == 'group':
global btf, hdr_start global btf, hdr_start
hdr_start = str(header_ID(_data)) hdr_start = str(header_ID(_data))
logger.info('Header from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + '. DMR ID: ' + str(int_id(_rf_src))) logger.info('Header from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + '. DMR ID: ' + str(int_id(_rf_src)))
logger.info(ahex(bptc_decode(_data))) logger.info(ahex(bptc_decode(_data)))
logger.info('Blocks to follow: ' + str(ba2num(bptc_decode(_data)[65:72]))) logger.info('Blocks to follow: ' + str(ba2num(bptc_decode(_data)[65:72])))
btf = ba2num(bptc_decode(_data)[65:72]) btf = ba2num(bptc_decode(_data)[65:72])
# Try resetting packet_assembly # Try resetting packet_assembly
packet_assembly = ''
# Data blocks at 1/2 rate, see https://github.com/g4klx/MMDVM/blob/master/DMRDefines.h for data types. _dtype_seq defined here also
if _dtype_vseq == 7:
btf = btf - 1
logger.info('Block #: ' + str(btf))
#logger.info(_seq)
logger.info('Data block from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + '. DMR ID: ' + str(int_id(_rf_src)) + '. Destination: ' + str(int_id(_dst_id)))
logger.info(ahex(bptc_decode(_data)))
if _seq == 0:
n_packet_assembly = 0
packet_assembly = '' packet_assembly = ''
# Data blocks at 1/2 rate, see https://github.com/g4klx/MMDVM/blob/master/DMRDefines.h for data types. _dtype_seq defined here also
if _dtype_vseq == 7: #if btf < btf + 1:
btf = btf - 1 # 14FRS2013 removed condition, works great!
logger.info('Block #: ' + str(btf)) n_packet_assembly = n_packet_assembly + 1
#logger.info(_seq) packet_assembly = packet_assembly + str(bptc_decode(_data)) #str((decode_full_lc(b_packet)).strip('bitarray('))
logger.info('Data block from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + '. DMR ID: ' + str(int_id(_rf_src)) + '. Destination: ' + str(int_id(_dst_id))) # Use block 0 as trigger. $GPRMC must also be in string to indicate NMEA.
logger.info(ahex(bptc_decode(_data))) # This triggers the APRS upload
if _seq == 0: if btf == 0:
n_packet_assembly = 0 final_packet = str(bitarray(re.sub("\)|\(|bitarray|'", '', packet_assembly)).tobytes().decode('utf-8', 'ignore'))
packet_assembly = '' sms_hex = str(ba2hx(bitarray(re.sub("\)|\(|bitarray|'", '', packet_assembly))))
sms_hex_string = re.sub("b'|'", '', str(sms_hex))
#if btf < btf + 1: #NMEA GPS sentence
# 14FRS2013 removed condition, works great! if '$GPRMC' in final_packet or '$GNRMC' in final_packet:
n_packet_assembly = n_packet_assembly + 1 logger.info(final_packet + '\n')
packet_assembly = packet_assembly + str(bptc_decode(_data)) #str((decode_full_lc(b_packet)).strip('bitarray(')) # Eliminate excess bytes based on NMEA type
# Use block 0 as trigger. $GPRMC must also be in string to indicate NMEA. # GPRMC
# This triggers the APRS upload if 'GPRMC' in final_packet:
if btf == 0: logger.info('GPRMC location')
final_packet = str(bitarray(re.sub("\)|\(|bitarray|'", '', packet_assembly)).tobytes().decode('utf-8', 'ignore')) #nmea_parse = re.sub('A\*.*|.*\$', '', str(final_packet))
sms_hex = str(ba2hx(bitarray(re.sub("\)|\(|bitarray|'", '', packet_assembly)))) nmea_parse = re.sub('A\*.*|.*\$|\n.*', '', str(final_packet))
sms_hex_string = re.sub("b'|'", '', str(sms_hex)) # GNRMC
#NMEA GPS sentence if 'GNRMC' in final_packet:
if '$GPRMC' in final_packet or '$GNRMC' in final_packet: logger.info('GNRMC location')
logger.info(final_packet + '\n') nmea_parse = re.sub('.*\$|\n.*|V\*.*', '', final_packet)
# Eliminate excess bytes based on NMEA type loc = pynmea2.parse(nmea_parse, check=False)
# GPRMC 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')
if 'GPRMC' in final_packet: if int_id(_dst_id) == data_id:
logger.info('GPRMC location')
#nmea_parse = re.sub('A\*.*|.*\$', '', str(final_packet))
nmea_parse = re.sub('A\*.*|.*\$|\n.*', '', str(final_packet))
# GNRMC
if 'GNRMC' in final_packet:
logger.info('GNRMC location')
nmea_parse = re.sub('.*\$|\n.*|V\*.*', '', final_packet)
loc = pynmea2.parse(nmea_parse, check=False)
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')
try: try:
# Begin APRS format and upload # Begin APRS format and upload
# Disable opening file for reading to reduce "collision" or reading and writing at same time. # Disable opening file for reading to reduce "collision" or reading and writing at same time.
@ -2532,8 +2546,8 @@ class routerHBP(HBSYSTEM):
# Get callsign based on DMR ID # Get callsign based on DMR ID
# End APRS-IS upload # End APRS-IS upload
# Assume this is an SMS message # Assume this is an SMS message
elif '$GPRMC' not in final_packet or '$GNRMC' not in final_packet: elif '$GPRMC' not in final_packet or '$GNRMC' not in final_packet:
#### # Motorola type SMS header #### # Motorola type SMS header
## if '824a' in hdr_start or '024a' in hdr_start: ## if '824a' in hdr_start or '024a' in hdr_start:
## logger.info('\nMotorola type SMS') ## logger.info('\nMotorola type SMS')
@ -2552,26 +2566,42 @@ class routerHBP(HBSYSTEM):
## packet_assembly = '' ## packet_assembly = ''
#### ####
## else: ## else:
logger.info('\nSMS detected. Attempting to parse.') logger.info('\nSMS detected. Attempting to parse.')
#logger.info(final_packet) #logger.info(final_packet)
logger.info(sms_hex) logger.info(sms_hex)
## logger.info(type(sms_hex)) ## logger.info(type(sms_hex))
logger.info('Attempting to find command...') logger.info('Attempting to find command...')
## sms = codecs.decode(bytes.fromhex(''.join(sms_hex[:-8].split('00'))), 'utf-8', 'ignore') ## sms = codecs.decode(bytes.fromhex(''.join(sms_hex[:-8].split('00'))), 'utf-8', 'ignore')
sms = codecs.decode(bytes.fromhex(''.join(sms_hex_string[:-8].split('00'))), 'utf-8', 'ignore') sms = codecs.decode(bytes.fromhex(''.join(sms_hex_string[:-8].split('00'))), 'utf-8', 'ignore')
msg_found = re.sub('.*\n', '', sms) msg_found = re.sub('.*\n', '', sms)
logger.info('\n\n' + 'Received SMS from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + ', DMR ID: ' + str(int_id(_rf_src)) + ': ' + str(msg_found) + '\n') logger.info('\n\n' + 'Received SMS from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + ', DMR ID: ' + str(int_id(_rf_src)) + ': ' + str(msg_found) + '\n')
if int_id(_dst_id) == data_id:
process_sms(_rf_src, msg_found, _call_type) process_sms(_rf_src, msg_found, _call_type)
#packet_assembly = '' if int_id(_dst_id) != data_id:
if '//' in sms or sms.count(',') > 4 or sms.count('.') > 3 or 'PIN' in sms:
logger.info('Not logging due to possible data error, or double slash.')
else:
if int_id(_dst_id) == data_id:
logger.info('SMS command, not logging')
else:
logger.info('Log SMS to dashboard and subscriber mailbox')
mailbox_write(get_alias(int_id(_rf_src), subscriber_ids), int_id(_rf_src), time(), msg_found, str(get_alias(int_id(_dst_id), subscriber_ids)).upper())
dashboard_sms_write(str(get_alias(int_id(_rf_src), subscriber_ids)), str(get_alias(int_id(_dst_id), subscriber_ids)), str(int_id(_dst_id)), str(int_id(_rf_src)), msg_found, time())
#packet_assembly = ''
pass pass
#logger.info(bitarray(re.sub("\)|\(|bitarray|'", '', str(bptc_decode(_data)).tobytes().decode('utf-8', 'ignore')))) #logger.info(bitarray(re.sub("\)|\(|bitarray|'", '', str(bptc_decode(_data)).tobytes().decode('utf-8', 'ignore'))))
#logger.info('\n\n' + 'Received SMS from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + ', DMR ID: ' + str(int_id(_rf_src)) + ': ' + str(sms) + '\n') #logger.info('\n\n' + 'Received SMS from ' + str(get_alias(int_id(_rf_src), subscriber_ids)) + ', DMR ID: ' + str(int_id(_rf_src)) + ': ' + str(sms) + '\n')
# Reset the packet assembly to prevent old data from returning. # Reset the packet assembly to prevent old data from returning.
# 14FRS2013 moved variable reset # 14FRS2013 moved variable reset
hdr_start = '' hdr_start = ''
n_packet_assembly = 0 n_packet_assembly = 0
packet_assembly = '' packet_assembly = ''
btf = 0 btf = 0
#logger.info(_seq) #logger.info(_seq)
#packet_assembly = '' #logger.info(_dtype_vseq) #packet_assembly = '' #logger.info(_dtype_vseq)
#logger.info(ahex(bptc_decode(_data)).decode('utf-8', 'ignore')) #logger.info(ahex(bptc_decode(_data)).decode('utf-8', 'ignore'))
@ -2585,16 +2615,16 @@ class routerHBP(HBSYSTEM):
if _call_type == 'group': if _call_type == 'group':
self.group_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _frame_type, _dtype_vseq, _stream_id, _data) self.group_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _frame_type, _dtype_vseq, _stream_id, _data)
# If destination ID = to DATA_DMR_ID, process packet # If destination ID = to DATA_DMR_ID, process packet
if int_id(_dst_id) == data_id: #if int_id(_dst_id) == data_id:
self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data) self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
# Used for dev, leave commented out # Used for dev, leave commented out
#self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data) #self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
elif _call_type == 'unit': elif _call_type == 'unit':
# If destination ID = to DATA_DMR_ID, process packet # If destination ID = to DATA_DMR_ID, process packet
if int_id(_dst_id) == data_id: #if int_id(_dst_id) == data_id:
#logger.info('btf' + str(btf)) #logger.info('btf' + str(btf))
self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data) self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
# Used for dev, leave commented out # Used for dev, leave commented out
#self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data) #self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
@ -2608,8 +2638,8 @@ class routerHBP(HBSYSTEM):
self.group_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _frame_type, _dtype_vseq, _stream_id, _data) self.group_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _frame_type, _dtype_vseq, _stream_id, _data)
logger.debug('CSBK recieved, but HBlink does not process them currently. Packets routed to talkgroup.') logger.debug('CSBK recieved, but HBlink does not process them currently. Packets routed to talkgroup.')
# If destination ID = to DATA_DMR_ID, process packet # If destination ID = to DATA_DMR_ID, process packet
if int_id(_dst_id) == data_id: #if int_id(_dst_id) == data_id:
self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data) self.data_received(_peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data)
else: else:
logger.error('Unknown call type recieved -- not processed') logger.error('Unknown call type recieved -- not processed')
@ -2679,6 +2709,7 @@ if __name__ == '__main__':
loc_file = CONFIG['GPS_DATA']['LOCATION_FILE'] loc_file = CONFIG['GPS_DATA']['LOCATION_FILE']
the_mailbox_file = CONFIG['GPS_DATA']['MAILBOX_FILE'] the_mailbox_file = CONFIG['GPS_DATA']['MAILBOX_FILE']
emergency_sos_file = CONFIG['GPS_DATA']['EMERGENCY_SOS_FILE'] emergency_sos_file = CONFIG['GPS_DATA']['EMERGENCY_SOS_FILE']
sms_file = CONFIG['GPS_DATA']['SMS_FILE']
# User APRS settings # User APRS settings
user_settings_file = CONFIG['GPS_DATA']['USER_SETTINGS_FILE'] user_settings_file = CONFIG['GPS_DATA']['USER_SETTINGS_FILE']
@ -2707,6 +2738,14 @@ if __name__ == '__main__':
with open(bb_file, 'w') as user_bb_file: with open(bb_file, 'w') as user_bb_file:
user_bb_file.write("[]") user_bb_file.write("[]")
user_bb_file.close() user_bb_file.close()
if Path(sms_file).is_file():
pass
else:
Path(sms_file).touch()
with open(sms_file, 'w') as user_sms_file:
user_sms_file.write("[]")
user_sms_file.close()
#Only create if API enabled #Only create if API enabled
if use_api == True: if use_api == True:
# Generate the apps dictionary # Generate the apps dictionary

View File

@ -92,6 +92,52 @@ def get_loc_data():
except: except:
return str('<h1 style="text-align: center;">No data</h1>') return str('<h1 style="text-align: center;">No data</h1>')
def get_sms_data():
try:
dash_sms = ast.literal_eval(os.popen('cat ' + sms_file).read())
tmp_sms = ''
sms_hdr = '''
<tr>
<td style="text-align: center;">
<h2><strong>&nbsp;Source <br /></strong></h2>
</td>
<td style="text-align: center;">
<h2>&nbsp;<strong>Destination</strong> </h2>
</td>
<td style="text-align: center;">
<h2>&nbsp;<strong>SMS</strong> </h2>
</td>
<td style="text-align: center;">
<h2>&nbsp;<strong>Local Time</strong>&nbsp;</h2>
</td>
</tr>
'''
for e in dash_sms:
if type(e['time']) == str:
loc_time = str(e['time'])
if type(e['time']) == int or type(e['time']) == float:
loc_time = datetime.fromtimestamp(e['time']).strftime(time_format)
tmp_sms = tmp_sms + '''
<tr>
<td style="text-align: center;">
<p><strong>&nbsp;''' + e['snd_call'] + '''&nbsp;<br /></strong>''' + e['snd_dmr_id'] + '''<strong><br /></strong></p>
</td>
<td style="text-align: center;">
<p><strong>''' + e['rcv_call'] + '''</strong><br />''' + e['rcv_dmr_id'] + '''</p>
</td>
<td style="text-align: center;"><strong>&nbsp;''' + e['sms'] + '''&nbsp;</strong></td>
<td style="text-align: center;">&nbsp;''' + loc_time + '''&nbsp;</td>
</tr>
'''
return str('<h1 style="text-align: center;">SMS</h1>' + tbl_hdr + sms_hdr + tmp_sms + tbl_ftr)
except:
return str('<h1 style="text-align: center;">No data</h1>')
def get_bb_data(): def get_bb_data():
try: try:
@ -241,6 +287,12 @@ def dash_loc():
def help(): def help():
#return get_data() #return get_data()
return render_template('help.html', title = dashboard_title, dashboard_url = dashboard_url, logo = logo, description = description, api = use_api, data_call_type = data_call_type, data_call_id = data_call_id, aprs_ssid = aprs_ssid) return render_template('help.html', title = dashboard_title, dashboard_url = dashboard_url, logo = logo, description = description, api = use_api, data_call_type = data_call_type, data_call_id = data_call_id, aprs_ssid = aprs_ssid)
@app.route('/sms/')
def dash_template_sms():
#return get_data()
#return render_template('sms.html', title = dashboard_title, logo = logo)
return render_template('generic.html', title = dashboard_title, dashboard_url = dashboard_url, logo = logo, content = Markup(get_sms_data()))
@app.route('/about/') @app.route('/about/')
def about(): def about():
#return get_data() #return get_data()
@ -1001,6 +1053,8 @@ if __name__ == '__main__':
user_settings_file = parser.get('GPS_DATA', 'USER_SETTINGS_FILE') user_settings_file = parser.get('GPS_DATA', 'USER_SETTINGS_FILE')
auth_token_file = parser.get('GPS_DATA', 'AUTHORIZED_TOKENS_FILE') auth_token_file = parser.get('GPS_DATA', 'AUTHORIZED_TOKENS_FILE')
sms_file = parser.get('GPS_DATA', 'SMS_FILE')
use_api = parser.get('GPS_DATA', 'USE_API') use_api = parser.get('GPS_DATA', 'USE_API')
#access_systems_file = parser.get('GPS_DATA', 'ACCESS_SYSTEMS_FILE') #access_systems_file = parser.get('GPS_DATA', 'ACCESS_SYSTEMS_FILE')
#authorized_users_file = parser.get('GPS_DATA', 'AUTHORIZED_USERS_FILE') #authorized_users_file = parser.get('GPS_DATA', 'AUTHORIZED_USERS_FILE')

View File

@ -7,6 +7,7 @@
<td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/';"> Dashboard Home </button></td> <td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/';"> Dashboard Home </button></td>
<td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/map';"> Station Map </button></td> <td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/map';"> Station Map </button></td>
<td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/mailbox';"> The Mailbox </button></td> <td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/mailbox';"> The Mailbox </button></td>
<td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/sms';"> SMS Capture </button></td>
<td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/user';"> User Settings </button></td> <td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/user';"> User Settings </button></td>
{% if api %} {% if api %}
<td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/external_apps';"> External Applications </button></td> <td style="text-align: center;"><button onclick="window.location.href='{{dashboard_url}}/external_apps';"> External Applications </button></td>

View File

@ -168,6 +168,7 @@ def build_config(_config_file):
'LOCATION_FILE': config.get(section, 'LOCATION_FILE'), 'LOCATION_FILE': config.get(section, 'LOCATION_FILE'),
'BULLETIN_BOARD_FILE': config.get(section, 'BULLETIN_BOARD_FILE'), 'BULLETIN_BOARD_FILE': config.get(section, 'BULLETIN_BOARD_FILE'),
'MAILBOX_FILE': config.get(section, 'MAILBOX_FILE'), 'MAILBOX_FILE': config.get(section, 'MAILBOX_FILE'),
'SMS_FILE': config.get(section, 'SMS_FILE'),
'EMERGENCY_SOS_FILE': config.get(section, 'EMERGENCY_SOS_FILE'), 'EMERGENCY_SOS_FILE': config.get(section, 'EMERGENCY_SOS_FILE'),
'USER_SETTINGS_FILE': config.get(section, 'USER_SETTINGS_FILE'), 'USER_SETTINGS_FILE': config.get(section, 'USER_SETTINGS_FILE'),
'USE_API': config.getboolean(section, 'USE_API'), 'USE_API': config.getboolean(section, 'USE_API'),