# Path: MotionStateMachine.py
# class MotionStateMachine:
#     IDLE = 1
#     MOTION_DETECTED = 2
#     SUSTAINED_MOTION = 3
# 
#     MOTION_DETECTED_MOTION = 1
#     MOTION_DETECTED_NOMOTION = 2
# 
#     SUSTAINED_MOTION_MOTION = 1
#     SUSTAINED_MOTION_NOMOTION = 2
# 
#     def __init__(self):
#         self.reset()
# 
#     def reset(self):
#         self.state = 0
#         self.MOTION_DETECTED_state = 0
#         self.SUSTAINED_MOTION_state = 0
# 
#         self.MOTION_DETECTED_tStart = 0
#         self.MOTION_DETECTED_NOMOTION_tStart = 0
#         self.SUSTAINED_MOTION_NOMOTION_tStart = 0
# 
#         self.CALM_TIME = 30
#         self.SUSTAINED_TIME = 90
# 
#     def inSustainedMotion(self):
#         return self.state == self.SUSTAINED_MOTION
# 
#     def secondsInSustainedMotion(self):
#         if not self.inSustainedMotion():
#             return 0
# 
#         return timeElapsed(self.SUSTAINED_MOTION_tStart)
# 
#     def step(self, motion, tnow=None):
#         if not tnow:
#             tnow = datetime.now()
# 
#         if self.state == 0:
#             self.state = self.IDLE
# 
#         if self.state == self.IDLE:
# 
#             if motion:
#                 self.state = self.MOTION_DETECTED
#                 self.MOTION_DETECTED_state = self.MOTION_DETECTED_MOTION
#                 self.MOTION_DETECTED_tStart = tnow
# 
#         elif self.state == self.MOTION_DETECTED:
# 
#             if motion and timeElapsed(tnow, self.MOTION_DETECTED_tStart) >= self.SUSTAINED_TIME:
#                 self.state = self.SUSTAINED_MOTION
#                 self.MOTION_DETECTED_state = 0
#                 self.SUSTAINED_MOTION_state = self.SUSTAINED_MOTION_MOTION
#                 self.SUSTAINED_MOTION_tStart = tnow
# 
#             elif self.MOTION_DETECTED_state == self.MOTION_DETECTED_MOTION:
# 
#                 if not motion:
#                     self.MOTION_DETECTED_state = self.MOTION_DETECTED_NOMOTION
#                     self.MOTION_DETECTED_NOMOTION_tStart = tnow
# 
#             elif self.MOTION_DETECTED_state == self.MOTION_DETECTED_NOMOTION:
# 
#                 if motion:
#                     self.MOTION_DETECTED_state = self.MOTION_DETECTED_MOTION
#                 else:
#                     dt = timeElapsed(tnow, self.MOTION_DETECTED_NOMOTION_tStart)
#                     if dt >= self.CALM_TIME:
#                         self.MOTION_DETECTED_state = 0
#                         self.state = self.IDLE
# 
#         elif self.state == self.SUSTAINED_MOTION:
# 
#             if self.SUSTAINED_MOTION_state == self.SUSTAINED_MOTION_MOTION:
#                 if not motion:
#                     self.SUSTAINED_MOTION_state = self.SUSTAINED_MOTION_NOMOTION
#                     self.SUSTAINED_MOTION_NOMOTION_tStart = tnow
# 
#             elif self.SUSTAINED_MOTION_state == self.SUSTAINED_MOTION_NOMOTION:
#                 if motion:
#                     self.SUSTAINED_MOTION_state = self.SUSTAINED_MOTION_MOTION
#                 elif timeElapsed(tnow, self.SUSTAINED_MOTION_NOMOTION_tStart) >= self.CALM_TIME:
#                     self.SUSTAINED_MOTION_state = 0
#                     self.state = self.IDLE
# 
# Path: LoggingUtils.py
# def log(msg):
#     tnow = datetime.now()
#     logging.info('%s' % msg)
# 
# def setupLogging():
#     logFormatter = logging.Formatter("%(message)s")
#     rootLogger = logging.getLogger()
#     rootLogger.setLevel(logging.DEBUG)
# 
#     consoleHandler = logging.StreamHandler()
#     consoleHandler.setFormatter(logFormatter)
#     rootLogger.addHandler(consoleHandler)
# 
# Path: Constants.py
# class OximeterStatus:
#     CONNECTED = 'connected'
#     PROBE_DISCONNECTED = 'Oximeter probe disconnected'
#     CABLE_DISCONNECTED = 'Serial cable disconnected'


