AVT相机arm版本SDK

This commit is contained in:
zhangpeng
2025-04-30 09:26:04 +08:00
parent 837c870f18
commit 78a1c63a95
705 changed files with 148770 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
"""BSD 2-Clause License
Copyright (c) 2019, Allied Vision Technologies GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import unittest
from vimba import *
class CamAncillaryDataTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
try:
self.cam._open()
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to open Camera.') from e
try:
self.chunk_mode = self.cam.get_feature_by_name('ChunkModeActive')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'ChunkModeActive\' not available.')
def tearDown(self):
self.cam._close()
self.vimba._shutdown()
def test_ancillary_data_access(self):
# Expectation: Ancillary Data is None if ChunkMode is disable.
# If ChunkMode is enabled Ancillary Data shall not be None.
old_state = self.chunk_mode.get()
try:
# Disable ChunkMode, acquire frame: Ancillary Data must be None
self.chunk_mode.set(False)
self.assertIsNone(self.cam.get_frame().get_ancillary_data())
# Enable ChunkMode, acquire frame: Ancillary Data must not be None
self.chunk_mode.set(True)
self.assertIsNotNone(self.cam.get_frame().get_ancillary_data())
finally:
self.chunk_mode.set(old_state)
def test_ancillary_data_context_manager_reentrancy(self):
# Expectation: Ancillary Data Context Manager must be reentrant.
old_state = self.chunk_mode.get()
try:
self.chunk_mode.set(True)
frame = self.cam.get_frame()
anc_data = frame.get_ancillary_data()
with anc_data:
with anc_data:
with anc_data:
pass
finally:
self.chunk_mode.set(old_state)
def test_ancillary_data_api_context_sensitity(self):
# Expectation: Ancillary Data implements a Context Manager, outside of with-scope
# a runtime error should be raised on all feature related methods accessed outside of the
# context.
old_state = self.chunk_mode.get()
try:
self.chunk_mode.set(True)
frame = self.cam.get_frame()
anc_data = frame.get_ancillary_data()
# Check Access Outside Context
self.assertRaises(RuntimeError, anc_data.get_all_features)
self.assertRaises(RuntimeError, anc_data.get_features_by_type, IntFeature)
self.assertRaises(RuntimeError, anc_data.get_features_by_category, '/ChunkData')
self.assertRaises(RuntimeError, anc_data.get_feature_by_name, 'ChunkExposureTime')
with anc_data:
# Check Access after Context entry
self.assertNoRaise(anc_data.get_all_features)
self.assertNoRaise(anc_data.get_features_by_type, IntFeature)
self.assertNoRaise(anc_data.get_features_by_category, '/ChunkData')
self.assertNoRaise(anc_data.get_feature_by_name, 'ChunkExposureTime')
# Check Access after Context leaving
self.assertRaises(RuntimeError, anc_data.get_all_features)
self.assertRaises(RuntimeError, anc_data.get_features_by_type, IntFeature)
self.assertRaises(RuntimeError, anc_data.get_features_by_category, '/ChunkData')
self.assertRaises(RuntimeError, anc_data.get_feature_by_name, 'ChunkExposureTime')
finally:
self.chunk_mode.set(old_state)
def test_ancillary_data_removed_attrs(self):
# Expectation: Ancillary Data are lightweight features. Calling most Feature-Methods that
# call VimbaC Features would cause an internal error. Those error prone methods
# shall raise a RuntimeError on call.
old_state = self.chunk_mode.get()
try:
self.chunk_mode.set(True)
frame = self.cam.get_frame()
anc_data = frame.get_ancillary_data()
with anc_data:
for feat in anc_data.get_all_features():
self.assertRaises(RuntimeError, feat.get_access_mode)
self.assertRaises(RuntimeError, feat.is_readable)
self.assertRaises(RuntimeError, feat.is_writeable)
self.assertRaises(RuntimeError, feat.register_change_handler)
self.assertRaises(RuntimeError, feat.get_range)
self.assertRaises(RuntimeError, feat.get_increment)
self.assertRaises(RuntimeError, feat.set)
finally:
self.chunk_mode.set(old_state)

View File

@@ -0,0 +1,422 @@
"""BSD 2-Clause License
Copyright (c) 2019, Allied Vision Technologies GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import unittest
import threading
import os
from vimba import *
from vimba.frame import *
def dummy_frame_handler(cam: Camera, frame: Frame):
pass
class CamCameraTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
self.cam.set_access_mode(AccessMode.Full)
def tearDown(self):
self.cam.set_access_mode(AccessMode.Full)
self.vimba._shutdown()
def test_camera_context_manager_access_mode(self):
# Expectation: Entering Context must not throw in cases where the current access mode is
# within get_permitted_access_modes()
permitted_modes = self.cam.get_permitted_access_modes()
for mode in permitted_modes:
self.cam.set_access_mode(mode)
try:
with self.cam:
pass
except BaseException:
self.fail()
def test_camera_context_manager_feature_discovery(self):
# Expectation: Outside of context, all features must be cleared,
# inside of context all features must be detected.
with self.cam:
self.assertNotEqual(self.cam.get_all_features(), ())
def test_camera_access_mode(self):
# Expectation: set/get access mode
self.cam.set_access_mode(AccessMode.None_)
self.assertEqual(self.cam.get_access_mode(), AccessMode.None_)
self.cam.set_access_mode(AccessMode.Full)
self.assertEqual(self.cam.get_access_mode(), AccessMode.Full)
self.cam.set_access_mode(AccessMode.Read)
self.assertEqual(self.cam.get_access_mode(), AccessMode.Read)
def test_camera_get_id(self):
# Expectation: get decoded camera id
self.assertTrue(self.cam.get_id())
def test_camera_get_name(self):
# Expectation: get decoded camera name
self.assertTrue(self.cam.get_name())
def test_camera_get_model(self):
# Expectation: get decoded camera model
self.assertTrue(self.cam.get_model())
def test_camera_get_serial(self):
# Expectation: get decoded camera serial
self.assertTrue(self.cam.get_serial())
def test_camera_get_permitted_access_modes(self):
# Expectation: get currently permitted access modes
expected = (AccessMode.None_, AccessMode.Full, AccessMode.Read, AccessMode.Config)
for mode in self.cam.get_permitted_access_modes():
self.assertIn(mode, expected)
def test_camera_get_interface_id(self):
# Expectation: get interface Id this camera is connected to
self.assertTrue(self.cam.get_interface_id())
def test_camera_get_features_affected(self):
# Expectation: Features that affect other features shall return a set of affected feature
# Features that don't affect other features shall return (). If a Feature is supplied that
# is not associated with that camera, a TypeError must be raised.
with self.cam:
try:
affect = self.cam.get_feature_by_name('Height')
except VimbaFeatureError as e:
raise unittest.SkipTest('Failed to lookup Feature Height') from e
try:
not_affect = self.cam.get_feature_by_name('AcquisitionFrameCount')
except VimbaFeatureError as e:
raise unittest.SkipTest('Failed to lookup Feature AcquisitionFrameCount') from e
self.assertEqual(self.cam.get_features_affected_by(not_affect), ())
try:
payload_size = self.cam.get_feature_by_name('PayloadSize')
except VimbaFeatureError as e:
raise unittest.SkipTest('Failed to lookup Feature PayloadSize') from e
self.assertIn(payload_size, self.cam.get_features_affected_by(affect))
def test_camera_frame_generator_limit_set(self):
# Expectation: The Frame generator fetches the given number of images.
with self.cam:
self.assertEqual(len([i for i in self.cam.get_frame_generator(0)]), 0)
self.assertEqual(len([i for i in self.cam.get_frame_generator(1)]), 1)
self.assertEqual(len([i for i in self.cam.get_frame_generator(7)]), 7)
self.assertEqual(len([i for i in self.cam.get_frame_generator(11)]), 11)
def test_camera_frame_generator_error(self):
# Expectation: The Frame generator raises a ValueError on a
# negative limit and the camera raises an ValueError
# if the camera is not opened.
# generator execution must throw if streaming is enabled
with self.cam:
# Check limits
self.assertRaises(ValueError, self.cam.get_frame_generator, -1)
self.assertRaises(ValueError, self.cam.get_frame_generator, 1, 0)
self.assertRaises(ValueError, self.cam.get_frame_generator, 1, -1)
self.cam.start_streaming(dummy_frame_handler, 5)
self.assertRaises(VimbaCameraError, self.cam.get_frame)
self.assertRaises(VimbaCameraError, next, self.cam.get_frame_generator(1))
# Stop Streaming: Everything should be fine.
self.cam.stop_streaming()
self.assertNoRaise(self.cam.get_frame)
self.assertNoRaise(next, self.cam.get_frame_generator(1))
def test_camera_get_frame(self):
# Expectation: Gets single Frame without any exception. Image data must be set.
# If a zero or negative timeouts must lead to a ValueError.
with self.cam:
self.assertRaises(ValueError, self.cam.get_frame, 0)
self.assertRaises(ValueError, self.cam.get_frame, -1)
self.assertNoRaise(self.cam.get_frame)
self.assertEqual(type(self.cam.get_frame()), Frame)
def test_camera_capture_error_outside_vimba_scope(self):
# Expectation: Camera access outside of Vimba scope must lead to a RuntimeError
gener = None
with self.cam:
gener = self.cam.get_frame_generator(1)
# Shutdown API
self.vimba._shutdown()
# Access invalid Iterator
self.assertRaises(RuntimeError, next, gener)
def test_camera_capture_error_outside_camera_scope(self):
# Expectation: Camera access outside of Camera scope must lead to a RuntimeError
gener = None
with self.cam:
gener = self.cam.get_frame_generator(1)
self.assertRaises(RuntimeError, next, gener)
def test_camera_capture_timeout(self):
# Expectation: Camera access outside of Camera scope must lead to a VimbaTimeout
with self.cam:
self.assertRaises(VimbaTimeout, self.cam.get_frame, 1)
def test_camera_is_streaming(self):
# Expectation: After start_streaming() is_streaming() must return true. After stop it must
# return false. If the camera context is left without stop_streaming(), leaving
# the context must stop streaming.
# Normal Operation
self.assertEqual(self.cam.is_streaming(), False)
with self.cam:
self.cam.start_streaming(dummy_frame_handler)
self.assertEqual(self.cam.is_streaming(), True)
self.cam.stop_streaming()
self.assertEqual(self.cam.is_streaming(), False)
# Missing the stream stop. Close must stop streaming
with self.cam:
self.cam.start_streaming(dummy_frame_handler, 5)
self.assertEqual(self.cam.is_streaming(), True)
self.assertEqual(self.cam.is_streaming(), False)
def test_camera_streaming_error_frame_count(self):
# Expectation: A negative or zero frame_count must lead to an value error
with self.cam:
self.assertRaises(ValueError, self.cam.start_streaming, dummy_frame_handler, 0)
self.assertRaises(ValueError, self.cam.start_streaming, dummy_frame_handler, -1)
def test_camera_streaming(self):
# Expectation: A given frame_handler must be executed for each buffered frame.
class FrameHandler:
def __init__(self, frame_count):
self.cnt = 0
self.frame_count = frame_count
self.event = threading.Event()
def __call__(self, cam: Camera, frame: Frame):
self.cnt += 1
if self.cnt == self.frame_count:
self.event.set()
timeout = 5.0
frame_count = 10
handler = FrameHandler(frame_count)
with self.cam:
try:
self.cam.start_streaming(handler, frame_count)
# Wait until the FrameHandler has been executed for each queued frame
self.assertTrue(handler.event.wait(timeout))
finally:
self.cam.stop_streaming()
def test_camera_streaming_queue(self):
# Expectation: A given frame must be reused if it is enqueued again.
class FrameHandler:
def __init__(self, frame_count):
self.cnt = 0
self.frame_count = frame_count
self.event = threading.Event()
def __call__(self, cam: Camera, frame: Frame):
self.cnt += 1
if self.cnt == self.frame_count:
self.event.set()
cam.queue_frame(frame)
timeout = 5.0
frame_count = 5
frame_reuse = 2
handler = FrameHandler(frame_count * frame_reuse)
with self.cam:
try:
self.cam.start_streaming(handler, frame_count)
# Wait until the FrameHandler has been executed for each queued frame
self.assertTrue(handler.event.wait(timeout))
finally:
self.cam.stop_streaming()
def test_camera_runtime_type_check(self):
def valid_handler(cam, frame):
pass
def invalid_handler_1(cam):
pass
def invalid_handler_2(cam, frame, extra):
pass
self.assertRaises(TypeError, self.cam.set_access_mode, -1)
with self.cam:
# Expectation: raise TypeError on passing invalid parameters
self.assertRaises(TypeError, self.cam.get_frame, 'hi')
self.assertRaises(TypeError, self.cam.get_features_affected_by, 'No Feature')
self.assertRaises(TypeError, self.cam.get_features_selected_by, 'No Feature')
self.assertRaises(TypeError, self.cam.get_features_by_type, 0.0)
self.assertRaises(TypeError, self.cam.get_feature_by_name, 0)
self.assertRaises(TypeError, self.cam.get_frame_generator, '3')
self.assertRaises(TypeError, self.cam.get_frame_generator, 0, 'foo')
self.assertRaises(TypeError, self.cam.start_streaming, valid_handler, 'no int')
self.assertRaises(TypeError, self.cam.start_streaming, invalid_handler_1)
self.assertRaises(TypeError, self.cam.start_streaming, invalid_handler_2)
self.assertRaises(TypeError, self.cam.save_settings, 0, PersistType.All)
self.assertRaises(TypeError, self.cam.save_settings, 'foo.xml', 'false type')
def test_camera_save_load_settings(self):
# Expectation: After settings export a settings change must be reverted by loading a
# Previously saved configuration.
file_name = 'test_save_load_settings.xml'
with self.cam:
feat_height = self.cam.get_feature_by_name('Height')
old_val = feat_height.get()
self.cam.save_settings(file_name, PersistType.All)
min_, max_ = feat_height.get_range()
inc = feat_height.get_increment()
feat_height.set(max_ - min_ - inc)
self.cam.load_settings(file_name, PersistType.All)
os.remove(file_name)
self.assertEqual(old_val, feat_height.get())
def test_camera_save_settings_verify_path(self):
# Expectation: Valid files end with .xml and can be either a absolute path or relative
# path to the given File. Everything else is a ValueError.
valid_paths = (
'valid1.xml',
os.path.join('.', 'valid2.xml'),
os.path.join('Tests', 'valid3.xml'),
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'valid4.xml'),
)
with self.cam:
self.assertRaises(ValueError, self.cam.save_settings, 'inval.xm', PersistType.All)
for path in valid_paths:
self.assertNoRaise(self.cam.save_settings, path, PersistType.All)
os.remove(path)
def test_camera_load_settings_verify_path(self):
# Expectation: Valid files end with .xml and must exist before before any execution.
valid_paths = (
'valid1.xml',
os.path.join('.', 'valid2.xml'),
os.path.join('Tests', 'valid3.xml'),
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'valid4.xml'),
)
with self.cam:
self.assertRaises(ValueError, self.cam.load_settings, 'inval.xm', PersistType.All)
for path in valid_paths:
self.assertRaises(ValueError, self.cam.load_settings, path, PersistType.All)
for path in valid_paths:
self.cam.save_settings(path, PersistType.All)
self.assertNoRaise(self.cam.load_settings, path, PersistType.All)
os.remove(path)
def test_camera_context_manager_reentrancy(self):
# Expectation: Camera Context Manager must be reentrant. Multiple calls to _open
# must be prevented (would cause VimbaC - Error)
with self.cam:
with self.cam:
with self.cam:
pass
def test_camera_api_context_sensitity_outside_context(self):
# Expectation: Call set_access_mode withing with scope must raise a RuntimeError
with self.cam:
self.assertRaises(RuntimeError, self.cam.set_access_mode)
def test_camera_api_context_sensitity_inside_context(self):
# Expectation: Most Camera related functions are only valid then called within the given
# Context. If called from Outside a runtime error must be raised.
self.assertRaises(RuntimeError, self.cam.read_memory)
self.assertRaises(RuntimeError, self.cam.write_memory)
self.assertRaises(RuntimeError, self.cam.read_registers)
self.assertRaises(RuntimeError, self.cam.write_registers)
self.assertRaises(RuntimeError, self.cam.get_all_features)
self.assertRaises(RuntimeError, self.cam.get_features_affected_by)
self.assertRaises(RuntimeError, self.cam.get_features_selected_by)
self.assertRaises(RuntimeError, self.cam.get_features_by_type)
self.assertRaises(RuntimeError, self.cam.get_features_by_category)
self.assertRaises(RuntimeError, self.cam.get_feature_by_name)
self.assertRaises(RuntimeError, self.cam.get_frame_generator)
self.assertRaises(RuntimeError, self.cam.get_frame)
self.assertRaises(RuntimeError, self.cam.start_streaming)
self.assertRaises(RuntimeError, self.cam.stop_streaming)
self.assertRaises(RuntimeError, self.cam.queue_frame)
self.assertRaises(RuntimeError, self.cam.get_pixel_formats)
self.assertRaises(RuntimeError, self.cam.get_pixel_format)
self.assertRaises(RuntimeError, self.cam.set_pixel_format)
self.assertRaises(RuntimeError, self.cam.save_settings)
self.assertRaises(RuntimeError, self.cam.load_settings)

