def set_frame(self, minx, miny, width, height):
        # passed in pixels are the "size" of the current binning
        #
        #
        # INDI expects us to set frame in 1x1 pixels
        #
        ccd_frame = indihelper.getNumber(self.cam, 'CCD_FRAME')
        if ccd_frame is None:
            return False
        binx, biny = self.get_binning()
        if None in [binx, biny]:
            logging.error('set_frame: unable to determine binning!')
            return False
        logging.debug(f'set_frame: binning = {binx} {biny}')
        ccd_x = indihelper.findNumber(ccd_frame, 'X')
        ccd_y = indihelper.findNumber(ccd_frame, 'Y')
        ccd_w = indihelper.findNumber(ccd_frame, 'WIDTH')
        ccd_h = indihelper.findNumber(ccd_frame, 'HEIGHT')
        # logging.debug(f'set_frame: {minx} {miny} {width} {height} {ccd_x.value} '
        #               f'{ccd_y.value} {ccd_w.value} {ccd_h.value}')

        if None in [ccd_x, ccd_y, ccd_w, ccd_h]:
            return False

        ccd_x.value = minx * binx
        ccd_y.value = miny * biny
        ccd_w.value = width * binx
        ccd_h.value = height * biny

        self.backend.indiclient.sendNewNumber(ccd_frame)
        return True
 def get_position_radec(self):
     """Returns tuple of (ra, dec) with ra in decimal hours and dec in degrees"""
     ra = indihelper.getfindNumberValue(self.mount,
                                        'EQUATORIAL_EOD_COORD', 'RA')
     dec = indihelper.getfindNumberValue(self.mount,
                                         'EQUATORIAL_EOD_COORD', 'DEC')
     return (ra, dec)
    def stop_exposure(self):
        # had trouble using the setfindSwitchState function for some reason!
        retries = 5
        i = 0
        sw_prop = None
        while i < retries:
            #logging.info('Trying to get CCD_ABORT_EXPOSURE')
            sw_prop = indihelper.getSwitch(self.cam, 'CCD_ABORT_EXPOSURE')
            #logging.info(f'sw_prop = {sw_prop}')
            if sw_prop is not None:
                break
            time.sleep(0.1)
            i += 1
        if sw_prop is None:
            return False

        sw = None
        i = 0
        while i < retries:
            logging.debug('Trying to get ABORT')
            sw = indihelper.findSwitch(sw_prop, 'ABORT')
            logging.debug(f'sw = {sw}')
            if sw is not None:
                break
            time.sleep(0.1)

        if sw is None:
            return False

        sw.s = PyIndi.ISS_ON
        self.backend.indiclient.sendNewSwitch(sw_prop)
        return True
    def get_frame(self):
        ccd_frame = indihelper.getNumber(self.cam, 'CCD_FRAME')
        if ccd_frame is None:
            return None

        ccd_x = indihelper.findNumber(ccd_frame, 'X')
        ccd_y = indihelper.findNumber(ccd_frame, 'Y')
        ccd_w = indihelper.findNumber(ccd_frame, 'WIDTH')
        ccd_h = indihelper.findNumber(ccd_frame, 'HEIGHT')

        if None in [ccd_x, ccd_y, ccd_w, ccd_h]:
            return (None, None, None, None)

        # called expects pixels are the "size" of the current binning
        #
        #
        # INDI returns frame in 1x1 pixels
        #
        binx, biny = self.get_binning()
        if None in [binx, biny]:
            logging.error('get_frame: unable to determine binning!')
            return False
        # logging.debug(f'get_frame: binning = {binx} {biny}')

        return (ccd_x.value // binx, ccd_y.value // biny,
                ccd_w.value // binx, ccd_h.value // biny)
    def start_exposure(self, expos):
        logging.debug(f'Exposing image for {expos} seconds')

        # FIXME currently always requesting a light frame
        # FIXME need to check return codes of all steps
        if self.cam:
            ccd_exposure = indihelper.getNumber(self.cam, 'CCD_EXPOSURE')
            if ccd_exposure is None:
                return False

            # we should inform the indi server that we want to receive the
            # 'CCD1' blob from this device
            # FIXME not good to reference global 'config' here - we already pass
            #       a device object should combine?
            self.backend.indiclient.setBLOBMode(PyIndi.B_ALSO, self.name, 'CCD1')

            ccd_ccd1 = self.cam.getBLOB('CCD1')
            while not ccd_ccd1:
                time.sleep(0.25)
                ccd_ccd1 = self.device.getBLOB('CCD1')

            self.backend.indiclient.clearBlobEvent()

            ccd_expnum = indihelper.findNumber(ccd_exposure, 'CCD_EXPOSURE_VALUE')
            if ccd_expnum is None:
                return False
            ccd_expnum.value = expos
            self.backend.indiclient.sendNewNumber(ccd_exposure)

            return True
        else:
            return False
 def get_binning(self):
     ccd_bin = indihelper.getNumber(self.cam, 'CCD_BINNING')
     binx = indihelper.findNumber(ccd_bin, 'HOR_BIN')
     biny = indihelper.findNumber(ccd_bin, 'VER_BIN')
     if binx is None or biny is None:
         return None, None
     return (binx.value, biny.value)
    def is_moving(self):
        state = indihelper.getNumberState(self.filterwheel, 'FILTER_SLOT')
        if state is None:
            return None
        return state == PyIndi.IPS_BUSY

        state = indihelper.getfindLightState(self.filterwheel,
                                             'FILTER_SLOT')
        return state == PyIndi.IPS_BUSY
 def get_pier_side(self):
     """Returns 'EAST' or 'WEST' or None if could not be determined."""
     if indihelper.getfindSwitchState(self.mount, 'TELESCOPE_PIER_SIDE',
                                      'PIER_EAST'):
         return 'EAST'
     elif indihelper.getfindSwitchState(self.mount, 'TELESCOPE_PIER_SIDE',
                                        'PIER_WEST'):
         return 'WEST'
     else:
         return None
    def sync(self, ra, dec):
        """Sync to ra/dec with ra in decimal hours and dec in degrees"""
        logging.debug(f'sync to {ra} {dec}')
        #logging.debug('finding) ON_COORD_SET switch')
        indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                      'ON_COORD_SET', 'SYNC', True)
        indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                      'ON_COORD_SET', 'SLEW', False)
        indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                      'ON_COORD_SET', 'TRACK', False)

        #logging.debug('getNumber EQUATORIAL_EOD_COORD')
        eq_coord = indihelper.getNumber(self.mount, 'EQUATORIAL_EOD_COORD')
        if eq_coord is None:
            return False
        #logging.debug('findNumber "RA"')
        ra_coord = indihelper.findNumber(eq_coord, 'RA')
        if ra_coord is None:
            return False
        #logging.debug('findNumber "DEC"')
        dec_coord = indihelper.findNumber(eq_coord, 'DEC')
        if dec_coord is None:
            return False
        #logging.debug(f'{ra_coord.value} {dec_coord.value}')
        ra_coord.value = ra
        dec_coord.value = dec
        #logging.debug(f'{ra_coord.value} {dec_coord.value}')
        #logging.debug('sending Number')
        self.backend.indiclient.sendNewNumber(eq_coord)
        return True
    def set_tracking(self, onoff):
        rc = indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                           'TELESCOPE_TRACK_STATE', 'TRACK_ON',
                                           onoff)
        if not rc:
            return rc

        rc = indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                           'TELESCOPE_TRACK_STATE', 'TRACK_OFF',
                                           not onoff)
        return rc
 def set_binning(self, binx, biny):
     ccd_bin = indihelper.getNumber(self.cam, 'CCD_BINNING')
     if ccd_bin is None:
         return False
     num_binx = indihelper.findNumber(ccd_bin, 'HOR_BIN')
     num_biny = indihelper.findNumber(ccd_bin, 'VER_BIN')
     if num_binx is None or num_biny is None:
         return False
     num_binx.value = binx
     num_biny.value = biny
     self.backend.indiclient.sendNewNumber(ccd_bin)
     return True
 def get_cooler_power(self):
     if self.camera_has_cooler_power is False:
         return None
     cool_power = indihelper.getNumber(self.cam, 'CCD_COOLER_POWER')
     if cool_power is None:
         self.camera_has_cooler_power = False
         return None
     num = indihelper.findNumber(cool_power, 'CCD_COOLER_VALUE')
     if num is None:
         self.camera_has_cooler_power = False
         return None
     return num.value
    def set_cooler_state(self, onoff):
        rc = indihelper.setfindSwitchState(self.backend.indiclient, self.cam,
                                           'CCD_COOLER', 'COOLER_ON',
                                           onoff)
        if not rc:
            return rc

        rc = indihelper.setfindSwitchState(self.backend.indiclient, self.cam,
                                           'CCD_COOLER', 'COOLER_OFF',
                                           not onoff)

        return rc
    def get_min_max_exposure(self):
        if self.cam:
            ccd_exposure = indihelper.getNumber(self.cam, 'CCD_EXPOSURE')
            if ccd_exposure is None:
                return None

            ccd_expnum = indihelper.findNumber(ccd_exposure, 'CCD_EXPOSURE_VALUE')
            if ccd_expnum is None:
                return None

            return (ccd_expnum.min, ccd_expnum.max)
        else:
            return None
    def get_camera_gain(self):
        """ Looks for camera specific gain - only works for ASI afaik"""
        if self.cam:
            ccd_controls = indihelper.getNumber(self.cam, 'CCD_CONTROLS')
            if ccd_controls is None:
                return None

            ccd_gain = indihelper.findNumber(ccd_controls, 'Gain')
            if ccd_gain is None:
                return None

            return ccd_gain.value
        else:
            return None
    def get_camera_offset(self):
        """ Looks for camera specific offset - only works for ASI afaik"""
        if self.cam:
            ccd_controls = indihelper.getNumber(self.cam, 'CCD_CONTROLS')
            if ccd_controls is None:
                return None

            ccd_offset = indihelper.findNumber(ccd_controls, 'Offset')
            if ccd_offset is None:
                return None

            return ccd_offset.value
        else:
            return None
    def get_camera_usbbandwidth(self):
        """ Looks for camera specific usb traffic - only works for ASI afaik"""
        if self.cam:
            ccd_controls = indihelper.getNumber(self.cam, 'CCD_CONTROLS')
            if ccd_controls is None:
                return None

            ccd_usb = indihelper.findNumber(ccd_controls, 'BandWidth')
            if ccd_usb is None:
                return None

            return ccd_usb.value
        else:
            return None
 def get_position_altaz(self):
     """Returns tuple of (alt, az) in degrees"""
     #
     # NOTE seems like some (most?) INDI GEM drivers don't return alt/az
     #
     if self.has_altaz_coord is not False:
         az = indihelper.getfindNumberValue(self.mount, 'HORIZONTAL_COORD', 'AZ')
         alt = indihelper.getfindNumberValue(self.mount, 'HORIZONTAL_COORD', 'ALT')
         if az is None or alt is None:
             self.has_altaz_coord = False
     else:
         az = None
         alt = None
     return (alt, az)
    def get_max_binning(self):
        if self.cam:
            ccd_bin = indihelper.getNumber(self.cam, 'CCD_BINNING')
            #logging.info(f'ccd_bin={ccd_bin}')
            if ccd_bin is None:
                return None

            ccd_hbin = indihelper.findNumber(ccd_bin, 'HOR_BIN')
            #logging.info(f'ccd_hbin={indihelper.dump_Number(ccd_hbin)}')
            if ccd_hbin is None:
                return None

            return ccd_hbin.max
        else:
            return None
 def get_position(self):
     """ Position starts at 0! """
     pos = indihelper.getfindNumberValue(self.filterwheel,
                                         'FILTER_SLOT', 'FILTER_SLOT_VALUE')
     if pos is not None:
         return int(pos) - 1
     return None
 def set_target_temperature(self, temp_c):
     # FIXME Handling ccd temperature needs to be more robust
     self.temperature_target = temp_c
     return indihelper.setfindNumberValue(self.backend.indiclient, self.cam,
                                          'CCD_TEMPERATURE',
                                          'CCD_TEMPERATURE_VALUE',
                                          temp_c)
    def get_info(self):
        ccd_info = indihelper.getNumber(self.cam, 'CCD_INFO')

        if ccd_info is None:
            return None

        maxx = indihelper.findNumber(ccd_info, 'CCD_MAX_X')
        maxy = indihelper.findNumber(ccd_info, 'CCD_MAX_Y')
        pix_size = indihelper.findNumber(ccd_info, 'CCD_PIXEL_SIZE')
        pix_size_x = indihelper.findNumber(ccd_info, 'CCD_PIXEL_SIZE_X')
        pix_size_y = indihelper.findNumber(ccd_info, 'CCD_PIXEL_SIZE_Y')
        bpp = indihelper.findNumber(ccd_info, 'CCD_BITSPERPIXEL')

        # if maxx is None or maxy is None is pix_size is None \
        #   or pix_size_x is None or pix_size_y is None or bpp is None:
        if None in [maxx, maxy, pix_size, pix_size_x, pix_size_y, bpp]:
            return None

        obj = self.CCD_INFO()
        obj.CCD_MAX_X = maxx.value
        obj.CCD_MAX_Y = maxy.value
        obj.CCD_PIXEL_SIZE = pix_size.value
        obj.CCD_PIXEL_SIZE_X = pix_size_x.value
        obj.CCD_PIXEL_SIZE_Y = pix_size_y.value
        obj.CCD_BITSPERPIXEL = bpp.value

        return obj
    def get_max_absolute_position(self):
        # Moonlite driver defines max travel
        if self.focuser_has_max_travel is not False:
            maxpos = indihelper.getfindNumberValue(self.focuser,
                                                   'FOCUS_MAXTRAVEL',
                                                   'MAXTRAVEL')
            if maxpos is not None:
                return maxpos
            else:
                self.focuser_has_max_travel = False

        # try using max value for abs pos slider
        p = indihelper.getfindNumber(self.focuser,
                                     'ABS_FOCUS_POSITION',
                                     'FOCUS_ABSOLUTE_POSITION')
        if p is not None:
            return p.max
        return None
