Exemple #1
0
    def algorithm(self):
        candidateClock = CorrelatedClock(self.clock.getParent(),
                                         tickRate=self.clock.tickRate,
                                         correlation=self.clock.correlation)

        while True:
            update = False
            cumulativeOffset = None
            candidate = (yield self.timeoutSecs)

            t = self.clock.ticks
            currentDispersion = self.clock.dispersionAtTime(t)

            if candidate is not None:

                candidateClock.correlation = candidate.calcCorrelationFor(
                    self.clock, self.localMaxFreqErrorPpm)
                candidateDispersion = candidateClock.dispersionAtTime(t)

                update = candidateDispersion < currentDispersion
                if update:
                    pt = self.clock.toParentTicks(t)
                    adjustment = candidateClock.fromParentTicks(pt) - t
                    if cumulativeOffset is None:
                        cumulativeOffset = 0
                    else:
                        cumulativeOffset += adjustment

                    self.clock.correlation = candidateClock.correlation
                    self.onClockAdjusted(
                        self.clock.ticks, adjustment,
                        1000000000 * currentDispersion,
                        1000000000 * candidateDispersion,
                        self.clock.correlation.errorGrowthRate)

                else:
                    pass

                # update worst dispersion seen so far
                self.worstDispersion = max(self.worstDispersion,
                                           currentDispersion,
                                           candidateDispersion)

                co = cumulativeOffset or 0  # convert None to 0
                self.log.info(
                    "Old / New dispersion (millis) is %.5f / %.5f ... offset=%20d  new best candidate? %s\n"
                    % (1000 * currentDispersion, 1000 * candidateDispersion,
                       co, str(update)))
            else:
                self.log.info("Timeout.  Dispersion (millis) is %.5f\n" %
                              (1000 * currentDispersion, ))
            # retry more quickly if we didn't get an improved candidate
            if update:
                time.sleep(self.repeatSecs)
            else:
                time.sleep(self.timeoutSecs)
Exemple #2
0
 def algorithm(self):
     while True:
         candidate = (yield self.timeoutSecs)
         if candidate is not None:
             self.log.info("Candidate: " + str(candidate) + "\n")
             self.clock.correlation = candidate.calcCorrelationFor(
                 self.clock, 500)  # guess as to local max freq error
             time.sleep(self.repeatSecs)
         else:
             self.log.debug("Response timeout\n")
    def test_sleep_works(self):
        """Check a sleep works"""
        t=self.t
        m=self.m

        start_t = t.time()
        m.sleep(5)
        end_t = t.time()

        diff_t = (end_t - start_t)

        self.assertLess(abs(5.0-diff_t), 0.05, "Sleep was correct to within 1%")
Exemple #4
0
    def test_sleep_works(self):
        """Check a sleep works"""
        t = self.t
        m = self.m

        start_t = t.time()
        m.sleep(5)
        end_t = t.time()

        diff_t = (end_t - start_t)

        self.assertLess(abs(5.0 - diff_t), 0.05,
                        "Sleep was correct to within 1%")
Exemple #5
0
    def algorithm(self):
        cumulativeOffset=None
        self.bestCandidate={"nanos":None,"ticks":None}
        while True:
            update=False
            candidate=(yield self.timeoutSecs)
    
            currentDispersion = self.getCurrentDispersion()
    
            if candidate is not None:
                cn=candidate['nanos']
                ct=candidate['ticks']
                candidateDispersion=self.dispCalc.calc(cn)
                
                if currentDispersion >= candidateDispersion:
                    self.bestCandidate = candidate
                    update=True
                    self.clock.adjustTicks(ct.offset)
                    if cumulativeOffset is None:
                        cumulativeOffset=0
                    else:
                        cumulativeOffset+=ct.offset
                        
                    # notify of the change
                    growthRate = self.dispCalc.getGrowthRate(cn)
                    self.onClockAdjusted(self.clock.ticks, ct.offset, currentDispersion, candidateDispersion, growthRate)
                    
                else:
                    pass

                # update worst dispersion seen so far
                self.worstDispersion = max(self.worstDispersion, currentDispersion, candidateDispersion)

                self.log.info("Old / New dispersion (millis) is %.5f / %.5f ... offset=%20d  new best candidate? %s\n" % (currentDispersion/1000000.0, candidateDispersion/1000000.0, cumulativeOffset, str(update)))
            else:
                self.log.info("Timeout.  Dispersion (millis) is %.5f\n" % (currentDispersion/1000000.0))
            # retry more quickly if we didn't get an improved candidate
            if update:
                time.sleep(self.repeatSecs)
            else:
                time.sleep(self.timeoutSecs)
