Mostly kinda works now
This commit is contained in:
parent
2860ec6847
commit
77d19f65ed
2
.gitignore
vendored
2
.gitignore
vendored
@ -93,3 +93,5 @@ hblink.cfg
|
|||||||
*.config
|
*.config
|
||||||
*.bak
|
*.bak
|
||||||
rules.py
|
rules.py
|
||||||
|
subscriber_ids.csv
|
||||||
|
peer_ids.csv
|
||||||
|
@ -46,7 +46,7 @@ from twisted.internet import reactor, task
|
|||||||
|
|
||||||
# Things we import from the main hblink module
|
# Things we import from the main hblink module
|
||||||
from hblink import HBSYSTEM, OPENBRIDGE, systems, hblink_handler, reportFactory, REPORT_OPCODES, config_reports, mk_aliases
|
from hblink import HBSYSTEM, OPENBRIDGE, systems, hblink_handler, reportFactory, REPORT_OPCODES, config_reports, mk_aliases
|
||||||
from dmr_utils.utils import hex_str_3, int_id, get_alias
|
from dmr_utils.utils import bytes_3, int_id, get_alias
|
||||||
from dmr_utils import decode, bptc, const
|
from dmr_utils import decode, bptc, const
|
||||||
import hb_config
|
import hb_config
|
||||||
import hb_log
|
import hb_log
|
||||||
|
54
bridge.py
54
bridge.py
@ -43,7 +43,7 @@ from twisted.internet import reactor, task
|
|||||||
|
|
||||||
# Things we import from the main hblink module
|
# Things we import from the main hblink module
|
||||||
from hblink import HBSYSTEM, OPENBRIDGE, systems, hblink_handler, reportFactory, REPORT_OPCODES, mk_aliases
|
from hblink import HBSYSTEM, OPENBRIDGE, systems, hblink_handler, reportFactory, REPORT_OPCODES, mk_aliases
|
||||||
from dmr_utils3.utils import hex_str_3, int_id, get_alias
|
from dmr_utils3.utils import bytes_3, int_id, get_alias
|
||||||
from dmr_utils3 import decode, bptc, const
|
from dmr_utils3 import decode, bptc, const
|
||||||
import config
|
import config
|
||||||
import log
|
import log
|
||||||
@ -107,11 +107,11 @@ def make_bridges(_hb_confbridge_bridges):
|
|||||||
if _system['SYSTEM'] not in CONFIG['SYSTEMS']:
|
if _system['SYSTEM'] not in CONFIG['SYSTEMS']:
|
||||||
sys.exit('ERROR: Conference bridges found for system not configured main configuration')
|
sys.exit('ERROR: Conference bridges found for system not configured main configuration')
|
||||||
|
|
||||||
_system['TGID'] = hex_str_3(_system['TGID'])
|
_system['TGID'] = bytes_3(_system['TGID'])
|
||||||
for i, e in enumerate(_system['ON']):
|
for i, e in enumerate(_system['ON']):
|
||||||
_system['ON'][i] = hex_str_3(_system['ON'][i])
|
_system['ON'][i] = bytes_3(_system['ON'][i])
|
||||||
for i, e in enumerate(_system['OFF']):
|
for i, e in enumerate(_system['OFF']):
|
||||||
_system['OFF'][i] = hex_str_3(_system['OFF'][i])
|
_system['OFF'][i] = bytes_3(_system['OFF'][i])
|
||||||
_system['TIMEOUT'] = _system['TIMEOUT']*60
|
_system['TIMEOUT'] = _system['TIMEOUT']*60
|
||||||
if _system['ACTIVE'] == True:
|
if _system['ACTIVE'] == True:
|
||||||
_system['TIMER'] = time() + _system['TIMEOUT']
|
_system['TIMER'] = time() + _system['TIMEOUT']
|
||||||
@ -151,7 +151,7 @@ def rule_timer_loop():
|
|||||||
logger.debug('Conference Bridge NO ACTION: System: %s, Bridge: %s, TS: %s, TGID: %s', _system['SYSTEM'], _bridge, _system['TS'], int_id(_system['TGID']))
|
logger.debug('Conference Bridge NO ACTION: System: %s, Bridge: %s, TS: %s, TGID: %s', _system['SYSTEM'], _bridge, _system['TS'], int_id(_system['TGID']))
|
||||||
|
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
report_server.send_clients('bridge updated')
|
report_server.send_clients(b'bridge updated')
|
||||||
|
|
||||||
|
|
||||||
# run this every 10 seconds to trim orphaned stream ids
|
# run this every 10 seconds to trim orphaned stream ids
|
||||||
@ -169,7 +169,7 @@ def stream_trimmer_loop():
|
|||||||
logger.info('(%s) *TIME OUT* RX STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \
|
logger.info('(%s) *TIME OUT* RX STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \
|
||||||
system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_RFS']), int_id(_slot['RX_TGID']), slot, _slot['RX_TIME'] - _slot['RX_START'])
|
system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_RFS']), int_id(_slot['RX_TGID']), slot, _slot['RX_TIME'] - _slot['RX_START'])
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[system]._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_PEER']), int_id(_slot['RX_RFS']), slot, int_id(_slot['RX_TGID']), _slot['RX_TIME'] - _slot['RX_START']))
|
systems[system]._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_PEER']), int_id(_slot['RX_RFS']), slot, int_id(_slot['RX_TGID']), _slot['RX_TIME'] - _slot['RX_START']).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
for slot in range(1,3):
|
for slot in range(1,3):
|
||||||
_slot = systems[system].STATUS[slot]
|
_slot = systems[system].STATUS[slot]
|
||||||
@ -178,7 +178,7 @@ def stream_trimmer_loop():
|
|||||||
logger.info('(%s) *TIME OUT* TX STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \
|
logger.info('(%s) *TIME OUT* TX STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \
|
||||||
system, int_id(_slot['TX_STREAM_ID']), int_id(_slot['TX_RFS']), int_id(_slot['TX_TGID']), slot, _slot['TX_TIME'] - _slot['TX_START'])
|
system, int_id(_slot['TX_STREAM_ID']), int_id(_slot['TX_RFS']), int_id(_slot['TX_TGID']), slot, _slot['TX_TIME'] - _slot['TX_START'])
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[system]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['TX_STREAM_ID']), int_id(_slot['TX_PEER']), int_id(_slot['TX_RFS']), slot, int_id(_slot['TX_TGID']), _slot['TX_TIME'] - _slot['TX_START']))
|
systems[system]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['TX_STREAM_ID']), int_id(_slot['TX_PEER']), int_id(_slot['TX_RFS']), slot, int_id(_slot['TX_TGID']), _slot['TX_TIME'] - _slot['TX_START']).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
# OBP systems
|
# OBP systems
|
||||||
# We can't delete items from a dicationry that's being iterated, so we have to make a temporarly list of entrys to remove later
|
# We can't delete items from a dicationry that's being iterated, so we have to make a temporarly list of entrys to remove later
|
||||||
@ -194,7 +194,7 @@ def stream_trimmer_loop():
|
|||||||
logger.info('(%s) *TIME OUT* STREAM ID: %s SUB: %s PEER: %s TGID: %s TS 1 Duration: %s', \
|
logger.info('(%s) *TIME OUT* STREAM ID: %s SUB: %s PEER: %s TGID: %s TS 1 Duration: %s', \
|
||||||
system, int_id(stream_id), get_alias(int_id(_system['RFS']), subscriber_ids), get_alias(int_id(_config['NETWORK_ID']), peer_ids), get_alias(int_id(_system['TGID']), talkgroup_ids), _system['LAST'] - _system['START'])
|
system, int_id(stream_id), get_alias(int_id(_system['RFS']), subscriber_ids), get_alias(int_id(_config['NETWORK_ID']), peer_ids), get_alias(int_id(_system['TGID']), talkgroup_ids), _system['LAST'] - _system['START'])
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[system]._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(stream_id), int_id(_config['NETWORK_ID']), int_id(_system['RFS']), 1, int_id(_system['TGID']), _system['LAST'] - _system['START']))
|
systems[system]._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(stream_id), int_id(_config['NETWORK_ID']), int_id(_system['RFS']), 1, int_id(_system['TGID']), _system['LAST'] - _system['START']).encode(encoding='utf-8', errors='ignore'))
|
||||||
removed = systems[system].STATUS.pop(stream_id)
|
removed = systems[system].STATUS.pop(stream_id)
|
||||||
else:
|
else:
|
||||||
logger.error('(%s) Attemped to remove OpenBridge Stream ID %s not in the Stream ID list: %s', system, int_id(stream_id), [id for id in systems[system].STATUS])
|
logger.error('(%s) Attemped to remove OpenBridge Stream ID %s not in the Stream ID list: %s', system, int_id(stream_id), [id for id in systems[system].STATUS])
|
||||||
@ -236,7 +236,7 @@ class routerOBP(OPENBRIDGE):
|
|||||||
logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \
|
logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \
|
||||||
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
|
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
self._report.send_bridgeEvent('GROUP VOICE,START,RX,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)))
|
self._report.send_bridgeEvent('GROUP VOICE,START,RX,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
self.STATUS[_stream_id]['LAST'] = pkt_time
|
self.STATUS[_stream_id]['LAST'] = pkt_time
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ class routerOBP(OPENBRIDGE):
|
|||||||
_tmp_bits = _bits & ~(1 << 7)
|
_tmp_bits = _bits & ~(1 << 7)
|
||||||
|
|
||||||
# Assemble transmit HBP packet header
|
# Assemble transmit HBP packet header
|
||||||
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + chr(_tmp_bits) + _data[16:20]
|
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + _tmp_bits.to_bytes(1, 'big') + _data[16:20]
|
||||||
|
|
||||||
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
||||||
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
||||||
@ -350,7 +350,7 @@ class routerOBP(OPENBRIDGE):
|
|||||||
logger.debug('(%s) Generating TX FULL and EMB LCs for HomeBrew destination: System: %s, TS: %s, TGID: %s', self._system, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
logger.debug('(%s) Generating TX FULL and EMB LCs for HomeBrew destination: System: %s, TS: %s, TGID: %s', self._system, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
||||||
logger.info('(%s) Conference Bridge: %s, Call Bridged to HBP System: %s TS: %s, TGID: %s', self._system, _bridge, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
logger.info('(%s) Conference Bridge: %s, Call Bridged to HBP System: %s TS: %s, TGID: %s', self._system, _bridge, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,START,TX,{},{},{},{},{},{}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID'])))
|
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,START,TX,{},{},{},{},{},{}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID'])).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
# Set other values for the contention handler to test next time there is a frame to forward
|
# Set other values for the contention handler to test next time there is a frame to forward
|
||||||
_target_status[_target['TS']]['TX_TIME'] = pkt_time
|
_target_status[_target['TS']]['TX_TIME'] = pkt_time
|
||||||
@ -363,7 +363,7 @@ class routerOBP(OPENBRIDGE):
|
|||||||
_tmp_bits = _bits
|
_tmp_bits = _bits
|
||||||
|
|
||||||
# Assemble transmit HBP packet header
|
# Assemble transmit HBP packet header
|
||||||
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + chr(_tmp_bits) + _data[16:20]
|
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + _tmp_bits.to_bytes(1, 'big') + _data[16:20]
|
||||||
|
|
||||||
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
||||||
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
||||||
@ -377,12 +377,12 @@ class routerOBP(OPENBRIDGE):
|
|||||||
elif _frame_type == HBPF_DATA_SYNC and _dtype_vseq == HBPF_SLT_VTERM:
|
elif _frame_type == HBPF_DATA_SYNC and _dtype_vseq == HBPF_SLT_VTERM:
|
||||||
dmrbits = _target_status[_target['TS']]['TX_T_LC'][0:98] + dmrbits[98:166] + _target_status[_target['TS']]['TX_T_LC'][98:197]
|
dmrbits = _target_status[_target['TS']]['TX_T_LC'][0:98] + dmrbits[98:166] + _target_status[_target['TS']]['TX_T_LC'][98:197]
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']), 1))
|
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']), 1).encode(encoding='utf-8', errors='ignore'))
|
||||||
# Create a Burst B-E packet (Embedded LC)
|
# Create a Burst B-E packet (Embedded LC)
|
||||||
elif _dtype_vseq in [1,2,3,4]:
|
elif _dtype_vseq in [1,2,3,4]:
|
||||||
dmrbits = dmrbits[0:116] + _target_status[_target['TS']]['TX_EMB_LC'][_dtype_vseq] + dmrbits[148:264]
|
dmrbits = dmrbits[0:116] + _target_status[_target['TS']]['TX_EMB_LC'][_dtype_vseq] + dmrbits[148:264]
|
||||||
dmrpkt = dmrbits.tobytes()
|
dmrpkt = dmrbits.tobytes()
|
||||||
_tmp_data = _tmp_data + dmrpkt + '\x00\x00' # Add two bytes of nothing since OBP doesn't include BER & RSSI bytes #_data[53:55]
|
_tmp_data = _tmp_data + dmrpkt + b'\x00\x00' # Add two bytes of nothing since OBP doesn't include BER & RSSI bytes #_data[53:55]
|
||||||
|
|
||||||
# Transmit the packet to the destination system
|
# Transmit the packet to the destination system
|
||||||
systems[_target['SYSTEM']].send_system(_tmp_data)
|
systems[_target['SYSTEM']].send_system(_tmp_data)
|
||||||
@ -396,7 +396,7 @@ class routerOBP(OPENBRIDGE):
|
|||||||
logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \
|
logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \
|
||||||
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration)
|
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration)
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
self._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration))
|
self._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration).encode(encoding='utf-8', errors='ignore'))
|
||||||
removed = self.STATUS.pop(_stream_id)
|
removed = self.STATUS.pop(_stream_id)
|
||||||
logger.debug('(%s) OpenBridge sourced call stream end, remove terminated Stream ID: %s', self._system, int_id(_stream_id))
|
logger.debug('(%s) OpenBridge sourced call stream end, remove terminated Stream ID: %s', self._system, int_id(_stream_id))
|
||||||
if not removed:
|
if not removed:
|
||||||
@ -483,7 +483,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \
|
logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \
|
||||||
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
|
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot)
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
self._report.send_bridgeEvent('GROUP VOICE,START,RX,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)))
|
self._report.send_bridgeEvent('GROUP VOICE,START,RX,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
# If we can, use the LC from the voice header as to keep all options intact
|
# If we can, use the LC from the voice header as to keep all options intact
|
||||||
if _frame_type == HBPF_DATA_SYNC and _dtype_vseq == HBPF_SLT_VHEAD:
|
if _frame_type == HBPF_DATA_SYNC and _dtype_vseq == HBPF_SLT_VHEAD:
|
||||||
@ -539,7 +539,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
_tmp_bits = _bits & ~(1 << 7)
|
_tmp_bits = _bits & ~(1 << 7)
|
||||||
|
|
||||||
# Assemble transmit HBP packet header
|
# Assemble transmit HBP packet header
|
||||||
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + chr(_tmp_bits) + _data[16:20]
|
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + _tmp_bits.to_bytes(1, 'big') + _data[16:20]
|
||||||
|
|
||||||
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
||||||
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
||||||
@ -585,8 +585,8 @@ class routerHBP(HBSYSTEM):
|
|||||||
logger.info('(%s) Call not routed for subscriber %s, call route in progress on target: HBSystem: %s, TS: %s, TGID: %s, SUB: %s', self._system, int_id(_rf_src), _target['SYSTEM'], _target['TS'], int_id(_target_status[_target['TS']]['TX_TGID']), int_id(_target_status[_target['TS']]['TX_RFS']))
|
logger.info('(%s) Call not routed for subscriber %s, call route in progress on target: HBSystem: %s, TS: %s, TGID: %s, SUB: %s', self._system, int_id(_rf_src), _target['SYSTEM'], _target['TS'], int_id(_target_status[_target['TS']]['TX_TGID']), int_id(_target_status[_target['TS']]['TX_RFS']))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Is this a new call stream?
|
# Is this a new call stream?
|
||||||
if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']) or (_target_status[_target['TS']]['TX_RFS'] != _rf_src) or (_target_status[_target['TS']]['TX_TGID'] != _target['TGID']):
|
if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']):
|
||||||
# Record the DST TGID and Stream ID
|
# Record the DST TGID and Stream ID
|
||||||
_target_status[_target['TS']]['TX_START'] = pkt_time
|
_target_status[_target['TS']]['TX_START'] = pkt_time
|
||||||
_target_status[_target['TS']]['TX_TGID'] = _target['TGID']
|
_target_status[_target['TS']]['TX_TGID'] = _target['TGID']
|
||||||
@ -601,7 +601,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
logger.debug('(%s) Generating TX FULL and EMB LCs for HomeBrew destination: System: %s, TS: %s, TGID: %s', self._system, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
logger.debug('(%s) Generating TX FULL and EMB LCs for HomeBrew destination: System: %s, TS: %s, TGID: %s', self._system, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
||||||
logger.info('(%s) Conference Bridge: %s, Call Bridged to HBP System: %s TS: %s, TGID: %s', self._system, _bridge, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
logger.info('(%s) Conference Bridge: %s, Call Bridged to HBP System: %s TS: %s, TGID: %s', self._system, _bridge, _target['SYSTEM'], _target['TS'], int_id(_target['TGID']))
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,START,TX,{},{},{},{},{},{}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID'])))
|
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,START,TX,{},{},{},{},{},{}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID'])).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
# Set other values for the contention handler to test next time there is a frame to forward
|
# Set other values for the contention handler to test next time there is a frame to forward
|
||||||
_target_status[_target['TS']]['TX_TIME'] = pkt_time
|
_target_status[_target['TS']]['TX_TIME'] = pkt_time
|
||||||
@ -614,7 +614,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
_tmp_bits = _bits
|
_tmp_bits = _bits
|
||||||
|
|
||||||
# Assemble transmit HBP packet header
|
# Assemble transmit HBP packet header
|
||||||
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + chr(_tmp_bits) + _data[16:20]
|
_tmp_data = _data[:8] + _target['TGID'] + _data[11:15] + _tmp_bits.to_bytes(1, 'big') + _data[16:20]
|
||||||
|
|
||||||
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
# MUST TEST FOR NEW STREAM AND IF SO, RE-WRITE THE LC FOR THE TARGET
|
||||||
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
# MUST RE-WRITE DESTINATION TGID IF DIFFERENT
|
||||||
@ -628,7 +628,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
elif _frame_type == HBPF_DATA_SYNC and _dtype_vseq == HBPF_SLT_VTERM:
|
elif _frame_type == HBPF_DATA_SYNC and _dtype_vseq == HBPF_SLT_VTERM:
|
||||||
dmrbits = _target_status[_target['TS']]['TX_T_LC'][0:98] + dmrbits[98:166] + _target_status[_target['TS']]['TX_T_LC'][98:197]
|
dmrbits = _target_status[_target['TS']]['TX_T_LC'][0:98] + dmrbits[98:166] + _target_status[_target['TS']]['TX_T_LC'][98:197]
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']), 1))
|
systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']), 1).encode(encoding='utf-8', errors='ignore'))
|
||||||
# Create a Burst B-E packet (Embedded LC)
|
# Create a Burst B-E packet (Embedded LC)
|
||||||
elif _dtype_vseq in [1,2,3,4]:
|
elif _dtype_vseq in [1,2,3,4]:
|
||||||
dmrbits = dmrbits[0:116] + _target_status[_target['TS']]['TX_EMB_LC'][_dtype_vseq] + dmrbits[148:264]
|
dmrbits = dmrbits[0:116] + _target_status[_target['TS']]['TX_EMB_LC'][_dtype_vseq] + dmrbits[148:264]
|
||||||
@ -647,7 +647,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \
|
logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \
|
||||||
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration)
|
self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration)
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
self._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration))
|
self._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
#
|
#
|
||||||
# Begin in-band signalling for call end. This has nothign to do with routing traffic directly.
|
# Begin in-band signalling for call end. This has nothign to do with routing traffic directly.
|
||||||
@ -721,10 +721,13 @@ class routerHBP(HBSYSTEM):
|
|||||||
class confbridgeReportFactory(reportFactory):
|
class confbridgeReportFactory(reportFactory):
|
||||||
|
|
||||||
def send_bridge(self):
|
def send_bridge(self):
|
||||||
serialized = pickle.dumps(BRIDGES, protocol=pickle.HIGHEST_PROTOCOL)
|
serialized = pickle.dumps(BRIDGES, protocol=2) #.decode("utf-8", errors='ignore')
|
||||||
self.send_clients(REPORT_OPCODES['BRIDGE_SND']+serialized)
|
self.send_clients(REPORT_OPCODES['BRIDGE_SND']+serialized)
|
||||||
|
|
||||||
def send_bridgeEvent(self, _data):
|
def send_bridgeEvent(self, _data):
|
||||||
|
if isinstance(_data, str):
|
||||||
|
print('bridge event was a string')
|
||||||
|
#_data = _data.decode('utf-8', error='ignore')
|
||||||
self.send_clients(REPORT_OPCODES['BRDG_EVENT']+_data)
|
self.send_clients(REPORT_OPCODES['BRDG_EVENT']+_data)
|
||||||
|
|
||||||
|
|
||||||
@ -772,7 +775,7 @@ if __name__ == '__main__':
|
|||||||
# Set signal handers so that we can gracefully exit if need be
|
# Set signal handers so that we can gracefully exit if need be
|
||||||
for sig in [signal.SIGINT, signal.SIGTERM]:
|
for sig in [signal.SIGINT, signal.SIGTERM]:
|
||||||
signal.signal(sig, sig_handler)
|
signal.signal(sig, sig_handler)
|
||||||
|
|
||||||
# Create the name-number mapping dictionaries
|
# Create the name-number mapping dictionaries
|
||||||
peer_ids, subscriber_ids, talkgroup_ids = mk_aliases(CONFIG)
|
peer_ids, subscriber_ids, talkgroup_ids = mk_aliases(CONFIG)
|
||||||
|
|
||||||
@ -806,6 +809,5 @@ if __name__ == '__main__':
|
|||||||
stream_trimmer_task = task.LoopingCall(stream_trimmer_loop)
|
stream_trimmer_task = task.LoopingCall(stream_trimmer_loop)
|
||||||
stream_trimmer = stream_trimmer_task.start(5)
|
stream_trimmer = stream_trimmer_task.start(5)
|
||||||
stream_trimmer.addErrback(loopingErrHandle)
|
stream_trimmer.addErrback(loopingErrHandle)
|
||||||
|
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
@ -30,7 +30,7 @@ import configparser
|
|||||||
import sys
|
import sys
|
||||||
import const
|
import const
|
||||||
|
|
||||||
from socket import gethostbyname
|
from socket import gethostbyname
|
||||||
|
|
||||||
# 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'
|
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||||
@ -222,7 +222,7 @@ def build_config(_config_file):
|
|||||||
'NETWORK_ID': config.getint(section, 'NETWORK_ID').to_bytes(4, 'big'),
|
'NETWORK_ID': config.getint(section, 'NETWORK_ID').to_bytes(4, 'big'),
|
||||||
'IP': gethostbyname(config.get(section, 'IP')),
|
'IP': gethostbyname(config.get(section, 'IP')),
|
||||||
'PORT': config.getint(section, 'PORT'),
|
'PORT': config.getint(section, 'PORT'),
|
||||||
'PASSPHRASE': config.get(section, 'PASSPHRASE').ljust(20,'\x00')[:20],
|
'PASSPHRASE': bytes(config.get(section, 'PASSPHRASE').ljust(20,'\x00')[:20], 'utf-8'),
|
||||||
'TARGET_SOCK': (gethostbyname(config.get(section, 'TARGET_IP')), config.getint(section, 'TARGET_PORT')),
|
'TARGET_SOCK': (gethostbyname(config.get(section, 'TARGET_IP')), config.getint(section, 'TARGET_PORT')),
|
||||||
'TARGET_IP': gethostbyname(config.get(section, 'TARGET_IP')),
|
'TARGET_IP': gethostbyname(config.get(section, 'TARGET_IP')),
|
||||||
'TARGET_PORT': config.getint(section, 'TARGET_PORT'),
|
'TARGET_PORT': config.getint(section, 'TARGET_PORT'),
|
||||||
|
7
const.py
7
const.py
@ -39,6 +39,9 @@ ID_MAX = 16776415
|
|||||||
# Timers
|
# Timers
|
||||||
STREAM_TO = .360
|
STREAM_TO = .360
|
||||||
|
|
||||||
|
# Options from the LC - used for late entry
|
||||||
|
LC_OPT = b'\x00\x00\x20'
|
||||||
|
|
||||||
# HomeBrew Protocol Frame Types
|
# HomeBrew Protocol Frame Types
|
||||||
HBPF_VOICE = 0x0
|
HBPF_VOICE = 0x0
|
||||||
HBPF_VOICE_SYNC = 0x1
|
HBPF_VOICE_SYNC = 0x1
|
||||||
@ -50,7 +53,7 @@ HBPF_SLT_VTERM = 0x2
|
|||||||
DMRD = b'DMRD'
|
DMRD = b'DMRD'
|
||||||
MSTCL = b'MSTCL'
|
MSTCL = b'MSTCL'
|
||||||
MSTNAK = b'MSTNAC'
|
MSTNAK = b'MSTNAC'
|
||||||
MSTPONG = b'MSTPONG'
|
MSTPONG = b'MSTPONG'
|
||||||
MSTN = b'MSTN'
|
MSTN = b'MSTN'
|
||||||
MSTP = b'MSTP'
|
MSTP = b'MSTP'
|
||||||
MSTC = b'MSTC'
|
MSTC = b'MSTC'
|
||||||
@ -67,4 +70,4 @@ RPTO = b'RPTO'
|
|||||||
|
|
||||||
|
|
||||||
# Higheset peer ID permitted by HBP
|
# Higheset peer ID permitted by HBP
|
||||||
PEER_MAX = 4294967295
|
PEER_MAX = 4294967295
|
||||||
|
16
hblink.py
16
hblink.py
@ -49,7 +49,7 @@ from twisted.internet import reactor, task
|
|||||||
import log
|
import log
|
||||||
import config
|
import config
|
||||||
from const import *
|
from const import *
|
||||||
from dmr_utils3.utils import int_id, hex_str_4, try_download, mk_id_dict
|
from dmr_utils3.utils import int_id, bytes_4, try_download, mk_id_dict
|
||||||
|
|
||||||
# Imports for the reporting server
|
# Imports for the reporting server
|
||||||
import pickle as pickle
|
import pickle as pickle
|
||||||
@ -141,7 +141,7 @@ class OPENBRIDGE(DatagramProtocol):
|
|||||||
# Keep This Line Commented Unless HEAVILY Debugging!
|
# Keep This Line Commented Unless HEAVILY Debugging!
|
||||||
#logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_packet))
|
#logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_packet))
|
||||||
|
|
||||||
if _packet[:4] == 'DMRD': # DMRData -- encapsulated DMR data frame
|
if _packet[:4] == b'DMRD': # DMRData -- encapsulated DMR data frame
|
||||||
_data = _packet[:53]
|
_data = _packet[:53]
|
||||||
_hash = _packet[53:]
|
_hash = _packet[53:]
|
||||||
_ckhs = hmac_new(self._config['PASSPHRASE'],_data,sha1).digest()
|
_ckhs = hmac_new(self._config['PASSPHRASE'],_data,sha1).digest()
|
||||||
@ -151,7 +151,7 @@ class OPENBRIDGE(DatagramProtocol):
|
|||||||
_seq = _data[4]
|
_seq = _data[4]
|
||||||
_rf_src = _data[5:8]
|
_rf_src = _data[5:8]
|
||||||
_dst_id = _data[8:11]
|
_dst_id = _data[8:11]
|
||||||
_bits = int_id(_data[15])
|
_bits = _data[15]
|
||||||
_slot = 2 if (_bits & 0x80) else 1
|
_slot = 2 if (_bits & 0x80) else 1
|
||||||
#_call_type = 'unit' if (_bits & 0x40) else 'group'
|
#_call_type = 'unit' if (_bits & 0x40) else 'group'
|
||||||
if _bits & 0x40:
|
if _bits & 0x40:
|
||||||
@ -414,7 +414,7 @@ class HBSYSTEM(DatagramProtocol):
|
|||||||
'PACKAGE_ID': '',
|
'PACKAGE_ID': '',
|
||||||
}})
|
}})
|
||||||
logger.info('(%s) Repeater Logging in with Radio ID: %s, %s:%s', self._system, int_id(_peer_id), _sockaddr[0], _sockaddr[1])
|
logger.info('(%s) Repeater Logging in with Radio ID: %s, %s:%s', self._system, int_id(_peer_id), _sockaddr[0], _sockaddr[1])
|
||||||
_salt_str = hex_str_4(self._peers[_peer_id]['SALT'])
|
_salt_str = bytes_4(self._peers[_peer_id]['SALT'])
|
||||||
self.send_peer(_peer_id, RPTACK + _salt_str)
|
self.send_peer(_peer_id, RPTACK + _salt_str)
|
||||||
self._peers[_peer_id]['CONNECTION'] = 'CHALLENGE_SENT'
|
self._peers[_peer_id]['CONNECTION'] = 'CHALLENGE_SENT'
|
||||||
logger.info('(%s) Sent Challenge Response to %s for login: %s', self._system, int_id(_peer_id), self._peers[_peer_id]['SALT'])
|
logger.info('(%s) Sent Challenge Response to %s for login: %s', self._system, int_id(_peer_id), self._peers[_peer_id]['SALT'])
|
||||||
@ -433,7 +433,7 @@ class HBSYSTEM(DatagramProtocol):
|
|||||||
_this_peer = self._peers[_peer_id]
|
_this_peer = self._peers[_peer_id]
|
||||||
_this_peer['LAST_PING'] = time()
|
_this_peer['LAST_PING'] = time()
|
||||||
_sent_hash = _data[8:]
|
_sent_hash = _data[8:]
|
||||||
_salt_str = hex_str_4(_this_peer['SALT'])
|
_salt_str = bytes_4(_this_peer['SALT'])
|
||||||
_calc_hash = bhex(sha256(_salt_str+self._config['PASSPHRASE']).hexdigest())
|
_calc_hash = bhex(sha256(_salt_str+self._config['PASSPHRASE']).hexdigest())
|
||||||
if _sent_hash == _calc_hash:
|
if _sent_hash == _calc_hash:
|
||||||
_this_peer['CONNECTION'] = 'WAITING_CONFIG'
|
_this_peer['CONNECTION'] = 'WAITING_CONFIG'
|
||||||
@ -708,7 +708,7 @@ class reportFactory(Factory):
|
|||||||
client.sendString(_message)
|
client.sendString(_message)
|
||||||
|
|
||||||
def send_config(self):
|
def send_config(self):
|
||||||
serialized = pickle.dumps(self._config['SYSTEMS'], protocol=2) #pickle.HIGHEST_PROTOCOL)
|
serialized = pickle.dumps(self._config['SYSTEMS'], protocol=2) #.decode('utf-8', errors='ignore') #pickle.HIGHEST_PROTOCOL)
|
||||||
self.send_clients(REPORT_OPCODES['CONFIG_SND']+serialized)
|
self.send_clients(REPORT_OPCODES['CONFIG_SND']+serialized)
|
||||||
|
|
||||||
|
|
||||||
@ -772,7 +772,7 @@ if __name__ == '__main__':
|
|||||||
logger = log.config_logging(CONFIG['LOGGER'])
|
logger = log.config_logging(CONFIG['LOGGER'])
|
||||||
logger.info('\n\nCopyright (c) 2013, 2014, 2015, 2016, 2018\n\tThe Founding Members of the K0USY Group. All rights reserved.\n')
|
logger.info('\n\nCopyright (c) 2013, 2014, 2015, 2016, 2018\n\tThe Founding Members of the K0USY Group. All rights reserved.\n')
|
||||||
logger.debug('Logging system started, anything from here on gets logged')
|
logger.debug('Logging system started, anything from here on gets logged')
|
||||||
|
|
||||||
# Set up the signal handler
|
# Set up the signal handler
|
||||||
def sig_handler(_signal, _frame):
|
def sig_handler(_signal, _frame):
|
||||||
logger.info('SHUTDOWN: HBLINK IS TERMINATING WITH SIGNAL %s', str(_signal))
|
logger.info('SHUTDOWN: HBLINK IS TERMINATING WITH SIGNAL %s', str(_signal))
|
||||||
@ -799,5 +799,5 @@ if __name__ == '__main__':
|
|||||||
systems[system] = HBSYSTEM(system, CONFIG, report_server)
|
systems[system] = HBSYSTEM(system, CONFIG, report_server)
|
||||||
reactor.listenUDP(CONFIG['SYSTEMS'][system]['PORT'], systems[system], interface=CONFIG['SYSTEMS'][system]['IP'])
|
reactor.listenUDP(CONFIG['SYSTEMS'][system]['PORT'], systems[system], interface=CONFIG['SYSTEMS'][system]['IP'])
|
||||||
logger.debug('%s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system])
|
logger.debug('%s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system])
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
@ -36,7 +36,7 @@ from twisted.internet import reactor, task
|
|||||||
|
|
||||||
# Things we import from the main hblink module
|
# Things we import from the main hblink module
|
||||||
from hblink import HBSYSTEM, systems, hblink_handler, reportFactory, REPORT_OPCODES, config_reports, mk_aliases
|
from hblink import HBSYSTEM, systems, hblink_handler, reportFactory, REPORT_OPCODES, config_reports, mk_aliases
|
||||||
from dmr_utils.utils import hex_str_3, int_id, get_alias
|
from dmr_utils.utils import bytes_3, int_id, get_alias
|
||||||
from dmr_utils import decode, bptc, const
|
from dmr_utils import decode, bptc, const
|
||||||
import hb_config
|
import hb_config
|
||||||
import hb_log
|
import hb_log
|
||||||
|
5591
peer_ids.csv
5591
peer_ids.csv
File diff suppressed because it is too large
Load Diff
@ -19,12 +19,12 @@
|
|||||||
# Opcodes for the network-based reporting protocol
|
# Opcodes for the network-based reporting protocol
|
||||||
|
|
||||||
REPORT_OPCODES = {
|
REPORT_OPCODES = {
|
||||||
'CONFIG_REQ': '\x00',
|
'CONFIG_REQ': b'\x00',
|
||||||
'CONFIG_SND': '\x01',
|
'CONFIG_SND': b'\x01',
|
||||||
'BRIDGE_REQ': '\x02',
|
'BRIDGE_REQ': b'\x02',
|
||||||
'BRIDGE_SND': '\x03',
|
'BRIDGE_SND': b'\x03',
|
||||||
'CONFIG_UPD': '\x04',
|
'CONFIG_UPD': b'\x04',
|
||||||
'BRIDGE_UPD': '\x05',
|
'BRIDGE_UPD': b'\x05',
|
||||||
'LINK_EVENT': '\x06',
|
'LINK_EVENT': b'\x06',
|
||||||
'BRDG_EVENT': '\x07',
|
'BRDG_EVENT': b'\x07',
|
||||||
}
|
}
|
||||||
|
21
rules.py
21
rules.py
@ -1,21 +0,0 @@
|
|||||||
'''
|
|
||||||
THIS EXAMPLE WILL NOT WORK AS IT IS - YOU MUST SPECIFY YOUR OWN VALUES!!!
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
BRIDGES = {
|
|
||||||
'KANSAS': [
|
|
||||||
{'SYSTEM': 'PLYMOUTH', 'TS': 2, 'TGID': 3120, 'ACTIVE': True, 'TIMEOUT': 2, 'TO_TYPE': 'NONE', 'ON': [2,], 'OFF': [9,]},
|
|
||||||
],
|
|
||||||
'BYRG': [
|
|
||||||
{'SYSTEM': 'PLYMOUTH', 'TS': 1, 'TGID': 3100, 'ACTIVE': True, 'TIMEOUT': 2, 'TO_TYPE': 'NONE', 'ON': [3,], 'OFF': [8,]},
|
|
||||||
],
|
|
||||||
'ENGLISH': [
|
|
||||||
{'SYSTEM': 'PLYMOUTH', 'TS': 1, 'TGID': 13, 'ACTIVE': True, 'TIMEOUT': 2, 'TO_TYPE': 'NONE', 'ON': [4,], 'OFF': [7,]},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
from pprint import pprint
|
|
||||||
pprint(BRIDGES)
|
|
116858
subscriber_ids.csv
116858
subscriber_ids.csv
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user