- Notifications
You must be signed in to change notification settings - Fork12
License
indilib/pyindi-client
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
version : v2.1.2
AnINDI Client Python API, auto-generated fromthe official C++ API usingSWIG.
sudo apt-add-repository ppa:mutlaqja/ppasudo apt-get -y install python3-indi-client
pip install pyindi-client
Alternatively download a zip archive (use commits history to get aprevious release), extract it and run
python setup.py install
The file [setup.cfg]{.title-ref} contains configuration options (mainlyconcerning [libindi]{.title-ref} installation path). Edit[setup.cfg]{.title-ref} if you use a libindi version < 1.4.1 (02/2017).The file setup.py searchs for the libindiclient.a library in somepredefined directories. If not found, the script fails. Locate thislibrary (try [locate lindiclient.a]{.title-ref} from the command line)and add its path to the [libindisearchpaths]{.title-ref} variable in thesetup script.
For the above installation to work, you need to have installed from yourdistribution repositories the following packages: Python setup tools,Python development files, libindi development files and swig.
On an Ubuntu-like distribution, you may use
apt-get install python-setuptoolsapt-get install python-devapt-get install libindi-devapt-get install swigapt-get install libcfitsio-devapt-get install libnova-dev
On a Fedora-like distribution, you may use
dnf install python-setuptoolsdnf install python-develdnf install libindi-develdnf install swigdnf install libcfitsio-devdnf install libnova-dev
In the following simple example, an INDI 2.0.0 client class is defined givingthe implementation of the virtual INDI client functions. This is notmandatory. This class is instantiated once, and after defining serverhost and port in this object, a list of devices together with theirproperties is printed on the console.
# for loggingimportsysimporttimeimportlogging# import the PyIndi moduleimportPyIndi# The IndiClient class which inherits from the module PyIndi.BaseClient class# Note that all INDI constants are accessible from the module as PyIndi.CONSTANTNAMEclassIndiClient(PyIndi.BaseClient):def__init__(self):super(IndiClient,self).__init__()self.logger=logging.getLogger('IndiClient')self.logger.info('creating an instance of IndiClient')defnewDevice(self,d):'''Emmited when a new device is created from INDI server.'''self.logger.info(f"new device{d.getDeviceName()}")defremoveDevice(self,d):'''Emmited when a device is deleted from INDI server.'''self.logger.info(f"remove device{d.getDeviceName()}")defnewProperty(self,p):'''Emmited when a new property is created for an INDI driver.'''self.logger.info(f"new property{p.getName()} as{p.getTypeAsString()} for device{p.getDeviceName()}")defupdateProperty(self,p):'''Emmited when a new property value arrives from INDI server.'''self.logger.info(f"update property{p.getName()} as{p.getTypeAsString()} for device{p.getDeviceName()}")defremoveProperty(self,p):'''Emmited when a property is deleted for an INDI driver.'''self.logger.info(f"remove property{p.getName()} as{p.getTypeAsString()} for device{p.getDeviceName()}")defnewMessage(self,d,m):'''Emmited when a new message arrives from INDI server.'''self.logger.info(f"new Message{d.messageQueue(m)}")defserverConnected(self):'''Emmited when the server is connected.'''self.logger.info(f"Server connected ({self.getHost()}:{self.getPort()})")defserverDisconnected(self,code):'''Emmited when the server gets disconnected.'''self.logger.info(f"Server disconnected (exit code ={code},{self.getHost()}:{self.getPort()})")logging.basicConfig(format='%(asctime)s %(message)s',level=logging.INFO)# Create an instance of the IndiClient class and initialize its host/port membersindiClient=IndiClient()indiClient.setServer("localhost",7624)# Connect to serverprint("Connecting and waiting 1 sec")ifnotindiClient.connectServer():print(f"No indiserver running on{indiClient.getHost()}:{indiClient.getPort()} - Try to run")print(" indiserver indi_simulator_telescope indi_simulator_ccd")sys.exit(1)# Waiting for discover devicestime.sleep(1)# Print list of devices. The list is obtained from the wrapper function getDevices as indiClient is an instance# of PyIndi.BaseClient and the original C++ array is mapped to a Python List. Each device in this list is an# instance of PyIndi.BaseDevice, so we use getDeviceName to print its actual name.print("List of devices")deviceList=indiClient.getDevices()fordeviceindeviceList:print(f" >{device.getDeviceName()}")# Print all properties and their associated values.print("List of Device Properties")fordeviceindeviceList:print(f"--{device.getDeviceName()}")genericPropertyList=device.getProperties()forgenericPropertyingenericPropertyList:print(f" >{genericProperty.getName()}{genericProperty.getTypeAsString()}")ifgenericProperty.getType()==PyIndi.INDI_TEXT:forwidgetinPyIndi.PropertyText(genericProperty):print(f"{widget.getName()}({widget.getLabel()}) ={widget.getText()}")ifgenericProperty.getType()==PyIndi.INDI_NUMBER:forwidgetinPyIndi.PropertyNumber(genericProperty):print(f"{widget.getName()}({widget.getLabel()}) ={widget.getValue()}")ifgenericProperty.getType()==PyIndi.INDI_SWITCH:forwidgetinPyIndi.PropertySwitch(genericProperty):print(f"{widget.getName()}({widget.getLabel()}) ={widget.getStateAsString()}")ifgenericProperty.getType()==PyIndi.INDI_LIGHT:forwidgetinPyIndi.PropertyLight(genericProperty):print(f"{widget.getLabel()}({widget.getLabel()}) ={widget.getStateAsString()}")ifgenericProperty.getType()==PyIndi.INDI_BLOB:forwidgetinPyIndi.PropertyBlob(genericProperty):print(f"{widget.getName()}({widget.getLabel()}) = <blob{widget.getSize()} bytes>")# Disconnect from the indiserverprint("Disconnecting")indiClient.disconnectServer()
Applies to all properties available in the library (Switch/Number/Text/Light/Blob)
New implementation since INDI Core 1.9.x
# setanyProperty.setDeviceName("Some device")anyProperty.setName("Some name")anyProperty.setLabel("Some label")anyProperty.setGroupName("Some group")anyProperty.setState(PyIndi.IPS_IDLE)anyProperty.setTimestamp("123")anyProperty.setPermission(PyIndi.IP_RO)# no effect for Light PropertyanyProperty.setTimeout(123)# no effect for Light PropertyanyProperty[0].setName("Some name of widget")anyProperty[0].setLabel("Some label of widget")# getdevice=anyProperty.getDeviceName()name=anyProperty.getName()label=anyProperty.getLabel()group=anyProperty.getGroupName()state=anyProperty.getState()timestamp=anyProperty.getTimestamp()perm=anyProperty.getPermission()# returns IP_RO for Light Propertytimeout=anyProperty.getTimeout()# returns 0 for Light Propertyname=anyProperty[0].getName()label=anyProperty[0].getLabel()# auxiliary functionsifanyProperty.isNameMatch("Some name"):# anyProperty.getName() is equal to "Some name"passifanyProperty.isLabelMatch("Some label"):# anyProperty.getLabel() is equal to "Some label"passifnotanyProperty.isValid():# e.g. PyIndi.Property() is not valid because type is unknown# PyIndi.PropertyText(somePropertySwitch) is also not valid because type# is mismatch (invalid cast)passstringState=anyProperty.getStateAsString()# returns Idle/Ok/Busy/AlertstringPerm=anyProperty.getPermissionAsString()# returns ro/wo/rwsomeWidget=anyProperty.findWidgetByName("Some name")# returns widget with `Some name` name
Deprecated implementation
# setanyProperty.device="Some device"anyProperty.name="Some name"anyProperty.label="Some label"anyProperty.group="Some group"anyProperty.s=PyIndi.IPS_IDLEanyProperty.timestamp="123"anyProperty.p=PyIndi.IP_RO# except Light PropertyanyProperty.timeout=123# except Light PropertyanyProperty[0].name="Some name of widget"anyProperty[0].label="Some label of widget"# getdevice=anyProperty.devicename=anyProperty.namelabel=anyProperty.labelgroup=anyProperty.groupstate=anyProperty.stimestamp=anyProperty.timestampperm=anyProperty.p# except Light Propertytimeout=anyProperty.timeout# except Light Propertyname=anyProperty[0].namelabel=anyProperty[0].label
New implementation since INDI Core 1.9.x
# settextProperty[0].setText("Some text")# gettext=textProperty[0].getText()
Deprecated implementation
# settextProperty[0].text="Some text"# gettext=textProperty[0].text
New implementation since INDI Core 1.9.x
# setnumberProperty[0].setFormat("Some format")numberProperty[0].setMin(0)numberProperty[0].setMax(1000)numberProperty[0].setMinMax(0,1000)# simplificationnumberProperty[0].setStep(1)numberProperty[0].setValue(123)# getformat=numberProperty[0].getFormat()min=numberProperty[0].getMin()max=numberProperty[0].getMax()step=numberProperty[0].getStep()value=numberProperty[0].getValue()
Deprecated implementation
# setnumberProperty[0].format="Some format"numberProperty[0].min=0numberProperty[0].max=1000numberProperty[0].step=1numberProperty[0].value=123# getformat=numberProperty[0].formatmin=numberProperty[0].minmax=numberProperty[0].maxstep=numberProperty[0].stepvalue=numberProperty[0].value
New implementation since INDI Core 1.9.x
# setswitchProperty.setRule(PyIndi.ISR_NOFMANY)switchProperty[0].setState(PyIndi.ISS_ON)# getrule=switchProperty.getRule()state=switchProperty[0].getState()# auxiliary functionsstringRule=switchProperty.getRuleAsString()# returns OneOfMany/AtMostOne/AnyOfManystringState=switchProperty[0].getStateAsString()# returns On/OffswitchProperty.reset()# reset all widget switches to OffswitchProperty.findOnSwitchIndex()# find index of Widget with On stateswitchProperty.findOnSwitch()# returns widget with On state
Deprecated implementation
# setswitchProperty.r=PyIndi.ISR_NOFMANYswitchProperty[0].s=PyIndi.ISS_ON# getrule=switchProperty.rstate=switchProperty[0].s
New implementation since INDI Core 1.9.x
# setlightProperty[0].setState(PyIndi.IPS_BUSY)# getlightState=lightProperty[0].getState()# auxiliary functionsstringState=lightProperty[0].getStateAsString()# returns Idle/Ok/Busy/Alert
Deprecated implementation
# setlightProperty[0].s=PyIndi.IPS_BUSY# getlightState=lightProperty[0].s
New implementation since INDI Core 1.9.x
# setblobProperty[0].setFormat("Some format")blobProperty[0].setBlob("Some blob")blobProperty[0].setBlobLen(123)blobProperty[0].setSize(123)# getformat=blobProperty[0].getFormat()blob=blobProperty[0].getBlob()bloblen=blobProperty[0].getBlobLen()size=blobProperty[0].getSize()
Deprecated implementation
# setblobProperty[0].format="Some format"blobProperty[0].blob="Some blob"blobProperty[0].bloblen=123blobProperty[0].size=123# getformat=blobProperty[0].formatblob=blobProperty[0].blobbloblen=blobProperty[0].bloblensize=blobProperty[0].size
As of INDI Core 2.0.0, there are no features like:
- newText
- newSwitch
- newNumber
- newLight
- newBlob
They have been replaced with a singleupdateProperty
function to differentiate the behavior betweennewProperty
and to provide more memory control in the INDI Core library itself.
It is not required to implement all functions. Please use as needed.
classIndiClient(PyIndi.BaseClient):def__init__(self):super(IndiClient,self).__init__()# Emmited when a new device is created from INDI server.defnewDevice(self,dev):pass# Emmited when a device is deleted from INDI server.defremoveDevice(self,dev):pass# Emmited when a new property is created for an INDI driver.defnewProperty(self,genericProperty):pass# Emmited when a new property value arrives from INDI server.defupdateProperty(self,genericProperty):pass# Emmited when a property is deleted for an INDI driver.defremoveProperty(self,genericProperty):pass# Emmited when a new message arrives from INDI server.defnewMessage(self,device,messageId):pass# Emmited when the server is connected.defserverConnected(self):pass# Emmited when the server gets disconnected.defserverDisconnected(self,exitCode):pass
The functionnewProperty
andupdateProperty
provide in argument a generic type in which you can read common information for all properties such as name, group, device, type, state. To read values associated with a specific type, e.g.Switch
, you need to perform cast.
switchProperty=PyIndi.PropertySwitch(genericProperty)
If successful, the functionswitchProperty.isValid()
will returntrue
.
A similar mechanism existed before version 2.0.0 for thenewProperty
function.
With Python, migration can be simple. Nothing stands in the way of creating a function for a given property type and naming it the same as for the INDI Core 1.x.x version
classIndiClient(PyIndi.BaseClient):def__init__(self):super(IndiClient,self).__init__()# Call functions in old styledefupdateProperty(self,prop):ifprop.getType()==PyIndi.INDI_NUMBER:self.newNumber(PyIndi.PropertyNumber(prop))elifprop.getType()==PyIndi.INDI_SWITCH:self.newSwitch(PyIndi.PropertySwitch(prop))elifprop.getType()==PyIndi.INDI_TEXT:self.newText(PyIndi.PropertyText(prop))elifprop.getType()==PyIndi.INDI_LIGHT:self.newLight(PyIndi.PropertyLight(prop))elifprop.getType()==PyIndi.INDI_BLOB:self.newBLOB(PyIndi.PropertyBlob(prop)[0])# The methods work again in INDI Core 2.0.0!defnewBLOB(self,prop):print(f"new BLOB{prop.getName()}")defnewSwitch(self,prop):print(f"new Switch{prop.getName()} for device{prop.getDeviceName()}")defnewNumber(self,prop):print(f"new Number{prop.getName()} for device{prop.getDeviceName()}")defnewText(self,prop):print(f"new Text{prop.getName()} for device{prop.getDeviceName()}")defnewLight(self,prop):print(f"new Light{prop.getName()} for device{prop.getDeviceName()}")
Versions | commit | pip |
---|---|---|
v2.0.4 - latest | HEAD | pip3 install 'git+https://github.com/indilib/pyindi-client.git' |
v2.0.0 - v2.0.3 | indilib/pyindi-client@674706f | pip3 install 'git+https://github.com/indilib/pyindi-client.git@674706f#egg=pyindi-client' |
v1.9.9 | indilib/pyindi-client@ce808b7 | pip3 install 'git+https://github.com/indilib/pyindi-client.git@ce808b7#egg=pyindi-client' |
v1.9.8 | indilib/pyindi-client@ffd939b | pip3 install 'git+https://github.com/indilib/pyindi-client.git@ffd939b#egg=pyindi-client' |
See theexamplesfor more simple demos of usingpyindi-client.
See theinterfacefilefor an insight of what is wrapped and how.
For documentation on the methods of INDI Client API, refer to theINDIC++ API documentation.
pyindi-client code is free software under theGNU General PublicLicense v3 or later (GPLv3+).