import glob
import re
import dateutil.parser
from datetime import datetime
from twisted.protocols.basic import LineReceiver
from twisted.internet.serialport import SerialPort
from twisted.internet.task import LoopingCall
from MotionStateMachine import MotionStateMachine
from LoggingUtils import log, setupLogging
from Constants import OximeterStatus
    from os import linesep as delimiter
    from twisted.internet import reactor
    from Config import Config
            self.resetTimer.reset(RESET_TIME)
        else:
            self.resetTimer = self.reactor.callLater(RESET_TIME, self.reset, OximeterStatus.CABLE_DISCONNECTED, 'timer')

    def connectionLost(self, reason):
        self.reset(OximeterStatus.CABLE_DISCONNECTED, 'connection lost')
        self.reader.searchForSerialPort()

class ForwardedAttrib(object):
    def __init__(self, propName):
        self.propName = propName

    def __get__(self, obj, objType):
        return getattr(obj.oximeterReader, self.propName)

class OximeterReader:
    def __init__(self, app):
        self.app = app
        self.reactor = app.reactor
        self.oximeterReader = OximeterReadProtocol(self)
        self.searchForSerialPort()

    def searchForSerialPort(self):
        self.loop = LoopingCall(self.connectToSerialPort)
        self.loop.start(2)

    def connectToSerialPort(self):
        devices = glob.glob('/dev/ttyUSB*')
        if len(devices) > 0:
            log('Started reading oximeter at %s' % devices[0])