Esempio n. 24
0
    def handle_set_buttons(self, id):
        print('handle_set_buttons: ', self, id)
        devicename, pvname, pname = id.split('::')

        property = self.device_propvectors[devicename][pvname].properties[
            pname]
        property_type = self.device_propvectors[devicename][pvname].type

        if property_type == PyIndi.INDI_TEXT:
            value = property.value_widget.text()
            print(devicename, pvname, pname, value)
            device = self.indiclient.getDevice(devicename)
            indihelper.setfindTextText(self.indiclient, device, pvname, pname,
                                       value)
#            device = self.indiclient.getDevice(devicename)
#            print(device)
#            indi_propvector = indihelper.getText(device, pvname)
#            print(indi_propvector)
#            indi_text = indihelper.findText(indi_propvector, pname)
#            print(indi_text)
#            indi_text.value = value
#            print(indihelper.dump_ITextVectorProperty(indi_propvector))
#            self.indiclient.sendNewText(indi_propvector)
        elif property_type == PyIndi.INDI_NUMBER:
            value = property.value_widget.value()
            print(devicename, pvname, pname, value)
            device = self.indiclient.getDevice(devicename)
            indihelper.setfindNumberValue(self.indiclient, device, pvname,
                                          pname, value)
#            indi_propvector = indihelper.getNumber(device, pvname)
#            indi_num = indihelper.findNumber(indi_propvector, pname)
#            indi_num.value = value
#            self.indiclient.sendNewNumber(indi_propvector)
        elif property_type == PyIndi.INDI_SWITCH:
            value = property.value_widget.isChecked()
            #print(property.value_widget, devicename, pvname, pname, value)
            device = self.indiclient.getDevice(devicename)
            #            indihelper.setfindSwitchState(self.indiclient, device, pvname, pname, value)
            indi_propvector = indihelper.getSwitch(device, pvname)
            prop = indihelper.findSwitch(indi_propvector, pname)
            prop.s = value

            # depending on rule turn off other buttons
            if indi_propvector.r != PyIndi.ISR_NOFMANY and value:
                for i in range(0, indi_propvector.nsp):
                    s = indi_propvector[i]
                    #print('scanning for buttons to turn off', s.name, pname)
                    if s.name != pname:
                        s.s = PyIndi.ISS_OFF
            self.indiclient.sendNewSwitch(indi_propvector)

            final_indi_propvector = indihelper.getSwitch(device, pvname)

            print(indihelper.dump_ISwitchVectorProperty(final_indi_propvector))
    def get_names(self):
        # lookup filter names from driver
        filter_name_prop = indihelper.getText(self.filterwheel, 'FILTER_NAME')
        if filter_name_prop is None:
            return None

        names = []
        for i in range(0, filter_name_prop.ntp):
            names.append(filter_name_prop[i].text)

        return names
    def get_current_temperature(self):
        if self.focuser_has_temperature is not False:
            curtemp = indihelper.getfindNumberValue(self.focuser,
                                                    'FOCUS_TEMPERATURE',
                                                    'TEMPERATURE')
            if curtemp is not None:
                return curtemp
            else:
                self.focuser_has_temperature = False

        return None
    def connect(self, name):
        logging.debug(f'Connecting to mount device: {name}')
        if self.mount is not None:
            logging.warning('Mount.connect() self.mount is not None!')

        mount = indihelper.connectDevice(self.backend.indiclient, name)

        #logging.debug(f'connectDevice returned {mount}')

        if mount is not None:
            self.name = name
            self.mount = mount
            return True

        return False
    def connect(self, name):
        logging.debug(f'Connecting to filterwheel device: {name}')
        if self.filterwheel is not None:
            logging.warning('FilterWheel.connect() self.filterwheel is not None!')

        fw = indihelper.connectDevice(self.backend.indiclient, name)

        #logging.info(f'connectDevice returned {fw}')

        if fw is not None:
            self.name = name
            self.filterwheel = fw
            return True

        return False
    def set_position(self, pos):
        """Sends request to driver to move filter wheel position

        This DOES NOT wait for filter to move into position!

        Use is_moving() method to check if its done.

        Positions start at 1 so we add one since backend defines position
        starting at 0 like ASCOM!
        """
        if pos < self.get_num_positions():
            return indihelper.setfindNumberValue(self.backend.indiclient,
                                                 self.filterwheel,
                                                 'FILTER_SLOT',
                                                 'FILTER_SLOT_VALUE',
                                                 pos + 1)
        else:
            return False
    def slew(self, ra, dec):
        """Slew to ra/dec with ra in decimal hours and dec in degrees"""
        indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                      'ON_COORD_SET', 'SLEW', False)
        indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                      'ON_COORD_SET', 'TRACK',  True)
        indihelper.setfindSwitchState(self.backend.indiclient, self.mount,
                                      'ON_COORD_SET', 'SYNC', False)

        eq_coord = indihelper.getNumber(self.mount, 'EQUATORIAL_EOD_COORD')
        if eq_coord is None:
            return False

        self.slew_eqcoord = eq_coord
        ra_coord = indihelper.findNumber(eq_coord, 'RA')
        if ra_coord is None:
            return False
        dec_coord = indihelper.findNumber(eq_coord, 'DEC')
        if dec_coord is None:
            return False
        ra_coord.value = ra
        dec_coord.value = dec
        self.backend.indiclient.sendNewNumber(eq_coord)
        return True