Revert "tidy up FreeDMR module and class structure"

This reverts commit 3bbb970198.
rate
Simon 4 years ago
parent 60afa46e7e
commit c25e1b95a6

@ -42,12 +42,12 @@ from twisted.protocols.basic import NetstringReceiver
from twisted.internet import reactor, task from twisted.internet import reactor, task
# Things we import from the main freedmr module # Things we import from the main freedmr module
from FreeDMR.freedmr import HBSYSTEM, OPENBRIDGE, systems, freedmr_handler, reportFactory, REPORT_OPCODES, mk_aliases from 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.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
from FreeDMR.Const.const import * from const import *
# Stuff for socket reporting # Stuff for socket reporting
import pickle import pickle

@ -46,24 +46,24 @@ from twisted.protocols.basic import NetstringReceiver
from twisted.internet import reactor, task from twisted.internet import reactor, task
# Things we import from the main freedmr module # Things we import from the main freedmr module
from FreeDMR.freedmr import HBSYSTEM, OPENBRIDGE, systems, freedmr_handler, reportFactory, REPORT_OPCODES, mk_aliases, acl_check from 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.utils import bytes_3, int_id, get_alias, bytes_4
from dmr_utils3 import decode, bptc, const from dmr_utils3 import decode, bptc, const
import config import config
from config import acl_build from config import acl_build
import log import log
from FreeDMR.Const.const import * from const import *
from mk_voice import pkt_gen from mk_voice import pkt_gen
#from voice_lib import words #from voice_lib import words
#Read voices #Read voices
from FreeDMR.Utilities.read_ambe import readAMBE from read_ambe import readAMBE
#Remap some words for certain languages #Remap some words for certain languages
from FreeDMR.i8n.i8n_voice_map import voiceMap from i8n_voice_map import voiceMap
#MySQL #MySQL
from FreeDMR.Utilities.mysql_config import useMYSQL from mysql_config import useMYSQL
# Stuff for socket reporting # Stuff for socket reporting
import pickle import pickle

@ -28,7 +28,7 @@ change.
import configparser import configparser
import sys import sys
import FreeDMR.Const.const as const import const
import socket import socket
import ipaddress import ipaddress

@ -0,0 +1,78 @@
#!/usr/bin/env python
#
###############################################################################
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
#
# 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

@ -0,0 +1,348 @@
###############################################################################
# Copyright (C) 2020 Simon Adlem, G7RZU <g7rzu@gb7fr.org.uk>
#
# 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',
},
}

@ -0,0 +1,107 @@
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())

@ -0,0 +1,175 @@
###############################################################################
# Copyright (C) 2020 Simon Adlem, G7RZU <g7rzu@gb7fr.org.uk>
#
# 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'))

@ -0,0 +1,30 @@
###############################################################################
# Copyright (C) 2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
#
# 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',
}
Loading…
Cancel
Save

Powered by TurnKey Linux.