Exemple #6
0
    def algorithm(self):
        while True:
            candidate = (yield self.timeoutSecs)
            if candidate is not None:

                # apply filters
                if None in [f.checkCandidate(candidate) for f in self.filters]:
                    self.log.debug("Candidate filtered out\n")
                    time.sleep(self.repeatSecs)
                else:

                    # filters passed, so now feed the candidate into the predictor
                    # and retrieve a new estimate of the correlation
                    self.predictor.addCandidate(candidate)
                    self.clock.correlation = self.predictor.predictCorrelation(
                    )

                    # act on it
                    self.log.debug("Candidate accepted. New Correlation = ",
                                   self.clock.correlation)

                    time.sleep(self.repeatSecs)
            else:
                self.log.debug("Response timeout\n")
Exemple #7
0
                                          wallClock=wallClock,
                                          clock=ptsTimeline,
                                          speedSource=ptsTimeline)
    temiSource = SimpleClockTimelineSource("urn:dvb:css:timeline:temi:1:1",
                                           wallClock=wallClock,
                                           clock=temiTimeline,
                                           speedSource=ptsTimeline)

    tsServer.attachTimelineSource(ptsSource)
    tsServer.attachTimelineSource(temiSource)

    wcServer.start()

    cherrypy.engine.start()

    try:
        while True:
            time.sleep(30)
            temiTimeline.setAvailability(False)
            tsServer.updateAllClients()

            time.sleep(30)
            temiTimeline.setAvailability(True)
            tsServer.updateAllClients()

    except KeyboardInterrupt:
        pass
    finally:
        cherrypy.engine.exit()
        wcServer.stop()
Exemple #8
0
    def pausePtsClock():
        """Pauses the PTS clock and adjusts the correlation to make it as if it paused at the current tick value"""
        ptsClock.rebaseCorrelationAtTicks(ptsClock.ticks)
        ptsClock.speed = 0.0

    def unpausePtsClock():
        """Unpauses the PTS clock and adjusts the correlation so the ticks continue to increase form this point forward."""
        ptsClock.correlation = ( ptsClock.getParent().ticks, ptsClock.correlation[1] )
        ptsClock.speed = 1.0


    try:
        while True:
            tsServer.updateAllClients()
            
            time.sleep(5)
            tweakPtsClock()
            tsServer.updateAllClients()
            print "Tweaked correlation timestamp for PTS and TEMI."
            print "PTS clock at %f (units of seconds)" % (float(ptsClock.ticks)/ptsClock.tickRate)
        
            time.sleep(5)
            tsServer.removeTimelineSource(sporadicTimeline)
            tsServer.updateAllClients()
            print "Made timeline "+sporadicTimeline._timelineSelector+" unavailable."
            
            time.sleep(5)
            pausePtsClock()
            tsServer.updateAllClients()
            print "Paused the PTS and TEMI timelines."
            print "PTS clock at %f (units of seconds)" % (float(ptsClock.ticks)/ptsClock.tickRate)
Exemple #9
0
 def run(self):
     monotonic_time.sleep(self.sleepArg)
