-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add read until terminator support for ip instrument #971
Changes from 5 commits
2600632
0ea8dd7
e68840c
71cf4e1
24da263
87bbd6b
ac12675
a6219b7
5df574b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,10 @@ class IPInstrument(Instrument): | |
r""" | ||
Bare socket ethernet instrument implementation. | ||
|
||
Before using the IPInstrument you should strongly consider if you can | ||
use Visa over raw sockets connecting to an address in the form: | ||
`TCPIP[board]::host address::port::SOCKET` | ||
|
||
Args: | ||
name (str): What this instrument is called locally. | ||
|
||
|
@@ -25,6 +29,11 @@ class IPInstrument(Instrument): | |
|
||
terminator (str): Character(s) to terminate each send. Default '\n'. | ||
|
||
read_terminator: Character(s) to look for at the end of each read. | ||
Defaults to None in which case only one recv is done | ||
Otherwise keeps reading until it gets the termination | ||
char(s). | ||
|
||
persistent (bool): Whether to leave the socket open between calls. | ||
Default True. | ||
|
||
|
@@ -40,13 +49,16 @@ class IPInstrument(Instrument): | |
|
||
def __init__(self, name, address=None, port=None, timeout=5, | ||
terminator='\n', persistent=True, write_confirmation=True, | ||
read_terminator=None, | ||
**kwargs): | ||
super().__init__(name, **kwargs) | ||
|
||
self._address = address | ||
self._port = port | ||
self._timeout = timeout | ||
self._terminator = terminator | ||
self._read_terminator = read_terminator | ||
|
||
self._confirmation = write_confirmation | ||
|
||
self._ensure_connection = EnsureConnection(self) | ||
|
@@ -56,6 +68,22 @@ def __init__(self, name, address=None, port=None, timeout=5, | |
|
||
self.set_persistent(persistent) | ||
|
||
@property | ||
def write_terminator(self): | ||
return self._terminator | ||
|
||
@write_terminator.setter | ||
def write_terminator(self, value): | ||
self._terminator = value | ||
|
||
@property | ||
def read_terminator(self): | ||
return self._read_terminator | ||
|
||
@read_terminator.setter | ||
def read_terminator(self, value): | ||
self._read_terminator = value | ||
|
||
def set_address(self, address=None, port=None): | ||
""" | ||
Change the IP address and/or port of this instrument. | ||
|
@@ -142,10 +170,25 @@ def _send(self, cmd): | |
self._socket.sendall(data.encode()) | ||
|
||
def _recv(self): | ||
result = self._socket.recv(self._buffer_size) | ||
if result == b'': | ||
log.warning("Got empty response from Socket recv() " | ||
"Connection broken.") | ||
result = b'' | ||
while True: | ||
partresult = self._socket.recv(self._buffer_size) | ||
result += partresult | ||
if partresult == b'': | ||
log.warning("Got empty response from Socket recv() " | ||
"Connection broken.") | ||
if self.read_terminator == None: | ||
break | ||
rtl = len(self.read_terminator) | ||
rtloc = result.find(self.read_terminator) | ||
if rtloc >= 0: | ||
if rtloc + rtl < len(result): | ||
log.warning("Multiple (partial) results received. " | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can have a look at this to see how we can handle receiving multiple partial messages: https://gist.github.com/sohailc/1a5db7bb260f36b94b552e630ea844f6 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A little better: |
||
"All but the first result will be discarded. " | ||
"Discarding {}".format(result[rtloc+rtl:])) | ||
result = result[0:rtloc] | ||
break | ||
|
||
return result.decode() | ||
|
||
def close(self): | ||
|
@@ -183,7 +226,7 @@ def ask_raw(self, cmd): | |
def __del__(self): | ||
self.close() | ||
|
||
def snapshot_base(self, update=False): | ||
def snapshot_base(self, update=False, params_to_skip_update=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add this arg in the docstring with a description what "params_to_skip_update" means |
||
""" | ||
State of the instrument as a JSON-compatible dict. | ||
|
||
|
@@ -194,7 +237,8 @@ def snapshot_base(self, update=False): | |
Returns: | ||
dict: base snapshot | ||
""" | ||
snap = super().snapshot_base(update=update) | ||
snap = super().snapshot_base(update=update, | ||
params_to_skip_update=params_to_skip_update) | ||
|
||
snap['port'] = self._port | ||
snap['confirmation'] = self._confirmation | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the read_terminator should not default to terminator