View File

@@ -0,0 +1,831 @@
"""BSD 2-Clause License
Copyright (c) 2019, Allied Vision Technologies GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import unittest
import threading
from vimba import *
from vimba.feature import *
class CamBaseFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
try:
self.cam._open()
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to open Camera.') from e
try:
self.height = self.cam.get_feature_by_name('Height')
except VimbaCameraError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'Height\' not available.')
def tearDown(self):
self.cam._close()
self.vimba._shutdown()
def test_get_name(self):
# Expectation: Return decoded FeatureName
self.assertEqual(self.height.get_name(), 'Height')
def test_get_flags(self):
# Expectation: Return decoded FeatureFlags
self.assertEqual(self.height.get_flags(), (FeatureFlags.Read, FeatureFlags.Write))
def test_get_category(self):
# Expectation: Return decoded category
self.assertNotEqual(self.height.get_category(), '')
def test_get_display_name(self):
# Expectation: Return decoded category
self.assertEqual(self.height.get_display_name(), 'Height')
def test_get_polling_time(self):
# Expectation: Return polling time. Only volatile features return
# anything other than zero.
self.assertEqual(self.height.get_polling_time(), 0)
def test_get_unit(self):
# Expectation: If Unit exists, return unit else return ''
self.assertEqual(self.height.get_unit(), '')
def test_get_representation(self):
# Expectation: Get numeric representation if existing else ''
self.assertEqual(self.height.get_representation(), '')
def test_get_visibility(self):
# Expectation: Get UI Visibility
self.assertEqual(self.height.get_visibility(), FeatureVisibility.Beginner)
def test_get_tooltip(self):
# Expectation: Shall not raise anything
self.assertNoRaise(self.height.get_tooltip)
def test_get_description(self):
# Expectation: Get decoded description
self.assertNotEqual(self.height.get_description(), '')
def test_get_sfnc_namespace(self):
# Expectation: Get decoded sfnc namespace
self.assertNotEqual(self.height.get_sfnc_namespace(), '')
def test_is_streamable(self):
# Expectation: Streamable features shall return True, others False
self.assertNoRaise(self.height.is_streamable)
def test_has_affected_features(self):
# Expectation:Features that affect features shall return True, others False
self.assertTrue(self.height.has_affected_features())
def test_has_selected_features(self):
# Expectation:Features that select features shall return True, others False
self.assertFalse(self.height.has_selected_features())
def test_get_access_mode(self):
# Expectation: Read/Write Features return (True, True), ReadOnly return (True, False)
self.assertEqual(self.height.get_access_mode(), (True, True))
def test_is_readable(self):
# Expectation: True if feature grant read access else False
self.assertTrue(self.height.is_readable())
def test_is_writeable(self):
# Expectation: True if feature grant write access else False
self.assertTrue(self.height.is_writeable())
def test_change_handler(self):
# Expectation: A given change handler is executed on value change.
# Adding the same handler multiple times shall not lead to multiple executions.
# The same goes for double unregister.
class Handler:
def __init__(self):
self.event = threading.Event()
self.call_cnt = 0
def __call__(self, feat):
self.call_cnt += 1
self.event.set()
handler = Handler()
self.height.register_change_handler(handler)
self.height.register_change_handler(handler)
tmp = self.height.get()
min_, _ = self.height.get_range()
inc = self.height.get_increment()
if min_ <= tmp - inc:
self.height.set(tmp - inc)
else:
self.height.set(tmp + inc)
handler.event.wait()
self.height.unregister_change_handler(handler)
self.height.unregister_change_handler(handler)
self.height.set(tmp)
self.assertEqual(handler.call_cnt, 1)
def test_stringify_features(self):
# Expectation: Each Feature must have a __str__ method. Depending on the Feature
# current Values are queried, this can fail. In those cases, all exceptions are
# fetched -> all features must be strinify able without raising any exception
for feat in self.vimba.get_all_features():
self.assertNoRaise(str, feat)
for feat in self.cam.get_all_features():
self.assertNoRaise(str, feat)
class CamBoolFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.feat = self.vimba.get_feature_by_name('UsbTLIsPresent')
except VimbaFeatureError:
self.vimba._shutdown()
self.skipTest('Required Feature \'UsbTLIsPresent\' not available.')
def tearDown(self):
self.vimba._shutdown()
def test_get_type(self):
# Expectation: BoolFeature must return BoolFeature on get_type
self.assertEqual(self.feat.get_type(), BoolFeature)
def test_get(self):
# Expectation: returns current boolean value.
self.assertNoRaise(self.feat.get)
def test_set(self):
# Expectation: Raises invalid Access on non-writeable features.
self.assertRaises(VimbaFeatureError, self.feat.set, True)
class CamCommandFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.feat = self.vimba.get_feature_by_name('ActionCommand')
except VimbaFeatureError:
self.vimba._shutdown()
self.skipTest('Required Feature \'ActionCommand\' not available.')
def tearDown(self):
self.vimba._shutdown()
def test_get_type(self):
# Expectation: CommandFeature must return CommandFeature on get_type
self.assertEqual(self.feat.get_type(), CommandFeature)
class CamEnumFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
try:
self.cam._open()
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to open Camera.') from e
try:
self.feat_r = self.cam.get_feature_by_name('DeviceScanType')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'DeviceScanType\' not available.')
try:
self.feat_rw = self.cam.get_feature_by_name('AcquisitionMode')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'AcquisitionMode\' not available.')
def tearDown(self):
self.cam._close()
self.vimba._shutdown()
def test_get_type(self):
# Expectation: EnumFeature must return EnumFeature on get_type
self.assertEqual(self.feat_r.get_type(), EnumFeature)
self.assertEqual(self.feat_rw.get_type(), EnumFeature)
def test_entry_as_bytes(self):
# Expectation: Get EnumEntry as encoded byte sequence
expected = b'MultiFrame'
entry = self.feat_rw.get_entry('MultiFrame')
self.assertEqual(bytes(entry), expected)
def test_entry_as_tuple(self):
# Expectation: Get EnumEntry as (str, int)
entry = self.feat_rw.get_entry('MultiFrame')
self.assertEqual(entry.as_tuple(), self.feat_rw.get_entry(int(entry)).as_tuple())
def test_get_all_entries(self):
# Expectation: Get all possible enum entries regardless of the availability
expected = (self.feat_r.get_entry('Areascan'),)
for e in expected:
self.assertIn(e, self.feat_r.get_all_entries())
expected = (
self.feat_rw.get_entry('SingleFrame'),
self.feat_rw.get_entry('MultiFrame'),
self.feat_rw.get_entry('Continuous')
)
for e in expected:
self.assertIn(e, self.feat_rw.get_all_entries())
def test_get_avail_entries(self):
# Expectation: All returned enum entries must be available
for e in self.feat_r.get_available_entries():
self.assertTrue(e.is_available())
for e in self.feat_rw.get_available_entries():
self.assertTrue(e.is_available())
def test_get_entry_int(self):
# Expectation: Lookup a given entry by using an int as key.
# Invalid keys must return VimbaFeatureError.
expected = self.feat_r.get_all_entries()[0]
self.assertEqual(self.feat_r.get_entry(int(expected)), expected)
expected = self.feat_rw.get_all_entries()[1]
self.assertEqual(self.feat_rw.get_entry(int(expected)), expected)
self.assertRaises(VimbaFeatureError, self.feat_r.get_entry, -1)
self.assertRaises(VimbaFeatureError, self.feat_rw.get_entry, -1)
def test_get_entry_str(self):
# Expectation: Lookup a given entry by using a str as key.
# Invalid keys must return VimbaFeatureError.
expected = self.feat_r.get_all_entries()[0]
self.assertEqual(self.feat_r.get_entry(str(expected)), expected)
expected = self.feat_rw.get_all_entries()[1]
self.assertEqual(self.feat_rw.get_entry(str(expected)), expected)
self.assertRaises(VimbaFeatureError, self.feat_r.get_entry, 'Should be invalid')
self.assertRaises(VimbaFeatureError, self.feat_rw.get_entry, 'Should be invalid')
def test_get(self):
# Expectation: Get must return the current value.
self.assertNoRaise(self.feat_r.get)
self.assertNoRaise(self.feat_rw.get)
def test_set_entry(self):
# Expectation: Set given enum entry if feature is writable.
# Raises:
# - VimbaFeatureError if enum entry is from other enum feature.
# - VimbaFeatureError if feature is read only
# Read Only Feature
entry = self.feat_r.get_all_entries()[0]
self.assertRaises(VimbaFeatureError, self.feat_r.set, entry)
# Read/Write Feature
old_entry = self.feat_rw.get()
try:
# Normal operation
self.assertNoRaise(self.feat_rw.set, self.feat_rw.get_entry(2))
self.assertEqual(self.feat_rw.get(), self.feat_rw.get_entry(2))
# Provoke FeatureError by setting the feature from the ReadOnly entry.
self.assertRaises(VimbaFeatureError, self.feat_rw.set, entry)
finally:
self.feat_rw.set(old_entry)
def test_set_str(self):
# Expectation: Set given enum entry string value if feature is writable.
# Raises:
# - VimbaFeatureError if given string is not associated with this feature.
# - VimbaFeatureError if feature is read only
# Read Only Feature
self.assertRaises(VimbaFeatureError, self.feat_r.set, str(self.feat_r.get_entry(0)))
# Read/Write Feature
old_entry = self.feat_rw.get()
try:
# Normal operation
self.assertNoRaise(self.feat_rw.set, str(self.feat_rw.get_entry(2)))
self.assertEqual(self.feat_rw.get(), self.feat_rw.get_entry(2))
# Provoke FeatureError by an invalid enum value
self.assertRaises(VimbaFeatureError, self.feat_rw.set, 'Hopefully invalid')
finally:
self.feat_rw.set(old_entry)
def test_set_int(self):
# Expectation: Set given enum entry int value if feature is writable.
# Raises:
# - VimbaFeatureError if given int is not associated with this feature.
# - VimbaFeatureError if feature is read only
# Read Only Feature
self.assertRaises(VimbaFeatureError, self.feat_r.set, int(self.feat_r.get_entry(0)))
# Read/Write Feature
old_entry = self.feat_rw.get()
try:
# Normal operation
self.assertNoRaise(self.feat_rw.set, int(self.feat_rw.get_entry(2)))
self.assertEqual(self.feat_rw.get(), self.feat_rw.get_entry(2))
# Provoke FeatureError by an invalid enum value
self.assertRaises(VimbaFeatureError, self.feat_rw.set, -23)
finally:
self.feat_rw.set(old_entry)
def test_set_in_callback(self):
# Expected behavior: A set operation within a change handler must
# Raise a VimbaFeatureError to prevent an endless handler execution.
class Handler:
def __init__(self):
self.raised = False
self.event = threading.Event()
def __call__(self, feat):
try:
feat.set(feat.get())
except VimbaFeatureError:
self.raised = True
self.event.set()
old_entry = self.feat_rw.get()
try:
handler = Handler()
self.feat_rw.register_change_handler(handler)
# Trigger change handler and wait for callback execution.
self.feat_rw.set(self.feat_rw.get())
handler.event.wait()
self.assertTrue(handler.raised)
finally:
self.feat_rw.unregister_change_handler(handler)
self.feat_rw.set(old_entry)
class CamFloatFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
try:
self.cam._open()
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to open Camera.') from e
try:
self.feat_r = self.vimba.get_feature_by_name('Elapsed')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'Elapsed\' not available.')
try:
self.feat_rw = self.cam.get_feature_by_name('ExposureTime')
except VimbaFeatureError:
# Some Cameras name ExposureTime as ExposureTimeAbs
try:
self.feat_rw = self.cam.get_feature_by_name('ExposureTimeAbs')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'ExposureTime\' not available.')
def tearDown(self):
self.cam._close()
self.vimba._shutdown()
def test_get_type(self):
# Expectation: FloatFeature returns FloatFeature on get_type.
self.assertEqual(self.feat_r.get_type(), FloatFeature)
self.assertEqual(self.feat_rw.get_type(), FloatFeature)
def test_get(self):
# Expectation: Get current value.
self.assertNoRaise(self.feat_r.get)
self.assertNoRaise(self.feat_rw.get)
def test_get_range(self):
# Expectation: Get value range. Raise VimbaFeatureError on non-read access.
self.assertNoRaise(self.feat_r.get_range)
self.assertNoRaise(self.feat_rw.get_range)
def test_get_increment(self):
# Expectation: Get value increment if existing. If this Feature has no
# increment, None is returned.
self.assertNoRaise(self.feat_r.get_increment)
self.assertNoRaise(self.feat_rw.get_increment)
def test_set(self):
# Expectation: Set value. Errors:
# VimbaFeatureError if access right are not writable
# VimbaFeatureError if value is out of bounds
# Read only feature
self.assertRaises(VimbaFeatureError, self.feat_r.set, 0.0)
# Read/Write Feature
old_value = self.feat_rw.get()
try:
delta = 0.1
# Range test
min_, max_ = self.feat_rw.get_range()
# Within bounds (no error)
self.assertNoRaise(self.feat_rw.set, min_)
self.assertAlmostEqual(self.feat_rw.get(), min_)
self.assertNoRaise(self.feat_rw.set, max_)
self.assertAlmostEqual(self.feat_rw.get(), max_)
# Out of bounds (must raise)
self.assertRaises(VimbaFeatureError, self.feat_rw.set, min_ - delta)
self.assertRaises(VimbaFeatureError, self.feat_rw.set, max_ + delta)
finally:
self.feat_rw.set(old_value)
def test_set_in_callback(self):
# Expectation: Calling set within change_handler must raise an VimbaFeatureError
class Handler:
def __init__(self):
self.raised = False
self.event = threading.Event()
def __call__(self, feat):
try:
feat.set(feat.get())
except VimbaFeatureError:
self.raised = True
self.event.set()
old_entry = self.feat_rw.get()
try:
handler = Handler()
self.feat_rw.register_change_handler(handler)
# Trigger change handler and wait for callback execution.
self.feat_rw.set(self.feat_rw.get())
handler.event.wait()
self.assertTrue(handler.raised)
finally:
self.feat_rw.unregister_change_handler(handler)
self.feat_rw.set(old_entry)
class CamIntFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
try:
self.cam._open()
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to open Camera.') from e
try:
self.feat_r = self.cam.get_feature_by_name('HeightMax')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'HeightMax\' not available.')
try:
self.feat_rw = self.cam.get_feature_by_name('Height')
except VimbaFeatureError:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Required Feature \'Height\' not available.')
def tearDown(self):
self.cam._close()
self.vimba._shutdown()
def test_get_type(self):
# Expectation: IntFeature must return IntFeature on get_type
self.assertEqual(self.feat_r.get_type(), IntFeature)
self.assertEqual(self.feat_rw.get_type(), IntFeature)
def test_get(self):
# Expectation: Get current value
self.assertNoRaise(self.feat_r.get)
self.assertNoRaise(self.feat_rw.get)
def test_get_range(self):
# Expectation: Get range of accepted values
self.assertNoRaise(self.feat_r.get_range)
self.assertNoRaise(self.feat_rw.get_range)
def test_get_increment(self):
# Expectation: Get step between valid values
self.assertNoRaise(self.feat_r.get_increment)
self.assertNoRaise(self.feat_rw.get_increment)
def test_set(self):
# Expectation: Set value or raise VimbaFeatureError under the following conditions.
# 1) Invalid Access Rights
# 2) Misaligned value.
# 3) Out-of-bounds Access
# Read only feature
self.assertRaises(VimbaFeatureError, self.feat_r.set, 0)
# Writable feature
old_value = self.feat_rw.get()
try:
inc = self.feat_rw.get_increment()
min_, max_ = self.feat_rw.get_range()
# Normal usage
self.assertNoRaise(self.feat_rw.set, min_)
self.assertEqual(self.feat_rw.get(), min_)
self.assertNoRaise(self.feat_rw.set, max_)
self.assertEqual(self.feat_rw.get(), max_)
# Out of bounds access.
self.assertRaises(VimbaFeatureError, self.feat_rw.set, min_ - inc)
self.assertRaises(VimbaFeatureError, self.feat_rw.set, max_ + inc)
finally:
self.feat_rw.set(old_value)
def test_set_in_callback(self):
# Expectation: Setting a value within a Callback must raise a VimbaFeatureError
class Handler:
def __init__(self):
self.raised = False
self.event = threading.Event()
def __call__(self, feat):
try:
feat.set(feat.get())
except VimbaFeatureError:
self.raised = True
self.event.set()
old_entry = self.feat_rw.get()
try:
handler = Handler()
self.feat_rw.register_change_handler(handler)
# Trigger change handler and wait for callback execution.
min_, _ = self.feat_rw.get_range()
inc = self.feat_rw.get_increment()
if min_ <= (old_entry - inc):
self.feat_rw.set(old_entry - inc)
else:
self.feat_rw.set(old_entry + inc)
handler.event.wait()
self.assertTrue(handler.raised)
finally:
self.feat_rw.unregister_change_handler(handler)
self.feat_rw.set(old_entry)
class CamStringFeatureTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
try:
self.cam._open()
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to open Camera.') from e
self.feat_r = None
feats = self.cam.get_features_by_type(StringFeature)
for feat in feats:
if feat.get_access_mode() == (True, False):
self.feat_r = feat
if self.feat_r is None:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Test requires read only StringFeature.')
self.feat_rw = None
feats = self.cam.get_features_by_type(StringFeature)
for feat in feats:
if feat.get_access_mode() == (True, True):
self.feat_rw = feat
if self.feat_rw is None:
self.cam._close()
self.vimba._shutdown()
self.skipTest('Test requires read/write StringFeature.')
def tearDown(self):
self.cam._close()
self.vimba._shutdown()
def test_get_type(self):
# Expectation: StringFeature must return StringFeature on get_type
self.assertEqual(self.feat_r.get_type(), StringFeature)
self.assertEqual(self.feat_rw.get_type(), StringFeature)
def test_get(self):
# Expectation: Get current value without raising an exception
self.assertNoRaise(self.feat_r.get)
self.assertNoRaise(self.feat_rw.get)
def test_get_max_length(self):
# Expectation: Get maximum string length
self.assertNoRaise(self.feat_r.get_max_length)
self.assertNoRaise(self.feat_rw.get_max_length)
def test_set(self):
# Expectation:
# 1) Setting a read only feature must raise a VimbaFeatureError
# 2) Setting a read/wrtie must raise VimbaFeatureError if the string is
# longer than max length
# 3) Setting a read/write feature must work if string is long enough
# Ensure Expectation 1
self.assertRaises(VimbaFeatureError, self.feat_r.set, self.feat_r.get())
self.assertNoRaise(self.feat_rw.set, self.feat_rw.get())
# Ensure Expectation 2
old_val = self.feat_rw.get()
try:
invalid = 'a' * self.feat_rw.get_max_length()
self.assertRaises(VimbaFeatureError, self.feat_rw.set, invalid)
finally:
self.feat_rw.set(old_val)
# Ensure Expectation 3
try:
valid = 'a' * (self.feat_rw.get_max_length() - 1)
self.assertNoRaise(self.feat_rw.set, valid)
self.assertEqual(valid, self.feat_rw.get())
finally:
self.feat_rw.set(old_val)
def test_set_in_callback(self):
# Expectation: Setting a value within a Callback must raise a VimbaFeatureError
class Handler:
def __init__(self):
self.raised = False
self.event = threading.Event()
def __call__(self, feat):
try:
feat.set(feat.get())
except VimbaFeatureError:
self.raised = True
self.event.set()
try:
handler = Handler()
self.feat_rw.register_change_handler(handler)
self.feat_rw.set(self.feat_rw.get())
handler.event.wait()
self.assertTrue(handler.raised)
finally:
self.feat_rw.unregister_change_handler(handler)

View File

@@ -0,0 +1,206 @@
"""BSD 2-Clause License
Copyright (c) 2019, Allied Vision Technologies GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import unittest
import copy
import ctypes
from vimba import *
from vimba.frame import *
class CamFrameTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
self.vimba._startup()
try:
self.cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
except VimbaCameraError as e:
self.vimba._shutdown()
raise Exception('Failed to lookup Camera.') from e
def tearDown(self):
self.vimba._shutdown()
def test_verify_buffer(self):
# Expectation: A Frame buffer shall have exactly the specified size on construction.
# Allocation is performed by VimbaPython
self.assertEqual(Frame(0, AllocationMode.AnnounceFrame).get_buffer_size(), 0)
self.assertEqual(Frame(1024, AllocationMode.AnnounceFrame).get_buffer_size(), 1024)
self.assertEqual(Frame(1024 * 1024, AllocationMode.AnnounceFrame).get_buffer_size(),
1024 * 1024)
def test_verify_no_copy_empty_buffer_access(self):
# Expectation: Accessing the internal buffer must not create a copy
# frame._buffer is only set on construction if buffer is allocated by VimbaPython
frame = Frame(10, AllocationMode.AnnounceFrame)
self.assertEqual(id(frame._buffer), id(frame.get_buffer()))
def test_verify_no_copy_filled_buffer_access(self):
# Expectation: Accessing the internal buffer must not create a copy
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
with self.cam:
frame = self.cam.get_frame(allocation_mode=allocation_mode)
self.assertEqual(id(frame._buffer), id(frame.get_buffer()))
def test_get_id(self):
# Expectation: get_id() must return None if Its locally constructed
# else it must return the frame id.
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
self.assertIsNone(Frame(0, allocation_mode).get_id())
with self.cam:
self.assertIsNotNone(
self.cam.get_frame(allocation_mode=allocation_mode).get_id())
def test_get_timestamp(self):
# Expectation: get_timestamp() must return None if Its locally constructed
# else it must return the timestamp.
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
self.assertIsNone(Frame(0, allocation_mode).get_timestamp())
with self.cam:
self.assertIsNotNone(
self.cam.get_frame(allocation_mode=allocation_mode).get_timestamp())
def test_get_offset(self):
# Expectation: get_offset_x() must return None if Its locally constructed
# else it must return the offset as int. Same goes for get_offset_y()
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
self.assertIsNone(Frame(0, allocation_mode).get_offset_x())
self.assertIsNone(Frame(0, allocation_mode).get_offset_y())
with self.cam:
frame = self.cam.get_frame(allocation_mode=allocation_mode)
self.assertIsNotNone(frame.get_offset_x())
self.assertIsNotNone(frame.get_offset_y())
def test_get_dimension(self):
# Expectation: get_width() must return None if Its locally constructed
# else it must return the offset as int. Same goes for get_height()
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
self.assertIsNone(Frame(0, allocation_mode).get_width())
self.assertIsNone(Frame(0, allocation_mode).get_height())
with self.cam:
frame = self.cam.get_frame(allocation_mode=allocation_mode)
self.assertIsNotNone(frame.get_width())
self.assertIsNotNone(frame.get_height())
def test_get_image_size(self):
# Expectation: get_image_size() must return 0 if locally constructed
# else it must return the image_size as int.
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
self.assertEquals(Frame(0, allocation_mode).get_image_size(), 0)
with self.cam:
self.assertNotEquals(
self.cam.get_frame(allocation_mode=allocation_mode).get_image_size(), 0)
def test_deepcopy(self):
# Expectation: a deepcopy must clone the frame buffer with its contents an
# update the internally store pointer in VmbFrame struct.
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
with self.cam:
frame = self.cam.get_frame(allocation_mode=allocation_mode)
frame_cpy = copy.deepcopy(frame)
# Ensure frames and their members are not the same object
self.assertNotEquals(id(frame), id(frame_cpy))
self.assertNotEquals(id(frame._buffer), id(frame_cpy._buffer))
self.assertNotEquals(id(frame._frame), id(frame_cpy._frame))
# Ensure that both buffers have the same size and contain the same data.
self.assertEquals(frame.get_buffer_size(), frame_cpy.get_buffer_size())
self.assertTrue(all(a == b for a, b in zip(frame.get_buffer(),
frame_cpy.get_buffer())))
# Ensure that internal Frame Pointer points to correct buffer.
self.assertEquals(frame._frame.buffer,
ctypes.cast(frame._buffer, ctypes.c_void_p).value)
self.assertEquals(frame_cpy._frame.buffer,
ctypes.cast(frame_cpy._buffer, ctypes.c_void_p).value)
self.assertEquals(frame._frame.bufferSize, frame_cpy._frame.bufferSize)
def test_get_pixel_format(self):
# Expectation: Frames have an image format set after acquisition
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
with self.cam:
self.assertNotEquals(
self.cam.get_frame(allocation_mode=allocation_mode).get_pixel_format(), 0)
def test_incompatible_formats_value_error(self):
# Expectation: Conversion into incompatible formats must lead to an value error
for allocation_mode in AllocationMode:
with self.subTest(f'allocation_mode={str(allocation_mode)}'):
with self.cam:
frame = self.cam.get_frame(allocation_mode=allocation_mode)
current_fmt = frame.get_pixel_format()
convertable_fmt = current_fmt.get_convertible_formats()
for fmt in PixelFormat.__members__.values():
if (fmt != current_fmt) and (fmt not in convertable_fmt):
self.assertRaises(ValueError, frame.convert_pixel_format, fmt)
def test_convert_to_all_given_formats(self):
# Expectation: A Series of Frame, each acquired with a different Pixel format
# Must be convertible to all formats the given format claims its convertible to without any
# errors.
test_frames = []
with self.cam:
for fmt in self.cam.get_pixel_formats():
self.cam.set_pixel_format(fmt)
frame = self.cam.get_frame()
self.assertEqual(fmt, frame.get_pixel_format())
test_frames.append(frame)
for frame in test_frames:
# The test shall work on a copy to keep the original Frame untouched
for expected_fmt in frame.get_pixel_format().get_convertible_formats():
cpy_frame = copy.deepcopy(frame)
cpy_frame.convert_pixel_format(expected_fmt)
self.assertEquals(expected_fmt, cpy_frame.get_pixel_format())

