Index: trunk/FACT++/src/RemoteControl.h
===================================================================
--- trunk/FACT++/src/RemoteControl.h	(revision 13837)
+++ trunk/FACT++/src/RemoteControl.h	(revision 13838)
@@ -119,12 +119,19 @@
     }
 
-    void infoHandler()
-    {
-        RemoteControlImp::infoHandler();
-        if (!fCurrentServer.empty() && !HasServer(fCurrentServer))
+    void RemoveServer(std::string s)
+    {
+        DimNetwork::RemoveServer(s);
+        if (fCurrentServer==s)
         {
             fCurrentServer = "";
             T::UpdatePrompt();
         }
+    }
+
+    void RemoveAllServers()
+    {
+        DimNetwork::RemoveAllServers();
+        fCurrentServer = "";
+        T::UpdatePrompt();
     }
 
Index: trunk/FACT++/src/datalogger.cc
===================================================================
--- trunk/FACT++/src/datalogger.cc	(revision 13837)
+++ trunk/FACT++/src/datalogger.cc	(revision 13838)
@@ -196,5 +196,5 @@
 };
 
-class DataLogger : public StateMachineDim, DimServiceInfoList
+class DataLogger : public StateMachineDim, DimServiceInfoListImp
 {
 public:
@@ -262,27 +262,27 @@
      ***************************************************/
     ///Reporting method for the services info received
-    void ReportPlease(DimInfo* I, SubscriptionType& sub);  
+    void Report(DimInfo* I, SubscriptionType& sub);
 
     ///Configuration of the nightly file path
     int ConfigureFilePath(const Event& evt);
     ///print the current state of the dataLogger
-    int PrintStatePlease(const Event& evt);
+    int PrintState(const Event& evt);
     ///checks whether or not the current info being treated is a run number
     void CheckForRunNumber(DimInfo* I);
     /// start transition
-    int StartPlease(); 
+    int Start();
     ///from waiting to logging transition
-    //int StartRunPlease();
+    //int StartRun();
     // from logging to waiting transition
     int StopRunLogging();
     ///stop and reset transition
-    int GoToReadyPlease(); 
+    int GoToReady();
     ///from NightlyOpen to waiting transition
-    int NightlyToWaitRunPlease(); 
+    int NightlyToWaitRun();
     ///from wait for run number to nightly open
-    int BackToNightlyOpenPlease();
+    int BackToNightlyOpen();
 #ifdef HAVE_FITS
     ///Open fits files
-    void OpenFITSFilesPlease(SubscriptionType& sub, RunNumberType* cRunNumber);
+    void OpenFITSFiles(SubscriptionType& sub, RunNumberType* cRunNumber);
     ///Write data to FITS files
     void WriteToFITS(SubscriptionType& sub);
@@ -355,7 +355,7 @@
     bool ShouldSubscribe(const string& server, const string& service);
     ///Subscribe to a given server and service
-    DimStampedInfo* SubscribeToPlease(const string& server, const string& service);
+    DimStampedInfo* SubscribeTo(const string& server, const string& service);
     ///Open a text file and checks for ofstream status
-    bool OpenTextFilePlease(ofstream& stream, const string& name);
+    bool OpenTextFile(ofstream& stream, const string& name);
     ///Checks if the input osftream is in error state, and if so close it.
     bool CheckForOfstreamError(ofstream& out, bool isDailyStream);
@@ -370,5 +370,5 @@
     bool CreateDirectory(string path);
     /***************************************************
-    * INHERITED FROM DIMSERVICEINFOLIST
+    * INHERITED FROM DimServiceInfoList
     ***************************************************/
     ///Add a new service subscription
@@ -480,5 +480,5 @@
     }
 
-    list[service].dimInfo.reset(SubscribeToPlease(server, service));
+    list[service].dimInfo.reset(SubscribeTo(server, service));
     list[service].server  = server;
     list[service].service = service;
@@ -615,5 +615,5 @@
 //! @name the file name
 //
