192 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| #include "PollingTransceiver.hpp"
 | |
| 
 | |
| #include <exception>
 | |
| 
 | |
| #include <QObject>
 | |
| #include <QString>
 | |
| #include <QTimer>
 | |
| 
 | |
| #include "moc_PollingTransceiver.cpp"
 | |
| 
 | |
| namespace
 | |
| {
 | |
|   unsigned const polls_to_stabilize {3};
 | |
| }
 | |
| 
 | |
| PollingTransceiver::PollingTransceiver (int poll_interval, QObject * parent)
 | |
|   : TransceiverBase {parent}
 | |
|   , interval_ {poll_interval * 1000}
 | |
|   , poll_timer_ {nullptr}
 | |
|   , retries_ {0}
 | |
| {
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::start_timer ()
 | |
| {
 | |
|   if (interval_)
 | |
|     {
 | |
|       if (!poll_timer_)
 | |
|         {
 | |
|           poll_timer_ = new QTimer {this}; // pass ownership to
 | |
|                                            // QObject which handles
 | |
|                                            // destruction for us
 | |
| 
 | |
|           connect (poll_timer_, &QTimer::timeout, this,
 | |
|                    &PollingTransceiver::handle_timeout);
 | |
|         }
 | |
|       poll_timer_->start (interval_);
 | |
|     }
 | |
|   else
 | |
|     {
 | |
|       stop_timer ();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::stop_timer ()
 | |
| {
 | |
|   if (poll_timer_)
 | |
|     {
 | |
|       poll_timer_->stop ();
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_post_start ()
 | |
| {
 | |
|   start_timer ();
 | |
|   if (!next_state_.online ())
 | |
|     {
 | |
|       // remember that we are expecting to go online
 | |
|       next_state_.online (true);
 | |
|       retries_ = polls_to_stabilize;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_post_stop ()
 | |
| {
 | |
|   // not much point waiting for rig to go offline since we are ceasing
 | |
|   // polls
 | |
|   stop_timer ();
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_post_frequency (Frequency f, MODE m)
 | |
| {
 | |
|   // take care not to set the expected next mode to unknown since some
 | |
|   // callers use mode == unknown to signify that they do not know the
 | |
|   // mode and don't care
 | |
|   if (next_state_.frequency () != f || (m != UNK && next_state_.mode () != m))
 | |
|     {
 | |
|       // update expected state with new frequency and set poll count
 | |
|       next_state_.frequency (f);
 | |
|       if (m != UNK)
 | |
|         {
 | |
|           next_state_.mode (m);
 | |
|         }
 | |
|       retries_ = polls_to_stabilize;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_post_tx_frequency (Frequency f, MODE)
 | |
| {
 | |
|   if (next_state_.tx_frequency () != f)
 | |
|     {
 | |
|       // update expected state with new TX frequency and set poll
 | |
|       // count
 | |
|       next_state_.tx_frequency (f);
 | |
|       next_state_.split (f); // setting non-zero TX frequency means split
 | |
|       retries_ = polls_to_stabilize;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_post_mode (MODE m)
 | |
| {
 | |
|   // we don't ever expect mode to goto to unknown
 | |
|   if (m != UNK && next_state_.mode () != m)
 | |
|     {
 | |
|       // update expected state with new mode and set poll count
 | |
|       next_state_.mode (m);
 | |
|       retries_ = polls_to_stabilize;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_post_ptt (bool p)
 | |
| {
 | |
|   if (next_state_.ptt () != p)
 | |
|     {
 | |
|       // update expected state with new PTT and set poll count
 | |
|       next_state_.ptt (p);
 | |
|       retries_ = polls_to_stabilize;
 | |
|       //retries_ = 0;             // fast feedback on PTT
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool PollingTransceiver::do_pre_update ()
 | |
| {
 | |
|   // if we are holding off a change then withhold the signal
 | |
|   if (retries_ && state () != next_state_)
 | |
|     {
 | |
|       return false;
 | |
|     }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::do_sync (bool force_signal, bool no_poll)
 | |
| {
 | |
|   if (!no_poll) poll ();        // tell sub-classes to update our state
 | |
| 
 | |
|   // Signal new state if it is directly requested or, what we expected
 | |
|   // or, hasn't become what we expected after polls_to_stabilize
 | |
|   // polls. Unsolicited changes will be signalled immediately unless
 | |
|   // they intervene in a expected sequence where they will be delayed.
 | |
|   if (retries_)
 | |
|     {
 | |
|       --retries_;
 | |
|       if (force_signal || state () == next_state_ || !retries_)
 | |
|         {
 | |
|           // our client wants a signal regardless
 | |
|           // or the expected state has arrived
 | |
|           // or there are no more retries
 | |
|           force_signal = true;
 | |
|         }
 | |
|     }
 | |
|   else if (force_signal || state () != last_signalled_state_)
 | |
|     {
 | |
|       // here is the normal passive polling path either our client has
 | |
|       // requested a state update regardless of change or state has
 | |
|       // changed asynchronously
 | |
|       force_signal = true;
 | |
|     }
 | |
| 
 | |
|   if (force_signal)
 | |
|     {
 | |
|       // reset everything, record and signal the current state
 | |
|       retries_ = 0;
 | |
|       next_state_ = state ();
 | |
|       last_signalled_state_ = state ();
 | |
|       update_complete (true);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void PollingTransceiver::handle_timeout ()
 | |
| {
 | |
|   QString message;
 | |
| 
 | |
|   // we must catch all exceptions here since we are called by Qt and
 | |
|   // inform our parent of the failure via the offline() message
 | |
|   try
 | |
|     {
 | |
|       do_sync ();
 | |
|     }
 | |
|   catch (std::exception const& e)
 | |
|     {
 | |
|       message = e.what ();
 | |
|     }
 | |
|   catch (...)
 | |
|     {
 | |
|       message = tr ("Unexpected rig error");
 | |
|     }
 | |
|   if (!message.isEmpty ())
 | |
|     {
 | |
|       offline (message);
 | |
|     }
 | |
| }
 | 
