Skip to content

Commit

Permalink
add support for passing raw attributes to readings (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
npmenard authored Aug 13, 2024
1 parent 397a6f9 commit 3bca23a
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 5 deletions.
18 changes: 18 additions & 0 deletions micro-rdk-ffi/include/micrordk.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ typedef struct get_readings_context get_readings_context;
*/
typedef struct hashmap_cstring_ptr hashmap_cstring_ptr;

typedef struct raw_attributes raw_attributes;

typedef struct viam_server_context viam_server_context;

/*
Expand Down Expand Up @@ -60,6 +62,16 @@ extern "C" {
*/
enum viam_code config_get_string(struct config_context *ctx, const char *key, char **out);

/*
Returns a pointer to the raw attribute structure of a component config
*/
struct raw_attributes *config_get_raw_attributes(struct config_context *ctx);

/*
Free a raw_attributes structure previously obtained with `config_get_raw_attributes`
*/
enum viam_code config_raw_attributes_free(struct raw_attributes *attrs);

/*
Free a string allocated by a successful call to `config_get_string`
*/
Expand Down Expand Up @@ -186,6 +198,12 @@ enum viam_code get_readings_add_string(struct get_readings_context *ctx,
const char *key,
const char *value);

/*
This function adds raw attributes to a sensor reading request
*/
enum viam_code get_readings_add_raw_attributes(struct get_readings_context *ctx,
const struct raw_attributes *raw_attrs);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
Expand Down
52 changes: 50 additions & 2 deletions micro-rdk-ffi/src/ffi/config.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::ffi::{c_char, c_int, CStr, CString};
use std::{
collections::HashMap,
ffi::{c_char, c_int, CStr, CString},
};

use micro_rdk::common::config::{AttributeError, ConfigType};
use micro_rdk::common::config::{AttributeError, ConfigType, Kind};

use super::errors;

Expand All @@ -9,6 +12,9 @@ pub struct config_context<'a> {
pub(crate) cfg: ConfigType<'a>,
}

#[allow(non_camel_case_types)]
pub struct raw_attributes(pub(crate) HashMap<String, Kind>);

/// Get a string from the attribute section of a sensor configuration
/// if found the content of the string will be written to `out`
///
Expand Down Expand Up @@ -40,6 +46,48 @@ pub unsafe extern "C" fn config_get_string(
unsafe { *out = c_str };
errors::viam_code::VIAM_OK
}

/// Returns a pointer to the raw attribute structure of a component config
/// pointers remains valid until `config_raw_attributes_free` is called.
/// Free the structure with `config_raw_attributes_free` when done using it.
///
/// # Safety
/// `ctx` must be a valid pointer
#[no_mangle]
pub unsafe extern "C" fn config_get_raw_attributes(
ctx: *mut config_context,
) -> *mut raw_attributes {
if ctx.is_null() {
return std::ptr::null_mut();
}

let ctx = unsafe { &mut *ctx };

let ConfigType::Dynamic(cfg) = ctx.cfg;
if let Some(attrs) = &cfg.attributes {
return Box::into_raw(Box::new(raw_attributes(attrs.clone())));
}

std::ptr::null_mut()
}

/// Free a raw_attributes structure previously obtained with `config_get_raw_attributes`
///
/// # Safety
/// `attrs` must be a valid pointer
#[no_mangle]
pub unsafe extern "C" fn config_raw_attributes_free(
attrs: *mut raw_attributes,
) -> errors::viam_code {
if attrs.is_null() {
return errors::viam_code::VIAM_INVALID_ARG;
}

drop(Box::from_raw(attrs));

errors::viam_code::VIAM_OK
}

/// Free a string allocated by a successful call to `config_get_string`
///
/// # Safety
Expand Down
46 changes: 44 additions & 2 deletions micro-rdk-ffi/src/ffi/sensor.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
use micro_rdk::{
common::{
config::Kind,
sensor::{GenericReadingsResult, Readings, Sensor, SensorError},
status::Status,
},
google::protobuf::Value,
google::protobuf::{value, Value},
DoCommand,
};
use std::{
collections::HashMap,
ffi::{c_char, c_int, c_uchar, c_uint, c_void, CStr},
};

use super::{config::config_context, errors::viam_code};
use super::{
config::{config_context, raw_attributes},
errors::viam_code,
};

#[allow(non_camel_case_types)]
type config_callback = extern "C" fn(*mut config_context, *mut c_void, *mut *mut c_void) -> c_int;
Expand Down Expand Up @@ -223,3 +227,41 @@ pub unsafe extern "C" fn get_readings_add_string(

viam_code::VIAM_OK
}

// converts a config::Kind to value::Kind purposefully skipping "nested" Kinds
fn into_value(kind: Kind) -> value::Kind {
match kind {
Kind::BoolValue(b) => value::Kind::BoolValue(b),
Kind::NullValue(n) => value::Kind::NullValue(n),
Kind::NumberValue(f) => value::Kind::NumberValue(f),
Kind::StringValue(s) => value::Kind::StringValue(s),
_ => value::Kind::NullValue(0),
}
}

/// This function can be use by a sensor during the call to `get_readings_callback` to add a `raw_attributes` struct
/// to get_readings
///
/// # Safety
/// `ctx`, and `raw_attrs` and `value` must be valid pointers for the duration of the call
#[no_mangle]
pub unsafe extern "C" fn get_readings_add_raw_attributes(
ctx: *mut get_readings_context,
raw_attrs: *const raw_attributes,
) -> viam_code {
if ctx.is_null() || raw_attrs.is_null() {
return viam_code::VIAM_INVALID_ARG;
}
let ctx = unsafe { &mut *ctx };
let attrs = unsafe { &*raw_attrs };
for attr in &attrs.0 {
let _ = ctx.readings.insert(
attr.0.clone(),
Value {
kind: Some(into_value(attr.1.clone())),
},
);
}

viam_code::VIAM_OK
}
2 changes: 1 addition & 1 deletion micro-rdk/src/common/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ impl TryFrom<&Kind> for Kind {
}
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum Kind {
NullValue(i32),
NumberValue(f64),
Expand Down

0 comments on commit 3bca23a

Please sign in to comment.