# 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.reactor = reader.reactor
        self.app = reader.app
        self.config = self.app.config
        self.resetTimer = None
        self.badReadCount = 0

        self.reset(OximeterStatus.CABLE_DISCONNECTED, 'init')

    def reset(self, status, asker=''):
        log('resetting with %s (by [%s])' % (status, asker))

        if not status == OximeterStatus.CONNECTED:
            self.SPO2 = -1
            self.BPM = -1
            self.alarm = 0
            self.readTime = datetime.min

        if status == OximeterStatus.CABLE_DISCONNECTED:
            self.badReadCount = 0

        self.motionDetected = False
        self.motionSustained = False
        self.status = status

        self.setLineMode()

        self.alarmStateMachine = MotionStateMachine()
        self.alarmStateMachine.CALM_TIME = 0
        self.alarmStateMachine.SUSTAINED_TIME = self.config.spo2AlarmTime


# 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.reactor = reader.reactor
        self.app = reader.app
        self.config = self.app.config
        self.resetTimer = None
        self.badReadCount = 0

        self.reset(OximeterStatus.CABLE_DISCONNECTED, 'init')

    def reset(self, status, asker=''):
        log('resetting with %s (by [%s])' % (status, asker))

        if not status == OximeterStatus.CONNECTED:
            self.SPO2 = -1
            self.BPM = -1
            self.alarm = 0
            self.readTime = datetime.min

        if status == OximeterStatus.CABLE_DISCONNECTED:
            self.badReadCount = 0

        self.motionDetected = False
        self.motionSustained = False
        self.status = status

        self.setLineMode()

        self.alarmStateMachine = MotionStateMachine()
        self.alarmStateMachine.CALM_TIME = 0
        self.alarmStateMachine.SUSTAINED_TIME = self.config.spo2AlarmTime


        self.motionStateMachine = MotionStateMachine()