Skip to content

An INDI client implemented with only the Python 3.7+ standard library

License

Notifications You must be signed in to change notification settings

magao-x/purepyindi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

purepyindi

Build status: Status badge for continuous integration

A pure Python client for INDI (the Instrument Neutral Distributed Interface) implemented with only the standard library of Python 3.6. (Compatible with Python 3.6 and later.)

Used by the MagAO-X team to control the instrument from scripts and Python notebooks.

Follows the INDI protocol version 1.7 spec, with the following deviations:

  • supports nullable number properties (represented as the empty string or whitespace in the XML messages, as None in the Python API)
  • adds and expects the 'Z' suffix to indicate UTC in ISO timestamps (e.g. 2019-08-12T20:49:50.420459Z) — other timezones not supported
  • does not support sexagesimal number formats in properties
  • when changing text and number property vectors, only the changed element in the vector is sent as part of the newProperty message

Quick start

$ git clone https://github.com/magao-x/purepyindi.git
$ pip install -e ./purepyindi[dev,ipyindi,plotINDI]
$ ipyindi
waiting to receive properties...

known properties:

maths_x.val.value=0.0

try:

>>> c['maths_x.val.value'] = 'something'

In [1]: c['maths_x.val.value'] = 4

In [2]: print(c)

maths_x.val.value=4.0

Connecting

from purepyindi.client import INDIClient
c = INDIClient('localhost', 7624)
c.start()

Reading properties

print(c.devices['devicename'].properties['propertyname'].elements['elementname'].value)
# or
print(c['devicename.propertyname.elementname'])

Setting properties

c.devices['devicename'].properties['propertyname'].elements['elementname'].value = 123.45
# or
c['devicename.propertyname.elementname'] = 123.45

Watching elements

def my_watcher(element, did_anything_change):
    if did_anything_change:
        print(f'{element.property.device.name}.{element.property.name}.{element.name} was just updated to {element.value}')

c.devices['devicename'].properties['propertyname'].elements['elementname'].add_watcher(my_watcher)

Wait for a desired state

targ = 50
c.wait_for_state({
    'timeSeriesSimulator.gizmo_0000.current': {
        'value': targ,
        'test': lambda current, value: abs(current - value) < tolerance,
    },
    'timeSeriesSimulator.gizmo_0000.target': {'value': targ},
    'timeSeriesSimulator.function.sin': {'value': SwitchState.ON},
})

The 'test' key lets you handle approximate equality in a customizable way, which can be useful when commanding things like stage moves where the requested position will not be reached to infinite precision. The callable gets the value from the sibling key in that dict, and the current value from incoming INDI messages that update the referenced element.

About

An INDI client implemented with only the Python 3.7+ standard library

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages