Example #1
0
 def test_history(self):
     ivc = NumericValueCounter('test_counter', history=2)
     ivc.update(10)
     ivc.update(11)
     hp, hn = ivc.get_history()
     self.assertEqual(hp[1], 10)
     self.assertEqual(hn[1], 11)
Example #2
0
    def __init__(self, oxmi, recovery_message, cc, confsection):
        BaseThread.__init__(self)
        self.name = confsection['handle']
        self.comport, self.baudrate = confsection['serial_port'], confsection['serial_baudrate']
        self.notifier = SMTPNotifier(confsection)
        self.mk_serport()
        self.mte = None     #: message to execute
        self.interesting_shit = Lock()
        self.interesting_shit.acquire()
        self.oxm = oxmi
        self.conseq_reset = 0

        self.recovery_message = recovery_message

        self.is_attempting_recovery = False

        self.cc_hard_resets = PulseCounter('hard_resets',
            resolution=24*60*60, units='resets', 
            description=u'Hard resets during last 24 hours')
        self.cc_soft_resets = PulseCounter('soft_resets',
            resolution=24*60*60, units='resets', 
            description=u'Hard resets during last 24 hours')
        self.cc_send_time = NumericValueCounter('send_time',
            units='seconds', description='Time it took to send last SMS',
            history=20)


        cc.add(self.cc_hard_resets)
        cc.add(self.cc_soft_resets)
        cc.add(self.cc_send_time)
Example #3
0
 def test_current_value(self):
     ivc = NumericValueCounter('test_counter')
     ivc.update(10)
     self.assertEqual(ivc.get_current(), 10)
     ivc.update(20)
     self.assertEqual(ivc.get_current(), 20)
Example #4
0
 def test_enabled(self):
     ivc = NumericValueCounter('test_counter')
     ivc.disable()
     ivc.update(10)
     self.assertRaises(NoData, ivc.get_current)