Exemple #10
0
    print "Will double clock speed halfway through"
    
    threading.Thread(target=threadrun).start()
    sleepUntil(tClock, tClock.ticks + 500)
    tClock.speed = 2
    print "Speed doubled"
    sleepUntil(tClock, tClock.ticks + 600)
    
    def go(message):
        print "Scheduled task ran. Message was: "+message
        
    print "Scheduling call back in 2 seconds..."
    args = ["huzzah!"]
    runAt(tClock, tClock.ticks + 400, go, args)

    time.sleep(5)
    
    print "Now same again, but with all callbacks scheduled in advance"
    tClock.slew = 0
    
    def doAdjust(amount):
        tClock.slew = amount
        print"Adjusted tClock frequency by +100 Hz"
      
    now=tClock.ticks
    for i in range(1,11):
        args = ["Tick "+str(100*i)]
        runAt(tClock, now+100*i, go, args)

    args=[100]
    runAt(tClock, now+500, doAdjust, args)
Exemple #11
0
    cherrypy.engine.start()

    dummyContentIds = [
        "dvb://233a.1004.1044;363a~20130218T0915Z--PT00H45M",
        "dvb://233a.1168.122a;1aa4~20130218T0910Z--PT00H30M",
        "dvb://233a.1050.1008;9fd~20130218T0920Z--PT00H50M",
    ]

    # we're going to pretend to be hopping channels every few seconds,
    # going through a brief 2 second "transitioniong" presentationStatus

    ciiServer.updateClients(sendOnlyDiff=True)
    try:
        while True:
            for contentId in dummyContentIds:
                ciiServer.cii.contentId = contentId
                ciiServer.cii.contentIdStatus = "final"
                ciiServer.cii.presentationStatus = ["transitioning"]
                ciiServer.updateClients(sendOnlyDiff=True)

                time.sleep(2)
                ciiServer.cii.contentIdStatus = "final"
                ciiServer.cii.presentationStatus = ["okay"]
                ciiServer.updateClients(sendOnlyDiff=True)

                time.sleep(5)
    except KeyboardInterrupt:
        pass
    finally:
        cherrypy.engine.exit()
Exemple #12
0
 def run(self):
     monotonic_time.sleep(self.sleepArg)
Exemple #13
0
    if args.quiet:
        logging.disable(logging.CRITICAL)
    else:
        logging.basicConfig(level=args.loglevel[0])

    cii = CIIClient(ciiUrl)

    # logger for outputting messages
    ciiClientLogger = logging.getLogger("CIIClient")

    # attach callbacks to generate notifications
    cii.onConnected = makeCallback("connected")
    cii.onDisconnected = makeCallback("disconnected")
    cii.onError = makeCallback("error")

    for name in CII.allProperties():
        funcname = "on" + name[0].upper() + name[1:] + "Change"
        callback = makePropertyChangeCallback(name)
        setattr(cii, funcname, callback)

    # specific handler for when a CII 'change' notification callback fires
    def onChange(changes):
        ciiClientLogger.info("CII is now: " + str(cii.cii))

    cii.onChange = onChange

    # connect and goto sleep. All callback activity happens in the websocket's own thread
    cii.connect()
    while True:
        time.sleep(1)
Exemple #14
0
    if args.quiet:
        logging.disable(logging.CRITICAL)
    else:
        logging.basicConfig(level=args.loglevel[0])

    #first we'll create a clock to represent the wall clock
    sysclock = SysClock(tickRate=1000000000)
    wallClock = CorrelatedClock(sysclock, tickRate=1000000000)

    # we'll also create the algorithm object that adjusts the clock and controls
    # how often requests are made to the server.
    algorithm = LowestDispersionCandidate(wallClock,
                                          repeatSecs=1,
                                          timeoutSecs=0.5)

    # finally we create the client and start it.
    wc_client = WallClockClient(bind, dest, wallClock, algorithm)
    wc_client.start()

    n = 0
    while True:
        time.sleep(0.2)
        print "Time=%20d microseconds. Dispersion = %15.3f milliseconds" % (
            wallClock.ticks * 1000000 / wallClock.tickRate,
            wc_client.algorithm.getCurrentDispersion() / 1000000)
        n = n + 1
        if n >= 25:
            print "*** Worst dispersion over previous 5 seconds = %15.3f milliseconds" % (
                wc_client.algorithm.getWorstDispersion() / 1000000)
            n = 0