-bool DataLogger::OpenTextFilePlease(ofstream& stream, const string& name)
+bool DataLogger::OpenTextFile(ofstream& stream, const string& name)
 {
     return OpenStreamImp(stream, name, true);
@@ -626,5 +626,5 @@
 //! @param service the service name
 //
-DimStampedInfo* DataLogger::SubscribeToPlease(const string& server, const string& service)
+DimStampedInfo* DataLogger::SubscribeTo(const string& server, const string& service)
 {
     if (fDebugIsOn)
@@ -780,14 +780,14 @@
 
     // Add the possible transitions for this machine
-    AddEvent(kSM_NightlyOpen, "START", kSM_Ready, kSM_BadFolder)
-        (bind(&DataLogger::StartPlease, this))
+    AddEvent("START", kSM_Ready, kSM_BadFolder)
+        (bind(&DataLogger::Start, this))
         ("Start the nightly logging. Nightly file location must be specified already");
 
-    AddEvent(kSM_Ready, "STOP", kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging, kSM_DailyWriteError, kSM_RunWriteError)
-        (bind(&DataLogger::GoToReadyPlease, this))
+    AddEvent("STOP", kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging, kSM_DailyWriteError, kSM_RunWriteError)
+        (bind(&DataLogger::GoToReady, this))
         ("Stop all data logging, close all files.");
 /*
     AddEvent(kSM_Logging, "START_RUN", kSM_WaitingRun, kSM_BadRunConfig)
-        (bind(&DataLogger::StartRunPlease, this))
+        (bind(&DataLogger::StartRun, this))
         ("Start the run logging. Run file location must be specified already.");
 
@@ -796,14 +796,14 @@
         ("Wait for a run to be started, open run-files as soon as a run number arrives.");
 */
-    AddEvent(kSM_Ready, "RESET", kSM_Error, kSM_BadFolder, kSM_DailyWriteError, kSM_RunWriteError)
-        (bind(&DataLogger::GoToReadyPlease, this))
+    AddEvent("RESET", kSM_Error, kSM_BadFolder, kSM_DailyWriteError, kSM_RunWriteError)
+        (bind(&DataLogger::GoToReady, this))
         ("Transition to exit error states. Closes the any open file.");
 
-    AddEvent(kSM_WaitingRun, "START_RUN_LOGGING", /*kSM_Logging,*/ kSM_NightlyOpen, kSM_Ready)
-        (bind(&DataLogger::NightlyToWaitRunPlease, this))
+    AddEvent("START_RUN_LOGGING", /*kSM_Logging,*/ kSM_NightlyOpen, kSM_Ready)
+        (bind(&DataLogger::NightlyToWaitRun, this))
         ("Go to waiting for run number state. In this state with any received run-number a new file is opened.");
 
-    AddEvent(kSM_NightlyOpen, "STOP_RUN_LOGGING", kSM_WaitingRun, kSM_Logging)
-        (bind(&DataLogger::BackToNightlyOpenPlease, this))
+    AddEvent("STOP_RUN_LOGGING", kSM_WaitingRun, kSM_Logging)
+        (bind(&DataLogger::BackToNightlyOpen, this))
         ("Go from the wait for run to nightly open state.");
 
@@ -822,5 +822,5 @@
      // Provide a print command
      AddEvent("PRINT_INFO")
-            (bind(&DataLogger::PrintStatePlease, this, placeholders::_1))
+            (bind(&DataLogger::PrintState, this, placeholders::_1))
             ("Print information about the internal status of the data logger.");
 
@@ -931,5 +931,5 @@
     }
     //go to the ready state. i.e. close all files, run-wise first
-    GoToReadyPlease();
+    GoToReady();
 
 
@@ -944,5 +944,5 @@
  //       messageBackup.reset();
 
-    if (fNightlyLogFile.is_open())//this file is the only one that has not been closed by GoToReadyPlease
+    if (fNightlyLogFile.is_open())//this file is the only one that has not been closed by GoToReady
     {
 //        dim_lock();
@@ -982,5 +982,5 @@
     {
         fAutoStarted = true;
-        SetCurrentState(StartPlease());
+        SetCurrentState(Start());
     }
     else {if (GetCurrentState() > kSM_Ready)
@@ -1009,8 +1009,6 @@
     }
     if (!found)
-    {
-        DimServiceInfoList::infoHandler();
         return;
-    }
+
     if (I->getSize() <= 0 || I->getData()==NULL)
     {
@@ -1040,5 +1038,5 @@
     CheckForRunNumber(I);
 
-    ReportPlease(I, y->second);
+    Report(I, y->second);
 
     //remove old run numbers
@@ -1167,5 +1165,5 @@
 //!        The dataLogger's subscription corresponding to this DimInfo
 //
-void DataLogger::ReportPlease(DimInfo* I, SubscriptionType& sub)
+void DataLogger::Report(DimInfo* I, SubscriptionType& sub)
 {
     const string fmt(I->getFormat());
@@ -1236,7 +1234,7 @@
 
         fFullNightlyLogFileName = CompileFileNameWithPath(fFilePath, "", "log");
-        if (!OpenTextFilePlease(fNightlyLogFile, fFullNightlyLogFileName))
-        {
-            GoToReadyPlease();
+        if (!OpenTextFile(fNightlyLogFile, fFullNightlyLogFileName))
+        {
+            GoToReady();
             SetCurrentState(kSM_BadFolder);
             return;
@@ -1245,7 +1243,7 @@
 
         fFullNightlyReportFileName = CompileFileNameWithPath(fFilePath, "", "rep");
-        if (!OpenTextFilePlease(fNightlyReportFile, fFullNightlyReportFileName))
-        {
-            GoToReadyPlease();
+        if (!OpenTextFile(fNightlyReportFile, fFullNightlyReportFileName))
+        {
+            GoToReady();
             SetCurrentState(kSM_BadFolder);
             return;
@@ -1377,5 +1375,5 @@
         if (!sub.nightlyFile.IsOpen() || !sub.runFile.IsOpen() || sub.runNumber != sub.runFile.fRunNumber)
             if (GetCurrentState() != kSM_Ready)
-                OpenFITSFilesPlease(sub, cRunNumber);
+                OpenFITSFiles(sub, cRunNumber);
         WriteToFITS(sub);
 #endif
@@ -1427,5 +1425,5 @@
         if (!sub.nightlyFile.IsOpen() || !sub.runFile.IsOpen() || sub.runNumber != sub.runFile.fRunNumber)
             if (GetCurrentState() != kSM_Ready)
-                OpenFITSFilesPlease(sub, cRunNumber);
+                OpenFITSFiles(sub, cRunNumber);
         WriteToFITS(sub);
     }
@@ -1441,5 +1439,5 @@
 //!        the new state. Which, in that case, is the current state
 //!
-int DataLogger::PrintStatePlease(const Event& )
+int DataLogger::PrintState(const Event& )
 {
     Message("------------------------------------------");
@@ -1738,5 +1736,5 @@
 //! @returns 
 //!        kSM_NightlyOpen if success, kSM_BadFolder if failure
-int DataLogger::StartPlease()
+int DataLogger::Start()
 {
     if (fDebugIsOn)
@@ -1746,5 +1744,5 @@
     fFullNightlyLogFileName = CompileFileNameWithPath(fFilePath, "", "log");
     bool nightlyLogOpen = fNightlyLogFile.is_open();
-    if (!OpenTextFilePlease(fNightlyLogFile, fFullNightlyLogFileName))
+    if (!OpenTextFile(fNightlyLogFile, fFullNightlyLogFileName))
         return kSM_BadFolder;
     if (!nightlyLogOpen)
@@ -1752,5 +1750,5 @@
 
     fFullNightlyReportFileName = CompileFileNameWithPath(fFilePath, "", "rep");
-    if (!OpenTextFilePlease(fNightlyReportFile, fFullNightlyReportFileName))
+    if (!OpenTextFile(fNightlyReportFile, fFullNightlyReportFileName))
     {
         fNightlyLogFile.close();
@@ -1776,5 +1774,5 @@
 //! @param sub
 //!     the current DimInfo subscription being examined
-void DataLogger::OpenFITSFilesPlease(SubscriptionType& sub, RunNumberType* cRunNumber)
+void DataLogger::OpenFITSFiles(SubscriptionType& sub, RunNumberType* cRunNumber)
 {
     string serviceName(sub.dimInfo->getName());
@@ -1993,5 +1991,5 @@
 //! @returns
 //!        kSM_Logging if success, kSM_BadRunConfig if failure.
-int DataLogger::StartRunPlease()
+int DataLogger::StartRun()
 {
     if (fDebugIsOn)
@@ -2003,5 +2001,5 @@
         if (OpenRunFile(*it) != 0)
         {
-            StopRunPlease();
+            StopRun();
             return kSM_BadRunConfig;
         }
@@ -2219,5 +2217,5 @@
 //! @returns
 //!     kSM_Ready
-int DataLogger::GoToReadyPlease()
+int DataLogger::GoToReady()
 {
    if (fDebugIsOn)
@@ -2264,5 +2262,5 @@
 //!    @returns
 //!        kSM_WaitingRun or kSM_BadFolder
-int DataLogger::NightlyToWaitRunPlease()
+int DataLogger::NightlyToWaitRun()
 {
     int cState = GetCurrentState();
@@ -2272,5 +2270,5 @@
 
     if (cState == kSM_Ready)
-        cState = StartPlease();
+        cState = Start();
 
     if (cState != kSM_NightlyOpen)
@@ -2289,5 +2287,5 @@
 //!    @returns
 //!        kSM_WaitingRun
-int DataLogger::BackToNightlyOpenPlease()
+int DataLogger::BackToNightlyOpen()
 {
     if (GetCurrentState()==kSM_Logging)
@@ -2349,5 +2347,5 @@
          fFilePath = folder;
          fFullNightlyLogFileName = CompileFileNameWithPath(fFilePath, "", "log");
-         if (!OpenTextFilePlease(fNightlyLogFile, fFullNightlyLogFileName))
+         if (!OpenTextFile(fNightlyLogFile, fFullNightlyLogFileName))
              return 3;
 
Index: trunk/FACT++/src/feedback.cc
===================================================================
--- trunk/FACT++/src/feedback.cc	(revision 13837)
+++ trunk/FACT++/src/feedback.cc	(revision 13838)
@@ -28,21 +28,10 @@
 
 #include "DimDescriptionService.h"
+#include "DimState.h"
 
 // ------------------------------------------------------------------------
 
-class StateMachineFeedback : public StateMachineDim, public DimInfoHandler
+class StateMachineFeedback : public StateMachineDim
 {
-    /*
-    int Wrap(boost::function<void()> f)
-    {
-        f();
-        return T::GetCurrentState();
-    }
-
-    boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
-    {
-        return bind(&StateMachineMCP::Wrap, this, func);
-    }*/
-
 private:
     enum states_t
@@ -76,20 +65,10 @@
     PixelMap fMap;
 
-    DimServiceInfoList fNetwork;
-
-    pair<Time, int> fStatusDim;
-    pair<Time, int> fStatusFAD;
-    pair<Time, int> fStatusFSC;
-    pair<Time, int> fStatusBias;
-
-    DimStampedInfo fDim;
-    DimStampedInfo fFAD;
-    DimStampedInfo fFSC;
-    DimStampedInfo fBias;
-    DimStampedInfo fBiasA;
-
-    DimStampedInfo fBiasData;
-    DimStampedInfo fBiasNom;
-    DimStampedInfo fCameraTemp;
+    DimServiceInfoListImp fNetwork;
+
+    DimVersion fDim;
+    DimState   fDimFAD;
+    DimState   fDimFSC;
+    DimState   fDimBias;
 
     DimDescribedService fDimReference;
@@ -133,22 +112,13 @@
     bool fOutputEnabled;
 
-    pair<Time, int> GetNewState(DimStampedInfo &info) const
-    {
-        const bool disconnected = info.getSize()==0;
-
-        // Make sure getTimestamp is called _before_ getTimestampMillisecs
-        const int tsec = info.getTimestamp();
-        const int tms  = info.getTimestampMillisecs();
-
-        return make_pair(Time(tsec, tms*1000),
-                         disconnected ? -2 : info.getQuality());
-    }
-
-    void HandleCameraTemp()
-    {
-        if (fCameraTemp.getSize()!=60*sizeof(float))
-            return;
-
-        const float *ptr = static_cast<float*>(fCameraTemp.getData());
+    int HandleCameraTemp(const EventImp &evt)
+    {
+        if (fControlType!=kTemp && fControlType!=kCurrents)
+            return GetCurrentState();
+
+        if (evt.GetSize()!=60*sizeof(float))
+            return GetCurrentState();
+
+        const float *ptr = evt.Ptr<float>();
 
         double avgt = 0;
@@ -164,5 +134,5 @@
         {
             Warn("Received sensor temperatures all invalid.");
-            return;
+            return GetCurrentState();
         }
 
@@ -177,5 +147,5 @@
             Warn("Trying to calibrate above G-APD breakdown volatge!");
             Warn(msg);
-            return;
+            return GetCurrentState();
         }
 
@@ -206,5 +176,5 @@
             {
                 //DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
-                return;
+                return GetCurrentState();
             }
 
@@ -275,4 +245,13 @@
                 vec[i+BIAS::kNumChannels] += dU;
 
+                // Angelegte Spannung:    U0+dU
+                // Gemessener Strom:      Im - Iavg
+                // Strom offset:          (U0+dU) / Ravg
+                // Fliessender Strom:     Im-Iavg - (U0+dU)/Ravg
+                // Korrektur:             [ Im-Iavg - (U0+dU)/Ravg ] * Rg
+
+                // Aufgeloest nach dU:    dU =  ( Im-Iavg - dU/Ravg ) / ( 1/Rg + 1/Ravg )
+                // Equivalent zu:         dU  = ( I*Ravg - U0 ) / ( Ravg/Rg+1 )
+
                 // Calculate statistics only for channels with a valid calibration
                 if (Iavg[i]>0)
@@ -299,6 +278,6 @@
         fDimDeviation.Update(vec);
 
-        if (!fOutputEnabled || fStatusBias.second!=BIAS::kVoltageOn)
-            return;
+        if (!fOutputEnabled || fDimBias.state()!=BIAS::kVoltageOn)
+            return GetCurrentState();
 
         // Trigger calibration
@@ -306,5 +285,5 @@
         {
             DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
-            return;
+            return GetCurrentState();
         }
 
@@ -336,12 +315,14 @@
 
         fCursorTemp++;
-    }
-
-    int AverageCurrents()
-    {
-        if (fBiasA.getSize()!=BIAS::kNumChannels*sizeof(int16_t))
+
+        return GetCurrentState();
+    }
+
+    int AverageCurrents(const EventImp &evt)
+    {
+        if (evt.GetSize()!=BIAS::kNumChannels*sizeof(int16_t))
             return -1;
 
-        if (fStatusBias.second!=BIAS::kVoltageOn)
+        if (fDimBias.state()!=BIAS::kVoltageOn)
             return false;
 
@@ -349,5 +330,5 @@
             return true;
 
-        const int16_t *ptr = static_cast<int16_t*>(fBiasA.getData());
+        const int16_t *ptr = evt.Ptr<int16_t>();
 
         for (int i=0; i<BIAS::kNumChannels; i++)
@@ -361,7 +342,7 @@
 
 
-    void HandleCalibration()
-    {
-        const int rc = AverageCurrents();
+    void HandleCalibration(const EventImp &evt)
+    {
+        const int rc = AverageCurrents(evt);
         if (rc<0)
             return;
@@ -369,5 +350,5 @@
         if (fCursorCur<fNumCalibRequests)
         {
-            if (fStatusBias.second==BIAS::kVoltageOn)
+            if (fDimBias.state()==BIAS::kVoltageOn)
                 DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
             return;
@@ -401,20 +382,16 @@
         Info("Calibration successfully done.");
 
-        if (fStatusBias.second==BIAS::kVoltageOn)
+        if (fDimBias.state()==BIAS::kVoltageOn)
             DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
     }
 
-    void HandleFeedback()
-    {
-        if (fBiasData.getSize()!=1440*sizeof(float))
+    void HandleFeedback(const EventImp &evt)
+    {
+        if (evt.GetSize()!=1440*sizeof(float))
             return;
 
         // -------- Check age of last stored event --------
 
-        // Must be called in this order
-        const int tsec = fBiasData.getTimestamp();
-        const int tms  = fBiasData.getTimestampMillisecs();
-
-        const Time tm(tsec, tms*1000);
+        const Time tm(evt.GetTime());
 
         if (Time()-fBiasLast>boost::posix_time::seconds(30))
@@ -427,7 +404,5 @@
         // -------- Store new event --------
 
-        fData[fCursorAmpl%fData.size()].assign(reinterpret_cast<float*>(fBiasData.getData()),
-                                               reinterpret_cast<float*>(fBiasData.getData())+1440);
-
+        fData[fCursorAmpl%fData.size()].assign(evt.Ptr<float>(), evt.Ptr<float>()+1440);
         if (++fCursorAmpl<fData.size())
             return;
@@ -610,5 +585,5 @@
         fDimDeviation.Update(vec);
 
-        if (!fOutputEnabled || fStatusBias.second!=BIAS::kVoltageOn)
+        if (!fOutputEnabled || fDimBias.state()!=BIAS::kVoltageOn)
             return;
 
@@ -619,13 +594,12 @@
     }
 
-    void HandleGlobalFeedback()
-    {
-        if (fBiasData.getSize()!=1440*sizeof(float))
+    void HandleGlobalFeedback(const EventImp &evt)
+    {
+        if (evt.GetSize()!=1440*sizeof(float))
             return;
 
         // -------- Store new event --------
 
-        vector<float> arr(reinterpret_cast<float*>(fBiasData.getData()),
-                          reinterpret_cast<float*>(fBiasData.getData())+1440);
+        vector<float> arr(evt.Ptr<float>(), evt.Ptr<float>()+1440);
 
         sort(arr.begin(), arr.end());
@@ -744,5 +718,5 @@
         fDimDeviation.Update(vec);
 
-        if (!fOutputEnabled || fStatusBias.second!=BIAS::kVoltageOn)
+        if (!fOutputEnabled || fDimBias.state()!=BIAS::kVoltageOn)
             return;
 
@@ -753,57 +727,33 @@
     }
 
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr)
-            return;
-
-        if (curr==&fBias)
-        {
-            fStatusBias = GetNewState(fBias);
-            return;
-        }
-
-        if (curr==&fFAD)
-        {
-            fStatusFAD = GetNewState(fFAD);
-            return;
-        }
-
-        if (curr==&fFSC)
-        {
-            fStatusFSC = GetNewState(fFSC);
-            return;
-        }
-
-        if (curr==&fDim)
-        {
-            fStatusDim = GetNewState(fDim);
-            fStatusDim.second = curr->getSize()==4 ? curr->getInt() : 0;
-            return;
-        }
-
-        if (curr==&fBiasNom)
-        {
-            const float *ptr = reinterpret_cast<float*>(fBiasNom.getData());
-            fVoltGapd.assign(ptr, ptr+416);
-            Info("Nominal bias voltages received.");
-            return;
-        }
-
-        if (curr==&fCameraTemp && (fControlType==kTemp || fControlType==kCurrents))
-            HandleCameraTemp();
-
-        if (curr==&fBiasA && fControlType==kTemp && GetCurrentState()==kStateCalibrating)
-            HandleCalibration();
-
-        if (curr==&fBiasA && (fControlType==kFeedbackGlobal || fControlType==kCurrents))
-            AverageCurrents();
-
-        if (curr==&fBiasData && fControlType==kFeedback)
-            HandleFeedback();
-
-        if (curr==&fBiasData && fControlType==kFeedbackGlobal)
-            HandleGlobalFeedback();
+    int HandleBiasCurrent(const EventImp &evt)
+    {
+        if (fControlType==kTemp && GetCurrentState()==kStateCalibrating)
+            HandleCalibration(evt);
+
+        if (fControlType==kFeedbackGlobal || fControlType==kCurrents)
+            AverageCurrents(evt);
+
+        return GetCurrentState();
+    }
+
+    int HandleBiasData(const EventImp &evt)
+    {
+        if (fControlType==kFeedback)
+            HandleFeedback(evt);
+
+        if (fControlType==kFeedbackGlobal)
+            HandleGlobalFeedback(evt);
+
+        return GetCurrentState();
+    }
+
+    int HandleBiasNom(const EventImp &evt)
+    {
+        fVoltGapd.assign(evt.Ptr<float>(), evt.Ptr<float>()+416);
+
+        Info("Nominal bias voltages received.");
+
+        return GetCurrentState();
     }
 
@@ -819,4 +769,39 @@
     }
 
+    const State GetState(const DimState &s) const
+    {
+        return fNetwork.GetState(s.name(), s.state());
+    }
+
+    void PrintState(const DimState &state) const
+    {
+        const State rc = GetState(state);
+
+        Out() << state.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << state.name() << ": ";
+        if (rc.index==-3)
+        {
+            Out() << kReset << "Offline" << endl;
+            return;
+        }
+        if (rc.index==-2)
+            Out() << state.state();
+        else
+            Out() << rc.name << "[" << rc.index << "]";
+        Out() << kReset << " - " << kBlue << rc.comment << endl;
+    }
+
+    int Print() const
+    {
+        Out() << fDim.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << "DIM_DNS: " << fDim.version() << endl;
+
+        PrintState(fDimFAD);
+        PrintState(fDimFSC);
+        PrintState(fDimBias);
+
+        return GetCurrentState();
+    }
+/*
     void PrintState(const pair<Time,int> &state, const char *server)
     {
@@ -844,5 +829,5 @@
         return GetCurrentState();
     }
-
+*/
     int PrintCalibration()
     {
@@ -886,7 +871,7 @@
     void WarnState(bool needfsc, bool needfad)
     {
-        const bool bias = fStatusBias.second >= BIAS::kConnecting;
-        const bool fsc  = fStatusFSC.second  >= 2;
-        const bool fad  = fStatusFAD.second  >= FAD::kConnected;
+        const bool bias = fDimBias.state() >= BIAS::kConnecting;
+        const bool fsc  = fDimFSC.state()  >= 2;
+        const bool fad  = fDimFAD.state()  >= FAD::kConnected;
 
         if (!bias)
@@ -1000,5 +985,5 @@
         Message(out);
 
-        if (fStatusBias.second==BIAS::kVoltageOn)
+        if (fDimBias.state()==BIAS::kVoltageOn)
             DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
 
@@ -1091,5 +1076,5 @@
 //            return kSM_FatalError;
 
-        if (fStatusBias.second==BIAS::kRamping)
+        if (fDimBias.state()==BIAS::kRamping)
         {
             Warn("Calibration cannot be started when biasctrl is in state Ramping.");
@@ -1143,10 +1128,10 @@
         //poll_one();
 
-        if (fStatusDim.second==0)
+        if (!fDim.online())
             return kStateDimNetworkNA;
 
-        const bool bias = fStatusBias.second >= BIAS::kConnecting;
-        const bool fad  = fStatusFAD.second  >= FAD::kConnected;
-        const bool fsc  = fStatusFSC.second  >= 2;
+        const bool bias = fDimBias.state() >= BIAS::kConnecting;
+        const bool fad  = fDimFAD.state()  >= FAD::kConnected;
+        const bool fsc  = fDimFSC.state()  >= 2;
 
         // All subsystems are not connected
@@ -1220,5 +1205,5 @@
                 if (fCurrentRequestInterval>0 && Time()-past>boost::posix_time::milliseconds(fCurrentRequestInterval))
                 {
-                    if (fStatusBias.second==BIAS::kVoltageOn)
+                    if (fDimBias.state()==BIAS::kVoltageOn)
                         DimClient::sendCommandNB("BIAS_CONTROL/REQUEST_STATUS", NULL, 0);
                     past = Time();
@@ -1240,15 +1225,9 @@
 public:
     StateMachineFeedback(ostream &out=cout) : StateMachineDim(out, "FEEDBACK"),
-        fStatusDim(make_pair(Time(), -2)),
-        fStatusFAD(make_pair(Time(), -2)),
-        fStatusBias(make_pair(Time(), -2)),
-        fDim("DIS_DNS/VERSION_NUMBER",  (void*)NULL, 0, this),
-        fFAD("FAD_CONTROL/STATE",       (void*)NULL, 0, this),
-        fFSC("FSC_CONTROL/STATE",       (void*)NULL, 0, this),
-        fBias("BIAS_CONTROL/STATE",     (void*)NULL, 0, this),
-        fBiasA("BIAS_CONTROL/CURRENT",  (void*)NULL, 0, this),
-        fBiasData("FAD_CONTROL/FEEDBACK_DATA", (void*)NULL, 0, this),
-        fBiasNom("BIAS_CONTROL/NOMINAL", (void*)NULL, 0, this),
-        fCameraTemp("FSC_CONTROL/TEMPERATURE", (void*)NULL, 0, this),
+        //---
+        fDimFAD("FAD_CONTROL"),
+        fDimFSC("FSC_CONTROL"),
+        fDimBias("BIAS_CONTROL"),
+        //---
         fDimReference("FEEDBACK/REFERENCE", "F:416",
                       "Amplitude reference value(s)"
@@ -1280,5 +1259,15 @@
         // deletion and creation of threads and more.
 
-//        fSP.resize(416);
+        fDim.Subscribe(*this);
+        fDimFAD.Subscribe(*this);
+        fDimFSC.Subscribe(*this);
+        fDimBias.Subscribe(*this);
+
+        Subscribe("BIAS_CONTROL/CURRENT")
+            (bind(&StateMachineFeedback::HandleBiasCurrent, this, placeholders::_1));
+        Subscribe("BIAS_CONTROL/FEEDBACK_DATA")
+            (bind(&StateMachineFeedback::HandleBiasData,    this, placeholders::_1));
+        Subscribe("FSC_CONTROL/TEMPERATURE")
+            (bind(&StateMachineFeedback::HandleCameraTemp,  this, placeholders::_1));
 
         // State names
Index: trunk/FACT++/src/logtime.cc
===================================================================
--- trunk/FACT++/src/logtime.cc	(revision 13837)
+++ trunk/FACT++/src/logtime.cc	(revision 13838)
@@ -14,4 +14,6 @@
     DimServer::start("TIME");
 
+
+
     // Some info on the console
     std::cout << "Offering TIME/MESSAGE...\n" << std::endl;
@@ -26,4 +28,17 @@
         // wait approximately one second
         usleep(1000000);
+
+        //std::cout << DimServer::getClientName() << std::endl;
+        //std::cout << DimServer::getClientId() << std::endl;
+        //std::cout << DimServer::getDnsPort() << std::endl;
+        std::cout << "con: " << dis_get_conn_id() << std::endl;
+
+        char **ids = DimServer::getClientServices();
+
+        while (*ids)
+        {
+            std::cout << *ids << std::endl;
+            ids++;
+        }
     }
 
Index: trunk/FACT++/src/mcp.cc
===================================================================
--- trunk/FACT++/src/mcp.cc	(revision 13837)
+++ trunk/FACT++/src/mcp.cc	(revision 13838)
@@ -26,21 +26,10 @@
 
 #include "DimDescriptionService.h"
+#include "DimState.h"
 
 // ------------------------------------------------------------------------
 
-class StateMachineMCP : public StateMachineDim, public DimInfoHandler
+class StateMachineMCP : public StateMachineDim
 {
-    /*
-    int Wrap(boost::function<void()> f)
-    {
-        f();
-        return T::GetCurrentState();
-    }
-
-    boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
-    {
-        return bind(&StateMachineMCP::Wrap, this, func);
-    }*/
-
 private:
     enum states_t
@@ -61,130 +50,59 @@
     };
 
-    DimServiceInfoList fNetwork;
-
-    pair<Time, int> fStatusDim;
-    pair<Time, int> fStatusFTM;
-    pair<Time, int> fStatusFAD;
-    pair<Time, int> fStatusLog;
-    pair<Time, int> fStatusRC;
-
-    DimStampedInfo fDim;
-    DimStampedInfo fFTM;
-    DimStampedInfo fFAD;
-    DimStampedInfo fLog;
-    DimStampedInfo fRC;
+    DimServiceInfoListImp fNetwork;
+
+    DimVersion fDim;
+    DimState   fDimFTM;
+    DimState   fDimFAD;
+    DimState   fDimLog;
+    DimState   fDimRC;
 
     DimDescribedService fService;
 
-    pair<Time, int> GetNewState(DimStampedInfo &info) const
-    {
-        const bool disconnected = info.getSize()==0;
-
-        // Make sure getTimestamp is called _before_ getTimestampMillisecs
-        const int tsec = info.getTimestamp();
-        const int tms  = info.getTimestampMillisecs();
-
-        return make_pair(Time(tsec, tms*1000),
-                         disconnected ? -2 : info.getQuality());
-    }
-
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr)
+    const State GetState(const DimState &s) const
+    {
+        return fNetwork.GetState(s.name(), s.state());
+    }
+
+    void PrintState(const DimState &state) const
+    {
+        const State rc = GetState(state);
+
+        Out() << state.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << state.name() << ": ";
+        if (rc.index==-3)
+        {
+            Out() << kReset << "Offline" << endl;
             return;
-
-        if (curr==&fFTM)
-        {
-            fStatusFTM = GetNewState(fFTM);
-            return;
-        }
-
-        if (curr==&fFAD)
-        {
-            fStatusFAD = GetNewState(fFAD);
-            return;
-        }
-
-        if (curr==&fLog)
-        {
-            fStatusLog = GetNewState(fLog);
-            return;
-        }
-
-        if (curr==&fRC)
-        {
-            fStatusRC = GetNewState(fRC);
-            return;
-        }
-
-        if (curr==&fDim)
-        {
-            fStatusDim = GetNewState(fDim);
-            fStatusDim.second = curr->getSize()==4 ? curr->getInt() : 0;
-            return;
-        }
-    }
-
-    bool CheckEventSize(size_t has, const char *name, size_t size)
-    {
-        if (has==size)
-            return true;
-
-        ostringstream msg;
-        msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
-        Fatal(msg);
-        return false;
-    }
-
-    int SetVerbosity(const EventImp &)
-    {
-        /*
-        if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
-            return T::kSM_FatalError;
-
-        fFSC.SetVerbose(evt.GetBool());
-
-        */
+        }
+        if (rc.index==-2)
+            Out() << state.state();
+        else
+            Out() << rc.name << "[" << rc.index << "]";
+        Out() << kReset << " - " << kBlue << rc.comment << endl;
+    }
+
+    int Print() const
+    {
+        Out() << fDim.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << "DIM_DNS: " << fDim.version() << endl;
+
+        PrintState(fDim);
+        PrintState(fDimFTM);
+        PrintState(fDimFAD);
+        PrintState(fDimLog);
+        PrintState(fDimRC);
 
         return GetCurrentState();
     }
 
-
-    void PrintState(const pair<Time,int> &state, const char *server)
-    {
-        const State rc = fNetwork.GetState(server, state.second);
-
-        Out() << state.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
-        Out() << kBold << server << ": ";
-        Out() << rc.name << "[" << rc.index << "]";
-        Out() << kReset << " - " << kBlue << rc.comment << endl;
-    }
-
-    int Print()
-    {
-        Out() << fStatusDim.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
-        Out() << kBold << "DIM_DNS: ";
-        if (fStatusDim.second==0)
-            Out() << "Offline" << endl;
-        else
-            Out() << "V" << fStatusDim.second/100 << 'r' << fStatusDim.second%100 << endl;
-
-        PrintState(fStatusFTM, "FTM_CONTROL");
-        PrintState(fStatusFAD, "FAD_CONTROL");
-        PrintState(fStatusLog, "DATA_LOGGER");
-        PrintState(fStatusRC,  "RATE_CONTROL");
-
+    int GetReady()
+    {
         return GetCurrentState();
     }
 
-    int GetReady()
-    {
-        return GetCurrentState();
-    }
-
     int StopRun(const EventImp &)
     {
-	if (fStatusFTM.second==FTM::kTriggerOn)
+	if (fDimFTM.state()==FTM::kTriggerOn)
 	{
             Message("Stopping FTM");
@@ -193,5 +111,5 @@
 
         // FIXME: Do step 2 only when FTM is stopped
-        if (fStatusFAD.second==FAD::kConnected)
+        if (fDimFAD.state()==FAD::kConnected)
         {
             //Dim::SendCommand("FAD_CONTROL/ENABLE_TRIGGER_LINE",      bool(false));
@@ -213,11 +131,11 @@
         /*
         // FIMXE: Handle error states!
-        if (fStatusLog.second>=20)//kSM_NightlyOpen
+        if (fDimLog.state()>=20)//kSM_NightlyOpen
             Dim::SendCommand("DATA_LOGGER/STOP");
 
-        if (fStatusLog.second==0)
+        if (fDimLog.state()==0)
             Dim::SendCommand("DATA_LOGGER/WAIT_FOR_RUN_NUMBER");
 
-        if (fStatusFAD.second==FAD::kConnected)
+        if (fDimFAD.state()==FAD::kConnected)
         {
             Dim::SendCommand("FAD_CONTROL/ENABLE_TRIGGER_LINE", bool(false));
@@ -225,5 +143,5 @@
         }
 
-        if (fStatusFTM.second==FTM::kTakingData)
+        if (fDimFTM.state()==FTM::kTakingData)
             Dim::SendCommand("FTM_CONTROL/STOP");
 
@@ -237,20 +155,20 @@
     int StartRun(const EventImp &evt)
     {
-        if (fStatusFTM.second==-2)
+        if (fDimFTM.state()==-2)
         {
             Error("No connection to ftmcontrol (see PRINT).");
             return GetCurrentState();
         }
-        if (fStatusFAD.second==-2)
+        if (fDimFAD.state()==-2)
         {
             Warn("No connection to fadcontrol (see PRINT).");
             return GetCurrentState();
         }
-        if (fStatusLog.second==-2)
+        if (fDimLog.state()==-2)
         {
             Warn("No connection to datalogger (see PRINT).");
             return GetCurrentState();
         }
-        if (fStatusRC.second==-2)
+        if (fDimRC.state()==-2)
         {
             Warn("No connection to ratecontrol (see PRINT).");
@@ -332,14 +250,14 @@
         //poll_one();
 
-        if (fStatusDim.second==0)
+        if (!fDim.online())
             return kStateDimNetworkNA;
 
-        if (fStatusFTM.second >= FTM::kConnected &&
-            fStatusFAD.second >= FAD::kConnected &&
-            fStatusLog.second >= kSM_Ready)
+        if (fDimFTM.state() >= FTM::kConnected &&
+            fDimFAD.state() >= FAD::kConnected &&
+            fDimLog.state() >= kSM_Ready)
         {
             if (GetCurrentState()==kStateConfiguring1)
             {
-		if (fStatusLog.second<30/*kSM_WaitForRun*/)
+		if (fDimLog.state()<30/*kSM_WaitForRun*/)
 		{
 		    Message("Starting datalogger");
@@ -355,7 +273,7 @@
             {
                 // FIMXE: Reset in case of error
-                if ((/*fStatusFTM.second != FTM::kConfiguring2 &&*/
-                     fStatusFTM.second != FTM::kConfigured) ||
-                    fStatusLog.second<30 || fStatusLog.second>0xff)
+                if ((/*fDimFTM.state() != FTM::kConfiguring2 &&*/
+                     fDimFTM.state() != FTM::kConfigured) ||
+                    fDimLog.state()<30 || fDimLog.state()>0xff)
                     return GetCurrentState();
 
@@ -374,7 +292,7 @@
             if (GetCurrentState()==kStateConfiguring3)
             {
-                if (fStatusFTM.second != FTM::kConfigured ||
-                    fStatusFAD.second != FAD::kConfigured ||
-                    fStatusRC.second  < 6)
+                if (fDimFTM.state() != FTM::kConfigured ||
+                    fDimFAD.state() != FAD::kConfigured ||
+                    fDimRC.state()  < 6)
                     return GetCurrentState();
 
@@ -387,5 +305,5 @@
             if (GetCurrentState()==kStateConfigured)
             {
-                if (fStatusFTM.second != FTM::kTriggerOn)
+                if (fDimFTM.state() != FTM::kTriggerOn)
                     return GetCurrentState();
 
@@ -397,5 +315,5 @@
             if (GetCurrentState()==kStateTriggerOn)
             {
-                if (fStatusFAD.second != FAD::kWritingData)
+                if (fDimFAD.state() != FAD::kWritingData)
                     return GetCurrentState();
 
@@ -407,6 +325,6 @@
             if (GetCurrentState()==kStateTakingData)
             {
-                if (fStatusFTM.second==FTM::kTriggerOn &&
-                    fStatusFAD.second==FAD::kWritingData)
+                if (fDimFTM.state()==FTM::kTriggerOn &&
+                    fDimFAD.state()==FAD::kWritingData)
                     return kStateTakingData;
 
@@ -418,19 +336,19 @@
 
         /*
-        if (fStatusFTM.second >= FTM::kConnected &&
-            fStatusFAD.second >= FAD::kConnected &&
-            fStatusLog.second >= kSM_Ready)
+        if (fDimFTM.state() >= FTM::kConnected &&
+            fDimFAD.state() >= FAD::kConnected &&
+            fDimLog.state() >= kSM_Ready)
             return kStateIdle;
          */
-        if (fStatusFTM.second >-2 &&
-            fStatusFAD.second >-2 &&
-            fStatusLog.second >-2 &&
-            fStatusRC.second >-2)
+        if (fDimFTM.state() >-2 &&
+            fDimFAD.state() >-2 &&
+            fDimLog.state() >-2 &&
+            fDimRC.state() >-2)
             return kStateConnected;
 
-        if (fStatusFTM.second >-2 ||
-            fStatusFAD.second >-2 ||
-            fStatusLog.second >-2 ||
-            fStatusRC.second >-2)
+        if (fDimFTM.state() >-2 ||
+            fDimFAD.state() >-2 ||
+            fDimLog.state() >-2 ||
+            fDimRC.state() >-2)
             return kStateConnecting;
 
@@ -440,13 +358,8 @@
 public:
     StateMachineMCP(ostream &out=cout) : StateMachineDim(out, "MCP"),
-        fStatusDim(make_pair(Time(), -2)),
-        fStatusFTM(make_pair(Time(), -2)),
-        fStatusFAD(make_pair(Time(), -2)),
-        fStatusLog(make_pair(Time(), -2)),
-        fDim("DIS_DNS/VERSION_NUMBER", (void*)NULL, 0, this),
-        fFTM("FTM_CONTROL/STATE",      (void*)NULL, 0, this),
-        fFAD("FAD_CONTROL/STATE",      (void*)NULL, 0, this),
-        fLog("DATA_LOGGER/STATE",      (void*)NULL, 0, this),
-        fRC("RATE_CONTROL/STATE",      (void*)NULL, 0, this),
+        fDimFTM("FTM_CONTROL"),
+        fDimFAD("FAD_CONTROL"),
+        fDimLog("DATA_LOGGER"),
+        fDimRC("RATE_CONTROL"),
         fService("MCP/CONFIGURATION", "X:1;X:1;C", "Run configuration information"
                  "|MaxTime[s]:Maximum time before the run gets stopped"
@@ -461,4 +374,10 @@
         // deletion and creation of threads and more.
 
+        fDim.Subscribe(*this);
+        fDimFTM.Subscribe(*this);
+        fDimFAD.Subscribe(*this);
+        fDimLog.Subscribe(*this);
+        fDimRC.Subscribe(*this);
+
         // State names
         AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
@@ -513,10 +432,4 @@
              "is also propagated to FTM and FAD");
 
-        // Verbosity commands
-        AddEvent("SET_VERBOSE", "B:1")
-            (bind(&StateMachineMCP::SetVerbosity, this, placeholders::_1))
-            ("set verbosity state"
-             "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
-
         AddEvent("PRINT")
             (bind(&StateMachineMCP::Print, this))
@@ -526,8 +439,4 @@
     int EvalOptions(Configuration &)
     {
-        //SetEndpoint(conf.Get<string>("addr"));
-
-        //fFSC.SetVerbose(!conf.Get<bool>("quiet"));
-
         return -1;
     }
Index: trunk/FACT++/src/ratecontrol.cc
===================================================================
--- trunk/FACT++/src/ratecontrol.cc	(revision 13837)
+++ trunk/FACT++/src/ratecontrol.cc	(revision 13838)
@@ -27,8 +27,9 @@
 
 #include "DimDescriptionService.h"
+#include "DimState.h"
 
 // ------------------------------------------------------------------------
 
-class StateMachineRateControl : public StateMachineDim, public DimInfoHandler
+class StateMachineRateControl : public StateMachineDim//, public DimInfoHandler
 {
 private:
@@ -50,18 +51,9 @@
     vector<bool> fBlock;
 
-    DimServiceInfoList fNetwork;
-
-    pair<Time, int> fStatusDim;
-    pair<Time, int> fStatusFTM;
-    pair<Time, int> fStatusRS;
-
-    DimStampedInfo fDim;
-    DimStampedInfo fFTM;
-    DimStampedInfo fRates;
-    DimStampedInfo fStatic;
-    DimStampedInfo fRateScan;
-
-//    DimDescribedService fDimData;
-//    DimDescribedService fDimProc;
+    DimServiceInfoListImp fNetwork;
+
+    DimVersion fDim;
+    DimState   fDimFTM;
+    DimState   fDimRS;
 
     float  fTargetRate;
@@ -76,26 +68,14 @@
     uint64_t fCounter;
 
-    pair<Time, int> GetNewState(DimStampedInfo &info) const
-    {
-        const bool disconnected = info.getSize()==0;
-
-        // Make sure getTimestamp is called _before_ getTimestampMillisecs
-        const int tsec = info.getTimestamp();
-        const int tms  = info.getTimestampMillisecs();
-
-        return make_pair(Time(tsec, tms*1000),
-                         disconnected ? -2 : info.getQuality());
-    }
-
-    bool CheckEventSize(size_t has, const char *name, size_t size)
-    {
-        if (has==size)
+    bool CheckEventSize(const EventImp &evt, size_t size)
+    {
+        if (size_t(evt.GetSize())==size)
             return true;
 
-        if (has==0)
+        if (evt.GetSize()==0)
             return false;
 
         ostringstream msg;
-        msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
+        msg << evt.GetName() << " - Received event has " << evt.GetSize() << " bytes, but expected " << size << ".";
         Fatal(msg);
         return false;
@@ -343,66 +323,42 @@
     }
 
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr)
-            return;
-
-        if (curr==&fFTM)
-        {
-            fStatusFTM = GetNewState(fFTM);
-            return;
-        }
-
-        if (curr==&fDim)
-        {
-            fStatusDim = GetNewState(fDim);
-            fStatusDim.second = curr->getSize()==4 ? curr->getInt() : 0;
-            return;
-        }
-        if (curr==&fRateScan)
-        {
-            fStatusRS = GetNewState(fRateScan);
-            fStatusRS.second = curr->getSize()==4 ? curr->getInt() : 0;
-            return;
-        }
-
-        static vector<uint8_t> counter(160);
-        if (curr==&fStatic)
-        {
-            if (!CheckEventSize(curr->getSize(), "infoHandler[DimStaticData]", sizeof(FTM::DimStaticData)))
-                return;
-
-            const FTM::DimStaticData &sdata = *static_cast<FTM::DimStaticData*>(curr->getData());
-            fTriggerOn = sdata.HasTrigger();
- 
-            PrintThresholds(sdata);
-
-            fThresholds.assign(sdata.fThreshold, sdata.fThreshold+160);
-            return;
-        }
-
-        if (curr==&fRates)
-        {
-            if (fThresholds.size()==0)
-                return;
-
-            if (!fTriggerOn && !fEnabled)
-                return;
-
-            if (fStatusRS.second==5)
-                return;
-
-            if (!CheckEventSize(curr->getSize(), "infoHandler[DimTriggerRates]", sizeof(FTM::DimTriggerRates)))
-                return;
-
-            const FTM::DimTriggerRates &sdata = *static_cast<FTM::DimTriggerRates*>(curr->getData());
-
-            if (GetCurrentState()==kStateSettingGlobalThreshold)
-                ProcessCamera(sdata);
-
-            if (GetCurrentState()==kStateInProgress)
-                ProcessPatches(sdata);
-        }
+    int HandleStaticData(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt, sizeof(FTM::DimStaticData)))
+            return GetCurrentState();
+
+        const FTM::DimStaticData &sdata = *static_cast<const FTM::DimStaticData*>(evt.GetData());
+        fTriggerOn = sdata.HasTrigger();
+
+        PrintThresholds(sdata);
+
+        fThresholds.assign(sdata.fThreshold, sdata.fThreshold+160);
+
+        return GetCurrentState();
+    }
+
+    int HandleTriggerRates(const EventImp &evt)
+    {
+        if (fThresholds.size()==0)
+            return GetCurrentState();
+
+        if (!fTriggerOn && !fEnabled)
+            return GetCurrentState();
+
+        if (fDimRS.state()==5)
+            return GetCurrentState();
+
+        if (!CheckEventSize(evt, sizeof(FTM::DimTriggerRates)))
+            return GetCurrentState();
+
+        const FTM::DimTriggerRates &sdata = *static_cast<const FTM::DimTriggerRates*>(evt.GetData());
+
+        if (GetCurrentState()==kStateSettingGlobalThreshold)
+            ProcessCamera(sdata);
+
+        if (GetCurrentState()==kStateInProgress)
+            ProcessPatches(sdata);
+
+        return GetCurrentState();
     }
 
@@ -446,5 +402,5 @@
     int SetEnabled(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "SetEnabled", 1))
+        if (!CheckEventSize(evt, 1))
             return kSM_FatalError;
 
@@ -456,5 +412,5 @@
     int SetMinThreshold(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "SetMinThreshold", 4))
+        if (!CheckEventSize(evt, 4))
             return kSM_FatalError;
 
@@ -468,5 +424,5 @@
     int SetTargetRate(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "SetTargetRate", 4))
+        if (!CheckEventSize(evt, 4))
             return kSM_FatalError;
 
@@ -475,5 +431,5 @@
         return GetCurrentState();
     }
-
+/*
     void PrintState(const pair<Time,int> &state, const char *server)
     {
@@ -500,8 +456,43 @@
         return GetCurrentState();
     }
+    */
+
+    const State GetState(const DimState &s) const
+    {
+        return fNetwork.GetState(s.name(), s.state());
+    }
+
+    void PrintState(const DimState &state) const
+    {
+        const State rc = GetState(state);
+
+        Out() << state.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << state.name() << ": ";
+        if (rc.index==-3)
+        {
+            Out() << kReset << "Offline" << endl;
+            return;
+        }
+        if (rc.index==-2)
+            Out() << state.state();
+        else
+            Out() << rc.name << "[" << rc.index << "]";
+        Out() << kReset << " - " << kBlue << rc.comment << endl;
+    }
+
+    int Print() const
+    {
+        Out() << fDim.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << "DIM_DNS: " << fDim.version() << endl;
+
+        PrintState(fDimFTM);
+        PrintState(fDimRS);
+
+        return GetCurrentState();
+    }
 
     int SetVerbosity(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
+        if (!CheckEventSize(evt, 1))
             return kSM_FatalError;
 
@@ -520,9 +511,9 @@
         //poll_one();
 
-        if (fStatusDim.second==0)
+        if (!fDim.online())
             return kStateDimNetworkNA;
 
         // All subsystems are not connected
-        if (fStatusFTM.second<FTM::kConnected)
+        if (fDimFTM.state()<FTM::kConnected)
             return kStateDisconnected;
 
@@ -543,6 +534,6 @@
 
         // At least one subsystem is not connected
-        //        if (fStatusFTM.second>=FTM::kConnected)
-        return fTriggerOn && fEnabled && fStatusRS.second!=5 ? kStateInProgress : kStateConnected;
+        //        if (fDimFTM.state()>=FTM::kConnected)
+        return fTriggerOn && fEnabled && fDimRS.state()!=5 ? kStateInProgress : kStateConnected;
     }
 
@@ -550,17 +541,6 @@
     StateMachineRateControl(ostream &out=cout) : StateMachineDim(out, "RATE_CONTROL"),
         fTriggerOn(false), fBlock(40),
-        fStatusDim(make_pair(Time(), -2)),
-        fStatusFTM(make_pair(Time(), -2)),
-        fDim("DIS_DNS/VERSION_NUMBER",  (void*)NULL, 0, this),
-        fFTM("FTM_CONTROL/STATE",       (void*)NULL, 0, this),
-        fRates("FTM_CONTROL/TRIGGER_RATES", (void*)NULL, 0, this),
-        fStatic("FTM_CONTROL/STATIC_DATA", (void*)NULL, 0, this),
-        fRateScan("RATE_SCAN/STATE", (void*)NULL, 0, this)/*,
-        fDimData("RATE_SCAN/DATA", "I:1;F:1;F:1;F:1;F:40;F:160", ""),
-        fDimProc("RATE_SCAN/PROCESS_DATA", "I:1;I:1;I:1",
-                 "Rate scan process data"
-                 "|min[DAC]:Value at which scan was started"
-                 "|max[DAC]:Value at which scan will end"
-                 "|step[DAC]:Step size for scan")*/
+        fDimFTM("FTM_CONTROL"),
+        fDimRS("RATE_SCAN")
     {
         // ba::io_service::work is a kind of keep_alive for the loop.
@@ -570,4 +550,13 @@
         // previous state but this might introduce some overhead of
         // deletion and creation of threads and more.
+
+        fDim.Subscribe(*this);
+        fDimFTM.Subscribe(*this);
+        fDimRS.Subscribe(*this);
+
+        Subscribe("FTM_CONTROL/TRIGGER_RATES")
+            (bind(&StateMachineRateControl::HandleTriggerRates, this, placeholders::_1));
+        Subscribe("FTM_CONTROL/STATIC_DATA")
+            (bind(&StateMachineRateControl::HandleStaticData,   this, placeholders::_1));
 
         // State names
Index: trunk/FACT++/src/ratescan.cc
===================================================================
--- trunk/FACT++/src/ratescan.cc	(revision 13837)
+++ trunk/FACT++/src/ratescan.cc	(revision 13838)
@@ -18,7 +18,6 @@
 #include "HeadersFTM.h"
 
-namespace ba    = boost::asio;
-namespace bs    = boost::system;
-namespace dummy = ba::placeholders;
+namespace ba = boost::asio;
+namespace bs = boost::system;
 
 using namespace std;
@@ -27,21 +26,10 @@
 
 #include "DimDescriptionService.h"
+#include "DimState.h"
 
 // ------------------------------------------------------------------------
 
-class StateMachineRateScan : public StateMachineDim, public DimInfoHandler
+class StateMachineRateScan : public StateMachineDim
 {
-    /*
-    int Wrap(boost::function<void()> f)
-    {
-        f();
-        return T::GetCurrentState();
-    }
-
-    boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
-    {
-        return bind(&StateMachineMCP::Wrap, this, func);
-    }*/
-
 private:
     enum states_t
@@ -54,14 +42,8 @@
     };
 
-//    PixelMap fMap;
-
-    DimServiceInfoList fNetwork;
-
-    pair<Time, int> fStatusDim;
-    pair<Time, int> fStatusFTM;
-
-    DimStampedInfo fDim;
-    DimStampedInfo fFTM;
-    DimStampedInfo fRates;
+    DimServiceInfoListImp fNetwork;
+
+    DimVersion fDim;
+    DimState   fDimFTM;
 
     DimDescribedService fDimData;
@@ -105,191 +87,170 @@
     }
 
-    pair<Time, int> GetNewState(DimStampedInfo &info) const
-    {
-        const bool disconnected = info.getSize()==0;
-
-        // Make sure getTimestamp is called _before_ getTimestampMillisecs
-        const int tsec = info.getTimestamp();
-        const int tms  = info.getTimestampMillisecs();
-
-        return make_pair(Time(tsec, tms*1000),
-                         disconnected ? -2 : info.getQuality());
-    }
-
-    bool CheckEventSize(size_t has, const char *name, size_t size)
-    {
-        if (has==size)
+    bool CheckEventSize(const EventImp &evt, size_t size)
+    {
+        if (size_t(evt.GetSize())==size)
             return true;
 
-        if (has==0)
+        if (evt.GetSize()==0)
             return false;
 
         ostringstream msg;
-        msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
+        msg << evt.GetName() << " - Received event has " << evt.GetSize() << " bytes, but expected " << size << ".";
         Fatal(msg);
         return false;
     }
 
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr)
+    int HandleTriggerRates(const EventImp &evt)
+    {
+        if (!CheckEventSize(evt, sizeof(FTM::DimTriggerRates)))
+            return GetCurrentState();
+
+        if (fThreshold<0/* || fDimFTM.state()!=FTM::kTakingData*/)
+            return GetCurrentState();
+
+        const FTM::DimTriggerRates &sdata = *static_cast<const FTM::DimTriggerRates*>(evt.GetData());
+
+        if (++fCounter<0)
+            return GetCurrentState();
+
+        if (fCounter==0)
+        {
+            fRate = 0;
+
+            memset(fRateBoard, 0,  40*sizeof(double));
+            memset(fRatePatch, 0, 160*sizeof(double));
+
+            fOnTime = 0;
+            return GetCurrentState();
+        }
+/*
+        if (sdata.fTriggerRate==0)
+        {
+            Message("Rate scan stopped due zero trigger rate.");
+            fThreshold = -1;
             return;
-
-        if (curr==&fFTM)
-        {
-            fStatusFTM = GetNewState(fFTM);
+        }
+*/
+
+        fRate += sdata.fTriggerRate;
+        for (int i=0; i<40; i++)
+            fRateBoard[i] += sdata.fBoardRate[i];
+        for (int i=0; i<160; i++)
+            fRatePatch[i] += sdata.fPatchRate[i];
+
+        double reference = fRate;
+        if (fReference==kBoard)
+            reference = fRateBoard[fReferenceIdx];
+        if (fReference==kPatch)
+            reference = fRatePatch[fReferenceIdx];
+
+        fOnTime += sdata.fOnTime;
+
+        reference *= sdata.fElapsedTime;
+
+        if ((reference==0 || sqrt(reference)>fResolution*reference) && fCounter<fCounterMax)
+        {
+            ostringstream out;
+            out << "Triggers so far: " << reference;
+            if (reference>0)
+                out << " (" << sqrt(reference)/reference << ")";
+            Info(out);
+
+            return GetCurrentState();
+        }
+
+        const double   time = sdata.fElapsedTime*fCounter;
+        const uint32_t th   = fThreshold;
+
+        float data[2+3+1+40+160];
+        memcpy(data,   &fStartTime, 8);
+        memcpy(data+2, &th, 4);
+        data[3] = time;         // total elapsed time
+        data[4] = fOnTime/time; // relative on time
+        data[5] = fRate/fCounter;
+        for (int i=0; i<40; i++)
+            data[i+6] = fRateBoard[i]/fCounter;
+        for (int i=0; i<160; i++)
+            data[i+46] = fRatePatch[i]/fCounter;
+
+        ostringstream sout1, sout2, sout3;
+
+        sout1 << th << " " << data[5];
+        for (int i=0; i<200; i++)
+            sout2 << " " << data[i+6];
+        sout3 << " " << data[3] << " " << data[4];
+
+        Info(sout1.str());
+
+        ofstream fout("ratescan.txt", ios::app);
+        fout << sout1.str() << sout2.str() << sout3.str() << endl;
+
+        fDimData.setQuality(fCommand=="FTM_CONTROL/SET_THRESHOLD");
+        fDimData.setData(data, sizeof(data));
+        fDimData.Update();
+
+        fThreshold += fThresholdStep;
+
+        if (fCounter>=fCounterMax)
+        {
+            Message("Rate scan stopped due to timeout.");
+            fThreshold=-1;
+            return GetCurrentState();
+        }
+
+        if (fThreshold>fThresholdMax)
+        {
+            Message("Rate scan finished.");
+            fThreshold = -1;
+            return GetCurrentState();
+        }
+
+        // Does this need to be shifted upwards?
+        if (fCounter>1 && fThresholdStepDyn>0)
+        {
+            //const double scale = fCounter/reference/fResolution/fResolution;
+            //const double step  = floor(scale*fThresholdStepDyn);
+
+            fThresholdStep = fCounter*fThresholdStepDyn;
+        }
+
+        //fCounter = -2;  // FIXME: In principle one missed report is enough
+        fCounter = -1;
+
+        const int32_t cmd[2] = { -1, fThreshold };
+        DimClient::sendCommandNB(fCommand.c_str(), (void*)cmd, 8);
+
+        return GetCurrentState();
+    }
+
+    const State GetState(const DimState &s) const
+    {
+        return fNetwork.GetState(s.name(), s.state());
+    }
+
+    void PrintState(const DimState &state) const
+    {
+        const State rc = GetState(state);
+
+        Out() << state.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << state.name() << ": ";
+        if (rc.index==-3)
+        {
+            Out() << kReset << "Offline" << endl;
             return;
         }
-
-        if (curr==&fDim)
-        {
-            fStatusDim = GetNewState(fDim);
-            fStatusDim.second = curr->getSize()==4 ? curr->getInt() : 0;
-            return;
-        }
-
-        if (curr==&fRates)
-        {
-            if (!CheckEventSize(curr->getSize(), "infoHandler[DimTriggerRates]", sizeof(FTM::DimTriggerRates)))
-                return;
-
-            if (fThreshold<0/* || fStatusFTM.second!=FTM::kTakingData*/)
-                return;
-
-            const FTM::DimTriggerRates &sdata = *static_cast<FTM::DimTriggerRates*>(curr->getData());
-
-            if (++fCounter<0)
-                return;
-
-            if (fCounter==0)
-            {
-                fRate = 0;
-
-                memset(fRateBoard, 0,  40*sizeof(double));
-                memset(fRatePatch, 0, 160*sizeof(double));
-
-                fOnTime = 0;
-                return;
-            }
-/*
-            if (sdata.fTriggerRate==0)
-            {
-                Message("Rate scan stopped due zero trigger rate.");
-                fThreshold = -1;
-                return;
-            }
-*/
-
-            fRate += sdata.fTriggerRate;
-            for (int i=0; i<40; i++)
-                fRateBoard[i] += sdata.fBoardRate[i];
-            for (int i=0; i<160; i++)
-                fRatePatch[i] += sdata.fPatchRate[i];
-
-            double reference = fRate;
-            if (fReference==kBoard)
-                reference = fRateBoard[fReferenceIdx];
-            if (fReference==kPatch)
-                reference = fRatePatch[fReferenceIdx];
-
-            fOnTime += sdata.fOnTime;
-
-            reference *= sdata.fElapsedTime;
-
-            if ((reference==0 || sqrt(reference)>fResolution*reference) && fCounter<fCounterMax)
-            {
-                ostringstream out;
-                out << "Triggers so far: " << reference;
-                if (reference>0)
-                    out << " (" << sqrt(reference)/reference << ")";
-                Info(out);
-
-                return;
-            }
-
-            const double   time = sdata.fElapsedTime*fCounter;
-            const uint32_t th   = fThreshold;
-
-            float data[2+3+1+40+160];
-            memcpy(data,   &fStartTime, 8);
-            memcpy(data+2, &th, 4);
-            data[3] = time;         // total elapsed time
-            data[4] = fOnTime/time; // relative on time
-            data[5] = fRate/fCounter;
-            for (int i=0; i<40; i++)
-                data[i+6] = fRateBoard[i]/fCounter;
-            for (int i=0; i<160; i++)
-                data[i+46] = fRatePatch[i]/fCounter;
-
-            ostringstream sout1, sout2, sout3;
-
-            sout1 << th << " " << data[5];
-            for (int i=0; i<200; i++)
-                sout2 << " " << data[i+6];
-            sout3 << " " << data[3] << " " << data[4];
-
-            Info(sout1.str());
-
-            ofstream fout("ratescan.txt", ios::app);
-            fout << sout1.str() << sout2.str() << sout3.str() << endl;
-
-            fDimData.setQuality(fCommand=="FTM_CONTROL/SET_THRESHOLD");
-            fDimData.setData(data, sizeof(data));
-            fDimData.Update();
-
-            fThreshold += fThresholdStep;
-
-            if (fCounter>=fCounterMax)
-            {
-                Message("Rate scan stopped due to timeout.");
-                fThreshold=-1;
-                return;
-            }
-
-            if (fThreshold>fThresholdMax)
-            {
-                Message("Rate scan finished.");
-                fThreshold = -1;
-                return;
-            }
-
-            // Does this need to be shifted upwards?
-            if (fCounter>1 && fThresholdStepDyn>0)
-            {
-                //const double scale = fCounter/reference/fResolution/fResolution;
-                //const double step  = floor(scale*fThresholdStepDyn);
-
-                fThresholdStep = fCounter*fThresholdStepDyn;
-            }
-
-            //fCounter = -2;  // FIXME: In principle one missed report is enough
-            fCounter = -1; 
-
-            const int32_t cmd[2] = { -1, fThreshold };
-            DimClient::sendCommandNB(fCommand.c_str(), (void*)cmd, 8);
-        }
-    }
-
-    void PrintState(const pair<Time,int> &state, const char *server)
-    {
-        const State rc = fNetwork.GetState(server, state.second);
-
-        Out() << state.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
-        Out() << kBold << server << ": ";
-        Out() << rc.name << "[" << rc.index << "]";
+        if (rc.index==-2)
+            Out() << state.state();
+        else
+            Out() << rc.name << "[" << rc.index << "]";
         Out() << kReset << " - " << kBlue << rc.comment << endl;
     }
 
-    int Print()
-    {
-        Out() << fStatusDim.first.GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
-        Out() << kBold << "DIM_DNS: ";
-        if (fStatusDim.second==0)
-            Out() << "Offline" << endl;
-        else
-            Out() << "V" << fStatusDim.second/100 << 'r' << fStatusDim.second%100 << endl;
-
-        PrintState(fStatusFTM,  "FTM_CONTROL");
+    int Print() const
+    {
+        Out() << fDim.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << "DIM_DNS: " << fDim.version() << endl;
+
+        PrintState(fDimFTM);
 
         return GetCurrentState();
@@ -298,5 +259,5 @@
     int StartRateScan(const EventImp &evt, const string &command)
     {
-        if (!CheckEventSize(evt.GetSize(), "StartRateScan", 12))
+        if (!CheckEventSize(evt, 12))
             return kSM_FatalError;
 
@@ -355,5 +316,5 @@
         Message("Rate scan manually stopped.");
 
-        //if (fStatusFTM.second==FTM::kTakingData)
+        //if (fDimFTM.state()==FTM::kTakingData)
 	{
             //Message("Stopping FTM");
@@ -373,5 +334,5 @@
     int SetReferenceBoard(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "SetReferenceBoard", 4))
+        if (!CheckEventSize(evt, 4))
             return kSM_FatalError;
 
@@ -390,5 +351,5 @@
     int SetReferencePatch(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "SetReferencePatch", 4))
+        if (!CheckEventSize(evt, 4))
             return kSM_FatalError;
 
@@ -407,5 +368,5 @@
     int ChangeStepSize(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "ChangeStepSize", 4))
+        if (!CheckEventSize(evt, 4))
             return kSM_FatalError;
 
@@ -423,5 +384,5 @@
     int ChangeMaximum(const EventImp &evt)
     {
-        if (!CheckEventSize(evt.GetSize(), "ChangeMaximum", 4))
+        if (!CheckEventSize(evt, 4))
             return kSM_FatalError;
 
@@ -440,13 +401,13 @@
         //poll_one();
 
-        if (fStatusDim.second==0)
+        if (!fDim.online())
             return kStateDimNetworkNA;
 
         // All subsystems are not connected
-        if (fStatusFTM.second<FTM::kConnected)
+        if (fDimFTM.state()<FTM::kConnected)
             return kStateDisconnected;
 
         // At least one subsystem is not connected
-        //        if (fStatusFTM.second>=FTM::kConnected)
+        //        if (fDimFTM.state()>=FTM::kConnected)
         return fThreshold<0 ? kStateConnected : kStateInProgress;
     }
@@ -454,9 +415,5 @@
 public:
     StateMachineRateScan(ostream &out=cout) : StateMachineDim(out, "RATE_SCAN"),
-        fStatusDim(make_pair(Time(), -2)),
-        fStatusFTM(make_pair(Time(), -2)),
-        fDim("DIS_DNS/VERSION_NUMBER",  (void*)NULL, 0, this),
-        fFTM("FTM_CONTROL/STATE",       (void*)NULL, 0, this),
-        fRates("FTM_CONTROL/TRIGGER_RATES", (void*)NULL, 0, this),
+        fDimFTM("FTM_CONTROL"),
         fDimData("RATE_SCAN/DATA", "X:1;I:1;F:1;F:1;F:1;F:40;F:160",
                  "|Id[s]:Start time used to identify measurement (UnixTime)"
@@ -480,4 +437,10 @@
         // previous state but this might introduce some overhead of
         // deletion and creation of threads and more.
+
+        fDim.Subscribe(*this);
+        fDimFTM.Subscribe(*this);
+
+        Subscribe("FTM_CONTROL/TRIGGER_RATES")
+            (bind(&StateMachineRateScan::HandleTriggerRates, this, placeholders::_1));
 
         // State names
Index: trunk/FACT++/src/smartfact.cc
===================================================================
--- trunk/FACT++/src/smartfact.cc	(revision 13837)
+++ trunk/FACT++/src/smartfact.cc	(revision 13838)
@@ -17,5 +17,4 @@
 
 #include "tools.h"
-#include "DimData.h"
 
 #include "LocalControl.h"
@@ -30,4 +29,5 @@
 
 #include "DimDescriptionService.h"
+#include "DimState.h"
 
 // ------------------------------------------------------------------------
@@ -305,234 +305,5 @@
 // ========================================================================
 
-class DimState : public DimInfoHandler
-{
-protected:
-    typedef function<void(const DimData &)> callback;
-
-public:
-    DimState(const string &n, const string s="STATE") : server(n),
-        info(make_pair(Time(), -4)),
-        dim((n+"/"+s).c_str(), (void*)NULL, 0, this) { }
-
-    string server;
-    pair<Time, int> info;
-    string msg;
-
-    DimStampedInfo dim;
-
-    callback fCallback;
-
-    void SetCallback(const callback &cb)
-    {
-        fCallback = cb;
-    }
-
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr || curr != &dim)
-            return;
-
-        const bool disconnected = dim.getSize()==0;
-
-        // Make sure getTimestamp is called _before_ getTimestampMillisecs
-        const int tsec = dim.getTimestamp();
-        const int tms  = dim.getTimestampMillisecs();
-
-        info = make_pair(Time(tsec, tms*1000),
-                         disconnected ? -4 : dim.getQuality());
-
-        msg = disconnected ? "" : dim.getString();
-
-        if (fCallback)
-            fCallback(DimData(curr));
-    }
-
-    const Time &time() const { return info.first; }
-    const int  &state() const { return info.second; }
-
-    bool online() const { return info.second>-4; }
-
-    const string &name() const { return server; }
-};
-
-class DimVersion : public DimState
-{
-public:
-    DimVersion() : DimState("DIS_DNS", "VERSION_NUMBER") { }
-
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr || curr != &dim)
-            return;
-
-        DimState::infoHandler();
-
-        info.second = dim.getSize()==4 ? dim.getInt() : 0;
-    }
-
-    string version() const
-    {
-        if (info.second==0)
-            return "Offline";
-
-        ostringstream out;
-        out << "V" << info.second/100 << 'r' << info.second%100;
-        return out.str();
-    }
-};
-
-class DimControl : public DimState
-{
-    map<string, callback> fCallbacks;
-public:
-    DimControl() : DimState("DIM_CONTROL") { }
-
-    void AddCallback(const string &script, const callback &cb)
-    {
-        fCallbacks[script] = cb;
-    }
-
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr || curr != &dim)
-            return;
-
-        DimState::infoHandler();
-
-        // Evaluate msg
-        const size_t p0 = msg.find_first_of(':');
-        if (p0==string::npos)
-            return;
-
-        const size_t p1 = msg.find_last_of('[');
-        if (p1==string::npos)
-            return;
-
-        const size_t p2 = msg.find_first_of(':', p0+1);
-
-        const size_t p3 = p2==string::npos || p2>p1 ? p1-1 : p2;
-
-        const string file = msg.substr(p0+2, p3-p0-2);
-
-        const auto func = fCallbacks.find(file);
-        if (func==fCallbacks.end())
-            return;
-
-        // Call callback
-        func->second(DimData(curr));
-    }
-};
-
-struct DimSubscriptions
-{
-    DimServiceInfoList fNetwork;
-
-    DimVersion fDNS;
-    DimControl fControl;
-    DimState   fMcp;
-    DimState   fDataLogger;
-    DimState   fDriveControl;
-    DimState   fMagicWeather;
-    DimState   fFeedback;
-    DimState   fBiasControl;
-    DimState   fFtmControl;
-    DimState   fFadControl;
-    DimState   fFscControl;
-    DimState   fRateControl;
-    DimState   fRateScan;
-    DimState   fChatServer;
-
-    DimStampedInfo fControlMessage;
-
-    DimStampedInfo fMcpConfiguration;
-
-    DimStampedInfo fDriveControlPointing;
-    DimStampedInfo fDriveControlTracking;
-    DimStampedInfo fDriveControlSource;
-
-    DimStampedInfo fFscControlTemperature;
-    DimStampedInfo fFscControlHumidity;
-
-    DimStampedInfo fMagicWeatherData;
-
-    DimStampedInfo fFeedbackDeviation;
-    DimStampedInfo fFeedbackCalibration;
-
-    DimStampedInfo fBiasControlVoltage;
-    DimStampedInfo fBiasControlCurrent;
-
-    DimStampedInfo fFadConnections;
-    DimStampedInfo fFadEvents;
-
-    DimStampedInfo fFtmControlTriggerRates;
-    DimStampedInfo fFtmControlStaticData;
-    DimStampedInfo fFtmControlFtuList;
-
-    DimStampedInfo fRateScanData;
-
-    DimStampedInfo fFadControlEventData;
-
-    DimSubscriptions(DimInfoHandler *h) :
-        fMcp                   ("MCP"),
-        fDataLogger            ("DATA_LOGGER"),
-        fDriveControl          ("DRIVE_CONTROL"),
-        fMagicWeather          ("MAGIC_WEATHER"),
-        fFeedback              ("FEEDBACK"),
-        fBiasControl           ("BIAS_CONTROL"),
-        fFtmControl            ("FTM_CONTROL"),
-        fFadControl            ("FAD_CONTROL"),
-        fFscControl            ("FSC_CONTROL"),
-        fRateControl           ("RATE_CONTROL"),
-        fRateScan              ("RATE_SCAN"),
-        fChatServer            ("CHAT_SERVER"),
-        //---
-        fControlMessage        ("DIM_CONTROL/MESSAGE",             (void*)NULL, 0, h),
-        //---
-        fMcpConfiguration      ("MCP/CONFIGURATION",               (void*)NULL, 0, h),
-        //---
-        fDriveControlPointing  ("DRIVE_CONTROL/POINTING_POSITION", (void*)NULL, 0, h),
-        fDriveControlTracking  ("DRIVE_CONTROL/TRACKING_POSITION", (void*)NULL, 0, h),
-        fDriveControlSource    ("DRIVE_CONTROL/SOURCE_POSITION",   (void*)NULL, 0, h),
-        //---
-        fFscControlTemperature ("FSC_CONTROL/TEMPERATURE",         (void*)NULL, 0, h),
-        fFscControlHumidity    ("FSC_CONTROL/HUMIDITY",            (void*)NULL, 0, h),
-        //---
-        fMagicWeatherData      ("MAGIC_WEATHER/DATA",              (void*)NULL, 0, h),
-        //---
-        fFeedbackDeviation     ("FEEDBACK/DEVIATION",              (void*)NULL, 0, h),
-        fFeedbackCalibration   ("FEEDBACK/CALIBRATION",            (void*)NULL, 0, h),
-        //---
-        fBiasControlVoltage    ("BIAS_CONTROL/VOLTAGE",            (void*)NULL, 0, h),
-        fBiasControlCurrent    ("BIAS_CONTROL/CURRENT",            (void*)NULL, 0, h),
-        //---
-        fFadConnections        ("FAD_CONTROL/CONNECTIONS",         (void*)NULL, 0, h),
-        fFadEvents             ("FAD_CONTROL/EVENTS",              (void*)NULL, 0, h),
-        //---
-        fFtmControlTriggerRates("FTM_CONTROL/TRIGGER_RATES",       (void*)NULL, 0, h),
-        fFtmControlStaticData  ("FTM_CONTROL/STATIC_DATA",         (void*)NULL, 0, h),
-        fFtmControlFtuList     ("FTM_CONTROL/FTU_LIST",            (void*)NULL, 0, h),
-        //---
-        fRateScanData          ("RATE_SCAN/DATA",                  (void*)NULL, 0, h),
-        //---
-        fFadControlEventData   ("FAD_CONTROL/EVENT_DATA",          (void*)NULL, 0, h)
-
-    {
-    }
-
-    const State GetState(const DimState &s) const
-    {
-        return fNetwork.GetState(s.name(), s.state());
-    }
-};
-
-// ========================================================================
-// ========================================================================
-// ========================================================================
-
-
-class StateMachineSmartFACT : public StateMachineDim, public DimInfoHandler
+class StateMachineSmartFACT : public StateMachineDim//, public DimInfoHandler
 {
 private:
@@ -601,11 +372,23 @@
     // ------------- Initialize variables before the Dim stuff ------------
 
-    DimSubscriptions *fDim;
+    DimServiceInfoListImp fNetwork;
+
+    DimVersion fDimDNS;
+    DimControl fDimControl;
+    DimState   fDimMcp;
+    DimState   fDimDataLogger;
+    DimState   fDimDriveControl;
+    DimState   fDimMagicWeather;
+    DimState   fDimFeedback;
+    DimState   fDimBiasControl;
+    DimState   fDimFtmControl;
+    DimState   fDimFadControl;
+    DimState   fDimFscControl;
+    DimState   fDimRateControl;
+    DimState   fDimRateScan;
+    DimState   fDimChatServer;
 
     // -------------------------------------------------------------------
-
-
-    // -------------------------------------------------------------------
-
+/*
     bool HandleService(DimInfo *curr, const DimInfo &service, void (StateMachineSmartFACT::*handle)(const DimData &))
     {
@@ -616,13 +399,13 @@
         return true;
     }
-
-
-    bool CheckDataSize(const DimData &d, const char *name, size_t size, bool min=false)
-    {
-        if ((!min && d.data.size()==size) || (min && d.data.size()>size))
+*/
+
+    bool CheckDataSize(const EventImp &d, const char *name, size_t size, bool min=false)
+    {
+        if ((!min && d.GetSize()==size) || (min && d.GetSize()>size))
             return true;
 
         ostringstream msg;
-        msg << name << " - Received service has " << d.data.size() << " bytes, but expected ";
+        msg << name << " - Received service has " << d.GetSize() << " bytes, but expected ";
         if (min)
             msg << "more than ";
@@ -636,5 +419,5 @@
 
     template<class T>
-        void WriteBinary(const DimData &d, const string &fname, const T &t, double scale, double offset=0)
+        void WriteBinary(const EventImp &d, const string &fname, const T &t, double scale, double offset=0)
     {
         vector<uint8_t> val(t.size(), 0);
@@ -652,5 +435,5 @@
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << offset << '\n';
         out << offset+scale << '\n';
@@ -695,18 +478,18 @@
     };
 
-    void HandleControlMessageImp(const DimData &d)
-    {
-        if (d.size()==0)
+    void HandleControlMessageImp(const EventImp &d)
+    {
+        if (d.GetSize()==0)
             return;
 
         const string str  = fControlMessageHist.size()>0 ? fControlMessageHist.back() : "<pre>  :  :  </pre> ";
-        const string time = "<pre>"+d.time.GetAsStr("%H:%M:%S")+"</pre> ";
+        const string time = "<pre>"+d.GetTimeAsStr("%H:%M:%S")+"</pre> ";
 
         ostringstream tst;
-        tst << d.qos;
+        tst << d.GetQoS();
 
         string msg;
         msg += str.substr(0, time.length())==time ? "<pre>        </pre> " : time;
-        msg += d.ptr<char>();
+        msg += d.Ptr<char>();
 
         fControlMessageHist.push_back(msg);
@@ -714,5 +497,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << "#ffffff\t";
 
@@ -725,34 +508,38 @@
     }
 
-    void HandleControlMessage(const DimData &d)
-    {
-        if (d.qos==90)
+    int HandleDimControlMessage(const EventImp &d)
+    {
+        if (d.GetQoS()==90)
             HandleControlMessageImp(d);
-    }
-
-    void HandleControlStateChange(const DimData &d)
-    {
-        if (d.qos==-2)
+
+        return GetCurrentState();
+    }
+
+    void HandleControlStateChange(const EventImp &d)
+    {
+        if (d.GetQoS()==-2)
             fControlMessageHist.clear();
 
-        if (d.qos<0)
+        if (d.GetQoS()<0)
             HandleControlMessageImp(d);
     }
 
-    void HandleMcpConfiguration(const DimData &d)
+    int HandleMcpConfiguration(const EventImp &d)
     {
         if (!CheckDataSize(d, "Mcp:Configuration", 16, true))
-            return;
-
-        fMcpConfigurationState     = d.qos;
-        fMcpConfigurationMaxTime   = d.get<uint64_t>();
-        fMcpConfigurationMaxEvents = d.get<uint64_t>(8);
-        fMcpConfigurationName      = d.ptr<char>(16);
-
-        if (d.qos==12)
+            return GetCurrentState();
+
+        fMcpConfigurationState     = d.GetQoS();
+        fMcpConfigurationMaxTime   = d.Get<uint64_t>();
+        fMcpConfigurationMaxEvents = d.Get<uint64_t>(8);
+        fMcpConfigurationName      = d.Ptr<char>(16);
+
+        if (d.GetQoS()==12)
             fMcpConfigurationRunStart = Time();
-    }
-
-    void WriteWeather(const DimData &d, const string &name, int i, float min, float max)
+
+        return GetCurrentState();
+    }
+
+    void WriteWeather(const EventImp &d, const string &name, int i, float min, float max)
     {
         const Statistics stat(fMagicWeatherHist[i]);
@@ -760,5 +547,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
 
         out << "#ffffff\t" << fMagicWeatherHist[i].back() << '\n';
@@ -772,13 +559,13 @@
     }
 
-    void HandleMagicWeatherData(const DimData &d)
+    int HandleMagicWeatherData(const EventImp &d)
     {
         if (!CheckDataSize(d, "MagicWeather:Data", 7*4+2))
-            return;
+            return GetCurrentState();
 
         // Store a history of the last 300 entries
         for (int i=kWeatherBegin; i<kWeatherEnd; i++)
         {
-            fMagicWeatherHist[i].push_back(d.ptr<float>(2)[i]);
+            fMagicWeatherHist[i].push_back(d.Ptr<float>(2)[i]);
             if (fMagicWeatherHist[i].size()>300)
                 fMagicWeatherHist[i].pop_front();
@@ -801,5 +588,5 @@
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << astro.color << '\t' << astro.description << '\n';
         out << setprecision(2);
@@ -836,14 +623,16 @@
         WriteWeather(d, "gusts", kGusts,   0,  100);
         WriteWeather(d, "press", kPress, 700, 1000);
-    }
-
-    void HandleDriveControlPointing(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleDrivePointing(const EventImp &d)
     {
         if (!CheckDataSize(d, "DriveControl:Pointing", 16))
-            return;
-
-        fDriveControlPointingZd = d.get<double>();
-
-        const double az = d.get<double>(8);
+            return GetCurrentState();
+
+        fDriveControlPointingZd = d.Get<double>();
+
+        const double az = d.Get<double>(8);
 
         static const char *dir[] =
@@ -859,5 +648,5 @@
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
 
         out << setprecision(5);
@@ -866,19 +655,21 @@
 
         ofstream(fPath+"/drive-pointing.txt") << out.str();
-    }
-
-    void HandleDriveControlTracking(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleDriveTracking(const EventImp &d)
     {
         if (!CheckDataSize(d, "DriveControl:Tracking", 56))
-            return;
-
-        const double Ra  = d.get<double>(0*8);
-        const double Dec = d.get<double>(1*8);
-        const double Zd  = d.get<double>(3*8);
-        const double Az  = d.get<double>(4*8);
+            return GetCurrentState();
+
+        const double Ra  = d.Get<double>(0*8);
+        const double Dec = d.Get<double>(1*8);
+        const double Zd  = d.Get<double>(3*8);
+        const double Az  = d.Get<double>(4*8);
 
         const double zd  = Zd                 * M_PI / 180;
-        const double dzd = d.get<double>(5*8) * M_PI / 180;
-        const double daz = d.get<double>(6*8) * M_PI / 180;
+        const double dzd = d.Get<double>(5*8) * M_PI / 180;
+        const double daz = d.Get<double>(6*8) * M_PI / 180;
 
         // Correct:
@@ -896,5 +687,5 @@
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
 
         out << kHtmlWhite << '\t' << fDriveControlSourceName << '\n';
@@ -923,12 +714,14 @@
 
         ofstream(fPath+"/tracking.txt") << out.str();
-    }
-
-    void HandleDriveControlSource(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleDriveSource(const EventImp &d)
     {
         if (!CheckDataSize(d, "DriveControl:Source", 7*4+2, true))
-            return;
-
-        const double *ptr = d.ptr<double>();
+            return GetCurrentState();
+
+        const double *ptr = d.Ptr<double>();
 
         const double ra   = ptr[0];  // Ra[h]
@@ -937,8 +730,8 @@
         const double wang = ptr[5];  // Wobble angle  [deg]
 
-        fDriveControlSourceName = d.ptr<char>(6*8);
+        fDriveControlSourceName = d.Ptr<char>(6*8);
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
 
         out << "#ffffff\t" << fDriveControlSourceName << '\n';
@@ -951,24 +744,28 @@
 
         ofstream(fPath+"/source.txt") << out.str();
-    }
-
-    void HandleFeedbackCalibration(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFeedbackCalibration(const EventImp &d)
     {
         if (!CheckDataSize(d, "Feedback:Calibration", 3*4*416))
         {
             fFeedbackCalibration.clear();
-            return;
-        }
-
-        const float *ptr = d.ptr<float>();
+            return GetCurrentState();
+        }
+
+        const float *ptr = d.Ptr<float>();
         fFeedbackCalibration.assign(ptr+2*416, ptr+3*416);
-    }
-
-    void HandleFeedbackDeviation(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFeedbackDeviation(const EventImp &d)
     {
         if (!CheckDataSize(d, "Feedback:Deviation", 2*4*416+8))
-            return;
-
-        const float *ptr = d.ptr<float>();
+            return GetCurrentState();
+
+        const float *ptr = d.Ptr<float>();
         vector<float> dev(ptr+416, ptr+416+320);
 
@@ -985,5 +782,5 @@
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << kHtmlWhite << '\t' << fFeedbackUserOffset << '\n';
         out << setprecision(3);
@@ -994,15 +791,17 @@
         out << kHtmlWhite << '\t' << stat.max << '\n';
         ofstream(fPath+"/feedback.txt") << out.str();
-    }
-
-    void HandleBiasControlVoltage(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleBiasVoltage(const EventImp &d)
     {
         if (!CheckDataSize(d, "BiasControl:Voltage", 1664))
         {
             fBiasControlVoltageVec.clear();
-            return;
-        }
-
-        fBiasControlVoltageVec.assign(d.ptr<float>(), d.ptr<float>()+320);
+            return GetCurrentState();
+        }
+
+        fBiasControlVoltageVec.assign(d.Ptr<float>(), d.Ptr<float>()+320);
 
         const Statistics stat(fBiasControlVoltageVec);
@@ -1017,5 +816,5 @@
         }
 
-        if (fDim->fBiasControl.state()==BIAS::kVoltageOn)
+        if (fDimBiasControl.state()==BIAS::kVoltageOn)
             WriteBinary(d, "biascontrol-voltage", val, 10, 65);
         else
@@ -1024,5 +823,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << kHtmlWhite << '\t' << stat.min << '\n';
         out << kHtmlWhite << '\t' << stat.med << '\n';
@@ -1031,15 +830,16 @@
         ofstream(fPath+"/voltage.txt") << out.str();
 
-    }
-
-    void HandleBiasControlCurrent(const DimData &d)
+        return GetCurrentState();
+    }
+
+    int HandleBiasCurrent(const EventImp &d)
     {
         if (!CheckDataSize(d, "BiasControl:Current", 832))
-            return;
+            return GetCurrentState();
 
         // Convert dac counts to uA
         vector<float> v(320);
         for (int i=0; i<320; i++)
-            v[i] = d.ptr<uint16_t>()[i] * 5000./4096;
+            v[i] = d.Ptr<uint16_t>()[i] * 5000./4096;
 
         const bool cal = fFeedbackCalibration.size()>0 && fBiasControlVoltageVec.size()>0;
@@ -1136,5 +936,5 @@
         ostringstream out;
         out << setprecision(2);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << col0 << '\t' << (cal?"yes":"no") << '\n';
         out << col1 << '\t' << stat.min << '\n';
@@ -1144,28 +944,32 @@
         out << kHtmlWhite << '\t' << power_tot << "W [" << power_apd << "mW]\n";
         ofstream(fPath+"/current.txt") << out.str();
-    }
-
-    void HandleFadEvents(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFadEvents(const EventImp &d)
     {
         if (!CheckDataSize(d, "FadControl:Events", 4*4))
         {
             fFadControlNumEvents = -1;
-            return;
-        }
-
-        fFadControlNumEvents = d.get<uint32_t>();
-    }
-
-    void HandleFadConnections(const DimData &d)
+            return GetCurrentState();
+        }
+
+        fFadControlNumEvents = d.Get<uint32_t>();
+
+        return GetCurrentState();
+    }
+
+    int HandleFadConnections(const EventImp &d)
     {
         if (!CheckDataSize(d, "FadControl:Connections", 41))
         {
             //fStatusEventBuilderLabel->setText("Offline");
-            return;
+            return GetCurrentState();
         }
 
         string rc(40, '-'); // orange/red [45]
 
-        const uint8_t *ptr = d.ptr<uint8_t>();
+        const uint8_t *ptr = d.Ptr<uint8_t>();
 
         int c[4] = { '.', '.', '.', '.' };
@@ -1198,5 +1002,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << col[0] << '\t' << rc.substr( 0, 10) << '\n';
         out << col[1] << '\t' << rc.substr(10, 10) << '\n';
@@ -1204,19 +1008,21 @@
         out << col[3] << '\t' << rc.substr(30, 10) << '\n';
         ofstream(fPath+"/fad.txt") << out.str();
-    }
-
-    void HandleFtmControlTriggerRates(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFtmTriggerRates(const EventImp &d)
     {
         if (!CheckDataSize(d, "FtmControl:TriggerRates", 24+160+640+8))
-            return;
+            return GetCurrentState();
 
         // New run started
-        if (d.get<float>(20)<0)
-            return;
-
-        fFtmControlTriggerRateCam = d.get<float>(20);
-
-        const float *brates = d.ptr<float>(24);     // Board rate
-        const float *prates = d.ptr<float>(24+160); // Patch rate
+        if (d.Get<float>(20)<0)
+            return GetCurrentState();
+
+        fFtmControlTriggerRateCam = d.Get<float>(20);
+
+        const float *brates = d.Ptr<float>(24);     // Board rate
+        const float *prates = d.Ptr<float>(24+160); // Patch rate
 
         // Store a history of the last 60 entries
@@ -1236,5 +1042,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << "#ffffff\t" << fFtmControlTriggerRateCam << '\n';
 
@@ -1245,5 +1051,5 @@
 
         out.str("");
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << kHtmlWhite << '\t' << bstat.min << '\n';
         out << kHtmlWhite << '\t' << bstat.med << '\n';
@@ -1253,5 +1059,5 @@
 
         out.str("");
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << kHtmlWhite << '\t' << pstat.min << '\n';
         out << kHtmlWhite << '\t' << pstat.med << '\n';
@@ -1259,12 +1065,14 @@
         out << kHtmlWhite << '\t' << pstat.max << '\n';
         ofstream(fPath+"/patchrates.txt") << out.str();
-    }
-
-    void HandleFtmControlStaticData(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFtmStaticData(const EventImp &d)
     {
         if (!CheckDataSize(d, "FtmControl:StaticData", 740))
-            return;
-
-        const uint16_t *ptr = d.ptr<uint16_t>(260);
+            return GetCurrentState();
+
+        const uint16_t *ptr = d.Ptr<uint16_t>(260);
         vector<uint16_t> vec(ptr, ptr+160);
 
@@ -1274,5 +1082,5 @@
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << kHtmlWhite << '\t' << stat.min << '\n';
         out << kHtmlWhite << '\t' << stat.med << '\n';
@@ -1280,15 +1088,17 @@
         out << kHtmlWhite << '\t' << stat.max << '\n';
         ofstream(fPath+"/thresholds.txt") << out.str();
-    }
-
-    void HandleFtmControlFtuList(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFtmFtuList(const EventImp &d)
     {
         if (!CheckDataSize(d, "FtmControl:FtuList", sizeof(FTM::DimFtuList)))
-            return;
-
-        const FTM::DimFtuList &sdata = d.ref<FTM::DimFtuList>();
+            return GetCurrentState();
+
+        const FTM::DimFtuList &sdata = d.Ref<FTM::DimFtuList>();
 
         ostringstream out;
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
 
         int cnt = 0;
@@ -1315,15 +1125,17 @@
 
         ofstream(fPath+"/ftu.txt") << out.str();
-    }
-
-    void HandleFadControlEventData(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFadEventData(const EventImp &d)
     {
         if (!CheckDataSize(d, "FadControl:EventData", 23040))
-            return;
-
-        //const float *avg = d.ptr<float>();
-        //const float *rms = d.ptr<float>(1440*sizeof(float));
-        const float *dat = d.ptr<float>(1440*sizeof(float)*2);
-        //const float *pos = d.ptr<float>(1440*sizeof(float)*3);
+            return GetCurrentState();
+
+        //const float *avg = d.Ptr<float>();
+        //const float *rms = d.Ptr<float>(1440*sizeof(float));
+        const float *dat = d.Ptr<float>(1440*sizeof(float)*2);
+        //const float *pos = d.Ptr<float>(1440*sizeof(float)*3);
 
         vector<float> max(320, -2);
@@ -1339,5 +1151,5 @@
         }
 
-        switch (d.qos)
+        switch (d.GetQoS())
         {
         case 0:  WriteBinary(d, "fadcontrol-eventdata", max, 2,   -1); break;
@@ -1345,12 +1157,14 @@
         default: WriteBinary(d, "fadcontrol-eventdata", max, 0.25, 0); break;
         }
-    }
-
-    void HandleFscControlTemperature(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFscTemperature(const EventImp &d)
     {
         if (!CheckDataSize(d, "FscControl:Temperature", 240))
-            return;
-
-        const float *ptr = d.ptr<float>(4);
+            return GetCurrentState();
+
+        const float *ptr = d.Ptr<float>(4);
 
         double avg =   0;
@@ -1391,5 +1205,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << "#ffffff\t" << fFscControlHumidityAvg << '\n';
         out << "#ffffff\t" << min      << '\n';
@@ -1404,12 +1218,14 @@
         WriteBinary(d, "fsccontrol-temperature-hist",
                     fFscControlTemperatureHist, 10);
-    }
-
-    void HandleFscControlHumidity(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleFscHumidity(const EventImp &d)
     {
         if (!CheckDataSize(d, "FscControl:Humidity", 5*4))
-            return;
-
-        const float *ptr = d.ptr<float>(4);
+            return GetCurrentState();
+
+        const float *ptr = d.Ptr<float>(4);
 
         double avg =   0;
@@ -1424,13 +1240,15 @@
 
         fFscControlHumidityAvg = avg/num;
-    }
-
-    void HandleRateScanData(const DimData &d)
+
+        return GetCurrentState();
+    }
+
+    int HandleRateScanData(const EventImp &d)
     {
         if (!CheckDataSize(d, "RateScan:Data", 824))
-            return;
-
-        const uint64_t id   = d.get<uint64_t>();
-        const float   *rate = d.ptr<float>(20);
+            return GetCurrentState();
+
+        const uint64_t id   = d.Get<uint64_t>();
+        const float   *rate = d.Ptr<float>(20);
 
         if (fRateScanDataId!=id)
@@ -1458,5 +1276,5 @@
         ostringstream out;
         out << setprecision(3);
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << "#ffffff\t" << pow(10, fRateScanDataHist[0].back()) << '\n';
         out << "#ffffff\t" << max << '\n';
@@ -1465,23 +1283,25 @@
 
         out.str("");
-        out << d.time.JavaDate() << '\n';
+        out << d.GetJavaDate() << '\n';
         out << "#ffffff\t" << int(fRateScanBoard) << '\n';
         out << "#ffffff\t" << pow(10, fRateScanDataHist[fRateScanBoard+1].back()) << '\n';
 
         ofstream(fPath+"/ratecan_board.txt") << out.str();
+
+        return GetCurrentState();
     }
 
     // -------------------------------------------------------------------
 
-    void HandleDoTest(const DimData &d)
+    void HandleDoTest(const EventImp &d)
     {
         ostringstream out;
-        out << d.time.JavaDate() << '\t' << fDim->fControl.online() << '\n';
-        switch (d.qos)
+        out << d.GetJavaDate() << '\t' << fDimControl.online() << '\n';
+        switch (d.GetQoS())
         {
         case -3: out << kHtmlWhite << "\tNot running\n";               break;
         case -2: out << kHtmlBlue  << "\tLoading\n";                   break;
         case -1: out << kHtmlBlue  << "\tStarted\n";                   break;
-        default: out << kHtmlGreen << "\tRunning [" << d.qos << "]\n"; break;
+        default: out << kHtmlGreen << "\tRunning [" << d.GetQoS() << "]\n"; break;
         }
 
@@ -1490,50 +1310,4 @@
 
     // -------------------------------------------------------------------
-
-    void infoHandler()
-    {
-        DimInfo *curr = getInfo(); // get current DimInfo address
-        if (!curr)
-            return;
-
-        if (HandleService(curr, fDim->fMcpConfiguration,       &StateMachineSmartFACT::HandleMcpConfiguration))
-            return;
-        if (HandleService(curr, fDim->fMagicWeatherData,       &StateMachineSmartFACT::HandleMagicWeatherData))
-            return;
-        if (HandleService(curr, fDim->fDriveControlPointing,   &StateMachineSmartFACT::HandleDriveControlPointing))
-            return;
-        if (HandleService(curr, fDim->fDriveControlTracking,   &StateMachineSmartFACT::HandleDriveControlTracking))
-            return;
-        if (HandleService(curr, fDim->fDriveControlSource,     &StateMachineSmartFACT::HandleDriveControlSource))
-            return;
-        if (HandleService(curr, fDim->fFeedbackDeviation,      &StateMachineSmartFACT::HandleFeedbackDeviation))
-            return;
-        if (HandleService(curr, fDim->fFeedbackCalibration,    &StateMachineSmartFACT::HandleFeedbackCalibration))
-            return;
-        if (HandleService(curr, fDim->fBiasControlVoltage,     &StateMachineSmartFACT::HandleBiasControlVoltage))
-            return;
-        if (HandleService(curr, fDim->fBiasControlCurrent,     &StateMachineSmartFACT::HandleBiasControlCurrent))
-            return;
-        if (HandleService(curr, fDim->fFadConnections,         &StateMachineSmartFACT::HandleFadConnections))
-            return;
-        if (HandleService(curr, fDim->fFadEvents,              &StateMachineSmartFACT::HandleFadEvents))
-            return;
-        if (HandleService(curr, fDim->fFtmControlTriggerRates, &StateMachineSmartFACT::HandleFtmControlTriggerRates))
-            return;
-        if (HandleService(curr, fDim->fFtmControlStaticData,   &StateMachineSmartFACT::HandleFtmControlStaticData))
-            return;
-        if (HandleService(curr, fDim->fFtmControlFtuList,      &StateMachineSmartFACT::HandleFtmControlFtuList))
-            return;
-        if (HandleService(curr, fDim->fFadControlEventData,    &StateMachineSmartFACT::HandleFadControlEventData))
-            return;
-        if (HandleService(curr, fDim->fFscControlTemperature,  &StateMachineSmartFACT::HandleFscControlTemperature))
-            return;
-        if (HandleService(curr, fDim->fFscControlHumidity,     &StateMachineSmartFACT::HandleFscControlHumidity))
-            return;
-        if (HandleService(curr, fDim->fControlMessage,         &StateMachineSmartFACT::HandleControlMessage))
-            return;
-        if (HandleService(curr, fDim->fRateScanData,           &StateMachineSmartFACT::HandleRateScanData))
-            return;
-    }
 
     bool CheckEventSize(size_t has, const char *name, size_t size)
@@ -1548,7 +1322,12 @@
     }
 
+    const State GetState(const DimState &s) const
+    {
+        return fNetwork.GetState(s.name(), s.state());
+    }
+
     void PrintState(const DimState &state) const
     {
-        const State rc = fDim->GetState(state);
+        const State rc = GetState(state);
 
         Out() << state.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
@@ -1568,20 +1347,20 @@
     int Print() const
     {
-        Out() << fDim->fDNS.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
-        Out() << kBold << "DIM_DNS: " << fDim->fDNS.version() << endl;
-
-        PrintState(fDim->fMcp);
-        PrintState(fDim->fControl);
-        PrintState(fDim->fDataLogger);
-        PrintState(fDim->fDriveControl);
-        PrintState(fDim->fFadControl);
-        PrintState(fDim->fFtmControl);
-        PrintState(fDim->fBiasControl);
-        PrintState(fDim->fFeedback);
-        PrintState(fDim->fRateControl);
-        PrintState(fDim->fFscControl);
-        PrintState(fDim->fMagicWeather);
-        PrintState(fDim->fRateScan);
-        PrintState(fDim->fChatServer);
+        Out() << fDimDNS.time().GetAsStr("%H:%M:%S.%f").substr(0, 12) << " - ";
+        Out() << kBold << "DIM_DNS: " << fDimDNS.version() << endl;
+
+        PrintState(fDimMcp);
+        PrintState(fDimControl);
+        PrintState(fDimDataLogger);
+        PrintState(fDimDriveControl);
+        PrintState(fDimFadControl);
+        PrintState(fDimFtmControl);
+        PrintState(fDimBiasControl);
+        PrintState(fDimFeedback);
+        PrintState(fDimRateControl);
+        PrintState(fDimFscControl);
+        PrintState(fDimMagicWeather);
+        PrintState(fDimRateScan);
+        PrintState(fDimChatServer);
 
         return GetCurrentState();
@@ -1593,5 +1372,5 @@
             return kHtmlWhite+"\t&mdash;\n";
 
-        if (&state==&fDim->fControl)
+        if (&state==&fDimControl)
         {
             ostringstream out;
@@ -1600,5 +1379,5 @@
         }
 
-        const State rc = fDim->GetState(state);
+        const State rc = GetState(state);
 
         // Sate not found in list, server online (-3: offline; -2: not found)
@@ -1630,5 +1409,5 @@
         //poll_one();
 
-        if (fDim->fDNS.state()==0)
+        if (fDimDNS.state()==0)
             return kStateDimNetworkNA;
 
@@ -1640,9 +1419,9 @@
 
         ostringstream out;
-        out << now.JavaDate() << '\t' << fDim->fControl.online() << '\n';
+        out << now.JavaDate() << '\t' << fDimControl.online() << '\n';
         out << setprecision(3);
 
         // -------------- System status --------------
-        if (fDim->fMcp.state()>=5) // Idle
+        if (fDimMcp.state()>=5) // Idle
         {
             string col = kHtmlBlue;
@@ -1651,17 +1430,17 @@
                 fMcpConfigurationState!=11 &&  // Trigger On
                 fMcpConfigurationState!=12)    // Taking Data*/
-            if (fDim->fMcp.state()!= 5 &&  // Idle
-                fDim->fMcp.state()!=11 &&  // Trigger On
-                fDim->fMcp.state()!=12)    // Taking Data
+            if (fDimMcp.state()!= 5 &&  // Idle
+                fDimMcp.state()!=11 &&  // Trigger On
+                fDimMcp.state()!=12)    // Taking Data
                 col = kHtmlYellow;
             else
-                if (fDim->fFadControl.state()==FAD::kWritingData)
+                if (fDimFadControl.state()==FAD::kWritingData)
                     col = kHtmlGreen;
 
             out << col << '\t';
 
-            if (fDim->fRateControl.state()!=5 && fDim->fRateScan.state()!=5)
+            if (fDimRateControl.state()!=5 && fDimRateScan.state()!=5)
             {
-                switch (fDim->fMcp.state()/*fMcpConfigurationState*/)
+                switch (fDimMcp.state()/*fMcpConfigurationState*/)
                 {
                 // kStateIdle
@@ -1679,12 +1458,12 @@
             }
             else
-                if (fDim->fRateControl.state()==5/*kStateSettingGlobalThreshold*/)
+                if (fDimRateControl.state()==5/*kStateSettingGlobalThreshold*/)
                     out << "Calibrating threshold";
                 else
 
-                    if (fDim->fRateScan.state()==5/*kStateSettingGlobalThreshold*/)
+                    if (fDimRateScan.state()==5/*kStateSettingGlobalThreshold*/)
                         out << "Rate scan in progress";
 
-            if (fDim->fMcp.state()>10 && fDim->fRateControl.state()!=5)
+            if (fDimMcp.state()>10 && fDimRateControl.state()!=5)
             {
                 if (fMcpConfigurationMaxEvents>0 || fMcpConfigurationMaxTime>0 || fMcpConfigurationState==12)
@@ -1732,8 +1511,8 @@
 
         // ------------------ Drive -----------------
-        if (fDim->fDriveControl.state()>=5)   // Armed, Moving, Tracking
+        if (fDimDriveControl.state()>=5)   // Armed, Moving, Tracking
         {
             const double dev = fDriveControlTrackingDevHist.size()>0 ? fDriveControlTrackingDevHist.back() : 0;
-            const State rc = fDim->GetState(fDim->fDriveControl);
+            const State rc = GetState(fDimDriveControl);
             string col = kHtmlGreen;
             if (rc.index==6) // Moving
@@ -1753,5 +1532,5 @@
             out << fDriveControlPointingZd  << '\t';
             out << fDriveControlPointingAz  << '\t';
-            if (fDim->fDriveControl.state()==7)
+            if (fDimDriveControl.state()==7)
             {
                 out << fDriveControlSourceName  << '\t';
@@ -1767,5 +1546,5 @@
 
         // ------------------- FSC ------------------
-        if (fDim->fFscControl.state()>1 && fFscControlTemperatureHist.size()>0)
+        if (fDimFscControl.state()>1 && fFscControlTemperatureHist.size()>0)
         {
             out << kHtmlGreen << '\t' << fFscControlTemperatureHist.back() << '\n';
@@ -1775,5 +1554,5 @@
 
         // --------------- MagicWeather -------------
-        if (fDim->fMagicWeather.state()==3 && fMagicWeatherHist[kWeatherBegin].size()>0)
+        if (fDimMagicWeather.state()==3 && fMagicWeatherHist[kWeatherBegin].size()>0)
         {
             /*
@@ -1804,5 +1583,5 @@
 
         // --------------- FtmControl -------------
-        if (fDim->fFtmControl.state()==FTM::kTriggerOn)
+        if (fDimFtmControl.state()==FTM::kTriggerOn)
         {
             string col = kHtmlGreen;
@@ -1818,11 +1597,11 @@
 
         // --------------- BiasControl -------------
-        if (fDim->fBiasControl.state()==BIAS::kRamping     ||
-            fDim->fBiasControl.state()==BIAS::kOverCurrent ||
-            fDim->fBiasControl.state()==BIAS::kVoltageOn   ||
-            fDim->fBiasControl.state()==BIAS::kVoltageOff)
-        {
-            const bool off = fDim->fBiasControl.state()==BIAS::kVoltageOff;
-            const bool oc  = fDim->fBiasControl.state()==BIAS::kOverCurrent;
+        if (fDimBiasControl.state()==BIAS::kRamping     ||
+            fDimBiasControl.state()==BIAS::kOverCurrent ||
+            fDimBiasControl.state()==BIAS::kVoltageOn   ||
+            fDimBiasControl.state()==BIAS::kVoltageOff)
+        {
+            const bool off = fDimBiasControl.state()==BIAS::kVoltageOff;
+            const bool oc  = fDimBiasControl.state()==BIAS::kOverCurrent;
 
             string col = fBiasControlVoltageMed>3?kHtmlGreen:kHtmlWhite;
@@ -1833,12 +1612,12 @@
 
             // Bias in overcurrent => Red
-            if (fDim->fBiasControl.state()==BIAS::kOverCurrent)
+            if (fDimBiasControl.state()==BIAS::kOverCurrent)
                 col = kHtmlRed;
 
             // MCP in ReadyForDatataking/Configuring/Configured/TriggerOn/TakingData
             // and Bias not in "data-taking state' => Red
-            if (fDim->fMcp.state()>5 &&
-                fDim->fBiasControl.state()!=BIAS::kVoltageOn &&
-                fDim->fBiasControl.state()!=BIAS::kVoltageOff)
+            if (fDimMcp.state()>5 &&
+                fDimBiasControl.state()!=BIAS::kVoltageOn &&
+                fDimBiasControl.state()!=BIAS::kVoltageOff)
                 col = kHtmlRed;
 
@@ -1846,5 +1625,5 @@
 
             // Feedback is currently calibrating => Blue
-            if (fDim->fFeedback.state()==13)
+            if (fDimFeedback.state()==13)
             {
                 out << kHtmlBlue << '\t';
@@ -1882,25 +1661,25 @@
 
         out.str("");
-        out << now.JavaDate() << '\t' << fDim->fControl.online() << '\n';
-
-        if (fDim->fDNS.state()==0)
+        out << now.JavaDate() << '\t' << fDimControl.online() << '\n';
+
+        if (fDimDNS.state()==0)
             out << kHtmlWhite << "\tOffline\n\n\n\n\n\n\n\n\n\n\n\n";
         else
         {
-            out << kHtmlGreen << '\t' << fDim->fDNS.version() << '\n';
-
-            out << GetStateHtml(fDim->fMcp,          4);
-            out << GetStateHtml(fDim->fControl,      0);
-            out << GetStateHtml(fDim->fDataLogger,   1);
-            out << GetStateHtml(fDim->fDriveControl, 2);
-            out << GetStateHtml(fDim->fFadControl,   FAD::kConnected);
-            out << GetStateHtml(fDim->fFtmControl,   FTM::kConnected);
-            out << GetStateHtml(fDim->fBiasControl,  BIAS::kConnected);
-            out << GetStateHtml(fDim->fFeedback,     4);
-            out << GetStateHtml(fDim->fRateControl,  4);
-            out << GetStateHtml(fDim->fFscControl,   2);
-            out << GetStateHtml(fDim->fMagicWeather, 2);
-            out << GetStateHtml(fDim->fRateScan,     4);
-            out << GetStateHtml(fDim->fChatServer,   1);
+            out << kHtmlGreen << '\t' << fDimDNS.version() << '\n';
+
+            out << GetStateHtml(fDimMcp,          4);
+            out << GetStateHtml(fDimControl,      0);
+            out << GetStateHtml(fDimDataLogger,   1);
+            out << GetStateHtml(fDimDriveControl, 2);
+            out << GetStateHtml(fDimFadControl,   FAD::kConnected);
+            out << GetStateHtml(fDimFtmControl,   FTM::kConnected);
+            out << GetStateHtml(fDimBiasControl,  BIAS::kConnected);
+            out << GetStateHtml(fDimFeedback,     4);
+            out << GetStateHtml(fDimRateControl,  4);
+            out << GetStateHtml(fDimFscControl,   2);
+            out << GetStateHtml(fDimMagicWeather, 2);
+            out << GetStateHtml(fDimRateScan,     4);
+            out << GetStateHtml(fDimChatServer,   1);
         }
 
@@ -1909,4 +1688,5 @@
         return kStateRunning;
     }
+
 
 public:
@@ -1918,6 +1698,82 @@
         fRateScanDataId(0),
         fRateScanBoard(0),
-        fDim(0)
-    {
+        // ---
+        fDimMcp         ("MCP"),
+        fDimDataLogger  ("DATA_LOGGER"),
+        fDimDriveControl("DRIVE_CONTROL"),
+        fDimMagicWeather("MAGIC_WEATHER"),
+        fDimFeedback    ("FEEDBACK"),
+        fDimBiasControl ("BIAS_CONTROL"),
+        fDimFtmControl  ("FTM_CONTROL"),
+        fDimFadControl  ("FAD_CONTROL"),
+        fDimFscControl  ("FSC_CONTROL"),
+        fDimRateControl ("RATE_CONTROL"),
+        fDimRateScan    ("RATE_SCAN"),
+        fDimChatServer  ("CHAT_SERVER")
+    {
+        fDimMcp.Subscribe(*this);
+        fDimDataLogger.Subscribe(*this);
+        fDimDriveControl.Subscribe(*this);
+        fDimMagicWeather.Subscribe(*this);
+        fDimFeedback.Subscribe(*this);
+        fDimBiasControl.Subscribe(*this);
+        fDimFtmControl.Subscribe(*this);
+        fDimFadControl.Subscribe(*this);
+        fDimFscControl.Subscribe(*this);
+        fDimRateControl.Subscribe(*this);
+        fDimRateScan.Subscribe(*this);
+        fDimChatServer.Subscribe(*this);
+
+        Subscribe("DIM_CONTROL/MESSAGE")
+            (bind(&StateMachineSmartFACT::HandleDimControlMessage,  this, placeholders::_1));
+
+        Subscribe("MCP/CONFIGURATION")
+            (bind(&StateMachineSmartFACT::HandleMcpConfiguration,   this, placeholders::_1));
+
+        Subscribe("DRIVE_CONTROL/POINTING_POSITION")
+            (bind(&StateMachineSmartFACT::HandleDrivePointing,      this, placeholders::_1));
+        Subscribe("DRIVE_CONTROL/TRACKING_POSITION")
+            (bind(&StateMachineSmartFACT::HandleDriveTracking,      this, placeholders::_1));
+        Subscribe("DRIVE_CONTROL/SOURCE_POSITION")
+            (bind(&StateMachineSmartFACT::HandleDriveSource,        this, placeholders::_1));
+
+        Subscribe("FSC_CONTROL/TEMPERATURE")
+            (bind(&StateMachineSmartFACT::HandleFscTemperature,     this, placeholders::_1));
+        Subscribe("FSC_CONTROL/HUMIDITY")
+            (bind(&StateMachineSmartFACT::HandleFscHumidity,        this, placeholders::_1));
+
+        Subscribe("MAGIC_WEATHER/DATA")
+            (bind(&StateMachineSmartFACT::HandleMagicWeatherData,   this, placeholders::_1));
+
+        Subscribe("FEEDBACK/DEVIATION")
+            (bind(&StateMachineSmartFACT::HandleFeedbackDeviation,   this, placeholders::_1));
+        Subscribe("FEEDBACK/CALIBRATION")
+            (bind(&StateMachineSmartFACT::HandleFeedbackCalibration, this, placeholders::_1));
+
+        Subscribe("BIAS_CONTROL/VOLTAGE")
+            (bind(&StateMachineSmartFACT::HandleBiasVoltage,         this, placeholders::_1));
+        Subscribe("BIAS_CONTROL/CURRENT")
+            (bind(&StateMachineSmartFACT::HandleBiasCurrent,         this, placeholders::_1));
+
+        Subscribe("FAD_CONTROL/CONNECTIONS")
+            (bind(&StateMachineSmartFACT::HandleFadConnections,      this, placeholders::_1));
+        Subscribe("FAD_CONTROL/EVENTS")
+            (bind(&StateMachineSmartFACT::HandleFadEvents,           this, placeholders::_1));
+
+        Subscribe("FTM_CONTROL/TRIGGER_RATES")
+            (bind(&StateMachineSmartFACT::HandleFtmTriggerRates,     this, placeholders::_1));
+        Subscribe("FTM_CONTROL/STATIC_DATA")
+            (bind(&StateMachineSmartFACT::HandleFtmStaticData,       this, placeholders::_1));
+        Subscribe("FTM_CONTROL/FTU_LIST")
+            (bind(&StateMachineSmartFACT::HandleFtmFtuList,          this, placeholders::_1));
+
+        Subscribe("RATE_SCAN/DATA")
+            (bind(&StateMachineSmartFACT::HandleRateScanData,        this, placeholders::_1));
+
+        Subscribe("FAD_CONTROL/EVENT_DATA")
+            (bind(&StateMachineSmartFACT::HandleFadEventData,        this, placeholders::_1));
+
+        // =================================================================
+
         // State names
         AddStateName(kStateDimNetworkNA, "DimNetworkNotAvailable",
@@ -1926,4 +1782,6 @@
         AddStateName(kStateRunning, "Running", "");
 
+        // =================================================================
+
         AddEvent("PRINT")
             (bind(&StateMachineSmartFACT::Print, this))
@@ -1931,8 +1789,4 @@
 
     }
-    ~StateMachineSmartFACT()
-    {
-        delete fDim;
-    }
     int EvalOptions(Configuration &conf)
     {
@@ -1945,7 +1799,6 @@
         fPath = conf.Get<string>("path");
 
-        fDim = new DimSubscriptions(this);
-        fDim->fControl.SetCallback(bind(&StateMachineSmartFACT::HandleControlStateChange, this, placeholders::_1));
-        fDim->fControl.AddCallback("dotest.dim", bind(&StateMachineSmartFACT::HandleDoTest, this, placeholders::_1));
+        fDimControl.SetCallback(bind(&StateMachineSmartFACT::HandleControlStateChange, this, placeholders::_1));
+        fDimControl.AddCallback("dotest.dim", bind(&StateMachineSmartFACT::HandleDoTest, this, placeholders::_1));
 
         return -1;
