Changeset 14325 for trunk/FACT++
- Timestamp:
- 08/07/12 23:12:23 (13 years ago)
- File:
-
- 1 edited
-
trunk/FACT++/src/agilentctrl.cc (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/agilentctrl.cc
r14324 r14325 59 59 } 60 60 61 boost::asio::deadline_timer fCheckStatusTimer; 62 boost::asio::deadline_timer fAntiFloddingTimer; 63 64 void PostStatusRequest() 65 { 66 PostMessage(string("*IDN?\n")); 67 PostMessage(string("meas:volt?\n")); 68 PostMessage(string("meas:curr?\n")); 69 } 70 61 boost::asio::deadline_timer fCheckStatusTimer; 62 boost::asio::deadline_timer fAntiFloddingTimer; 63 64 void PostStatusRequest() 65 { 66 PostMessage(string("*IDN?\n")); 67 PostMessage(string("meas:volt?\n")); 68 PostMessage(string("meas:curr?\n")); 69 } 70 71 72 void RequestStatus() 73 { 74 PostStatusRequest(); 75 76 fCheckStatusTimer.expires_from_now(boost::posix_time::seconds(60)); 77 fCheckStatusTimer.async_wait(boost::bind(&ConnectionAgilent::HandleRequest, 78 this, bapla::error)); 79 } 80 81 void HandleRequest(const bs::error_code &error) 82 { 83 // 125: Operation canceled (bs::error_code(125, bs::system_category)) 84 if (error && error!=ba::error::basic_errors::operation_aborted) 85 { 86 ostringstream str; 87 str << "Write timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl; 88 Error(str); 89 90 PostClose(false); 91 return; 92 } 93 94 if (!is_open()) 95 { 96 // For example: Here we could schedule a new accept if we 97 // would not want to allow two connections at the same time. 98 PostClose(true); 99 return; 100 } 101 102 // Check whether the deadline has passed. We compare the deadline 103 // against the current time since a new asynchronous operation 104 // may have moved the deadline before this actor had a chance 105 // to run. 106 if (fCheckStatusTimer.expires_at() > ba::deadline_timer::traits_type::now()) 107 return; 108 109 RequestStatus(); 110 } 111 private: 112 113 int fLineCounter; 114 115 void Start_async_read_until() 116 { 117 // Bind Received Data Handler to the event: "received <enter> character" 118 // this Handler will try to parse the incoming data 119 ba::async_read_until(*this, fBuffer, "\n", 120 boost::bind(&ConnectionAgilent::ReceivedStatusHandler, this, 121 bapla::error, bapla::bytes_transferred, 0)); 122 123 // FIXME: Add timeout here 124 } 125 126 void ReceivedStatusHandler(const bs::error_code& err, size_t bytes_received, int /*type*/) 127 { 71 128 72 void RequestStatus() 73 { 74 PostStatusRequest(); 75 76 fCheckStatusTimer.expires_from_now(boost::posix_time::seconds(60)); 77 fCheckStatusTimer.async_wait(boost::bind(&ConnectionAgilent::HandleRequest, 78 this, bapla::error)); 79 } 80 81 void HandleRequest(const bs::error_code &error) 82 { 83 // 125: Operation canceled (bs::error_code(125, bs::system_category)) 84 if (error && error!=ba::error::basic_errors::operation_aborted) 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 85 140 { 86 141 ostringstream str; 87 str << " Write timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;142 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl; 88 143 Error(str); 89 90 PostClose(false);91 return;92 144 } 93 94 if (!is_open()) 145 PostClose(err!=ba::error::basic_errors::operation_aborted); 146 return; 147 } 148 149 if (fIsVerbose) 150 { 151 Out() << kBold << "Received (" << bytes_received << " bytes):" << endl; 152 } 153 // FIXME: the piece of code below causes a Seg Fault in case 154 // The Agilent is not listening during program start, then after a while is 155 // listening and after connection established. 156 // It sends: 1.) a string and 2.) and empty line (just an <Enter> pressed) 157 // 158 // then the agilent_ctrl segfaults ... was able to reproduce it. 159 // gdp just gave me the hint, that Time().GetAdStr() caused the Seg Fault in a way... 160 // Is Time threadsafe? 161 /* 162 if (fDump) 163 { 164 ostringstream msg; 165 msg << "--- " << Time().GetAsStr() << " --- received " << bytes_received << " bytes."; 166 Dump(msg.str()); 167 } 168 */ 169 170 171 istream is(&fBuffer); 172 fLineCounter++; 173 174 if (fLineCounter == 1) 175 { 176 // this is the Agilent identity string, do nothing 177 string s; 178 getline(is,s, '\n'); 179 Out() << "ID string: " << s << endl; 180 } 181 else if (fLineCounter == 2) 182 { 183 // this should be a float containing the measured voltage 184 is >> fMeasuredVoltage; 185 Out() << "voltage: " << fMeasuredVoltage << endl; 186 } 187 else if (fLineCounter >= 3) 188 { 189 // this should be a float containing the measured voltage 190 is >> fMeasuredCurrent; 191 Out() << "current: " << fMeasuredCurrent << endl; 192 fLineCounter = 0; 193 194 // data should contain two floats: 195 // * measured output voltage in volts 196 // * measured ouput current in amperes 197 vector<float> data(2); 198 data[0] = fMeasuredVoltage; 199 data[1] = fMeasuredCurrent; 200 UpdateDim(data); 201 } 202 203 // read the buffer empty ... 204 // FIXME: I surely misunderstand that damn fBuffer thing. 205 // I thought it should be emtpy by now... 206 string buffer; 207 while (getline(is,buffer, '\n')) 208 { 209 buffer = Tools::Trim(buffer); 210 if (buffer.empty()) continue; 211 } 212 213 214 if (fMeasuredVoltage > 1.0) 215 { 216 fState = State::kVoltage_On; 217 } 218 else 219 { 220 fState = State::kVoltage_Off; 221 } 222 Start_async_read_until(); 223 } 224 225 226 // This is called when a connection was established 227 void ConnectionEstablished() 228 { 229 // DN 07.08.2012: The next line is imho not needed. 230 // But I'm in a train and cannot test it. 231 fState = State::kConnected; 232 Start_async_read_until(); 233 RequestStatus(); 234 235 fLineCounter = 0; 236 fBuffer.prepare(1000); 237 } 238 239 public: 240 241 ConnectionAgilent(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()), 242 fIsVerbose(true), 243 fDump(true), 244 fCheckStatusTimer(ioservice), 245 fAntiFloddingTimer(ioservice) 246 { 247 SetLogStream(&imp); 248 fState = State::kDisconnected; 249 fMeasuredVoltage=-1; 250 fMeasuredCurrent=-1; 251 } 252 253 void SetVerbose(bool b) 254 { 255 fIsVerbose = b; 256 } 257 258 void SetDumpStream(bool b) 259 { 260 fDump = b; 261 } 262 263 void SetOutput(bool b) 264 { 265 if (b) 266 { 267 // check if the previous 'outp off' is some time ago 268 if (fAntiFloddingTimer.expires_at() < ba::deadline_timer::traits_type::now()) 95 269 { 96 // For example: Here we could schedule a new accept if we 97 // would not want to allow two connections at the same time. 98 PostClose(true); 99 return; 270 PostMessage(string("outp on\n")); 100 271 } 101 102 // Check whether the deadline has passed. We compare the deadline 103 // against the current time since a new asynchronous operation 104 // may have moved the deadline before this actor had a chance 105 // to run. 106 if (fCheckStatusTimer.expires_at() > ba::deadline_timer::traits_type::now()) 107 return; 108 109 RequestStatus(); 110 } 272 } 273 else 274 { 275 PostMessage(string("outp off\n")); 276 // start a Timer, which runs out in 60sec making sure, that the 277 // camera can't be switched off&on on short time scales. 278 // sending repetetive outp off is possible 279 // sending repetivitve outp on is also posible 280 // switching off immediately after switching on is also possible. 281 fAntiFloddingTimer.expires_from_now(boost::posix_time::seconds(60)); 282 } 283 RequestStatus(); 284 } 285 286 int GetState() const 287 { 288 // fState is set in ReceivedStatusHandler 289 return fState; 290 } 291 292 293 }; 294 295 // ------------------------------------------------------------------------ 296 297 #include "DimDescriptionService.h" 298 299 class ConnectionDimAgilent : public ConnectionAgilent 300 { 111 301 private: 112 302 113 int fLineCounter; 114 115 void Start_async_read_until() 116 { 117 // Bind Received Data Handler to the event: "received <enter> character" 118 // this Handler will try to parse the incoming data 119 ba::async_read_until(*this, fBuffer, "\n", 120 boost::bind(&ConnectionAgilent::ReceivedStatusHandler, this, 121 bapla::error, bapla::bytes_transferred, 0)); 122 123 // FIXME: Add timeout here 124 } 125 126 void ReceivedStatusHandler(const bs::error_code& err, size_t bytes_received, int /*type*/) 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 140 { 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 if (fIsVerbose) 150 { 151 Out() << kBold << "Received (" << bytes_received << " bytes):" << endl; 152 } 153 // FIXME: the piece of code below causes a Seg Fault in case 154 // The Agilent is not listening during program start, then after a while is 155 // listening and after connection established. 156 // It sends: 1.) a string and 2.) and empty line (just an <Enter> pressed) 157 // 158 // then the agilent_ctrl segfaults ... was able to reproduce it. 159 // gdp just gave me the hint, that Time().GetAdStr() caused the Seg Fault in a way... 160 // Is Time threadsafe? 161 /* 162 if (fDump) 163 { 164 ostringstream msg; 165 msg << "--- " << Time().GetAsStr() << " --- received " << bytes_received << " bytes."; 166 Dump(msg.str()); 167 } 168 */ 169 170 171 istream is(&fBuffer); 172 fLineCounter++; 173 174 if (fLineCounter == 1) 175 { 176 // this is the Agilent identity string, do nothing 177 string s; 178 getline(s,buffer, '\n'); 179 Out() << "ID string: " << s << endl; 180 } 181 else if (fLineCounter == 2) 182 { 183 // this should be a float containing the measured voltage 184 is >> fMeasuredVoltage; 185 Out() << "voltage: " << fMeasuredVoltage << endl; 186 } 187 else if (fLineCounter >= 3) 188 { 189 // this should be a float containing the measured voltage 190 is >> fMeasuredCurrent; 191 Out() << "current: " << fMeasuredCurrent << endl; 192 fLineCounter = 0; 193 194 // data should contain two floats: 195 // * measured output voltage in volts 196 // * measured ouput current in amperes 197 vector<float> data(2); 198 data[0] = fMeasuredVoltage; 199 data[1] = fMeasuredCurrent; 200 UpdateDim(data); 201 } 202 203 // read the buffer empty ... 204 // FIXME: I surely misunderstand that damn fBuffer thing. 205 // I thought it should be emtpy by now... 206 string buffer; 207 while (getline(is,buffer, '\n')) 208 { 209 buffer = Tools::Trim(buffer); 210 if (buffer.empty()) continue; 211 } 212 213 214 if (fMeasuredVoltage > 1.0) 215 { 216 fState = State::kVoltage_On; 217 } 218 else 219 { 220 fState = State::kVoltage_Off; 221 } 222 Start_async_read_until(); 223 } 224 225 226 // This is called when a connection was established 227 void ConnectionEstablished() 228 { 229 // DN 07.08.2012: The next line is imho not needed. 230 // But I'm in a train and cannot test it. 231 fState = State::kConnected; 232 Start_async_read_until(); 233 RequestStatus(); 234 235 fLineCounter = 0; 236 fBuffer.prepare(1000); 237 } 303 DimDescribedService fDim; 304 305 void Update(DimDescribedService &svc, vector<float> data) const 306 { 307 svc.Update(data); 308 } 309 310 void UpdateDim(const vector<float> &data) 311 { 312 Update(fDim, data); 313 } 314 238 315 239 316 public: 240 241 ConnectionAgilent(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()), 242 fIsVerbose(true), 243 fDump(true), 244 fCheckStatusTimer(ioservice), 245 fAntiFloddingTimer(ioservice) 246 { 247 SetLogStream(&imp); 248 fState = State::kDisconnected; 249 fMeasuredVoltage=-1; 250 fMeasuredCurrent=-1; 251 } 252 253 void SetVerbose(bool b) 254 { 255 fIsVerbose = b; 256 } 257 258 void SetDumpStream(bool b) 259 { 260 fDump = b; 261 } 262 263 void SetOutput(bool b) 264 { 265 if (b) 266 { 267 // check if the previous 'outp off' is some time ago 268 if (fAntiFloddingTimer.expires_at() > ba::deadline_timer::traits_type::now()) 269 { 270 PostMessage(string("outp on\n")); 271 } 272 } 273 else 274 { 275 PostMessage(string("outp off\n")); 276 // start a Timer, which runs out in 60sec making sure, that the 277 // camera can't be switched off&on on short time scales. 278 // sending repetetive outp off is possible 279 // sending repetivitve outp on is also posible 280 // switching off immediately after switching on is also possible. 281 fAntiFloddingTimer.expires_from_now(boost::posix_time::seconds(60)); 282 } 283 RequestStatus(); 284 } 285 286 int GetState() const 287 { 288 // fState is set in ReceivedStatusHandler 289 return fState; 290 } 291 292 293 }; 294 295 // ------------------------------------------------------------------------ 296 297 #include "DimDescriptionService.h" 298 299 class ConnectionDimAgilent : public ConnectionAgilent 300 { 301 private: 302 303 DimDescribedService fDim; 304 305 void Update(DimDescribedService &svc, vector<float> data) const 306 { 307 svc.Update(data); 308 } 309 310 void UpdateDim(const vector<float> &data) 311 { 312 Update(fDim, data); 313 } 314 315 316 public: 317 ConnectionDimAgilent(ba::io_service& ioservice, MessageImp &imp) : 318 ConnectionAgilent(ioservice, imp), 319 fDim("AGILENT_CONTROL/DATA", "F:1;F:1", 320 "|U[V]: output voltage" 321 "|I[A]: output current") 322 { 323 // nothing happens here. 324 } 317 ConnectionDimAgilent(ba::io_service& ioservice, MessageImp &imp) : 318 ConnectionAgilent(ioservice, imp), 319 fDim("AGILENT_CONTROL/DATA", "F:1;F:1", 320 "|U[V]: output voltage" 321 "|I[A]: output current") 322 { 323 // nothing happens here. 324 } 325 325 }; 326 326 … … 331 331 { 332 332 private: 333 S fAgilent;334 335 int Disconnect()336 {337 // Close all connections338 fAgilent.PostClose(false);339 340 /*341 // Now wait until all connection have been closed and342 // all pending handlers have been processed343 poll();344 */345 346 return T::GetCurrentState();347 }348 349 int Reconnect(const EventImp &evt)350 {351 // Close all connections to supress the warning in SetEndpoint352 fAgilent.PostClose(false);353 354 // Now wait until all connection have been closed and355 // all pending handlers have been processed356 poll();357 358 if (evt.GetBool())359 fAgilent.SetEndpoint(evt.GetString());360 361 // Now we can reopen the connection362 fAgilent.PostClose(true);363 364 return T::GetCurrentState();365 }366 367 int Execute()368 {369 // Dispatch (execute) at most one handler from the queue. In contrary370 // to run_one(), it doesn't wait until a handler is available371 // which can be dispatched, so poll_one() might return with 0372 // handlers dispatched. The handlers are always dispatched/executed373 // synchronously, i.e. within the call to poll_one()374 poll_one();375 376 if ( fAgilent.IsConnected() )377 return fAgilent.GetState();378 else333 S fAgilent; 334 335 int Disconnect() 336 { 337 // Close all connections 338 fAgilent.PostClose(false); 339 340 /* 341 // Now wait until all connection have been closed and 342 // all pending handlers have been processed 343 poll(); 344 */ 345 346 return T::GetCurrentState(); 347 } 348 349 int Reconnect(const EventImp &evt) 350 { 351 // Close all connections to supress the warning in SetEndpoint 352 fAgilent.PostClose(false); 353 354 // Now wait until all connection have been closed and 355 // all pending handlers have been processed 356 poll(); 357 358 if (evt.GetBool()) 359 fAgilent.SetEndpoint(evt.GetString()); 360 361 // Now we can reopen the connection 362 fAgilent.PostClose(true); 363 364 return T::GetCurrentState(); 365 } 366 367 int Execute() 368 { 369 // Dispatch (execute) at most one handler from the queue. In contrary 370 // to run_one(), it doesn't wait until a handler is available 371 // which can be dispatched, so poll_one() might return with 0 372 // handlers dispatched. The handlers are always dispatched/executed 373 // synchronously, i.e. within the call to poll_one() 374 poll_one(); 375 376 if ( fAgilent.IsConnected() ) 377 return fAgilent.GetState(); 378 else 379 379 return State::kDisconnected; 380 380 }
Note:
See TracChangeset
for help on using the changeset viewer.
