Ignore:
Timestamp:
10/27/12 18:58:15 (12 years ago)
Author:
tbretz
Message:
Updated to a fully working version (still missing: access to all agilents)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/agilentctrl.cc

    r14326 r14537  
    33#include "Dim.h"
    44#include "Event.h"
    5 #include "Shell.h"
    65#include "StateMachineDim.h"
    76#include "Connection.h"
    87#include "LocalControl.h"
    98#include "Configuration.h"
    10 #include "Console.h"
    11 #include "Converter.h"
    129
    1310#include "tools.h"
     
    1714namespace ba    = boost::asio;
    1815namespace bs    = boost::system;
    19 namespace bapla = ba::placeholders;
     16namespace dummy = ba::placeholders;
    2017
    2118using namespace std;
     
    2623class ConnectionAgilent : public Connection
    2724{
     25    bool fIsVerbose;
     26    bool fDebugRx;
     27
     28    uint16_t fInterval;
     29
     30    boost::asio::deadline_timer fTimeout;
     31    boost::asio::deadline_timer fTimeoutPowerCycle;
    2832    boost::asio::streambuf fBuffer;
    29     bool fIsVerbose;
    30     bool fDump;
    31     ofstream fDumpStream;
    32     int fState;
    33     float fMeasuredVoltage;
    34     float fMeasuredCurrent;
    35    
     33
     34    Data fData;
     35
     36    Time fLastReceived;
     37    Time fLastCommand;
    3638
    3739protected:
    3840
    39     virtual void UpdateDim(const vector<float> &)
    40     {
    41     }
    42 
    43     void Dump(const string &str)
    44     {
    45         if (!fDumpStream.is_open())
    46         {
    47             fDumpStream.open("socket_dump-agilent.txt", ios::app);
    48             if (!fDumpStream)
     41    virtual void UpdateDim(const Data &)
     42    {
     43    }
     44
     45    void RequestStatus()
     46    {
     47        if (IsConnected())
     48            PostMessage(string("*IDN?\nvolt?\nmeas:volt?\nmeas:curr?\ncurr?\n"));
     49
     50        fTimeout.expires_from_now(boost::posix_time::seconds(fInterval));
     51        fTimeout.async_wait(boost::bind(&ConnectionAgilent::HandleStatusTimer,
     52                                        this, dummy::error));
     53    }
     54
     55
     56    void HandleStatusTimer(const bs::error_code &error)
     57    {
     58        // 125: Operation canceled (bs::error_code(125, bs::system_category))
     59        if (error && error!=ba::error::basic_errors::operation_aborted)
     60        {
     61            ostringstream str;
     62            str << "Status request timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
     63            Error(str);
     64
     65            PostClose(false);
     66            return;
     67        }
     68
     69        if (!is_open())
     70        {
     71            // For example: Here we could schedule a new accept if we
     72            // would not want to allow two connections at the same time.
     73            PostClose(true);
     74            return;
     75        }
     76
     77        // Check whether the deadline has passed. We compare the deadline
     78        // against the current time since a new asynchronous operation
     79        // may have moved the deadline before this actor had a chance
     80        // to run.
     81        if (fTimeout.expires_at() > ba::deadline_timer::traits_type::now())
     82            return;
     83
     84        RequestStatus();
     85    }
     86
     87    void HandlePowerCycle(const bs::error_code &error)
     88    {
     89        // 125: Operation canceled (bs::error_code(125, bs::system_category))
     90        if (error && error!=ba::error::basic_errors::operation_aborted)
     91        {
     92            ostringstream str;
     93            str << "Power cycle timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
     94            Error(str);
     95
     96            PostClose(false);
     97            return;
     98        }
     99
     100        if (!is_open())
     101        {
     102            // For example: Here we could schedule a new accept if we
     103            // would not want to allow two connections at the same time.
     104            PostClose(true);
     105            return;
     106        }
     107
     108        // Check whether the deadline has passed. We compare the deadline
     109        // against the current time since a new asynchronous operation
     110        // may have moved the deadline before this actor had a chance
     111        // to run.
     112        if (fTimeout.expires_at() > ba::deadline_timer::traits_type::now())
     113            return;
     114
     115        SetPower(true);
     116    }
     117
     118private:
     119    void StartRead(int line=0)
     120    {
     121        ba::async_read_until(*this, fBuffer, "\n",
     122                             boost::bind(&ConnectionAgilent::HandleReceivedData, this,
     123                                         dummy::error, dummy::bytes_transferred, line+1));
     124    }
     125
     126    void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int line)
     127    {
     128
     129        // Do not schedule a new read if the connection failed.
     130        if (bytes_received==0 || err)
     131        {
     132            if (err==ba::error::eof)
     133                Warn("Connection closed by remote host (FTM).");
     134
     135            // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
     136            // 125: Operation canceled
     137            if (err && err!=ba::error::eof &&                     // Connection closed by remote host
     138                err!=ba::error::basic_errors::not_connected &&    // Connection closed by remote host
     139                err!=ba::error::basic_errors::operation_aborted)  // Connection closed by us
    49140            {
    50                 //ostringstream str;
    51                 //str << "Open file " << name << ": " << strerror(errno) << " (errno=" << errno << ")";
    52                 //Error(str);
    53 
     141                ostringstream str;
     142                str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
     143                Error(str);
     144            }
     145            PostClose(err!=ba::error::basic_errors::operation_aborted);
     146            return;
     147        }
     148
     149
     150        if (fDebugRx)
     151        {
     152            Out() << kBold << "Received (" << bytes_received << ", " << fBuffer.size() << " bytes):" << endl;
     153            Out() << "-----\n" << string(ba::buffer_cast<const char*>(fBuffer.data()), bytes_received) << "-----\n";
     154        }
     155
     156        istream is(&fBuffer);
     157
     158        string str;
     159        getline(is, str, '\n');
     160
     161        try
     162        {
     163            switch (line)
     164            {
     165            case 1:  Out() << "ID: " << str << endl; break;
     166            case 2:  fData.fVoltageSet      = stof(str); break;
     167            case 3:  fData.fVoltageMeasured = stof(str); break;
     168            case 4:  fData.fCurrentMeasured = stof(str); break;
     169            case 5:  fData.fCurrentLimit    = stof(str); break;
     170            default:
    54171                return;
    55172            }
    56173        }
    57 
    58         fDumpStream << str << endl;
    59     }
    60    
    61 boost::asio::deadline_timer fCheckStatusTimer;
    62 boost::asio::deadline_timer fAntiFloddingTimer;
    63 
    64 void PostStatusRequest()
    65 {
    66     if (IsConnected())
    67     {
    68         PostMessage(string("*IDN?\n"));
    69         PostMessage(string("meas:volt?\n"));
    70         PostMessage(string("meas:curr?\n"));
    71     }
    72 }
    73 
    74 
    75 void RequestStatus()
    76 {
    77     PostStatusRequest();
    78 
    79     fCheckStatusTimer.expires_from_now(boost::posix_time::seconds(60));
    80     fCheckStatusTimer.async_wait(boost::bind(&ConnectionAgilent::HandleRequest,
    81                                       this, bapla::error));
    82 }
    83 
    84 void HandleRequest(const bs::error_code &error)
    85 {
    86     // 125: Operation canceled (bs::error_code(125, bs::system_category))
    87     if (error && error!=ba::error::basic_errors::operation_aborted)
    88     {
    89         ostringstream str;
    90         str << "Write timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
    91         Error(str);
    92 
    93         PostClose(false);
    94         return;
    95     }
    96 
    97     if (!is_open())
    98     {
    99         // For example: Here we could schedule a new accept if we
    100         // would not want to allow two connections at the same time.
    101         PostClose(true);
    102         return;
    103     }
    104 
    105     // Check whether the deadline has passed. We compare the deadline
    106     // against the current time since a new asynchronous operation
    107     // may have moved the deadline before this actor had a chance
    108     // to run.
    109     if (fCheckStatusTimer.expires_at() > ba::deadline_timer::traits_type::now())
    110         return;
    111 
    112     RequestStatus();
    113 }
     174        catch (const exception &e)
     175        {
     176            Error("String conversion failed for '"+str+" ("+e.what()+")");
     177            return;
     178        }
     179
     180        if (line==5)
     181        {
     182            if (fIsVerbose)
     183            {
     184                Out() << "Voltage: " << fData.fVoltageMeasured << "V/" << fData.fVoltageSet   << "V\n";
     185                Out() << "Current: " << fData.fCurrentMeasured << "A/" << fData.fCurrentLimit << "A\n" << endl;
     186            }
     187
     188            UpdateDim(fData);
     189
     190            fLastReceived = Time();
     191
     192            line = 0;
     193
     194        }
     195
     196        StartRead(line);
     197    }
     198
     199
     200    // This is called when a connection was established
     201    void ConnectionEstablished()
     202    {
     203        fBuffer.prepare(1000);
     204
     205        StartRead();
     206        RequestStatus();
     207    }
     208
     209public:
     210
     211    ConnectionAgilent(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
     212        fIsVerbose(true), fDebugRx(false), fTimeout(ioservice), fTimeoutPowerCycle(ioservice)
     213    {
     214        SetLogStream(&imp);
     215    }
     216
     217    void SetVerbose(bool b)
     218    {
     219        fIsVerbose = b;
     220    }
     221
     222    void SetDebugRx(bool b)
     223    {
     224        fDebugRx = b;
     225    }
     226
     227    void SetInterval(uint16_t i)
     228    {
     229        fInterval = i;
     230    }
     231
     232    bool SetPower(bool on)
     233    {
     234        if (!IsConnected())
     235            return false;
     236
     237        if (fLastCommand+boost::posix_time::seconds(59)>Time())
     238        {
     239            Error("Last power command within the last 59 seconds... ignored.");
     240            return false;
     241        }
     242
     243        PostMessage("outp "+string(on?"on":"off")+"\n*IDN?\nvolt?\nmeas:volt?\nmeas:curr?\ncurr?\n");
     244        fLastCommand = Time();
     245
     246        // Stop any pending power cycling
     247        fTimeoutPowerCycle.cancel();
     248
     249        return true;
     250    }
     251
     252    void PowerCycle(uint16_t seconds)
     253    {
     254        if (!SetPower(false))
     255            return;
     256
     257        fTimeoutPowerCycle.expires_from_now(boost::posix_time::seconds(seconds));
     258        fTimeoutPowerCycle.async_wait(boost::bind(&ConnectionAgilent::HandlePowerCycle,
     259                                                  this, dummy::error));
     260    }
     261
     262    int GetState()
     263    {
     264        if (!IsConnected())
     265            return State::kDisconnected;
     266
     267        if (fLastReceived+boost::posix_time::seconds(fInterval*2)<Time())
     268            return State::kDisconnected;
     269
     270        if (fData.fCurrentMeasured<0)
     271            return State::kConnected;
     272
     273        if (fData.fVoltageMeasured<0.1)
     274            return State::kVoltageOff;
     275
     276        if (fData.fVoltageMeasured<fData.fVoltageSet-0.1)
     277            return State::kVoltageLow;
     278
     279        if (fData.fVoltageMeasured>fData.fVoltageSet+0.1)
     280            return State::kVoltageHigh;
     281
     282        return State::kVoltageOn;
     283    }
     284};
     285
     286// ------------------------------------------------------------------------
     287
     288#include "DimDescriptionService.h"
     289
     290class ConnectionDimAgilent : public ConnectionAgilent
     291{
    114292private:
    115293
    116 int  fLineCounter;
    117 
    118 void Start_async_read_until()
    119 {
    120     // Bind Received Data Handler to the event: "received <enter> character"
    121     //   this Handler will try to parse the incoming data
    122     ba::async_read_until(*this, fBuffer, "\n",
    123                          boost::bind(&ConnectionAgilent::ReceivedStatusHandler, this,
    124                                      bapla::error, bapla::bytes_transferred, 0));
    125 
    126     // FIXME: Add timeout here
    127 }
    128 
    129 void ReceivedStatusHandler(const bs::error_code& err, size_t bytes_received, int /*type*/)
    130 {
    131    
    132     // Do not schedule a new read if the connection failed.
    133     if (bytes_received==0 || err)
    134     {
    135         if (err==ba::error::eof)
    136             Warn("Connection closed by remote host (FTM).");
    137 
    138         // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
    139         // 125: Operation canceled
    140         if (err && err!=ba::error::eof &&                     // Connection closed by remote host
    141             err!=ba::error::basic_errors::not_connected &&    // Connection closed by remote host
    142             err!=ba::error::basic_errors::operation_aborted)  // Connection closed by us
    143         {
    144             ostringstream str;
    145             str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
    146             Error(str);
    147         }
    148         PostClose(err!=ba::error::basic_errors::operation_aborted);
    149         return;
    150     }
    151 
    152     if (fIsVerbose)
    153     {
    154        Out() << kBold << "Received (" << bytes_received << " bytes):" << endl;
    155     }
    156     // FIXME: the piece of code below causes a Seg Fault in case
    157     // The Agilent is not listening during program start, then after a while is
    158     // listening and after connection established.
    159     // It sends: 1.) a string and 2.) and empty line (just an <Enter> pressed)
    160     //
    161     // then the agilent_ctrl segfaults ... was able to reproduce it.
    162     // gdp just gave me the hint, that Time().GetAdStr() caused the Seg Fault in a way...
    163     // Is Time threadsafe?
    164     /*
    165     if (fDump)
    166     {
    167         ostringstream msg;
    168         msg << "--- " << Time().GetAsStr() << " --- received " << bytes_received << " bytes.";
    169         Dump(msg.str());
    170     }
    171     */
    172 
    173 
    174     istream is(&fBuffer);
    175     fLineCounter++;
    176 
    177     if (fLineCounter == 1)
    178     {
    179         // this is the Agilent identity string, do nothing
    180         string s;
    181         getline(is,s, '\n');
    182         Out() << "ID string: " << s << endl;
    183     }
    184     else if (fLineCounter == 2)
    185     {
    186         // this should be a float containing the measured voltage
    187         is >> fMeasuredVoltage;
    188         Out() << "voltage: " << fMeasuredVoltage << endl;
    189     }
    190     else if (fLineCounter >= 3)
    191     {
    192         // this should be a float containing the measured voltage
    193         is >> fMeasuredCurrent;
    194         Out() << "current: " << fMeasuredCurrent << endl;
    195         fLineCounter = 0;
    196 
    197         // data should contain two floats:
    198         //  * measured output voltage in volts
    199         //  * measured ouput current in amperes
    200         vector<float> data(2);
    201         data[0] = fMeasuredVoltage;
    202         data[1] = fMeasuredCurrent;
    203         UpdateDim(data);
    204     }
    205    
    206     // read the buffer empty ...
    207     // FIXME: I surely misunderstand that damn fBuffer thing.
    208     // I thought it should be emtpy by now...
    209     string buffer;
    210     while (getline(is,buffer, '\n'))
    211     {
    212         buffer = Tools::Trim(buffer);
    213         if (buffer.empty()) continue;
    214     }
    215 
    216 
    217     if (fMeasuredVoltage > 1.0)
    218     {
    219         fState = State::kVoltage_On;
    220     }
    221     else
    222     {
    223         fState = State::kVoltage_Off;
    224     }
    225     Start_async_read_until();
    226 }
    227 
    228 
    229 // This is called when a connection was established
    230 void ConnectionEstablished()
    231 {
    232     // DN 07.08.2012: The next line is imho not needed.
    233     // But I'm in a train and cannot test it.
    234     fState = State::kConnected;
    235     Start_async_read_until();
    236     RequestStatus();
    237    
    238     fLineCounter = 0;
    239     fBuffer.prepare(1000);
    240 }
     294    DimDescribedService fDim;
     295
     296    void UpdateDim(const Data &data)
     297    {
     298        fDim.Update(data);
     299    }
    241300
    242301public:
    243 
    244 ConnectionAgilent(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
    245     fIsVerbose(true),
    246     fDump(true),
    247     fCheckStatusTimer(ioservice),
    248     fAntiFloddingTimer(ioservice)
    249 {
    250     SetLogStream(&imp);
    251     fState = State::kDisconnected;
    252     fMeasuredVoltage=-1;
    253     fMeasuredCurrent=-1;
    254 }
    255 
    256 void SetVerbose(bool b)
    257 {
    258     fIsVerbose = b;
    259 }
    260 
    261 void SetDumpStream(bool b)
    262 {
    263     fDump = b;
    264 }
    265 
    266 void SetOutput(bool b)
    267 {
    268     if (b)
    269     {
    270         // check if the previous 'outp off' is some time ago
    271         if (fAntiFloddingTimer.expires_at() < ba::deadline_timer::traits_type::now())
    272         {   
    273             if (IsConnected()) PostMessage(string("outp on\n"));
    274         }
    275     }
    276     else
    277     {
    278         if (IsConnected()) PostMessage(string("outp off\n"));
    279         // start a Timer, which runs out in 60sec making sure, that the
    280         // camera can't be switched off&on on short time scales.
    281         // sending repetetive outp off is possible
    282         // sending repetivitve outp on is also posible
    283         // switching off immediately after switching on is also possible.
    284         fAntiFloddingTimer.expires_from_now(boost::posix_time::seconds(60));
    285     }
    286     RequestStatus();
    287 }
    288 
    289 int GetState() const
    290 {
    291     // fState is set in ReceivedStatusHandler
    292     return fState;
    293 }
    294 
    295 
    296 };
    297 
    298 // ------------------------------------------------------------------------
    299 
    300 #include "DimDescriptionService.h"
    301 
    302 class ConnectionDimAgilent : public ConnectionAgilent
    303 {
    304 private:
    305 
    306 DimDescribedService fDim;
    307 
    308 void Update(DimDescribedService &svc, vector<float> data) const
    309 {
    310     svc.Update(data);
    311 }
    312 
    313 void UpdateDim(const vector<float> &data)
    314 {
    315     Update(fDim, data);
    316 }
    317 
    318 
    319 public:
    320 ConnectionDimAgilent(ba::io_service& ioservice, MessageImp &imp) :
    321     ConnectionAgilent(ioservice, imp),
    322     fDim("AGILENT_CONTROL/DATA", "F:1;F:1",
    323                 "|U[V]: output voltage"
    324                 "|I[A]: output current")
    325 {
    326     // nothing happens here.
    327 }
     302    ConnectionDimAgilent(ba::io_service& ioservice, MessageImp &imp) :
     303        ConnectionAgilent(ioservice, imp),
     304        fDim("AGILENT_CONTROL/DATA", "F:1;F:1;F:1;F:1",
     305             "|U_nom[V]: Nominal output voltage"
     306             "|U_mes[V]: Measured output voltage"
     307             "|I_mes[A]: Measured current"
     308             "|I_max[A]: Current limit")
     309    {
     310        // nothing happens here.
     311    }
    328312};
    329313
     
    334318{
    335319private:
    336 S fAgilent;
    337 
    338 int Disconnect()
    339 {
    340     // Close all connections
    341     fAgilent.PostClose(false);
    342 
    343     /*
    344      // Now wait until all connection have been closed and
    345      // all pending handlers have been processed
    346      poll();
    347      */
    348 
    349     return T::GetCurrentState();
    350 }
    351 
    352 int Reconnect(const EventImp &evt)
    353 {
    354     // Close all connections to supress the warning in SetEndpoint
    355     fAgilent.PostClose(false);
    356 
    357     // Now wait until all connection have been closed and
    358     // all pending handlers have been processed
    359     poll();
    360 
    361     if (evt.GetBool())
    362         fAgilent.SetEndpoint(evt.GetString());
    363 
    364     // Now we can reopen the connection
    365     fAgilent.PostClose(true);
    366 
    367     return T::GetCurrentState();
    368 }
    369 
    370 int Execute()
    371 {
    372     // Dispatch (execute) at most one handler from the queue. In contrary
    373     // to run_one(), it doesn't wait until a handler is available
    374     // which can be dispatched, so poll_one() might return with 0
    375     // handlers dispatched. The handlers are always dispatched/executed
    376     // synchronously, i.e. within the call to poll_one()
    377     poll_one();
    378    
    379     if ( fAgilent.IsConnected() )
     320    S fAgilent;
     321
     322    int Disconnect()
     323    {
     324        // Close all connections
     325        fAgilent.PostClose(false);
     326
     327        /*
     328         // Now wait until all connection have been closed and
     329         // all pending handlers have been processed
     330         poll();
     331         */
     332
     333        return T::GetCurrentState();
     334    }
     335
     336    int Reconnect(const EventImp &evt)
     337    {
     338        // Close all connections to supress the warning in SetEndpoint
     339        fAgilent.PostClose(false);
     340
     341        // Now wait until all connection have been closed and
     342        // all pending handlers have been processed
     343        poll();
     344
     345        if (evt.GetBool())
     346            fAgilent.SetEndpoint(evt.GetString());
     347
     348        // Now we can reopen the connection
     349        fAgilent.PostClose(true);
     350
     351        return T::GetCurrentState();
     352    }
     353
     354    int Execute()
     355    {
     356        // Dispatch (execute) at most one handler from the queue. In contrary
     357        // to run_one(), it doesn't wait until a handler is available
     358        // which can be dispatched, so poll_one() might return with 0
     359        // handlers dispatched. The handlers are always dispatched/executed
     360        // synchronously, i.e. within the call to poll_one()
     361        poll_one();
     362
     363        if (!fAgilent.IsConnected())
     364            return State::kDisconnected;
     365
    380366        return fAgilent.GetState();
    381     else
    382             return State::kDisconnected;
    383367    }
    384368
     
    404388    }
    405389
    406     int SetDumpStream(const EventImp &evt)
    407     {
    408         if (!CheckEventSize(evt.GetSize(), "SetDumpStream", 1))
     390    int SetDebugRx(const EventImp &evt)
     391    {
     392        if (!CheckEventSize(evt.GetSize(), "SetDebugRx", 1))
    409393            return T::kSM_FatalError;
    410394
    411         fAgilent.SetDumpStream(evt.GetBool());
     395        fAgilent.SetDebugRx(evt.GetBool());
    412396
    413397        return T::GetCurrentState();
    414398    }
    415399
    416     int SetOutput(const EventImp &evt)
    417     {
    418         if (!CheckEventSize(evt.GetSize(), "SetOutput", 1))
     400    int SetPower(const EventImp &evt)
     401    {
     402        if (!CheckEventSize(evt.GetSize(), "SetPower", 1))
    419403            return T::kSM_FatalError;
    420404
    421         fAgilent.SetOutput(evt.GetBool());
     405        fAgilent.SetPower(evt.GetBool());
     406
     407        return T::GetCurrentState();
     408    }
     409
     410    int PowerCycle(const EventImp &evt)
     411    {
     412        if (!CheckEventSize(evt.GetSize(), "PowerCyle", 2))
     413            return T::kSM_FatalError;
     414
     415        if (evt.GetShort()<60)
     416        {
     417            T::Warn("Power cycle delays of less than 60s not allowed.");
     418            return T::GetCurrentState();
     419        }
     420
     421        fAgilent.PowerCycle(evt.GetShort());
    422422
    423423        return T::GetCurrentState();
     
    439439        // State names
    440440        T::AddStateName(State::kDisconnected, "Disconnected",
    441                      "Agilent not connected via ethernet.");
    442 
     441                        "Agilent not connected via ethernet.");
    443442        T::AddStateName(State::kConnected, "Connected",
    444                      "Ethernet connection to Agilent established.");
    445 
    446         T::AddStateName(State::kVoltage_On, "Voltage_On",
    447                      "The measured output voltage is higher than 1.0V");
    448 
    449         T::AddStateName(State::kVoltage_Off, "Voltage_Off",
    450                      "The measured output voltage is lower than 1.0V");
     443                        "Ethernet connection to Agilent established, but not data received yet.");
     444
     445        T::AddStateName(State::kVoltageOff, "VoltageOff",
     446                        "The measured output voltage is lower than 0.1V");
     447        T::AddStateName(State::kVoltageLow, "VoltageLow",
     448                        "The measured output voltage is higher than 0.1V, but lower than the command voltage");
     449        T::AddStateName(State::kVoltageOn, "VoltageOn",
     450                        "The measured output voltage is higher than 0.1V and comparable to the command voltage");
     451        T::AddStateName(State::kVoltageHigh, "VoltageHigh",
     452                        "The measured output voltage is higher than the command voltage!");
    451453
    452454        // Verbosity commands
     
    456458             "|verbosity[bool]:disable or enable verbosity for received data (yes/no)");
    457459
    458         T::AddEvent("DUMP_STREAM", "B:1")
    459             (bind(&StateMachineAgilent::SetDumpStream, this, placeholders::_1))
    460             (""
    461              "");
     460        T::AddEvent("SET_DEBUG_RX", "B:1")
     461            (bind(&StateMachineAgilent::SetVerbosity, this, placeholders::_1))
     462            ("set debug state"
     463             "|debug[bool]:disable or enable verbosity for received raw data (yes/no)");
     464
     465        T::AddEvent("SET_POWER", "B:1")
     466            (bind(&StateMachineAgilent::SetPower, this, placeholders::_1))
     467            ("Enable or disable power output"
     468             "|output[bool]:set power output to 'on' or 'off'");
     469
     470        T::AddEvent("POWER_CYCLE", "S:1")
     471            (bind(&StateMachineAgilent::PowerCycle, this, placeholders::_1))
     472            ("Power cycle the power output"
     473             "|delay[short]:Defines the delay between switching off and on.");
     474
    462475
    463476        // Conenction commands
     
    471484             "|[host][string]:new ethernet address in the form <host:port>");
    472485
    473         T::AddEvent("OUTPUT", "B:1")
    474             (bind(&StateMachineAgilent::SetOutput, this, placeholders::_1))
    475             ("set output on or off"
    476              "|[state][boolean]: output setting (1;0 or 'on';'off')");
    477 
    478486        fAgilent.StartConnect();
    479487    }
     
    487495    {
    488496        fAgilent.SetVerbose(!conf.Get<bool>("quiet"));
     497        fAgilent.SetDebugRx(conf.Get<bool>("debug-rx"));
     498        fAgilent.SetInterval(conf.Get<uint16_t>("interval"));
    489499
    490500        SetEndpoint(conf.Get<string>("addr"));
     
    508518    po::options_description control("agilent_ctrl control options");
    509519    control.add_options()
    510         ("no-dim",        po_bool(),  "Disable dim services")
    511 //        ("addr,a",        var<string>("localhost:8080"),  "network address of Agilent")
    512         ("addr,a",        var<string>("10.0.100.220:5025"),  "network address of Agilent")
    513         ("quiet,q",       po_bool(true),  "Disable printing contents of all received messages (except dynamic data) in clear text.")
     520        ("no-dim",    po_bool(),         "Disable dim services")
     521        ("addr,a",    var<string>("10.0.100.220:5025"),  "network address of Agilent")
     522        ("debug-rx",  po_bool(false),    "Enable raw debug output wehen receiving data")
     523        ("interval",  var<uint16_t>(15), "Interval in seconds in which the Agilent status is requested")
     524        ("quiet,q",   po_bool(true),     "Disable printing contents of all received messages (except dynamic data) in clear text.")
    514525        ;
    515526
     
    529540{
    530541    cout <<
    531         "The agilentctrl controls the FACT camera power supply.\n"
    532         "The powersupply is made by Agilent, so we call it 'The Agilent'. \n"
    533         "Since FACT uses three Agilent Power Supplies with different output voltages\n"
    534         "one might still not now which one ist controlled by this Program, so:\n"
     542        "The agilentctrl controls the FACT camera power supply.\n\n"
    535543        "\n"
    536         "This program controls the 48V Agilent."
    537         "\n"
    538         "The default is that the program is started with user intercation. "
     544        "The default is that the program is started without user intercation. "
    539545        "All actions are supposed to arrive as DimCommands. Using the -c "
    540546        "option, a local shell can be initialized. With h or help a short "
Note: See TracChangeset for help on using the changeset viewer.