Example #5
0
class ExecutorThread(BaseThread):

    class ATCommsError(Exception): 
        def __init__(self, instant_failure=False):
            self.instant_failure = instant_failure

    def mk_serport(self):
        try:
            self.serport
        except:
            pass
        else:
            self.serport.close()

        self.serport = serial.Serial(self.comport, self.baudrate, timeout=0)

    def __init__(self, oxmi, recovery_message, cc, confsection):
        BaseThread.__init__(self)
        self.name = confsection['handle']
        self.comport, self.baudrate = confsection['serial_port'], confsection['serial_baudrate']
        self.notifier = SMTPNotifier(confsection)
        self.mk_serport()
        self.mte = None     #: message to execute
        self.interesting_shit = Lock()
        self.interesting_shit.acquire()
        self.oxm = oxmi
        self.conseq_reset = 0

        self.recovery_message = recovery_message

        self.is_attempting_recovery = False

        self.cc_hard_resets = PulseCounter('hard_resets',
            resolution=24*60*60, units='resets', 
            description=u'Hard resets during last 24 hours')
        self.cc_soft_resets = PulseCounter('soft_resets',
            resolution=24*60*60, units='resets', 
            description=u'Hard resets during last 24 hours')
        self.cc_send_time = NumericValueCounter('send_time',
            units='seconds', description='Time it took to send last SMS',
            history=20)


        cc.add(self.cc_hard_resets)
        cc.add(self.cc_soft_resets)
        cc.add(self.cc_send_time)

    def on_interesting_shit(self):
        try:
            self.interesting_shit.release()
        except:
            pass

    def terminate(self):
        BaseThread.terminate(self)
        self.on_interesting_shit()

    def send_message(self, order):
        """Attempts sending the message. Raises ATCommsError if something
        failed"""

        
        sms_sent_speed = time()
        # switch to text mode
        self.serport.write('AT+CMGF=1\r')
        sleep(0.1)
        k = self.serport.read(1024)
        started_waiting_on = time()
        while not 'OK' in k:
            if (time() - started_waiting_on) > DASH_TIMEOUT:
                raise self.ATCommsError()
            sleep(0.1)
            k += self.serport.read(1024)

        if 'ERROR' in k:
            raise self.ATCommsError(True)

        # transforms content into msgcnt
        msgtext = unicode_to_sane_ascii(order.content)

        # clear any URCs
        k = self.serport.read(1024)
        while len(k) > 0: k = self.serport.read(1024)

        self.serport.write('AT+CMGS="%s"\r' % (order.target.encode('utf8'), ))
        sleep(0.1)
        k = self.serport.read(1024)
        started_waiting_on = time()
        while not '>' in k:
            if (time() - started_waiting_on) > DASH_TIMEOUT:
                raise self.ATCommsError()
            sleep(0.1)
            k += self.serport.read(1024)

        if 'ERROR' in k:
            raise self.ATCommsError(True)

        self.serport.write('%s\x1A' % (msgtext, ))
        started_waiting_on = time()

        k = ''
        while True:
            if (time() - started_waiting_on) > OK_TIMEOUT:
                raise self.ATCommsError()
            sleep(0.5)
            k += self.serport.read(1024)

            if '\r\nERROR\r\n' in k:
                raise self.ATCommsError(True)

            if '\n\r\nOK\r\n' in k:
                self.cc_send_time.update(time() - sms_sent_speed)
                return


    def run(self):
        self._run()
        if self.mte != None:
            self.oxm.eio.order_passback(self.mte)

    def _run(self):
        while not self._terminating:
            self.interesting_shit.acquire()

            if self.is_attempting_recovery:

                while not self._terminating:
                    # We will be attempting to periodically send a SMS

                    for i in xrange(0, 15): # delay loop
                        sleep(3)
                        if self._terminating: break

                    try:
                        self.send_message(self.recovery_message)
                    except self.ATCommsError:
                        # still f****d up
                        self.attempt_recovery()
                    else:
                        # success!
                        self.is_attempting_recovery = False
                        self.oxm.eio.on_fail_status(False)
                        self.notifier.notify('EUNIKE: %s left failed state' % (self.name, ))                        
                        self.conseq_reset = 0
                        break

                if self._terminating:
                    return

            elif self.mte != None:
                try:
                    self.send_message(self.mte)
                except self.ATCommsError:
                    if not self.attempt_recovery():
                        self.oxm.eio.on_fail_status(True)
                        self.notifier.notify('EUNIKE: %s entered failed state' % (self.name, ))
                        self.oxm.eio.on_ready() # We won't be scheduled anyway :)
                        self.oxm.eio.on_order_failed(self.mte)
                        self.mte = None
                        self.is_attempting_recovery = True
                        self.on_interesting_shit()
                        continue
                    else:
                        # Try again
                        self.on_interesting_shit()
                        continue
                else:
                    self.conseq_reset = 0
                    self.oxm.eio.on_sent_successfully(self.mte)
                    self.mte = None
                    self.oxm.eio.on_ready()
            
    def attempt_recovery(self):
        """Returns False when it's hopeless"""
        self.conseq_reset += 1

        if self.conseq_reset == 7:
            return False

        elif self.conseq_reset > 4:  
            self.attempt_hard_reset()         
        else:
            self.attempt_soft_reset()

        return True # after conseq_reset==7 there's no need to return False

    def attempt_soft_reset(self):
        """To be used in case of transmission failure"""
        self.serport.write(' \x1AAT+CSQ\r\r')   # Vulcan nerve pinch
        sleep(1)
        self.serport.read(2048)
        self.cc_soft_resets.update()

    def attempt_hard_reset(self):
        """To be used in case of hard failures"""
        self.serport.write(' \x1A\r\rAT+CFUN=1\r\r')
        sleep(5)
        self.serport.read(2048)
        self.cc_hard_resets.update()
        self.mk_serport()