5.2. Servicing Protocol (RS-232)#
The servicing protocol is used to read and modify the operating parameters of the flow meter. Device settings such as filtering parameters, measurement units selection, interface configuration, and other internal parameters are adjusted using this protocol.
Since the NMEA-like measurement protocol is unidirectional (measurement data is transmitted only from the device to the host), the servicing protocol provides independent two-way configuration and maintenance access on the same RS-232 interface when the device is awake. To simplify device setup and parameter adjustment, Geolux provides the Geolux Instrument Configurator software tool. End users typically do not need to interact directly with the servicing protocol, as all configuration tasks are performed through the Configurator application. A detailed description of the software is provided in 6. Geolux Instrument Configurator.
Each command must begin with the ‘#’ character and be terminated with a newline character. All standard combinations of carriage return (CR) and line feed (LF) characters (CR, LF, or CR+LF) are accepted as valid line termination.
Reading All Parameters at Once#
To read all parameters at once, send the following command to the device:
#get_info
The device will respond with a structured list of all current parameters and system information in the following format:
#device_type: 10003
#firmware: 1.2.3
#serial_number: 12345
#<parameter_name_1>: <value1>
#<parameter_name_2>: <value2>
...
#update_status: 0
The response includes device identification information (such as device type, firmware version, and serial number), followed by all configurable and status parameters. A complete description of all available parameters is provided later in this chapter.
Reading Single Parameter#
Any configuration parameter can be read individually:
#get_<parameter_name>
The device will respond:
#<parameter_name>: <value>
Writing Single Parameter#
Any configuration parameter that is not read-only can be changed by the following command format:
#set_<parameter_name>=<value>
The device will respond, depending on success or failure:
#set_<parameter_name>:OK
#set_<parameter_name>:ERR
Enumerated parameters accept both the string name and the numeric index, for example:
#set_direction=incoming
#set_direction=1
List of Parameters#
Maximum Velocity Treshold#
Defines the upper bound for valid surface velocity measurements. Velocity readings above this threshold are rejected. The numeric value parameter is interpreted in the unit defined by max_velocity_unit.
See Maximum Velocity for the detailed setting description.
max_velocity#get_max_velocity#set_max_velocity=<value>Maximum Velocity Unit#
Defines the physical unit used by max_velocity command. The accepted units are:
See Maximum Velocity for the detailed setting description.
mms= mm/s,ms= m/s,mph= mph,kmh= km/h,fps= ft/s,fpm= ft/min,cms= cm/s.
max_velocity_unit#get_max_velocity_unit#set_max_velocity_unit=<value>Direction Filter#
Defines the direction filter configuration. The accepted values are:
See Direction Filter for the detailed setting description.
both= measure both directions,incoming= incoming flow only,outgoing= outgoing flow only.
direction#get_direction#set_direction=<value>SNR Threshold#
Defines the SNR threshold value for the surface velocity radar. See SNR Threshold for the detailed setting description.
snr_threshold#get_snr_threshold#set_snr_threshold=<value>Filter Length#
Defines the number of seconds used for internal smoothing. Higher values reduce noise but increase response lag. The valid range is between 1 and 120.
See Filter Length for the detailed setting description.
filter_len#get_filter_len#set_filter_len=<value>Discharge Unit#
Defines the unit used for the discharge value in the SDI-12 measurement response, NMEA and on Modbus output. See Discharge Output Unit for the detailed setting description.
The accepted units are:
m3/s= m³/s,m3/h= m³/h,l/s= l/s,l/h= l/h,cfs= ft³/s,gal/min= gal/min,ML/day= ML/day.
discharge_unit#get_discharge_unit#set_discharge_unit=<value>Water Level Unit#
Defines the unit used for the water level value in the SDI-12 measurement response, NMEA and on Modbus output. See Water Level Output Unit for the detailed setting description.
The accepted units are:
mm= millimeters,cm= centimeters,m= meters,ft= feet,in= inches.
level_unit#get_level_unit#set_level_unit=<value>Velocity Output Unit#
Defines the unit used for the velocity value in the SDI-12 measurement response, NMEA and on Modbus output. See Surface Velocity Output Unit for the detailed setting description.
The accepted units are:
mms= mm/s,ms= m/s,mph= mph,kmh= km/h,fps= ft/s,fpm= ft/min,cms= cm/s.
units#get_units#set_units=<value>Volume Output Unit#
Defines the unit used for the total flow volume value in the SDI-12 measurement response, NMEA and on Modbus output. See Volume Output Unit for the detailed setting description.
The accepted units are:
m3= cubic meters,l= liters,ft3= cubic feet,gal= galons,ML= mega (million) liters.
volume_unit#get_volume_units#set_volume_units=<value>Beam Width#
Defines the radar beam width pattern for the surface velocity radar. Wide beam covers a larger area; narrow beam is more focused and rejects off-axis targets. The accepted values are:
See Beam Width for the detailed setting description.
wide,narrow.
beam_width#get_beam_width#set_beam_width=<value>Beam Offset#
Defines the near or far measurement zone placed along the radar beam used for target detection, for the surface velocity radar. The accepted values are:
See Beam Position for the detailed setting description.
near,far.
beam_offset#get_beam_offset#set_beam_offset=<value>DFP Enable#
Defines the enable status of Dynamic Flow Profiler algorithm, which tracks and accumulates flow history for improved accuracy in low-flow conditions. The accepted values are:
See Dynamic Flow Profiler for the detailed setting description.
off,on.
use_dfp#get_use_dfp#set_use_dfp=<value>Radar Height#
Gets / sets the vertical distance between the instrument and the water level reference point (gauge zero). The instrument uses this value to calculate and report the water level relative to the gauge zero. The corresponding measurement unit is defined by radar_height_unit parameter.
radar_height#get_radar_height#set_radar_height=<value>Radar Height Unit#
Defines the measurement unit for the radar_height parameter.
The accepted units are:
mm= millimeters,cm= centimeters,m= meters,ft= feet,in= inches.
radar_height_unit#get_radar_height_unit#set_radar_height_unit=<value>Minimum Valid Distance#
Defines the minimum valid distance to water surface. Reflections detected closer than this distance are ignored. Use this parameter to exclude near-field returns e.g., mounting hardware, bridge elements, or other objects close to the sensor. The corresponding measurement unit is defined by min_distance_unit parameter.
See Minimum Distance for the detailed setting description.
min_distance#get_min_distance#set_min_distance=<value>Minimum Valid Distance Unit#
Defines the measurement unit used by min_distance parameter. The accepted units are:
See Minimum Distance for the detailed setting description.
mm,cm,m,ft,in.
min_distance_unit#get_min_distance_unit#set_min_distance_unit=<value>Maximum Valid Distance#
Gets / sets the maximum valid distance to water surface. Reflections detected beyond this distance are ignored. Use this parameter to exclude far-field returns outside the intended measurement zone e.g., opposite bank, structures, or background targets. The corresponding measurement unit is defined by max_distance_unit parameter.
See Maximum Distance for the detailed setting description.
max_distance#get_max_distance#set_max_distance=<value>Maximum Valid Distance Unit#
Gets / sets the measurement unit used by max_distance parameter. The accepted units are:
See Maximum Distance for the detailed setting description.
mm,cm,m,ft,in.
max_distance_unit#get_max_distance_unit#set_max_distance_unit=<value>RS-232 Baud Rate#
Gets / sets the baud rate of the RS-232 serial interface. The change takes effect immediately. The accepted values for baud rates are:
See RS-232 Baud Rate for the detailed setting description.
4800,9600,14400,19200,38400,57600,115200.
baud_rate#get_baud_rate#set_baud_rate=<value>Modbus Baud Rate#
Gets / sets the baud rate of the RS-485/Modbus serial interface. The change takes effect immediately. The accepted values for baud rates are:
See RS-485 Baud Rate for the detailed setting description.
4800,9600,14400,19200,38400,57600,115200.
modbus_baud_rate#get_modbus_baud_rate#set_modbus_baud_rate=<value>Modbus Device ID#
Gets / sets the Modbus RTU slave address. Must be unique on the RS485 bus. The accepted value range for Modbus RTU slave address is 1 - 247.
See Modbus ID for the detailed setting description.
modbus_id#get_modbus_id#set_modbus_id=<value>Modbus Serial Line Parity#
Gets / sets the serial line parity for RS-485 / Modbus connection. The change takes place immediately. The accepted values are:
See Modbus Parity for the detailed setting description.
none,odd,even.
modbus_parity#get_modbus_parity#set_modbus_parity=<value>Modbus Serial Line Stop Bits#
Gets / sets the number of stop bits for the serial line of RS-485 / Modbus connection. The change takes place immediately. The accepted values are:
See RS-485 Stop Bits for the detailed setting description.
one,two.
modbus_stopbits#get_modbus_stopbits#set_modbus_stopbits=<value>SDI-12 Address#
Address of the device on the SDI-12 bus. Valid range is 0-61, which will be converted to characters 0-9, A-Z and a-z.
See SDI-12 ID for the detailed setting description.
sdi_id#get_sdi_id#set_sdi_id=<value>Disable NMEA Output#
Gets / sets the parameters that disables NMEA sentence output on RS-232. The accepted values are:
off,on.
disable_nmea#get_disable_nmea#set_disable_nmea=<value>Analog Output Type#
Gets / sets the which device measurement will be used to drive the analog output.
See 4 - 20 mA Output Type for the detailed setting description.
The accepted values are:
none,discharge,level,distance,velocity,volume.
analog_output#get_analog_output#set_analog_output=<value>Analog Output Minimum Value#
Gets / sets the measurement value that corresponds to the minimum output on the analog current interface (4 mA). The corresponding measurement unit is defined by analog_min_unit parameter.
See 4 - 20 mA Minimum Value for the detailed setting description.
analog_min#get_analog_min#set_analog_min=<value>Analog Output Minimum Unit#
Gets / sets the measurement unit for the value defined by analog_min parameter. The accepted units depend on the analog_output parameter.
If the analog_output is set to discharge:
m3/s= m³/s,m3/h= m³/h,l/s= l/s,l/h= l/h,cfs= ft³/s,gal/min= gal/min,ML/day= ML/day.
If the analog_output is set to level or distance:
mm= millimeters,cm= centimeters,m= meters,ft= feet,in= inches.
If the analog_output is set to velocity:
mms= mm/s,ms= m/s,mph= mph,kmh= km/h,fps= ft/s,fpm= ft/min,cms= cm/s.
If the analog_output is set to volume:
m3= cubic meters,l= liters,ft3= cubic feet,gal= galons,ML= mega (million) liters.
See 4 - 20 mA Minimum Value for the detailed setting description.
analog_min_unit#get_analog_min_unit#set_analog_min_unit=<value>Analog Output Maximum Value#
Gets / sets the measurement value that corresponds to the maximum output on the analog current interface (20 mA). The corresponding measurement unit is defined by analog_max_unit parameter.
See 4 - 20 mA Maximum Value for the detailed setting description.
analog_max#get_analog_max#set_analog_max=<value>Analog Output Maximum Unit#
Gets / sets the measurement unit for the value defined by analog_max parameter. The accepted units depend on the analog_output parameter.
If the analog_output is set to discharge:
m3/s= m³/s,m3/h= m³/h,l/s= l/s,l/h= l/h,cfs= ft³/s,gal/min= gal/min,ML/day= ML/day.
If the analog_output is set to level or distance:
mm= millimeters,cm= centimeters,m= meters,ft= feet,in= inches.
If the analog_output is set to velocity:
mms= mm/s,ms= m/s,mph= mph,kmh= km/h,fps= ft/s,fpm= ft/min,cms= cm/s.
If the analog_output is set to volume:
m3= cubic meters,l= liters,ft3= cubic feet,gal= galons,ML= mega (million) liters.
See 4 - 20 mA Maximum Value for the detailed setting description.
analog_max_unit#get_analog_max_unit#set_analog_max_unit=<value>Configure Power Management Mode (SDI-12 Sleep Mode)#
Gets / sets the automatic SDI-12 sleep mode parameter. When sleep is enabled, the device enters low-power sleep between SDI-12 transactions. When disabled, the sensor runs continuously and is ready at all times. The accepted values are:
See Power Management for the detailed setting description.
on= sleep enabled,off= sleep disabled (continuous scanning).
sdi_sleep#get_sdi_sleep#set_sdi_sleep=<value>Configure Operation Mode#
Gets / sets the operation mode parameter. When the operation mode is set to standby, the device will go to standby mode. In standby mode, it will communicate on all communication interfaces, but the radar transmitters will be turned off to reduce the power, and the instrument will not be making any measurements. The accepted values are:
See Operation Mode for the detailed setting description.
off= normal operation,on= standby operation.
power_save#get_power_save#set_power_save=<value>Configure Wi-Fi Operation Mode#
Gets / sets the WiFi hotspot status:
off= default setting, the WiFi access point on the instrument is disabled,on= WiFi hotspot on the instrument is active.
See Enable WiFi for the detailed setting description.
enable_wifi#get_enable_wifi#set_enable_wifi=<value>Configure Wi-Fi Password#
Gets / sets the WiFi hotspot password. The password must be at least 8 characters long.
See WiFi Password for the detailed setting description.
wifi_password#get_wifi_password#set_wifi_password=<value>Configure LiDAR Mode#
Gets / sets the automatic LiDAR scanning mode. The accepted values are:
off= automatic scanning is disabled,automatic= the channel cross-section is scanned periodically.
See LiDAR Mode for the detailed setting description.
lidar_mode#get_lidar_mode#set_lidar_mode=<value>Configure LiDAR Scan Period#
Gets / sets the interval between two consecutive automatic LiDAR scans, in minutes. The valid range is between 1 and 1440 minutes. This parameter is used only when lidar_mode is set to automatic.
See LiDAR Scan Period for the detailed setting description.
lidar_scan_period_min#get_lidar_scan_period_min#set_lidar_scan_period_min=<value>Configure LiDAR Left Limit Angle#
Gets / sets how far the LiDAR sweep extends towards the left side of the channel, in degrees measured from the vertical axis of the instrument. The default value of 70 corresponds to the full mechanical sweep range of the sensor.
See Left Limit Angle for the detailed setting description.
lidar_left_limit_angle#get_lidar_left_limit_angle#set_lidar_left_limit_angle=<value>Configure LiDAR Right Limit Angle#
Gets / sets how far the LiDAR sweep extends towards the right side of the channel, in degrees measured from the vertical axis of the instrument. The default value of 70 corresponds to the full mechanical sweep range of the sensor.
See Right Limit Angle for the detailed setting description.
lidar_right_limit_angle#get_lidar_right_limit_angle#set_lidar_right_limit_angle=<value>Configure Fixed Mounting Angle#
Override measured forward angle with a fixed value (degrees). Changing this parameter will affect the reported velocity as cosine correction behaviour will be changed. Use this parameter only during tow-tank testing. Set 0 to use real measured angle. The accepted value range for fixed angle is: 0 - 89.
fixed_angle#get_fixed_angle#set_fixed_angle=<value>Show Data on Error#
Continue reporting velocity data even when angle errors are detected. The accepted values are:
off= clear velocity on error (send 0 as velocity instead of the measured value),on= keep velocity.
show_data_on_error#get_show_data_on_error#set_show_data_on_error=<value>List of Commands#
Perform Soft Reset#
Restarts the device firmware. All settings are retained (stored in non-volatile memory). The device will be unresponsive for a few seconds after issuing this command.
#resetReset DFP#
Clears all accumulated DFP history data. Use this after a significant change in site conditions or sensor placement.
#reset_dfpFactory Reset#
Restores all settings to their factory defaults and restarts the device. This is irreversible.
#factory_resetSet Staff Gauge Reading#
Takes current reading from the staff gage to automatically adjust the radar_height parameter according to the given value and current measurement of the distance to water surface.
#set_staff_gauge=<value>Reset Totalizer#
Resets the volume totalizer which keeps track of the total accumulated volume over time.
#reset_totalizerStart Manual LiDAR Scan#
Starts a single LiDAR scan of the channel cross-section. The command can be used regardless of the configured LiDAR mode. The scan takes 30 to 45 seconds to complete. If a scan is already running, the command is ignored.
See Manual LiDAR Scan for the detailed description.
#start_manual_scanCheck LiDAR Scan Status#
The status of the LiDAR scanning is reported in the #get_info response, in the #lidar_scan_status line:
off= no scan is currently running,manual= a manually started scan is in progress,automatic= an automatic scan is in progress.
Send #get_info and read the reported value to check whether a scan is still ongoing:
#lidar_scan_status: manual
Reading LiDAR Scan#
The channel cross-section produced by the most recent manual LiDAR scan (the same data shown on the LiDAR page of the configurator, see 6.3. Using LiDAR) can be read out over the servicing protocol.
Unlike the simple text parameters, the scan is a relatively large data set (up to
1000 measured points). To transfer it efficiently it is serialized to a compact
binary form, compressed, and returned in a single dedicated response rather than
as a plain #<name>: <value> line.
Request#
#read_lidarscan=manual
Response#
The device replies with a single line:
#lidarscan=<length>,<data>,<crc>\r\n
<length>– the number of bytes in the<data>field, as a decimal number.<data>– the scan payload (see below), byte-stuffed so that it does not contain any character that would break the line-based protocol.<crc>– a four-character uppercase hexadecimal CRC-16 (see CRC) computed over the compressed payload before byte-stuffing.
If the scan cannot be prepared (for example, no scan is stored or the device is out of memory), the device responds with:
#lidarscan:ERR
Payload encoding#
The <data> field is produced in three steps:
Serialization. The scanned profile is encoded as a CBOR (RFC 8949) map. The relevant keys are:
Key
Type
Description
unttext string
Unit of the coordinates. Always
mm.xarray of float32
X coordinates of the profile points, left to right.
yarray of float32
Y coordinates of the profile points. Values are negative, measured downward from the sensor.
xof,yoffloat32
X and Y offsets applied to the coordinates.
0for a raw scan.lvl,kfc,shp,sld,sdp,shnarray / bool / uint
Discharge and channel-shape metadata. Empty / zero for a raw scan. Can be ignored.
The
xandyarrays have the same length and together define the cross-section points.Compression. The CBOR byte stream is compressed with Zstandard (zstd).
Byte-stuffing. The compressed bytes are escaped so that no reserved character remains in the payload. Each reserved byte is replaced by the
=character followed by a single digit:Original byte
Escaped as
#(0x23)=0=(0x3D)=1,(0x2C)=2CR (0x0D)
=3LF (0x0A)
=4NUL (0x00)
=5$(0x24)=6To recover the compressed payload, reverse this mapping: whenever a
=is found, read the following digit and substitute the corresponding byte.
CRC#
The CRC is a CRC-16 with polynomial 0x8005, initial value 0, and input
and output reflected. This is the algorithm commonly known as CRC-16/ARC. It
is computed over the compressed payload before byte-stuffing (i.e. over the
same bytes obtained after un-escaping the received <data> field).
Python example#
The following example reads the scan over the serial port and saves the profile
as a CSV file with x and y columns in millimeters. It requires the
pyserial, zstandard, and cbor2 packages
(pip install pyserial zstandard cbor2).
import csv
import serial
import zstandard
import cbor2
PORT = "COM3" # serial port of the FX200 (e.g. "/dev/ttyUSB0")
BAUD = 115200
OUTPUT_CSV = "lidar_profile.csv"
# Byte-stuffing table: index -> original byte (see the escaping table above).
SUBS = b"#=,\r\n\x00$"
def unescape(data: bytes) -> bytes:
out = bytearray()
i = 0
while i < len(data):
if data[i] == ord("="):
i += 1
idx = data[i] - ord("0")
if 0 <= idx <= 6:
out.append(SUBS[idx])
else:
out.append(data[i])
i += 1
return bytes(out)
def crc16_arc(data: bytes) -> int:
"""CRC-16/ARC: polynomial 0x8005, init 0, reflected in/out."""
crc = 0
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 1:
crc = (crc >> 1) ^ 0xA001 # 0xA001 = bit-reversed 0x8005
else:
crc >>= 1
return crc
with serial.Serial(PORT, BAUD, timeout=5) as port:
port.write(b"#read_lidarscan=0\r\n")
# Read lines until the "#lidarscan=" response arrives.
line = b""
while True:
line = port.readline()
if not line:
raise TimeoutError("no response from device")
if line.startswith(b"#lidarscan"):
break
if line.startswith(b"#lidarscan:ERR"):
raise RuntimeError("device could not provide a LiDAR scan")
body = line[len("#lidarscan="):].rstrip(b"\r\n")
length_str, rest = body.split(b",", 1)
length = int(length_str)
escaped = rest[:length]
crc_received = int(rest[length + 1:], 16)
compressed = unescape(escaped)
if crc16_arc(compressed) != crc_received:
raise ValueError("CRC mismatch")
cbor_bytes = zstandard.ZstdDecompressor().decompress(compressed)
profile = cbor2.loads(cbor_bytes)
with open(OUTPUT_CSV, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["x_mm", "y_mm"])
for x, y in zip(profile["x"], profile["y"]):
writer.writerow([x, y])
print(f"Saved {len(profile['x'])} points to {OUTPUT_CSV}")