Exemple #1
0
void EQModSimulator::Connect() {
    char *settingstexts[2];
    char *settingsnames[]= {(char *)"SIM_RASETTING", (char *)"SIM_DESETTING"};
    ISwitch *sw=IUFindOnSwitch(SimModeSP);
    sksim=new SkywatcherSimulator();
    if (!strcmp(sw->name, "SIM_EQ6")) {
        sksim->setupVersion("020300");
        sksim->setupRA(180, 47,12,200,64,2);
        sksim->setupDE(180, 47,12,200,64,2);
    } else {
        if (!strcmp(sw->name, "SIM_HEQ5")) {
            sksim->setupVersion("020301");
            sksim->setupRA(135, 47,9,200,64,2);
            sksim->setupDE(135, 47,9,200,64,2);
        } else {
            if (!strcmp(sw->name, "SIM_NEQ5")) {
                sksim->setupVersion("020302");
                sksim->setupRA(144, 44,9,200,32,2);
                sksim->setupDE(144, 44,9,200,32,2);
            } else {
                if (!strcmp(sw->name, "SIM_NEQ3")) {
                    sksim->setupVersion("020303");
                    sksim->setupRA(130, 55,10,200,32,2);
                    sksim->setupDE(130, 55,10,200,32,2);
                } else {
                    if (!strcmp(sw->name, "SIM_GEEHALEL")) {
                        sksim->setupVersion("0203F0");
                        sksim->setupRA(144, 60,15,400,8,1);
                        sksim->setupDE(144, 60,10,400,8,1);
                    } else {
                        if (!strcmp(sw->name, "SIM_CUSTOM")) {
                            double teeth, num, den, steps, microsteps, highspeed;
                            ISwitch *hssw=IUFindOnSwitch(SimHighSpeedSP);
                            sksim->setupVersion(IUFindText(SimMCVersionTP, "SIM_MCPHRASE")->text);
                            teeth=IUFindNumber(SimWormNP, "RA_TEETH")->value;
                            num=IUFindNumber(SimRatioNP, "RA_RATIO_NUM")->value;
                            den=IUFindNumber(SimRatioNP, "RA_RATIO_DEN")->value;
                            steps=IUFindNumber(SimMotorNP, "RA_MOTOR_STEPS")->value;
                            microsteps=IUFindNumber(SimMotorNP, "RA_MOTOR_USTEPS")->value;
                            highspeed=1;
                            if (!strcmp(hssw->name, "SIM_HALFSTEP")) highspeed=2;
                            sksim->setupRA(teeth, num, den, steps, microsteps, highspeed);

                            teeth=IUFindNumber(SimWormNP, "DE_TEETH")->value;
                            num=IUFindNumber(SimRatioNP, "DE_RATIO_NUM")->value;
                            den=IUFindNumber(SimRatioNP, "DE_RATIO_DEN")->value;
                            steps=IUFindNumber(SimMotorNP, "DE_MOTOR_STEPS")->value;
                            microsteps=IUFindNumber(SimMotorNP, "DE_MOTOR_USTEPS")->value;
                            sksim->setupDE(teeth, num, den, steps, microsteps, highspeed);

                        }
                    }
                }
            }
        }
    }
}
Exemple #2
0
void INDI::BaseClientQt::sendNewSwitch (ISwitchVectorProperty * svp)
{
    svp->s = IPS_BUSY;
    ISwitch * onSwitch = IUFindOnSwitch(svp);

    QString prop;

    prop += QString("<newSwitchVector\n");

    prop += QString("  device='%1'\n").arg(svp->device);
    prop += QString("  name='%1'>\n").arg(svp->name);

    if (svp->r == ISR_1OFMANY && onSwitch)
    {
        prop += QString("  <oneSwitch\n");
        prop += QString("    name='%1'>\n").arg(onSwitch->name);
        prop += QString("      %1\n").arg((onSwitch->s == ISS_ON) ? "On" : "Off");
        prop += QString("  </oneSwitch>\n");
    }
    else
    {
        for (int i=0; i < svp->nsp; i++)
        {
            prop += QString("  <oneSwitch\n");
            prop += QString("    name='%1'>\n").arg(svp->sp[i].name);
            prop += QString("      %1\n").arg((svp->sp[i].s == ISS_ON) ? "On" : "Off");
            prop += QString("  </oneSwitch>\n");
        }
    }

    prop += QString("</newSwitchVector>\n");

    client_socket.write(prop.toLatin1());
}
Exemple #3
0
bool Vantage::Connect()
{
    int connectrc=0;
    char errorMsg[MAXRBUF];

    DEBUGF(INDI::Logger::DBG_DEBUG, "Vantage connecting to %s", PortT[0].text);

    if ( (connectrc = tty_connect(PortT[0].text, atoi(IUFindOnSwitch(&BaudRateSP)->name), 8, 0, 1, &PortFD)) != TTY_OK)
    {
        tty_error_msg(connectrc, errorMsg, MAXRBUF);
        DEBUGF(INDI::Logger::DBG_ERROR,"Failed to connect to port %s @ baud %d. Error: %s", PortT[0].text,atoi(IUFindOnSwitch(&BaudRateSP)->name),  errorMsg);
        return false;
    }

    DEBUGF(INDI::Logger::DBG_DEBUG, "Port FD %d",PortFD);

    return ack();
}
Exemple #4
0
bool GPhotoCCD::StartExposure(float duration)
{
    if (PrimaryCCD.isExposing())
    {
        DEBUG(INDI::Logger::DBG_ERROR, "GPhoto driver is already exposing. Can not abort.");
        return false;
    }

    if (mFormatS != NULL)
    {
        ISwitch *sp = IUFindOnSwitch(&mFormatSP);
        if (sp == NULL)
        {
            DEBUG(INDI::Logger::DBG_ERROR, "Please select a format before capturing an image.");
            return false;
        }
    }

    /* start new exposure with last ExpValues settings.
     * ExpGo goes busy. set timer to read when done
     */

    int expms = (int)ceil(duration*1000);

    PrimaryCCD.setExposureDuration(duration);


    if (sim == false && gphoto_start_exposure(gphotodrv, expms, mMirrorLockN[0].value) < 0)
    {
        DEBUG(INDI::Logger::DBG_ERROR, "Error starting exposure");
        return false;
    }

    ExposureRequest = duration;
    gettimeofday(&ExpStart, NULL);
    InExposure = true;

    DEBUGF(INDI::Logger::DBG_SESSION, "Starting %g sec exposure", duration);

    SetTimer(POLLMS);

    return true;
}
Exemple #5
0
void GPhotoCCD::addFITSKeywords(fitsfile *fptr, CCDChip *targetChip)
{

    INDI::CCD::addFITSKeywords(fptr, targetChip);

    int status=0;

    if (mIsoSP.nsp > 0)
    {

        ISwitch *onISO = IUFindOnSwitch(&mIsoSP);
        if (onISO)
        {
            int isoSpeed=-1;
            isoSpeed = atoi(onISO->label);
            if (isoSpeed > 0)
                fits_update_key_s(fptr, TUINT, "ISOSPEED", &isoSpeed, "ISO Speed", &status);
        }

    }
}
Exemple #6
0
bool GPhotoCCD::Connect()
{

  sim = isSimulation();

  int setidx;
  char **options;
  int max_opts;
  const char *port = NULL;
  DEBUGF(INDI::Logger::DBG_DEBUG, "Mirror lock value: %f\n", mMirrorLockN[0].value);

  if(PortTP.tp[0].text && strlen(PortTP.tp[0].text)) {
      port = PortTP.tp[0].text;
      
  }
  if (sim == false && ! (gphotodrv = gphoto_open(port)))
  {
      DEBUG(INDI::Logger::DBG_ERROR, "Can not open camera: Power OK?");
      return false;
  }

  if (mFormatS)
  {
      free(mFormatS);
      mFormatS=NULL;
  }

  if (sim)
  {
    setidx =0;
    max_opts=1;
    const char *fmts[] = {"Custom"};
    options = (char **) fmts;
  }
  else
  {
      setidx = gphoto_get_format_current(gphotodrv);
      options = gphoto_get_formats(gphotodrv, &max_opts);
  }

  if (max_opts > 0)
  {
      mFormatS = create_switch("FORMAT", options, max_opts, setidx);
      mFormatSP.sp = mFormatS;
      mFormatSP.nsp = max_opts;

      ISwitch *sp = IUFindOnSwitch(&mFormatSP);
      if (sp && strstr(sp->label, "+"))
      {
          IUResetSwitch(&mFormatSP);
          int i=0;

          // Prefer RAW format in case selected format is not supported.
          for (i=0; i < mFormatSP.nsp; i++)
          {
              if (!strcmp("RAW", mFormatSP.sp[i].label))
              {
                  mFormatS[i].s = ISS_ON;
                  break;
              }
          }

          if (i == mFormatSP.nsp)
          {
            DEBUGF(INDI::Logger::DBG_ERROR, "%s format is not supported. Please select another format.", sp->label);
            mFormatSP.s = IPS_ALERT;
          }

          IDSetSwitch(&mFormatSP, NULL);
      }
  }

  if (mIsoS)
      free(mIsoS);

  if (sim)
  {
      setidx=0;
      max_opts=4;
      const char *isos[] = { "100", "200", "400", "800" };
      options = (char **) isos;
  }
  else
  {
    setidx = gphoto_get_iso_current(gphotodrv);
    options = gphoto_get_iso(gphotodrv, &max_opts);
  }

  mIsoS = create_switch("ISO", options, max_opts, setidx);    
  mIsoSP.sp = mIsoS;
  mIsoSP.nsp = max_opts;

  DEBUGF(INDI::Logger::DBG_SESSION, "%s is online.", getDeviceName());

  frameInitialized = false;

  return true;

}
Exemple #7
0
bool GPhotoCCD::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
{

  if (strcmp(dev, getDeviceName()) == 0)
  {
      if (!strcmp(name, mIsoSP.name))
      {
          if (IUUpdateSwitch(&mIsoSP, states, names, n) < 0)
              return false;

          for (int i = 0; i < mIsoSP.nsp; i++)
          {
              if (mIsoS[i].s == ISS_ON)
              {
                  if (sim == false)
                      gphoto_set_iso(gphotodrv, i);
                  mIsoSP.s = IPS_OK;
                  IDSetSwitch(&mIsoSP, NULL);
                  break;
              }
          }
      }
      
      if (!strcmp(name, mFormatSP.name))
      {
          int prevSwitch = IUFindOnSwitchIndex(&mFormatSP);
          if (IUUpdateSwitch(&mFormatSP, states, names, n) < 0)
              return false;

          ISwitch *sp = IUFindOnSwitch(&mFormatSP);
          if (sp)
          {
              if (strstr(sp->label, "+"))
              {
                  DEBUGF(INDI::Logger::DBG_ERROR, "%s format is not supported.", sp->label);
                  IUResetSwitch(&mFormatSP);
                  mFormatSP.s = IPS_ALERT;
                  mFormatSP.sp[prevSwitch].s = ISS_ON;
                  IDSetSwitch(&mFormatSP, NULL);
                  return false;
              }
          }
          for (int i = 0; i < mFormatSP.nsp; i++)
          {
              if (mFormatS[i].s == ISS_ON)
              {
                  if (sim == false)
                    gphoto_set_format(gphotodrv, i);
                  mFormatSP.s = IPS_OK;
                  IDSetSwitch(&mFormatSP, NULL);
                  // We need to get frame W and H if format changes
                  frameInitialized = false;
                  break;
              }
          }
      }

      if (!strcmp(name, transferFormatSP.name))
      {
          IUUpdateSwitch(&transferFormatSP, states, names, n);
          transferFormatSP.s = IPS_OK;
          IDSetSwitch(&transferFormatSP, NULL);
          // We need to get frame W and H if transfer format changes
          frameInitialized = false;
          return true;
      }

      if (!strcmp(name, autoFocusSP.name))
      {
          IUResetSwitch(&autoFocusSP);
          if (gphoto_auto_focus(gphotodrv) == GP_OK)
              autoFocusSP.s = IPS_OK;
          else
              autoFocusSP.s = IPS_ALERT;

          IDSetSwitch(&autoFocusSP, NULL);
          return true;
      }

      if (!strcmp(name, UploadSP.name))
      {
          IUUpdateSwitch(&UploadSP, states, names, n);
          UploadSP.s = IPS_OK;
          IDSetSwitch(&UploadSP, NULL);

          if (!sim)
              gphoto_set_upload_settings(gphotodrv, IUFindOnSwitchIndex(&UploadSP));
          return true;
      }

      if (!strcmp(name, livePreviewSP.name))
      {
          IUUpdateSwitch(&livePreviewSP, states, names, n);
          if (livePreviewS[0].s == ISS_ON)
          {
              livePreviewSP.s = IPS_BUSY;
              SetTimer(STREAMPOLLMS);
          }
          else
              livePreviewSP.s = IPS_IDLE;
          IDSetSwitch(&livePreviewSP, NULL);
          return true;
      }

      if (strstr(name, "FOCUS"))
      {
          return processFocuserSwitch(dev, name, states, names, n);
      }

      if(CamOptions.find(name) != CamOptions.end())
      {
          cam_opt *opt = CamOptions[name];
          if (opt->widget->type != GP_WIDGET_RADIO
              && opt->widget->type != GP_WIDGET_MENU
              && opt->widget->type != GP_WIDGET_TOGGLE)
          {
              DEBUGF(INDI::Logger::DBG_ERROR, "ERROR: Property '%s'is not a switch (%d)", name, opt->widget->type);
              return false;
          }

          if (opt->widget->readonly)
          {
              DEBUGF(INDI::Logger::DBG_WARNING, "WARNING: Property %s is read-only", name);
              IDSetSwitch(&opt->prop.sw, NULL);
              return false;
          }

          if (IUUpdateSwitch(&opt->prop.sw, states, names, n) < 0)
              return false;

          if (opt->widget->type == GP_WIDGET_TOGGLE)
          {
              gphoto_set_widget_num(gphotodrv, opt->widget, opt->item.sw[ON_S].s == ISS_ON);
          } else
          {
              for (int i = 0; i < opt->prop.sw.nsp; i++)
              {
                  if (opt->item.sw[i].s == ISS_ON)
                  {
                      gphoto_set_widget_num(gphotodrv, opt->widget, i);
                      break;
                  }
              }
          }
          opt->prop.sw.s = IPS_OK;
          IDSetSwitch(&opt->prop.sw, NULL);
          return true;
      }            
  }

  return INDI::CCD::ISNewSwitch(dev, name, states, names, n);

}
Exemple #8
0
void TCFS::TimerHit()
{
    static double lastPosition = -1, lastTemperature = -1000;

    if (!isConnected())
    {
        SetTimer(POLLMS);
        return;
    }
    int f_position      = 0;
    float f_temperature = 0;
    char response[TCFS_MAX_CMD] = { 0 };

    if(!isSimulation() && currentMode != MANUAL)
    {
        if (FocusTelemetrySP.sp[1].s == ISS_ON)
        {
            LOGF_DEBUG("%s %s",__FUNCTION__, "Telemetry is off");
            SetTimer(POLLMS);
            return;            
        }
        for(int i=0; i<2; i++)
        {
            if (read_tcfs(response) == false)
            {
                SetTimer(POLLMS);
                return;
            }
            LOGF_DEBUG("%s Received %s",__FUNCTION__, response);
            if(sscanf(response, "P=%d", &f_position) == 1)
            {
                currentPosition = f_position;
                if (lastPosition != currentPosition)
                {
                    lastPosition = currentPosition;
                    IDSetNumber(&FocusAbsPosNP, nullptr);
                }
            }
            else if(sscanf(response, "T=%f", &f_temperature)==1)
            {
                FocusTemperatureNP.np[0].value = f_temperature;

                if (lastTemperature != FocusTemperatureNP.np[0].value)
                {
                    lastTemperature = FocusTemperatureNP.np[0].value;
                    IDSetNumber(&FocusTemperatureNP, nullptr);
                }
            }
        }
        SetTimer(POLLMS);
        return;
    }

    if (FocusGotoSP.s == IPS_BUSY)
    {
        ISwitch *sp = IUFindOnSwitch(&FocusGotoSP);

        if (sp != nullptr && strcmp(sp->name, "FOCUS_CENTER") == 0)
        {
            bool rc = read_tcfs(response, true);

            if (!rc)
            {
                SetTimer(POLLMS);
                return;
            }

            if (isSimulation())
                strncpy(response, "CENTER", TCFS_MAX_CMD);

            if (strcmp(response, "CENTER") == 0)
            {
                IUResetSwitch(&FocusGotoSP);
                FocusGotoSP.s  = IPS_OK;
                FocusAbsPosNP.s = IPS_OK;

                IDSetSwitch(&FocusGotoSP, nullptr);
                IDSetNumber(&FocusAbsPosNP, nullptr);

                LOG_INFO("Focuser moved to center position.");
            }
        }
    }

    switch (FocusAbsPosNP.s)
    {
        case IPS_OK:
            if (FocusModeSP.sp[0].s == ISS_ON)
                dispatch_command(FPOSRO);

            if (read_tcfs(response) == false)
            {
                SetTimer(POLLMS);
                return;
            }

            if (isSimulation())
                snprintf(response, TCFS_MAX_CMD, "P=%04d", (int)simulated_position);

            sscanf(response, "P=%d", &f_position);
            currentPosition = f_position;

            if (lastPosition != currentPosition)
            {
                lastPosition = currentPosition;
                IDSetNumber(&FocusAbsPosNP, nullptr);
            }
            break;

        case IPS_BUSY:
            if (read_tcfs(response, true) == false)
            {
                SetTimer(POLLMS);
                return;
            }

            // Ignore error
            if (strstr(response, "ER") != nullptr)
            {
                LOGF_DEBUG("Received error: %s", response);
                SetTimer(POLLMS);
                return;
            }

            if (isSimulation())
                strncpy(response, "*", 2);

            if (strcmp(response, "*") == 0)
            {
                LOGF_DEBUG("Moving focuser %d steps to position %d.", targetTicks, targetPosition);
                FocusAbsPosNP.s = IPS_OK;
                FocusRelPosNP.s = IPS_OK;
                FocusGotoSP.s  = IPS_OK;
                IDSetNumber(&FocusAbsPosNP, nullptr);
                IDSetNumber(&FocusRelPosNP, nullptr);
                IDSetSwitch(&FocusGotoSP, nullptr);
            }
            else
            {
                FocusAbsPosNP.s = IPS_ALERT;
                LOGF_ERROR("Unable to read response from focuser #%s#.", response);
                IDSetNumber(&FocusAbsPosNP, nullptr);
            }
            break;

        default:
            break;
    }

    if (FocusTemperatureNP.s != IPS_IDLE)
    {
        // Read Temperature
        // Manual Mode
        if (FocusModeSP.sp[0].s == ISS_ON)
            dispatch_command(FTMPRO);

        if (read_tcfs(response) == false)
        {
            SetTimer(POLLMS);
            return;
        }

        if (isSimulation())
            snprintf(response, TCFS_MAX_CMD, "T=%0.1f", simulated_temperature);

        sscanf(response, "T=%f", &f_temperature);

        FocusTemperatureNP.np[0].value = f_temperature;

        if (lastTemperature != FocusTemperatureNP.np[0].value)
        {
            lastTemperature = FocusTemperatureNP.np[0].value;
            IDSetNumber(&FocusTemperatureNP, nullptr);
        }
    }

    SetTimer(POLLMS);
}
Exemple #9
0
bool TCFS::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
{
//LOGF_DEBUG("%s %s",__FUNCTION__, me);
    if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
    {
        char response[TCFS_MAX_CMD] = { 0 };

        if (!strcmp(FocusPowerSP.name, name))
        {
            IUUpdateSwitch(&FocusPowerSP, states, names, n);
            bool sleep = false;

            ISwitch *sp = IUFindOnSwitch(&FocusPowerSP);

            // Sleep
            if (!strcmp(sp->name, "FOCUS_SLEEP"))
            {
                dispatch_command(FSLEEP);
                sleep = true;
            }
            // Wake Up
            else
                dispatch_command(FWAKUP);

            if (read_tcfs(response) == false)
            {
                IUResetSwitch(&FocusPowerSP);
                FocusPowerSP.s = IPS_ALERT;
                IDSetSwitch(&FocusPowerSP, "Error reading TCF-S reply.");
                return true;
            }

            if (sleep)
            {
                if (isSimulation())
                    strncpy(response, "ZZZ", TCFS_MAX_CMD);

                if (strcmp(response, "ZZZ") == 0)
                {
                    FocusPowerSP.s = IPS_OK;
                    IDSetSwitch(&FocusPowerSP, "Focuser is set into sleep mode.");
                    FocusAbsPosNP.s = IPS_IDLE;
                    IDSetNumber(&FocusAbsPosNP, nullptr);
//                    if (FocusTemperatureNP)
                    {
                        FocusTemperatureNP.s = IPS_IDLE;
                        IDSetNumber(&FocusTemperatureNP, nullptr);
                    }

                    return true;
                }
                else
                {
                    FocusPowerSP.s = IPS_ALERT;
                    IDSetSwitch(&FocusPowerSP, "Focuser sleep mode operation failed. Response: %s.", response);
                    return true;
                }
            }
            else
            {
                if (isSimulation())
                    strncpy(response, "WAKE", TCFS_MAX_CMD);

                if (strcmp(response, "WAKE") == 0)
                {
                    FocusPowerSP.s = IPS_OK;
                    IDSetSwitch(&FocusPowerSP, "Focuser is awake.");
                    FocusAbsPosNP.s = IPS_OK;
                    IDSetNumber(&FocusAbsPosNP, nullptr);
//                    if (FocusTemperatureNP)
                    {
                        FocusTemperatureNP.s = IPS_OK;
                        IDSetNumber(&FocusTemperatureNP, nullptr);
                    }

                    return true;
                }
                else
                {
                    FocusPowerSP.s = IPS_ALERT;
                    IDSetSwitch(&FocusPowerSP, "Focuser wake up operation failed. Response: %s", response);
                    return true;
                }
            }
        }

        // Do not process any command if focuser is asleep
        if (isConnected() && FocusPowerSP.sp[0].s == ISS_ON)
        {
            ISwitchVectorProperty *svp = getSwitch(name);
            if (svp)
            {
                svp->s = IPS_IDLE;
                LOG_WARN("Focuser is still in sleep mode. Wake up in order to issue commands.");
                IDSetSwitch(svp, nullptr);
            }
            return true;
        }

        if (!strcmp(FocusModeSP.name, name))
        {
            IUUpdateSwitch(&FocusModeSP, states, names, n);
            FocusModeSP.s = IPS_OK;

            ISwitch *sp = IUFindOnSwitch(&FocusModeSP);

            if (!strcmp(sp->name, "Manual"))
            {
                if (!isSimulation() && !SetManualMode())
                {
                    IUResetSwitch(&FocusModeSP);
                    FocusModeSP.s = IPS_ALERT;
                    IDSetSwitch(&FocusModeSP, "Error switching to manual mode. No reply from TCF-S. Try again.");
                    return true;
                }
            }
            else if (!strcmp(sp->name, "Auto A"))
            {
                dispatch_command(FAMODE);
                read_tcfs(response);
                if (!isSimulation() && strcmp(response, "A") != 0)
                {
                    IUResetSwitch(&FocusModeSP);
                    FocusModeSP.s = IPS_ALERT;
                    IDSetSwitch(&FocusModeSP, "Error switching to Auto Mode A. No reply from TCF-S. Try again.");
                    return true;
                }
                LOG_INFO("Entered Auto Mode A");
                currentMode = MODE_A;
            }
            else
            {
                dispatch_command(FBMODE);
                read_tcfs(response);
                if (!isSimulation() && strcmp(response, "B") != 0)
                {
                    IUResetSwitch(&FocusModeSP);
                    FocusModeSP.s = IPS_ALERT;
                    IDSetSwitch(&FocusModeSP, "Error switching to Auto Mode B. No reply from TCF-S. Try again.");
                    return true;
                }
                LOG_INFO("Entered Auto Mode B");
                currentMode = MODE_B;
            }

            IDSetSwitch(&FocusModeSP, nullptr);
            return true;
        }

        if (!strcmp(FocusGotoSP.name, name))
        {
            if (FocusModeSP.sp[0].s != ISS_ON)
            {
                FocusGotoSP.s = IPS_IDLE;
                IDSetSwitch(&FocusGotoSP, nullptr);
                LOG_WARN("The focuser can only be moved in Manual mode.");
                return false;
            }

            IUUpdateSwitch(&FocusGotoSP, states, names, n);
            FocusGotoSP.s = IPS_BUSY;

            ISwitch *sp = IUFindOnSwitch(&FocusGotoSP);

            // Min
            if (!strcmp(sp->name, "FOCUS_MIN"))
            {
                targetTicks = currentPosition;
                MoveRelFocuser(FOCUS_INWARD, currentPosition);
                IDSetSwitch(&FocusGotoSP, "Moving focuser to minimum position...");
            }
            // Center
            else if (!strcmp(sp->name, "FOCUS_CENTER"))
            {
                dispatch_command(FCENTR);
                FocusAbsPosNP.s = FocusRelPosNP.s = IPS_BUSY;
                IDSetNumber(&FocusAbsPosNP, nullptr);
                IDSetNumber(&FocusRelPosNP, nullptr);
                IDSetSwitch(&FocusGotoSP, "Moving focuser to center position %d...", isTCFS3 ? 5000 : 3500);
                return true;
            }
            // Max
            else if (!strcmp(sp->name, "FOCUS_MAX"))
            {
                unsigned int delta = 0;
                delta              = FocusAbsPosN[0].max - currentPosition;
                MoveRelFocuser(FOCUS_OUTWARD, delta);
                IDSetSwitch(&FocusGotoSP, "Moving focuser to maximum position %g...", FocusAbsPosN[0].max);
            }
            // Home
            else if (!strcmp(sp->name, "FOCUS_HOME"))
            {
                dispatch_command(FHOME);
                read_tcfs(response);

                if (isSimulation())
                    strncpy(response, "DONE", TCFS_MAX_CMD);

                if (strcmp(response, "DONE") == 0)
                {
                    IUResetSwitch(&FocusGotoSP);
                    FocusGotoSP.s = IPS_OK;
                    IDSetSwitch(&FocusGotoSP, "Moving focuser to new calculated position based on temperature...");
                    return true;
                }
                else
                {
                    IUResetSwitch(&FocusGotoSP);
                    FocusGotoSP.s = IPS_ALERT;
                    IDSetSwitch(&FocusGotoSP, "Failed to move focuser to home position!");
                    return true;
                }
            }

            IDSetSwitch(&FocusGotoSP, nullptr);
            return true;
        }
        // handle quiet mode on/off
        if (!strcmp(FocusTelemetrySP.name, name))
        {
            IUUpdateSwitch(&FocusTelemetrySP, states, names, n);


            bool quiet = false;

            ISwitch *sp = IUFindOnSwitch(&FocusTelemetrySP);

            // Telemetry off
            if (!strcmp(sp->name, "FOCUS_TELEMETRY_OFF"))
            {
                dispatch_command(FQUIET, 1);
                quiet = true;
            }
            // Telemetry On
            else
                dispatch_command(FQUIET, 0);

            if (read_tcfs(response) == false)
            {
                IUResetSwitch(&FocusTelemetrySP);
                FocusTelemetrySP.s = IPS_ALERT;
                IDSetSwitch(&FocusTelemetrySP, "Error reading TCF-S reply.");
                return true;
            }

            if (isSimulation())
                strncpy(response, "DONE", TCFS_MAX_CMD);

            if (strcmp(response, "DONE") == 0)
            {
                FocusTelemetrySP.s = IPS_OK;
                IDSetSwitch(&FocusTelemetrySP, 
                        quiet ? "Focuser Telemetry is off." : "Focuser Telemetry is on.");
//                if (FocusTemperatureNP)
                {
                    FocusTemperatureNP.s = quiet?IPS_IDLE:IPS_OK;
                    IDSetNumber(&FocusTemperatureNP, nullptr);
                }
                return true;
            }
            else
            {
                FocusTelemetrySP.s = IPS_ALERT;
                IDSetSwitch(&FocusTelemetrySP, "Focuser telemetry mode failed. Response: %s.", response);
                return true;
            }
        }
    }
    return INDI::Focuser::ISNewSwitch(dev, name, states, names, n);
}