Skip to content
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

Fix for backwards compatibility, new feature ROIs and RODs for AutoFocus and new timeout mechanic for all clients #34

Merged
merged 18 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
8429898
Fixed backwards compatibility and added new unittests for device client
Galoshi Mar 26, 2024
5005ac2
Added new feature for usage of ROIs and RODs for AutoFocus
Galoshi Mar 26, 2024
e92e4df
Fixed backwards compatibility
Galoshi Mar 26, 2024
f0131e4
Added new config flag importDeviceConfigUnittests for avoiding applic…
Galoshi Mar 26, 2024
498bfb4
Set config flag importDeviceConfigUnittests to default value True
Galoshi Mar 26, 2024
5968368
Incrementing setup.py version from 0.4 to 0.5
Galoshi Mar 26, 2024
da511aa
Moved module imports to top level for RPC client
Mar 27, 2024
c402920
Setting default ip in config file for unittests
Mar 27, 2024
a1a6a86
Changed input argument saturatedRatio for method startCalculateExposu…
Mar 27, 2024
18696db
Modified timeout mechanic for RPC so timeout is only set for its own …
Mar 27, 2024
f45574b
Removed method socket_exception_handler which is not needed anymore s…
Mar 27, 2024
3985d90
Replaced unsecure method eval() to json.loads()
Mar 27, 2024
4d73fe6
Fixed proxy issues for RPC timeout mechanic
Mar 27, 2024
f66a283
Replaced update methods for startCalculateExposureTime and startCalcu…
Mar 27, 2024
b07a070
Removed method rpc_exception_handler which is not needed anymore sinc…
Mar 27, 2024
3f24e51
Removed unnecessary comments in RPC client
Mar 28, 2024
a75903d
Fixed stack overflow error for overloaded __gettattr__ proxy method, …
Apr 4, 2024
8f1f108
Fixed versionioning of package so it equals the tagged package
Apr 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@

# Cache data unittests
/.pytest_cache
/.coverage

# proto folders/scripts
/examples_development
28 changes: 28 additions & 0 deletions examples/update_scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,31 @@ Go to the `examples/update_scripts` folder and run the script with following arg
Go to the `examples/update_scripts` folder and run the script with following arguments

$ python o2x5xx_multi_fw_updater.py -i O2x5xx_Firmware_1.30.10629.swu -H 192.168.0.69

### Build stand-alone application

Navigate to the project folder and build the application with following command:

```
python -m PyInstaller --onefile --windowed --name O2X5xxO3D3xxMultiFWUpdater o2x5xx_multi_fw_updater.py
```

You will find the stand-alone application LogTracesExtractor.exe in the dist folder.

Usage of O2X5xxO3D3xxMultiFWUpdater.exe stand-alone application:

usage: O2X5xxO3D3xxMultiFWUpdater.exe [-h] -i INPUT [INPUT ...] -H HOST [HOST ...]
[-b BACKUP] [-l LOG] [-r]

example: O2X5xxO3D3xxMultiFWUpdater.exe -i O2x5xx_Firmware_1.30.10629.swu -H 192.168.0.69

optional arguments:
-h, --help show this help message and exit
-i INPUT [INPUT ...], --input INPUT [INPUT ...]
specify input SWU file(s)
-H HOST [HOST ...], --host HOST [HOST ...]
specify host IPs
-b BACKUP, --backup BACKUP
path for config backup folder
-l LOG, --log LOG path for log file folder
-r, --remove remove config backup folder after application finished
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def read_requires():

setup(
name='o2x5xx',
version='0.4',
version='0.5',
description='A Python library for ifm O2x5xx (O2D5xx / O2I5xx) devices',
author='Michael Gann',
author_email='[email protected]',
Expand Down
32 changes: 18 additions & 14 deletions source/device/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
class O2x5xxDevice(O2x5xxPCICDevice):
def __init__(self, address="192.168.0.69", port=50010, autoconnect=True, timeout=SOCKET_TIMEOUT):
self._address = address
self._port = port
self._autoconnect = autoconnect
self._timeout = timeout
self._rpc = None
if autoconnect:
self._rpc = O2x5xxRPCDevice(address=self._address)
super(O2x5xxPCICDevice, self).__init__(address, port, autoconnect, timeout)
self._rpc = O2x5xxRPCDevice(address=address, timeout=timeout)
super(O2x5xxPCICDevice, self).__init__(address=address, port=port, autoconnect=autoconnect, timeout=timeout)

def __enter__(self):
return self
Expand All @@ -22,7 +20,9 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self._rpc = None

@property
def rpc(self):
def rpc(self) -> O2x5xxRPCDevice:
if not self._rpc:
self._rpc = O2x5xxRPCDevice(address=self._address, timeout=self._timeout)
return self._rpc


Expand All @@ -32,25 +32,29 @@ def __init__(self, address="192.168.0.69", port=50010, autoconnect=True, timeout
self._port = port
self._timeout = timeout
self._autoconnect = autoconnect
self._pcic = None
self._rpc = None
self._rpc = O2x5xxRPCDevice(address=address, timeout=timeout)
self._pcic = O2x5xxPCICDevice(address=address, port=port, autoconnect=autoconnect, timeout=timeout)

def __enter__(self):
self._pcic = O2x5xxPCICDevice(address=self._address, port=self._port, autoconnect=self._autoconnect,
timeout=self._timeout)
self._rpc = O2x5xxRPCDevice(address=self._address)
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self._pcic.close()
self._rpc.mainProxy.close()
self._pcic = None
if self._rpc:
self._rpc.mainProxy.close()
if self._pcic:
self._pcic.close()
self._rpc = None
self._pcic = None
Galoshi marked this conversation as resolved.
Show resolved Hide resolved

@property
def rpc(self) -> O2x5xxRPCDevice:
if not self._rpc:
self._rpc = O2x5xxRPCDevice(address=self._address, timeout=self._timeout)
return self._rpc

@property
def pcic(self) -> O2x5xxPCICDevice:
if not self._pcic:
self._pcic = O2x5xxPCICDevice(address=self._address, port=self._port,
autoconnect=self._autoconnect, timeout=self._timeout)
return self._pcic
79 changes: 30 additions & 49 deletions source/pcic/client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from ..static.formats import error_codes, serialization_format
from .utils import socket_exception_handler
import matplotlib.image as mpimg
import binascii
import socket
Expand All @@ -18,7 +17,7 @@ def __init__(self, address, port, autoconnect=True, timeout=SOCKET_TIMEOUT):
self.address = address
self.port = port
self.autoconnect = autoconnect
self.timeout = timeout
self._timeout = timeout
self.pcicSocket = None
self.connected = False
if self.autoconnect:
Expand All @@ -27,19 +26,42 @@ def __init__(self, address, port, autoconnect=True, timeout=SOCKET_TIMEOUT):
self.debug = False
self.debugFull = False

@socket_exception_handler(timeout=SOCKET_TIMEOUT)
def connect(self):
"""
Open the socket session with the device.

:return: None
"""
if not self.connected:
self.pcicSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.pcicSocket.settimeout(self.timeout)
self.pcicSocket.connect((self.address, self.port))
self.pcicSocket = socket.create_connection((self.address, self.port), timeout=self.timeout)
self.connected = True

@property
def timeout(self):
"""
Get the current timeout value on blocking socket operations. If no socket instance available
the preset timeout value will be returned.

:return: (float) socket timeout in seconds
"""
if self.pcicSocket:
return self.pcicSocket.gettimeout()
return self._timeout

@timeout.setter
def timeout(self, value):
"""
Set a timeout on blocking socket operations. If a non-zero value is given, subsequent socket operations will
raise a timeout exception if the timeout period value has elapsed before the operation has completed.
If zero is given, the socket is put in non-blocking mode. If None is given, the socket is put in blocking mode.

:param value: (float) non-negative socket timeout in seconds
:return: None
"""
self._timeout = value
if self.pcicSocket:
self.pcicSocket.settimeout(self._timeout)

def disconnect(self):
"""
Close the socket session with the device.
Expand Down Expand Up @@ -81,27 +103,6 @@ def recv(self, number_bytes):
fragments.append(chunk)
return b''.join(fragments)

@property
def pcic_socket_timeout(self) -> float:
"""
Getter for timeout value of lowlevel connection socket.

:return: (float) socket timeout in seconds
"""
return self.timeout

@pcic_socket_timeout.setter
def pcic_socket_timeout(self, value: float) -> None:
"""
Setter for timeout value of lowlevel connection socket.

:param value: (float) in seconds.
:return: None
"""
if self.pcicSocket:
self.pcicSocket.settimeout(value)
self.timeout = value


class PCICV3Client(Client):
DEFAULT_TICKET = "1000"
Expand Down Expand Up @@ -154,7 +155,7 @@ def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self.disconnect()
self.close()

def activate_application(self, application_number: [str, int]) -> str:
"""
Expand Down Expand Up @@ -241,6 +242,7 @@ def retrieve_current_process_interface_configuration(self):
"""
result = self.send_command('C?')
result = result.decode()

return result

def request_current_error_state(self):
Expand Down Expand Up @@ -494,27 +496,6 @@ def set_logic_state_of_an_id(self, io_id, state):
result = result.decode()
return result

# def set_logic_state_of_an_id2(self, io_id, state):
# """
# This is a reST style.
#
# :param io_id : (int)
# 2 digits for digital output
# * "01": IO1
# * "02": IO2
# :param state : (str)
# this is a second param
# * "01": IO1
# * "02": IO2
# :returns: this is a description of what is returned
# :raises keyError: raises an exception
# """
# if str(io_id).isnumeric():
# io_id = str(io_id).zfill(2)
# result = self.send_command('o{io_id}{state}'.format(io_id=io_id, state=str(state)))
# result = result.decode()
# return result

def request_state_of_an_id(self, io_id):
"""
Requests the state of a specific ID.
Expand Down
43 changes: 0 additions & 43 deletions source/pcic/utils.py

This file was deleted.

Loading