From 9854274e0201be824943baee80991192908d19aa Mon Sep 17 00:00:00 2001 From: Eric Tsai Date: Mon, 17 Dec 2018 02:36:10 -0800 Subject: [PATCH] More example script improvements --- examples/acc_threshold_detector.py | 52 ++----- examples/calibrate.py | 2 +- examples/log_acc.py | 99 +++++--------- examples/log_temp.py | 142 ++++++-------------- examples/macro_remove.py | 25 ++++ examples/macro_setup.py | 44 ++++++ examples/{multi_device.py => stream_acc.py} | 6 +- examples/stream_data.py | 54 -------- mbientlab/metawear/__init__.py | 53 ++++++++ 9 files changed, 209 insertions(+), 268 deletions(-) create mode 100644 examples/macro_remove.py create mode 100644 examples/macro_setup.py rename examples/{multi_device.py => stream_acc.py} (96%) delete mode 100644 examples/stream_data.py diff --git a/examples/acc_threshold_detector.py b/examples/acc_threshold_detector.py index 45b1ec0..caee9d8 100644 --- a/examples/acc_threshold_detector.py +++ b/examples/acc_threshold_detector.py @@ -1,17 +1,10 @@ -# usage: python acc_threshold_detector [mac] +# usage: python acc_threshold_detector.py [mac] from __future__ import print_function -from mbientlab.metawear import MetaWear, libmetawear, parse_value +from mbientlab.metawear import MetaWear, libmetawear, parse_value, create_voidp_int, create_voidp from mbientlab.metawear.cbindings import * from time import sleep from threading import Event - -# CURRENT: -# Sample accelerometer at 50Hz -# Use the rms to combine X,Y,Z -# Use the average to downsample to about 4Hz (averaging 8 samples) -# Use the threshold detector to detect a bump -# Also log all the event and download it later - + print("Searching for device...") d = MetaWear(sys.argv[1]) d.connect() @@ -21,35 +14,6 @@ sleep(1.0) e = Event() -def create_voidp(create, resource): - result = [None] - def handler(ctx, pointer): - result[0] = RuntimeError("Could not create " + resource) if pointer == None else pointer - e.set() - - callback_wrapper = FnVoid_VoidP_VoidP(handler) - create(callback_wrapper) - e.wait() - - e.clear() - if (result[0] is RuntimeError): - raise result[0] - return result[0] - -def end_event_record(evt): - result = [None] - def handler(ctx, pointer, status): - if (status != Const.STATUS_OK): - result[0] = RuntimeError("Event recording returned a non-zero status (%d)" % (status)) - e.set() - - callback_wrapper = FnVoid_VoidP_VoidP_Int(handler) - libmetawear.mbl_mw_event_end_record(evt, None, callback_wrapper) - e.wait() - - e.clear() - if (result[0] is RuntimeError): - raise result[0] try: # setup accelerometer (odr 50Hz and 2Gs) @@ -61,24 +25,24 @@ def handler(ctx, pointer, status): acc_signal = libmetawear.mbl_mw_acc_get_acceleration_data_signal(d.board) # create RMS - root mean square of acc X,Y,Z - rms = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_rms_create(acc_signal, None, fn), "RMS") + rms = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_rms_create(acc_signal, None, fn), resource = "RMS", event = e) print("RMS created") # setup averager - averages over 8 RMS samples @ 50Hz - avg = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_average_create(rms, 8, None, fn), "averager") + avg = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_average_create(rms, 8, None, fn), resource = "averager", event = e) print("Averager created") # setup event on avg - reset averager libmetawear.mbl_mw_event_record_commands(avg) libmetawear.mbl_mw_dataprocessor_average_reset(avg) - end_event_record(avg) + create_voidp_int(lambda fn: libmetawear.mbl_mw_event_end_record(avg, None, fn), event = e) # setup threshold detector - detect anything above 1 - ths = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_threshold_create(avg, ThresholdMode.BINARY, 1.0, 0.0, None, fn), "threshold detector") + ths = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_threshold_create(avg, ThresholdMode.BINARY, 1.0, 0.0, None, fn), resource = "threshold detector", event = e) print("Threshold detector created") # setup logger - log the final signal of the averaged data - ths_logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(ths, None, fn), "threshold logger") + ths_logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(ths, None, fn), resource = "threshold logger", event = e) print("Threshold logger created") # start accelerometer and event logging diff --git a/examples/calibrate.py b/examples/calibrate.py index 443b1f3..af683d3 100644 --- a/examples/calibrate.py +++ b/examples/calibrate.py @@ -1,4 +1,4 @@ -# usage: python led.py [mac] +# usage: python calibrate.py [mac] from mbientlab.metawear import MetaWear, libmetawear, parse_value from mbientlab.metawear.cbindings import * from time import sleep diff --git a/examples/log_acc.py b/examples/log_acc.py index 0774d0a..4316376 100644 --- a/examples/log_acc.py +++ b/examples/log_acc.py @@ -1,87 +1,60 @@ -# usage: python log_acc [mac] +# usage: python log_acc.py [mac] from __future__ import print_function -from mbientlab.metawear import MetaWear, libmetawear, parse_value +from mbientlab.metawear import MetaWear, libmetawear, parse_value, create_voidp, create_voidp_int from mbientlab.metawear.cbindings import * from time import sleep from threading import Event -import platform import sys -if sys.version_info[0] == 2: - range = xrange - -class State: - def __init__(self, device): - self.device = device - - def setup_logger(self): - e = Event() - result = [None] - - def logger_handler(ctx, pointer): - result[0] = RuntimeError("Could not create logger") if pointer == None else pointer - e.set() - fn_wrapper = FnVoid_VoidP_VoidP(logger_handler) - - signal = libmetawear.mbl_mw_acc_get_acceleration_data_signal(self.device.board) - libmetawear.mbl_mw_datasignal_log(signal, None, fn_wrapper) - e.wait() - - if (result[0] is RuntimeError): - raise result[0] - - self.logger = result[0] - - libmetawear.mbl_mw_acc_enable_acceleration_sampling(self.device.board) - libmetawear.mbl_mw_acc_start(self.device.board) - libmetawear.mbl_mw_logging_start(self.device.board, 0); - - def download_data(self): - libmetawear.mbl_mw_acc_stop(self.device.board) - libmetawear.mbl_mw_acc_disable_acceleration_sampling(self.device.board) - libmetawear.mbl_mw_logging_stop(self.device.board) - - e = Event() - def progress_update_handler(context, entries_left, total_entries): - if (entries_left == 0): - e.set() - - fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler) - download_handler= LogDownloadHandler(context = None, \ - received_progress_update = fn_wrapper, \ - received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \ - received_unhandled_entry = cast(None, FnVoid_VoidP_DataP)) - - callback = FnVoid_VoidP_DataP(lambda ctx, p: print("%s -> %s" % (self.device.address, parse_value(p)))) - libmetawear.mbl_mw_logger_subscribe(self.logger, None, callback) - libmetawear.mbl_mw_logging_download(self.device.board, 0, byref(download_handler)) - e.wait() - print("Searching for device...") d = MetaWear(sys.argv[1]) d.connect() print("Connected to " + d.address) -s = State(d) print("Configuring device") -libmetawear.mbl_mw_settings_set_connection_parameters(s.device.board, 7.5, 7.5, 0, 6000) -sleep(1.0) try: - s.setup_logger() + signal = libmetawear.mbl_mw_acc_get_acceleration_data_signal(d.board) + logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(signal, None, fn), resource = "acc_logger") + + libmetawear.mbl_mw_logging_start(d.board, 0) + libmetawear.mbl_mw_acc_enable_acceleration_sampling(d.board) + libmetawear.mbl_mw_acc_start(d.board) print("Logging data for 15s") sleep(15.0) - s.download_data() - -except RuntimeError as e: - print(e) + libmetawear.mbl_mw_acc_stop(d.board) + libmetawear.mbl_mw_acc_disable_acceleration_sampling(d.board) + libmetawear.mbl_mw_logging_stop(d.board) + print("Downloading data") + libmetawear.mbl_mw_settings_set_connection_parameters(d.board, 7.5, 7.5, 0, 6000) + sleep(1.0) + + e = Event() + def progress_update_handler(context, entries_left, total_entries): + if (entries_left == 0): + e.set() + + fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler) + download_handler = LogDownloadHandler(context = None, \ + received_progress_update = fn_wrapper, \ + received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \ + received_unhandled_entry = cast(None, FnVoid_VoidP_DataP)) + + callback = FnVoid_VoidP_DataP(lambda ctx, p: print("{epoch: %d, value: %s}" % (p.contents.epoch, parse_value(p)))) + libmetawear.mbl_mw_logger_subscribe(logger, None, callback) + libmetawear.mbl_mw_logging_download(d.board, 0, byref(download_handler)) + e.wait() + +except RuntimeError as err: + print(err) finally: print("Resetting device") + e = Event() - s.device.on_disconnect = lambda status: e.set() - libmetawear.mbl_mw_debug_reset(s.device.board) + d.on_disconnect = lambda status: e.set() + libmetawear.mbl_mw_debug_reset(d.board) e.wait() diff --git a/examples/log_temp.py b/examples/log_temp.py index dc10c5f..d118e3c 100644 --- a/examples/log_temp.py +++ b/examples/log_temp.py @@ -1,124 +1,62 @@ -# usage: python log_temp [mac] +# usage: python log_temp.py [mac] from __future__ import print_function -from mbientlab.metawear import MetaWear, libmetawear, parse_value +from mbientlab.metawear import MetaWear, libmetawear, parse_value, create_voidp, create_voidp_int from mbientlab.metawear.cbindings import * from time import sleep from threading import Event -import platform import sys -if sys.version_info[0] == 2: - range = xrange - -class State: - def __init__(self, device): - self.device = device - - def setup_logger(self): - e = Event() - result = [None] - - def logger_handler(ctx, pointer): - result[0] = RuntimeError("Could not create logger") if pointer == None else pointer - e.set() - fn_wrapper = FnVoid_VoidP_VoidP(logger_handler) - - #streaming and logging - signal = libmetawear.mbl_mw_multi_chnl_temp_get_temperature_data_signal(self.device.board, \ - MetaWearRProChannel.ON_BOARD_THERMISTOR) - libmetawear.mbl_mw_datasignal_log(signal, None, fn_wrapper) - e.wait() - - if (result[0] is RuntimeError): - raise result[0] - - self.logger = result[0] - self.timer = self._setup_timer() - self._setup_read_event(self.timer, signal) - - libmetawear.mbl_mw_logging_start(self.device.board, 0); - libmetawear.mbl_mw_timer_start(self.timer) - - def _setup_timer(self): - e = Event() - result = [None] - - def timer_handler(ctx, pointer): - result[0] = RuntimeError("Could not create timer") if pointer == None else pointer - e.set() - fn_wrapper = FnVoid_VoidP_VoidP(timer_handler) - - libmetawear.mbl_mw_timer_create_indefinite(self.device.board, 1000, 0, None, fn_wrapper) - e.wait() - - if (result[0] is RuntimeError): - raise result[0] - - return result[0] - - def _setup_read_event(self, timer, signal): - e = Event() - result = [None] - - def commands_recorded(ctx, event, status): - result[0] = RuntimeError("Could not create read event") if status != Const.STATUS_OK else None - e.set() - fn_wrapper = FnVoid_VoidP_VoidP_Int(commands_recorded) - - libmetawear.mbl_mw_event_record_commands(timer) - libmetawear.mbl_mw_datasignal_read(signal) - libmetawear.mbl_mw_event_end_record(timer, None, fn_wrapper) - e.wait() - - if (result[0] is RuntimeError): - raise result[0] - - def download_data(self): - libmetawear.mbl_mw_timer_remove(self.timer) - libmetawear.mbl_mw_logging_stop(self.device.board) - - e = Event() - def progress_update_handler(context, entries_left, total_entries): - if (entries_left == 0): - e.set() - - fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler) - download_handler= LogDownloadHandler(context = None, \ - received_progress_update = fn_wrapper, \ - received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \ - received_unhandled_entry = cast(None, FnVoid_VoidP_DataP)) - - callback = FnVoid_VoidP_DataP(lambda ctx, p: print("%f" % (parse_value(p)))) - libmetawear.mbl_mw_logger_subscribe(self.logger, None, callback) - libmetawear.mbl_mw_logging_download(self.device.board, 0, byref(download_handler)) - e.wait() - - - print("Searching for device...") d = MetaWear(sys.argv[1]) d.connect() print("Connected to " + d.address) -s = State(d) - -print("Configuring device") -libmetawear.mbl_mw_settings_set_connection_parameters(s.device.board, 7.5, 7.5, 0, 6000) -sleep(1.0) try: + e = Event() + + print("Configuring device") #logging - s.setup_logger() + signal = libmetawear.mbl_mw_multi_chnl_temp_get_temperature_data_signal(d.board, MetaWearRProChannel.ON_BOARD_THERMISTOR) + logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(signal, None, fn), resource = "temp_logger", event = e) + + timer = create_voidp(lambda fn: libmetawear.mbl_mw_timer_create_indefinite(d.board, 1000, 0, None, fn), resource = "timer", event = e) + libmetawear.mbl_mw_event_record_commands(timer) + libmetawear.mbl_mw_datasignal_read(signal) + create_voidp_int(lambda fn: libmetawear.mbl_mw_event_end_record(timer, None, fn), event = e) + + libmetawear.mbl_mw_logging_start(d.board, 0) + libmetawear.mbl_mw_timer_start(timer) print("Logging data for 15s") sleep(15.0) - s.download_data() -except RuntimeError as e: - print(e) + libmetawear.mbl_mw_timer_remove(timer) + libmetawear.mbl_mw_logging_stop(d.board) + + print("Downloading data") + libmetawear.mbl_mw_settings_set_connection_parameters(d.board, 7.5, 7.5, 0, 6000) + sleep(1.0) + + def progress_update_handler(context, entries_left, total_entries): + if (entries_left == 0): + e.set() + + fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler) + download_handler = LogDownloadHandler(context = None, \ + received_progress_update = fn_wrapper, \ + received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \ + received_unhandled_entry = cast(None, FnVoid_VoidP_DataP)) + + callback = FnVoid_VoidP_DataP(lambda ctx, p: print("{epoch: %d, value: %s}" % (p.contents.epoch, parse_value(p)))) + libmetawear.mbl_mw_logger_subscribe(logger, None, callback) + libmetawear.mbl_mw_logging_download(d.board, 0, byref(download_handler)) + e.wait() +except RuntimeError as err: + print(err) finally: print("Resetting device") e = Event() - s.device.on_disconnect = lambda status: e.set() - libmetawear.mbl_mw_debug_reset(s.device.board) + d.on_disconnect = lambda status: e.set() + libmetawear.mbl_mw_debug_reset(d.board) e.wait() diff --git a/examples/macro_remove.py b/examples/macro_remove.py new file mode 100644 index 0000000..0ae90dc --- /dev/null +++ b/examples/macro_remove.py @@ -0,0 +1,25 @@ +# usage: python macro_remove.py [mac] +from __future__ import print_function +from mbientlab.metawear import MetaWear, libmetawear, parse_value +from mbientlab.metawear.cbindings import * +from time import sleep +from threading import Event + +import platform +import sys + +event = Event() + +device = MetaWear(sys.argv[1]) +device.connect() + +print("Connected to " + device.address) +sleep(1.0) + +print("Removing all macros") +libmetawear.mbl_mw_macro_erase_all(device.board) +libmetawear.mbl_mw_debug_reset_after_gc(device.board) + +device.on_disconnect = lambda status: event.set() +libmetawear.mbl_mw_debug_disconnect(device.board) +event.wait() \ No newline at end of file diff --git a/examples/macro_setup.py b/examples/macro_setup.py new file mode 100644 index 0000000..058ad66 --- /dev/null +++ b/examples/macro_setup.py @@ -0,0 +1,44 @@ +# usage: python macro_setup.py [mac] +from __future__ import print_function +from mbientlab.metawear import MetaWear, libmetawear, parse_value, create_voidp_int, create_voidp +from mbientlab.metawear.cbindings import * +from threading import Event + +import platform +import sys + +device = MetaWear(sys.argv[1]) +device.connect() +print("Connected to " + device.address) + +e = Event() + +print("Configuring device") +accel_signal= libmetawear.mbl_mw_acc_get_acceleration_data_signal(device.board) + +libmetawear.mbl_mw_macro_record(device.board, 1) +rss = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_rss_create(accel_signal, None, fn), resource = "rss", event = e) +avg = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_average_create(rss, 4, None, fn), resource = "avg", event = e) +threshold = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_threshold_create(avg, ThresholdMode.BINARY, 0.5, 0.0, None, fn), resource = "threhsold", event = e) +ths_below = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_comparator_create(threshold, ComparatorOperation.EQ, -1.0, None, fn), resource = "ths_below", event = e) +ths_above = create_voidp(lambda fn: libmetawear.mbl_mw_dataprocessor_comparator_create(threshold, ComparatorOperation.EQ, 1.0, None, fn), resource = "ths_above", event = e) + +pattern= LedPattern(pulse_duration_ms=1000, high_time_ms=500, high_intensity=16, low_intensity=16, repeat_count=Const.LED_REPEAT_INDEFINITELY) +libmetawear.mbl_mw_event_record_commands(ths_below) +libmetawear.mbl_mw_led_write_pattern(device.board, byref(pattern), LedColor.BLUE) +libmetawear.mbl_mw_led_play(device.board) +create_voidp_int(lambda fn: libmetawear.mbl_mw_event_end_record(ths_below, None, fn), event = e) + +libmetawear.mbl_mw_event_record_commands(ths_above) +libmetawear.mbl_mw_led_stop_and_clear(device.board) +create_voidp_int(lambda fn: libmetawear.mbl_mw_event_end_record(ths_above, None, fn), event = e) + +libmetawear.mbl_mw_acc_enable_acceleration_sampling(device.board) +libmetawear.mbl_mw_acc_start(device.board) + +create_voidp_int(lambda fn: libmetawear.mbl_mw_macro_end_record(device.board, None, fn), event = e) + +print("Resetting device") +device.on_disconnect = lambda status: e.set() +libmetawear.mbl_mw_debug_reset(device.board) +e.wait() \ No newline at end of file diff --git a/examples/multi_device.py b/examples/stream_acc.py similarity index 96% rename from examples/multi_device.py rename to examples/stream_acc.py index 85b3ab5..7d23f50 100644 --- a/examples/multi_device.py +++ b/examples/stream_acc.py @@ -1,4 +1,4 @@ -# usage: python multi_device [mac1] [mac2] ... [mac(n)] +# usage: python stream_acc.py [mac1] [mac2] ... [mac(n)] from __future__ import print_function from mbientlab.metawear import MetaWear, libmetawear, parse_value from mbientlab.metawear.cbindings import * @@ -43,7 +43,7 @@ def data_handler(self, ctx, data): libmetawear.mbl_mw_acc_enable_acceleration_sampling(s.device.board) libmetawear.mbl_mw_acc_start(s.device.board) -sleep(3.0) +sleep(30.0) for s in states: libmetawear.mbl_mw_acc_stop(s.device.board) @@ -53,8 +53,6 @@ def data_handler(self, ctx, data): libmetawear.mbl_mw_datasignal_unsubscribe(signal) libmetawear.mbl_mw_debug_disconnect(s.device.board) -sleep(30.0) - print("Total Samples Received") for s in states: print("%s -> %d" % (s.device.address, s.samples)) diff --git a/examples/stream_data.py b/examples/stream_data.py deleted file mode 100644 index 5552e52..0000000 --- a/examples/stream_data.py +++ /dev/null @@ -1,54 +0,0 @@ -# usage: python stream_data [mac] -from __future__ import print_function -from mbientlab.metawear import MetaWear, libmetawear, parse_value -from mbientlab.metawear.cbindings import * -from time import sleep -from threading import Event - -import platform -import sys - -if sys.version_info[0] == 2: - range = xrange - -class State: - def __init__(self, device): - self.device = device - self.samples = 0 - self.callback = FnVoid_VoidP_DataP(self.data_handler) - - def data_handler(self, ctx, data): - print("%s -> %s" % (self.device.address, parse_value(data))) - self.samples+= 1 - -d = MetaWear(sys.argv[1]) -d.connect() -print("Connected to " + d.address) -s = State(d) -sleep(1.0) - -print("Configuring device") -libmetawear.mbl_mw_settings_set_connection_parameters(s.device.board, 7.5, 7.5, 0, 6000) -libmetawear.mbl_mw_acc_set_odr(s.device.board, 25.0) -libmetawear.mbl_mw_acc_set_range(s.device.board, 16.0) -libmetawear.mbl_mw_acc_write_acceleration_config(s.device.board) - -signal = libmetawear.mbl_mw_acc_get_acceleration_data_signal(s.device.board) -libmetawear.mbl_mw_datasignal_subscribe(signal, None, s.callback) - -libmetawear.mbl_mw_acc_enable_acceleration_sampling(s.device.board) -libmetawear.mbl_mw_acc_start(s.device.board) - -sleep(10.0) - -libmetawear.mbl_mw_acc_stop(s.device.board) -libmetawear.mbl_mw_acc_disable_acceleration_sampling(s.device.board) - -signal = libmetawear.mbl_mw_acc_get_acceleration_data_signal(s.device.board) -libmetawear.mbl_mw_datasignal_unsubscribe(signal) -libmetawear.mbl_mw_debug_disconnect(s.device.board) - -sleep(1.0) - -print("Total Samples Received") -print("%s -> %d" % (s.device.address, s.samples)) diff --git a/mbientlab/metawear/__init__.py b/mbientlab/metawear/__init__.py index 36a67df..956ab50 100644 --- a/mbientlab/metawear/__init__.py +++ b/mbientlab/metawear/__init__.py @@ -56,3 +56,56 @@ def parse_value(pointer, **kwargs): raise RuntimeError("Missing optional parameter 'n_elem' for parsing DataTypeId.DATA_ARRAY value") else: raise RuntimeError('Unrecognized data type id: ' + str(pointer.contents.type_id)) + +from threading import Event + +def create_voidp(fn, **kwargs): + """ + Helper function that converts a libmetawear FnVoid_VoidP_VoidP async functions into a synchronous one + @params: + fn - Required : `(FnVoid_VoidP_VoidP) -> void` function that wraps the call to a libmetawear FnVoid_VoidP_VoidP async function + resource - Optional : Name of the resource the fn is attempting to create + event - Optional : Event object used to block until completion. If not provided, the function will instantiate its own Event object + """ + e = kwargs['event'] if 'event' in kwargs else Event() + + result = [None] + def handler(ctx, pointer): + result[0] = RuntimeError("Could not create " + (resource if 'resource' in kwarg else "resource") ) if pointer == None else pointer + e.set() + + callback_wrapper = FnVoid_VoidP_VoidP(handler) + fn(callback_wrapper) + e.wait() + + e.clear() + if (result[0] is RuntimeError): + raise result[0] + return result[0] + +def create_voidp_int(fn, **kwargs): + """ + Helper function that converts a libmetawear FnVoid_VoidP_VoidP_Int async function into a synchronous one + @params: + fn - Required : `(FnVoid_VoidP_VoidP_Int) -> void` function that wraps the call to a libmetawear FnVoid_VoidP_VoidP_Int async function + resource - Optional : Name of the resource the fn is attempting to create + event - Optional : Event object used to block until completion. If not provided, the function will instantiate its own Event object + is_error - Optional : `(int) -> bool` function used to check if the async function failed, checks if the int value is equal to Const.STATUS_OK if not specified + """ + e = kwargs['event'] if 'event' in kwargs else Event() + + result = [None] + def handler(ctx, pointer, status): + is_error = kwargs['is_error'] if 'is_error' in kwargs else lambda v: v != Const.STATUS_OK + if (is_error(status)): + result[0] = RuntimeError("Non-zero status returned (%d)" % (status)) + e.set() + + callback_wrapper = FnVoid_VoidP_VoidP_Int(handler) + fn(callback_wrapper) + e.wait() + + e.clear() + if (result[0] is RuntimeError): + raise result[0] +