DBUS is a very powerful and versatile inter-process communication system used in Linux and other OSes. DBUS replaced DCOP in KDE4 and has since became the standard for IPC messages in KDE. With KStars (>v.2.3.0), it exposes a new INDI DBUS interface in addition to the existing KStars's DBUS interface giving you a fine control over most of KStars functionality.

In this tutorial, we will learn how to perform basic control of a telescope and CCD using DBUS and Python. We will utilize an external FITS viewer fv, you can install it in Ubuntu:

sudo apt-get install ftools-fv

The complete Python script can be downloaded, to run it, simply run KStars first, then execute the script:

python indidbus.py

We begin by starting a session bus and obtaining a remote object instance to KStars/INDI interface. DBUS can introspect the interface and prints all available methods as shown below.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# You must initialize the gobject/dbus support for threading
# before doing anything.
import gobject
import os
import time


from dbus import glib

# Create a session bus.
import dbus
bus = dbus.SessionBus()

# Create an object that will proxy for a particular remote object.
remote_object = bus.get_object("org.kde.kstars", # Connection name
                               "/KStars/INDI" # Object's path

# Introspection returns an XML document containing information
# about the methods supported by an interface.
print ("Introspection data:\n")
print remote_object.Introspect()

Next, we obtain a handle to the INDI interface that we will use thorough out the script to call methods and get results back.

# Get INDI interface
iface = dbus.Interface(remote_object, 'org.kde.kstars.INDI')

We define our target devices as we plan to run the Telescope and CCD simulators

myDevices = [ "indi_simulator_telescope", "indi_simulator_ccd" ]

We make our first call to the INDI interface, and we ask it to start an INDI server on port 7624 with our devices

# Start INDI devices
iface.start("7624", myDevices)

print "Waiting for INDI devices..."

# Create array for received devices
devices = []

while True:
    devices = iface.getDevices()
    if (len(devices) < len(myDevices)):

print "We received the following devices:"
for device in devices:
    print device

Above, we invoke the getDevices() method which returns an array of devices, and we wait until all the devices are received. Please note that devices are not necessarily received in order, i.e. telescope first followed by CCD. It can be in any order. Furthermore, I didn't implement any timeout or error checking above, please do not forget to check for errors when building DBUS scripts.

Next, we establish a connection to the telescope and CCD. Note that we utilize methods to set the value of a property, but the value is not sent to the INDI server unless we use the sendProperty method. You must be familiar with INDI properties, and in particular INDI Standard Properties before you can write any useful script.

print "Establishing connection to Telescope and CCD..."

# Set connect switch to ON to connect the devices
iface.setSwitch("Telescope Simulator", "CONNECTION", "CONNECT", "On")
# Send the switch to INDI server so that it gets processed by the driver
iface.sendProperty("Telescope Simulator", "CONNECTION")
# Same thing for CCD Simulator
iface.setSwitch("CCD Simulator", "CONNECTION", "CONNECT", "On")
iface.sendProperty("CCD Simulator", "CONNECTION")

telescopeState = "Busy"
ccdState       = "Busy"

# Wait until devices are connected
while True:
    telescopeState = iface.getPropertyState("Telescope Simulator", "CONNECTION")
    ccdState       = iface.getPropertyState("CCD Simulator", "CONNECTION")
    if (telescopeState != "Ok" or ccdState != "Ok"):

print "Connected to Telescope and CCD is established."

Above, after we connected, we inquired about the state of the CONNECTION property. Once we established it is Ok, we can proceed.

When we command the telescope, we need to send the Epoch of Date (EOD) coordinates or JNow. The following coordinates are the approximate coordinate for Caph at the time of writing this tutorial.

print "Commanding telescope to slew to coordinates of star Caph..."

# Set Telescope RA,DEC coords in JNOW
iface.setNumber("Telescope Simulator", "EQUATORIAL_EOD_COORD", "RA", 0.166)
iface.setNumber("Telescope Simulator", "EQUATORIAL_EOD_COORD", "DEC", 59.239)
iface.sendProperty("Telescope Simulator", "EQUATORIAL_EOD_COORD")

# Wait until slew is done
telescopeState = "Busy"
while True:
    telescopeState = iface.getPropertyState("Telescope Simulator", "EQUATORIAL_EOD_COORD")
    if (telescopeState != "Ok"):

print "Telescope slew is complete, tracking..."

As with before, we wait until the property state turns to Ok

Next, we take a 5 second exposure

print "Taking a 5 second CCD exposure..."

# Take 5 second exposure
iface.setNumber("CCD Simulator", "CCD_EXPOSURE", "CCD_EXPOSURE_VALUE", 5.0)
iface.sendProperty("CCD Simulator", "CCD_EXPOSURE")

# Wait until exposure is done
ccdState       = "Busy"
while True:
    ccdState = iface.getPropertyState("CCD Simulator", "CCD_EXPOSURE")
    if (ccdState != "Ok"):

print "Exposure complete"

After exposure is complete, KStars stores the captured FITS image in a temporary file. We have two methods to access BLOB data. The first method is to obtain the filename where the BLOB data is currently stored. Please note that not all BLOB data are stored by KStars into files (such as video streams) and for BLOBs that are updated very frequently (> 1 Hz), the filename might already point to the next BLOB segment and might not be current. But for regular FITS images, the filename method is more than sufficient. The other DBUS method getBLOBData returns the BLOB raw data. This might be inefficient for large blobs as DBUS is not optimized to transfer large amounts of data.

Next we obtain the filename of the blob (CCD1.CCD1 is the primary CCD whereas CCD2.CCD2 is the guide CCD chip if available). We pass the filename to the external fv tool.

# Get image file name and open it in external fv tool
fileinfo = iface.getBLOBFile("CCD Simulator", "CCD1", "CCD1")
print "We received file: ", fileinfo[0], " with format ", fileinfo[1], " and size ", fileinfo[2]

print "Invoking fv tool to view the received FITS file..."
# run external fits viewer
command = "fv " + fileinfo[0]

After closing the fv tool, the script continues execution and we finally send a command to shutdown the INDI server running on port 7624

print "Shutting down INDI server..."
# Stop INDI server

That's a very basic tutorial illustrating the capabilities of DBUS scripting with Python in KStars. If you have any questions or suggestions or scripts you'd like to share, please let us know in INDI forums!


There’s always point where you have to decide in any expensive undertaking, such as amateur astronomy, where it’s best to apply your hard earned currency. For any given piece of equipment, you have to determine what feature set is required, decide what commercial products, if any, suit your needs and finally, what your best purchase option may be. For me, there’s always been a desire to see if I can build a more cost effective solution first, before I proceed to purchase.

With that in mind, it’s been my goal for some time, to complete my automated and remote solution for my personal astronomical observatory. Not having found a cost effective remote focusing solution on the market, I decided to see about low cost DIY alternatives. During my search and evaluation I turned to the INDI platform for ideas.

My project goals were simple; I must have the following:

  1. Reduced complexity, easy to build.

  2. INDI platform compatibility. As a result, the basic solution should be deployable to any UNIX/POSIX based system.

  3. The ability to remotely support main scope focus, as well as a guide scope.

  4. Applicable to commercially available SCT scopes Meade, Celestron and guide scopes such as Orion 80ED.

  5. Use of Continuous Rotation Servos as an alternative to the higher cost, increased complexity and power requirements of a stepper based solution.

  6. Adjustable speed control.

  7. Keep It Low cost.

  8. Wireless Capability.

The ultimate desire was to have all of the above, yet have a completely integrated hardware and software interface to all of my equipment. INDI, it seemed, provided all of the features needed for imaging, guiding, tracking, control and focus in one integrated software solution, provided that my devices were all supported. They were, except for driver support for the servo based focuser I had envisioned.

No problem here, I decided, I would create my own software driver based on the excellent examples provided by the INDI site.

How did I put all of this together? I actually created two solutions, one direct wired via USB and one wireless solution:

My solution utilizes an Arduino UNO board with a simple wiring diagram to interface directly to 2 servos. It’s really quite simple, and should work with any Arduino board that can drive a servo. In my ‘direct connect’ solution which was used for testing, I connect directly to the Arduino board using a USB cable and a local indiserver instance running on the same Linux based PC as the INDI client. For deployment, I installed the INDI platform and INDI server to a Raspberry PI Rev2 and use an 802.1n USB dongle to provide remote/wireless capability to allow remote access from anywhere on my local network. First, a little bit about servos. I used ‘standard’ servos which are of a size and shape similar to those seen on hobby RC airplanes. There, the similarity ends, as RC controlled airplanes use limited travel angle servos. Their control protocols are very much different from continuous rotation servos and are not suitable for this application.

NOTE: This solution and software driver absolutely will not work with limited travel angle servos without necessary changes to the driver (and maybe not even then). The servos used for this solution must be ‘continuous rotation’. They’re available for around $9.00 USD or maybe less from vendors such as Parallax or Futaba etc.

Design considerations

  1. Continuous Rotation Servos are Open Loop devices.

    • Input Pulse Controls Direction and Rotational Speed

    • Digital pulse of 90 Stops Rotation, Smaller Value equals Clockwise rotation, Larger Value equals Counter-Clockwise Rotation, speed increases relative to absolute integer value of the pulse from 90, plus or minus. Greater the value plus or minus from 90 the greater the speed.

    • There are 3 wires on a servo, 2 wires for DC power, 1 for control, typically uses 4.8 volts.

  1. There were some tradeoffs to all of this.

    • This solution is NOT good for varying loads

    • There is no feedback on position, so automated focus mode, which requires some sort of closed loop feedback, is not an option.

    • Manual push button operation is the ONLY supported mode at this time.

  1. This basic solution should be deployable to any Unix/Posix based system upon re-build/compilation.

    1. This was developed on Ubuntu/Kubuntu Linux

    2. Currently, tested on Ubuntu/Kubuntu Open Source distribution 13.10

    3. INDI Drivers also compiled and tested on Raspberry Pi ‘Raspbian’ distribution of Linux

  2. Two (2) Servos maximum are supported in current design.

  3. No current support in this release for alternate configuration of Arduino hardware control pins to other than 8 and 9.

  4. This solution becomes wireless-enabled when drivers are deployed to Raspberry PI.

DISCLAIMER: Any decision to implement a strategy or recommendation contained in this design is made solely by you. This is what worked for me; it may not work for you. Please check your design and implementation strategy carefully. The user is responsible for ensuring suitability of this or any design and direct interfacing of all hardware.

Construction & Operations

The Arduino UNO board layout, as illustrated below, shows a direct connection to the Servo’s pulse line (which in my case was the white wire) from either pin 8 or 9 depending on the servo I wanted to control. I attached the red and black to the power and ground, respectively.

Direct USB Connection Wiring Layout

For Wireless Connection it’s almost as simple for the wiring layout. Except, here we connect the Arduino to a powered hub, the powered hub to the Raspberry Pi and we install the focus driver on the Raspberry instead of the client Linux machine. It’s that simple.

The added benefit, of course, is that we now have the option to run more devices remotely by adding new device drivers to the Raspberry Pi. Be sure your powered hub can support the demands of your devices.

How do I run all of this?

Direct Connection using USB from client Linux machine to the Arduino

  1. Launch KStars on Linux client.

  2. Connect required devices via USB.

  3. Open an XTerm session on the client and start an INDI Server with any device driver(s) including the focus driver

  4. Connect to the INDI server instance, using the IP address and port number of choice or the typical default of 7624.

  5. Use the INDI control panel to connect to the Focus Driver.

Remote/Wireless Operations from client Linux machine to the Arduino

  1. Install INDI software on Raspberry Pi

  2. Install Focus Driver software on Raspberry Pi

  3. Connect Wireless 802.1n ‘dongle’

  4. Connect Powered USB hub

  5. Power up Hub, then Raspberry Pi

  6. Connect devices to the powered hub.

  7. Open an XTerm session and initiate an SSH session to the Raspberry Pi, start indiserver with Focus Driver

  8. Start the KStars Client on the Linux Client.

  9. Connect to the remote instance of the indiserver via Tools/Devices/Device Manager/Client

  10. Use INDI Control Panel to Manage Focus and other devices.

How much will this cost?

For me the out of pocket cost wasn’t too bad, as I already had some of these components lying around.

Total Out of Pocket Hardware Cost - $ 97 USD

    • Raspberry Pi Rev2 $35 USD

    • Wireless Dongle $9 USD

    • Arduino Uno $35 USD

    • Servo $9 USD x 2

Total Out of Pocket Software Cost - $0 USD

    • Operating System $0 USD

    • KStars $0 USD

    • Driver $0 USD

How do I connect the focuser to my telescope?

First of all, I had to be creative. I don’t have a metal lathe or machine shop. There are many examples of custom mechanical solutions connecting servos to focusers on the web. Some use pulleys; others use a direct friction drive. Most are very clever and use available hardware and other common items. I’ve found that the ½ inch PVC pipe end caps available in most hardware stores fit the focus knob on the CPC-800 and the legacy LX series Meade I own perfectly and are a nice snug fit. I plan to alter my current arrangement of a friction wheel and attach the PVC cap directly to the servo using a small set screw and then use a small hardware brace made from aluminum to attach the servo to my SCT.

The Arduino is housed in a small hobby box, along with the Raspberry Pi board. Both are attached via small straps to the optical tube of my SCT. Low tech, but effective.


This design appeals to me in its simplicity and its low cost. Hopefully, it will enable you to create your own solutions and may be a starting point for your own design. Good luck!

With EQMod & Ekos, you can finally put the alignment woes to rest. No more two or three star alignment, no more trying to recenter that star in the eye piece, all you have to do is to point your mount north, and Ekos does that rest. After the first sync, you can expect your desired object to be dead center. You don't have to build any complicated models, every time you slew to a target, you can use Ekos Alignment Module to verify the location and slew to the real coordinates if necessary. This is all made possible thanks to the astrometry.net solver.

So What do you need in order to achieve sub-arcseconds GOTOs?

  • Recent version of KStars.
  • INDI Library v0.9.7 or higher.
  • Astrometry.net v0.45 or higher (for offline plate solving). Ekos supports both online and offline solvers.
  • Mount that supports EQMod.
  • CCD.

My personal setup is HEQ5 mount, QSI583wsg CCD, and I have Starlight Xpress Lodestar, but I use that for guiding only.

If you're using Ubuntu, all the packages are available for Ubuntu Saucy or later, including bleeding edge version of KStars & INDI.

sudo apt-add-repository ppa:mutlaqja/ppa
sudo apt-add-repository ppa:mutlaqja/astrometry.net
sudo apt-get update
sudo apt-get install kstars-bleeding astrometry.net

If you prefer to use the offline (local) astrometry.net solver, you need to download the index files necessary for your CCD Field of View (FOV). Please refer to Ekos Alignment Module documentation for details.

Point your mount toward Polaris, if you're the northern hemisphere, and attach your CCD to the telescope. Make sure the CCD is already in focus, if not, use Ekos Focus Module to aid you in the focusing process.

Start KStars, select Ekos from the Tools menu. Next, select the telescope driver as EQMod, and select your CCD from the drop-down list. Click Start INDI, and then Connect.

In KStars SkyMap, you will see the EQMod cross-hair close to Polaris. Go to Ekos alignment tab, and make sure Update Coordinates After Slew checkbox is checked, and under GOTO, select Slew to Target. This option instructs Ekos that once a solution is found, it slews the mount to the target coordinates.

Now, select a nearby star, right click, select EQMod, and then Track. Your mount should now start slewing to the star. After slew is complete, go to Ekos Alignment tab and click Capture & Solve. The solver may take some time to find a solution, but in my setup (offline solver) it usually takes less than 10 seconds to find a solution. Once a solution is found, Ekos will slew the telescope to the actual star coordinates. Capture an image using the CCD module, and your star should be now dead-center. 

By default, EQMod driver uses N-Star alignment to build a pointing model. Each time your perform a sync, a new point is added to the model. You don't have to do anything, this is done transparently for you. In practice when performing astrophotography, I run the Capture & Solve command after every slew, just to make sure I am really dead-center on my target. The solver typically takes 2-3 seconds to solve the image at this stage.

After you are done with your observation/astrophotography session, make sure to save the model in the Align tab of the EQMod driver, which can be found in the INDI Control Panel so that it gets loaded on subsequent observation sessions.

That's all it takes to achieve highly accurate GOTOs with EQMOd & Ekos for Linux!


The Raspberry PI (RPi) is an ARM-based credit-card-sized single board computer. It costs around $35 (Model B) and therefore it is a very attractive choice for amateur astronomers to control their equipment either locally or remotely.

Due to power limitations of the RPi, it is recommended to connect all devices to a powered USB hub. INDI Library v0.9.7 packages in addition to 3rd party drivers are available for the RPi (Raspbian). You typically would run an INDI server on the RPi and connect to it remotely from Ekos. While it is technically possible to build Ekos in RPi, it would not run smoothly; therefore it is recommended to run INDI server on the RPi and Ekos on a more powerful machine.

The following steps are applicable to RPi running the Raspbian OS:

  1. Install the dependencies:
    sudo apt-get install cdbs libcfitsio3-dev libnova-dev libusb-1.0-0-dev libjpeg-dev libusb-dev libtiff4-dev libftdi-dev fxload libcurl4-gnutls-dev dcraw libgphoto2-2-dev libgsl0-dev
  2. Download INDI Library for RPi
  3. Extract and Install INDI Library
  4. tar -xzf libindi_0.9.9_rpi.tar.gz
    cd libindi_0.9.9_rpi
    sudo dpkg -i *.deb

Included in the INDI Library for RPi are INDI servers, tools, and drivers. The following are some of the drivers in the package. For a complete list, please check the devices page:

Driver Executable
EQMod Driver indi_eqmod_telescope
Atik CCD Driver indi_atik_ccd
GPhoto Driver (for DSLRs) indi_gphoto_ccd
Starlight Xpress Driver indi_sx_ccd, indi_sx_wheel, indi_sx_ao
QSI Driver indi_qsi_ccd
QHI Driver indi_qhi_ccd
SBIG Driver indi_sbig_ccd
Fishcamp Driver indi_fishcamp_ccd
Apogee Driver indi_apogee_ccd
ZWO Optics ASI Driver indi_asi_ccd
AAG Cloud Watcher Driver indi_aagcloudwatcher

To run INDI server:

indiserver -v -m 100 driver_executable

For example, to run INDI server with EQMod, Atik CCD, and Joystick driver:

indiserver -v -m 100 indi_eqmod_telescope indi_joystick indi_atik_ccd

This will start INDI server on the RPi on port 7624 by default. You can then connect to the INDI server from Ekos/KStars or any INDI compatible client.

INDI library v0.9.7 or above supports joystick integration under Linux. To control your telescope under INDI, you need the following:

  • Wired or wireless controller supported by Linux.
  • Telescope driver that supports joystick integration.

To date, all LX200 based (LX200 GPS, Autostar..etc), Celestron, and EQMOd drivers support joystick integration.

So, how do you control your telescope? In this tutorial, I will be connecting my ThurstMaster Wireless Joystick to an LX200 GPS telescope.

Follow the steps below:

1. Start KStars

2. Go to Device Manager under the Tools Menu --> Devices.

3. Select your telescope driver from the Telescope devices tree.

4. Select the joystick driver from Auxiliary devices tree.

Make sure that both drivers are selected. After selecting the telescope driver, hold Ctrl, and scroll down to the auxliary tree, expand it, and then select the joystick driver.

5. Click Run Service

6. Connect and test your joystick driver.

Here, the driver connected successfully to the wireless controller, which has three joysticks, and six axis (each joystick has 2 axis), and 13 buttons. Next, we need to see if the driver reads the joystick input property. Click on the monitor tab, and start playing with your joystick:

As illustrated above, I was moving joystick #1 on my controller, and it showed the angle and magnitude of my motion. The numbers do not matter, what matters is to know which joystick on the physical controller correspond to which property and joystick number # within the driver, because we will use this information to map telescope actions to specific joysticks and buttons on our controller.

7. Enable joystick input in the telescope driver

 Next, select the telescope driver tab, then select the Options tab, and Enable the joystick support.

8. Set joystick preference in the telescope driver.

After the joystick is enabled, you will see a new joystick tab appearing in the telescope driver, select the joystick tab and set your settings

In the LX200 GPS driver, the NSWE Control, which is used to move the telescope North/South/West/East is by default assigned to JOYSTICK_1. Buttons #1 to #4 are assigned to different slew speeds. Finally, button #5 is assigned to the Abort Motion function. Here you can change the settings per your preferences. Just make sure you do not put JOYSTICK_# where it is expecting buttons and vice versa. How to find out which joystick is which number? You can find this out in the Monitor tab of the joystick driver, just move the joystick you prefer around a bit and check which number it is assigned to by the driver, then simply put the joystick name (JOYSTICK_1, JOYSTICK_2...etc) in the field you wish to map it, and that's it! The same is applicable to buttons.

9. Control your telescope!

 Now you are ready to control your telescope! You can test your control by click on the Motion Control tab in the telescope driver.

Here I am commanding the telescope to move Northeast by simply moving the joystick in that direction. You have to keep the joystick pressed in that direction for the telescope motion to be continuous. If you release the joystick, the telescope motion is stopped.


Subscribe to INDI


3rd Party

Choose from the numerous 3rd party INDI drivers to suit your needs!

Got Problem?

Check out the FAQ, the forum, and the bug tracking system to resolve any issues you might have!
You can also subscribe to INDI newsletter and development mailing lists to get the latest updates on INDI!