View File

@@ -0,0 +1,149 @@
"""BSD 2-Clause License
Copyright (c) 2019, Allied Vision Technologies GmbH
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import unittest
import ipaddress
import struct
from vimba import *
class CamVimbaTest(unittest.TestCase):
def setUp(self):
self.vimba = Vimba.get_instance()
def tearDown(self):
pass
def test_context_entry_exit(self):
# Expected Behavior:
# On entering the context features, cameras and interfaces shall
# be detected and after leaving the context, everything should be reverted.
self.assertRaises(RuntimeError, self.vimba.get_all_features)
self.assertRaises(RuntimeError, self.vimba.get_all_interfaces)
self.assertRaises(RuntimeError, self.vimba.get_all_cameras)
with self.vimba:
self.assertNotEqual(self.vimba.get_all_features(), ())
self.assertNotEqual(self.vimba.get_all_interfaces(), ())
self.assertNotEqual(self.vimba.get_all_cameras(), ())
self.assertRaises(RuntimeError, self.vimba.get_all_features)
self.assertRaises(RuntimeError, self.vimba.get_all_interfaces)
self.assertRaises(RuntimeError, self.vimba.get_all_cameras)
def test_get_all_interfaces(self):
# Expected Behavior: get_all_interfaces() must raise an RuntimeError in closed state and
# be non-empty then opened.
self.assertRaises(RuntimeError, self.vimba.get_all_interfaces)
with self.vimba:
self.assertTrue(self.vimba.get_all_interfaces())
def test_get_interface_by_id(self):
# Expected Behavior: All detected Interfaces must be lookup able by their Id.
# If outside of given scope, an error must be returned
with self.vimba:
ids = [inter.get_id() for inter in self.vimba.get_all_interfaces()]
for id_ in ids:
self.assertNoRaise(self.vimba.get_interface_by_id, id_)
for id_ in ids:
self.assertRaises(RuntimeError, self.vimba.get_interface_by_id, id_)
def test_get_all_cameras(self):
# Expected Behavior: get_all_cameras() must only return camera handles on a open camera.
self.assertRaises(RuntimeError, self.vimba.get_all_cameras)
with self.vimba:
self.assertTrue(self.vimba.get_all_cameras())
def test_get_camera_by_id(self):
# Expected Behavior: Lookup of test camera must not fail after system opening
camera_id = self.get_test_camera_id()
with self.vimba:
self.assertNoRaise(self.vimba.get_camera_by_id, camera_id)
def test_get_camera_by_ip(self):
# Expected Behavior: get_camera_by_id() must work with a valid ipv4 address.
# A with lookup of an invalid ipv4 address (no Camera attached)
# must raise a VimbaCameraError, a lookup with an ipv6 address must raise a
# VimbaCameraError in general (VimbaC doesn't support ipv6)
with self.vimba:
# Verify that the Test Camera is a GigE - Camera
cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
inter = self.vimba.get_interface_by_id(cam.get_interface_id())
if inter.get_type() != InterfaceType.Ethernet:
raise self.skipTest('Test requires GigE - Camera.')
# Lookup test cameras IP address.
with cam:
ip_as_number = cam.get_feature_by_name('GevCurrentIPAddress').get()
# Swap byte order, the raw value does not seem to follow network byte order.
ip_as_number = struct.pack('<L', ip_as_number)
# Verify that lookup with IPv4 Address returns the same Camera Object
ip_addr = str(ipaddress.IPv4Address(ip_as_number))
self.assertEqual(self.vimba.get_camera_by_id(ip_addr), cam)
# Verify that a lookup with an invalid IPv4 Address raises a VimbaCameraError
ip_addr = str(ipaddress.IPv4Address('127.0.0.1'))
self.assertRaises(VimbaCameraError, self.vimba.get_camera_by_id, ip_addr)
# Verify that a lookup with an IPv6 Address raises a VimbaCameraError
ip_addr = str(ipaddress.IPv6Address('FD00::DEAD:BEEF'))
self.assertRaises(VimbaCameraError, self.vimba.get_camera_by_id, ip_addr)
def test_get_camera_by_mac(self):
# Expected Behavior: get_feature_by_id must be usable with a given MAC Address.
with self.vimba:
# Verify that the Test Camera is a GigE - Camera
cam = self.vimba.get_camera_by_id(self.get_test_camera_id())
inter = self.vimba.get_interface_by_id(cam.get_interface_id())
if inter.get_type() != InterfaceType.Ethernet:
raise self.skipTest('Test requires GigE - Camera.')
# Lookup test cameras MAC Address.
with cam:
# Construct MAC Address from raw value.
mac_as_number = cam.get_feature_by_name('GevDeviceMACAddress').get()
mac_as_bytes = mac_as_number.to_bytes(6, byteorder='big')
mac_as_str = ''.join(format(s, '02x') for s in mac_as_bytes).upper()
# Verify that lookup with MAC Address returns the same Camera Object
self.assertEqual(self.vimba.get_camera_by_id(mac_as_str), cam)
# Verify that a lookup with an invalid MAC Address raises a VimbaCameraError
invalid_mac = 'ffffffff'
self.assertRaises(VimbaCameraError, self.vimba.get_camera_by_id, invalid_mac)