Timer-Daten



Jede Timer-Message transportiert die Timer-Eckdaten

Timer-Messages transportieren ihre eigenen Eckdaten. Diese können mit einer vordefinierten statischen Zugriffsklasse ausgelesen werden (CRecordTimer).

Wir verwenden dieses mal einen vordefinierten Timer:

<record id="bfd95823-d4f2-43bf-aa51-97e9bef28bc3" name="TIMER_TARGET_013">
    
    <description>
        A Timer for Target013 without data
    </description>
    
</record>
final class CTarget013 extends CTarget
{
    private static final long TIMEOUT = 7000L;

    CTarget013()
    {
        addMessageHandler(CRecordStartTarget.ID, new IMessageHandler()
        {
            @Override
            public boolean handleMessage(final CEnvelope aEnvelope,
                                         final CRecord aRecord) throws Exception
            {

                getKernel().getNameDb().getTargetNameDb().putName(getAddress(), "Target003");

                getTimerManager().startTimer(CRecordTimerTarget013.ID, getAddress(), TIMEOUT, false, null);

                aEnvelope.setResult(null);
                return true;
            }

        });

        addMessageHandler(CRecordTimerTarget013.ID, new IMessageHandler()
        {
            @Override
            public boolean handleMessage(final CEnvelope aEnvelope,
                                         final CRecord aRecord) throws Exception
            {
                getTimerManager().startTimer(CRecordTimerTarget013.ID, getAddress(), TIMEOUT, false, null);

                // Timers always have some payload. You can access this with usage of the CRecordTimer record helper.
                final long counter = CRecordTimer.getParamCounter(aRecord, 0);
                CConstants.LOG.trace("TimerTarget013 counter = {}", counter);

                final ITargetAddress owner = CRecordTimer.getParamOwner(aRecord, null);
                CConstants.LOG.trace("TimerTarget013 owner = {}", owner);

                final boolean repeatedTimer = CRecordTimer.getParamRepeatedTimer(aRecord, false);
                CConstants.LOG.trace("TimerTarget013 repeat = {}", repeatedTimer);

                final long timeout = CRecordTimer.getParamTimeout(aRecord, 0);
                CConstants.LOG.trace("TimerTarget013 timeout = {}", timeout);

                // The handle of the timer is returned from the method startTimer(..).
                // It is used to stop or retrigger the timer.
                final long handle = CRecordTimer.getParamTimerHandle(aRecord, 0);
                CConstants.LOG.trace("TimerTarget013 handle = {}", handle);

                aEnvelope.setResult(null);
                return true;
            }

        });
    }
}

Auf den ersten Blick macht es kaum Sinn, für einen Timer ohne eigene Daten eine Zugriffsklasse zu definieren. Schließlich verwenden wir hier lediglich die ID der Klasse CRecordTimerTarget013. Der tiefere Sinn ergibt sich aber dann, wenn man die lokale Message-Sequenz im Sequenz-Monitor anschaut. Dort sieht man dann, dass dieser Timer im Gegensatz zu den Timern in Target011 und Target012 einen Namen besitzt. Die Record-Beschreibungen werden nämlich beim Laden des PlugIns gelesen und u.a. in die Namens-Datenbanken eingetragen. Das ist auch der Grund, warum wir im StartTarget-Handler einen Namen für das Target registrieren.

Wir sehen hier außerdem, dass im Timer-Handler mit einer unbekannten Zugriffsklasse Daten aus dem Record geholt und angezeigt werden. Es handelt sich um die systemeigene Klasse CRecordTimer. Diese Klasse verwendet UUIDs für die SlotKeys, damit sie nicht mit anderen Zugriffsklassen kollidieren. So kann man leicht in einem Record die Daten von mehreren verschiedenen Records transportieren.

Bei den Daten handelt es sich um die Eckdaten des Timers. Besonders erwähnenswert ist hier der Counter (wie oft der Timer schon Messages gesandt hat) sowie das Timer-Handle, welches zum Stoppen oder Retriggern eines Timers verwenden kann.

Diese Beispiele findest du im Projekt D1ExamplesNode001 im package de.softdevel.d1.examples.node001.example002.