# Path: MotionStateMachine.py
# class MotionStateMachine:
#     IDLE = 1
#     MOTION_DETECTED = 2
#     SUSTAINED_MOTION = 3
# 
#     MOTION_DETECTED_MOTION = 1
#     MOTION_DETECTED_NOMOTION = 2
# 
#     SUSTAINED_MOTION_MOTION = 1
#     SUSTAINED_MOTION_NOMOTION = 2
# 
#     def __init__(self):
#         self.reset()
# 
#     def reset(self):
#         self.state = 0
#         self.MOTION_DETECTED_state = 0
#         self.SUSTAINED_MOTION_state = 0
# 
#         self.MOTION_DETECTED_tStart = 0
#         self.MOTION_DETECTED_NOMOTION_tStart = 0
#         self.SUSTAINED_MOTION_NOMOTION_tStart = 0
# 
#         self.CALM_TIME = 30
#         self.SUSTAINED_TIME = 90
# 
#     def inSustainedMotion(self):
#         return self.state == self.SUSTAINED_MOTION
# 
#     def secondsInSustainedMotion(self):
#         if not self.inSustainedMotion():
#             return 0
# 
#         return timeElapsed(self.SUSTAINED_MOTION_tStart)
# 
#     def step(self, motion, tnow=None):
#         if not tnow:
#             tnow = datetime.now()
# 
#         if self.state == 0:
#             self.state = self.IDLE
# 
#         if self.state == self.IDLE:
# 
#             if motion:
#                 self.state = self.MOTION_DETECTED
#                 self.MOTION_DETECTED_state = self.MOTION_DETECTED_MOTION
#                 self.MOTION_DETECTED_tStart = tnow
# 
#         elif self.state == self.MOTION_DETECTED:
# 
#             if motion and timeElapsed(tnow, self.MOTION_DETECTED_tStart) >= self.SUSTAINED_TIME:
#                 self.state = self.SUSTAINED_MOTION
#                 self.MOTION_DETECTED_state = 0
#                 self.SUSTAINED_MOTION_state = self.SUSTAINED_MOTION_MOTION
#                 self.SUSTAINED_MOTION_tStart = tnow
# 
#             elif self.MOTION_DETECTED_state == self.MOTION_DETECTED_MOTION:
# 
#                 if not motion:
#                     self.MOTION_DETECTED_state = self.MOTION_DETECTED_NOMOTION
#                     self.MOTION_DETECTED_NOMOTION_tStart = tnow
# 
#             elif self.MOTION_DETECTED_state == self.MOTION_DETECTED_NOMOTION:
# 
#                 if motion:
#                     self.MOTION_DETECTED_state = self.MOTION_DETECTED_MOTION
#                 else:
#                     dt = timeElapsed(tnow, self.MOTION_DETECTED_NOMOTION_tStart)
#                     if dt >= self.CALM_TIME:
#                         self.MOTION_DETECTED_state = 0
#                         self.state = self.IDLE
# 
#         elif self.state == self.SUSTAINED_MOTION:
# 
#             if self.SUSTAINED_MOTION_state == self.SUSTAINED_MOTION_MOTION:
#                 if not motion:
#                     self.SUSTAINED_MOTION_state = self.SUSTAINED_MOTION_NOMOTION
#                     self.SUSTAINED_MOTION_NOMOTION_tStart = tnow
# 
#             elif self.SUSTAINED_MOTION_state == self.SUSTAINED_MOTION_NOMOTION:
#                 if motion:
#                     self.SUSTAINED_MOTION_state = self.SUSTAINED_MOTION_MOTION
#                 elif timeElapsed(tnow, self.SUSTAINED_MOTION_NOMOTION_tStart) >= self.CALM_TIME:
#                     self.SUSTAINED_MOTION_state = 0
#                     self.state = self.IDLE
# 
# Path: LoggingUtils.py
# def log(msg):
#     tnow = datetime.now()
#     logging.info('%s' % msg)
# 
# def setupLogging():
#     logFormatter = logging.Formatter("%(message)s")
#     rootLogger = logging.getLogger()
#     rootLogger.setLevel(logging.DEBUG)
# 
#     consoleHandler = logging.StreamHandler()
#     consoleHandler.setFormatter(logFormatter)
#     rootLogger.addHandler(consoleHandler)
# 
# Path: Constants.py
# class OximeterStatus:
#     CONNECTED = 'connected'
#     PROBE_DISCONNECTED = 'Oximeter probe disconnected'
#     CABLE_DISCONNECTED = 'Serial cable disconnected'


# Path: OximeterReader.py
import glob
import re
import dateutil.parser
from datetime import datetime
from twisted.protocols.basic import LineReceiver
from twisted.internet.serialport import SerialPort
from twisted.internet.task import LoopingCall
from MotionStateMachine import MotionStateMachine
from LoggingUtils import log, setupLogging
from Constants import OximeterStatus
    from os import linesep as delimiter
    from twisted.internet import reactor
    from Config import Config

            self.resetTimer.reset(RESET_TIME)
        else:
            self.resetTimer = self.reactor.callLater(RESET_TIME, self.reset, OximeterStatus.CABLE_DISCONNECTED, 'timer')

    def connectionLost(self, reason):
        self.reset(OximeterStatus.CABLE_DISCONNECTED, 'connection lost')
        self.reader.searchForSerialPort()

class ForwardedAttrib(object):
    def __init__(self, propName):
        self.propName = propName

    def __get__(self, obj, objType):
        return getattr(obj.oximeterReader, self.propName)

class OximeterReader:
    def __init__(self, app):
        self.app = app
        self.reactor = app.reactor
        self.oximeterReader = OximeterReadProtocol(self)
        self.searchForSerialPort()

    def searchForSerialPort(self):
        self.loop = LoopingCall(self.connectToSerialPort)
        self.loop.start(2)

    def connectToSerialPort(self):
        devices = glob.glob('/dev/ttyUSB*')
        if len(devices) > 0:
            log('Started reading oximeter at %s' % devices[0])

            self.oximeterReader.reset(OximeterStatus.CABLE_DISCONNECTED, 'got connection')