From 3bbb970198b06a5ccefecf67a354a12e356beccb Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 27 Dec 2021 01:47:15 +0000 Subject: [PATCH] tidy up FreeDMR module and class structure --- bridge.py | 4 +- bridge_master.py | 10 +- config.py | 2 +- const.py | 78 ---------- i8n_voice_map.py | 348 --------------------------------------------- mysql_config.py | 107 -------------- read_ambe.py | 175 ----------------------- reporting_const.py | 30 ---- 8 files changed, 8 insertions(+), 746 deletions(-) delete mode 100755 const.py delete mode 100644 i8n_voice_map.py delete mode 100644 mysql_config.py delete mode 100644 read_ambe.py delete mode 100755 reporting_const.py diff --git a/bridge.py b/bridge.py index 8657138..1a66388 100755 --- a/bridge.py +++ b/bridge.py @@ -42,12 +42,12 @@ from twisted.protocols.basic import NetstringReceiver from twisted.internet import reactor, task # Things we import from the main freedmr module -from freedmr import HBSYSTEM, OPENBRIDGE, systems, freedmr_handler, reportFactory, REPORT_OPCODES, mk_aliases +from FreeDMR.freedmr import HBSYSTEM, OPENBRIDGE, systems, freedmr_handler, reportFactory, REPORT_OPCODES, mk_aliases from dmr_utils3.utils import bytes_3, int_id, get_alias from dmr_utils3 import decode, bptc, const import config import log -from const import * +from FreeDMR.Const.const import * # Stuff for socket reporting import pickle diff --git a/bridge_master.py b/bridge_master.py index f8c6820..211ff68 100644 --- a/bridge_master.py +++ b/bridge_master.py @@ -46,24 +46,24 @@ from twisted.protocols.basic import NetstringReceiver from twisted.internet import reactor, task # Things we import from the main freedmr module -from freedmr import HBSYSTEM, OPENBRIDGE, systems, freedmr_handler, reportFactory, REPORT_OPCODES, mk_aliases, acl_check +from FreeDMR.freedmr import HBSYSTEM, OPENBRIDGE, systems, freedmr_handler, reportFactory, REPORT_OPCODES, mk_aliases, acl_check from dmr_utils3.utils import bytes_3, int_id, get_alias, bytes_4 from dmr_utils3 import decode, bptc, const import config from config import acl_build import log -from const import * +from FreeDMR.Const.const import * from mk_voice import pkt_gen #from voice_lib import words #Read voices -from read_ambe import readAMBE +from FreeDMR.Utilities.read_ambe import readAMBE #Remap some words for certain languages -from i8n_voice_map import voiceMap +from FreeDMR.i8n.i8n_voice_map import voiceMap #MySQL -from mysql_config import useMYSQL +from FreeDMR.Utilities.mysql_config import useMYSQL # Stuff for socket reporting import pickle diff --git a/config.py b/config.py index 11923b8..81964f3 100755 --- a/config.py +++ b/config.py @@ -28,7 +28,7 @@ change. import configparser import sys -import const +import FreeDMR.Const.const as const import socket import ipaddress diff --git a/const.py b/const.py deleted file mode 100755 index c491223..0000000 --- a/const.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -############################################################################### -# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -############################################################################### - -''' -These are contants used by HBlink. Rather than stuff them into the main program -file, any new constants should be placed here. It makes them easier to keep track -of and keeps hblink.py shorter. -''' - -__author__ = 'Cortney T. Buffington, N0MJS' -__copyright__ = 'Copyright (c) 2016 Cortney T. Buffington, N0MJS and the K0USY Group' -__credits__ = '' -__license__ = 'GNU GPLv3' -__maintainer__ = 'Cort Buffington, N0MJS' -__email__ = 'n0mjs@me.com' - - -# DMR Related constants -ID_MIN = 1 -ID_MAX = 16776415 - -# Timers -STREAM_TO = .360 - -# Options from the LC - used for late entry -LC_OPT = b'\x00\x00\x20' - -# HomeBrew Protocol Frame Types -HBPF_VOICE = 0x0 -HBPF_VOICE_SYNC = 0x1 -HBPF_DATA_SYNC = 0x2 -HBPF_SLT_VHEAD = 0x1 -HBPF_SLT_VTERM = 0x2 - -# HomeBrew Protocol Commands -DMRD = b'DMRD' -MSTCL = b'MSTCL' -MSTNAK = b'MSTNAK' -MSTPONG = b'MSTPONG' -MSTN = b'MSTN' -MSTP = b'MSTP' -MSTC = b'MSTC' -RPTL = b'RPTL' -RPTPING = b'RPTPING' -RPTCL = b'RPTCL' -RPTL = b'RPTL' -RPTACK = b'RPTACK' -RPTK = b'RPTK' -RPTC = b'RPTC' -RPTP = b'RPTP' -RPTA = b'RPTA' -RPTO = b'RPTO' -DMRA = b'DMRA' - -#Bridge Control commands -BC = b'BC' -BCKA = b'BCKA' -BCSQ = b'BCSQ' - -# Higheset peer ID permitted by HBP -PEER_MAX = 4294967295 diff --git a/i8n_voice_map.py b/i8n_voice_map.py deleted file mode 100644 index 401d2c1..0000000 --- a/i8n_voice_map.py +++ /dev/null @@ -1,348 +0,0 @@ -############################################################################### -# Copyright (C) 2020 Simon Adlem, G7RZU -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -############################################################################### -voiceMap = { - 'en_GB': { - 'A': 'alpha', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - - - 'en_GB_2': { - 'A': 'alpha', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - 'cy_GB': { - 'A': 'alpha', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - - 'en_US': { - 'to': '2', - 'freedmr': 'silence', - 'this-is': 'silence' - }, - - 'es_ES': { - '1': 'one', - '2': 'two', - '3': 'three', - '4': 'four', - '5': 'five', - '6': 'six', - '7': 'seven', - '8': 'eight', - '9': 'nine', - 'A': 'alfa', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - 'es_ES_2': { - '1': 'one', - '2': 'two', - '3': 'three', - '4': 'four', - '5': 'five', - '6': 'six', - '7': 'seven', - '8': 'eight', - '9': 'nine', - 'A': 'alfa', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - - 'fr_FR': { - 'A': 'alpha', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - - 'pt_PT': { - 'A': 'alpha', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - - 'el_GR': { - 'A': 'alpha', - 'B': 'bravo', - 'C': 'charlie', - 'D': 'delta', - 'E': 'echo', - 'F': 'foxtrot', - 'G': 'golf', - 'H': 'hotel', - 'I': 'india', - 'J': 'juliet', - 'K': 'kilo', - 'L': 'lima', - 'M': 'mike', - 'N': 'november', - 'O': 'oscar', - 'P': 'papa', - 'Q': 'quebec', - 'R': 'romeo', - 'S': 'sierra', - 'T': 'tango', - 'U': 'uniform', - 'V': 'victor', - 'W': 'whiskey', - 'X': 'x-ray', - 'Y': 'yankee', - 'Z': 'zulu', - 'to': 'silence', - 'notlinked': 'not-linked', - 'linkedto': 'linked-to' - }, - - 'de_DE': { - - 'to': 'silence', - }, - - 'dk_DK': { - 'to': 'silence', - 'freedmr': 'silence', - 'this-is': 'silence' - - }, - - 'it_IT': { - 'to': 'silence', - 'freedmr': 'silence', - 'this-is': 'silence' - }, - - 'no_NO': { - 'to': 'silence', - 'freedmr': 'silence', - 'this-is': 'silence' - }, - - 'pl_PL': { - 'to': 'silence', - 'freedmr': 'silence', - 'this-is': 'silence' - }, - - 'se_SE': { - 'to': 'silence', - 'freedmr': 'silence', - 'this-is': 'silence' - }, - - 'CW': { - 'to': 'silence', - 'freedmr': 'silence', - 'this-is': 'silence', - 'linkedto': 'silence' - }, - - 'th_TH': { - - 'to': 'silence', - }, - - -} - diff --git a/mysql_config.py b/mysql_config.py deleted file mode 100644 index fe8553b..0000000 --- a/mysql_config.py +++ /dev/null @@ -1,107 +0,0 @@ -import mysql.connector -from mysql.connector import errorcode -#import mysql.connector.pooling - -# Does anybody read this stuff? There's a PEP somewhere that says I should do this. -__author__ = 'Simon Adlem - G7RZU' -__copyright__ = 'Copyright (c) Simon Adlem, G7RZU 2020,2021' -__credits__ = 'Colin Durbridge, G4EML, Steve Zingman, N4IRS; Mike Zingman, N4IRR; Jonathan Naylor, G4KLX; Hans Barthen, DL5DI; Torsten Shultze, DG1HT; Jon Lee, G4TSN; Norman Williams, M6NBP' -__license__ = 'GNU GPLv3' -__maintainer__ = 'Simon Adlem G7RZU' -__email__ = 'simon@gb7fr.org.uk' - - -class useMYSQL: - #Init new object - def __init__(self, server,user,password,database,table,logger): - self.server = server - self.user = user - self.password = password - self.database = database - self.table = table - self.logger = logger - - #Connect - def con(self): - logger = self.logger - try: - self.db = mysql.connector.connect( - host=self.server, - user=self.user, - password=self.password, - database=self.database, - # pool_name = "hblink_master", - # pool_size = 2 - ) - except mysql.connector.Error as err: - if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: - logger.info('(MYSQL) username or password error') - return (False) - elif err.errno == errorcode.ER_BAD_DB_ERROR: - logger.info('(MYSQL) DB Error') - return (False) - else: - logger.info('(MYSQL) error: %s',err) - return(False) - - return(True) - - #Close DB connection - def close(self): - self.db.close() - - #Get config from DB - def getConfig(self): - - CONFIG = {} - CONFIG['SYSTEMS'] = {} - - _cursor = self.db.cursor() - - try: - _cursor.execute("select * from {} where MODE='MASTER'".format(self.table)) - except mysql.connector.Error as err: - _cursor.close() - logger.info('(MYSQL) error, problem with cursor execute') - raise Exception('Problem with cursor execute') - - for (callsign, mode, enabled, _repeat, max_peers, export_ambe, ip, port, passphrase, group_hangtime, use_acl, reg_acl, sub_acl, tgid_ts1_acl, tgid_ts2_acl, default_ua_timer, single_mode, voice_ident,ts1_static,ts2_static,default_reflector, announce_lang) in _cursor: - try: - CONFIG['SYSTEMS'].update({callsign: { - 'MODE': mode, - 'ENABLED': bool(enabled), - 'REPEAT': bool(_repeat), - 'MAX_PEERS': int(max_peers), - 'IP': ip, - 'PORT': int(port), - 'PASSPHRASE': bytes(passphrase, 'utf-8'), - 'GROUP_HANGTIME': int(group_hangtime), - 'USE_ACL': bool(use_acl), - 'REG_ACL': reg_acl, - 'SUB_ACL': sub_acl, - 'TG1_ACL': tgid_ts1_acl, - 'TG2_ACL': tgid_ts2_acl, - 'DEFAULT_UA_TIMER': int(default_ua_timer), - 'SINGLE_MODE': bool(single_mode), - 'VOICE_IDENT': bool(voice_ident), - 'TS1_STATIC': ts1_static, - 'TS2_STATIC': ts2_static, - 'DEFAULT_REFLECTOR': int(default_reflector), - 'GENERATOR': int(1), - 'ANNOUNCEMENT_LANGUAGE': announce_lang - }}) - CONFIG['SYSTEMS'][callsign].update({'PEERS': {}}) - except TypeError: - logger.info('(MYSQL) Problem with data from MySQL - TypeError, carrying on to next row') - - return(CONFIG['SYSTEMS']) - - -#For testing -if __name__ == '__main__': - - sql = useMYSQL("ip","user","pass","db") - - sql.con() - - print( sql.getConfig()) diff --git a/read_ambe.py b/read_ambe.py deleted file mode 100644 index 0442aba..0000000 --- a/read_ambe.py +++ /dev/null @@ -1,175 +0,0 @@ -############################################################################### -# Copyright (C) 2020 Simon Adlem, G7RZU -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -############################################################################### -from bitarray import bitarray -from itertools import islice -import os -import glob - -class readAMBE: - - def __init__(self, lang,path): - self.langcsv = lang - self.langs = lang.split(',') - self.path = path - - def _make_bursts(self,data): - it = iter(data) - for i in range(0, len(data), 108): - yield bitarray([k for k in islice(it, 108)] ) - - #Read indexed files - def readfiles(self): - - _AMBE_LENGTH = 9 - - _wordBADictofDicts = {} - - for _lang in self.langs: - - _prefix = self.path+_lang - _wordBADict = {} - - indexDict = {} - - if os.path.isdir(_prefix): - ambeBytearray = {} - _wordBitarray = bitarray(endian='big') - _wordBADict = {} - _glob = _prefix + "/*.ambe" - for ambe in glob.glob(_glob): - basename = os.path.basename(ambe) - _voice,ext = basename.split('.') - inambe = open(ambe,'rb') - _wordBitarray.frombytes(inambe.read()) - inambe.close() - _wordBADict[_voice] = [] - pairs = 1 - _lastburst = '' - for _burst in self._make_bursts(_wordBitarray): - #Not sure if we need to pad or not? Seems to make little difference. - if len(_burst) < 108: - pad = (108 - len(_burst)) - for i in range(0,pad,1): - _burst.append(False) - if pairs == 2: - _wordBADict[_voice].append([_lastburst,_burst]) - _lastburst = '' - pairs = 1 - next - else: - pairs = pairs + 1 - _lastburst = _burst - - _wordBitarray.clear() - _wordBADict['silence'] = ([ - [bitarray('101011000000101010100000010000000000001000000000000000000000010001000000010000000000100000000000100000000000'), - bitarray('001010110000001010101000000100000000000010000000000000000000000100010000000100000000001000000000001000000000')] - ]) - _wordBADictofDicts[_lang] = _wordBADict - else: - try: - with open(_prefix+'.indx') as index: - for line in index: - (voice,start,length) = line.split() - indexDict[voice] = [int(start) * _AMBE_LENGTH ,int(length) * _AMBE_LENGTH] - index.close() - except IOError: - return False - - ambeBytearray = {} - _wordBitarray = bitarray(endian='big') - _wordBADict = {} - try: - with open(_prefix+'.ambe','rb') as ambe: - for _voice in indexDict: - ambe.seek(indexDict[_voice][0]) - _wordBitarray.frombytes(ambe.read(indexDict[_voice][1])) - #108 - _wordBADict[_voice] = [] - pairs = 1 - _lastburst = '' - for _burst in self._make_bursts(_wordBitarray): - #Not sure if we need to pad or not? Seems to make little difference. - if len(_burst) < 108: - pad = (108 - len(_burst)) - for i in range(0,pad,1): - _burst.append(False) - if pairs == 2: - _wordBADict[_voice].append([_lastburst,_burst]) - _lastburst = '' - pairs = 1 - next - else: - pairs = pairs + 1 - _lastburst = _burst - - _wordBitarray.clear() - ambe.close() - except IOError: - return False - _wordBADict['silence'] = ([ - [bitarray('101011000000101010100000010000000000001000000000000000000000010001000000010000000000100000000000100000000000'), - bitarray('001010110000001010101000000100000000000010000000000000000000000100010000000100000000001000000000001000000000')] - ]) - _wordBADictofDicts[_lang] = _wordBADict - - return _wordBADictofDicts - - #Read a single ambe file from the audio directory - def readSingleFile(self,filename): - ambeBytearray = {} - _wordBitarray = bitarray(endian='big') - _wordBA= [] - try: - with open(self.path+filename,'rb') as ambe: - _wordBitarray.frombytes(ambe.read()) - #108 - _wordBA = [] - pairs = 1 - _lastburst = '' - for _burst in self._make_bursts(_wordBitarray): -#Not sure if we need to pad or not? Seems to make little difference. - if len(_burst) < 108: - pad = (108 - len(_burst)) - for i in range(0,pad,1): - _burst.append(False) - if pairs == 2: - _wordBA.append([_lastburst,_burst]) - _lastburst = '' - pairs = 1 - next - else: - pairs = pairs + 1 - _lastburst = _burst - - _wordBitarray.clear() - ambe.close() - except IOError: - raise - - return(_wordBA) - - -if __name__ == '__main__': - - #test = readAMBE('en_GB','./Audio/') - - #print(test.readfiles()) - test = readAMBE('en_GB_2','./Audio/') - print(test.readfiles()) - print(test.readSingleFile('44xx.ambe')) diff --git a/reporting_const.py b/reporting_const.py deleted file mode 100755 index 332e515..0000000 --- a/reporting_const.py +++ /dev/null @@ -1,30 +0,0 @@ -############################################################################### -# Copyright (C) 2018 Cortney T. Buffington, N0MJS -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -############################################################################### - -# Opcodes for the network-based reporting protocol - -REPORT_OPCODES = { - 'CONFIG_REQ': b'\x00', - 'CONFIG_SND': b'\x01', - 'BRIDGE_REQ': b'\x02', - 'BRIDGE_SND': b'\x03', - 'CONFIG_UPD': b'\x04', - 'BRIDGE_UPD': b'\x05', - 'LINK_EVENT': b'\x06', - 'BRDG_EVENT': b'\x07', - }