Exemple #15
0
def FilterAndPredict(clock,repeatSecs=1.0,timeoutSecs=0.2,filters=[],predictor=PredictSimple()):
    """\
    Combines zero, one or more Filters and a Predictor and returns an algorithm for a WallClockClient.
    
    :param clock: A :class:`~dvbcss.clock.CorrelatedClock` object that will be adjusted to match the Wall Clock.
    :param repeatSecs: (:class:`float`) The rate at which Wall Clock protocol requests are to be sent (in seconds).
    :param timeoutSecs: (:class:`float`) The timeout on waiting for responses to requests (in seconds).
    :param filters: (:class:`list` of Filters) A list of zero, one or more Filters
    :param predictor: (Predictor) The Predictor to use.
    
    :returns: An algorithm object embodying the filtering and prediction process, that is suitable to be passed to a
            :class:`~dvbcss.protocol.client.wc.WallClockClient`.
    
    This algorithm controls the :class:`~dvbcss.clock.CorrelatedClock` object by settings its
    :data:`~dvbcss.clock.CorrelatedClock.correlation` property to (0,offset) where `offset` is provided by the
    predictor. The parent of this clock is the clock used by the :class:`~dvbcss.protocol.client.wc.WallClockClient`
    in generating the measurement candidates. So the job of the predictor is always to estimate the current absolute
    offset between that clock and the wall clock of the server.
    
    Requests are made at the repetition rate specified. If a response is received within the timeout period it
    is then it is transformed into a measurement candidate and passed to the filters.
    Filters are applied in the order you list them. If a candidate survives filtering, then it is passed to the
    predictor. Every time a candidate is provided to the predictor, the offset returned by the predictor replaces
    the previous offset.
    
    .. note:: The Clock object must be :mod:`~dvbcss.clock.CorrelatedClock` whose parent is the clock object
              provided to the WallClockClient object with which this algorithm is used.
              
              *It must not be the same clock object.* However both must have
              the same tick rate. If the same clock object is used or different tick rates are used then
              the Wall Clock will not synchronise correctly..
    
    The tick rate of the Clock can be any tick rate (it does not have to be one tick per nanosecond),
    but too low a tick rate will limit clock synchronisation precision.
    
    
    """
    log=logging.getLogger("dvbcss.protocol.client.wc.algorithm.FilterAndPredict")
    prevOffset=0
    while True:
        candidate=(yield timeoutSecs)
        if candidate is not None:
            
            # apply filters
            if None in [f.checkCandidate(candidate['nanos']) for f in filters]:
                log.debug("Candidate filtered out\n")
                time.sleep(repeatSecs)
            else:
                
                # filters passed, so now feed the candidate into the predictor
                # and retrieve a new estimate of the offset
                predictor.addCandidate(candidate['nanos'])
                offsetNanos=predictor.predictOffset()
                offsetTicks=round(offsetNanos * clock.tickRate / 1000000000.0)

                # act on it
                log.debug("Candidate accepted. Predicted offset (ticks)=%20d   delta (ticks)=%20d\n" % (offsetTicks, offsetTicks-prevOffset))
                clock.correlation=(0,offsetTicks)
                prevOffset=offsetTicks

                time.sleep(repeatSecs)
        else:
            log.debug("Response timeout\n")
Exemple #16
0
        timelines = [
            TimelineOption("urn:dvb:css:timeline:pts", unitsPerTick=1, unitsPerSecond=90000),
            TimelineOption("urn:dvb:css:timeline:temi:1:1", unitsPerTick=1, unitsPerSecond=50)
        ]
    )

    ptsTimeline = CorrelatedClock(parentClock=wallClock, tickRate=90000, correlation=(wallClock.ticks, 0))
    temiTimeline = CorrelatedClock(parentClock=ptsTimeline, tickRate=50, correlation=(0,0))

    ptsSource = SimpleClockTimelineSource("urn:dvb:css:timeline:pts", wallClock=wallClock, clock=ptsTimeline, speedSource=ptsTimeline)
    temiSource = SimpleClockTimelineSource("urn:dvb:css:timeline:temi:1:1", wallClock=wallClock, clock=temiTimeline, speedSource=ptsTimeline)
    
    tsServer.attachTimelineSource(ptsSource)
    tsServer.attachTimelineSource(temiSource)
    
    wcServer.start()
    
    cherrypy.engine.start()

    try:
        while True:
            time.sleep(1)

    except KeyboardInterrupt:
        pass
    finally:
        cherrypy.engine.exit()
        wcServer.stop()
    
      
