add "DMR Standard" per Anytone SMS format for generation, clean code, swap MQTT commands
This commit is contained in:
parent
0d49fba100
commit
64af83e5cd
297
data_gateway.py
297
data_gateway.py
|
|
@ -123,12 +123,29 @@ __email__ = 'kf7eel@qsl.net'
|
||||||
|
|
||||||
sms_seq_num = 0
|
sms_seq_num = 0
|
||||||
use_csbk = False
|
use_csbk = False
|
||||||
hdr_type = ''
|
|
||||||
btf = -1
|
|
||||||
ssid = ''
|
ssid = ''
|
||||||
UNIT_MAP = {}
|
UNIT_MAP = {}
|
||||||
PACKET_MATCH = {}
|
PACKET_MATCH = {}
|
||||||
mqtt_services = {}
|
mqtt_services = {}
|
||||||
|
subscriber_format = {}
|
||||||
|
btf = {}
|
||||||
|
sub_hdr = {}
|
||||||
|
packet_assembly = {}
|
||||||
|
|
||||||
|
# Keep track of what user needs which SMS format
|
||||||
|
|
||||||
|
def sms_type(sub, sms):
|
||||||
|
# Port 5016, specified in ETSI 361-3
|
||||||
|
if sms[40:48] == '13981398':
|
||||||
|
subscriber_format[sub] = 'etsi'
|
||||||
|
# Port 4007, Motorola
|
||||||
|
elif sms[40:48] == '0fa70fa7':
|
||||||
|
subscriber_format[sub] = 'motorola'
|
||||||
|
else:
|
||||||
|
subscriber_format[sub] = 'motorola'
|
||||||
|
logger.debug(subscriber_format)
|
||||||
|
|
||||||
|
|
||||||
##mqtt_shortcut_gen = ''.join(random.choices(string.ascii_uppercase, k=4))
|
##mqtt_shortcut_gen = ''.join(random.choices(string.ascii_uppercase, k=4))
|
||||||
|
|
||||||
def mqtt_main(broker_url = 'localhost', broker_port = 1883):
|
def mqtt_main(broker_url = 'localhost', broker_port = 1883):
|
||||||
|
|
@ -198,7 +215,7 @@ def mqtt_send_msg(network_shortcut, rcv_dmr_id, snd_dmr_id, message):
|
||||||
logger.info('Sent message to another network via MQTT: ' + network_shortcut)
|
logger.info('Sent message to another network via MQTT: ' + network_shortcut)
|
||||||
|
|
||||||
def mqtt_send_app(network_shortcut, snd_dmr_id, message):
|
def mqtt_send_app(network_shortcut, snd_dmr_id, message):
|
||||||
msg_dict = json.dumps({'dmr_id': str(snd_dmr_id), 'message':message, 'network':mqtt_shortcut_gen}, indent = 4)
|
msg_dict = json.dumps({'dmr_id': str(snd_dmr_id), 'message':message, 'network':mqtt_shortcut_gen, 'sms_type':'unit'}, indent = 4)
|
||||||
mqtt_client.publish(topic='APP/' + network_shortcut, payload=msg_dict, qos=0, retain=False)
|
mqtt_client.publish(topic='APP/' + network_shortcut, payload=msg_dict, qos=0, retain=False)
|
||||||
logger.info('Sent message to external application via MQTT: ' + network_shortcut)
|
logger.info('Sent message to external application via MQTT: ' + network_shortcut)
|
||||||
|
|
||||||
|
|
@ -395,7 +412,7 @@ def send_known_services(CONFIG, _data):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = requests.post(user_man_url, data=json_object, headers={'Content-Type': 'application/json'})
|
req = requests.post(user_man_url, data=json_object, headers={'Content-Type': 'application/json'})
|
||||||
logger.debug('Sent UNIT table')
|
logger.debug('Sent MQTT table')
|
||||||
## resp = json.loads(req.text)
|
## resp = json.loads(req.text)
|
||||||
## print(resp)
|
## print(resp)
|
||||||
## return resp['rules']
|
## return resp['rules']
|
||||||
|
|
@ -560,7 +577,6 @@ def download_config(CONFIG_FILE, cli_file):
|
||||||
for o in mqtt_options:
|
for o in mqtt_options:
|
||||||
final_options = o.split('=')
|
final_options = o.split('=')
|
||||||
|
|
||||||
print(final_options)
|
|
||||||
if final_options[0] == 'gateway_callsign':
|
if final_options[0] == 'gateway_callsign':
|
||||||
mqtt_server = corrected_config['DATA_CONFIG']['GATEWAY_CALLSIGN'] = final_options[1].upper()
|
mqtt_server = corrected_config['DATA_CONFIG']['GATEWAY_CALLSIGN'] = final_options[1].upper()
|
||||||
if final_options[0] == 'server':
|
if final_options[0] == 'server':
|
||||||
|
|
@ -574,7 +590,6 @@ def download_config(CONFIG_FILE, cli_file):
|
||||||
if 'DATA_GATEWAY:' in i:
|
if 'DATA_GATEWAY:' in i:
|
||||||
## print(i)
|
## print(i)
|
||||||
gateway_options = i[13:].split(':')
|
gateway_options = i[13:].split(':')
|
||||||
## print(gateway_options)
|
|
||||||
## print(gateway_options)
|
## print(gateway_options)
|
||||||
for o in gateway_options:
|
for o in gateway_options:
|
||||||
## print(o)
|
## print(o)
|
||||||
|
|
@ -622,7 +637,7 @@ def download_config(CONFIG_FILE, cli_file):
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
# Headers for GPS by model of radio:
|
# Headers for GPS by model of radio:
|
||||||
# AT-D878 - Compressed UDP
|
# AT-D878 - Unconfirmed Data
|
||||||
# MD-380 - Unified Data Transport
|
# MD-380 - Unified Data Transport
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -643,23 +658,11 @@ def decode_full(_data):
|
||||||
return binlc
|
return binlc
|
||||||
|
|
||||||
|
|
||||||
n_packet_assembly = 0
|
|
||||||
|
|
||||||
packet_assembly = ''
|
|
||||||
|
|
||||||
final_packet = ''
|
|
||||||
|
|
||||||
#Convert DMR packet to binary from MMDVM packet and remove Slot Type and EMB Sync stuff to allow for BPTC 196,96 decoding
|
#Convert DMR packet to binary from MMDVM packet and remove Slot Type and EMB Sync stuff to allow for BPTC 196,96 decoding
|
||||||
def bptc_decode(_data):
|
def bptc_decode(_data):
|
||||||
binary_packet = bitarray(decode.to_bits(_data[20:]))
|
binary_packet = bitarray(decode.to_bits(_data[20:]))
|
||||||
del binary_packet[98:166]
|
del binary_packet[98:166]
|
||||||
return decode_full(binary_packet)
|
return decode_full(binary_packet)
|
||||||
# Placeholder for future header id
|
|
||||||
def header_ID(_data):
|
|
||||||
hex_hdr = str(ahex(bptc_decode(_data)))
|
|
||||||
return hex_hdr[2:6]
|
|
||||||
# Work in progress, used to determine data format
|
|
||||||
## pass
|
|
||||||
|
|
||||||
def aprs_send(packet):
|
def aprs_send(packet):
|
||||||
if 'N0CALL' in aprs_callsign:
|
if 'N0CALL' in aprs_callsign:
|
||||||
|
|
@ -765,13 +768,12 @@ def user_setting_write(dmr_id, setting, value, call_type):
|
||||||
user_dict_file.close()
|
user_dict_file.close()
|
||||||
logger.info('User setting saved')
|
logger.info('User setting saved')
|
||||||
f.close()
|
f.close()
|
||||||
packet_assembly = ''
|
|
||||||
|
|
||||||
# Process SMS, do something bases on message
|
# Process SMS, do something bases on message
|
||||||
def process_sms(_rf_src, sms, call_type, system_name):
|
def process_sms(_rf_src, sms, call_type, system_name):
|
||||||
parse_sms = sms.split(' ')
|
parse_sms = sms.split(' ')
|
||||||
logger.debug(parse_sms)
|
logger.debug(parse_sms)
|
||||||
logger.debug(call_type)
|
## logger.debug(call_type)
|
||||||
# Social Status function
|
# Social Status function
|
||||||
if '*SS' == parse_sms[0]:
|
if '*SS' == parse_sms[0]:
|
||||||
s = ' '
|
s = ' '
|
||||||
|
|
@ -784,6 +786,9 @@ def process_sms(_rf_src, sms, call_type, system_name):
|
||||||
elif '?' in parse_sms[0]:
|
elif '?' in parse_sms[0]:
|
||||||
send_sms_cmd(CONFIG, int_id(_rf_src), sms)
|
send_sms_cmd(CONFIG, int_id(_rf_src), sms)
|
||||||
|
|
||||||
|
elif parse_sms[0] == 'ECHO':
|
||||||
|
send_sms(False, int_id(_rf_src), data_id[0], data_id[0], 'unit', 'ECHO')
|
||||||
|
|
||||||
elif parse_sms[0] == 'ID':
|
elif parse_sms[0] == 'ID':
|
||||||
logger.info(str(get_alias(int_id(_rf_src), subscriber_ids)) + ' - ' + str(int_id(_rf_src)))
|
logger.info(str(get_alias(int_id(_rf_src), subscriber_ids)) + ' - ' + str(int_id(_rf_src)))
|
||||||
if call_type == 'unit':
|
if call_type == 'unit':
|
||||||
|
|
@ -880,16 +885,16 @@ def process_sms(_rf_src, sms, call_type, system_name):
|
||||||
logger.error('Exception. Not uploaded')
|
logger.error('Exception. Not uploaded')
|
||||||
logger.error(error_exception)
|
logger.error(error_exception)
|
||||||
logger.error(str(traceback.extract_tb(error_exception.__traceback__)))
|
logger.error(str(traceback.extract_tb(error_exception.__traceback__)))
|
||||||
packet_assembly = ''
|
## packet_assembly = ''
|
||||||
|
|
||||||
elif '#' == parse_sms[0][0:1]:
|
elif '.' == parse_sms[0][0:1]:
|
||||||
## print(mqtt_services.keys())
|
## print(mqtt_services.keys())
|
||||||
## if parse_sms[0][1:] in mqtt_services.keys():
|
## if parse_sms[0][1:] in mqtt_services.keys():
|
||||||
mqtt_send_msg(str(parse_sms[0])[1:], parse_sms[1], int_id(_rf_src), ' '.join(parse_sms[2:]))
|
mqtt_send_msg(str(parse_sms[0])[1:], parse_sms[1], int_id(_rf_src), ' '.join(parse_sms[2:]))
|
||||||
## else:
|
## else:
|
||||||
## # Add error message
|
## # Add error message
|
||||||
## pass
|
## pass
|
||||||
elif '!' == parse_sms[0][0:1]:
|
elif '#' == parse_sms[0][0:1]:
|
||||||
## print(mqtt_services.keys())
|
## print(mqtt_services.keys())
|
||||||
## if parse_sms[0][1:] in mqtt_services.keys():
|
## if parse_sms[0][1:] in mqtt_services.keys():
|
||||||
mqtt_send_app(str(parse_sms[0])[1:], str(int_id(_rf_src)), ' '.join(parse_sms[1:]))
|
mqtt_send_app(str(parse_sms[0])[1:], str(int_id(_rf_src)), ' '.join(parse_sms[1:]))
|
||||||
|
|
@ -943,7 +948,6 @@ def process_sms(_rf_src, sms, call_type, system_name):
|
||||||
logger.info('Exception. Command possibly not in list, or other error.')
|
logger.info('Exception. Command possibly not in list, or other error.')
|
||||||
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__)))
|
||||||
## packet_assembly = ''
|
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -1043,6 +1047,7 @@ def create_crc16_csbk(fragment_input):
|
||||||
## print(fragment_input)
|
## print(fragment_input)
|
||||||
crc16_csbk = libscrc.gsm16(bytearray.fromhex(fragment_input))
|
crc16_csbk = libscrc.gsm16(bytearray.fromhex(fragment_input))
|
||||||
return fragment_input + re.sub('x', '0', str(hex(crc16_csbk ^ 0xa5a5))[-4:])
|
return fragment_input + re.sub('x', '0', str(hex(crc16_csbk ^ 0xa5a5))[-4:])
|
||||||
|
|
||||||
def csbk_gen(to_id, from_id, tot_block):
|
def csbk_gen(to_id, from_id, tot_block):
|
||||||
csbk_lst = ['BD0080', 'BD0080', 'BD0080', 'BD0080', 'BD0080']
|
csbk_lst = ['BD0080', 'BD0080', 'BD0080', 'BD0080', 'BD0080']
|
||||||
|
|
||||||
|
|
@ -1055,8 +1060,22 @@ def csbk_gen(to_id, from_id, tot_block):
|
||||||
send_seq_list = send_seq_list + block
|
send_seq_list = send_seq_list + block
|
||||||
tot_block = tot_block - 1
|
tot_block = tot_block - 1
|
||||||
## print(block)
|
## print(block)
|
||||||
print(send_seq_list)
|
|
||||||
print('---===---')
|
return send_seq_list
|
||||||
|
|
||||||
|
def csbk_gen2(to_id, from_id, tot_block):
|
||||||
|
csbk_lst = ['BD0080', 'BD0080', 'BD0080', 'BD0080', 'BD0080', 'BD0080', 'BD0080', 'BD0080']
|
||||||
|
|
||||||
|
send_seq_list = ''
|
||||||
|
tot_block = tot_block + 8
|
||||||
|
for block in csbk_lst:
|
||||||
|
print(str(ahex(tot_block.to_bytes(1, 'big')))[2:-1])
|
||||||
|
block = block + str(ahex(tot_block.to_bytes(1, 'big')))[2:-1] + to_id + from_id#str(ahex(int(tot_block))[2:-1])
|
||||||
|
block = create_crc16_csbk(block)
|
||||||
|
send_seq_list = send_seq_list + block
|
||||||
|
tot_block = tot_block - 1
|
||||||
|
## print(block)
|
||||||
|
|
||||||
return send_seq_list
|
return send_seq_list
|
||||||
|
|
||||||
def mmdvm_encapsulate(dst_id, src_id, peer_id, _seq, _slot, _call_type, _dtype_vseq, _stream_id, _dmr_data):
|
def mmdvm_encapsulate(dst_id, src_id, peer_id, _seq, _slot, _call_type, _dtype_vseq, _stream_id, _dmr_data):
|
||||||
|
|
@ -1179,70 +1198,9 @@ def create_sms_seq(dst_id, src_id, peer_id, _slot, _call_type, dmr_string):
|
||||||
## packet_write_file.write(str(mmdvm_send_seq))
|
## packet_write_file.write(str(mmdvm_send_seq))
|
||||||
|
|
||||||
return mmdvm_send_seq
|
return mmdvm_send_seq
|
||||||
## return the_mmdvm_pkt
|
|
||||||
|
|
||||||
### Built for max length msg, will improve later
|
|
||||||
##def sms_headers(to_id, from_id):
|
|
||||||
#### #ETSI 102 361-2 uncompressed ipv4
|
|
||||||
#### # UDP header, src and dest ports are 4007, 0fa7
|
|
||||||
#### udp_ports = '0fa70fa7'
|
|
||||||
#### # Length, of what?
|
|
||||||
#### udp_length = '00da'
|
|
||||||
#### # Checksum
|
|
||||||
#### udp_checksum = '4b37'
|
|
||||||
####
|
|
||||||
#### # IPV4
|
|
||||||
#### #IPV4 version and header length, always 45
|
|
||||||
#### ipv4_v_l = '45'
|
|
||||||
#### #Type of service, always 00
|
|
||||||
#### ipv4_svc = '00'
|
|
||||||
#### #length, always 00ee
|
|
||||||
#### ipv4_len = '00ee'
|
|
||||||
#### #ID always 000d
|
|
||||||
#### ipv4_id = '000d'
|
|
||||||
#### #Flags and offset always0
|
|
||||||
#### ipv4_flag_off = '0000'
|
|
||||||
#### #TTL and Protocol always 4011, no matter what
|
|
||||||
#### ipv4_ttl_proto = '4011'
|
|
||||||
## #ipv4 = '450000ee000d0000401100000c' + from_id + '0c' + to_id
|
|
||||||
#### print(gen_sms_seq())
|
|
||||||
## ipv4 = '450000ee00' + gen_sms_seq() + '0000401100000c' + from_id + '0c' + to_id
|
|
||||||
## count_index = 0
|
|
||||||
## hdr_lst = []
|
|
||||||
## while count_index < len(ipv4):
|
|
||||||
## hdr_lst.append((ipv4[count_index:count_index + 4]))
|
|
||||||
## count_index = count_index + 4
|
|
||||||
## sum = 0
|
|
||||||
## for i in hdr_lst:
|
|
||||||
## sum = sum + int(i, 16)
|
|
||||||
## flipped = ''
|
|
||||||
## for i in str(bin(sum))[2:]:
|
|
||||||
## if i == '1':
|
|
||||||
## flipped = flipped + '0'
|
|
||||||
## if i == '0':
|
|
||||||
## flipped = flipped + '1'
|
|
||||||
## ipv4_chk_sum = str(hex(int(flipped, 2)))[2:]
|
|
||||||
## # UDP checksum is optional per ETSI, zero for now as Anytone is not affected.
|
|
||||||
## header = ipv4[:20] + ipv4_chk_sum + ipv4[24:] + '0fa70fa700da000000d0a00081040d000a'
|
|
||||||
## return header
|
|
||||||
|
|
||||||
##def format_sms(msg, to_id, from_id, use_header = True):
|
|
||||||
## msg_bytes = str.encode(msg)
|
|
||||||
## encoded = "".join([str('00' + x) for x in re.findall('..',bytes.hex(msg_bytes))] )
|
|
||||||
## final = encoded
|
|
||||||
## while len(final) < 400:
|
|
||||||
## final = final + '002e'
|
|
||||||
## final = final + '0000000000000000000000'
|
|
||||||
## if use_header == False:
|
|
||||||
## headers = ''
|
|
||||||
## if use_header == True:
|
|
||||||
## headers = sms_headers(to_id, from_id)
|
|
||||||
## return headers + final
|
|
||||||
|
|
||||||
def format_sms(msg, to_id, from_id, call_type, use_header = True):
|
def format_sms(msg, to_id, from_id, call_type, use_header = True):
|
||||||
msg_bytes = str.encode(msg)
|
|
||||||
encoded = "".join([str('00' + x) for x in re.findall('..',bytes.hex(msg_bytes))] )
|
|
||||||
final = encoded
|
|
||||||
|
|
||||||
call_seq_num = gen_sms_seq()
|
call_seq_num = gen_sms_seq()
|
||||||
|
|
||||||
|
|
@ -1253,32 +1211,30 @@ def format_sms(msg, to_id, from_id, call_type, use_header = True):
|
||||||
src_dmr_id = str(ipaddress.IPv4Address(int(hex_2_ip_src, 16)))
|
src_dmr_id = str(ipaddress.IPv4Address(int(hex_2_ip_src, 16)))
|
||||||
dst_dmr_id = str(ipaddress.IPv4Address(int(hex_2_ip_dest, 16)))
|
dst_dmr_id = str(ipaddress.IPv4Address(int(hex_2_ip_dest, 16)))
|
||||||
|
|
||||||
|
if to_id not in subscriber_format.keys():
|
||||||
|
subscriber_format[to_id] = 'motorola'
|
||||||
|
|
||||||
|
if subscriber_format[to_id] == 'etsi':
|
||||||
|
# Anytone "DMR Standard decodes utf-15 LE, not BE. BE is specified in ETSI 361-3
|
||||||
|
final = str(ahex(msg.encode('utf-16le')))[2:-1]
|
||||||
|
sms_header = '000d000a'
|
||||||
|
ip_udp = IP(dst=dst_dmr_id, src=src_dmr_id, ttl=1, id=int(call_seq_num, 16))/UDP(sport=5016, dport=5016)/(bytes.fromhex(sms_header + final) + bytes.fromhex('00'))# + bytes.fromhex('0000000000000000000000'))
|
||||||
|
logger.debug('Sending in ETSI? format.')
|
||||||
|
elif subscriber_format[to_id] == 'motorola':
|
||||||
|
final = str(ahex(msg.encode('utf-16be')))[2:-1]
|
||||||
# Unknown what byte is for, but it does correlate to the charaters : (number of characters + 4) * 2 . Convert to bytes.
|
# Unknown what byte is for, but it does correlate to the charaters : (number of characters + 4) * 2 . Convert to bytes.
|
||||||
unk_count = int((len(msg) + 4) * 2).to_bytes(1, 'big')
|
unk_count = int((len(msg) + 4) * 2).to_bytes(1, 'big')
|
||||||
|
## hdr_seq_num = (ahex(int((int(call_seq_num, 16) + 128)).to_bytes(1, 'big')))
|
||||||
hdr_seq_num = (ahex(int((int(call_seq_num, 16) + 128)).to_bytes(1, 'big')))
|
hdr_seq_num = (ahex(int((random.randint(1,7) + 128)).to_bytes(1, 'big')))
|
||||||
## print('-----------')
|
|
||||||
## print(int(call_seq_num, 16) + 128)
|
|
||||||
## print('-------------')
|
|
||||||
sms_header = '00' + str(ahex(unk_count))[2:-1] + 'a000' + str(hdr_seq_num)[2:-1] + '040d000a'
|
sms_header = '00' + str(ahex(unk_count))[2:-1] + 'a000' + str(hdr_seq_num)[2:-1] + '040d000a'
|
||||||
|
ip_udp = IP(dst=dst_dmr_id, src=src_dmr_id, ttl=1, id=int(call_seq_num, 16))/UDP(sport=5016, dport=5016)/(bytes.fromhex(sms_header + final) + bytes.fromhex('00'))# + bytes.fromhex('0000000000000000000000'))
|
||||||
|
logger.debug('Sending in Motorola format')
|
||||||
## ip_udp = packet = IP(dst=dst_dmr_id, src=src_dmr_id)/UDP(sport=4007, dport=4007)/(bytes.fromhex('0012A00083040D000A') + msg.encode('utf-16') + bytes.fromhex('0000000000000000000000'))
|
|
||||||
|
|
||||||
ip_udp = IP(dst=dst_dmr_id, src=src_dmr_id, id=int(call_seq_num, 16))/UDP(sport=4007, dport=4007)/(bytes.fromhex(sms_header + final) + bytes.fromhex('00'))# + bytes.fromhex('0000000000000000000000'))
|
|
||||||
|
|
||||||
header_bits = btf_poc(str(ahex(raw(ip_udp)))[2:-1])
|
header_bits = btf_poc(str(ahex(raw(ip_udp)))[2:-1])
|
||||||
|
|
||||||
|
|
||||||
sms_complete_header = create_crc16(gen_header2(to_id, from_id, call_type, header_bits[1], header_bits[0]))
|
sms_complete_header = create_crc16(gen_header2(to_id, from_id, call_type, header_bits[1], header_bits[0]))
|
||||||
sms_csbk = (csbk_gen(to_id, from_id, header_bits[0]))
|
sms_csbk = (csbk_gen(to_id, from_id, header_bits[0]))
|
||||||
logger.debug(sms_complete_header)
|
logger.debug(sms_complete_header)
|
||||||
|
|
||||||
## print(type(sms_csbk))
|
|
||||||
## print('---')
|
|
||||||
## print((sms_csbk))# + sms_complete_header))
|
|
||||||
## print('---')
|
|
||||||
|
|
||||||
# Return corrected fragment with BTF and generate CRC16 with header
|
# Return corrected fragment with BTF and generate CRC16 with header
|
||||||
|
|
||||||
|
|
@ -1469,6 +1425,7 @@ def ars_resp(msg, to_id, from_id, call_type, use_header = True):
|
||||||
|
|
||||||
|
|
||||||
sms_complete_header = create_crc16(gen_header2(to_id, from_id, call_type, header_bits[1], header_bits[0]))
|
sms_complete_header = create_crc16(gen_header2(to_id, from_id, call_type, header_bits[1], header_bits[0]))
|
||||||
|
sms_csbk = (csbk_gen2(to_id, from_id, header_bits[0]))
|
||||||
logger.debug(sms_complete_header)
|
logger.debug(sms_complete_header)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1584,16 +1541,16 @@ def aprs_beacon_send():
|
||||||
##### DMR data function ####
|
##### DMR data function ####
|
||||||
def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data, mirror = False):
|
def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data, mirror = False):
|
||||||
# Capture data headers
|
# Capture data headers
|
||||||
global n_packet_assembly, hdr_type
|
## global hdr_type
|
||||||
#logger.info(_dtype_vseq)
|
#logger.info(_dtype_vseq)
|
||||||
#logger.info(_call_type)
|
#logger.info(_call_type)
|
||||||
#logger.info(_frame_type)
|
#logger.info(_frame_type)
|
||||||
## print(int_id(_stream_id))
|
## print(int_id(_stream_id))
|
||||||
## print((_seq))
|
## print((_seq))
|
||||||
logger.info(strftime('%H:%M:%S - %m/%d/%y'))
|
logger.info(strftime('%H:%M:%S - %m/%d/%y'))
|
||||||
#logger.info('Special debug for developement:')
|
logger.debug('Decoded data:')
|
||||||
logger.info(ahex(bptc_decode(_data)))
|
logger.debug(ahex(bptc_decode(_data)))
|
||||||
#logger.info(_rf_src)
|
## logger.info(_seq)
|
||||||
#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:
|
||||||
|
|
@ -1610,10 +1567,10 @@ def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _fr
|
||||||
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'
|
sub_hdr[_rf_src] = '380'
|
||||||
if _dtype_vseq == 6 and hdr_type == '380' or _dtype_vseq == 'group' and hdr_type == '380':
|
if _dtype_vseq == 6 and sub_hdr[_rf_src] == '380' or _dtype_vseq == 'group' and sub_hdr[_rf_src] == '380':
|
||||||
udt_block = 1
|
udt_block = 1
|
||||||
if _dtype_vseq == 7 and hdr_type == '380':
|
if _dtype_vseq == 7 and sub_hdr[_rf_src] == '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.')
|
||||||
|
|
@ -1632,9 +1589,6 @@ def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _fr
|
||||||
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.
|
|
||||||
#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
|
|
||||||
# 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
|
||||||
|
|
@ -1686,59 +1640,49 @@ def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _fr
|
||||||
logger.error(error_exception)
|
logger.error(error_exception)
|
||||||
logger.error(str(traceback.extract_tb(error_exception.__traceback__)))
|
logger.error(str(traceback.extract_tb(error_exception.__traceback__)))
|
||||||
udt_block = 1
|
udt_block = 1
|
||||||
hdr_type = ''
|
sub_hdr[_rf_src] = ''
|
||||||
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 ):
|
|
||||||
# 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 btf
|
||||||
if _dtype_vseq == 6 or _dtype_vseq == 'group':
|
if _dtype_vseq == 6 or _dtype_vseq == 'group':
|
||||||
global btf, hdr_start
|
## global hdr_start
|
||||||
# Header is a "Defined Short Data", used by Hytera I suspect
|
# Header is a "Defined Short Data", used by Hytera I suspect
|
||||||
if ahex(bptc_decode(_data)[4:-88]) == b'd0':
|
if ahex(bptc_decode(_data)[4:-88]) == b'd0':
|
||||||
logger.debug('Defined Short Data header detected.')
|
logger.debug('Defined Short Data header detected.')
|
||||||
# Construct blocks to follow
|
# Construct blocks to follow
|
||||||
btf = (ba2num(bptc_decode(_data)[2:-92] + bptc_decode(_data)[12:-80]))
|
btf[_rf_src] = (ba2num(bptc_decode(_data)[2:-92] + bptc_decode(_data)[12:-80]))
|
||||||
hdr_type = 'dsd'
|
sub_hdr[_rf_src] = 'dsd'
|
||||||
# Everyone else
|
# Everyone else
|
||||||
else:
|
else:
|
||||||
logger.debug('Unconfirmed Data header detected.')
|
logger.debug('Unconfirmed Data header detected.')
|
||||||
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.debug(ahex(bptc_decode(_data)))
|
logger.debug(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[_rf_src] = ba2num(bptc_decode(_data)[65:72])
|
||||||
hdr_type = ''
|
sub_hdr[_rf_src] = ''
|
||||||
print(ba2num(bptc_decode(_data)[12:16]))
|
|
||||||
# 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
|
# 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 _dtype_vseq == 7:
|
||||||
btf = btf - 1
|
btf[_rf_src] = btf[_rf_src] - 1
|
||||||
logger.info('Block #: ' + str(btf))
|
logger.info('Block #: ' + str(btf[_rf_src]))
|
||||||
#logger.info(_seq)
|
#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('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 _rf_src not in packet_assembly.keys():
|
||||||
if _seq == 0:
|
packet_assembly[_rf_src] = ''
|
||||||
n_packet_assembly = 0
|
packet_assembly[_rf_src] = packet_assembly[_rf_src] + str(ahex(bptc_decode(_data)))[2:-1] #str((decode_full_lc(b_packet)).strip('bitarray(')))
|
||||||
packet_assembly = ''
|
|
||||||
|
|
||||||
#if btf < btf + 1:
|
|
||||||
# 14FRS2013 removed condition, works great!
|
|
||||||
n_packet_assembly = n_packet_assembly + 1
|
|
||||||
packet_assembly = packet_assembly + str(bptc_decode(_data)) #str((decode_full_lc(b_packet)).strip('bitarray('))
|
|
||||||
# Use block 0 as trigger. $GPRMC must also be in string to indicate NMEA.
|
# Use block 0 as trigger. $GPRMC must also be in string to indicate NMEA.
|
||||||
# This triggers the APRS upload
|
# This triggers the APRS upload or SMS decode
|
||||||
if btf == 0:
|
if btf[_rf_src] == 0:
|
||||||
print(ahex(_rf_src))
|
sms_hex_string = packet_assembly[_rf_src]
|
||||||
final_packet = str(bitarray(re.sub("\)|\(|bitarray|'", '', packet_assembly)).tobytes().decode('utf-8', 'ignore'))
|
# Determin SMS format
|
||||||
sms_hex = str(ba2hx(bitarray(re.sub("\)|\(|bitarray|'", '', packet_assembly))))
|
sms_type(str(ahex(_rf_src))[2:-1], sms_hex_string)
|
||||||
sms_hex_string = re.sub("b'|'", '', str(sms_hex))
|
sms = codecs.decode(bytes.fromhex(''.join(sms_hex_string[:-8].split('00'))), 'utf-8', 'ignore')
|
||||||
if hdr_type == 'dsd':
|
if sub_hdr[_rf_src] == 'dsd':
|
||||||
logger.debug('Trimmed for Defined Short Data')
|
logger.debug('Trimmed for Defined Short Data')
|
||||||
print(hdr_type)
|
|
||||||
sms_hex_string = sms_hex_string[2:]
|
sms_hex_string = sms_hex_string[2:]
|
||||||
# Filter out ARS
|
# Filter out ARS
|
||||||
# Look for port 4005 twice, and 'hello' - 000cf0, and UDP header in first 16 characters
|
# Look for port 4005 twice, and 'hello' - 000cf0, and UDP header in first 16 characters
|
||||||
|
|
@ -1750,37 +1694,27 @@ def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _fr
|
||||||
if '000cf0' in sms_hex_string:
|
if '000cf0' in sms_hex_string:
|
||||||
logger.info('Received ARS "hello"')
|
logger.info('Received ARS "hello"')
|
||||||
logger.debug('Attempt response')
|
logger.debug('Attempt response')
|
||||||
|
|
||||||
## ars_response = (ars_resp('0002BF01', str(ahex(_rf_src))[2:-1], str(ahex(_dst_id))[2:-1], 1))
|
## ars_response = (ars_resp('0002BF01', str(ahex(_rf_src))[2:-1], str(ahex(_dst_id))[2:-1], 1))
|
||||||
|
|
||||||
ars_response = (ars_resp('0002B700', str(ahex(_rf_src))[2:-1], str(ahex(_dst_id))[2:-1], 1))
|
ars_response = (ars_resp('0002B700', str(ahex(_rf_src))[2:-1], str(ahex(_dst_id))[2:-1], 1))
|
||||||
|
|
||||||
ars_snd = create_sms_seq(int_id(_rf_src), int_id(_dst_id), int_id(_dst_id), _slot, 1, ars_response[1] + ars_response[0])
|
ars_snd = create_sms_seq(int_id(_rf_src), int_id(_dst_id), int_id(_dst_id), _slot, 1, ars_response[1] + ars_response[0])
|
||||||
print(ars_snd)
|
|
||||||
|
|
||||||
for i in ars_snd:
|
for i in ars_snd:
|
||||||
print(ahex(bptc_decode(i)))
|
|
||||||
## systems[UNIT_MAP[_rf_src][0]].send_system(i)
|
|
||||||
systems[UNIT_MAP[_rf_src][0]].send_system(i)
|
systems[UNIT_MAP[_rf_src][0]].send_system(i)
|
||||||
|
## systems['LOCAL'].send_system(i)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
#NMEA GPS sentence
|
#NMEA GPS sentence
|
||||||
if '$GPRMC' in final_packet or '$GNRMC' in final_packet:
|
if '$GPRMC' in sms or '$GNRMC' in sms:
|
||||||
logger.debug(final_packet + '\n')
|
logger.debug(sms + '\n')
|
||||||
# Eliminate excess bytes based on NMEA type
|
# Eliminate excess bytes based on NMEA type
|
||||||
# GPRMC
|
# GPRMC
|
||||||
if 'GPRMC' in final_packet:
|
if 'GPRMC' in sms:
|
||||||
logger.debug('GPRMC location')
|
logger.debug('GPRMC location')
|
||||||
#nmea_parse = re.sub('A\*.*|.*\$', '', str(final_packet))
|
#nmea_parse = re.sub('A\*.*|.*\$', '', str(final_packet))
|
||||||
nmea_parse = re.sub('A\*.*|.*\$|\n.*', '', str(final_packet))
|
nmea_parse = re.sub('A\*.*|.*\$|\n.*', '', str(sms))
|
||||||
# GNRMC
|
# GNRMC
|
||||||
if 'GNRMC' in final_packet:
|
if 'GNRMC' in sms:
|
||||||
logger.debug('GNRMC location')
|
logger.debug('GNRMC location')
|
||||||
nmea_parse = re.sub('.*\$|\n.*|V\*.*', '', final_packet)
|
nmea_parse = re.sub('.*\$|\n.*|V\*.*', '', sms)
|
||||||
loc = pynmea2.parse(nmea_parse, check=False)
|
loc = pynmea2.parse(nmea_parse, check=False)
|
||||||
logger.debug('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.debug('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 mirror == False:
|
if mirror == False:
|
||||||
|
|
@ -1838,35 +1772,28 @@ def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _fr
|
||||||
# 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 sms or '$GNRMC' not in sms:
|
||||||
logger.info('\nSMS detected. Attempting to parse.')
|
logger.info('\nSMS detected. Attempting to parse.')
|
||||||
#logger.info(final_packet)
|
#logger.info(final_packet)
|
||||||
## 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:
|
|
||||||
if int_id(_dst_id) in data_id:
|
if int_id(_dst_id) in data_id:
|
||||||
|
print('process sms')
|
||||||
process_sms(_rf_src, msg_found, _call_type, UNIT_MAP[_rf_src][0])
|
process_sms(_rf_src, msg_found, _call_type, UNIT_MAP[_rf_src][0])
|
||||||
## if int_id(_dst_id) != data_id:
|
|
||||||
if int_id(_dst_id) not in data_id:
|
if int_id(_dst_id) not in data_id:
|
||||||
dashboard_sms_write(str(get_alias(int_id(_rf_src), subscriber_ids)), str(get_alias(int_id(_dst_id), subscriber_ids)), int_id(_dst_id), int_id(_rf_src), msg_found, time(), UNIT_MAP[_rf_src][0])
|
dashboard_sms_write(str(get_alias(int_id(_rf_src), subscriber_ids)), str(get_alias(int_id(_dst_id), subscriber_ids)), int_id(_dst_id), int_id(_rf_src), msg_found, time(), UNIT_MAP[_rf_src][0])
|
||||||
#packet_assembly = ''
|
|
||||||
pass
|
pass
|
||||||
#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')
|
# Reset assembly
|
||||||
# Reset the packet assembly to prevent old data from returning.
|
del packet_assembly[_rf_src]
|
||||||
# 14FRS2013 moved variable reset
|
del btf[_rf_src]
|
||||||
hdr_start = ''
|
# Reset header type for next sequence
|
||||||
n_packet_assembly = 0
|
del sub_hdr[_rf_src]
|
||||||
packet_assembly = ''
|
|
||||||
btf = 0
|
|
||||||
#logger.info(_seq)
|
|
||||||
#packet_assembly = '' #logger.info(_dtype_vseq)
|
|
||||||
#logger.info(ahex(bptc_decode(_data)).decode('utf-8', 'ignore'))
|
|
||||||
#logger.info(bitarray(re.sub("\)|\(|bitarray|'", '', str(bptc_decode(_data)).tobytes().decode('utf-8', 'ignore'))))
|
|
||||||
|
|
||||||
|
|
||||||
######
|
######
|
||||||
|
|
@ -1940,6 +1867,9 @@ class OBP(OPENBRIDGE):
|
||||||
UNIT_MAP[_rf_src] = (self._system, time())
|
UNIT_MAP[_rf_src] = (self._system, time())
|
||||||
if _rf_src not in PACKET_MATCH:
|
if _rf_src not in PACKET_MATCH:
|
||||||
PACKET_MATCH[_rf_src] = [_seq, time()]
|
PACKET_MATCH[_rf_src] = [_seq, time()]
|
||||||
|
if _rf_src not in sub_hdr.keys():
|
||||||
|
sub_hdr[_rf_src] = ''
|
||||||
|
logger.debug('Added blank hdr')
|
||||||
|
|
||||||
# Check to see if we have already received this packet
|
# Check to see if we have already received this packet
|
||||||
elif _seq == PACKET_MATCH[_rf_src][0] and time() - 1 < PACKET_MATCH[_rf_src][1]:
|
elif _seq == PACKET_MATCH[_rf_src][0] and time() - 1 < PACKET_MATCH[_rf_src][1]:
|
||||||
|
|
@ -1984,15 +1914,14 @@ class OBP(OPENBRIDGE):
|
||||||
## print(ahex(bptc_decode(_data)))
|
## print(ahex(bptc_decode(_data)))
|
||||||
|
|
||||||
if _mode == b'MDAT' or _mode == b'DATA':
|
if _mode == b'MDAT' or _mode == b'DATA':
|
||||||
print('MDAT')
|
logger.debug('MDAT')
|
||||||
if _rf_src not in PACKET_MATCH:
|
if _rf_src not in PACKET_MATCH:
|
||||||
PACKET_MATCH[_rf_src] = [_seq, time()]
|
PACKET_MATCH[_rf_src] = [_seq, time()]
|
||||||
if _seq == PACKET_MATCH[_rf_src][0] and time() - 1 < PACKET_MATCH[_rf_src][1]:
|
if _seq == PACKET_MATCH[_rf_src][0] and time() - 1 < PACKET_MATCH[_rf_src][1]:
|
||||||
print('matched, dropping')
|
logger.debug('Matched, dropping')
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print('no match')
|
|
||||||
if _mode == b'MDAT':
|
if _mode == b'MDAT':
|
||||||
data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data, True)
|
data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data, True)
|
||||||
if _mode == b'DATA':
|
if _mode == b'DATA':
|
||||||
|
|
@ -2007,6 +1936,10 @@ class HBP(HBSYSTEM):
|
||||||
|
|
||||||
def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
|
def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
|
||||||
UNIT_MAP[_rf_src] = (self._system, time())
|
UNIT_MAP[_rf_src] = (self._system, time())
|
||||||
|
# Set data header type
|
||||||
|
if _rf_src not in sub_hdr.keys():
|
||||||
|
sub_hdr[_rf_src] = ''
|
||||||
|
logger.debug('Added blank hdr')
|
||||||
## logger.debug(ahex(_data))
|
## logger.debug(ahex(_data))
|
||||||
logger.debug('MMDVM RCVD')
|
logger.debug('MMDVM RCVD')
|
||||||
if _rf_src not in PACKET_MATCH:
|
if _rf_src not in PACKET_MATCH:
|
||||||
|
|
|
||||||
|
|
@ -7081,7 +7081,7 @@ Name: <strong>''' + p.name + '''</strong> - Port: <strong>''' + str(
|
||||||
</tr>
|
</tr>
|
||||||
'''
|
'''
|
||||||
web_output = '''
|
web_output = '''
|
||||||
<h4 style="text-align: center;">External Services for discovered: ''' + i.name + '''</h4>
|
<h4 style="text-align: center;">External Services discovered: ''' + i.name + '''</h4>
|
||||||
<table data-toggle="table" data-pagination="true" data-search="true">
|
<table data-toggle="table" data-pagination="true" data-search="true">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
|
@ -77,10 +77,10 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>![SHORTCUT] [MESSAGE]</strong></td>
|
<td><strong>![SHORTCUT] [MESSAGE]</strong></td>
|
||||||
<td>Send a message to an external application.</td>
|
<td>Send a message to an external application.</td>
|
||||||
<td><em><code>!TST test</code></em></td>
|
<td><em><code>#WX spokane, wa</code></em></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><strong>#[SHORTCUT] [DMR ID] [MESSAGE]</strong></td>
|
<td><strong>.[SHORTCUT] [DMR ID] [MESSAGE]</strong></td>
|
||||||
<td>Send an SMS to another user on a different network.</td>
|
<td>Send an SMS to another user on a different network.</td>
|
||||||
<td><em><code>#DMRNET 1234567 Are you there?</code></em></td>
|
<td><em><code>#DMRNET 1234567 Are you there?</code></em></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue