Skip to content
Merged
Changes from all commits
Commits
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
132 changes: 132 additions & 0 deletions deapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
from datetime import datetime
from time import sleep
import re
import win32event
import win32api
import threading
from typing import List, Union, Tuple

import numpy as np
Expand Down Expand Up @@ -2473,6 +2476,125 @@ def get_time(self):
return time.clock()
else:
return time.perf_counter()

def enable_get_event(self):
"""
Enable event retrieval from the server.

Creates a Windows semaphore to handle event notifications and enables
the getEventEnabled flag. This must be called before get_event() can be used.

Returns
-------
bool
True if event retrieval was successfully enabled, False otherwise.
"""
with self.eventMutex:
command = self._addSingleCommand(self.ENABLE_GET_EVENT, None, None)
response = self._sendCommand(command)

if response != False:
semaphoreName = self.__getParameters(response.acknowledge[0])[0]
if semaphoreName is not None:
self.sdkEventSemaphore = win32event.CreateSemaphore(None, 0, 999, semaphoreName)
else:
return False

self.getEventEnabled = True
return True
else:
return False

def get_event(self):
"""
Retrieve the next event from the server.

Waits for an event signal on the semaphore and retrieves the event specification
from the server. This method blocks until an event is signaled. If the client
is not connected or event retrieval was not enabled via `enable_get_event()`,
an empty list is returned instead of attempting to fetch an event.

Returns
-------
list
A list of 5 strings that represent the specification for 1 event with the following order:
[event_type, name, value, lower_limit, upper_limit].
* event_type can be "Property", "AllowedValues", or "Readonly".
- "Property" means the event was triggered by a change in a property's value or its limits.
- "AllowedValues" means the event was triggered by a change in the options of a property.
Please use get_property_specifications after an "AllowedValues" event to get the updated specifications
for the property that triggered the event.
- "Readonly" means the event was triggered by a property changing between read-only and read-write.
* name is the name of the property that triggered the event.
* value is the new value of the property that triggered the event.
It can also indicate if a property is now read-only ("1") or read-write ("0") for a "Readonly" event.
For "AllowedValues" events, value may be an empty string.
* lower_limit and upper_limit are the new limits of the property that triggered a "Property" event.
If they are empty strings, then the limits did not change.
If event retrieval is disabled or the client is disconnected, an empty list is returned.
"""
if self.sdkEventSemaphore is not None:
win32event.WaitForSingleObject(self.sdkEventSemaphore, win32event.INFINITE)
else:
return []

with self.eventMutex:
if not self.connected or not self.getEventEnabled:
return []

command = self._addSingleCommand(self.GET_EVENT, None, None)
response = self._sendCommand(command)

eventSpec = []
if response != False:
values = self.__getParameters(response.acknowledge[0])
if type(values) is list:
eventSpec.append(values[0])
eventSpec.append(values[1])
eventSpec.append(values[2])
eventSpec.append(values[3])
eventSpec.append(values[4])

return eventSpec

def disable_get_event(self):
"""
Disable event retrieval from the server.

Releases and closes the Windows semaphore used for event notification,
and disables the getEventEnabled flag. After calling this, get_event()
will no longer function.

Returns
-------
bool
True if event retrieval was successfully disabled, False otherwise.
"""
with self.eventMutex:
command = self._addSingleCommand(self.DISABLE_GET_EVENT, None, None)
response = self._sendCommand(command)

if response != False:
if self.sdkEventSemaphore is not None:
win32event.ReleaseSemaphore(self.sdkEventSemaphore, 1)
win32api.CloseHandle(self.sdkEventSemaphore)
self.sdkEventSemaphore = None
self.getEventEnabled = False
return True
else:
return False

def is_get_event_enabled(self):
"""
Check if event retrieval from the server is currently enabled.

Returns
-------
bool
True if event retrieval is enabled, False otherwise.
"""
with self.eventMutex:
return self.getEventEnabled

# private methods

Expand Down Expand Up @@ -2783,6 +2905,10 @@ def ParseChangedProperties(self, changedProperties, response):
GetImage = get_image
TakeDarkReference = take_dark_reference
GetTime = get_time
EnableGetEvent = enable_get_event
GetEvent = get_event
DisableGetEvent = disable_get_event
IsGetEventEnabled = is_get_event_enabled

# method setProperty was renamed to SetProperty. please use SetProperty
setProperty = SetProperty
Expand All @@ -2801,6 +2927,9 @@ def ParseChangedProperties(self, changedProperties, response):
host = 0
port = 0
read_only = False
sdkEventSemaphore = None
getEventEnabled = False
eventMutex = threading.Lock()

# command lists
LIST_CAMERAS = 0
Expand All @@ -2811,6 +2940,7 @@ def ParseChangedProperties(self, changedProperties, response):
GET_IMAGE_16U = 5
GET_IMAGE_32F = 10
STOP_ACQUISITION = 11
GET_EVENT = 12
GET_RESULT = 14
START_ACQUISITION = 15
SET_HW_ROI = 16
Expand All @@ -2833,6 +2963,8 @@ def ParseChangedProperties(self, changedProperties, response):
SET_ADAPTIVE_ROI = 33
SET_ADAPTIVE_ROI_AND_GET_CHANGED_PROPERTIES = 34
GET_PROPERTY_SPECIFICATIONS = 35
ENABLE_GET_EVENT = 36
DISABLE_GET_EVENT = 37
GET_REGISTER = 38
SET_REGISTER = 39
LIST_REGISTERS = 40
Expand Down
Loading