Exemple #17
0
    print "Connecting, requesting timeline for:"
    print "   Any contentId beginning with:",contentIdStem
    print "   and using timeline selector: ",timelineSelector
    print

    ts = TSClientClockController(tsUrl, contentIdStem, timelineSelector, timelineClock, correlationChangeThresholdSecs=0.001)
    
    exiting=False
    tsClientLogger = logging.getLogger("TSClient")
    def reportCallback(msg,exit=False):
        def callback(*a,**k):
            global exiting
            tsClientLogger.info(msg+"\n")
            if exit:
                exiting=True
                wc_client.stop()
                sys.exit(0)
        return callback
    
    ts.onConnected           = reportCallback("connected")
    ts.onDisconnected        = reportCallback("disconnected",exit=True)
    ts.onTimelineAvailable   = reportCallback("timeline became available")
    ts.onTimelineUnavailable = reportCallback("timeline became un-available")
    ts.onTimingChange        = reportCallback("change in timing and/or play speed")
    
    ts.connect()
    while not exiting:
        time.sleep(0.4)
        print ts.getStatusSummary(),
        print "   Uncertainty (dispersion) = +/- %0.3f milliseconds" % (algorithm.getCurrentDispersion()/1000000.0)
Exemple #18
0
    print "Will double clock speed halfway through"

    threading.Thread(target=threadrun).start()
    sleepUntil(tClock, tClock.ticks + 500)
    tClock.speed = 2
    print "Speed doubled"
    sleepUntil(tClock, tClock.ticks + 600)

    def go(message):
        print "Scheduled task ran. Message was: " + message

    print "Scheduling call back in 2 seconds..."
    args = ["huzzah!"]
    runAt(tClock, tClock.ticks + 400, go, args)

    time.sleep(5)

    print "Now same again, but with all callbacks scheduled in advance"
    tClock.slew = 0

    def doAdjust(amount):
        tClock.slew = amount
        print "Adjusted tClock frequency by +100 Hz"

    now = tClock.ticks
    for i in range(1, 11):
        args = ["Tick " + str(100 * i)]
        runAt(tClock, now + 100 * i, go, args)

    args = [100]
    runAt(tClock, now + 500, doAdjust, args)
Exemple #19
0
    print "Connecting, requesting timeline for:"
    print "   Any contentId beginning with:",contentIdStem
    print "   and using timeline selector: ",timelineSelector
    print

    ts = TSClientClockController(tsUrl, contentIdStem, timelineSelector, timelineClock, correlationChangeThresholdSecs=0.001)
    
    exiting=False
    tsClientLogger = logging.getLogger("TSClient")
    def reportCallback(msg,exit=False):
        def callback(*a,**k):
            global exiting
            tsClientLogger.info(msg+"\n")
            if exit:
                exiting=True
                wc_client.stop()
                sys.exit(0)
        return callback
    
    ts.onConnected           = reportCallback("connected")
    ts.onDisconnected        = reportCallback("disconnected",exit=True)
    ts.onTimelineAvailable   = reportCallback("timeline became available")
    ts.onTimelineUnavailable = reportCallback("timeline became un-available")
    ts.onTimingChange        = reportCallback("change in timing and/or play speed")
    
    ts.connect()
    while not exiting:
        time.sleep(0.4)
        print ts.getStatusSummary(),
        print "   Uncertainty (dispersion) = +/- %0.3f milliseconds" % (algorithm.getCurrentDispersion()/1000000.0)