Vögtlin Instruments Python API
How to install
To install the Vögtlin Instruments Python API ("viapi") package:
- Install Python (version 3.8 or more recent)
- Open a terminal and type (requires pip):
- If SSL is available:
pip install --no-cache-dir --extra-index-url https://api.voegtlin.com viapi
or*
python -m pip install --no-cache-dir --extra-index-url https://api.voegtlin.com viapi
- Without SSL using HTTP only:
pip install --no-cache-dir --trusted-host api.voegtlin.com --extra-index-url http://api.voegtlin.com viapi
or*
python -m pip install --no-cache-dir --trusted-host api.voegtlin.com --extra-index-url http://api.voegtlin.com viapi
* Use this if multiple Python versions are installed on the machine
- To verify install open a Python interactive shell and type:
import viapi
This should not raise any errors.
- To use a local copy of the register database type:
viapi.Updater.update_database()
This downloads and stores register database on local machine.
Otherwise most recent register definitions are fetched from the internet whenever needed ("on-the-fly").
To install a specific package version use the following command:
# install version 1.0.1
pip install --no-cache-dir --extra-index-url https://api.voegtlin.com --force-reinstall "viapi==1.0.1"
To update the package to the most recent version use one of the following commands:
- If SSL is available:
python -m pip install viapi --upgrade --no-cache-dir --extra-index-url https://api.voegtlin.com
- Without SSL using HTTP only:
python -m pip install viapi --upgrade --no-cache-dir --trusted-host api.voegtlin.com --extra-index-url http://api.voegtlin.com
Getting started
Using a dflux flow meter to read current flow value:
import viapi
# Make an object for serial port to which device is connected (COM1),
# specify serial port settings (57600,8,N,1) and MODBUS slave address (247)
serial = viapi.IO(port=1, slave=247, baudrate=57600, parity='N')
# Specify type of device and connect via serial port
device = viapi.Instrument('dflux').connect(serial)
# Read flow value
print(device['FLOW_VALUE'])
Using a Smart 6.0 flow meter:
serial = viapi.IO(port=1, slave=247, baudrate=9600, parity='E')
device = viapi.Instrument('smart', '<= 6.0').connect(serial)
Reading and writing registers
Simple syntax to read and write registers:
# Select degree Celsius as temperature unit
device['TEMP_UNIT_SELECT'] = 1
# Read temperature value (now in °C)
print('{} {}'.format(device['TEMP_VALUE'], device['TEMP_UNIT_NAME']))
Use extended syntax to partially read and write array registers:
# Set user range overflow to 8%
device.write(register='RANGE_N_OVERFLOW', offset=2, count=1, value=8.0)
# The simple syntax "device['RANGE_N_OVERFLOW'][2]" is less efficient
# because it would first read the entire array
# and then discard all unneeded values.
print(device.read(register='RANGE_N_OVERFLOW', offset=2, count=1))
Check if a register exists:
index = 6 # mln/min
# If possible don't store selection in persistent memory
if device.exists('FLOW_UNIT_SELECT_RAM') == True:
device['FLOW_UNIT_SELECT_RAM'] = index
else:
device['FLOW_UNIT_SELECT'] = index
Check if a register is readable and writable:
# Reset totalizer if supported by device and current active user
if device.writable('TOTALIZER_VALUE'):
device['TOTALIZER_VALUE'] = 0
# Read pressure if the device can measure this or assume a default
if device.readable('PRESSURE_VALUE'):
pressure = device['PRESSURE_VALUE']
else:
pressure = 1013.25
MODBUS register names are always case-sensitive.
Repository location
By default most recent register definitions are used.
This however requires internet access to download register definitions.
A local directory containing the register definitions can be used instead:
import os
# Use local register definitions in folder 'database' relative to current location.
# Execute this before creating any Instrument objects.
viapi.Instrument.REPOSITORY = os.path.realpath('./database')
Register definitions can be put into a ZIP archive if they reside in local filesystem:
viapi.Instrument.REPOSITORY = os.path.realpath("db.zip")
The default setting
viapi.Instrument.REPOSITORY = None
downloads most recent register definitions as long as there is no such local repository.
To create a local repository invoke the following command using interactive Python shell:
import viapi
viapi.Updater.update_database()
Executing this downloads the repository from server and copies it into local package folder.
After this is done the register definitions in this local repository are used.
The register database db.zip is also available for download.
Instruments
The device version is needed to load proper register definitions.
If no specific device version is given the most recent device version is assumed.
It is possible to manually choose a specific device version when creating an Instrument object:
# Most recent version >= 6.0.0 but < 7.0
device = viapi.Instrument('smart', '>= 6.0.0, < 7.0')
It is also possible to auto-detect a device:
import viapi
# Create Instrument object without arguments to enable auto-detection:
# The device will be auto-detected as soon as an I/O channel is assigned.
device = viapi.Instrument()
device.connect(viapi.IO(port=1, slave=247, baudrate=9600, parity='E'))
This detects device type only. It's still required to specify connection settings.
Some device families (e.g. Smart 6.0) do not support auto-detection.
To close underlying serial port disconnect the Instrument object:
device.disconnect()
To boost performance the Instrument object keeps a cache containing several device settings.
If the device is reset bypassing the library this cache must be refreshed:
device.sync()
This is not required if the library is used to reset the device.
User privilege and access rights
Some registers require additional user privilege.
To access those registers it's required to login via username and password:
# use real username and password here
password = 0
device.login('username', password)
A more advanced approach is to assign a Personality object that contains
one or more user credentials (username and password):
# use real usernames and passwords here
personality = viapi.Personality({'user_1': 0, 'user_2': 0})
device.user(personality)
The user privilege is then automatically escalated behind the scenes as needed upon register access.
The Personality object can be assigned to multiple instruments.
Logging
By default the terminal is used to output logging data. This can be turned off
viapi.Logger.redirect(None)
or redirected into a file or a file-like object
viapi.Logger.redirect(open('viapi.log', 'a'))
or into another output stream
import sys
viapi.Logger.redirect(sys.stderr)
Additional debug output can be enabled by setting the verbose attribute on an Instrument object:
device = viapi.Instrument()
device.verbose = True
Device memory
It is possible to read and write the configuration memory of devices.
This requires extended user privilege and may not be supported by old devices.
# use real username and password here
password = 0
device.login('username', password)
# Create a backup of configuration memory and if successful overwrite with new data
if device.read_memory(0, "backup.bin") > 0:
device.write_memory(0, "new.bin")
Device settings are stored in persistent EEPROM memory.
These settings can be read and written like any MODBUS register e.g.
device['EE_SWITCH_VALUE'] = 0
This requires extended user privilege and may not be supported by old devices.