From bf9b9a1099fce4ee18a426689b659cb0f08a0158 Mon Sep 17 00:00:00 2001 From: John-Luke Navarro Date: Thu, 8 Dec 2022 20:07:59 +0000 Subject: [PATCH 01/39] initial commit --- nrm/client.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 nrm/client.py diff --git a/nrm/client.py b/nrm/client.py new file mode 100644 index 00000000..23e2a0df --- /dev/null +++ b/nrm/client.py @@ -0,0 +1,4 @@ +from ctypes.util import find_library +from ctypes import CDLL + +libnrm = CDLL(find_library("nrm")) \ No newline at end of file From cd18c4539a96d85f690410ee1d19586f1faf50f4 Mon Sep 17 00:00:00 2001 From: John-Luke Navarro Date: Fri, 9 Dec 2022 00:27:22 +0000 Subject: [PATCH 02/39] trying cffi approach - can successfully call nrm_client_create from py --- nrm/client.py | 9 ++++++--- nrm/setup_client_ext.py | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 nrm/setup_client_ext.py diff --git a/nrm/client.py b/nrm/client.py index 23e2a0df..859bc9df 100644 --- a/nrm/client.py +++ b/nrm/client.py @@ -1,4 +1,7 @@ -from ctypes.util import find_library -from ctypes import CDLL +from _nrm_cffi import ffi,lib -libnrm = CDLL(find_library("nrm")) \ No newline at end of file +client = ffi.new("nrm_client_t **") +uri = ffi.new("char[]", b"tcp://127.0.0.1") +err = lib.nrm_client_create(client, uri, 2345, 3456) + +print(err) \ No newline at end of file diff --git a/nrm/setup_client_ext.py b/nrm/setup_client_ext.py new file mode 100644 index 00000000..68b71e5a --- /dev/null +++ b/nrm/setup_client_ext.py @@ -0,0 +1,22 @@ +from cffi import FFI +ffi = FFI() + +ffi.set_source("_nrm_cffi", +""" + #include "nrm.h" +""", + libraries=["nrm"]) + +ffi.cdef(""" +typedef struct nrm_client_s nrm_client_t; + +int nrm_client_create(nrm_client_t **client, + const char *uri, + int pub_port, + int rpc_port); +""") + +if __name__ == "__main__": + ffi.compile(verbose=True) + + From 49be7f47854772230ee065c4e1291018c89f4fc1 Mon Sep 17 00:00:00 2001 From: jlnav Date: Tue, 13 Dec 2022 09:46:14 -0600 Subject: [PATCH 03/39] prototyping interface of NRMClient class --- nrm/client.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 4 deletions(-) diff --git a/nrm/client.py b/nrm/client.py index 859bc9df..b5b09c07 100644 --- a/nrm/client.py +++ b/nrm/client.py @@ -1,7 +1,104 @@ from _nrm_cffi import ffi,lib +from dataclasses import dataclass +from typing import Union, List, Callable -client = ffi.new("nrm_client_t **") -uri = ffi.new("char[]", b"tcp://127.0.0.1") -err = lib.nrm_client_create(client, uri, 2345, 3456) -print(err) \ No newline at end of file +@dataclass +class NRMClient: + """Client class for interacting with NRM C interface. Prototyped interface for client below. + + Tentative usage: + + ``` + with NRMClient() as nrmc: + + ... + nrmc.add_actuator(my_actuator) + ... + nrmc.send_event(get_time(), sensor, scope, 1234) + ... + + ``` + + """ + + uri:str = "tcp://127.0.0.1" + pub_port:int=2345 + rpc_port:int=3456 + actuators: List[NRMActuator] = [] + scopes: List[NRMScope] = [] + sensors: List[NRMSensor] = [] + slices: List[NRMSlice] = [] + + def __enter__(self): + self._c_client = ffi.new("nrm_client_t **") + self._c_uri = ffi.new("char[]", bytes(self.uri)) + lib.nrm_client_create(self._c_client, self._c_uri, self.pub_port, self.rpc_port) + + def __exit__(self): + pass + # lib.nrm_client_destroy + + def actuate(self, actuator:NRMActuator, float:value) -> int: + pass + # lib.nrm_client_actuate + + def add_actuator(self, actuator:NRMActuator) -> int: + pass + # lib.nrm_client_add_actuator + + def add_scope(self, scope:NRMScope) -> int: + pass + # lib.nrm_client_add_scope + + def add_sensor(self, sensor:NRMSensor) -> int: + pass + # lib.nrm_client_add_sensor + + def add_slice(self, slice:NRMSlice) -> int: + pass + # lib.nrm_client_add_slice + + def find(self, obj:Union[NRMScope, NRMSensor, NRMSlice], uuid:str) -> Union[NRMScope, NRMSensor, NRMSlice]: + pass + # lib.nrm_client_find + + def get_actuators(self) -> List[NRMActuator]: + pass + # lib.nrm_client_list_actuators + + def get_scopes(self) -> List[NRMScope]: + pass + # lib.nrm_client_list_scopes + + def get_sensors(self) -> List[NRMSensor]: + pass + # lib.nrm_client_list_sensors + + def get_slices(self) -> List[NRMSlice]: + pass + # lib.nrm_client_list_slices + + def remove_slice(self, type:int, uuid:str) -> int: + pass + # lib.nrm_client_remove + + def send_event(self, time:int, sensor:NRMSensor, scope:NRMScope, value:float) -> int: + pass + # lib.nrm_client_send_event + + def set_event_listener(self, event_listener:Callable) -> int: + pass + # lib.nrm_client_set_event_listener + + def start_event_listener(self, topic:str) -> int: + pass + # lib.nrm_client_start_event_listener + + def set_actuate_listener(self, actuate_listener:Callable) -> int: + pass + # lib.nrm_client_set_actuate_listener + + def start_actuate_listener(self) -> int: + pass + # lib.nrm_client_start_actuate_listener \ No newline at end of file From a8f91abf2e92caa227aff192ab930cb923f98b5a Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 16 Dec 2022 12:29:51 -0600 Subject: [PATCH 04/39] attempt to add rest of client functions and relevant typedefs to ffi.cdef setup, continue to prototype matching functions in client.py --- nrm/client.py | 116 ++++++++++++++++------------------------ nrm/setup_client_ext.py | 53 ++++++++++++++++++ 2 files changed, 100 insertions(+), 69 deletions(-) diff --git a/nrm/client.py b/nrm/client.py index b5b09c07..a8c343d5 100644 --- a/nrm/client.py +++ b/nrm/client.py @@ -1,99 +1,72 @@ from _nrm_cffi import ffi,lib -from dataclasses import dataclass from typing import Union, List, Callable - -@dataclass -class NRMClient: +class Client: """Client class for interacting with NRM C interface. Prototyped interface for client below. - Tentative usage: - ``` - with NRMClient() as nrmc: - + from nrm import Client, "Actuator" + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... - nrmc.add_actuator(my_actuator) + nrmc["my_actuator"] = actuator ... nrmc.send_event(get_time(), sensor, scope, 1234) ... ``` - """ - uri:str = "tcp://127.0.0.1" - pub_port:int=2345 - rpc_port:int=3456 - actuators: List[NRMActuator] = [] - scopes: List[NRMScope] = [] - sensors: List[NRMSensor] = [] - slices: List[NRMSlice] = [] - - def __enter__(self): - self._c_client = ffi.new("nrm_client_t **") - self._c_uri = ffi.new("char[]", bytes(self.uri)) + def __init__(self): + self._nrm_objects = {} + + def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int=3456): + self._c_client_p = ffi.new("nrm_client_t **") + self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) + self.pub_port = pub_port + self.rpc_port = rpc_port lib.nrm_client_create(self._c_client, self._c_uri, self.pub_port, self.rpc_port) + self._c_client = self._c_client_p[0] + # Based on following from cffi docs: + # p_handle = ffi.new("opaque_t **") + # lib.init_stuff(p_handle) # pass the pointer to the 'handle' pointer + # handle = p_handle[0] # now we can read 'handle' out of 'p_handle' + # lib.more_stuff(handle) def __exit__(self): - pass - # lib.nrm_client_destroy - - def actuate(self, actuator:NRMActuator, float:value) -> int: - pass - # lib.nrm_client_actuate - - def add_actuator(self, actuator:NRMActuator) -> int: - pass - # lib.nrm_client_add_actuator - - def add_scope(self, scope:NRMScope) -> int: - pass - # lib.nrm_client_add_scope - - def add_sensor(self, sensor:NRMSensor) -> int: - pass - # lib.nrm_client_add_sensor - - def add_slice(self, slice:NRMSlice) -> int: - pass - # lib.nrm_client_add_slice - - def find(self, obj:Union[NRMScope, NRMSensor, NRMSlice], uuid:str) -> Union[NRMScope, NRMSensor, NRMSlice]: - pass + lib.nrm_client_destroy(self._c_client_p) + + def __setitem__(self, uuid_key:str, nrm_object:Union["Scope", "Sensor", "Slice", "Actuator"]): + self._nrm_objects[key] = nrm_object + if isinstance(nrm_object, "Scope"): + return lib.nrm_client_add_scope(self._c_client, nrm_object._c_scope) + elif isinstance(nrm_object, "Sensor"): + return lib.nrm_client_add_sensor(self._c_client, nrm_object._c_sensor) + elif isinstance(nrm_object, "Slice"): + return lib.nrm_client_add_slice(self._c_client, nrm_object._c_slice) + elif isinstance(nrm_object, "Actuator"): + return lib.nrm_client_add_actuator(self._c_client, nrm_object._c_actuator) + + def __getitem__(self, key): # lib.nrm_client_find + return self._nrm_objects[key] - def get_actuators(self) -> List[NRMActuator]: + def __delitem__(self, key): pass - # lib.nrm_client_list_actuators - def get_scopes(self) -> List[NRMScope]: - pass - # lib.nrm_client_list_scopes - - def get_sensors(self) -> List[NRMSensor]: - pass - # lib.nrm_client_list_sensors + def actuate(self, actuator:"Actuator", value:float) -> int: + return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) - def get_slices(self) -> List[NRMSlice]: - pass - # lib.nrm_client_list_slices - - def remove_slice(self, type:int, uuid:str) -> int: - pass - # lib.nrm_client_remove - - def send_event(self, time:int, sensor:NRMSensor, scope:NRMScope, value:float) -> int: - pass - # lib.nrm_client_send_event + def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: + return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) def set_event_listener(self, event_listener:Callable) -> int: pass # lib.nrm_client_set_event_listener def start_event_listener(self, topic:str) -> int: - pass - # lib.nrm_client_start_event_listener + topic = ffi.new("char []", bytes(topic, "utf-8")) + topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) + return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) def set_actuate_listener(self, actuate_listener:Callable) -> int: pass @@ -101,4 +74,9 @@ def set_actuate_listener(self, actuate_listener:Callable) -> int: def start_actuate_listener(self) -> int: pass - # lib.nrm_client_start_actuate_listener \ No newline at end of file + return lib.nrm_client_start_actuate_listener(self._c_client) + + +if __name__ == "__main__": + with Client() as nrmc: + pass \ No newline at end of file diff --git a/nrm/setup_client_ext.py b/nrm/setup_client_ext.py index 68b71e5a..011e62c0 100644 --- a/nrm/setup_client_ext.py +++ b/nrm/setup_client_ext.py @@ -9,11 +9,64 @@ ffi.cdef(""" typedef struct nrm_client_s nrm_client_t; +typedef struct nrm_actuator_s nrm_actuator_t; +typedef struct nrm_slice_s nrm_slice_t; +typedef struct nrm_sensor_s nrm_sensor_t; +typedef struct nrm_scope nrm_scope_t; +typedef struct nrm_vector_s nrm_vector_t; +typedef char *nrm_string_t; +typedef struct timespec nrm_time_t; +typedef nrm_string_t nrm_uuid_t; + +typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, + nrm_time_t time, + nrm_scope_t *scope, + double value); +typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, double value); int nrm_client_create(nrm_client_t **client, const char *uri, int pub_port, int rpc_port); + +int nrm_client_actuate(const nrm_client_t *client, + nrm_actuator_t *actuator, + double value); + +int nrm_client_add_actuator(const nrm_client_t *client, + nrm_actuator_t *actuator); + +int nrm_client_add_scope(const nrm_client_t *client, nrm_scope_t *scope); + +int nrm_client_add_sensor(const nrm_client_t *client, nrm_sensor_t *sensor); + +int nrm_client_add_slice(const nrm_client_t *client, nrm_slice_t *slice); + +int nrm_client_find(const nrm_client_t *client, + int type, + const char *uuid, + nrm_vector_t **results); + +int nrm_client_remove(const nrm_client_t *client, int type, nrm_string_t uuid); + +int nrm_client_send_event(const nrm_client_t *client, + nrm_time_t time, + nrm_sensor_t *sensor, + nrm_scope_t *scope, + double value); + +int nrm_client_set_event_listener(nrm_client_t *client, + nrm_client_event_listener_fn fn); + +int nrm_client_start_event_listener(const nrm_client_t *client, + nrm_string_t topic); + +int nrm_client_set_actuate_listener(nrm_client_t *client, + nrm_client_actuate_listener_fn fn); +int nrm_client_start_actuate_listener(const nrm_client_t *client); + +void nrm_client_destroy(nrm_client_t **client); + """) if __name__ == "__main__": From b4af60dc73dfced68d58191d80f44c394e689ba5 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 16 Dec 2022 13:41:16 -0600 Subject: [PATCH 05/39] tentative reorganization --- nrm/api/__init__.py | 9 +++++++++ nrm/{setup_client_ext.py => api/build.py} | 2 +- nrm/{ => api}/client.py | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 nrm/api/__init__.py rename nrm/{setup_client_ext.py => api/build.py} (98%) rename nrm/{ => api}/client.py (98%) diff --git a/nrm/api/__init__.py b/nrm/api/__init__.py new file mode 100644 index 00000000..e5433105 --- /dev/null +++ b/nrm/api/__init__.py @@ -0,0 +1,9 @@ +############################################################################### +# Copyright 2019 UChicago Argonne, LLC. +# (c.f. AUTHORS, LICENSE) +# +# This file is part of the NRM project. +# For more info, see https://github.com/anlsys/nrm-python +# +# SPDX-License-Identifier: BSD-3-Clause +############################################################################### diff --git a/nrm/setup_client_ext.py b/nrm/api/build.py similarity index 98% rename from nrm/setup_client_ext.py rename to nrm/api/build.py index 011e62c0..556f4d35 100644 --- a/nrm/setup_client_ext.py +++ b/nrm/api/build.py @@ -1,7 +1,7 @@ from cffi import FFI ffi = FFI() -ffi.set_source("_nrm_cffi", +ffi.set_source("./build/_nrm_cffi", """ #include "nrm.h" """, diff --git a/nrm/client.py b/nrm/api/client.py similarity index 98% rename from nrm/client.py rename to nrm/api/client.py index a8c343d5..9fafeee2 100644 --- a/nrm/client.py +++ b/nrm/api/client.py @@ -5,7 +5,7 @@ class Client: """Client class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: ``` - from nrm import Client, "Actuator" + from nrm import Client, Actuator with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... nrmc["my_actuator"] = actuator From ce9c27cb9df1c9d0ddc289918106ff42ca6b263a Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 16 Dec 2022 16:45:50 -0600 Subject: [PATCH 06/39] tentatively creating separate files for the additional structures, adds other functions to build.py --- nrm/api/actuator.py | 5 +++ nrm/api/build.py | 14 ++++++- nrm/api/build/__init__.py | 9 +++++ nrm/api/client.py | 4 +- nrm/api/scope.py | 37 ++++++++++++++++++ nrm/api/sensor.py | 82 +++++++++++++++++++++++++++++++++++++++ nrm/api/slice.py | 8 ++++ 7 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 nrm/api/actuator.py create mode 100644 nrm/api/build/__init__.py create mode 100644 nrm/api/scope.py create mode 100644 nrm/api/sensor.py create mode 100644 nrm/api/slice.py diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py new file mode 100644 index 00000000..76862120 --- /dev/null +++ b/nrm/api/actuator.py @@ -0,0 +1,5 @@ +from build._nrm_cffi import ffi,lib +from typing import Union, List, Callable + +class Actuator: + """Actuator class for interacting with NRM C interface. Prototyped interface for client below.""" diff --git a/nrm/api/build.py b/nrm/api/build.py index 556f4d35..8ec7275a 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -1,7 +1,7 @@ from cffi import FFI ffi = FFI() -ffi.set_source("./build/_nrm_cffi", +ffi.set_source("build._nrm_cffi", """ #include "nrm.h" """, @@ -67,6 +67,18 @@ void nrm_client_destroy(nrm_client_t **client); +nrm_sensor_t *nrm_sensor_create(const char *name); + +void nrm_sensor_destroy(nrm_sensor_t **); + +nrm_slice_t *nrm_slice_create(const char *name); + +void nrm_slice_destroy(nrm_slice_t **); + +nrm_actuator_t *nrm_actuator_create(const char *name); + +void nrm_actuator_destroy(nrm_actuator_t **); + """) if __name__ == "__main__": diff --git a/nrm/api/build/__init__.py b/nrm/api/build/__init__.py new file mode 100644 index 00000000..e5433105 --- /dev/null +++ b/nrm/api/build/__init__.py @@ -0,0 +1,9 @@ +############################################################################### +# Copyright 2019 UChicago Argonne, LLC. +# (c.f. AUTHORS, LICENSE) +# +# This file is part of the NRM project. +# For more info, see https://github.com/anlsys/nrm-python +# +# SPDX-License-Identifier: BSD-3-Clause +############################################################################### diff --git a/nrm/api/client.py b/nrm/api/client.py index 9fafeee2..77c6ea19 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,4 +1,4 @@ -from _nrm_cffi import ffi,lib +from build._nrm_cffi import ffi,lib from typing import Union, List, Callable class Client: @@ -24,7 +24,7 @@ def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int= self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) self.pub_port = pub_port self.rpc_port = rpc_port - lib.nrm_client_create(self._c_client, self._c_uri, self.pub_port, self.rpc_port) + lib.nrm_client_create(self._c_client_p, self._c_uri, self.pub_port, self.rpc_port) self._c_client = self._c_client_p[0] # Based on following from cffi docs: # p_handle = ffi.new("opaque_t **") diff --git a/nrm/api/scope.py b/nrm/api/scope.py new file mode 100644 index 00000000..f43f5ebc --- /dev/null +++ b/nrm/api/scope.py @@ -0,0 +1,37 @@ +from build._nrm_cffi import ffi,lib +from typing import Union, List, Callable + +class Scope: + """Scope class for interacting with NRM C interface. Prototyped interface for scope below. + """ + + def __init__(self): + self._nrm_objects = {} + + def actuate(self, actuator:"Actuator", value:float) -> int: + return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) + + def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: + return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) + + def set_event_listener(self, event_listener:Callable) -> int: + pass + # lib.nrm_client_set_event_listener + + def start_event_listener(self, topic:str) -> int: + topic = ffi.new("char []", bytes(topic, "utf-8")) + topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) + return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) + + def set_actuate_listener(self, actuate_listener:Callable) -> int: + pass + # lib.nrm_client_set_actuate_listener + + def start_actuate_listener(self) -> int: + pass + return lib.nrm_client_start_actuate_listener(self._c_client) + + +if __name__ == "__main__": + with Client() as nrmc: + pass \ No newline at end of file diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py new file mode 100644 index 00000000..77c6ea19 --- /dev/null +++ b/nrm/api/sensor.py @@ -0,0 +1,82 @@ +from build._nrm_cffi import ffi,lib +from typing import Union, List, Callable + +class Client: + """Client class for interacting with NRM C interface. Prototyped interface for client below. + Tentative usage: + ``` + from nrm import Client, Actuator + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + ... + nrmc["my_actuator"] = actuator + ... + nrmc.send_event(get_time(), sensor, scope, 1234) + ... + + ``` + """ + + def __init__(self): + self._nrm_objects = {} + + def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int=3456): + self._c_client_p = ffi.new("nrm_client_t **") + self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) + self.pub_port = pub_port + self.rpc_port = rpc_port + lib.nrm_client_create(self._c_client_p, self._c_uri, self.pub_port, self.rpc_port) + self._c_client = self._c_client_p[0] + # Based on following from cffi docs: + # p_handle = ffi.new("opaque_t **") + # lib.init_stuff(p_handle) # pass the pointer to the 'handle' pointer + # handle = p_handle[0] # now we can read 'handle' out of 'p_handle' + # lib.more_stuff(handle) + + def __exit__(self): + lib.nrm_client_destroy(self._c_client_p) + + def __setitem__(self, uuid_key:str, nrm_object:Union["Scope", "Sensor", "Slice", "Actuator"]): + self._nrm_objects[key] = nrm_object + if isinstance(nrm_object, "Scope"): + return lib.nrm_client_add_scope(self._c_client, nrm_object._c_scope) + elif isinstance(nrm_object, "Sensor"): + return lib.nrm_client_add_sensor(self._c_client, nrm_object._c_sensor) + elif isinstance(nrm_object, "Slice"): + return lib.nrm_client_add_slice(self._c_client, nrm_object._c_slice) + elif isinstance(nrm_object, "Actuator"): + return lib.nrm_client_add_actuator(self._c_client, nrm_object._c_actuator) + + def __getitem__(self, key): + # lib.nrm_client_find + return self._nrm_objects[key] + + def __delitem__(self, key): + pass + + def actuate(self, actuator:"Actuator", value:float) -> int: + return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) + + def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: + return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) + + def set_event_listener(self, event_listener:Callable) -> int: + pass + # lib.nrm_client_set_event_listener + + def start_event_listener(self, topic:str) -> int: + topic = ffi.new("char []", bytes(topic, "utf-8")) + topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) + return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) + + def set_actuate_listener(self, actuate_listener:Callable) -> int: + pass + # lib.nrm_client_set_actuate_listener + + def start_actuate_listener(self) -> int: + pass + return lib.nrm_client_start_actuate_listener(self._c_client) + + +if __name__ == "__main__": + with Client() as nrmc: + pass \ No newline at end of file diff --git a/nrm/api/slice.py b/nrm/api/slice.py new file mode 100644 index 00000000..5b10a720 --- /dev/null +++ b/nrm/api/slice.py @@ -0,0 +1,8 @@ +from build._nrm_cffi import ffi,lib +from typing import Union, List, Callable + +class Slice: + """Slice class for interacting with NRM C interface. Prototyped interface for client below. + Tentative usage: + """ + From 0118bdfbc12b5746c7bae7683789b655d6797a68 Mon Sep 17 00:00:00 2001 From: jlnav Date: Tue, 20 Dec 2022 10:36:38 -0600 Subject: [PATCH 07/39] some notes, and cleaning junk out of ctrl-c-ctrl-v'd sensor.py --- nrm/api/client.py | 7 +++++-- nrm/api/sensor.py | 50 +++++++++-------------------------------------- 2 files changed, 14 insertions(+), 43 deletions(-) diff --git a/nrm/api/client.py b/nrm/api/client.py index 77c6ea19..4bc31638 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -8,7 +8,10 @@ class Client: from nrm import Client, Actuator with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... - nrmc["my_actuator"] = actuator + nrmc["my_actuator"] = actuator not this + + nrmc.scopes["uuid"] = my_scope # do thisZ!!! + ... nrmc.send_event(get_time(), sensor, scope, 1234) ... @@ -65,7 +68,7 @@ def set_event_listener(self, event_listener:Callable) -> int: def start_event_listener(self, topic:str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) - topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) + topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) # need nrm string create return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) def set_actuate_listener(self, actuate_listener:Callable) -> int: diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py index 77c6ea19..8bf71fd6 100644 --- a/nrm/api/sensor.py +++ b/nrm/api/sensor.py @@ -1,12 +1,12 @@ from build._nrm_cffi import ffi,lib from typing import Union, List, Callable -class Client: - """Client class for interacting with NRM C interface. Prototyped interface for client below. +class Sensor: + """Sensor class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: ``` - from nrm import Client, Actuator - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + from nrm import Sensor, Actuator + with Sensor() as nrms: ... nrmc["my_actuator"] = actuator ... @@ -19,21 +19,12 @@ class Client: def __init__(self): self._nrm_objects = {} - def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int=3456): - self._c_client_p = ffi.new("nrm_client_t **") - self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) - self.pub_port = pub_port - self.rpc_port = rpc_port - lib.nrm_client_create(self._c_client_p, self._c_uri, self.pub_port, self.rpc_port) - self._c_client = self._c_client_p[0] - # Based on following from cffi docs: - # p_handle = ffi.new("opaque_t **") - # lib.init_stuff(p_handle) # pass the pointer to the 'handle' pointer - # handle = p_handle[0] # now we can read 'handle' out of 'p_handle' - # lib.more_stuff(handle) + def __enter__(self, name:str= "nrm-sensor", uuid:str="default-uuid"): + self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) + sensor_ptr = lib.nrm_sensor_create(self._c_sensor_name) # intantiate a pointer? def __exit__(self): - lib.nrm_client_destroy(self._c_client_p) + lib.nrm_sensor_destroy(self._c_sensor_p) def __setitem__(self, uuid_key:str, nrm_object:Union["Scope", "Sensor", "Slice", "Actuator"]): self._nrm_objects[key] = nrm_object @@ -53,30 +44,7 @@ def __getitem__(self, key): def __delitem__(self, key): pass - def actuate(self, actuator:"Actuator", value:float) -> int: - return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) - - def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: - return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) - - def set_event_listener(self, event_listener:Callable) -> int: - pass - # lib.nrm_client_set_event_listener - - def start_event_listener(self, topic:str) -> int: - topic = ffi.new("char []", bytes(topic, "utf-8")) - topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) - return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) - - def set_actuate_listener(self, actuate_listener:Callable) -> int: - pass - # lib.nrm_client_set_actuate_listener - - def start_actuate_listener(self) -> int: - pass - return lib.nrm_client_start_actuate_listener(self._c_client) - if __name__ == "__main__": - with Client() as nrmc: + with Sensor() as nrmc: pass \ No newline at end of file From cbaba37c6c099c65f52e68b24b2fc47e7cec2ea6 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 18 Jan 2023 11:26:07 -0600 Subject: [PATCH 08/39] some more silliness --- nrm/api/actuator.py | 26 +++++++++++++++++++++++++- nrm/api/build.py | 4 +++- nrm/api/client.py | 4 +--- nrm/api/sensor.py | 23 +++-------------------- nrm/api/slice.py | 19 +++++++++++++++++++ 5 files changed, 51 insertions(+), 25 deletions(-) diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py index 76862120..7c37bbe3 100644 --- a/nrm/api/actuator.py +++ b/nrm/api/actuator.py @@ -2,4 +2,28 @@ from typing import Union, List, Callable class Actuator: - """Actuator class for interacting with NRM C interface. Prototyped interface for client below.""" + """Actuator class for interacting with NRM C interface. Prototyped interface for client below. + Tentative usage: + ``` + from nrm import Actuator, Client + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + + act = Actuator(name="hello-act", uuid="abcd1234") + nrmc.actuators.append(act) + + + ``` + """ + + def __enter__(self, name:str= "nrm-actuator", uuid:str="default-uuid"): + self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) + self._actuator_ptr = lib.nrm_actuator_create(self._c_actuator_name) # intantiate a pointer? + + def __init(self): + self.__enter__() + + def __exit__(self): + lib.nrm_actuator_destroy(self._actuator_ptr) + + def __delitem__(self, key): + lib.nrm_actuator_destroy(self._actuator_ptr) \ No newline at end of file diff --git a/nrm/api/build.py b/nrm/api/build.py index 8ec7275a..81b29e75 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -18,6 +18,8 @@ typedef struct timespec nrm_time_t; typedef nrm_string_t nrm_uuid_t; +nrm_string_t nrm_string_fromchar(const char *buf); + typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, nrm_time_t time, nrm_scope_t *scope, @@ -56,7 +58,7 @@ double value); int nrm_client_set_event_listener(nrm_client_t *client, - nrm_client_event_listener_fn fn); + nrm_client_event_listener_fn fn); int nrm_client_start_event_listener(const nrm_client_t *client, nrm_string_t topic); diff --git a/nrm/api/client.py b/nrm/api/client.py index 4bc31638..4d91065d 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -8,8 +8,6 @@ class Client: from nrm import Client, Actuator with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... - nrmc["my_actuator"] = actuator not this - nrmc.scopes["uuid"] = my_scope # do thisZ!!! ... @@ -68,7 +66,7 @@ def set_event_listener(self, event_listener:Callable) -> int: def start_event_listener(self, topic:str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) - topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) # need nrm string create + topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) # need nrm_string_fromchar return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) def set_actuate_listener(self, actuate_listener:Callable) -> int: diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py index 8bf71fd6..6a479757 100644 --- a/nrm/api/sensor.py +++ b/nrm/api/sensor.py @@ -16,32 +16,15 @@ class Sensor: ``` """ - def __init__(self): - self._nrm_objects = {} - def __enter__(self, name:str= "nrm-sensor", uuid:str="default-uuid"): self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) - sensor_ptr = lib.nrm_sensor_create(self._c_sensor_name) # intantiate a pointer? + self._sensor_ptr = lib.nrm_sensor_create(self._c_sensor_name) # intantiate a pointer? def __exit__(self): - lib.nrm_sensor_destroy(self._c_sensor_p) - - def __setitem__(self, uuid_key:str, nrm_object:Union["Scope", "Sensor", "Slice", "Actuator"]): - self._nrm_objects[key] = nrm_object - if isinstance(nrm_object, "Scope"): - return lib.nrm_client_add_scope(self._c_client, nrm_object._c_scope) - elif isinstance(nrm_object, "Sensor"): - return lib.nrm_client_add_sensor(self._c_client, nrm_object._c_sensor) - elif isinstance(nrm_object, "Slice"): - return lib.nrm_client_add_slice(self._c_client, nrm_object._c_slice) - elif isinstance(nrm_object, "Actuator"): - return lib.nrm_client_add_actuator(self._c_client, nrm_object._c_actuator) - - def __getitem__(self, key): - # lib.nrm_client_find - return self._nrm_objects[key] + lib.nrm_sensor_destroy(self._sensor_ptr) def __delitem__(self, key): + lib.nrm_sensor_destroy(self._sensor_ptr) pass diff --git a/nrm/api/slice.py b/nrm/api/slice.py index 5b10a720..046f062c 100644 --- a/nrm/api/slice.py +++ b/nrm/api/slice.py @@ -4,5 +4,24 @@ class Slice: """Slice class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: + ``` + from nrm import Slice, Actuator + with Slice() as nrms: + ... + nrmc["my_actuator"] = actuator + ... + nrmc.send_event(get_time(), slice, scope, 1234) + ... + + ``` """ + def __enter__(self, name:str= "nrm-slice", uuid:str="default-uuid"): + self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) + self._slice_ptr = lib.nrm_slice_create(self._c_slice_name) # intantiate a pointer? + + def __exit__(self): + lib.nrm_slice_destroy(self._slice_ptr) + + def __delitem__(self, key): + lib.nrm_slice_destroy(self._slice_ptr) From dd9a218dcc31b8e91ac0384950272ffd6b0cd9d2 Mon Sep 17 00:00:00 2001 From: jlnav Date: Mon, 23 Jan 2023 15:50:14 -0600 Subject: [PATCH 09/39] refactors interface for assigning nrm objects to client, initializes tests (mostly to experiment with interface at this point), various cleanup of currently ctrlc+ctrlv'd objects --- nrm/api/__init__.py | 6 ++++ nrm/api/build.py | 24 ++++++------- nrm/api/client.py | 81 ++++++++++++++++++++++++++++---------------- nrm/api/scope.py | 32 +++++------------ nrm/api/sensor.py | 4 +-- nrm/api/slice.py | 11 +++--- tests/test_client.py | 58 +++++++++++++++++++++++++++++++ 7 files changed, 145 insertions(+), 71 deletions(-) create mode 100644 tests/test_client.py diff --git a/nrm/api/__init__.py b/nrm/api/__init__.py index e5433105..27478c75 100644 --- a/nrm/api/__init__.py +++ b/nrm/api/__init__.py @@ -7,3 +7,9 @@ # # SPDX-License-Identifier: BSD-3-Clause ############################################################################### + +from .actuator import Actuator +from .client import Client +from .scope import Scope +from .sensor import Sensor +from .slice import Slice \ No newline at end of file diff --git a/nrm/api/build.py b/nrm/api/build.py index 81b29e75..d8992abe 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -58,28 +58,28 @@ double value); int nrm_client_set_event_listener(nrm_client_t *client, - nrm_client_event_listener_fn fn); + nrm_client_event_listener_fn fn); + +int nrm_client_set_event_Pylistener(nrm_client_t *client, + PyObject *fn); int nrm_client_start_event_listener(const nrm_client_t *client, nrm_string_t topic); +int nrm_client_start_event_Pylistener(nrm_client_t *client, + nrm_string_t topic); + int nrm_client_set_actuate_listener(nrm_client_t *client, nrm_client_actuate_listener_fn fn); -int nrm_client_start_actuate_listener(const nrm_client_t *client); - -void nrm_client_destroy(nrm_client_t **client); -nrm_sensor_t *nrm_sensor_create(const char *name); +int nrm_client_set_actuate_Pylistener(nrm_client_t *client, + PyObject *fn); -void nrm_sensor_destroy(nrm_sensor_t **); - -nrm_slice_t *nrm_slice_create(const char *name); - -void nrm_slice_destroy(nrm_slice_t **); +int nrm_client_start_actuate_listener(const nrm_client_t *client); -nrm_actuator_t *nrm_actuator_create(const char *name); +int nrm_client_start_actuate_Pylistener(const nrm_client_t *client); -void nrm_actuator_destroy(nrm_actuator_t **); +void nrm_client_destroy(nrm_client_t **client); """) diff --git a/nrm/api/client.py b/nrm/api/client.py index 4d91065d..dc230b66 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,6 +1,41 @@ from build._nrm_cffi import ffi,lib from typing import Union, List, Callable +from dataclasses import dataclass + +class _NRM_d(dict): + + def __init__(self, *args): + dict.__init__(self, args) + + def _set_client(client): + self._c_client = client + +class _NRMScopes(_NRM_d): + + def __setitem__(self, uuid_key:str, nrm_object:"Scope"): + super().__setitem__(self, uuid_key, nrm_object) + return lib.nrm_client_add_scope(self._c_client, nrm_object._c_scope) + +class _NRMSensors(_NRM_d): + + def __setitem__(self, uuid_key:str, nrm_object:"Sensor"): + super().__setitem__(self, uuid_key, nrm_object) + return lib.nrm_client_add_sensor(self._c_client, nrm_object._c_sensor) + +class _NRMSlices(_NRM_d): + + def __setitem__(self, uuid_key:str, nrm_object:"Slice"): + super().__setitem__(self, uuid_key, nrm_object) + return lib.nrm_client_add_slice(self._c_client, nrm_object._c_scope) + +class _NRMActuators(_NRM_d): + + def __setitem__(self, uuid_key:str, nrm_object:"Actuator"): + super().__setitem__(self, uuid_key, nrm_object) + return lib.nrm_client_add_actuator(self._c_client, nrm_object._c_scope) + +@dataclass class Client: """Client class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: @@ -8,7 +43,7 @@ class Client: from nrm import Client, Actuator with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... - nrmc.scopes["uuid"] = my_scope # do thisZ!!! + nrmc.scopes["uuid"] = my_scope ... nrmc.send_event(get_time(), sensor, scope, 1234) @@ -17,8 +52,10 @@ class Client: ``` """ - def __init__(self): - self._nrm_objects = {} + scopes: _NRMScopes = _NRMScopes() + sensors: _NRMSensors = _NRMSensors() + slices: _NRMSlices = _NRMSlices() + actuators: _NRMActuators = _NRMActuators() def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int=3456): self._c_client_p = ffi.new("nrm_client_t **") @@ -27,6 +64,9 @@ def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int= self.rpc_port = rpc_port lib.nrm_client_create(self._c_client_p, self._c_uri, self.pub_port, self.rpc_port) self._c_client = self._c_client_p[0] + + for d in [self.scopes, self.sensors, self.slices, self.actuators]: + d._set_client(self._c_client) # Based on following from cffi docs: # p_handle = ffi.new("opaque_t **") # lib.init_stuff(p_handle) # pass the pointer to the 'handle' pointer @@ -36,24 +76,6 @@ def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int= def __exit__(self): lib.nrm_client_destroy(self._c_client_p) - def __setitem__(self, uuid_key:str, nrm_object:Union["Scope", "Sensor", "Slice", "Actuator"]): - self._nrm_objects[key] = nrm_object - if isinstance(nrm_object, "Scope"): - return lib.nrm_client_add_scope(self._c_client, nrm_object._c_scope) - elif isinstance(nrm_object, "Sensor"): - return lib.nrm_client_add_sensor(self._c_client, nrm_object._c_sensor) - elif isinstance(nrm_object, "Slice"): - return lib.nrm_client_add_slice(self._c_client, nrm_object._c_slice) - elif isinstance(nrm_object, "Actuator"): - return lib.nrm_client_add_actuator(self._c_client, nrm_object._c_actuator) - - def __getitem__(self, key): - # lib.nrm_client_find - return self._nrm_objects[key] - - def __delitem__(self, key): - pass - def actuate(self, actuator:"Actuator", value:float) -> int: return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) @@ -62,21 +84,22 @@ def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> i def set_event_listener(self, event_listener:Callable) -> int: pass - # lib.nrm_client_set_event_listener + # lib.nrm_client_set_event_Pylistener - def start_event_listener(self, topic:str) -> int: + def start_event_listener(self, topic:str, *args, **kwargs) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) - topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) # need nrm_string_fromchar - return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) + topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) + # return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) + # lib.nrm_client_start_event_Pylistener def set_actuate_listener(self, actuate_listener:Callable) -> int: pass - # lib.nrm_client_set_actuate_listener + # lib.nrm_client_set_actuate_Pylistener - def start_actuate_listener(self) -> int: + def start_actuate_listener(self, *args, **kwargs) -> int: pass - return lib.nrm_client_start_actuate_listener(self._c_client) - + # return lib.nrm_client_start_actuate_listener(self._c_client) + # lib.nrm_client_start_event_Pylistener if __name__ == "__main__": with Client() as nrmc: diff --git a/nrm/api/scope.py b/nrm/api/scope.py index f43f5ebc..838e808b 100644 --- a/nrm/api/scope.py +++ b/nrm/api/scope.py @@ -5,32 +5,18 @@ class Scope: """Scope class for interacting with NRM C interface. Prototyped interface for scope below. """ - def __init__(self): - self._nrm_objects = {} + def __enter__(self, name:str= "nrm-actuator", uuid:str="default-uuid"): + self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) + self._actuator_ptr = lib.nrm_actuator_create(self._c_actuator_name) # intantiate a pointer? - def actuate(self, actuator:"Actuator", value:float) -> int: - return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) + def __init(self): + self.__enter__() - def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: - return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) - - def set_event_listener(self, event_listener:Callable) -> int: - pass - # lib.nrm_client_set_event_listener - - def start_event_listener(self, topic:str) -> int: - topic = ffi.new("char []", bytes(topic, "utf-8")) - topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) - return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) - - def set_actuate_listener(self, actuate_listener:Callable) -> int: - pass - # lib.nrm_client_set_actuate_listener - - def start_actuate_listener(self) -> int: - pass - return lib.nrm_client_start_actuate_listener(self._c_client) + def __exit__(self): + lib.nrm_actuator_destroy(self._actuator_ptr) + def __delitem__(self, key): + lib.nrm_actuator_destroy(self._actuator_ptr) if __name__ == "__main__": with Client() as nrmc: diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py index 6a479757..2c386934 100644 --- a/nrm/api/sensor.py +++ b/nrm/api/sensor.py @@ -6,9 +6,9 @@ class Sensor: Tentative usage: ``` from nrm import Sensor, Actuator - with Sensor() as nrms: + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... - nrmc["my_actuator"] = actuator + nrmc.sensors["abc123"] = my_sensor ... nrmc.send_event(get_time(), sensor, scope, 1234) ... diff --git a/nrm/api/slice.py b/nrm/api/slice.py index 046f062c..016877e0 100644 --- a/nrm/api/slice.py +++ b/nrm/api/slice.py @@ -5,14 +5,15 @@ class Slice: """Slice class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: ``` - from nrm import Slice, Actuator - with Slice() as nrms: + from nrm import Client, Actuator + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... - nrmc["my_actuator"] = actuator + my_slice = Slice("nrm-slice", "abc123) + nrmc.slices["uuid"] = my_slice + ... - nrmc.send_event(get_time(), slice, scope, 1234) + nrmc.send_event(get_time(), sensor, scope, 1234) ... - ``` """ diff --git a/tests/test_client.py b/tests/test_client.py new file mode 100644 index 00000000..59f41e43 --- /dev/null +++ b/tests/test_client.py @@ -0,0 +1,58 @@ +import secrets +import pytest +from nrm.api import Client, Actuator, Scope, Sensor, Slice + + +def test_client_objs_init(): + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + act_uuid = secrets.token_hex(3) + sco_uuid = secrets.token_hex(3) + sen_uuid = secrets.token_hex(3) + sli_uuid = secrets.token_hex(3) + + act = Actuator("nrm-test-actuator", act_uuid) + sco = Scope("nrm-test-scope", sco_uuid) + sen = Sensor("nrm-test-sensor", sen_uuid) + sli = Slice("nrm-test-slice", sli_uuid) + +def test_client_delete(): + pass + +def test_set_objs_to_client(): + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + act_uuid = secrets.token_hex(3) + sco_uuid = secrets.token_hex(3) + sen_uuid = secrets.token_hex(3) + sli_uuid = secrets.token_hex(3) + + act = Actuator("nrm-test-actuator", act_uuid) + sco = Scope("nrm-test-scope", sco_uuid) + sen = Sensor("nrm-test-sensor", sen_uuid) + sli = Slice("nrm-test-slice", sli_uuid) + + nrmc.actuators[act_uuid] = act + nrmc.scopes[sco_uuid] = sco + nrmc.sensors[sen_uuid] = sen + nrmc.slices[sli_uuid] = sli + +def test_actuate(): + pass + +def test_send_event(): + pass + +def test_event_callbacks(): + pass + +def test_actuate_callbacks(): + pass + + +if __name__ == "__main__": + test_client_objs_init() + test_client_delete() + test_set_objs_to_client() + test_actuate() + test_send_event() + test_event_callbacks() + test_actuate_callbacks() From 0d496f3f0b19e60b88a05460b038f26e7bab04e2 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 26 Jan 2023 14:18:05 -0600 Subject: [PATCH 10/39] molding out test_client.py --- nrm/api/actuator.py | 8 +---- nrm/api/client.py | 11 +++--- tests/test_client.py | 82 +++++++++++++++++++++++++++++--------------- 3 files changed, 63 insertions(+), 38 deletions(-) diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py index 7c37bbe3..6a4b78ff 100644 --- a/nrm/api/actuator.py +++ b/nrm/api/actuator.py @@ -15,15 +15,9 @@ class Actuator: ``` """ - def __enter__(self, name:str= "nrm-actuator", uuid:str="default-uuid"): + def __init__(self, name:str= "nrm-actuator", uuid:str="default-uuid"): self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) self._actuator_ptr = lib.nrm_actuator_create(self._c_actuator_name) # intantiate a pointer? - def __init(self): - self.__enter__() - - def __exit__(self): - lib.nrm_actuator_destroy(self._actuator_ptr) - def __delitem__(self, key): lib.nrm_actuator_destroy(self._actuator_ptr) \ No newline at end of file diff --git a/nrm/api/client.py b/nrm/api/client.py index dc230b66..dbd035da 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -80,25 +80,28 @@ def actuate(self, actuator:"Actuator", value:float) -> int: return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: + # need nrm_time_t time return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) def set_event_listener(self, event_listener:Callable) -> int: pass + # assert event_listener accepts 4 arguments? + # with call with: uuid, time, scope, msg->event->value # lib.nrm_client_set_event_Pylistener - def start_event_listener(self, topic:str, *args, **kwargs) -> int: + def start_event_listener(self, topic:str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) - # return lib.nrm_client_start_event_listener(self._c_client, topic_as_nrm_string_t) # lib.nrm_client_start_event_Pylistener def set_actuate_listener(self, actuate_listener:Callable) -> int: pass + # assert actuate_listener accepts 2 arguments? + # will call with: uuid, msg->event->value # lib.nrm_client_set_actuate_Pylistener - def start_actuate_listener(self, *args, **kwargs) -> int: + def start_actuate_listener(self) -> int: pass - # return lib.nrm_client_start_actuate_listener(self._c_client) # lib.nrm_client_start_event_Pylistener if __name__ == "__main__": diff --git a/tests/test_client.py b/tests/test_client.py index 59f41e43..8c3cec79 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,56 +1,84 @@ import secrets import pytest +import time from nrm.api import Client, Actuator, Scope, Sensor, Slice +act_uuid = secrets.token_hex(3) +sco_uuid = secrets.token_hex(3) +sen_uuid = secrets.token_hex(3) +sli_uuid = secrets.token_hex(3) -def test_client_objs_init(): - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - act_uuid = secrets.token_hex(3) - sco_uuid = secrets.token_hex(3) - sen_uuid = secrets.token_hex(3) - sli_uuid = secrets.token_hex(3) - act = Actuator("nrm-test-actuator", act_uuid) - sco = Scope("nrm-test-scope", sco_uuid) - sen = Sensor("nrm-test-sensor", sen_uuid) - sli = Slice("nrm-test-slice", sli_uuid) +def test_client_init(): + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + # evaluate nrmc + pass -def test_client_delete(): - pass def test_set_objs_to_client(): - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - act_uuid = secrets.token_hex(3) - sco_uuid = secrets.token_hex(3) - sen_uuid = secrets.token_hex(3) - sli_uuid = secrets.token_hex(3) - act = Actuator("nrm-test-actuator", act_uuid) - sco = Scope("nrm-test-scope", sco_uuid) - sen = Sensor("nrm-test-sensor", sen_uuid) - sli = Slice("nrm-test-slice", sli_uuid) + act = Actuator("nrm-test-actuator", act_uuid) + sco = Scope("nrm-test-scope", sco_uuid) + sen = Sensor("nrm-test-sensor", sen_uuid) + sli = Slice("nrm-test-slice", sli_uuid) + # assert names, pointers, objects are instantiated underneath for each + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: nrmc.actuators[act_uuid] = act nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen nrmc.slices[sli_uuid] = sli + # assert both py and C client contains new objects + def test_actuate(): - pass + act = Actuator("nrm-test-actuator", act_uuid) + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + nrmc.actuators[act_uuid] = act + flag = nrmc.actuate(act, 1234) + # assert flag == 0, read log? + def test_send_event(): - pass + sco = Scope("nrm-test-scope", sco_uuid) + sen = Sensor("nrm-test-sensor", sen_uuid) + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + nrmc.scopes[sco_uuid] = sco + nrmc.sensors[sen_uuid] = sen + now = int(time.time()) + flag = nrmc.send_event(now, sen, sco, 1234) + # assert flag == 0, read log? + def test_event_callbacks(): - pass + + def print_event_info(*args): + print("Responding to subscribed event") + uuid, time, scope, value = args + print(uuid, time, scope, value) + + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + nrmc.set_event_listener(print_event_info) + # check if pyfn has made it into client struct? + nrmc.start_event_listener("test-report-numa-pwr") + # check logs? + def test_actuate_callbacks(): - pass + def print_actuate_info(*args): + print("Responding to actuation request") + uuid, value = args + print(uuid, value) + + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + nrmc.set_actuate_listener(print_actuate_info) + # check if pyfn has made it into client struct? + nrmc.start_actuate_listener() + # check logs? if __name__ == "__main__": - test_client_objs_init() - test_client_delete() + test_client_init() test_set_objs_to_client() test_actuate() test_send_event() From ddb33293d028b4a9c77a94ccddfc5a3530c74f7f Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 26 Jan 2023 15:05:13 -0600 Subject: [PATCH 11/39] need to access object creators underneath --- nrm/api/build.py | 10 ++++++++++ nrm/api/client.py | 5 ++++- tests/test_client.py | 8 ++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index d8992abe..2046b289 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -20,6 +20,16 @@ nrm_string_t nrm_string_fromchar(const char *buf); +void nrm_time_gettime(nrm_time_t *now); + +nrm_actuator_t *nrm_actuator_create(const char *name); + +nrm_scope_t *nrm_scope_create(const char *name); + +nrm_sensor_t *nrm_sensor_create(const char *name); + +nrm_slice_t *nrm_slice_create(const char *name); + typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, nrm_time_t time, nrm_scope_t *scope, diff --git a/nrm/api/client.py b/nrm/api/client.py index dbd035da..c2d54996 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -81,7 +81,10 @@ def actuate(self, actuator:"Actuator", value:float) -> int: def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: # need nrm_time_t time - return lib.nrm_client_send_event(self._c_client, time, sensor._c_sensor, scope._c_scope, value) + timespec_p = ffi.new("nrm_time_t **") + lib.nrm_time_gettime(timespec_p) + timespec = timespec_p[0] + return lib.nrm_client_send_event(self._c_client, timespec, sensor._c_sensor, scope._c_scope, value) def set_event_listener(self, event_listener:Callable) -> int: pass diff --git a/tests/test_client.py b/tests/test_client.py index 8c3cec79..71f58936 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -58,9 +58,9 @@ def print_event_info(*args): print(uuid, time, scope, value) with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - nrmc.set_event_listener(print_event_info) + flag = nrmc.set_event_listener(print_event_info) # check if pyfn has made it into client struct? - nrmc.start_event_listener("test-report-numa-pwr") + flag = nrmc.start_event_listener("test-report-numa-pwr") # check logs? @@ -71,9 +71,9 @@ def print_actuate_info(*args): print(uuid, value) with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - nrmc.set_actuate_listener(print_actuate_info) + flag = nrmc.set_actuate_listener(print_actuate_info) # check if pyfn has made it into client struct? - nrmc.start_actuate_listener() + flag = nrmc.start_actuate_listener() # check logs? From 9cff0fec6e48987a5e1d01084ebcc2e9a86dfba0 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 27 Jan 2023 12:31:20 -0600 Subject: [PATCH 12/39] some reorganization, adjustments based on not needing PyObject --- nrm/api/actuator.py | 2 +- nrm/api/build.py | 45 ++++++++++++++++++++++++--------------- nrm/api/build/__init__.py | 9 -------- nrm/api/client.py | 2 +- nrm/api/scope.py | 2 +- nrm/api/sensor.py | 2 +- nrm/api/slice.py | 2 +- tests/test_client.py | 13 ++++++----- 8 files changed, 39 insertions(+), 38 deletions(-) delete mode 100644 nrm/api/build/__init__.py diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py index 6a4b78ff..c126d07d 100644 --- a/nrm/api/actuator.py +++ b/nrm/api/actuator.py @@ -1,4 +1,4 @@ -from build._nrm_cffi import ffi,lib +from _build._nrm_cffi import ffi,lib from typing import Union, List, Callable class Actuator: diff --git a/nrm/api/build.py b/nrm/api/build.py index 2046b289..8ce3123b 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -18,6 +18,34 @@ typedef struct timespec nrm_time_t; typedef nrm_string_t nrm_uuid_t; +typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, + nrm_time_t time, + nrm_scope_t *scope, + double value); +typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, double value); + +// PY STUFF + +extern "Python" int _event_listener(nrm_string_t sensor_uuid, + nrm_time_t time, + nrm_scope_t *scope, + double value); + +extern "Python" int _actuate_listener(nrm_uuid_t *uuid, double value); + +int nrm_client_set_event_Pylistener(nrm_client_t *client, + nrm_client_event_listener_fn *fn); + +int nrm_client_set_actuate_Pylistener(nrm_client_t *client, + nrm_client_actuate_listener_fn *fn); + +int nrm_client_start_event_Pylistener(const nrm_client_t *client, + nrm_string_t topic); + +int nrm_client_start_actuate_Pylistener(const nrm_client_t *client); + +// END PY STUFF + nrm_string_t nrm_string_fromchar(const char *buf); void nrm_time_gettime(nrm_time_t *now); @@ -30,12 +58,6 @@ nrm_slice_t *nrm_slice_create(const char *name); -typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, - nrm_time_t time, - nrm_scope_t *scope, - double value); -typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, double value); - int nrm_client_create(nrm_client_t **client, const char *uri, int pub_port, @@ -70,25 +92,14 @@ int nrm_client_set_event_listener(nrm_client_t *client, nrm_client_event_listener_fn fn); -int nrm_client_set_event_Pylistener(nrm_client_t *client, - PyObject *fn); - int nrm_client_start_event_listener(const nrm_client_t *client, nrm_string_t topic); -int nrm_client_start_event_Pylistener(nrm_client_t *client, - nrm_string_t topic); - int nrm_client_set_actuate_listener(nrm_client_t *client, nrm_client_actuate_listener_fn fn); -int nrm_client_set_actuate_Pylistener(nrm_client_t *client, - PyObject *fn); - int nrm_client_start_actuate_listener(const nrm_client_t *client); -int nrm_client_start_actuate_Pylistener(const nrm_client_t *client); - void nrm_client_destroy(nrm_client_t **client); """) diff --git a/nrm/api/build/__init__.py b/nrm/api/build/__init__.py deleted file mode 100644 index e5433105..00000000 --- a/nrm/api/build/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -############################################################################### -# Copyright 2019 UChicago Argonne, LLC. -# (c.f. AUTHORS, LICENSE) -# -# This file is part of the NRM project. -# For more info, see https://github.com/anlsys/nrm-python -# -# SPDX-License-Identifier: BSD-3-Clause -############################################################################### diff --git a/nrm/api/client.py b/nrm/api/client.py index c2d54996..f9cb5d76 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,4 +1,4 @@ -from build._nrm_cffi import ffi,lib +from _build._nrm_cffi import ffi,lib from typing import Union, List, Callable from dataclasses import dataclass diff --git a/nrm/api/scope.py b/nrm/api/scope.py index 838e808b..cf38de5f 100644 --- a/nrm/api/scope.py +++ b/nrm/api/scope.py @@ -1,4 +1,4 @@ -from build._nrm_cffi import ffi,lib +from _build._nrm_cffi import ffi,lib from typing import Union, List, Callable class Scope: diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py index 2c386934..b745fa3e 100644 --- a/nrm/api/sensor.py +++ b/nrm/api/sensor.py @@ -1,4 +1,4 @@ -from build._nrm_cffi import ffi,lib +from _build._nrm_cffi import ffi,lib from typing import Union, List, Callable class Sensor: diff --git a/nrm/api/slice.py b/nrm/api/slice.py index 016877e0..67b701d4 100644 --- a/nrm/api/slice.py +++ b/nrm/api/slice.py @@ -1,4 +1,4 @@ -from build._nrm_cffi import ffi,lib +from _build._nrm_cffi import ffi,lib from typing import Union, List, Callable class Slice: diff --git a/tests/test_client.py b/tests/test_client.py index 71f58936..14bbdcaf 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,5 +1,4 @@ import secrets -import pytest import time from nrm.api import Client, Actuator, Scope, Sensor, Slice @@ -10,7 +9,7 @@ def test_client_init(): - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + with Client() as nrmc: # evaluate nrmc pass @@ -23,7 +22,7 @@ def test_set_objs_to_client(): sli = Slice("nrm-test-slice", sli_uuid) # assert names, pointers, objects are instantiated underneath for each - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + with Client() as nrmc: nrmc.actuators[act_uuid] = act nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen @@ -33,7 +32,7 @@ def test_set_objs_to_client(): def test_actuate(): act = Actuator("nrm-test-actuator", act_uuid) - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + with Client() as nrmc: nrmc.actuators[act_uuid] = act flag = nrmc.actuate(act, 1234) # assert flag == 0, read log? @@ -42,7 +41,7 @@ def test_actuate(): def test_send_event(): sco = Scope("nrm-test-scope", sco_uuid) sen = Sensor("nrm-test-sensor", sen_uuid) - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + with Client() as nrmc: nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen now = int(time.time()) @@ -57,7 +56,7 @@ def print_event_info(*args): uuid, time, scope, value = args print(uuid, time, scope, value) - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + with Client() as nrmc: flag = nrmc.set_event_listener(print_event_info) # check if pyfn has made it into client struct? flag = nrmc.start_event_listener("test-report-numa-pwr") @@ -70,7 +69,7 @@ def print_actuate_info(*args): uuid, value = args print(uuid, value) - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + with Client() as nrmc: flag = nrmc.set_actuate_listener(print_actuate_info) # check if pyfn has made it into client struct? flag = nrmc.start_actuate_listener() From 4b4fb871fb78bd3a557d969d4c8dec195718c000 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 27 Jan 2023 14:32:26 -0600 Subject: [PATCH 13/39] fix imports, black reformatting, place .so in separate dir, client runs nrm_init, fix init of scope/sensor/slice/actuator client dicts, fix context switcher, fix various pointers, adjust non-client objects to not use context-switches, --- nrm/api/__init__.py | 2 +- nrm/api/actuator.py | 11 +++--- nrm/api/build.py | 19 +++++++---- nrm/api/client.py | 80 ++++++++++++++++++++++++-------------------- nrm/api/scope.py | 26 +++++--------- nrm/api/sensor.py | 20 ++++------- nrm/api/slice.py | 12 +++---- tests/test_client.py | 2 -- 8 files changed, 85 insertions(+), 87 deletions(-) diff --git a/nrm/api/__init__.py b/nrm/api/__init__.py index 27478c75..a13419b0 100644 --- a/nrm/api/__init__.py +++ b/nrm/api/__init__.py @@ -12,4 +12,4 @@ from .client import Client from .scope import Scope from .sensor import Sensor -from .slice import Slice \ No newline at end of file +from .slice import Slice diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py index c126d07d..c37dd2bf 100644 --- a/nrm/api/actuator.py +++ b/nrm/api/actuator.py @@ -1,6 +1,7 @@ -from _build._nrm_cffi import ffi,lib +from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable + class Actuator: """Actuator class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: @@ -15,9 +16,11 @@ class Actuator: ``` """ - def __init__(self, name:str= "nrm-actuator", uuid:str="default-uuid"): + def __init__(self, name: str = "nrm-actuator", uuid: str = "default-uuid"): self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) - self._actuator_ptr = lib.nrm_actuator_create(self._c_actuator_name) # intantiate a pointer? + self._actuator_ptr = lib.nrm_actuator_create( + self._c_actuator_name + ) # intantiate a pointer? def __delitem__(self, key): - lib.nrm_actuator_destroy(self._actuator_ptr) \ No newline at end of file + lib.nrm_actuator_destroy(self._actuator_ptr) diff --git a/nrm/api/build.py b/nrm/api/build.py index 8ce3123b..c547a21f 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -1,13 +1,17 @@ from cffi import FFI + ffi = FFI() -ffi.set_source("build._nrm_cffi", -""" +ffi.set_source( + "_build._nrm_cffi", + """ #include "nrm.h" """, - libraries=["nrm"]) + libraries=["nrm"], +) -ffi.cdef(""" +ffi.cdef( + """ typedef struct nrm_client_s nrm_client_t; typedef struct nrm_actuator_s nrm_actuator_t; typedef struct nrm_slice_s nrm_slice_t; @@ -46,6 +50,8 @@ // END PY STUFF +int nrm_init(int *argc, char **argv[]); + nrm_string_t nrm_string_fromchar(const char *buf); void nrm_time_gettime(nrm_time_t *now); @@ -102,9 +108,8 @@ void nrm_client_destroy(nrm_client_t **client); -""") +""" +) if __name__ == "__main__": ffi.compile(verbose=True) - - diff --git a/nrm/api/client.py b/nrm/api/client.py index f9cb5d76..fa848c25 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,39 +1,39 @@ -from _build._nrm_cffi import ffi,lib +from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable -from dataclasses import dataclass +from dataclasses import dataclass, field class _NRM_d(dict): - def __init__(self, *args): dict.__init__(self, args) - def _set_client(client): + def _set_client(self, client): self._c_client = client + class _NRMScopes(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Scope"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_scope(self._c_client, nrm_object._scope_ptr) - def __setitem__(self, uuid_key:str, nrm_object:"Scope"): - super().__setitem__(self, uuid_key, nrm_object) - return lib.nrm_client_add_scope(self._c_client, nrm_object._c_scope) class _NRMSensors(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Sensor"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_sensor(self._c_client, nrm_object._sensor_ptr) - def __setitem__(self, uuid_key:str, nrm_object:"Sensor"): - super().__setitem__(self, uuid_key, nrm_object) - return lib.nrm_client_add_sensor(self._c_client, nrm_object._c_sensor) class _NRMSlices(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Slice"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_slice(self._c_client, nrm_object._slice_ptr) - def __setitem__(self, uuid_key:str, nrm_object:"Slice"): - super().__setitem__(self, uuid_key, nrm_object) - return lib.nrm_client_add_slice(self._c_client, nrm_object._c_scope) class _NRMActuators(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Actuator"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_actuator(self._c_client, nrm_object._actuator_ptr) - def __setitem__(self, uuid_key:str, nrm_object:"Actuator"): - super().__setitem__(self, uuid_key, nrm_object) - return lib.nrm_client_add_actuator(self._c_client, nrm_object._c_scope) @dataclass class Client: @@ -52,52 +52,57 @@ class Client: ``` """ - scopes: _NRMScopes = _NRMScopes() - sensors: _NRMSensors = _NRMSensors() - slices: _NRMSlices = _NRMSlices() - actuators: _NRMActuators = _NRMActuators() + scopes: _NRMScopes = field(default_factory=_NRMScopes) + sensors: _NRMSensors = field(default_factory=_NRMSensors) + slices: _NRMSlices = field(default_factory=_NRMSlices) + actuators: _NRMActuators = field(default_factory=_NRMActuators) - def __enter__(self, uri:str= "tcp://127.0.0.1", pub_port:int=2345, rpc_port:int=3456): + def __enter__( + self, uri: str = "tcp://127.0.0.1", pub_port: int = 2345, rpc_port: int = 3456 + ): self._c_client_p = ffi.new("nrm_client_t **") self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) self.pub_port = pub_port self.rpc_port = rpc_port - lib.nrm_client_create(self._c_client_p, self._c_uri, self.pub_port, self.rpc_port) + flag = lib.nrm_init(ffi.NULL, ffi.NULL) + flag = lib.nrm_client_create( + self._c_client_p, self._c_uri, self.pub_port, self.rpc_port + ) self._c_client = self._c_client_p[0] for d in [self.scopes, self.sensors, self.slices, self.actuators]: d._set_client(self._c_client) - # Based on following from cffi docs: - # p_handle = ffi.new("opaque_t **") - # lib.init_stuff(p_handle) # pass the pointer to the 'handle' pointer - # handle = p_handle[0] # now we can read 'handle' out of 'p_handle' - # lib.more_stuff(handle) - def __exit__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): lib.nrm_client_destroy(self._c_client_p) - def actuate(self, actuator:"Actuator", value:float) -> int: - return lib.nrm_client_actuate(self._c_client, actuator._c_actuator, value) + def actuate(self, actuator: "Actuator", value: float) -> int: + return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr, value) - def send_event(self, time:int, sensor:"Sensor", scope:"Scope", value:float) -> int: - # need nrm_time_t time + def send_event( + self, sensor: "Sensor", scope: "Scope", value: float + ) -> int: timespec_p = ffi.new("nrm_time_t **") lib.nrm_time_gettime(timespec_p) timespec = timespec_p[0] - return lib.nrm_client_send_event(self._c_client, timespec, sensor._c_sensor, scope._c_scope, value) + return lib.nrm_client_send_event( + self._c_client, timespec, sensor._sensor_ptr, scope._scope_ptr, value + ) - def set_event_listener(self, event_listener:Callable) -> int: + def set_event_listener(self, event_listener: Callable) -> int: pass # assert event_listener accepts 4 arguments? # with call with: uuid, time, scope, msg->event->value # lib.nrm_client_set_event_Pylistener - def start_event_listener(self, topic:str) -> int: + def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) # lib.nrm_client_start_event_Pylistener - def set_actuate_listener(self, actuate_listener:Callable) -> int: + def set_actuate_listener(self, actuate_listener: Callable) -> int: pass # assert actuate_listener accepts 2 arguments? # will call with: uuid, msg->event->value @@ -107,6 +112,7 @@ def start_actuate_listener(self) -> int: pass # lib.nrm_client_start_event_Pylistener + if __name__ == "__main__": with Client() as nrmc: - pass \ No newline at end of file + pass diff --git a/nrm/api/scope.py b/nrm/api/scope.py index cf38de5f..8a6fc38a 100644 --- a/nrm/api/scope.py +++ b/nrm/api/scope.py @@ -1,23 +1,15 @@ -from _build._nrm_cffi import ffi,lib +from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable -class Scope: - """Scope class for interacting with NRM C interface. Prototyped interface for scope below. - """ - def __enter__(self, name:str= "nrm-actuator", uuid:str="default-uuid"): - self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) - self._actuator_ptr = lib.nrm_actuator_create(self._c_actuator_name) # intantiate a pointer? +class Scope: + """Scope class for interacting with NRM C interface. Prototyped interface for scope below.""" - def __init(self): - self.__enter__() + def __init__(self, name: str = "nrm-scope", uuid: str = "default-uuid"): + self._c_scope_name = ffi.new("char[]", bytes(name, "utf-8")) + self._scope_ptr = lib.nrm_scope_create( + self._c_scope_name + ) # intantiate a pointer? - def __exit__(self): + def __delitem__(self): lib.nrm_actuator_destroy(self._actuator_ptr) - - def __delitem__(self, key): - lib.nrm_actuator_destroy(self._actuator_ptr) - -if __name__ == "__main__": - with Client() as nrmc: - pass \ No newline at end of file diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py index b745fa3e..21745243 100644 --- a/nrm/api/sensor.py +++ b/nrm/api/sensor.py @@ -1,6 +1,7 @@ -from _build._nrm_cffi import ffi,lib +from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable + class Sensor: """Sensor class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: @@ -16,18 +17,11 @@ class Sensor: ``` """ - def __enter__(self, name:str= "nrm-sensor", uuid:str="default-uuid"): + def __init__(self, name: str = "nrm-sensor", uuid: str = "default-uuid"): self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) - self._sensor_ptr = lib.nrm_sensor_create(self._c_sensor_name) # intantiate a pointer? - - def __exit__(self): - lib.nrm_sensor_destroy(self._sensor_ptr) + self._sensor_ptr = lib.nrm_sensor_create( + self._c_sensor_name + ) # intantiate a pointer? - def __delitem__(self, key): + def __delitem__(self): lib.nrm_sensor_destroy(self._sensor_ptr) - pass - - -if __name__ == "__main__": - with Sensor() as nrmc: - pass \ No newline at end of file diff --git a/nrm/api/slice.py b/nrm/api/slice.py index 67b701d4..d08ee64b 100644 --- a/nrm/api/slice.py +++ b/nrm/api/slice.py @@ -1,6 +1,7 @@ -from _build._nrm_cffi import ffi,lib +from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable + class Slice: """Slice class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: @@ -17,12 +18,11 @@ class Slice: ``` """ - def __enter__(self, name:str= "nrm-slice", uuid:str="default-uuid"): + def __init__(self, name: str = "nrm-slice", uuid: str = "default-uuid"): self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) - self._slice_ptr = lib.nrm_slice_create(self._c_slice_name) # intantiate a pointer? - - def __exit__(self): - lib.nrm_slice_destroy(self._slice_ptr) + self._slice_ptr = lib.nrm_slice_create( + self._c_slice_name + ) # intantiate a pointer? def __delitem__(self, key): lib.nrm_slice_destroy(self._slice_ptr) diff --git a/tests/test_client.py b/tests/test_client.py index 14bbdcaf..6298da4f 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -10,7 +10,6 @@ def test_client_init(): with Client() as nrmc: - # evaluate nrmc pass @@ -50,7 +49,6 @@ def test_send_event(): def test_event_callbacks(): - def print_event_info(*args): print("Responding to subscribed event") uuid, time, scope, value = args From 4da23775e61ee9ba7ea5d11578356e0b8b7d08ed Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 2 Feb 2023 17:11:44 -0600 Subject: [PATCH 14/39] trying to set up wrappers and registration --- nrm/api/build.py | 15 +++++++++------ nrm/api/client.py | 29 ++++++++++++++++++----------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index c547a21f..5c5ecb49 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -30,12 +30,15 @@ // PY STUFF -extern "Python" int _event_listener(nrm_string_t sensor_uuid, - nrm_time_t time, - nrm_scope_t *scope, - double value); - -extern "Python" int _actuate_listener(nrm_uuid_t *uuid, double value); +extern "Python" int _event_listener_wrap(nrm_client_event_listener_fn *fn, + nrm_string_t sensor_uuid, + nrm_time_t time, + nrm_scope_t *scope, + double value); + +extern "Python" int _actuate_listener_wrap(nrm_client_actuate_listener_fn *fn, + nrm_uuid_t uuid, + double value); int nrm_client_set_event_Pylistener(nrm_client_t *client, nrm_client_event_listener_fn *fn); diff --git a/nrm/api/client.py b/nrm/api/client.py index fa848c25..fa53db29 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,6 +1,7 @@ from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable from dataclasses import dataclass, field +import inspect class _NRM_d(dict): @@ -92,10 +93,11 @@ def send_event( ) def set_event_listener(self, event_listener: Callable) -> int: - pass - # assert event_listener accepts 4 arguments? - # with call with: uuid, time, scope, msg->event->value - # lib.nrm_client_set_event_Pylistener + assert len(inspect.signature(event_listener).parameters) == 4, \ + "Provided Python callable doesn't accept expected parameter amount" + listener = ffi.new_handle(event_listener) + self._event_listener = listener + flag = lib.nrm_client_set_event_Pylistener(self._c_client, listener) def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) @@ -103,16 +105,21 @@ def start_event_listener(self, topic: str) -> int: # lib.nrm_client_start_event_Pylistener def set_actuate_listener(self, actuate_listener: Callable) -> int: - pass - # assert actuate_listener accepts 2 arguments? - # will call with: uuid, msg->event->value - # lib.nrm_client_set_actuate_Pylistener + assert len(inspect.signature(event_listener).parameters) == 2, \ + "Provided Python callable doesn't accept expected parameter amount" + listener = ffi.new_handle(actuate_listener) + self._actuate_listener = listener + flag = lib.nrm_client_set_actuate_Pylistener(self._c_client, listener) def start_actuate_listener(self) -> int: pass # lib.nrm_client_start_event_Pylistener -if __name__ == "__main__": - with Client() as nrmc: - pass +@ffi.def_extern() +def _event_listener_wrap(fn, sensor_uuid, time, scope, value): + return fn(sensor_uuid, time, scope, value) + +@ffi.def_extern() +def _actuate_listener_wrap(fn, uuid, value): + return fn(uuid, value) \ No newline at end of file From e38faa9f701a79c81b71a1468ff65f0ad72b4aef Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 3 Feb 2023 16:21:29 -0600 Subject: [PATCH 15/39] we can pass handles to the Client class through to C, where they can be passed back to Py to then envoke the callback as a class method. attempting to address cffi insisting that nrm_time_t is an opaque type --- nrm/api/build.py | 20 ++++++++++++++++---- nrm/api/client.py | 36 +++++++++++++++++++++++------------- tests/test_client.py | 3 +-- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 5c5ecb49..bb7d999a 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -6,12 +6,21 @@ "_build._nrm_cffi", """ #include "nrm.h" -""", + """, libraries=["nrm"], ) ffi.cdef( """ + +typedef int... time_t; + +typedef struct timespec{ + time_t tv_sec; + long tv_nsec; + ...; +}; + typedef struct nrm_client_s nrm_client_t; typedef struct nrm_actuator_s nrm_actuator_t; typedef struct nrm_slice_s nrm_slice_t; @@ -28,22 +37,25 @@ double value); typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, double value); +nrm_time_t nrm_time_fromns(int64_t ns); + // PY STUFF -extern "Python" int _event_listener_wrap(nrm_client_event_listener_fn *fn, +extern "Python" int _event_listener_wrap(void *pyclient, nrm_string_t sensor_uuid, - nrm_time_t time, nrm_scope_t *scope, double value); -extern "Python" int _actuate_listener_wrap(nrm_client_actuate_listener_fn *fn, +extern "Python" int _actuate_listener_wrap(void *pyclient, nrm_uuid_t uuid, double value); int nrm_client_set_event_Pylistener(nrm_client_t *client, + void *pyclient, nrm_client_event_listener_fn *fn); int nrm_client_set_actuate_Pylistener(nrm_client_t *client, + void *pyclient, nrm_client_actuate_listener_fn *fn); int nrm_client_start_event_Pylistener(const nrm_client_t *client, diff --git a/nrm/api/client.py b/nrm/api/client.py index fa53db29..df67c7c2 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -2,6 +2,7 @@ from typing import Union, List, Callable from dataclasses import dataclass, field import inspect +import time class _NRM_d(dict): @@ -82,9 +83,7 @@ def __exit__(self, exc_type, exc_value, traceback): def actuate(self, actuator: "Actuator", value: float) -> int: return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr, value) - def send_event( - self, sensor: "Sensor", scope: "Scope", value: float - ) -> int: + def send_event(self, sensor: "Sensor", scope: "Scope", value: float) -> int: timespec_p = ffi.new("nrm_time_t **") lib.nrm_time_gettime(timespec_p) timespec = timespec_p[0] @@ -95,9 +94,10 @@ def send_event( def set_event_listener(self, event_listener: Callable) -> int: assert len(inspect.signature(event_listener).parameters) == 4, \ "Provided Python callable doesn't accept expected parameter amount" - listener = ffi.new_handle(event_listener) - self._event_listener = listener - flag = lib.nrm_client_set_event_Pylistener(self._c_client, listener) + py_client = ffi.new_handle(self) + self.py_client = py_client + self._event_listener = event_listener + flag = lib.nrm_client_set_event_Pylistener(self._c_client, py_client, lib._event_listener_wrap) def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) @@ -107,19 +107,29 @@ def start_event_listener(self, topic: str) -> int: def set_actuate_listener(self, actuate_listener: Callable) -> int: assert len(inspect.signature(event_listener).parameters) == 2, \ "Provided Python callable doesn't accept expected parameter amount" - listener = ffi.new_handle(actuate_listener) - self._actuate_listener = listener - flag = lib.nrm_client_set_actuate_Pylistener(self._c_client, listener) + py_client = ffi.new_handle(self) + self.py_client = py_client + self._actuate_listener = actuate_listener + flag = lib.nrm_client_set_actuate_Pylistener(self._c_client, py_client, lib._actuate_listener_wrap) def start_actuate_listener(self) -> int: pass # lib.nrm_client_start_event_Pylistener + def _event(self, sensor_uuid, time, scope, value): + return self._event_listener(sensor_uuid, time, scope, value) + + def _actuate(self, uuid, value): + return self._actuate_listener(uuid, value) + @ffi.def_extern() -def _event_listener_wrap(fn, sensor_uuid, time, scope, value): - return fn(sensor_uuid, time, scope, value) +def _event_listener_wrap(py_client, sensor_uuid, scope, value): + timespec_p = ffi.new("nrm_time_t **") + lib.nrm_time_gettime(timespec_p) + timespec = timespec_p[0] + return ffi.from_handle(py_client)._event(sensor_uuid, timespec, scope, value) @ffi.def_extern() -def _actuate_listener_wrap(fn, uuid, value): - return fn(uuid, value) \ No newline at end of file +def _actuate_listener_wrap(py_client, uuid, value): + return ffi.from_handle(py_client)._actuate(uuid, value) \ No newline at end of file diff --git a/tests/test_client.py b/tests/test_client.py index 6298da4f..836e7c62 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -43,8 +43,7 @@ def test_send_event(): with Client() as nrmc: nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen - now = int(time.time()) - flag = nrmc.send_event(now, sen, sco, 1234) + flag = nrmc.send_event(sen, sco, 1234) # assert flag == 0, read log? From 1cf7c363bf0b97c2b902a1ecd654907f5010f365 Mon Sep 17 00:00:00 2001 From: jlnav Date: Wed, 8 Feb 2023 15:36:48 -0600 Subject: [PATCH 16/39] making callback wrappers match listener_fn signatures with pyclient passed through in *arg --- nrm/api/build.py | 21 ++++++++++++--------- nrm/api/client.py | 17 +++++------------ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index bb7d999a..12aa6799 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -18,7 +18,6 @@ typedef struct timespec{ time_t tv_sec; long tv_nsec; - ...; }; typedef struct nrm_client_s nrm_client_t; @@ -34,21 +33,25 @@ typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, nrm_time_t time, nrm_scope_t *scope, - double value); -typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, double value); + double value, + void *arg); +typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, + double value, + void *arg); nrm_time_t nrm_time_fromns(int64_t ns); // PY STUFF -extern "Python" int _event_listener_wrap(void *pyclient, - nrm_string_t sensor_uuid, +extern "Python" int _event_listener_wrap(nrm_string_t sensor_uuid, + nrm_time_t time, nrm_scope_t *scope, - double value); + double value, + void *pyclient); -extern "Python" int _actuate_listener_wrap(void *pyclient, - nrm_uuid_t uuid, - double value); +extern "Python" int _actuate_listener_wrap(nrm_uuid_t *uuid, + double value, + void *pyclient); int nrm_client_set_event_Pylistener(nrm_client_t *client, void *pyclient, diff --git a/nrm/api/client.py b/nrm/api/client.py index df67c7c2..4db87736 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -84,16 +84,12 @@ def actuate(self, actuator: "Actuator", value: float) -> int: return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr, value) def send_event(self, sensor: "Sensor", scope: "Scope", value: float) -> int: - timespec_p = ffi.new("nrm_time_t **") - lib.nrm_time_gettime(timespec_p) - timespec = timespec_p[0] + timespec = lib.nrm_time_fromns(time.time_ns()) return lib.nrm_client_send_event( self._c_client, timespec, sensor._sensor_ptr, scope._scope_ptr, value ) def set_event_listener(self, event_listener: Callable) -> int: - assert len(inspect.signature(event_listener).parameters) == 4, \ - "Provided Python callable doesn't accept expected parameter amount" py_client = ffi.new_handle(self) self.py_client = py_client self._event_listener = event_listener @@ -105,8 +101,6 @@ def start_event_listener(self, topic: str) -> int: # lib.nrm_client_start_event_Pylistener def set_actuate_listener(self, actuate_listener: Callable) -> int: - assert len(inspect.signature(event_listener).parameters) == 2, \ - "Provided Python callable doesn't accept expected parameter amount" py_client = ffi.new_handle(self) self.py_client = py_client self._actuate_listener = actuate_listener @@ -117,19 +111,18 @@ def start_actuate_listener(self) -> int: # lib.nrm_client_start_event_Pylistener def _event(self, sensor_uuid, time, scope, value): + print("GOT EVENT!") return self._event_listener(sensor_uuid, time, scope, value) def _actuate(self, uuid, value): + print("GOT ACTUATE") return self._actuate_listener(uuid, value) @ffi.def_extern() -def _event_listener_wrap(py_client, sensor_uuid, scope, value): - timespec_p = ffi.new("nrm_time_t **") - lib.nrm_time_gettime(timespec_p) - timespec = timespec_p[0] +def _event_listener_wrap(sensor_uuid, timespec, scope, value, py_client): return ffi.from_handle(py_client)._event(sensor_uuid, timespec, scope, value) @ffi.def_extern() -def _actuate_listener_wrap(py_client, uuid, value): +def _actuate_listener_wrap(uuid, value, py_client): return ffi.from_handle(py_client)._actuate(uuid, value) \ No newline at end of file From 413970942d4b411d7a6b2085d086460a1cf32581 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 9 Feb 2023 16:35:35 -0600 Subject: [PATCH 17/39] removing providing uuid on creation of most objects, name is all thats needed. adds set_choices and set_value to actuator --- nrm/api/actuator.py | 4 ++-- nrm/api/build.py | 6 ++++++ nrm/api/client.py | 11 ++++++++--- nrm/api/scope.py | 2 +- nrm/api/sensor.py | 2 +- nrm/api/slice.py | 2 +- tests/test_client.py | 32 +++++++++++++++++++++++--------- 7 files changed, 42 insertions(+), 17 deletions(-) diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py index c37dd2bf..efb371fc 100644 --- a/nrm/api/actuator.py +++ b/nrm/api/actuator.py @@ -9,14 +9,14 @@ class Actuator: from nrm import Actuator, Client with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - act = Actuator(name="hello-act", uuid="abcd1234") + act = Actuator(name="hello-act") nrmc.actuators.append(act) ``` """ - def __init__(self, name: str = "nrm-actuator", uuid: str = "default-uuid"): + def __init__(self, name: str = "nrm-actuator"): self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) self._actuator_ptr = lib.nrm_actuator_create( self._c_actuator_name diff --git a/nrm/api/build.py b/nrm/api/build.py index 12aa6799..449c7887 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -126,6 +126,12 @@ void nrm_client_destroy(nrm_client_t **client); +int nrm_actuator_set_value(nrm_actuator_t *actuator, double value); + +int nrm_actuator_set_choices(nrm_actuator_t *actuator, + size_t nchoices, + double *choices); + """ ) diff --git a/nrm/api/client.py b/nrm/api/client.py index 4db87736..8151fc2b 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -93,7 +93,9 @@ def set_event_listener(self, event_listener: Callable) -> int: py_client = ffi.new_handle(self) self.py_client = py_client self._event_listener = event_listener - flag = lib.nrm_client_set_event_Pylistener(self._c_client, py_client, lib._event_listener_wrap) + flag = lib.nrm_client_set_event_Pylistener( + self._c_client, py_client, lib._event_listener_wrap + ) def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) @@ -104,7 +106,9 @@ def set_actuate_listener(self, actuate_listener: Callable) -> int: py_client = ffi.new_handle(self) self.py_client = py_client self._actuate_listener = actuate_listener - flag = lib.nrm_client_set_actuate_Pylistener(self._c_client, py_client, lib._actuate_listener_wrap) + flag = lib.nrm_client_set_actuate_Pylistener( + self._c_client, py_client, lib._actuate_listener_wrap + ) def start_actuate_listener(self) -> int: pass @@ -123,6 +127,7 @@ def _actuate(self, uuid, value): def _event_listener_wrap(sensor_uuid, timespec, scope, value, py_client): return ffi.from_handle(py_client)._event(sensor_uuid, timespec, scope, value) + @ffi.def_extern() def _actuate_listener_wrap(uuid, value, py_client): - return ffi.from_handle(py_client)._actuate(uuid, value) \ No newline at end of file + return ffi.from_handle(py_client)._actuate(uuid, value) diff --git a/nrm/api/scope.py b/nrm/api/scope.py index 8a6fc38a..b915352a 100644 --- a/nrm/api/scope.py +++ b/nrm/api/scope.py @@ -5,7 +5,7 @@ class Scope: """Scope class for interacting with NRM C interface. Prototyped interface for scope below.""" - def __init__(self, name: str = "nrm-scope", uuid: str = "default-uuid"): + def __init__(self, name: str = "nrm-scope"): self._c_scope_name = ffi.new("char[]", bytes(name, "utf-8")) self._scope_ptr = lib.nrm_scope_create( self._c_scope_name diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py index 21745243..34c8301f 100644 --- a/nrm/api/sensor.py +++ b/nrm/api/sensor.py @@ -17,7 +17,7 @@ class Sensor: ``` """ - def __init__(self, name: str = "nrm-sensor", uuid: str = "default-uuid"): + def __init__(self, name: str = "nrm-sensor"): self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) self._sensor_ptr = lib.nrm_sensor_create( self._c_sensor_name diff --git a/nrm/api/slice.py b/nrm/api/slice.py index d08ee64b..d1e9ba16 100644 --- a/nrm/api/slice.py +++ b/nrm/api/slice.py @@ -18,7 +18,7 @@ class Slice: ``` """ - def __init__(self, name: str = "nrm-slice", uuid: str = "default-uuid"): + def __init__(self, name: str = "nrm-slice"): self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) self._slice_ptr = lib.nrm_slice_create( self._c_slice_name diff --git a/tests/test_client.py b/tests/test_client.py index 836e7c62..e2943537 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -9,16 +9,17 @@ def test_client_init(): + print("test_client_init") with Client() as nrmc: pass def test_set_objs_to_client(): - - act = Actuator("nrm-test-actuator", act_uuid) - sco = Scope("nrm-test-scope", sco_uuid) - sen = Sensor("nrm-test-sensor", sen_uuid) - sli = Slice("nrm-test-slice", sli_uuid) + print("test_set_objs_to_client") + act = Actuator("nrm-test-actuator") + sco = Scope("nrm-test-scope") + sen = Sensor("nrm-test-sensor") + sli = Slice("nrm-test-slice") # assert names, pointers, objects are instantiated underneath for each with Client() as nrmc: @@ -30,16 +31,20 @@ def test_set_objs_to_client(): def test_actuate(): - act = Actuator("nrm-test-actuator", act_uuid) + print("test_actuate") + act = Actuator("nrm-test-actuator") + act.set_choices(12.0, 123.0, 1234.0, 12345.0) + act.set_value(1234.0) with Client() as nrmc: nrmc.actuators[act_uuid] = act - flag = nrmc.actuate(act, 1234) + flag = nrmc.actuate(act, 123.0) # assert flag == 0, read log? def test_send_event(): - sco = Scope("nrm-test-scope", sco_uuid) - sen = Sensor("nrm-test-sensor", sen_uuid) + print("test_send_event") + sco = Scope("nrm-test-scope") + sen = Sensor("nrm-test-sensor") with Client() as nrmc: nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen @@ -48,12 +53,15 @@ def test_send_event(): def test_event_callbacks(): + print("test_event_callbacks") def print_event_info(*args): print("Responding to subscribed event") uuid, time, scope, value = args print(uuid, time, scope, value) + sco = Scope("nrm-test-scope") with Client() as nrmc: + nrmc.scopes[sco_uuid] = sco flag = nrmc.set_event_listener(print_event_info) # check if pyfn has made it into client struct? flag = nrmc.start_event_listener("test-report-numa-pwr") @@ -61,12 +69,18 @@ def print_event_info(*args): def test_actuate_callbacks(): + print("test_actuate_callbacks") def print_actuate_info(*args): print("Responding to actuation request") uuid, value = args print(uuid, value) + + act = Actuator("nrm-test-actuator") + act.set_choices(12.0, 123.0, 1234.0, 12345.0) + act.set_value(1234.0) with Client() as nrmc: + nrmc.actuators[act_uuid] = act flag = nrmc.set_actuate_listener(print_actuate_info) # check if pyfn has made it into client struct? flag = nrmc.start_actuate_listener() From 6646b076664e94e9a6c23b75e8244acb318db565 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 10 Feb 2023 13:41:17 -0600 Subject: [PATCH 18/39] implement start_event and start_actuate on the frontend, small fixes --- nrm/api/actuator.py | 6 ++++++ nrm/api/build.py | 4 ++-- nrm/api/client.py | 18 +++++++++--------- tests/test_client.py | 26 +++++++++----------------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py index efb371fc..67afb1f2 100644 --- a/nrm/api/actuator.py +++ b/nrm/api/actuator.py @@ -24,3 +24,9 @@ def __init__(self, name: str = "nrm-actuator"): def __delitem__(self, key): lib.nrm_actuator_destroy(self._actuator_ptr) + + def set_choices(self, *cargs) -> int: + return lib.nrm_actuator_set_choices(self._actuator_ptr, len(cargs), list(cargs)) + + def set_value(self, value: float) -> int: + return lib.nrm_actuator_set_value(self._actuator_ptr, value) diff --git a/nrm/api/build.py b/nrm/api/build.py index 449c7887..aad04d83 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -61,10 +61,10 @@ void *pyclient, nrm_client_actuate_listener_fn *fn); -int nrm_client_start_event_Pylistener(const nrm_client_t *client, +int nrm_client_start_event_Pylistener(nrm_client_t *client, nrm_string_t topic); -int nrm_client_start_actuate_Pylistener(const nrm_client_t *client); +int nrm_client_start_actuate_Pylistener(nrm_client_t *client); // END PY STUFF diff --git a/nrm/api/client.py b/nrm/api/client.py index 8151fc2b..d72ed04c 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,7 +1,6 @@ from nrm.api._build._nrm_cffi import ffi, lib from typing import Union, List, Callable from dataclasses import dataclass, field -import inspect import time @@ -93,41 +92,42 @@ def set_event_listener(self, event_listener: Callable) -> int: py_client = ffi.new_handle(self) self.py_client = py_client self._event_listener = event_listener - flag = lib.nrm_client_set_event_Pylistener( + return lib.nrm_client_set_event_Pylistener( self._c_client, py_client, lib._event_listener_wrap ) def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) - # lib.nrm_client_start_event_Pylistener + return lib.nrm_client_start_event_Pylistener(self._c_client, topic) def set_actuate_listener(self, actuate_listener: Callable) -> int: py_client = ffi.new_handle(self) self.py_client = py_client self._actuate_listener = actuate_listener - flag = lib.nrm_client_set_actuate_Pylistener( + return lib.nrm_client_set_actuate_Pylistener( self._c_client, py_client, lib._actuate_listener_wrap ) def start_actuate_listener(self) -> int: - pass - # lib.nrm_client_start_event_Pylistener + return lib.nrm_client_start_actuate_Pylistener(self._c_client) def _event(self, sensor_uuid, time, scope, value): - print("GOT EVENT!") + print("GOT EVENT!", flush=True) return self._event_listener(sensor_uuid, time, scope, value) def _actuate(self, uuid, value): - print("GOT ACTUATE") + print("GOT ACTUATE", flush=True) return self._actuate_listener(uuid, value) @ffi.def_extern() -def _event_listener_wrap(sensor_uuid, timespec, scope, value, py_client): +def _event_listener_wrap(sensor_uuid, timespec, scope, value, py_client): # see build.py for the C declaration of this and _actuate_listener_wrap + print("HELLO", flush=True) return ffi.from_handle(py_client)._event(sensor_uuid, timespec, scope, value) @ffi.def_extern() def _actuate_listener_wrap(uuid, value, py_client): + print("WORLD", flush=True) return ffi.from_handle(py_client)._actuate(uuid, value) diff --git a/tests/test_client.py b/tests/test_client.py index e2943537..ab6c9502 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -20,25 +20,22 @@ def test_set_objs_to_client(): sco = Scope("nrm-test-scope") sen = Sensor("nrm-test-sensor") sli = Slice("nrm-test-slice") - # assert names, pointers, objects are instantiated underneath for each with Client() as nrmc: nrmc.actuators[act_uuid] = act nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen nrmc.slices[sli_uuid] = sli - # assert both py and C client contains new objects def test_actuate(): print("test_actuate") act = Actuator("nrm-test-actuator") - act.set_choices(12.0, 123.0, 1234.0, 12345.0) - act.set_value(1234.0) + assert not act.set_choices(12.0, 123.0, 1234.0, 12345.0) + assert not act.set_value(1234.0) with Client() as nrmc: nrmc.actuators[act_uuid] = act flag = nrmc.actuate(act, 123.0) - # assert flag == 0, read log? def test_send_event(): @@ -48,8 +45,7 @@ def test_send_event(): with Client() as nrmc: nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen - flag = nrmc.send_event(sen, sco, 1234) - # assert flag == 0, read log? + assert not nrmc.send_event(sen, sco, 1234) def test_event_callbacks(): @@ -62,10 +58,8 @@ def print_event_info(*args): sco = Scope("nrm-test-scope") with Client() as nrmc: nrmc.scopes[sco_uuid] = sco - flag = nrmc.set_event_listener(print_event_info) - # check if pyfn has made it into client struct? - flag = nrmc.start_event_listener("test-report-numa-pwr") - # check logs? + assert not nrmc.set_event_listener(print_event_info) + assert not nrmc.start_event_listener("test-report-numa-pwr") def test_actuate_callbacks(): @@ -77,14 +71,12 @@ def print_actuate_info(*args): act = Actuator("nrm-test-actuator") - act.set_choices(12.0, 123.0, 1234.0, 12345.0) - act.set_value(1234.0) + assert not act.set_choices(12.0, 123.0, 1234.0, 12345.0) + assert not act.set_value(1234.0) with Client() as nrmc: nrmc.actuators[act_uuid] = act - flag = nrmc.set_actuate_listener(print_actuate_info) - # check if pyfn has made it into client struct? - flag = nrmc.start_actuate_listener() - # check logs? + assert not nrmc.set_actuate_listener(print_actuate_info) + assert not nrmc.start_actuate_listener() if __name__ == "__main__": From 5adc2564d03d969bc26617aea129b1ca6639791c Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 10 Feb 2023 13:57:01 -0600 Subject: [PATCH 19/39] adding event and actuate to callback tests --- tests/test_client.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_client.py b/tests/test_client.py index ab6c9502..f2c5b92f 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -35,7 +35,7 @@ def test_actuate(): assert not act.set_value(1234.0) with Client() as nrmc: nrmc.actuators[act_uuid] = act - flag = nrmc.actuate(act, 123.0) + assert not nrmc.actuate(act, 123.0) def test_send_event(): @@ -56,10 +56,14 @@ def print_event_info(*args): print(uuid, time, scope, value) sco = Scope("nrm-test-scope") + sen = Sensor("test-report-numa-pwr") with Client() as nrmc: nrmc.scopes[sco_uuid] = sco + nrmc.sensors[sen_uuid] = sen assert not nrmc.set_event_listener(print_event_info) assert not nrmc.start_event_listener("test-report-numa-pwr") + assert not nrmc.send_event(sen, sco, 1234) + time.sleep(0.25) def test_actuate_callbacks(): @@ -77,6 +81,8 @@ def print_actuate_info(*args): nrmc.actuators[act_uuid] = act assert not nrmc.set_actuate_listener(print_actuate_info) assert not nrmc.start_actuate_listener() + assert not nrmc.actuate(act, 123.0) + time.sleep(0.25) if __name__ == "__main__": From d6533b2bdf72193887911b86aabf925be1809a97 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 10 Feb 2023 15:08:59 -0600 Subject: [PATCH 20/39] on py frontend, using normal start_listener's --- nrm/api/build.py | 5 ----- nrm/api/client.py | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index aad04d83..498ca487 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -61,11 +61,6 @@ void *pyclient, nrm_client_actuate_listener_fn *fn); -int nrm_client_start_event_Pylistener(nrm_client_t *client, - nrm_string_t topic); - -int nrm_client_start_actuate_Pylistener(nrm_client_t *client); - // END PY STUFF int nrm_init(int *argc, char **argv[]); diff --git a/nrm/api/client.py b/nrm/api/client.py index d72ed04c..99037d0f 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -99,7 +99,7 @@ def set_event_listener(self, event_listener: Callable) -> int: def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) - return lib.nrm_client_start_event_Pylistener(self._c_client, topic) + return lib.nrm_client_start_event_listener(self._c_client, topic) def set_actuate_listener(self, actuate_listener: Callable) -> int: py_client = ffi.new_handle(self) @@ -110,7 +110,7 @@ def set_actuate_listener(self, actuate_listener: Callable) -> int: ) def start_actuate_listener(self) -> int: - return lib.nrm_client_start_actuate_Pylistener(self._c_client) + return lib.nrm_client_start_actuate_listener(self._c_client) def _event(self, sensor_uuid, time, scope, value): print("GOT EVENT!", flush=True) From ec7a3e8f8a79103fa044c59ae5cc4e3b97506a30 Mon Sep 17 00:00:00 2001 From: jlnav Date: Mon, 13 Feb 2023 14:23:30 -0600 Subject: [PATCH 21/39] create pyinfo struct, passing through pyclient handle and cffi externs for storage --- nrm/api/build.py | 32 ++++++++++++++++++++++++-------- nrm/api/client.py | 33 ++++++++++++++++----------------- tests/test_client.py | 23 ++++++++++++++--------- 3 files changed, 54 insertions(+), 34 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 498ca487..d5d783ff 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -29,6 +29,7 @@ typedef char *nrm_string_t; typedef struct timespec nrm_time_t; typedef nrm_string_t nrm_uuid_t; +typedef struct pyinfo_s pyinfo_t; typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, nrm_time_t time, @@ -47,19 +48,32 @@ nrm_time_t time, nrm_scope_t *scope, double value, - void *pyclient); + void *arg); extern "Python" int _actuate_listener_wrap(nrm_uuid_t *uuid, double value, - void *pyclient); + void *arg); + +int nrm_client_externpython_event(nrm_string_t sensor_uuid, + nrm_time_t time, + nrm_scope_t *scope, + double value, + void *arg); + +int nrm_client_externpython_actuate(nrm_uuid_t *uuid, + double value, + void *arg); int nrm_client_set_event_Pylistener(nrm_client_t *client, - void *pyclient, - nrm_client_event_listener_fn *fn); + void *pyinfo); int nrm_client_set_actuate_Pylistener(nrm_client_t *client, - void *pyclient, - nrm_client_actuate_listener_fn *fn); + void *pyinfo); + +int nrm_pyinfo_create(pyinfo_t **pyinfo, + void *pyclient, + nrm_client_event_listener_fn *extern_user_fn, + nrm_client_actuate_listener_fn *extern_actuate_fn); // END PY STUFF @@ -109,13 +123,15 @@ double value); int nrm_client_set_event_listener(nrm_client_t *client, - nrm_client_event_listener_fn fn); + nrm_client_event_listener_fn *fn, + void *arg); int nrm_client_start_event_listener(const nrm_client_t *client, nrm_string_t topic); int nrm_client_set_actuate_listener(nrm_client_t *client, - nrm_client_actuate_listener_fn fn); + nrm_client_actuate_listener_fn *fn, + void *arg); int nrm_client_start_actuate_listener(const nrm_client_t *client); diff --git a/nrm/api/client.py b/nrm/api/client.py index 99037d0f..20d041b3 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -62,14 +62,23 @@ def __enter__( self, uri: str = "tcp://127.0.0.1", pub_port: int = 2345, rpc_port: int = 3456 ): self._c_client_p = ffi.new("nrm_client_t **") + self._pyinfo_p = ffi.new("pyinfo_t **") + self._py_client = ffi.new_handle(self) self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) self.pub_port = pub_port self.rpc_port = rpc_port - flag = lib.nrm_init(ffi.NULL, ffi.NULL) - flag = lib.nrm_client_create( + assert not lib.nrm_init(ffi.NULL, ffi.NULL) + assert not lib.nrm_client_create( self._c_client_p, self._c_uri, self.pub_port, self.rpc_port ) self._c_client = self._c_client_p[0] + assert not lib.nrm_pyinfo_create( + self._pyinfo_p, + self._py_client, + lib._event_listener_wrap, + lib._actuate_listener_wrap, + ) + self._pyinfo = self._pyinfo_p[0] for d in [self.scopes, self.sensors, self.slices, self.actuators]: d._set_client(self._c_client) @@ -89,12 +98,8 @@ def send_event(self, sensor: "Sensor", scope: "Scope", value: float) -> int: ) def set_event_listener(self, event_listener: Callable) -> int: - py_client = ffi.new_handle(self) - self.py_client = py_client self._event_listener = event_listener - return lib.nrm_client_set_event_Pylistener( - self._c_client, py_client, lib._event_listener_wrap - ) + return lib.nrm_client_set_event_Pylistener(self._c_client, self._pyinfo) def start_event_listener(self, topic: str) -> int: topic = ffi.new("char []", bytes(topic, "utf-8")) @@ -102,32 +107,26 @@ def start_event_listener(self, topic: str) -> int: return lib.nrm_client_start_event_listener(self._c_client, topic) def set_actuate_listener(self, actuate_listener: Callable) -> int: - py_client = ffi.new_handle(self) - self.py_client = py_client self._actuate_listener = actuate_listener - return lib.nrm_client_set_actuate_Pylistener( - self._c_client, py_client, lib._actuate_listener_wrap - ) + return lib.nrm_client_set_actuate_Pylistener(self._c_client, self._pyinfo) def start_actuate_listener(self) -> int: return lib.nrm_client_start_actuate_listener(self._c_client) def _event(self, sensor_uuid, time, scope, value): - print("GOT EVENT!", flush=True) return self._event_listener(sensor_uuid, time, scope, value) def _actuate(self, uuid, value): - print("GOT ACTUATE", flush=True) return self._actuate_listener(uuid, value) @ffi.def_extern() -def _event_listener_wrap(sensor_uuid, timespec, scope, value, py_client): # see build.py for the C declaration of this and _actuate_listener_wrap - print("HELLO", flush=True) +def _event_listener_wrap( + sensor_uuid, timespec, scope, value, py_client +): # see build.py for the C declaration of this and _actuate_listener_wrap return ffi.from_handle(py_client)._event(sensor_uuid, timespec, scope, value) @ffi.def_extern() def _actuate_listener_wrap(uuid, value, py_client): - print("WORLD", flush=True) return ffi.from_handle(py_client)._actuate(uuid, value) diff --git a/tests/test_client.py b/tests/test_client.py index f2c5b92f..9840dd18 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -50,10 +50,10 @@ def test_send_event(): def test_event_callbacks(): print("test_event_callbacks") + def print_event_info(*args): - print("Responding to subscribed event") - uuid, time, scope, value = args - print(uuid, time, scope, value) + print("IN EVENT PYTHON CALLBACK: Responding to subscribed event") + return 0 sco = Scope("nrm-test-scope") sen = Sensor("test-report-numa-pwr") @@ -63,16 +63,18 @@ def print_event_info(*args): assert not nrmc.set_event_listener(print_event_info) assert not nrmc.start_event_listener("test-report-numa-pwr") assert not nrmc.send_event(sen, sco, 1234) - time.sleep(0.25) + time.sleep(2) + assert not nrmc.send_event(sen, sco, 12) + time.sleep(2) + assert not nrmc.send_event(sen, sco, 1) def test_actuate_callbacks(): print("test_actuate_callbacks") - def print_actuate_info(*args): - print("Responding to actuation request") - uuid, value = args - print(uuid, value) + def print_actuate_info(*args): + print("IN PYTHON ACTUATE CALLBACK: Responding to actuation request") + return 0 act = Actuator("nrm-test-actuator") assert not act.set_choices(12.0, 123.0, 1234.0, 12345.0) @@ -82,7 +84,10 @@ def print_actuate_info(*args): assert not nrmc.set_actuate_listener(print_actuate_info) assert not nrmc.start_actuate_listener() assert not nrmc.actuate(act, 123.0) - time.sleep(0.25) + time.sleep(2) + assert not nrmc.actuate(act, 12345.0) + time.sleep(2) + assert not nrmc.actuate(act, 12.0) if __name__ == "__main__": From fc9385add45c443f1c74ac89e5102ed313f50040 Mon Sep 17 00:00:00 2001 From: jlnav Date: Mon, 13 Feb 2023 16:13:54 -0600 Subject: [PATCH 22/39] initial round of cleaning up, documenting --- nrm/api/__init__.py | 7 +-- nrm/api/actuator.py | 32 ----------- nrm/api/client.py | 119 ++++++++++++++++++++++---------------- nrm/api/components.py | 129 ++++++++++++++++++++++++++++++++++++++++++ nrm/api/scope.py | 15 ----- nrm/api/sensor.py | 27 --------- nrm/api/slice.py | 28 --------- setup.py | 2 +- tests/test_client.py | 7 +-- 9 files changed, 206 insertions(+), 160 deletions(-) delete mode 100644 nrm/api/actuator.py create mode 100644 nrm/api/components.py delete mode 100644 nrm/api/scope.py delete mode 100644 nrm/api/sensor.py delete mode 100644 nrm/api/slice.py diff --git a/nrm/api/__init__.py b/nrm/api/__init__.py index a13419b0..9455df56 100644 --- a/nrm/api/__init__.py +++ b/nrm/api/__init__.py @@ -1,5 +1,5 @@ ############################################################################### -# Copyright 2019 UChicago Argonne, LLC. +# Copyright 2023 UChicago Argonne, LLC. # (c.f. AUTHORS, LICENSE) # # This file is part of the NRM project. @@ -8,8 +8,5 @@ # SPDX-License-Identifier: BSD-3-Clause ############################################################################### -from .actuator import Actuator +from .components import Actuator, Scope, Sensor, Slice from .client import Client -from .scope import Scope -from .sensor import Sensor -from .slice import Slice diff --git a/nrm/api/actuator.py b/nrm/api/actuator.py deleted file mode 100644 index 67afb1f2..00000000 --- a/nrm/api/actuator.py +++ /dev/null @@ -1,32 +0,0 @@ -from nrm.api._build._nrm_cffi import ffi, lib -from typing import Union, List, Callable - - -class Actuator: - """Actuator class for interacting with NRM C interface. Prototyped interface for client below. - Tentative usage: - ``` - from nrm import Actuator, Client - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - - act = Actuator(name="hello-act") - nrmc.actuators.append(act) - - - ``` - """ - - def __init__(self, name: str = "nrm-actuator"): - self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) - self._actuator_ptr = lib.nrm_actuator_create( - self._c_actuator_name - ) # intantiate a pointer? - - def __delitem__(self, key): - lib.nrm_actuator_destroy(self._actuator_ptr) - - def set_choices(self, *cargs) -> int: - return lib.nrm_actuator_set_choices(self._actuator_ptr, len(cargs), list(cargs)) - - def set_value(self, value: float) -> int: - return lib.nrm_actuator_set_value(self._actuator_ptr, value) diff --git a/nrm/api/client.py b/nrm/api/client.py index 20d041b3..134cd249 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -1,122 +1,143 @@ -from nrm.api._build._nrm_cffi import ffi, lib -from typing import Union, List, Callable -from dataclasses import dataclass, field import time +from loguru import logger +from dataclasses import dataclass, field +from typing import Callable, List, Union - -class _NRM_d(dict): - def __init__(self, *args): - dict.__init__(self, args) - - def _set_client(self, client): - self._c_client = client - - -class _NRMScopes(_NRM_d): - def __setitem__(self, uuid_key: str, nrm_object: "Scope"): - super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_scope(self._c_client, nrm_object._scope_ptr) - - -class _NRMSensors(_NRM_d): - def __setitem__(self, uuid_key: str, nrm_object: "Sensor"): - super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_sensor(self._c_client, nrm_object._sensor_ptr) - - -class _NRMSlices(_NRM_d): - def __setitem__(self, uuid_key: str, nrm_object: "Slice"): - super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_slice(self._c_client, nrm_object._slice_ptr) - - -class _NRMActuators(_NRM_d): - def __setitem__(self, uuid_key: str, nrm_object: "Actuator"): - super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_actuator(self._c_client, nrm_object._actuator_ptr) +from nrm.api._build._nrm_cffi import ffi, lib +from nrm.api.components import NRMActuators, NRMScopes, NRMSensors, NRMSlices @dataclass class Client: - """Client class for interacting with NRM C interface. Prototyped interface for client below. + """Client class for interacting with NRM C interface. Use as a context switcher. Tentative usage: ``` - from nrm import Client, Actuator + from nrm.api import Client, Actuator with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: ... nrmc.scopes["uuid"] = my_scope ... - nrmc.send_event(get_time(), sensor, scope, 1234) + nrmc.send_event(sensor, scope, 1234) ... ``` """ - scopes: _NRMScopes = field(default_factory=_NRMScopes) - sensors: _NRMSensors = field(default_factory=_NRMSensors) - slices: _NRMSlices = field(default_factory=_NRMSlices) - actuators: _NRMActuators = field(default_factory=_NRMActuators) + scopes: _NRMScopes = field(default_factory=NRMScopes) + sensors: _NRMSensors = field(default_factory=NRMSensors) + slices: _NRMSlices = field(default_factory=NRMSlices) + actuators: _NRMActuators = field(default_factory=NRMActuators) def __enter__( self, uri: str = "tcp://127.0.0.1", pub_port: int = 2345, rpc_port: int = 3456 ): self._c_client_p = ffi.new("nrm_client_t **") - self._pyinfo_p = ffi.new("pyinfo_t **") - self._py_client = ffi.new_handle(self) self._c_uri = ffi.new("char[]", bytes(uri, "utf-8")) + self._pyinfo_p = ffi.new("pyinfo_t **") + self._py_client_h = ffi.new_handle(self) self.pub_port = pub_port self.rpc_port = rpc_port - assert not lib.nrm_init(ffi.NULL, ffi.NULL) + + assert not lib.nrm_init(ffi.NULL, ffi.NULL), \ + "NRM library did not initialize successfully" + logger.debug("NRM initialized") + assert not lib.nrm_client_create( self._c_client_p, self._c_uri, self.pub_port, self.rpc_port - ) + ), "Python Client was unable to instantiate an underlying NRM C client" + logger.debug("NRM client created") self._c_client = self._c_client_p[0] + assert not lib.nrm_pyinfo_create( self._pyinfo_p, - self._py_client, + self._py_client_h, lib._event_listener_wrap, lib._actuate_listener_wrap, - ) + ), "Python Client was unable to instantiate an underlying NRM C structure" + logger.debug("C pyinfo structure populated") self._pyinfo = self._pyinfo_p[0] for d in [self.scopes, self.sensors, self.slices, self.actuators]: d._set_client(self._c_client) - + logger.debug("NRM client assigned to Scopes, Sensors, Slices, and Actuators dict subclasses") + logger.info("Client instance initialized. Starting") return self def __exit__(self, exc_type, exc_value, traceback): + logger.info("Destroying Client instance") lib.nrm_client_destroy(self._c_client_p) def actuate(self, actuator: "Actuator", value: float) -> int: + """Perform an actuation given an actuator and a value to set. Register this actuator + with the client first: + ``` + from nrm.api import Client, Actuator + act = Actuator("my-actuator") + act.set_choices(1.0, 2.0, 3.0, 4.0) + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + ``` + NOTE: The given value should've already been set with `actuator_instance.set_values()`. + + Parameters + ---------- + """ + logger.debug(f"ACTUATING with (actuator: {actuator}), (value: {value})") return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr, value) def send_event(self, sensor: "Sensor", scope: "Scope", value: float) -> int: + """ + Parameters + ---------- + """ timespec = lib.nrm_time_fromns(time.time_ns()) + logger.debug(f"SENDING EVENT with (sensor: {sensor}), (value: {value}), (Value: {value})") return lib.nrm_client_send_event( self._c_client, timespec, sensor._sensor_ptr, scope._scope_ptr, value ) def set_event_listener(self, event_listener: Callable) -> int: + """ + Parameters + ---------- + """ self._event_listener = event_listener + logger.debug(f"Setting event Python callback: {event_listener}") return lib.nrm_client_set_event_Pylistener(self._c_client, self._pyinfo) def start_event_listener(self, topic: str) -> int: + """ + Parameters + ---------- + """ topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) + logger.debug(f"Starting event listener. Will call: {self._event_listener}") return lib.nrm_client_start_event_listener(self._c_client, topic) def set_actuate_listener(self, actuate_listener: Callable) -> int: + """ + Parameters + ---------- + """ self._actuate_listener = actuate_listener + logger.debug(f"Setting actuate Python callback: {actuate_listener}") return lib.nrm_client_set_actuate_Pylistener(self._c_client, self._pyinfo) def start_actuate_listener(self) -> int: + """ + Returns + ------- + """ + logger.debug(f"Starting actuate listener. Will call: {self._actuate_listener}") return lib.nrm_client_start_actuate_listener(self._c_client) def _event(self, sensor_uuid, time, scope, value): + logger.debug(f"Calling event callback: {self._event_listener}") return self._event_listener(sensor_uuid, time, scope, value) def _actuate(self, uuid, value): + logger.debug(f"Calling actuate callback: {self._actuate_listener}") return self._actuate_listener(uuid, value) @@ -124,9 +145,11 @@ def _actuate(self, uuid, value): def _event_listener_wrap( sensor_uuid, timespec, scope, value, py_client ): # see build.py for the C declaration of this and _actuate_listener_wrap + logger.debug("In event extern wrapper. Unpacking client") return ffi.from_handle(py_client)._event(sensor_uuid, timespec, scope, value) @ffi.def_extern() def _actuate_listener_wrap(uuid, value, py_client): + logger.debug("In actuate extern wrapper. Unpacking client") return ffi.from_handle(py_client)._actuate(uuid, value) diff --git a/nrm/api/components.py b/nrm/api/components.py new file mode 100644 index 00000000..6d0996fe --- /dev/null +++ b/nrm/api/components.py @@ -0,0 +1,129 @@ +from typing import Callable, List, Union + +from nrm.api._build._nrm_cffi import ffi, lib + + +class Actuator: + """Actuator class for interacting with NRM C interface. Prototyped interface for client below. + Tentative usage: + ``` + from nrm import Actuator, Client + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + + act = Actuator(name="hello-act") + nrmc.actuators.append(act) + + + ``` + """ + + def __init__(self, name: str = "nrm-actuator"): + self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) + self._actuator_ptr = lib.nrm_actuator_create( + self._c_actuator_name + ) # intantiate a pointer? + + def __delitem__(self, key): + lib.nrm_actuator_destroy(self._actuator_ptr) + + def set_choices(self, *cargs) -> int: + return lib.nrm_actuator_set_choices(self._actuator_ptr, len(cargs), list(cargs)) + + def set_value(self, value: float) -> int: + return lib.nrm_actuator_set_value(self._actuator_ptr, value) + + +class Scope: + """Scope class for interacting with NRM C interface. Prototyped interface for scope below.""" + + def __init__(self, name: str = "nrm-scope"): + self._c_scope_name = ffi.new("char[]", bytes(name, "utf-8")) + self._scope_ptr = lib.nrm_scope_create( + self._c_scope_name + ) # intantiate a pointer? + + def __delitem__(self): + lib.nrm_actuator_destroy(self._actuator_ptr) + + +class Sensor: + """Sensor class for interacting with NRM C interface. Prototyped interface for client below. + Tentative usage: + ``` + from nrm import Sensor, Actuator + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + ... + nrmc.sensors["abc123"] = my_sensor + ... + nrmc.send_event(get_time(), sensor, scope, 1234) + ... + + ``` + """ + + def __init__(self, name: str = "nrm-sensor"): + self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) + self._sensor_ptr = lib.nrm_sensor_create( + self._c_sensor_name + ) # intantiate a pointer? + + def __delitem__(self): + lib.nrm_sensor_destroy(self._sensor_ptr) + + +class Slice: + """Slice class for interacting with NRM C interface. Prototyped interface for client below. + Tentative usage: + ``` + from nrm import Client, Actuator + with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: + ... + my_slice = Slice("nrm-slice", "abc123) + nrmc.slices["uuid"] = my_slice + + ... + nrmc.send_event(get_time(), sensor, scope, 1234) + ... + ``` + """ + + def __init__(self, name: str = "nrm-slice"): + self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) + self._slice_ptr = lib.nrm_slice_create( + self._c_slice_name + ) # intantiate a pointer? + + def __delitem__(self, key): + lib.nrm_slice_destroy(self._slice_ptr) + + +class _NRM_d(dict): + def __init__(self, *args): + dict.__init__(self, args) + + def _set_client(self, client): + self._c_client = client + + +class NRMScopes(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Scope"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_scope(self._c_client, nrm_object._scope_ptr) + + +class NRMSensors(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Sensor"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_sensor(self._c_client, nrm_object._sensor_ptr) + + +class NRMSlices(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Slice"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_slice(self._c_client, nrm_object._slice_ptr) + + +class NRMActuators(_NRM_d): + def __setitem__(self, uuid_key: str, nrm_object: "Actuator"): + super().__setitem__(uuid_key, nrm_object) + return lib.nrm_client_add_actuator(self._c_client, nrm_object._actuator_ptr) \ No newline at end of file diff --git a/nrm/api/scope.py b/nrm/api/scope.py deleted file mode 100644 index b915352a..00000000 --- a/nrm/api/scope.py +++ /dev/null @@ -1,15 +0,0 @@ -from nrm.api._build._nrm_cffi import ffi, lib -from typing import Union, List, Callable - - -class Scope: - """Scope class for interacting with NRM C interface. Prototyped interface for scope below.""" - - def __init__(self, name: str = "nrm-scope"): - self._c_scope_name = ffi.new("char[]", bytes(name, "utf-8")) - self._scope_ptr = lib.nrm_scope_create( - self._c_scope_name - ) # intantiate a pointer? - - def __delitem__(self): - lib.nrm_actuator_destroy(self._actuator_ptr) diff --git a/nrm/api/sensor.py b/nrm/api/sensor.py deleted file mode 100644 index 34c8301f..00000000 --- a/nrm/api/sensor.py +++ /dev/null @@ -1,27 +0,0 @@ -from nrm.api._build._nrm_cffi import ffi, lib -from typing import Union, List, Callable - - -class Sensor: - """Sensor class for interacting with NRM C interface. Prototyped interface for client below. - Tentative usage: - ``` - from nrm import Sensor, Actuator - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - ... - nrmc.sensors["abc123"] = my_sensor - ... - nrmc.send_event(get_time(), sensor, scope, 1234) - ... - - ``` - """ - - def __init__(self, name: str = "nrm-sensor"): - self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) - self._sensor_ptr = lib.nrm_sensor_create( - self._c_sensor_name - ) # intantiate a pointer? - - def __delitem__(self): - lib.nrm_sensor_destroy(self._sensor_ptr) diff --git a/nrm/api/slice.py b/nrm/api/slice.py deleted file mode 100644 index d1e9ba16..00000000 --- a/nrm/api/slice.py +++ /dev/null @@ -1,28 +0,0 @@ -from nrm.api._build._nrm_cffi import ffi, lib -from typing import Union, List, Callable - - -class Slice: - """Slice class for interacting with NRM C interface. Prototyped interface for client below. - Tentative usage: - ``` - from nrm import Client, Actuator - with Client("tcp://127.0.0.1", 2345, 3456) as nrmc: - ... - my_slice = Slice("nrm-slice", "abc123) - nrmc.slices["uuid"] = my_slice - - ... - nrmc.send_event(get_time(), sensor, scope, 1234) - ... - ``` - """ - - def __init__(self, name: str = "nrm-slice"): - self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) - self._slice_ptr = lib.nrm_slice_create( - self._c_slice_name - ) # intantiate a pointer? - - def __delitem__(self, key): - lib.nrm_slice_destroy(self._slice_ptr) diff --git a/setup.py b/setup.py index b74b9103..0d90ac73 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ ], packages=find_packages(), - install_requires=['msgpack', 'pyyaml', "warlock", "pyzmq", "tornado", "jsonschema"], + install_requires=['msgpack', 'pyyaml', "warlock", "pyzmq", "tornado", "jsonschema", "loguru", "cffi"], package_data={'nrm': ['schemas/*.json', 'schemas/*.yml']}, scripts=['bin/nrmd'] ) diff --git a/tests/test_client.py b/tests/test_client.py index 9840dd18..e98e29cb 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -50,7 +50,6 @@ def test_send_event(): def test_event_callbacks(): print("test_event_callbacks") - def print_event_info(*args): print("IN EVENT PYTHON CALLBACK: Responding to subscribed event") return 0 @@ -68,10 +67,8 @@ def print_event_info(*args): time.sleep(2) assert not nrmc.send_event(sen, sco, 1) - def test_actuate_callbacks(): print("test_actuate_callbacks") - def print_actuate_info(*args): print("IN PYTHON ACTUATE CALLBACK: Responding to actuation request") return 0 @@ -88,7 +85,9 @@ def print_actuate_info(*args): assert not nrmc.actuate(act, 12345.0) time.sleep(2) assert not nrmc.actuate(act, 12.0) - + time.sleep(2) + assert not act.set_value(123.0) + time.sleep(2) if __name__ == "__main__": test_client_init() From f10653b9011fd219425ab7829420508a9f8bcd62 Mon Sep 17 00:00:00 2001 From: jlnav Date: Mon, 13 Feb 2023 16:27:44 -0600 Subject: [PATCH 23/39] fix --- nrm/api/client.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nrm/api/client.py b/nrm/api/client.py index 134cd249..e0149782 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -24,10 +24,10 @@ class Client: ``` """ - scopes: _NRMScopes = field(default_factory=NRMScopes) - sensors: _NRMSensors = field(default_factory=NRMSensors) - slices: _NRMSlices = field(default_factory=NRMSlices) - actuators: _NRMActuators = field(default_factory=NRMActuators) + scopes: NRMScopes = field(default_factory=NRMScopes) + sensors: NRMSensors = field(default_factory=NRMSensors) + slices: NRMSlices = field(default_factory=NRMSlices) + actuators: NRMActuators = field(default_factory=NRMActuators) def __enter__( self, uri: str = "tcp://127.0.0.1", pub_port: int = 2345, rpc_port: int = 3456 From 3b4751c29e47407e50cef82732898822e1ca2d99 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 17 Feb 2023 16:55:06 -0600 Subject: [PATCH 24/39] tentatively creating close methods for each component. need to determine how to pass double-pointers to destructors --- nrm/api/build.py | 8 ++++++++ nrm/api/client.py | 21 ++++++++++++++++++++- nrm/api/components.py | 28 +++++++++++++++++++--------- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index d5d783ff..7a536da5 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -143,6 +143,14 @@ size_t nchoices, double *choices); +void nrm_actuator_destroy(nrm_actuator_t **); + +int nrm_scope_destroy(nrm_scope_t *scope); + +void nrm_slice_destroy(nrm_slice_t **); + +void nrm_sensor_destroy(nrm_sensor_t **); + """ ) diff --git a/nrm/api/client.py b/nrm/api/client.py index e0149782..5499f6a1 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -81,6 +81,9 @@ def actuate(self, actuator: "Actuator", value: float) -> int: Parameters ---------- + + Returns + ------- """ logger.debug(f"ACTUATING with (actuator: {actuator}), (value: {value})") return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr, value) @@ -89,9 +92,12 @@ def send_event(self, sensor: "Sensor", scope: "Scope", value: float) -> int: """ Parameters ---------- + + Returns + ------- """ timespec = lib.nrm_time_fromns(time.time_ns()) - logger.debug(f"SENDING EVENT with (sensor: {sensor}), (value: {value}), (Value: {value})") + logger.debug(f"SENDING EVENT with (Sensor: {sensor}), (Scope: {scope}), (Value: {value})") return lib.nrm_client_send_event( self._c_client, timespec, sensor._sensor_ptr, scope._scope_ptr, value ) @@ -100,6 +106,9 @@ def set_event_listener(self, event_listener: Callable) -> int: """ Parameters ---------- + + Returns + ------- """ self._event_listener = event_listener logger.debug(f"Setting event Python callback: {event_listener}") @@ -109,6 +118,9 @@ def start_event_listener(self, topic: str) -> int: """ Parameters ---------- + + Returns + ------- """ topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) @@ -119,6 +131,9 @@ def set_actuate_listener(self, actuate_listener: Callable) -> int: """ Parameters ---------- + + Returns + ------- """ self._actuate_listener = actuate_listener logger.debug(f"Setting actuate Python callback: {actuate_listener}") @@ -132,6 +147,10 @@ def start_actuate_listener(self) -> int: logger.debug(f"Starting actuate listener. Will call: {self._actuate_listener}") return lib.nrm_client_start_actuate_listener(self._c_client) + def _remove(self, obj_type: int, uuid: str) -> int: + # TODO: create nrm_string_t out of uuid + return lib.nrm_client_remove(self._c_client, obj_type, nrm_string_t_uuid) + def _event(self, sensor_uuid, time, scope, value): logger.debug(f"Calling event callback: {self._event_listener}") return self._event_listener(sensor_uuid, time, scope, value) diff --git a/nrm/api/components.py b/nrm/api/components.py index 6d0996fe..d712ca08 100644 --- a/nrm/api/components.py +++ b/nrm/api/components.py @@ -1,4 +1,5 @@ from typing import Callable, List, Union +from loguru import logger from nrm.api._build._nrm_cffi import ffi, lib @@ -21,11 +22,14 @@ def __init__(self, name: str = "nrm-actuator"): self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) self._actuator_ptr = lib.nrm_actuator_create( self._c_actuator_name - ) # intantiate a pointer? + ) - def __delitem__(self, key): + def __del__(self): lib.nrm_actuator_destroy(self._actuator_ptr) + def close(self) -> int: + return lib.nrm_actuator_destroy(self._actuator_ptr) + def set_choices(self, *cargs) -> int: return lib.nrm_actuator_set_choices(self._actuator_ptr, len(cargs), list(cargs)) @@ -40,11 +44,13 @@ def __init__(self, name: str = "nrm-scope"): self._c_scope_name = ffi.new("char[]", bytes(name, "utf-8")) self._scope_ptr = lib.nrm_scope_create( self._c_scope_name - ) # intantiate a pointer? + ) - def __delitem__(self): - lib.nrm_actuator_destroy(self._actuator_ptr) + def __del__(self): + lib.nrm_scope_destroy(self._scope_ptr) + def close(self) -> int: + return lib.nrm_scope_destroy(self._scope_ptr) class Sensor: """Sensor class for interacting with NRM C interface. Prototyped interface for client below. @@ -65,11 +71,13 @@ def __init__(self, name: str = "nrm-sensor"): self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) self._sensor_ptr = lib.nrm_sensor_create( self._c_sensor_name - ) # intantiate a pointer? + ) - def __delitem__(self): + def __del__(self): lib.nrm_sensor_destroy(self._sensor_ptr) + def close(self) -> int: + return lib.nrm_sensor_destroy(self._sensor_ptr) class Slice: """Slice class for interacting with NRM C interface. Prototyped interface for client below. @@ -91,11 +99,13 @@ def __init__(self, name: str = "nrm-slice"): self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) self._slice_ptr = lib.nrm_slice_create( self._c_slice_name - ) # intantiate a pointer? + ) - def __delitem__(self, key): + def __del__(self): lib.nrm_slice_destroy(self._slice_ptr) + def close(self) -> int: + return lib.nrm_slice_destroy(self._slice_ptr) class _NRM_d(dict): def __init__(self, *args): From 4a56b884033283e3380ae2abcf9b48b094aa0c8d Mon Sep 17 00:00:00 2001 From: jlnav Date: Tue, 21 Feb 2023 14:38:01 -0600 Subject: [PATCH 25/39] tentative changes for correct component destruction, adding client.remove() --- nrm/api/client.py | 37 ++++++++++----------------- nrm/api/components.py | 58 +++++++++++++++++++++++-------------------- tests/test_client.py | 22 +++++++++++----- 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/nrm/api/client.py b/nrm/api/client.py index 5499f6a1..010d035d 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -39,8 +39,9 @@ def __enter__( self.pub_port = pub_port self.rpc_port = rpc_port - assert not lib.nrm_init(ffi.NULL, ffi.NULL), \ - "NRM library did not initialize successfully" + assert not lib.nrm_init( + ffi.NULL, ffi.NULL + ), "NRM library did not initialize successfully" logger.debug("NRM initialized") assert not lib.nrm_client_create( @@ -60,7 +61,9 @@ def __enter__( for d in [self.scopes, self.sensors, self.slices, self.actuators]: d._set_client(self._c_client) - logger.debug("NRM client assigned to Scopes, Sensors, Slices, and Actuators dict subclasses") + logger.debug( + "NRM client assigned to Scopes, Sensors, Slices, and Actuators dict subclasses" + ) logger.info("Client instance initialized. Starting") return self @@ -81,34 +84,27 @@ def actuate(self, actuator: "Actuator", value: float) -> int: Parameters ---------- - - Returns - ------- """ logger.debug(f"ACTUATING with (actuator: {actuator}), (value: {value})") - return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr, value) + return lib.nrm_client_actuate(self._c_client, actuator._actuator_ptr[0], value) def send_event(self, sensor: "Sensor", scope: "Scope", value: float) -> int: """ Parameters ---------- - - Returns - ------- """ timespec = lib.nrm_time_fromns(time.time_ns()) - logger.debug(f"SENDING EVENT with (Sensor: {sensor}), (Scope: {scope}), (Value: {value})") + logger.debug( + f"SENDING EVENT with (sensor: {sensor}), (value: {value}), (Value: {value})" + ) return lib.nrm_client_send_event( - self._c_client, timespec, sensor._sensor_ptr, scope._scope_ptr, value + self._c_client, timespec, sensor._sensor_ptr[0], scope._scope_ptr, value ) def set_event_listener(self, event_listener: Callable) -> int: """ Parameters ---------- - - Returns - ------- """ self._event_listener = event_listener logger.debug(f"Setting event Python callback: {event_listener}") @@ -118,9 +114,6 @@ def start_event_listener(self, topic: str) -> int: """ Parameters ---------- - - Returns - ------- """ topic = ffi.new("char []", bytes(topic, "utf-8")) topic_as_nrm_string_t = ffi.new("nrm_string_t *", topic) @@ -131,9 +124,6 @@ def set_actuate_listener(self, actuate_listener: Callable) -> int: """ Parameters ---------- - - Returns - ------- """ self._actuate_listener = actuate_listener logger.debug(f"Setting actuate Python callback: {actuate_listener}") @@ -147,9 +137,8 @@ def start_actuate_listener(self) -> int: logger.debug(f"Starting actuate listener. Will call: {self._actuate_listener}") return lib.nrm_client_start_actuate_listener(self._c_client) - def _remove(self, obj_type: int, uuid: str) -> int: - # TODO: create nrm_string_t out of uuid - return lib.nrm_client_remove(self._c_client, obj_type, nrm_string_t_uuid) + def remove(self, obj) -> int: + return lib.nrm_client_remove(self._c_client, obj.TYPE, obj._c_name) def _event(self, sensor_uuid, time, scope, value): logger.debug(f"Calling event callback: {self._event_listener}") diff --git a/nrm/api/components.py b/nrm/api/components.py index d712ca08..dd7307ac 100644 --- a/nrm/api/components.py +++ b/nrm/api/components.py @@ -19,32 +19,33 @@ class Actuator: """ def __init__(self, name: str = "nrm-actuator"): - self._c_actuator_name = ffi.new("char[]", bytes(name, "utf-8")) - self._actuator_ptr = lib.nrm_actuator_create( - self._c_actuator_name - ) + self.TYPE = 3 + self._actuator_ptr = ffi.new("nrm_actuator_t **") + self._c_name = ffi.new("char[]", bytes(name, "utf-8")) + self._actuator_ptr[0] = lib.nrm_actuator_create(self._c_name) def __del__(self): lib.nrm_actuator_destroy(self._actuator_ptr) - def close(self) -> int: - return lib.nrm_actuator_destroy(self._actuator_ptr) + def close(self): + lib.nrm_actuator_destroy(self._actuator_ptr) def set_choices(self, *cargs) -> int: - return lib.nrm_actuator_set_choices(self._actuator_ptr, len(cargs), list(cargs)) + return lib.nrm_actuator_set_choices( + self._actuator_ptr[0], len(cargs), list(cargs) + ) def set_value(self, value: float) -> int: - return lib.nrm_actuator_set_value(self._actuator_ptr, value) + return lib.nrm_actuator_set_value(self._actuator_ptr[0], value) class Scope: """Scope class for interacting with NRM C interface. Prototyped interface for scope below.""" def __init__(self, name: str = "nrm-scope"): - self._c_scope_name = ffi.new("char[]", bytes(name, "utf-8")) - self._scope_ptr = lib.nrm_scope_create( - self._c_scope_name - ) + self.TYPE = 2 + self._c_name = ffi.new("char[]", bytes(name, "utf-8")) + self._scope_ptr = lib.nrm_scope_create(self._c_name) def __del__(self): lib.nrm_scope_destroy(self._scope_ptr) @@ -52,6 +53,7 @@ def __del__(self): def close(self) -> int: return lib.nrm_scope_destroy(self._scope_ptr) + class Sensor: """Sensor class for interacting with NRM C interface. Prototyped interface for client below. Tentative usage: @@ -68,16 +70,17 @@ class Sensor: """ def __init__(self, name: str = "nrm-sensor"): - self._c_sensor_name = ffi.new("char[]", bytes(name, "utf-8")) - self._sensor_ptr = lib.nrm_sensor_create( - self._c_sensor_name - ) + self.TYPE = 1 + self._sensor_ptr = ffi.new("nrm_sensor_t **") + self._c_name = ffi.new("char[]", bytes(name, "utf-8")) + self._sensor_ptr[0] = lib.nrm_sensor_create(self._c_name) def __del__(self): lib.nrm_sensor_destroy(self._sensor_ptr) - def close(self) -> int: - return lib.nrm_sensor_destroy(self._sensor_ptr) + def close(self): + lib.nrm_sensor_destroy(self._sensor_ptr) + class Slice: """Slice class for interacting with NRM C interface. Prototyped interface for client below. @@ -96,16 +99,17 @@ class Slice: """ def __init__(self, name: str = "nrm-slice"): - self._c_slice_name = ffi.new("char[]", bytes(name, "utf-8")) - self._slice_ptr = lib.nrm_slice_create( - self._c_slice_name - ) + self.TYPE = 0 + self._slice_ptr = ffi.new("nrm_slice_t **") + self._c_name = ffi.new("char[]", bytes(name, "utf-8")) + self._slice_ptr[0] = lib.nrm_slice_create(self._c_name) def __del__(self): lib.nrm_slice_destroy(self._slice_ptr) - def close(self) -> int: - return lib.nrm_slice_destroy(self._slice_ptr) + def close(self): + lib.nrm_slice_destroy(self._slice_ptr) + class _NRM_d(dict): def __init__(self, *args): @@ -124,16 +128,16 @@ def __setitem__(self, uuid_key: str, nrm_object: "Scope"): class NRMSensors(_NRM_d): def __setitem__(self, uuid_key: str, nrm_object: "Sensor"): super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_sensor(self._c_client, nrm_object._sensor_ptr) + return lib.nrm_client_add_sensor(self._c_client, nrm_object._sensor_ptr[0]) class NRMSlices(_NRM_d): def __setitem__(self, uuid_key: str, nrm_object: "Slice"): super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_slice(self._c_client, nrm_object._slice_ptr) + return lib.nrm_client_add_slice(self._c_client, nrm_object._slice_ptr[0]) class NRMActuators(_NRM_d): def __setitem__(self, uuid_key: str, nrm_object: "Actuator"): super().__setitem__(uuid_key, nrm_object) - return lib.nrm_client_add_actuator(self._c_client, nrm_object._actuator_ptr) \ No newline at end of file + return lib.nrm_client_add_actuator(self._c_client, nrm_object._actuator_ptr[0]) diff --git a/tests/test_client.py b/tests/test_client.py index e98e29cb..1311d3f3 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -26,6 +26,8 @@ def test_set_objs_to_client(): nrmc.scopes[sco_uuid] = sco nrmc.sensors[sen_uuid] = sen nrmc.slices[sli_uuid] = sli + nrmc.remove(act) + act.close() def test_actuate(): @@ -36,6 +38,8 @@ def test_actuate(): with Client() as nrmc: nrmc.actuators[act_uuid] = act assert not nrmc.actuate(act, 123.0) + nrmc.remove(act) + act.close() def test_send_event(): @@ -50,6 +54,7 @@ def test_send_event(): def test_event_callbacks(): print("test_event_callbacks") + def print_event_info(*args): print("IN EVENT PYTHON CALLBACK: Responding to subscribed event") return 0 @@ -62,13 +67,15 @@ def print_event_info(*args): assert not nrmc.set_event_listener(print_event_info) assert not nrmc.start_event_listener("test-report-numa-pwr") assert not nrmc.send_event(sen, sco, 1234) - time.sleep(2) + time.sleep(1) assert not nrmc.send_event(sen, sco, 12) - time.sleep(2) + time.sleep(1) assert not nrmc.send_event(sen, sco, 1) + def test_actuate_callbacks(): print("test_actuate_callbacks") + def print_actuate_info(*args): print("IN PYTHON ACTUATE CALLBACK: Responding to actuation request") return 0 @@ -81,13 +88,16 @@ def print_actuate_info(*args): assert not nrmc.set_actuate_listener(print_actuate_info) assert not nrmc.start_actuate_listener() assert not nrmc.actuate(act, 123.0) - time.sleep(2) + time.sleep(1) assert not nrmc.actuate(act, 12345.0) - time.sleep(2) + time.sleep(1) assert not nrmc.actuate(act, 12.0) - time.sleep(2) + time.sleep(1) assert not act.set_value(123.0) - time.sleep(2) + time.sleep(1) + nrmc.remove(act) + act.close() + if __name__ == "__main__": test_client_init() From 5b915b4d80cded213e8ce0589c9f7c9002d591e8 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 23 Feb 2023 16:05:39 -0600 Subject: [PATCH 26/39] bringing api inline with recent libnrm update --- nrm/api/build.py | 11 +++++++++-- nrm/api/client.py | 21 +++++++++++++++++++-- nrm/api/components.py | 4 ---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 7a536da5..6e98ac0b 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -114,8 +114,6 @@ const char *uuid, nrm_vector_t **results); -int nrm_client_remove(const nrm_client_t *client, int type, nrm_string_t uuid); - int nrm_client_send_event(const nrm_client_t *client, nrm_time_t time, nrm_sensor_t *sensor, @@ -151,6 +149,15 @@ void nrm_sensor_destroy(nrm_sensor_t **); +int nrm_client_remove_actuator(const nrm_client_t *client, + nrm_actuator_t *actuator); + +int nrm_client_remove_slice(const nrm_client_t *client, nrm_slice_t *slice); + +int nrm_client_remove_sensor(const nrm_client_t *client, nrm_sensor_t *sensor); + +int nrm_client_remove_scope(const nrm_client_t *client, nrm_scope_t *scope); + """ ) diff --git a/nrm/api/client.py b/nrm/api/client.py index 010d035d..4be0621b 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -4,7 +4,16 @@ from typing import Callable, List, Union from nrm.api._build._nrm_cffi import ffi, lib -from nrm.api.components import NRMActuators, NRMScopes, NRMSensors, NRMSlices +from nrm.api.components import ( + NRMActuators, + NRMScopes, + NRMSensors, + NRMSlices, + Actuator, + Scope, + Sensor, + Slice, +) @dataclass @@ -138,7 +147,15 @@ def start_actuate_listener(self) -> int: return lib.nrm_client_start_actuate_listener(self._c_client) def remove(self, obj) -> int: - return lib.nrm_client_remove(self._c_client, obj.TYPE, obj._c_name) + + if isinstance(obj, Actuator): + return lib.nrm_client_remove_actuator(self._c_client, obj._actuator_ptr[0]) + elif isinstance(obj, Slice): + return lib.nrm_client_remove_slice(self._c_client, obj._slice_ptr[0]) + elif isinstance(obj, Sensor): + return lib.nrm_client_remove_sensor(self._c_client, obj._sensor_ptr[0]) + else: + return lib.nrm_client_remove_scope(self._c_client, obj._scope_ptr) def _event(self, sensor_uuid, time, scope, value): logger.debug(f"Calling event callback: {self._event_listener}") diff --git a/nrm/api/components.py b/nrm/api/components.py index dd7307ac..56cc2693 100644 --- a/nrm/api/components.py +++ b/nrm/api/components.py @@ -19,7 +19,6 @@ class Actuator: """ def __init__(self, name: str = "nrm-actuator"): - self.TYPE = 3 self._actuator_ptr = ffi.new("nrm_actuator_t **") self._c_name = ffi.new("char[]", bytes(name, "utf-8")) self._actuator_ptr[0] = lib.nrm_actuator_create(self._c_name) @@ -43,7 +42,6 @@ class Scope: """Scope class for interacting with NRM C interface. Prototyped interface for scope below.""" def __init__(self, name: str = "nrm-scope"): - self.TYPE = 2 self._c_name = ffi.new("char[]", bytes(name, "utf-8")) self._scope_ptr = lib.nrm_scope_create(self._c_name) @@ -70,7 +68,6 @@ class Sensor: """ def __init__(self, name: str = "nrm-sensor"): - self.TYPE = 1 self._sensor_ptr = ffi.new("nrm_sensor_t **") self._c_name = ffi.new("char[]", bytes(name, "utf-8")) self._sensor_ptr[0] = lib.nrm_sensor_create(self._c_name) @@ -99,7 +96,6 @@ class Slice: """ def __init__(self, name: str = "nrm-slice"): - self.TYPE = 0 self._slice_ptr = ffi.new("nrm_slice_t **") self._c_name = ffi.new("char[]", bytes(name, "utf-8")) self._slice_ptr[0] = lib.nrm_slice_create(self._c_name) From 048b53be4cebb6e649efea16b25d17b2c83aea34 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 23 Feb 2023 16:20:43 -0600 Subject: [PATCH 27/39] tentative changes for setup.py integration --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index 0d90ac73..802b313b 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,8 @@ ], packages=find_packages(), + setup_requires=["cffi"], + cffi_modules=["nrm/api/build.py:ffi"], install_requires=['msgpack', 'pyyaml', "warlock", "pyzmq", "tornado", "jsonschema", "loguru", "cffi"], package_data={'nrm': ['schemas/*.json', 'schemas/*.yml']}, scripts=['bin/nrmd'] From a6100805c79c0ea6ce5d50ee514376e50acd7078 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 23 Feb 2023 16:24:31 -0600 Subject: [PATCH 28/39] fix path --- nrm/api/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 6e98ac0b..70aa80ab 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -3,7 +3,7 @@ ffi = FFI() ffi.set_source( - "_build._nrm_cffi", + "nrm.api._build._nrm_cffi", """ #include "nrm.h" """, From 4849a20d6243c4c3e2d2c48b8c90780035c5febb Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 24 Feb 2023 15:03:29 -0600 Subject: [PATCH 29/39] add _build dir --- nrm/api/_build/__init__.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 nrm/api/_build/__init__.py diff --git a/nrm/api/_build/__init__.py b/nrm/api/_build/__init__.py new file mode 100644 index 00000000..e5433105 --- /dev/null +++ b/nrm/api/_build/__init__.py @@ -0,0 +1,9 @@ +############################################################################### +# Copyright 2019 UChicago Argonne, LLC. +# (c.f. AUTHORS, LICENSE) +# +# This file is part of the NRM project. +# For more info, see https://github.com/anlsys/nrm-python +# +# SPDX-License-Identifier: BSD-3-Clause +############################################################################### From f1bb2b74b316e5770b1643c4763d55b51cfb87a7 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 12 Oct 2023 13:02:19 -0500 Subject: [PATCH 30/39] updates to build.py to match nrm.h --- nrm/api/build.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 70aa80ab..adda98f5 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -96,42 +96,46 @@ int pub_port, int rpc_port); -int nrm_client_actuate(const nrm_client_t *client, +int nrm_client_actuate(nrm_client_t *client, nrm_actuator_t *actuator, double value); -int nrm_client_add_actuator(const nrm_client_t *client, +int nrm_client_add_actuator(nrm_client_t *client, nrm_actuator_t *actuator); -int nrm_client_add_scope(const nrm_client_t *client, nrm_scope_t *scope); +int nrm_client_add_scope(nrm_client_t *client, nrm_scope_t *scope); -int nrm_client_add_sensor(const nrm_client_t *client, nrm_sensor_t *sensor); +int nrm_client_add_sensor(nrm_client_t *client, nrm_sensor_t *sensor); -int nrm_client_add_slice(const nrm_client_t *client, nrm_slice_t *slice); +int nrm_client_add_slice(nrm_client_t *client, nrm_slice_t *slice); -int nrm_client_find(const nrm_client_t *client, +int nrm_client_find(nrm_client_t *client, int type, const char *uuid, nrm_vector_t **results); -int nrm_client_send_event(const nrm_client_t *client, +int nrm_client_send_event(nrm_client_t *client, nrm_time_t time, nrm_sensor_t *sensor, nrm_scope_t *scope, double value); +int nrm_client_send_exit(nrm_client_t *client); + +int nrm_client_send_tick(nrm_client_t *client); + int nrm_client_set_event_listener(nrm_client_t *client, nrm_client_event_listener_fn *fn, void *arg); -int nrm_client_start_event_listener(const nrm_client_t *client, +int nrm_client_start_event_listener(nrm_client_t *client, nrm_string_t topic); int nrm_client_set_actuate_listener(nrm_client_t *client, nrm_client_actuate_listener_fn *fn, void *arg); -int nrm_client_start_actuate_listener(const nrm_client_t *client); +int nrm_client_start_actuate_listener(nrm_client_t *client); void nrm_client_destroy(nrm_client_t **client); @@ -149,14 +153,14 @@ void nrm_sensor_destroy(nrm_sensor_t **); -int nrm_client_remove_actuator(const nrm_client_t *client, +int nrm_client_remove_actuator(nrm_client_t *client, nrm_actuator_t *actuator); -int nrm_client_remove_slice(const nrm_client_t *client, nrm_slice_t *slice); +int nrm_client_remove_slice(nrm_client_t *client, nrm_slice_t *slice); -int nrm_client_remove_sensor(const nrm_client_t *client, nrm_sensor_t *sensor); +int nrm_client_remove_sensor(nrm_client_t *client, nrm_sensor_t *sensor); -int nrm_client_remove_scope(const nrm_client_t *client, nrm_scope_t *scope); +int nrm_client_remove_scope(nrm_client_t *client, nrm_scope_t *scope); """ ) From e8eafc870b860934ff57d437644b249c99e5415c Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 12 Oct 2023 13:03:42 -0500 Subject: [PATCH 31/39] tiny fix --- nrm/api/build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index adda98f5..af5a0cab 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -96,7 +96,7 @@ int pub_port, int rpc_port); -int nrm_client_actuate(nrm_client_t *client, +int nrm_client_actuate(const nrm_client_t *client, nrm_actuator_t *actuator, double value); From 90f47cb05b81098fdeaae4535d495a7205ecbd53 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 12 Oct 2023 13:10:19 -0500 Subject: [PATCH 32/39] tentatively complete send_exit and send_tick --- nrm/api/client.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nrm/api/client.py b/nrm/api/client.py index 4be0621b..952c75bc 100644 --- a/nrm/api/client.py +++ b/nrm/api/client.py @@ -157,6 +157,14 @@ def remove(self, obj) -> int: else: return lib.nrm_client_remove_scope(self._c_client, obj._scope_ptr) + def send_exit(self) -> int: + logger.debug("Sending daemon EXIT request") + return lib.nrm_client_send_exit(self._c_client) + + def send_tick(self) -> int: + logger.debug("Sending daemon TICK request") + return lib.nrm_client_send_tick(self._c_client) + def _event(self, sensor_uuid, time, scope, value): logger.debug(f"Calling event callback: {self._event_listener}") return self._event_listener(sensor_uuid, time, scope, value) From 268b51b9dc60c1af9ef62b3a58133742c73ec528 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 13 Oct 2023 13:39:42 -0500 Subject: [PATCH 33/39] removing a bunch of old config files, small adjust to build.py, removing old nrmd --- bin/nrmd | 24 - nrm/api/build.py | 2 +- nrm/schemas/downstreamEvent.json | 345 ------- resources/defaults/manifest.json | 7 - resources/defaults/manifest.yml | 4 - resources/defaults/nrmd.json | 35 - resources/defaults/nrmd.yml | 23 - resources/schemas/downstream.json | 258 ------ resources/schemas/upstream-pub.json | 1111 ---------------------- resources/schemas/upstream-rep.json | 1316 --------------------------- resources/schemas/upstream-req.json | 277 ------ 11 files changed, 1 insertion(+), 3401 deletions(-) delete mode 100755 bin/nrmd delete mode 100644 nrm/schemas/downstreamEvent.json delete mode 100644 resources/defaults/manifest.json delete mode 100644 resources/defaults/manifest.yml delete mode 100644 resources/defaults/nrmd.json delete mode 100644 resources/defaults/nrmd.yml delete mode 100644 resources/schemas/downstream.json delete mode 100644 resources/schemas/upstream-pub.json delete mode 100644 resources/schemas/upstream-rep.json delete mode 100644 resources/schemas/upstream-req.json diff --git a/bin/nrmd b/bin/nrmd deleted file mode 100755 index 94aef68d..00000000 --- a/bin/nrmd +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -############################################################################### -# Copyright 2019 UChicago Argonne, LLC. -# (c.f. AUTHORS, LICENSE) -# -# This file is part of the NRM project. -# For more info, see https://github.com/anlsys/nrm-python -# -# SPDX-License-Identifier: BSD-3-Clause -############################################################################### - -import sys -from nrm.sharedlib import WrapEither, Lib -import nrm.daemon -import os -from ctypes.util import find_library - -nrmcoreso = find_library("nrm-core") -if not nrmcoreso: - nrmcoreso = os.environ.get("NRMSO") - -with Lib(nrmcoreso) as lib: - cfg = lib.cli(sys.argv[1:]) - nrm.daemon.runner(cfg, lib) diff --git a/nrm/api/build.py b/nrm/api/build.py index af5a0cab..adda98f5 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -96,7 +96,7 @@ int pub_port, int rpc_port); -int nrm_client_actuate(const nrm_client_t *client, +int nrm_client_actuate(nrm_client_t *client, nrm_actuator_t *actuator, double value); diff --git a/nrm/schemas/downstreamEvent.json b/nrm/schemas/downstreamEvent.json deleted file mode 100644 index 8afb4f44..00000000 --- a/nrm/schemas/downstreamEvent.json +++ /dev/null @@ -1,345 +0,0 @@ -{ - "required": [ - "timestamp", - "info" - ], - "type": "object", - "properties": { - "timestamp": { - "type": "number" - }, - "info": { - "oneOf": [ - { - "required": [ - "cmdPerformance" - ], - "type": "object", - "properties": { - "cmdPerformance": { - "required": [ - "cmdID", - "perf" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "perf": { - "type": "number" - } - } - } - } - }, - { - "required": [ - "cmdPause" - ], - "type": "object", - "properties": { - "cmdPause": { - "required": [ - "cmdID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - } - } - } - } - }, - { - "required": [ - "threadProgress" - ], - "type": "object", - "properties": { - "threadProgress": { - "required": [ - "downstreamThreadID", - "scopes", - "progress" - ], - "type": "object", - "properties": { - "progress": { - "type": "number" - }, - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - }, - "scopes": { - "required": [ - "cpu", - "node", - "gpu" - ], - "type": "object", - "properties": { - "cpu": { - "type": "array", - "items": { - "type": "number" - } - }, - "node": { - "type": "array", - "items": { - "type": "number" - } - }, - "gpu": { - "type": "array", - "items": { - "type": "number" - } - } - } - } - } - } - } - }, - { - "required": [ - "threadPause" - ], - "type": "object", - "properties": { - "threadPause": { - "required": [ - "downstreamThreadID" - ], - "type": "object", - "properties": { - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - } - } - } - } - }, - { - "required": [ - "threadPhaseContext" - ], - "type": "object", - "properties": { - "threadPhaseContext": { - "required": [ - "downstreamThreadID", - "scopes", - "phaseContext" - ], - "type": "object", - "properties": { - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - }, - "scopes": { - "required": [ - "cpu", - "node", - "gpu" - ], - "type": "object", - "properties": { - "cpu": { - "type": "array", - "items": { - "type": "number" - } - }, - "node": { - "type": "array", - "items": { - "type": "number" - } - }, - "gpu": { - "type": "array", - "items": { - "type": "number" - } - } - } - }, - "phaseContext": { - "required": [ - "cpu", - "aggregation", - "computetime", - "totaltime" - ], - "type": "object", - "properties": { - "computetime": { - "type": "number" - }, - "aggregation": { - "type": "number" - }, - "totaltime": { - "type": "number" - }, - "cpu": { - "type": "number" - } - } - } - } - } - } - }, - { - "required": [ - "threadPhasePause" - ], - "type": "object", - "properties": { - "threadPhasePause": { - "required": [ - "downstreamThreadID", - "scopes" - ], - "type": "object", - "properties": { - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - }, - "scopes": { - "required": [ - "cpu", - "node", - "gpu" - ], - "type": "object", - "properties": { - "cpu": { - "type": "array", - "items": { - "type": "number" - } - }, - "node": { - "type": "array", - "items": { - "type": "number" - } - }, - "gpu": { - "type": "array", - "items": { - "type": "number" - } - } - } - } - } - } - } - } - ] - } - } -} diff --git a/resources/defaults/manifest.json b/resources/defaults/manifest.json deleted file mode 100644 index 81cbbdc7..00000000 --- a/resources/defaults/manifest.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "app": { - "instrumentation": null, - "perfwrapper": null - }, - "name": "default" -} \ No newline at end of file diff --git a/resources/defaults/manifest.yml b/resources/defaults/manifest.yml deleted file mode 100644 index 16ec122d..00000000 --- a/resources/defaults/manifest.yml +++ /dev/null @@ -1,4 +0,0 @@ -app: - instrumentation: - perfwrapper: -name: default diff --git a/resources/defaults/nrmd.json b/resources/defaults/nrmd.json deleted file mode 100644 index c41d7217..00000000 --- a/resources/defaults/nrmd.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "extraStaticPassiveSensors": [], - "perfPath": "perf", - "verbose": "Error", - "logfile": "/tmp/nrm.log", - "controlCfg": "ControlOff", - "upstreamCfg": { - "upstreamBindAddress": "*", - "rpcPort": 3456, - "pubPort": 2345 - }, - "libnrmPath": null, - "downstreamCfg": { - "downstreamBindAddress": "ipc:///tmp/nrm-downstream-event" - }, - "perfwrapperPath": "nrm-perfwrapper", - "extraStaticActuators": [], - "raplCfg": { - "referencePower": { - "microwatts": 250000000 - }, - "raplActions": [ - { - "microwatts": 100000000 - }, - { - "microwatts": 200000000 - } - ], - "raplPath": "/sys/devices/virtual/powercap/intel-rapl" - }, - "passiveSensorFrequency": { - "hertz": 1 - } -} \ No newline at end of file diff --git a/resources/defaults/nrmd.yml b/resources/defaults/nrmd.yml deleted file mode 100644 index cfdc8933..00000000 --- a/resources/defaults/nrmd.yml +++ /dev/null @@ -1,23 +0,0 @@ -extraStaticPassiveSensors: [] -perfPath: perf -verbose: Error -logfile: "/tmp/nrm.log" -controlCfg: ControlOff -upstreamCfg: - upstreamBindAddress: "*" - rpcPort: 3456 - pubPort: 2345 -libnrmPath: -downstreamCfg: - downstreamBindAddress: ipc:///tmp/nrm-downstream-event -perfwrapperPath: nrm-perfwrapper -extraStaticActuators: [] -raplCfg: - referencePower: - microwatts: 250000000 - raplActions: - - microwatts: 100000000 - - microwatts: 200000000 - raplPath: "/sys/devices/virtual/powercap/intel-rapl" -passiveSensorFrequency: - hertz: 1 diff --git a/resources/schemas/downstream.json b/resources/schemas/downstream.json deleted file mode 100644 index 4389d0d4..00000000 --- a/resources/schemas/downstream.json +++ /dev/null @@ -1,258 +0,0 @@ -{ - "required": [ - "timestamp", - "info" - ], - "type": "object", - "properties": { - "timestamp": { - "type": "number" - }, - "info": { - "oneOf": [ - { - "required": [ - "cmdPerformance" - ], - "type": "object", - "properties": { - "cmdPerformance": { - "required": [ - "cmdID", - "perf" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "perf": { - "type": "number" - } - } - } - } - }, - { - "required": [ - "cmdPause" - ], - "type": "object", - "properties": { - "cmdPause": { - "required": [ - "cmdID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - } - } - } - } - }, - { - "required": [ - "threadProgress" - ], - "type": "object", - "properties": { - "threadProgress": { - "required": [ - "downstreamThreadID", - "progress" - ], - "type": "object", - "properties": { - "progress": { - "type": "number" - }, - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - } - } - } - } - }, - { - "required": [ - "threadPause" - ], - "type": "object", - "properties": { - "threadPause": { - "required": [ - "downstreamThreadID" - ], - "type": "object", - "properties": { - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - } - } - } - } - }, - { - "required": [ - "threadPhaseContext" - ], - "type": "object", - "properties": { - "threadPhaseContext": { - "required": [ - "downstreamThreadID", - "phaseContext" - ], - "type": "object", - "properties": { - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - }, - "phaseContext": { - "required": [ - "cpu", - "aggregation", - "computetime", - "totaltime" - ], - "type": "object", - "properties": { - "computetime": { - "type": "number" - }, - "aggregation": { - "type": "number" - }, - "totaltime": { - "type": "number" - }, - "cpu": { - "type": "number" - } - } - } - } - } - } - }, - { - "required": [ - "threadPhasePause" - ], - "type": "object", - "properties": { - "threadPhasePause": { - "required": [ - "downstreamThreadID" - ], - "type": "object", - "properties": { - "downstreamThreadID": { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - } - } - } - } - } - ] - } - } -} \ No newline at end of file diff --git a/resources/schemas/upstream-pub.json b/resources/schemas/upstream-pub.json deleted file mode 100644 index 238d2403..00000000 --- a/resources/schemas/upstream-pub.json +++ /dev/null @@ -1,1111 +0,0 @@ -{ - "oneOf": [ - { - "required": [ - "pubMeasurements" - ], - "type": "object", - "properties": { - "pubMeasurements": { - "items": [ - { - "type": "number" - }, - { - "uniqueItems": false, - "items": { - "required": [ - "sensorID", - "sensorValue", - "time" - ], - "type": "object", - "properties": { - "time": { - "type": "number" - }, - "sensorValue": { - "type": "number" - }, - "sensorID": { - "type": "string" - } - } - }, - "type": "array" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "pubCPD" - ], - "type": "object", - "properties": { - "pubCPD": { - "items": [ - { - "type": "number" - }, - { - "required": [ - "sensors", - "actuators", - "objectives", - "constraints" - ], - "type": "object", - "properties": { - "objectives": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - {} - ], - "type": "array" - }, - "type": "array" - }, - "constraints": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - {} - ], - "type": "array" - }, - "type": "array" - }, - "sensors": { - "additionalProperties": { - "required": [ - "range", - "maxFrequency" - ], - "type": "object", - "properties": { - "maxFrequency": { - "type": "number" - }, - "range": { - "oneOf": [ - { - "required": [ - "i" - ], - "type": "object", - "properties": { - "i": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "empty" - ], - "type": "object", - "properties": { - "empty": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - }, - "type": "object" - }, - "actuators": { - "additionalProperties": { - "required": [ - "actions" - ], - "type": "object", - "properties": { - "actions": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - } - } - }, - "type": "object" - } - } - } - ], - "type": "array" - } - } - }, - { - "required": [ - "pubPerformance" - ], - "type": "object", - "properties": { - "pubPerformance": { - "items": [ - { - "type": "number" - }, - { - "type": "string" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "pubPhaseContext" - ], - "type": "object", - "properties": { - "pubPhaseContext": { - "items": [ - { - "type": "number" - }, - { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - }, - { - "oneOf": [ - { - "required": [ - "sliceID" - ], - "type": "object", - "properties": { - "sliceID": { - "type": "string" - } - } - }, - { - "required": [ - "name" - ], - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - { - "required": [ - "cpu", - "aggregation", - "computetime", - "totaltime" - ], - "type": "object", - "properties": { - "computetime": { - "type": "number" - }, - "aggregation": { - "type": "number" - }, - "totaltime": { - "type": "number" - }, - "cpu": { - "type": "number" - } - } - } - ], - "type": "array" - } - } - }, - { - "required": [ - "pubProgress" - ], - "type": "object", - "properties": { - "pubProgress": { - "items": [ - { - "type": "number" - }, - { - "required": [ - "cmdID", - "processID", - "taskID", - "threadID", - "rankID" - ], - "type": "object", - "properties": { - "cmdID": { - "type": "string" - }, - "taskID": { - "type": "string" - }, - "processID": { - "type": "number" - }, - "rankID": { - "type": "number" - }, - "threadID": { - "type": "number" - } - } - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "pubAction" - ], - "type": "object", - "properties": { - "pubAction": { - "items": [ - { - "type": "number" - }, - { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - }, - { - "oneOf": [ - { - "required": [ - "initialDecision" - ], - "type": "object", - "properties": { - "initialDecision": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "referenceMeasurementDecision" - ], - "type": "object", - "properties": { - "referenceMeasurementDecision": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "innerDecision" - ], - "type": "object", - "properties": { - "innerDecision": { - "required": [ - "constraints", - "objectives", - "loss", - "reportEvaluatedObjectives", - "reportNormalizedObjectives", - "reportEvaluatedConstraints" - ], - "type": "object", - "properties": { - "objectives": { - "uniqueItems": false, - "items": { - "required": [ - "fromObjectiveValue" - ], - "type": "object", - "properties": { - "fromObjectiveValue": { - "type": "number" - } - } - }, - "type": "array" - }, - "reportEvaluatedConstraints": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - }, - { - "oneOf": [ - { - "required": [ - "i" - ], - "type": "object", - "properties": { - "i": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "empty" - ], - "type": "object", - "properties": { - "empty": { - "type": "object", - "properties": {} - } - } - } - ] - } - ], - "type": "array" - }, - "type": "array" - }, - "reportEvaluatedObjectives": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - { - "oneOf": [ - { - "required": [ - "Just" - ], - "type": "object", - "properties": { - "Just": { - "type": "number" - } - } - }, - { - "required": [ - "Nothing" - ], - "type": "object", - "properties": { - "Nothing": { - "const": "null" - } - } - } - ] - }, - { - "oneOf": [ - { - "required": [ - "Just" - ], - "type": "object", - "properties": { - "Just": { - "oneOf": [ - { - "required": [ - "i" - ], - "type": "object", - "properties": { - "i": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "empty" - ], - "type": "object", - "properties": { - "empty": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - }, - { - "required": [ - "Nothing" - ], - "type": "object", - "properties": { - "Nothing": { - "const": "null" - } - } - } - ] - } - ], - "type": "array" - }, - "type": "array" - }, - "reportNormalizedObjectives": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - }, - "type": "array" - }, - "loss": { - "type": "number" - }, - "constraints": { - "uniqueItems": false, - "items": { - "required": [ - "fromConstraintValue" - ], - "type": "object", - "properties": { - "fromConstraintValue": { - "type": "number" - } - } - }, - "type": "array" - } - } - } - } - } - ] - }, - { - "required": [ - "integrator", - "armstats", - "referenceMeasurements", - "referenceMeasurementCounter" - ], - "type": "object", - "properties": { - "bandit": { - "oneOf": [ - { - "required": [ - "lagrange" - ], - "type": "object", - "properties": { - "lagrange": { - "required": [ - "lagrange" - ], - "type": "object", - "properties": { - "lagrange": { - "required": [ - "t", - "lastAction", - "k", - "weights" - ], - "type": "object", - "properties": { - "lastAction": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - }, - "k": { - "type": "number" - }, - "t": { - "type": "number" - }, - "weights": { - "uniqueItems": false, - "items": { - "required": [ - "probability", - "cumulativeLoss", - "action" - ], - "type": "object", - "properties": { - "probability": { - "required": [ - "getProbability" - ], - "type": "object", - "properties": { - "getProbability": { - "type": "number" - } - } - }, - "action": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - }, - "cumulativeLoss": { - "required": [ - "getCumulativeLoss" - ], - "type": "object", - "properties": { - "getCumulativeLoss": { - "type": "number" - } - } - } - } - }, - "type": "array" - } - } - } - } - } - } - }, - { - "required": [ - "random" - ], - "type": "object", - "properties": { - "random": { - "required": [ - "random" - ], - "type": "object", - "properties": { - "random": { - "uniqueItems": false, - "items": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - }, - "type": "array" - } - } - } - } - }, - { - "required": [ - "contextual" - ], - "type": "object", - "properties": { - "contextual": { - "required": [ - "contextual" - ], - "type": "object", - "properties": { - "contextual": { - "required": [ - "t", - "horizon", - "k", - "n", - "lambda", - "constraint", - "experts" - ], - "type": "object", - "properties": { - "lastAction": { - "required": [ - "action", - "globalProbabilityOfSample", - "perExpertProbabilityOfSample" - ], - "type": "object", - "properties": { - "perExpertProbabilityOfSample": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - }, - "action": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - }, - "globalProbabilityOfSample": { - "type": "number" - } - } - }, - "k": { - "type": "number" - }, - "n": { - "type": "number" - }, - "t": { - "type": "number" - }, - "lambda": { - "type": "number" - }, - "horizon": { - "type": "number" - }, - "experts": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - } - ], - "type": "array" - }, - "type": "array" - } - ], - "type": "array" - }, - "type": "array" - }, - "constraint": { - "type": "number" - } - } - } - } - } - } - } - ] - }, - "referenceMeasurements": { - "additionalProperties": { - "required": [ - "getMemBuffer" - ], - "type": "object", - "properties": { - "getMemBuffer": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - } - } - }, - "type": "object" - }, - "referenceMeasurementCounter": { - "type": "number" - }, - "bufferedMeasurements": { - "additionalProperties": { - "type": "number" - }, - "type": "object" - }, - "integrator": { - "required": [ - "meta", - "measured" - ], - "type": "object", - "properties": { - "measured": { - "additionalProperties": { - "oneOf": [ - { - "required": [ - "never" - ], - "type": "object", - "properties": { - "never": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "discarded" - ], - "type": "object", - "properties": { - "discarded": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "running" - ], - "type": "object", - "properties": { - "running": { - "required": [ - "firstTime", - "lastTime", - "lastValue", - "area" - ], - "type": "object", - "properties": { - "area": { - "type": "number" - }, - "firstTime": { - "type": "number" - }, - "lastTime": { - "type": "number" - }, - "lastValue": { - "type": "number" - } - } - } - } - }, - { - "required": [ - "done" - ], - "type": "object", - "properties": { - "done": { - "required": [ - "firstTime", - "lastTime", - "lastValue", - "area" - ], - "type": "object", - "properties": { - "area": { - "type": "number" - }, - "firstTime": { - "type": "number" - }, - "lastTime": { - "type": "number" - }, - "lastValue": { - "type": "number" - } - } - } - } - } - ] - }, - "type": "object" - }, - "meta": { - "required": [ - "tLast", - "minimumWaitInterval", - "minimumControlInterval" - ], - "type": "object", - "properties": { - "minimumWaitInterval": { - "type": "number" - }, - "minimumControlInterval": { - "type": "number" - }, - "tLast": { - "type": "number" - } - } - } - } - }, - "armstats": { - "additionalProperties": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - }, - { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - }, - { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - }, - { - "additionalProperties": { - "type": "number" - }, - "type": "object" - }, - { - "additionalProperties": { - "type": "number" - }, - "type": "object" - } - ], - "type": "array" - }, - "type": "object" - }, - "lastA": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - } - } - } - ], - "type": "array" - } - } - }, - { - "required": [ - "pubEnd" - ], - "type": "object", - "properties": { - "pubEnd": { - "type": "string" - } - } - } - ] -} \ No newline at end of file diff --git a/resources/schemas/upstream-rep.json b/resources/schemas/upstream-rep.json deleted file mode 100644 index 7b671130..00000000 --- a/resources/schemas/upstream-rep.json +++ /dev/null @@ -1,1316 +0,0 @@ -{ - "oneOf": [ - { - "required": [ - "repList" - ], - "type": "object", - "properties": { - "repList": { - "required": [ - "slices" - ], - "type": "object", - "properties": { - "slices": { - "uniqueItems": false, - "items": { - "items": [ - { - "oneOf": [ - { - "required": [ - "sliceID" - ], - "type": "object", - "properties": { - "sliceID": { - "type": "string" - } - } - }, - { - "required": [ - "name" - ], - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - { - "required": [ - "cmds", - "awaiting" - ], - "type": "object", - "properties": { - "awaiting": { - "additionalProperties": { - "required": [ - "cmdPath", - "arguments", - "manifest" - ], - "type": "object", - "properties": { - "upstreamClientID": { - "type": "string" - }, - "arguments": { - "uniqueItems": false, - "items": { - "type": "string" - }, - "type": "array" - }, - "cmdPath": { - "type": "string" - }, - "manifest": { - "required": [ - "app", - "name" - ], - "type": "object", - "properties": { - "app": { - "type": "object", - "properties": { - "instrumentation": { - "required": [ - "ratelimit" - ], - "type": "object", - "properties": { - "ratelimit": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - }, - "perfwrapper": { - "required": [ - "perfFreq", - "perfLimit" - ], - "type": "object", - "properties": { - "perfLimit": { - "type": "number" - }, - "perfFreq": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - } - } - }, - "name": { - "type": "string" - } - } - } - } - }, - "type": "object" - }, - "cmds": { - "additionalProperties": { - "required": [ - "cmdCore", - "pid", - "processState", - "downstreamCmds", - "downstreamThreads" - ], - "type": "object", - "properties": { - "downstreamCmds": { - "additionalProperties": { - "required": [ - "maxValue", - "ratelimit", - "dtLastReferenceMeasurements" - ], - "type": "object", - "properties": { - "ratelimit": { - "type": "number" - }, - "maxValue": { - "type": "number" - }, - "dtLastReferenceMeasurements": { - "required": [ - "getMemBuffer" - ], - "type": "object", - "properties": { - "getMemBuffer": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - } - } - }, - "lastRead": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - "type": "object" - }, - "cmdCore": { - "required": [ - "cmdPath", - "arguments", - "manifest" - ], - "type": "object", - "properties": { - "upstreamClientID": { - "type": "string" - }, - "arguments": { - "uniqueItems": false, - "items": { - "type": "string" - }, - "type": "array" - }, - "cmdPath": { - "type": "string" - }, - "manifest": { - "required": [ - "app", - "name" - ], - "type": "object", - "properties": { - "app": { - "type": "object", - "properties": { - "instrumentation": { - "required": [ - "ratelimit" - ], - "type": "object", - "properties": { - "ratelimit": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - }, - "perfwrapper": { - "required": [ - "perfFreq", - "perfLimit" - ], - "type": "object", - "properties": { - "perfLimit": { - "type": "number" - }, - "perfFreq": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - } - } - }, - "name": { - "type": "string" - } - } - } - } - }, - "processState": { - "required": [ - "stdoutFinished", - "stderrFinished" - ], - "type": "object", - "properties": { - "stderrFinished": { - "type": "boolean" - }, - "stdoutFinished": { - "type": "boolean" - }, - "ended": { - "oneOf": [ - { - "required": [ - "exitSuccess" - ], - "type": "object", - "properties": { - "exitSuccess": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "exitFailure" - ], - "type": "object", - "properties": { - "exitFailure": { - "type": "number" - } - } - } - ] - } - } - }, - "pid": { - "type": "number" - }, - "downstreamThreads": { - "additionalProperties": { - "required": [ - "maxValue", - "ratelimit", - "dtLastReferenceMeasurements" - ], - "type": "object", - "properties": { - "ratelimit": { - "type": "number" - }, - "maxValue": { - "type": "number" - }, - "dtLastReferenceMeasurements": { - "required": [ - "getMemBuffer" - ], - "type": "object", - "properties": { - "getMemBuffer": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - } - } - }, - "lastRead": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - "type": "object" - } - } - }, - "type": "object" - } - } - } - ], - "type": "array" - }, - "type": "array" - } - } - } - } - }, - { - "required": [ - "repCPD" - ], - "type": "object", - "properties": { - "repCPD": { - "required": [ - "sensors", - "actuators", - "objectives", - "constraints" - ], - "type": "object", - "properties": { - "objectives": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - {} - ], - "type": "array" - }, - "type": "array" - }, - "constraints": { - "uniqueItems": false, - "items": { - "items": [ - { - "type": "number" - }, - {} - ], - "type": "array" - }, - "type": "array" - }, - "sensors": { - "additionalProperties": { - "required": [ - "range", - "maxFrequency" - ], - "type": "object", - "properties": { - "maxFrequency": { - "type": "number" - }, - "range": { - "oneOf": [ - { - "required": [ - "i" - ], - "type": "object", - "properties": { - "i": { - "items": [ - { - "type": "number" - }, - { - "type": "number" - } - ], - "type": "array" - } - } - }, - { - "required": [ - "empty" - ], - "type": "object", - "properties": { - "empty": { - "type": "object", - "properties": {} - } - } - } - ] - } - } - }, - "type": "object" - }, - "actuators": { - "additionalProperties": { - "required": [ - "actions" - ], - "type": "object", - "properties": { - "actions": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - } - } - }, - "type": "object" - } - } - } - } - }, - { - "required": [ - "repStart" - ], - "type": "object", - "properties": { - "repStart": { - "required": [ - "startSliceID", - "startCmdID" - ], - "type": "object", - "properties": { - "startCmdID": { - "type": "string" - }, - "startSliceID": { - "oneOf": [ - { - "required": [ - "sliceID" - ], - "type": "object", - "properties": { - "sliceID": { - "type": "string" - } - } - }, - { - "required": [ - "name" - ], - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - ] - } - } - } - } - }, - { - "required": [ - "repStdout" - ], - "type": "object", - "properties": { - "repStdout": { - "required": [ - "stdoutCmdID", - "stdoutPayload" - ], - "type": "object", - "properties": { - "stdoutPayload": { - "type": "string" - }, - "stdoutCmdID": { - "type": "string" - } - } - } - } - }, - { - "required": [ - "repStderr" - ], - "type": "object", - "properties": { - "repStderr": { - "required": [ - "stderrCmdID", - "stderrPayload" - ], - "type": "object", - "properties": { - "stderrPayload": { - "type": "string" - }, - "stderrCmdID": { - "type": "string" - } - } - } - } - }, - { - "required": [ - "repEndStream" - ], - "type": "object", - "properties": { - "repEndStream": { - "required": [ - "streamType" - ], - "type": "object", - "properties": { - "streamType": { - "oneOf": [ - { - "const": "\"stdoutOutput\"" - }, - { - "const": "\"stderrOutput\"" - } - ] - } - } - } - } - }, - { - "required": [ - "repStartFailure" - ], - "type": "object", - "properties": { - "repStartFailure": { - "const": "\"startFailure\"" - } - } - }, - { - "required": [ - "repCmdEnded" - ], - "type": "object", - "properties": { - "repCmdEnded": { - "required": [ - "exitCode" - ], - "type": "object", - "properties": { - "exitCode": { - "oneOf": [ - { - "required": [ - "exitSuccess" - ], - "type": "object", - "properties": { - "exitSuccess": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "exitFailure" - ], - "type": "object", - "properties": { - "exitFailure": { - "type": "number" - } - } - } - ] - } - } - } - } - }, - { - "required": [ - "repNoSuchSlice" - ], - "type": "object", - "properties": { - "repNoSuchSlice": { - "const": "\"noSuchSlice\"" - } - } - }, - { - "required": [ - "repNoSuchCmd" - ], - "type": "object", - "properties": { - "repNoSuchCmd": { - "const": "\"noSuchCmd\"" - } - } - }, - { - "required": [ - "repSliceKilled" - ], - "type": "object", - "properties": { - "repSliceKilled": { - "required": [ - "killedSliceID" - ], - "type": "object", - "properties": { - "killedSliceID": { - "oneOf": [ - { - "required": [ - "sliceID" - ], - "type": "object", - "properties": { - "sliceID": { - "type": "string" - } - } - }, - { - "required": [ - "name" - ], - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - ] - } - } - } - } - }, - { - "required": [ - "repCmdKilled" - ], - "type": "object", - "properties": { - "repCmdKilled": { - "required": [ - "killedCmdID" - ], - "type": "object", - "properties": { - "killedCmdID": { - "type": "string" - } - } - } - } - }, - { - "required": [ - "repThisCmdKilled" - ], - "type": "object", - "properties": { - "repThisCmdKilled": { - "const": "\"thisCmdKilled\"" - } - } - }, - { - "required": [ - "repActuate" - ], - "type": "object", - "properties": { - "repActuate": { - "oneOf": [ - { - "const": "\"actuated\"" - }, - { - "const": "\"notActuated\"" - } - ] - } - } - }, - { - "required": [ - "repGetState" - ], - "type": "object", - "properties": { - "repGetState": { - "type": "string" - } - } - }, - { - "required": [ - "repGetConfig" - ], - "type": "object", - "properties": { - "repGetConfig": { - "required": [ - "config" - ], - "type": "object", - "properties": { - "config": { - "required": [ - "controlCfg", - "downstreamCfg", - "extraStaticActuators", - "extraStaticPassiveSensors", - "logfile", - "passiveSensorFrequency", - "perfPath", - "perfwrapperPath", - "upstreamCfg", - "verbose" - ], - "type": "object", - "properties": { - "extraStaticPassiveSensors": { - "uniqueItems": false, - "items": { - "required": [ - "sensor", - "sensorID" - ], - "type": "object", - "properties": { - "sensorID": { - "type": "string" - }, - "sensor": { - "required": [ - "range", - "sensorArguments", - "sensorBehavior", - "sensorBinary", - "tags" - ], - "type": "object", - "properties": { - "range": { - "required": [ - "lower", - "upper" - ], - "type": "object", - "properties": { - "upper": { - "type": "number" - }, - "lower": { - "type": "number" - } - } - }, - "sensorBehavior": { - "oneOf": [ - { - "required": [ - "cumulative" - ], - "type": "object", - "properties": { - "cumulative": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "cumulativeWithCapacity" - ], - "type": "object", - "properties": { - "cumulativeWithCapacity": { - "type": "number" - } - } - }, - { - "required": [ - "intervalBased" - ], - "type": "object", - "properties": { - "intervalBased": { - "type": "object", - "properties": {} - } - } - } - ] - }, - "sensorArguments": { - "uniqueItems": false, - "items": { - "type": "string" - }, - "type": "array" - }, - "tags": { - "uniqueItems": false, - "items": { - "oneOf": [ - { - "const": "\"tagDownstreamCmdSignal\"" - }, - { - "const": "\"tagDownstreamThreadSignal\"" - }, - { - "const": "\"tagMaximize\"" - }, - { - "const": "\"tagMinimize\"" - }, - { - "const": "\"tagPower\"" - }, - { - "const": "\"tagRapl\"" - } - ] - }, - "type": "array" - }, - "sensorBinary": { - "type": "string" - } - } - } - } - }, - "type": "array" - }, - "perfPath": { - "type": "string" - }, - "verbose": { - "oneOf": [ - { - "const": "\"debug\"" - }, - { - "const": "\"error\"" - }, - { - "const": "\"info\"" - } - ] - }, - "logfile": { - "type": "string" - }, - "controlCfg": { - "oneOf": [ - { - "required": [ - "controlCfg" - ], - "type": "object", - "properties": { - "controlCfg": { - "required": [ - "hint", - "learnCfg", - "minimumControlInterval", - "minimumWaitInterval", - "referenceMeasurementRoundInterval", - "speedThreshold", - "staticPower" - ], - "type": "object", - "properties": { - "referenceMeasurementRoundInterval": { - "type": "number" - }, - "minimumWaitInterval": { - "required": [ - "microseconds" - ], - "type": "object", - "properties": { - "microseconds": { - "type": "number" - } - } - }, - "hint": { - "oneOf": [ - { - "required": [ - "full" - ], - "type": "object", - "properties": { - "full": { - "type": "object", - "properties": {} - } - } - }, - { - "required": [ - "only" - ], - "type": "object", - "properties": { - "only": { - "required": [ - "neHead", - "neTail" - ], - "type": "object", - "properties": { - "neHead": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorValue", - "actuatorValueID" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorValueID": { - "type": "string" - } - } - }, - "type": "array" - }, - "neTail": { - "uniqueItems": false, - "items": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorValue", - "actuatorValueID" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorValueID": { - "type": "string" - } - } - }, - "type": "array" - }, - "type": "array" - } - } - } - } - } - ] - }, - "learnCfg": { - "oneOf": [ - { - "required": [ - "contextual" - ], - "type": "object", - "properties": { - "contextual": { - "required": [ - "horizon" - ], - "type": "object", - "properties": { - "horizon": { - "type": "number" - } - } - } - } - }, - { - "required": [ - "lagrange" - ], - "type": "object", - "properties": { - "lagrange": { - "required": [ - "lagrange" - ], - "type": "object", - "properties": { - "lagrange": { - "type": "number" - } - } - } - } - }, - { - "required": [ - "random" - ], - "type": "object", - "properties": { - "random": { - "required": [ - "seed" - ], - "type": "object", - "properties": { - "seed": { - "type": "number" - } - } - } - } - } - ] - }, - "staticPower": { - "required": [ - "microwatts" - ], - "type": "object", - "properties": { - "microwatts": { - "type": "number" - } - } - }, - "speedThreshold": { - "type": "number" - }, - "minimumControlInterval": { - "required": [ - "microseconds" - ], - "type": "object", - "properties": { - "microseconds": { - "type": "number" - } - } - } - } - } - } - }, - { - "required": [ - "controlOff" - ], - "type": "object", - "properties": { - "controlOff": { - "type": "object", - "properties": {} - } - } - } - ] - }, - "upstreamCfg": { - "required": [ - "pubPort", - "rpcPort", - "upstreamBindAddress" - ], - "type": "object", - "properties": { - "upstreamBindAddress": { - "type": "string" - }, - "rpcPort": { - "type": "number" - }, - "pubPort": { - "type": "number" - } - } - }, - "libnrmPath": { - "type": "string" - }, - "downstreamCfg": { - "required": [ - "downstreamBindAddress" - ], - "type": "object", - "properties": { - "downstreamBindAddress": { - "type": "string" - } - } - }, - "perfwrapperPath": { - "type": "string" - }, - "extraStaticActuators": { - "uniqueItems": false, - "items": { - "required": [ - "actuator", - "actuatorID" - ], - "type": "object", - "properties": { - "actuator": { - "required": [ - "actions", - "actuatorArguments", - "actuatorBinary", - "referenceAction" - ], - "type": "object", - "properties": { - "actuatorBinary": { - "type": "string" - }, - "actions": { - "uniqueItems": false, - "items": { - "type": "number" - }, - "type": "array" - }, - "actuatorArguments": { - "uniqueItems": false, - "items": { - "type": "string" - }, - "type": "array" - }, - "referenceAction": { - "type": "number" - } - } - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - }, - "raplCfg": { - "required": [ - "raplActions", - "raplPath", - "referencePower" - ], - "type": "object", - "properties": { - "referencePower": { - "required": [ - "microwatts" - ], - "type": "object", - "properties": { - "microwatts": { - "type": "number" - } - } - }, - "raplActions": { - "uniqueItems": false, - "items": { - "required": [ - "microwatts" - ], - "type": "object", - "properties": { - "microwatts": { - "type": "number" - } - } - }, - "type": "array" - }, - "raplPath": { - "type": "string" - } - } - }, - "passiveSensorFrequency": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - } - } - } - } - }, - { - "required": [ - "repException" - ], - "type": "object", - "properties": { - "repException": { - "type": "string" - } - } - } - ] -} \ No newline at end of file diff --git a/resources/schemas/upstream-req.json b/resources/schemas/upstream-req.json deleted file mode 100644 index 7c38a072..00000000 --- a/resources/schemas/upstream-req.json +++ /dev/null @@ -1,277 +0,0 @@ -{ - "oneOf": [ - { - "required": [ - "reqSliceList" - ], - "type": "object", - "properties": { - "reqSliceList": { - "const": "\"sliceList\"" - } - } - }, - { - "required": [ - "reqRun" - ], - "type": "object", - "properties": { - "reqRun": { - "required": [ - "manifest", - "spec", - "runSliceID", - "detachCmd" - ], - "type": "object", - "properties": { - "detachCmd": { - "type": "boolean" - }, - "runSliceID": { - "oneOf": [ - { - "required": [ - "sliceID" - ], - "type": "object", - "properties": { - "sliceID": { - "type": "string" - } - } - }, - { - "required": [ - "name" - ], - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - ] - }, - "manifest": { - "required": [ - "app", - "name" - ], - "type": "object", - "properties": { - "app": { - "type": "object", - "properties": { - "instrumentation": { - "required": [ - "ratelimit" - ], - "type": "object", - "properties": { - "ratelimit": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - }, - "perfwrapper": { - "required": [ - "perfFreq", - "perfLimit" - ], - "type": "object", - "properties": { - "perfLimit": { - "type": "number" - }, - "perfFreq": { - "required": [ - "hertz" - ], - "type": "object", - "properties": { - "hertz": { - "type": "number" - } - } - } - } - } - } - }, - "name": { - "type": "string" - } - } - }, - "spec": { - "required": [ - "cmd", - "args", - "env" - ], - "type": "object", - "properties": { - "args": { - "uniqueItems": false, - "items": { - "type": "string" - }, - "type": "array" - }, - "env": { - "required": [ - "fromEnv" - ], - "type": "object", - "properties": { - "fromEnv": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - } - } - }, - "cmd": { - "type": "string" - } - } - } - } - } - } - }, - { - "required": [ - "reqKillSlice" - ], - "type": "object", - "properties": { - "reqKillSlice": { - "required": [ - "killSliceID" - ], - "type": "object", - "properties": { - "killSliceID": { - "oneOf": [ - { - "required": [ - "sliceID" - ], - "type": "object", - "properties": { - "sliceID": { - "type": "string" - } - } - }, - { - "required": [ - "name" - ], - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - ] - } - } - } - } - }, - { - "required": [ - "reqCPD" - ], - "type": "object", - "properties": { - "reqCPD": { - "const": "\"cPD\"" - } - } - }, - { - "required": [ - "reqKillCmd" - ], - "type": "object", - "properties": { - "reqKillCmd": { - "required": [ - "killCmdID" - ], - "type": "object", - "properties": { - "killCmdID": { - "type": "string" - } - } - } - } - }, - { - "required": [ - "reqActuate" - ], - "type": "object", - "properties": { - "reqActuate": { - "uniqueItems": false, - "items": { - "required": [ - "actuatorID", - "actuatorValue" - ], - "type": "object", - "properties": { - "actuatorValue": { - "type": "number" - }, - "actuatorID": { - "type": "string" - } - } - }, - "type": "array" - } - } - }, - { - "required": [ - "reqGetState" - ], - "type": "object", - "properties": { - "reqGetState": { - "const": "\"getState\"" - } - } - }, - { - "required": [ - "reqGetConfig" - ], - "type": "object", - "properties": { - "reqGetConfig": { - "const": "\"getConfig\"" - } - } - } - ] -} \ No newline at end of file From 0a905a99cf82ad8be5699ac965f6784954943e08 Mon Sep 17 00:00:00 2001 From: jlnav Date: Fri, 13 Oct 2023 15:08:02 -0500 Subject: [PATCH 34/39] remove scripts=[bin/nrmd] --- setup.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/setup.py b/setup.py index 802b313b..4580d3c0 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,4 @@ setup_requires=["cffi"], cffi_modules=["nrm/api/build.py:ffi"], install_requires=['msgpack', 'pyyaml', "warlock", "pyzmq", "tornado", "jsonschema", "loguru", "cffi"], - package_data={'nrm': ['schemas/*.json', 'schemas/*.yml']}, - scripts=['bin/nrmd'] ) From 2bbebe73ff5f40c37fff0d2691b7054e078e7358 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 19 Oct 2023 10:18:42 -0500 Subject: [PATCH 35/39] tiny fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ed09c18..2866782d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # NRM Python -Python binaries and notebook infrastructure on top of nrm-core. +Python binaries and notebook infrastructure on top of libnrm. Currently contains the official nrm daemon implementation, as well as additional python modules to talk to the NRM from a python application, both From ea521392be04757b4b1dbdd0605f19fc3c9fb593 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 19 Oct 2023 13:29:28 -0500 Subject: [PATCH 36/39] try reading nrm.h, appending contents so cffi can compile it --- nrm/api/build.py | 139 +++++------------------------------------------ 1 file changed, 15 insertions(+), 124 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index adda98f5..7ebcc238 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -1,4 +1,5 @@ from cffi import FFI +import subprocess ffi = FFI() @@ -10,8 +11,10 @@ libraries=["nrm"], ) -ffi.cdef( - """ +nrmh = subprocess.Popen(["locate", "nrm.h"], stdout=subprocess.PIPE).communicate()[0].decode().split("\n")[0] + +cdef_base = \ +""" typedef int... time_t; @@ -20,29 +23,12 @@ long tv_nsec; }; -typedef struct nrm_client_s nrm_client_t; -typedef struct nrm_actuator_s nrm_actuator_t; -typedef struct nrm_slice_s nrm_slice_t; -typedef struct nrm_sensor_s nrm_sensor_t; -typedef struct nrm_scope nrm_scope_t; -typedef struct nrm_vector_s nrm_vector_t; +nrm_time_t nrm_time_fromns(int64_t ns); typedef char *nrm_string_t; -typedef struct timespec nrm_time_t; typedef nrm_string_t nrm_uuid_t; -typedef struct pyinfo_s pyinfo_t; - -typedef int(nrm_client_event_listener_fn)(nrm_string_t sensor_uuid, - nrm_time_t time, - nrm_scope_t *scope, - double value, - void *arg); -typedef int(nrm_client_actuate_listener_fn)(nrm_uuid_t *uuid, - double value, - void *arg); - -nrm_time_t nrm_time_fromns(int64_t ns); - -// PY STUFF +typedef struct timespec nrm_time_t; +typedef struct nrm_vector_s nrm_vector_t; +typedef struct nrm_scope nrm_scope_t; extern "Python" int _event_listener_wrap(nrm_string_t sensor_uuid, nrm_time_t time, @@ -54,116 +40,21 @@ double value, void *arg); -int nrm_client_externpython_event(nrm_string_t sensor_uuid, - nrm_time_t time, - nrm_scope_t *scope, - double value, - void *arg); - -int nrm_client_externpython_actuate(nrm_uuid_t *uuid, - double value, - void *arg); - -int nrm_client_set_event_Pylistener(nrm_client_t *client, - void *pyinfo); - -int nrm_client_set_actuate_Pylistener(nrm_client_t *client, - void *pyinfo); - -int nrm_pyinfo_create(pyinfo_t **pyinfo, - void *pyclient, - nrm_client_event_listener_fn *extern_user_fn, - nrm_client_actuate_listener_fn *extern_actuate_fn); - -// END PY STUFF - -int nrm_init(int *argc, char **argv[]); - nrm_string_t nrm_string_fromchar(const char *buf); void nrm_time_gettime(nrm_time_t *now); -nrm_actuator_t *nrm_actuator_create(const char *name); - -nrm_scope_t *nrm_scope_create(const char *name); - -nrm_sensor_t *nrm_sensor_create(const char *name); - -nrm_slice_t *nrm_slice_create(const char *name); - -int nrm_client_create(nrm_client_t **client, - const char *uri, - int pub_port, - int rpc_port); - -int nrm_client_actuate(nrm_client_t *client, - nrm_actuator_t *actuator, - double value); - -int nrm_client_add_actuator(nrm_client_t *client, - nrm_actuator_t *actuator); - -int nrm_client_add_scope(nrm_client_t *client, nrm_scope_t *scope); - -int nrm_client_add_sensor(nrm_client_t *client, nrm_sensor_t *sensor); - -int nrm_client_add_slice(nrm_client_t *client, nrm_slice_t *slice); - -int nrm_client_find(nrm_client_t *client, - int type, - const char *uuid, - nrm_vector_t **results); - -int nrm_client_send_event(nrm_client_t *client, - nrm_time_t time, - nrm_sensor_t *sensor, - nrm_scope_t *scope, - double value); - -int nrm_client_send_exit(nrm_client_t *client); - -int nrm_client_send_tick(nrm_client_t *client); - -int nrm_client_set_event_listener(nrm_client_t *client, - nrm_client_event_listener_fn *fn, - void *arg); - -int nrm_client_start_event_listener(nrm_client_t *client, - nrm_string_t topic); - -int nrm_client_set_actuate_listener(nrm_client_t *client, - nrm_client_actuate_listener_fn *fn, - void *arg); - -int nrm_client_start_actuate_listener(nrm_client_t *client); - -void nrm_client_destroy(nrm_client_t **client); - -int nrm_actuator_set_value(nrm_actuator_t *actuator, double value); - -int nrm_actuator_set_choices(nrm_actuator_t *actuator, - size_t nchoices, - double *choices); - -void nrm_actuator_destroy(nrm_actuator_t **); - int nrm_scope_destroy(nrm_scope_t *scope); -void nrm_slice_destroy(nrm_slice_t **); - -void nrm_sensor_destroy(nrm_sensor_t **); - -int nrm_client_remove_actuator(nrm_client_t *client, - nrm_actuator_t *actuator); - -int nrm_client_remove_slice(nrm_client_t *client, nrm_slice_t *slice); +""" -int nrm_client_remove_sensor(nrm_client_t *client, nrm_sensor_t *sensor); +with open(nrmh, "r") as f: + lines = f.readlines() -int nrm_client_remove_scope(nrm_client_t *client, nrm_scope_t *scope); +for line in lines: + cdef_base += line -""" -) +ffi.cdef(cdef_base) if __name__ == "__main__": ffi.compile(verbose=True) From 8ca1d7ebf1df3edc56635a64efb2bfef64d22ef6 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 19 Oct 2023 13:41:46 -0500 Subject: [PATCH 37/39] rearrange --- nrm/api/build.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 7ebcc238..8e5b2358 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -23,10 +23,11 @@ long tv_nsec; }; +typedef struct timespec nrm_time_t; + nrm_time_t nrm_time_fromns(int64_t ns); typedef char *nrm_string_t; typedef nrm_string_t nrm_uuid_t; -typedef struct timespec nrm_time_t; typedef struct nrm_vector_s nrm_vector_t; typedef struct nrm_scope nrm_scope_t; From e89c882ab8789fb202708e00857a6944fd4724e9 Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 19 Oct 2023 14:11:47 -0500 Subject: [PATCH 38/39] more universal way of finding nrm.h --- nrm/api/build.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 8e5b2358..6df9f6f5 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -1,5 +1,6 @@ from cffi import FFI import subprocess +import os ffi = FFI() @@ -11,7 +12,7 @@ libraries=["nrm"], ) -nrmh = subprocess.Popen(["locate", "nrm.h"], stdout=subprocess.PIPE).communicate()[0].decode().split("\n")[0] +nrmh = subprocess.Popen(["find", os.environ["HOME"], "/usr/local", "-name", "nrm.h"], stdout=subprocess.PIPE).communicate()[0].decode().split("\n")[0] cdef_base = \ """ From 791370c0063fe28c5e9a57318b095280e54469ee Mon Sep 17 00:00:00 2001 From: jlnav Date: Thu, 19 Oct 2023 15:56:15 -0500 Subject: [PATCH 39/39] tentative progress, now skipping nrm_log_perror preprocessor block, but other types need to be skipped --- nrm/api/build.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/nrm/api/build.py b/nrm/api/build.py index 6df9f6f5..2c764e2f 100644 --- a/nrm/api/build.py +++ b/nrm/api/build.py @@ -12,7 +12,10 @@ libraries=["nrm"], ) -nrmh = subprocess.Popen(["find", os.environ["HOME"], "/usr/local", "-name", "nrm.h"], stdout=subprocess.PIPE).communicate()[0].decode().split("\n")[0] +def my_temporary_header_locator(): + return subprocess.Popen(["find", "../libnrm", "-name", "nrm.h"], stdout=subprocess.PIPE).communicate()[0].decode().split("\n")[0] + +nrmh = my_temporary_header_locator() cdef_base = \ """ @@ -53,8 +56,21 @@ with open(nrmh, "r") as f: lines = f.readlines() +avoid_tokens = ["#", "extern \"C\" {", " nrm_log_printf("] +avoid_block = [ +"\tdo { \\\n", +"\t\tchar *__nrm_errstr = strerror(errno); \\\n", +"\t\tnrm_log_printf(NRM_LOG_ERROR, __FILE__, __LINE__, \\\n", +"\t\t __VA_ARGS__); \\\n", +"\t\tnrm_log_printf(NRM_LOG_ERROR, __FILE__, __LINE__, \\\n", +"\t\t \"perror: %s\\n\", __nrm_errstr); \\\n", +"\t} while (0)\n", +] + for line in lines: - cdef_base += line + if not any([line.startswith(token) for token in avoid_tokens]) and line not in avoid_block: + cdef_base += line + ffi.cdef(cdef_base)