* Added docker folder to repo
* Ubuntu based docker file can be build from the repo's root by ``` docker-compose -f docker/docker-compose.yml build ``` * and started by ``` docker-compose -f docker/docker-compose.yml build ``` * Restructured code by packaging the CallMonitoring and SpeexConverting * main() runs on startup and then watches for disconnected calls as trigger for running again. * Commented main file
This commit is contained in:
85
libs/message/conversion/__init__.py
Normal file
85
libs/message/conversion/__init__.py
Normal file
@@ -0,0 +1,85 @@
|
||||
|
||||
import wave, ctypes
|
||||
|
||||
|
||||
### Convert fb speex format to wav ###
|
||||
######################################
|
||||
"""
|
||||
This piece of code is just copied & pasted from https://git.savannah.nongnu.org/cgit/fbvbconv-py.git/tree/fbvbconv.py
|
||||
which has kindly managed to convert the messages of the answering machine of fritzboxes from a specially configured Speex format to a wave file. All appreciation to the author(s).
|
||||
"""
|
||||
|
||||
speexlib = ctypes.cdll.LoadLibrary("libspeex.so.1")
|
||||
SPEEX_SET_SAMPLING_RATE = 24
|
||||
SPEEX_GET_FRAME_SIZE = 3
|
||||
|
||||
class SpeexMode(ctypes.c_void_p):
|
||||
pass
|
||||
class Speex(ctypes.c_void_p):
|
||||
pass
|
||||
class SpeexBits(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('chars', ctypes.c_char_p),
|
||||
('nbBits', ctypes.c_int),
|
||||
('charPtr', ctypes.c_int),
|
||||
('bitPtr', ctypes.c_int),
|
||||
('owner', ctypes.c_int),
|
||||
('overflow', ctypes.c_int),
|
||||
('but_size', ctypes.c_int),
|
||||
('reserved1', ctypes.c_int),
|
||||
('reserved2', ctypes.c_void_p)
|
||||
]
|
||||
|
||||
speex_lib_get_mode = speexlib.speex_lib_get_mode
|
||||
speex_lib_get_mode.restype = SpeexMode
|
||||
speex_decoder_init = speexlib.speex_decoder_init
|
||||
speex_decoder_init.restype = Speex
|
||||
speex_decoder_ctl = speexlib.speex_decoder_ctl
|
||||
speex_bits_init = speexlib.speex_bits_init
|
||||
speex_bits_read_from = speexlib.speex_bits_read_from
|
||||
speex_decode_int = speexlib.speex_decode_int
|
||||
speex_bits_remaining = speexlib.speex_bits_remaining
|
||||
speex_bits_destroy = speexlib.speex_bits_destroy
|
||||
|
||||
|
||||
def speex_convert(inp, outp):
|
||||
# rec = open(inp, 'rb').read()
|
||||
rec = inp.read()
|
||||
wav = wave.open(outp, 'wb')
|
||||
wav.setnchannels(1)
|
||||
wav.setsampwidth(2)
|
||||
wav.setframerate(8000)
|
||||
|
||||
mode = speex_lib_get_mode(0)
|
||||
speex = speex_decoder_init(mode)
|
||||
speex_decoder_ctl(speex, SPEEX_SET_SAMPLING_RATE, ctypes.byref(ctypes.c_int(8000)))
|
||||
bits = SpeexBits()
|
||||
speex_bits_init(ctypes.byref(bits))
|
||||
frame_size = ctypes.c_int()
|
||||
speex_decoder_ctl(speex, SPEEX_GET_FRAME_SIZE, ctypes.byref(frame_size))
|
||||
|
||||
output = ctypes.create_string_buffer(2000)
|
||||
offs = 0
|
||||
while offs < len(rec):
|
||||
nbytes = rec[offs]
|
||||
offs += 1
|
||||
if nbytes != 0x26:
|
||||
continue
|
||||
buf = ctypes.create_string_buffer(rec[offs:offs + nbytes])
|
||||
offs += nbytes
|
||||
speex_bits_read_from(ctypes.byref(bits), buf, ctypes.c_int(nbytes))
|
||||
# this loop looks strange, but its like in roger router and seems to work
|
||||
for i in range(2):
|
||||
rc = speex_decode_int(speex, ctypes.byref(bits), output)
|
||||
if rc == -1:
|
||||
break
|
||||
elif rc == -2:
|
||||
print("Decoding error: corrupted stream?");
|
||||
break
|
||||
if speex_bits_remaining(ctypes.byref(bits)) < 0:
|
||||
print("Decoding overflow: corrupted stream?");
|
||||
break
|
||||
wav.writeframes(output[0:2 * frame_size.value])
|
||||
|
||||
wav.close()
|
||||
speex_bits_destroy(ctypes.byref(bits))
|
||||
36
libs/monitoring/__init__.py
Normal file
36
libs/monitoring/__init__.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import queue
|
||||
from fritzconnection.core.fritzmonitor import FritzMonitor
|
||||
|
||||
### Monitor the calls of a fritzbox continously ###
|
||||
###################################################
|
||||
|
||||
def watch_disconnect(monitor, event_queue, func, healthcheck_interval=10):
|
||||
while True:
|
||||
try:
|
||||
event = event_queue.get(timeout=healthcheck_interval)
|
||||
except queue.Empty:
|
||||
# check health:
|
||||
if not monitor.is_alive:
|
||||
raise OSError("Error: fritzmonitor connection failed")
|
||||
else:
|
||||
# do event processing here:
|
||||
print(event)
|
||||
if 'DISCONNECT' in event:
|
||||
print("Anruf beendet. Jetzt den AB checken.\n")
|
||||
func()
|
||||
|
||||
|
||||
|
||||
def endedCall(func, fritz_ip='192.168.1.1'):
|
||||
"""
|
||||
Call this to trigger a given function if a call is disconnected
|
||||
"""
|
||||
try:
|
||||
# as a context manager FritzMonitor will shut down the monitor thread
|
||||
with FritzMonitor(address=fritz_ip) as monitor:
|
||||
event_queue = monitor.start()
|
||||
watch_disconnect(monitor, event_queue, func)
|
||||
except (OSError, KeyboardInterrupt) as err:
|
||||
print(err)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user