/// <summary>
        /// Unpause the service, and immediately force it to update the charge status.
        /// </summary>
        public void Restart()
        {
            Log.Debug(Name + " Restarting...");
            lock (this)
            {
                // Setting the interval equal to executeInterval will cause the charge status
                // to be updated on the service's next 'tick'.
                _currentInterval = new TimeSpan(_executeInterval.Ticks);

                // Whenever we restart the service, assume a docked instrument is charging (until we find out otherwise)
                if (IsBatteryRechargable())
                {
                    State  = ChargingState.Charging;
                    _phase = ChargePhase.FullCharge;
                }
                else
                {
                    //State = ChargingState.NotCharging;
                    _phase = ChargePhase.ChargeOff;
                }

                _phaseStart = DateTime.UtcNow;

                Paused = false;
            }
        }
        /// <summary>
        /// Helper method for Run() which communicates with instrument to determine its charging status
        /// then updates charger service status properties
        /// </summary>
        private void RunUpdateChargerState()
        {
            const string funcName = "RunUpdateChargerState";

            Log.Debug(string.Format("{0} invoking {1} on a \"{2}\" battery", Name, funcName, BatteryCode));

            if (!Controller.IsDocked())
            {
                Log.Debug(string.Format("{0}: instrument undocked.", funcName));
                return;
            }

            try
            {
                InstrumentChargingOperation op = new InstrumentChargingOperation();

                op.Execute();

                // Keep track of consecutively occurring phases, and when they first occur.
                if (_phase != op.InstrumentChargePhase)
                {
                    _phase      = op.InstrumentChargePhase;
                    _phaseStart = DateTime.UtcNow;
                }

                // If instrument is having any charging problems, report the error to server.
                // This will also allow the error to upload to iNet if they're an inet customer.
                if (_phase == ISC.iNet.DS.DomainModel.ChargePhase.ChargeFailure ||
                    _phase == ISC.iNet.DS.DomainModel.ChargePhase.ChargeFault
                    //                ||   _phase == ISC.iNet.DS.DomainModel.ChargePhase.ChargeOverTempFailure
                    //                ||   _phase == ISC.iNet.DS.DomainModel.ChargePhase.ChargeUnderTempFailure
                    //                ||   _phase == ISC.iNet.DS.DomainModel.ChargePhase.ChargeOff ( AND battery is lithium )
                    || _phase == ISC.iNet.DS.DomainModel.ChargePhase.PreChargeFault ||
                    _phase == ISC.iNet.DS.DomainModel.ChargePhase.ChargeTimeout)
                {
                    // Do not change this message.  iNet is parsing it!
                    string msg = string.Format("Instrument \"{0}\" has reported a \"{1}\" charging error (Battery=\"{2}\", type=\"{3}\").",
                                               op.InstrumentSerialNumber, _phase.ToString(), op.BatterySerialNumber, op.BatteryCode);
                    Master.ReporterService.ReportError(new DockingStationError(msg, DockingStationErrorLevel.Warning, op.InstrumentSerialNumber));
                }

                // BatteryCode should be empty if user has docked a completely dead
                // battery.  If the instrument has now charged up enough such that we
                // can now talk to it, then get the battery type.
                if (BatteryCode == string.Empty)
                {
                    BatteryCode = op.BatteryCode;
                }

                if (op.ChargingState == ChargingState.Error)
                {
                    // How much time has elasped between now and when we first saw the
                    // instrument go into error?

                    TimeSpan errorTimeElapsed = DateTime.UtcNow - _phaseStart;

                    Log.Debug(string.Format("{0} - BATTERY IN {1} PHASE!  ELAPSED TIME: {2}", Name, _phase.ToString(), errorTimeElapsed.ToString()));

                    // Instrument hasn't been in error too long?  Then
                    // just treat it as if the intrument is normally charging; no need to
                    // scare the user.  But if it's been stuck in error too
                    // long, then finally just report it as an error.

                    TimeSpan maxTimeAllowed = (_phase == ChargePhase.ChargeOverTempFailure || _phase == ChargePhase.ChargeUnderTempFailure) ? _maxTempFailureTimeAllowed : _maxErrorPhaseAllowed;

                    if (errorTimeElapsed <= maxTimeAllowed)
                    {
                        State = ChargingState.Charging;
                    }
                    else
                    {
                        State = ChargingState.Error;

                        // Do not change this message.  iNet is parsing it!
                        string msg = string.Format("Instrument \"{0}\" has been in \"{1}\" for an overextended period of time ({2}). (Battery=\"{3}\", type=\"{4}\")",
                                                   op.InstrumentSerialNumber, _phase.ToString(), errorTimeElapsed.ToString(), op.BatterySerialNumber, op.BatteryCode);

                        Log.Error(string.Format("{0} - {1}", Name, msg.ToUpper()));
                        Log.Error(string.Format("{0} - Reporting {1} to server", Name, op.InstrumentChargePhase.ToString()));

                        Master.ReporterService.ReportError(new DockingStationError(msg, DockingStationErrorLevel.Warning, op.InstrumentSerialNumber));
                    }
                }                 // end ChargingState.Error

                else              // op.State != ChargingState.Error
                {
                    State = op.ChargingState;
                }

                Log.Debug(Name + " - ChargingState=" + State);

                // When instrument is done charging, then turn it off!
                if (State == ChargingState.NotCharging)
                {
                    Log.Debug(Name + " - INSTRUMENT APPEARS FULLY CHARGED. TURNING OFF INSTRUMENT.");
                    Log.Debug(Name + " - WILL NO LONGER POLL INSTRUMENT FOR CHARGING STATUS.");
                    new InstrumentTurnOffOperation(InstrumentTurnOffOperation.Reason.ChargingComplete).Execute();
                }
            }
            catch (InstrumentPingFailedException e)
            {
                Log.Error(Name, e);
                if (!Controller.IsDocked())                   // May have got the exception because they undocked. Ignore it.
                {
                    State = ChargingState.NotCharging;
                }
                else
                {
                    State = ChargingState.Error;                      // Couldn't ping the instrument.  dead battery?
                }
            }
            catch (Exception e)
            {
                Log.Error(Name, e);

                // Whatever the error was, if the instrument isn't present, then it's
                // not charging.
                if (!Controller.IsDocked())
                {
                    State = ChargingState.NotCharging;
                }
                // Not sure what the error is.  Leave charging state as is.
            }
        }