separate start and init sequences in statemachine
This commit is contained in:
parent
964445ca77
commit
766b5f6c81
|
@ -31,15 +31,17 @@ class Blinkenlights(ExceptionThread):
|
||||||
pwm.stop() # required to avoid core dumps when process terminates
|
pwm.stop() # required to avoid core dumps when process terminates
|
||||||
|
|
||||||
super().__init__(target=blinkLights, daemon=True)
|
super().__init__(target=blinkLights, daemon=True)
|
||||||
self.start()
|
|
||||||
logger.debug('Starting LED on pin %s', self._pin)
|
|
||||||
|
|
||||||
def setCyclePeriod(self, cyclePeriod):
|
def start(self):
|
||||||
self._sleeptime = cyclePeriod/20/2
|
ExceptionThread.start(self)
|
||||||
|
logger.debug('Starting LED on pin %s', self._pin)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._stopper.set()
|
self._stopper.set()
|
||||||
logger.debug('Stopping LED on pin %s', self._pin)
|
logger.debug('Stopping LED on pin %s', self._pin)
|
||||||
|
|
||||||
|
def setCyclePeriod(self, cyclePeriod):
|
||||||
|
self._sleeptime = cyclePeriod/20/2
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
38
listeners.py
38
listeners.py
|
@ -11,7 +11,7 @@ import stateMachine
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class KeypadListener():
|
class KeypadListener:
|
||||||
'''
|
'''
|
||||||
Interface for standard numpad device. Capabilities include:
|
Interface for standard numpad device. Capabilities include:
|
||||||
- accepting numeric input
|
- accepting numeric input
|
||||||
|
@ -35,20 +35,11 @@ class KeypadListener():
|
||||||
82: '0', 83: '.'
|
82: '0', 83: '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
devPath = '/dev/input/by-id/usb-04d9_1203-event-kbd'
|
|
||||||
|
|
||||||
waitForPath(devPath, logger)
|
|
||||||
|
|
||||||
self._dev = InputDevice(devPath)
|
|
||||||
self._dev.grab()
|
|
||||||
|
|
||||||
numKeySound = soundLib.soundEffects['numKey']
|
numKeySound = soundLib.soundEffects['numKey']
|
||||||
ctrlKeySound = soundLib.soundEffects['ctrlKey']
|
ctrlKeySound = soundLib.soundEffects['ctrlKey']
|
||||||
wrongPassSound = soundLib.soundEffects['wrongPass']
|
wrongPassSound = soundLib.soundEffects['wrongPass']
|
||||||
backspaceSound = soundLib.soundEffects['backspace']
|
backspaceSound = soundLib.soundEffects['backspace']
|
||||||
|
|
||||||
self._clearBuffer()
|
|
||||||
|
|
||||||
def getInput():
|
def getInput():
|
||||||
while 1:
|
while 1:
|
||||||
r, w, x = select([self._dev], [], [])
|
r, w, x = select([self._dev], [], [])
|
||||||
|
@ -112,11 +103,24 @@ class KeypadListener():
|
||||||
ctrlKeySound.play()
|
ctrlKeySound.play()
|
||||||
self._dev.set_led(ecodes.LED_NUML, 0 if soundLib.volume > 0 else 1)
|
self._dev.set_led(ecodes.LED_NUML, 0 if soundLib.volume > 0 else 1)
|
||||||
|
|
||||||
self._resetCountdown = None
|
|
||||||
|
|
||||||
self._listener = ExceptionThread(target=getInput, daemon=True)
|
self._listener = ExceptionThread(target=getInput, daemon=True)
|
||||||
|
self._resetCountdown = None
|
||||||
|
self._clearBuffer()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
devPath = '/dev/input/by-id/usb-04d9_1203-event-kbd'
|
||||||
|
|
||||||
|
waitForPath(devPath, logger)
|
||||||
|
|
||||||
|
self._dev = InputDevice(devPath)
|
||||||
|
self._dev.grab()
|
||||||
|
|
||||||
self._listener.start()
|
self._listener.start()
|
||||||
logger.debug('Started keypad device')
|
logger.debug('Started keypad listener')
|
||||||
|
|
||||||
|
def resetBuffer(self):
|
||||||
|
self._stopResetCountdown
|
||||||
|
self._clearBuffer()
|
||||||
|
|
||||||
def _startResetCountdown(self):
|
def _startResetCountdown(self):
|
||||||
self._resetCountdown = CountdownTimer(30, self._clearBuffer)
|
self._resetCountdown = CountdownTimer(30, self._clearBuffer)
|
||||||
|
@ -126,10 +130,6 @@ class KeypadListener():
|
||||||
self._resetCountdown.stop()
|
self._resetCountdown.stop()
|
||||||
self._resetCountdown = None
|
self._resetCountdown = None
|
||||||
|
|
||||||
def resetBuffer(self):
|
|
||||||
self._stopResetCountdown
|
|
||||||
self._clearBuffer()
|
|
||||||
|
|
||||||
def _clearBuffer(self):
|
def _clearBuffer(self):
|
||||||
self._buf = ''
|
self._buf = ''
|
||||||
|
|
||||||
|
@ -170,7 +170,9 @@ class PipeListener(ExceptionThread):
|
||||||
callback(msg, logger)
|
callback(msg, logger)
|
||||||
|
|
||||||
super().__init__(target=listen, daemon=True)
|
super().__init__(target=listen, daemon=True)
|
||||||
self.start()
|
|
||||||
|
def start(self):
|
||||||
|
ExceptionThread.start(self)
|
||||||
logger.debug('Started pipe listener at path %s', self._path)
|
logger.debug('Started pipe listener at path %s', self._path)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
|
1
main.py
1
main.py
|
@ -36,6 +36,7 @@ if __name__ == '__main__':
|
||||||
GPIO.setmode(GPIO.BCM)
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
|
||||||
stateMachine = StateMachine()
|
stateMachine = StateMachine()
|
||||||
|
stateMachine.start()
|
||||||
|
|
||||||
signal.signal(signal.SIGTERM, sigtermHandler)
|
signal.signal(signal.SIGTERM, sigtermHandler)
|
||||||
|
|
||||||
|
|
10
sensors.py
10
sensors.py
|
@ -22,12 +22,12 @@ def lowPassFilter(pin, targetVal, period=0.001):
|
||||||
|
|
||||||
return GPIO.input(pin) == targetVal
|
return GPIO.input(pin) == targetVal
|
||||||
|
|
||||||
def setupGPIO(name, pin, GPIOEvent, callback):
|
def _initGPIO(name, pin, GPIOEvent, callback):
|
||||||
logger.info('setting up \"%s\" on pin %s', name, pin)
|
logger.info('setting up \"%s\" on pin %s', name, pin)
|
||||||
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
|
||||||
GPIO.add_event_detect(pin, GPIOEvent, callback=callback, bouncetime=500)
|
GPIO.add_event_detect(pin, GPIOEvent, callback=callback, bouncetime=500)
|
||||||
|
|
||||||
def setupMotionSensor(pin, location, action):
|
def startMotionSensor(pin, location, action):
|
||||||
name = 'MotionSensor@' + location
|
name = 'MotionSensor@' + location
|
||||||
|
|
||||||
def trip(channel):
|
def trip(channel):
|
||||||
|
@ -36,9 +36,9 @@ def setupMotionSensor(pin, location, action):
|
||||||
action()
|
action()
|
||||||
|
|
||||||
logger.debug('waiting %s for %s to power on', INIT_DELAY, name)
|
logger.debug('waiting %s for %s to power on', INIT_DELAY, name)
|
||||||
CountdownTimer(INIT_DELAY, partial(setupGPIO, name, pin, GPIO.RISING, trip))
|
CountdownTimer(INIT_DELAY, partial(_initGPIO, name, pin, GPIO.RISING, trip))
|
||||||
|
|
||||||
def setupDoorSensor(pin, action, sound=None):
|
def startDoorSensor(pin, action, sound=None):
|
||||||
def trip(channel):
|
def trip(channel):
|
||||||
nonlocal closed
|
nonlocal closed
|
||||||
val = GPIO.input(pin)
|
val = GPIO.input(pin)
|
||||||
|
@ -56,5 +56,5 @@ def setupDoorSensor(pin, action, sound=None):
|
||||||
sound.play()
|
sound.play()
|
||||||
action()
|
action()
|
||||||
|
|
||||||
setupGPIO('DoorSensor', pin, GPIO.BOTH, trip)
|
_initGPIO('DoorSensor', pin, GPIO.BOTH, trip)
|
||||||
closed = GPIO.input(pin)
|
closed = GPIO.input(pin)
|
||||||
|
|
|
@ -88,6 +88,8 @@ class SoundLib:
|
||||||
|
|
||||||
self._ttsQueue = queue.Queue()
|
self._ttsQueue = queue.Queue()
|
||||||
self._stopper = Event()
|
self._stopper = Event()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
self._startMonitor()
|
self._startMonitor()
|
||||||
|
|
||||||
def changeVolume(self, volumeDelta):
|
def changeVolume(self, volumeDelta):
|
||||||
|
|
|
@ -6,18 +6,16 @@ from collections import namedtuple
|
||||||
|
|
||||||
from auxilary import CountdownTimer, resetUSBDevice
|
from auxilary import CountdownTimer, resetUSBDevice
|
||||||
from config import stateFile
|
from config import stateFile
|
||||||
from sensors import setupDoorSensor, setupMotionSensor
|
from sensors import startDoorSensor, startMotionSensor
|
||||||
from gmail import intruderAlert
|
from gmail import intruderAlert
|
||||||
from listeners import KeypadListener, PipeListener
|
from listeners import KeypadListener, PipeListener
|
||||||
from blinkenLights import Blinkenlights
|
from blinkenLights import Blinkenlights
|
||||||
from soundLib import SoundLib
|
from soundLib import SoundLib
|
||||||
from webInterface import initWebInterface
|
from webInterface import startWebInterface
|
||||||
from stream import Camera, FileDump
|
from stream import Camera, FileDump
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
resetUSBDevice('1-1')
|
|
||||||
|
|
||||||
class SIGNALS:
|
class SIGNALS:
|
||||||
ARM = 1
|
ARM = 1
|
||||||
INSTANT_ARM = 2
|
INSTANT_ARM = 2
|
||||||
|
@ -69,7 +67,12 @@ class State:
|
||||||
|
|
||||||
class StateMachine:
|
class StateMachine:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self._lock = Lock()
|
||||||
|
|
||||||
self.soundLib = SoundLib()
|
self.soundLib = SoundLib()
|
||||||
|
self.LED = Blinkenlights(17)
|
||||||
|
self.camera = Camera()
|
||||||
|
self.fileDump = FileDump()
|
||||||
|
|
||||||
def startTimer(t, sound):
|
def startTimer(t, sound):
|
||||||
self._timer = CountdownTimer(t, partial(self.selectState, SIGNALS.TIMOUT), sound)
|
self._timer = CountdownTimer(t, partial(self.selectState, SIGNALS.TIMOUT), sound)
|
||||||
|
@ -131,35 +134,6 @@ class StateMachine:
|
||||||
(self.states.triggered, SIGNALS.ARM): self.states.armed,
|
(self.states.triggered, SIGNALS.ARM): self.states.armed,
|
||||||
}
|
}
|
||||||
|
|
||||||
self._lock = Lock()
|
|
||||||
|
|
||||||
self.LED = Blinkenlights(17)
|
|
||||||
|
|
||||||
self.camera = Camera()
|
|
||||||
|
|
||||||
def action():
|
|
||||||
if self.currentState == self.states.armed:
|
|
||||||
self.selectState(SIGNALS.TRIGGER)
|
|
||||||
|
|
||||||
self.fileDump = FileDump()
|
|
||||||
sensitiveStates = (self.states.armed, self.states.armedCountdown, self.states.triggered)
|
|
||||||
|
|
||||||
def actionVideo(pin):
|
|
||||||
if self.currentState in sensitiveStates:
|
|
||||||
self.selectState(SIGNALS.TRIGGER)
|
|
||||||
self.fileDump.addInitiator(pin)
|
|
||||||
while GPIO.input(pin) and self.currentState in sensitiveStates:
|
|
||||||
time.sleep(0.1)
|
|
||||||
self.fileDump.removeInitiator(pin)
|
|
||||||
|
|
||||||
setupMotionSensor(5, 'Nate\'s room', action)
|
|
||||||
setupMotionSensor(19, 'front door', action)
|
|
||||||
setupMotionSensor(26, 'Laura\'s room', action)
|
|
||||||
setupMotionSensor(6, 'deck window', partial(actionVideo, 6))
|
|
||||||
setupMotionSensor(13, 'kitchen bar', partial(actionVideo, 13))
|
|
||||||
|
|
||||||
setupDoorSensor(22, action, self.soundLib.soundEffects['door'])
|
|
||||||
|
|
||||||
secretTable = {
|
secretTable = {
|
||||||
"dynamoHum": partial(self.selectState, SIGNALS.DISARM),
|
"dynamoHum": partial(self.selectState, SIGNALS.DISARM),
|
||||||
"zombyWoof": partial(self.selectState, SIGNALS.ARM),
|
"zombyWoof": partial(self.selectState, SIGNALS.ARM),
|
||||||
|
@ -186,7 +160,39 @@ class StateMachine:
|
||||||
passwd = '5918462'
|
passwd = '5918462'
|
||||||
)
|
)
|
||||||
|
|
||||||
initWebInterface(self)
|
def start(self):
|
||||||
|
resetUSBDevice('1-1')
|
||||||
|
|
||||||
|
self.soundLib.start()
|
||||||
|
self.LED.start()
|
||||||
|
self.keypadListener.start()
|
||||||
|
self.secretListener.start()
|
||||||
|
self.camera.start()
|
||||||
|
self.fileDump.start()
|
||||||
|
|
||||||
|
def action():
|
||||||
|
if self.currentState == self.states.armed:
|
||||||
|
self.selectState(SIGNALS.TRIGGER)
|
||||||
|
|
||||||
|
sensitiveStates = (self.states.armed, self.states.armedCountdown, self.states.triggered)
|
||||||
|
|
||||||
|
def actionVideo(pin):
|
||||||
|
if self.currentState in sensitiveStates:
|
||||||
|
self.selectState(SIGNALS.TRIGGER)
|
||||||
|
self.fileDump.addInitiator(pin)
|
||||||
|
while GPIO.input(pin) and self.currentState in sensitiveStates:
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.fileDump.removeInitiator(pin)
|
||||||
|
|
||||||
|
startMotionSensor(5, 'Nate\'s room', action)
|
||||||
|
startMotionSensor(19, 'front door', action)
|
||||||
|
startMotionSensor(26, 'Laura\'s room', action)
|
||||||
|
startMotionSensor(6, 'deck window', partial(actionVideo, 6))
|
||||||
|
startMotionSensor(13, 'kitchen bar', partial(actionVideo, 13))
|
||||||
|
|
||||||
|
startDoorSensor(22, action, self.soundLib.soundEffects['door'])
|
||||||
|
|
||||||
|
startWebInterface(self)
|
||||||
|
|
||||||
self.currentState.entry()
|
self.currentState.entry()
|
||||||
|
|
||||||
|
|
109
stream.py
109
stream.py
|
@ -68,7 +68,48 @@ class ThreadedPipeline:
|
||||||
self._stopper = Event()
|
self._stopper = Event()
|
||||||
|
|
||||||
def start(self, play=True):
|
def start(self, play=True):
|
||||||
self._startPipeline(play)
|
pName = self._pipeline.get_name()
|
||||||
|
stateChange = self._pipeline.set_state(Gst.State.PAUSED)
|
||||||
|
_gstPrintMsg(pName, 'Setting to PAUSED', level=logging.INFO)
|
||||||
|
|
||||||
|
if stateChange == Gst.StateChangeReturn.FAILURE:
|
||||||
|
_gstPrintMsg(pName, 'Cannot set to PAUSE', level=logging.INFO)
|
||||||
|
self._eventLoop(block=False, doProgress=False, targetState=Gst.State.VOID_PENDING)
|
||||||
|
# we should always end up here because live
|
||||||
|
elif stateChange == Gst.StateChangeReturn.NO_PREROLL:
|
||||||
|
_gstPrintMsg(pName, 'Live and does not need preroll')
|
||||||
|
elif stateChange == Gst.StateChangeReturn.ASYNC:
|
||||||
|
_gstPrintMsg(pName, 'Prerolling')
|
||||||
|
try:
|
||||||
|
_eventLoop(block=True, doProgress=True, targetState=Gst.State.PAUSED)
|
||||||
|
except GstException:
|
||||||
|
_gstPrintMsg(pName, 'Does not want to preroll', level=logging.ERROR)
|
||||||
|
raise SystemExit
|
||||||
|
elif stateChange == Gst.StateChangeReturn.SUCCESS:
|
||||||
|
_gstPrintMsg(pName, 'Is prerolled')
|
||||||
|
|
||||||
|
# this should always succeed...
|
||||||
|
try:
|
||||||
|
self._eventLoop(block=False, doProgress=True, targetState=Gst.State.PLAYING)
|
||||||
|
except GstException:
|
||||||
|
_gstPrintMsg(pName, 'Does not want to preroll', level=logging.ERROR)
|
||||||
|
raise SystemExit
|
||||||
|
# ...and end up here
|
||||||
|
else:
|
||||||
|
if play:
|
||||||
|
_gstPrintMsg(pName, 'Setting to PLAYING', level=logging.INFO)
|
||||||
|
|
||||||
|
# ...and since this will ALWAYS be successful...
|
||||||
|
if self._pipeline.set_state(Gst.State.PLAYING) == Gst.StateChangeReturn.FAILURE:
|
||||||
|
_gstPrintMsg(pName, 'Cannot set to PLAYING', level=logging.ERROR)
|
||||||
|
err = self._pipeline.get_bus().pop_filtered(Gst.MessageType.Error)
|
||||||
|
_processErrorMessage(pName, msgSrcName, err)
|
||||||
|
|
||||||
|
# ...we end up here and loop until Tool releases their next album
|
||||||
|
try:
|
||||||
|
self._mainLoop()
|
||||||
|
except:
|
||||||
|
raise GstException
|
||||||
|
|
||||||
# TODO: this might not all be necessary
|
# TODO: this might not all be necessary
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
@ -248,50 +289,6 @@ class ThreadedPipeline:
|
||||||
def _mainLoop(self):
|
def _mainLoop(self):
|
||||||
self._eventLoop(block=True, doProgress=False, targetState=Gst.State.PLAYING)
|
self._eventLoop(block=True, doProgress=False, targetState=Gst.State.PLAYING)
|
||||||
|
|
||||||
def _startPipeline(self, play):
|
|
||||||
pName = self._pipeline.get_name()
|
|
||||||
stateChange = self._pipeline.set_state(Gst.State.PAUSED)
|
|
||||||
_gstPrintMsg(pName, 'Setting to PAUSED', level=logging.INFO)
|
|
||||||
|
|
||||||
if stateChange == Gst.StateChangeReturn.FAILURE:
|
|
||||||
_gstPrintMsg(pName, 'Cannot set to PAUSE', level=logging.INFO)
|
|
||||||
self._eventLoop(block=False, doProgress=False, targetState=Gst.State.VOID_PENDING)
|
|
||||||
# we should always end up here because live
|
|
||||||
elif stateChange == Gst.StateChangeReturn.NO_PREROLL:
|
|
||||||
_gstPrintMsg(pName, 'Live and does not need preroll')
|
|
||||||
elif stateChange == Gst.StateChangeReturn.ASYNC:
|
|
||||||
_gstPrintMsg(pName, 'Prerolling')
|
|
||||||
try:
|
|
||||||
_eventLoop(block=True, doProgress=True, targetState=Gst.State.PAUSED)
|
|
||||||
except GstException:
|
|
||||||
_gstPrintMsg(pName, 'Does not want to preroll', level=logging.ERROR)
|
|
||||||
raise SystemExit
|
|
||||||
elif stateChange == Gst.StateChangeReturn.SUCCESS:
|
|
||||||
_gstPrintMsg(pName, 'Is prerolled')
|
|
||||||
|
|
||||||
# this should always succeed...
|
|
||||||
try:
|
|
||||||
self._eventLoop(block=False, doProgress=True, targetState=Gst.State.PLAYING)
|
|
||||||
except GstException:
|
|
||||||
_gstPrintMsg(pName, 'Does not want to preroll', level=logging.ERROR)
|
|
||||||
raise SystemExit
|
|
||||||
# ...and end up here
|
|
||||||
else:
|
|
||||||
if play:
|
|
||||||
_gstPrintMsg(pName, 'Setting to PLAYING', level=logging.INFO)
|
|
||||||
|
|
||||||
# ...and since this will ALWAYS be successful...
|
|
||||||
if self._pipeline.set_state(Gst.State.PLAYING) == Gst.StateChangeReturn.FAILURE:
|
|
||||||
_gstPrintMsg(pName, 'Cannot set to PLAYING', level=logging.ERROR)
|
|
||||||
err = self._pipeline.get_bus().pop_filtered(Gst.MessageType.Error)
|
|
||||||
_processErrorMessage(pName, msgSrcName, err)
|
|
||||||
|
|
||||||
# ...we end up here and loop until Tool releases their next album
|
|
||||||
try:
|
|
||||||
self._mainLoop()
|
|
||||||
except:
|
|
||||||
raise GstException
|
|
||||||
|
|
||||||
class Camera(ThreadedPipeline):
|
class Camera(ThreadedPipeline):
|
||||||
'''
|
'''
|
||||||
Class for usb camera. The 'video' and 'audio' flags are meant for testing.
|
Class for usb camera. The 'video' and 'audio' flags are meant for testing.
|
||||||
|
@ -304,11 +301,12 @@ class Camera(ThreadedPipeline):
|
||||||
X = 1 is used by the Janus WebRTC interface and X = 2 is used by the
|
X = 1 is used by the Janus WebRTC interface and X = 2 is used by the
|
||||||
FileDump class below.
|
FileDump class below.
|
||||||
'''
|
'''
|
||||||
|
_vPath = '/dev/video0'
|
||||||
|
_aPath = 'hw:1,0'
|
||||||
|
|
||||||
def __init__(self, video=True, audio=True):
|
def __init__(self, video=True, audio=True):
|
||||||
super().__init__('camera')
|
super().__init__('camera')
|
||||||
|
|
||||||
vPath = '/dev/video0'
|
|
||||||
|
|
||||||
if video:
|
if video:
|
||||||
vSource = Gst.ElementFactory.make("v4l2src", "videoSource")
|
vSource = Gst.ElementFactory.make("v4l2src", "videoSource")
|
||||||
vConvert = Gst.ElementFactory.make("videoconvert", "videoConvert")
|
vConvert = Gst.ElementFactory.make("videoconvert", "videoConvert")
|
||||||
|
@ -318,7 +316,7 @@ class Camera(ThreadedPipeline):
|
||||||
vRTPPay = Gst.ElementFactory.make("rtph264pay", "videoRTPPayload")
|
vRTPPay = Gst.ElementFactory.make("rtph264pay", "videoRTPPayload")
|
||||||
vRTPSink = Gst.ElementFactory.make("multiudpsink", "videoRTPSink")
|
vRTPSink = Gst.ElementFactory.make("multiudpsink", "videoRTPSink")
|
||||||
|
|
||||||
vSource.set_property('device', vPath)
|
vSource.set_property('device', self._vPath)
|
||||||
vRTPPay.set_property('config-interval', 1)
|
vRTPPay.set_property('config-interval', 1)
|
||||||
vRTPPay.set_property('pt', 96)
|
vRTPPay.set_property('pt', 96)
|
||||||
vRTPSink.set_property('clients', '127.0.0.1:9001,127.0.0.1:9002')
|
vRTPSink.set_property('clients', '127.0.0.1:9001,127.0.0.1:9002')
|
||||||
|
@ -342,7 +340,7 @@ class Camera(ThreadedPipeline):
|
||||||
aRTPPay = Gst.ElementFactory.make("rtpopuspay", "audioRTPPayload")
|
aRTPPay = Gst.ElementFactory.make("rtpopuspay", "audioRTPPayload")
|
||||||
aRTPSink = Gst.ElementFactory.make("multiudpsink", "audioRTPSink")
|
aRTPSink = Gst.ElementFactory.make("multiudpsink", "audioRTPSink")
|
||||||
|
|
||||||
aSource.set_property('device', 'hw:1,0')
|
aSource.set_property('device', self._aPath)
|
||||||
aRTPSink.set_property('clients', '127.0.0.1:8001,127.0.0.1:8002')
|
aRTPSink.set_property('clients', '127.0.0.1:8001,127.0.0.1:8002')
|
||||||
|
|
||||||
aCaps = Gst.Caps.from_string('audio/x-raw,rate=48000,channels=1')
|
aCaps = Gst.Caps.from_string('audio/x-raw,rate=48000,channels=1')
|
||||||
|
@ -355,9 +353,10 @@ class Camera(ThreadedPipeline):
|
||||||
_linkElements(aEncode, aRTPPay)
|
_linkElements(aEncode, aRTPPay)
|
||||||
_linkElements(aRTPPay, aRTPSink)
|
_linkElements(aRTPPay, aRTPSink)
|
||||||
|
|
||||||
waitForPath(vPath) # video is on usb, so wait until it comes back after we hard reset the bus
|
def start(self):
|
||||||
|
# video is on usb, so wait until it comes back after we hard reset the bus
|
||||||
self.start()
|
waitForPath(self._vPath)
|
||||||
|
ThreadedPipeline.start(self, play=False)
|
||||||
|
|
||||||
class FileDump(ThreadedPipeline):
|
class FileDump(ThreadedPipeline):
|
||||||
'''
|
'''
|
||||||
|
@ -379,7 +378,7 @@ class FileDump(ThreadedPipeline):
|
||||||
logger.error('Attempting to init FileDump without gluster mounted. Aborting')
|
logger.error('Attempting to init FileDump without gluster mounted. Aborting')
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
self._savePath = os.path.join(gluster.mountpoint + '/video')
|
self._savePath = os.path.join(gluster.mountpoint, 'video')
|
||||||
|
|
||||||
mkdirSafe(self._savePath, logger)
|
mkdirSafe(self._savePath, logger)
|
||||||
|
|
||||||
|
@ -424,10 +423,10 @@ class FileDump(ThreadedPipeline):
|
||||||
|
|
||||||
_linkElements(mux, self.sink)
|
_linkElements(mux, self.sink)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
# TODO: there is probably a better way to init than starting up to PAUSE
|
# TODO: there is probably a better way to init than starting up to PAUSE
|
||||||
# and then dropping back down to NULL
|
# and then dropping back down to NULL
|
||||||
self.start(play=False)
|
ThreadedPipeline.start(self, play=False)
|
||||||
|
|
||||||
self._pipeline.post_message(Gst.Message.new_request_state(self._pipeline, Gst.State.NULL))
|
self._pipeline.post_message(Gst.Message.new_request_state(self._pipeline, Gst.State.NULL))
|
||||||
|
|
||||||
def addInitiator(self, identifier):
|
def addInitiator(self, identifier):
|
||||||
|
|
|
@ -20,7 +20,7 @@ class TTSForm(FlaskForm):
|
||||||
# TODO: fix random connection fails (might be an nginx thing)
|
# TODO: fix random connection fails (might be an nginx thing)
|
||||||
|
|
||||||
@async(daemon=True)
|
@async(daemon=True)
|
||||||
def initWebInterface(stateMachine):
|
def startWebInterface(stateMachine):
|
||||||
siteRoot = Blueprint('siteRoot', __name__, static_folder='static', static_url_path='')
|
siteRoot = Blueprint('siteRoot', __name__, static_folder='static', static_url_path='')
|
||||||
|
|
||||||
@siteRoot.route('/', methods=['GET', 'POST'])
|
@siteRoot.route('/', methods=['GET', 'POST'])
|
||||||
|
|
Loading…
Reference in New Issue