External Programs¶
The MeterVision program achieves maximum efficiency when used in combination with other programs capable of processing machine vision recognition results. For example, such a program can be METLAB or user-written software.
For this purpose, the program can send recognition results to external programs in two ways
(files in output and a socket server; enable the modes in Recognition results).
It is also possible to control certain MeterVision functions from external programs in two ways:
Via the text file
input/command.txtin the Program Directory.Over a socket (if “Send results over socket” is enabled in Settings) — using the same command syntax; each command on a separate line; the server replies with
OK/ERROR: ...(or with results for thegetcommand).
You can send several commands at once in the file or over the socket: each command on a separate line. Commands are executed from the first line to the last.
The following commands are available:
Close the MeterVision program
exit
Save a Screenshot
To the default folder (output/screenshots/ in Program Directory) with the default file name (creation date and time)
screenshot
To the default folder with a custom file name
screenshot my_name.png
To a specified folder with a custom file name
screenshot path/to/my/dir/my_name.png
Open a zone settings file
open path/to/my/dir/settings.mv
Fix the background (pointer methods only)
fix_background n
Where n is the target zone number
Remove the background fixation (pointer methods only)
unfix_background n
Where n is the target zone number
Fix the center (pointer methods only)
fix_center n
Where n is the target zone number
Remove the center fixation (pointer methods only)
unfix_center n
Where n is the target zone number
Forget the zone statistics (pointer methods only)
forget_stats n
Where n is the target zone number
Forget the background (pointer methods only)
forget_background n
Where n is the target zone number
Switch to another scale (pointer methods only)
scale n m
Where n is the target zone number and m is the index of the scale to switch to
Switch the result display mode (pointer methods only)
Result is the scale reading
result_mode n scale
Result is the pointer inclination angle (in degrees)
result_mode n angle
Where n is the target zone number
Example input/command.txt file¶
screenshot my_name.png
unfix_background 1
fix_center 1
scale 1 3
result_mode 1 angle
Sending commands and results over socket¶
When the socket mode is enabled (see Recognition results), an external program connects to the host/port from
input/socket_config.txt and sends text lines ending with a newline.
The command and reply separator is a newline. Several commands can be sent in one connection;
the server replies with one line per command (for get — a results line like
{1: '24.10', 2: 'AC'}, for other commands — OK or ERROR: ...).
getorresults— get the current recognition results (one reply per request; the command can be repeated as many times as needed on the same connection).Any command from the list above — perform the action; reply
OKorERROR: ....
Example command sequence:
get
fix_center 1
scale 1 2
Example of requesting results (examples/socket_results_example.py).
You can call get_results() multiple times on the same connection:
import socket
import time
class MeterVisionClient:
def __init__(self, host='localhost', port=65432):
self.host = host
self.port = port
self.sock = None
self._buffer = ''
def connect(self):
"""Connect to the MeterVision server."""
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.host, self.port))
self._buffer = ''
print(f"Connected to server {self.host}:{self.port}")
def get_results(self):
"""
Request current results. Can be called repeatedly on the same
connection. Returns a string like "{1: '24.10', 2: 'AC'}".
"""
if self.sock is None:
raise RuntimeError('Call connect() first')
self.sock.sendall(b'get\n')
while '\n' not in self._buffer:
chunk = self.sock.recv(4096)
if not chunk:
raise ConnectionError('Server closed the connection')
self._buffer += chunk.decode('utf-8')
line, self._buffer = self._buffer.split('\n', 1)
return line
def close(self):
"""Close the connection."""
if self.sock is not None:
self.sock.close()
self.sock = None
print('Connection closed')
if __name__ == "__main__":
client = MeterVisionClient()
try:
client.connect()
for i in range(5):
results = client.get_results()
print(f"[{i + 1}] Received:", results)
time.sleep(1)
except ConnectionRefusedError as e:
print(e)
except KeyboardInterrupt:
print('Connection interrupted')
finally:
client.close()
Example of sending commands (examples/socket_commands_example.py):
import socket
def send_commands(commands, host='localhost', port=65432):
"""
Sends a list of commands and prints server replies.
Args:
commands: list of command strings without a trailing \\n
host, port: MeterVision server address
"""
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client_socket.connect((host, port))
print(f"Connected to server {host}:{port}")
except ConnectionRefusedError as e:
print(e)
return
try:
payload = ''.join(cmd.strip() + '\n' for cmd in commands if cmd.strip())
client_socket.sendall(payload.encode('utf-8'))
buffer = ''
replies_expected = sum(1 for cmd in commands if cmd.strip())
replies_got = 0
while replies_got < replies_expected:
data = client_socket.recv(4096)
if not data:
break
buffer += data.decode('utf-8')
while '\n' in buffer:
line, buffer = buffer.split('\n', 1)
print("Reply:", line)
replies_got += 1
if replies_got >= replies_expected:
break
except KeyboardInterrupt:
print('Connection interrupted')
finally:
client_socket.close()
if __name__ == "__main__":
# Example: request results and run commands for a pointer zone
send_commands([
'get',
'fix_center 1',
'result_mode 1 scale',
])
Note
These examples are also available as examples/socket_results_example.py and
examples/socket_commands_example.py relative to the program installation directory.