gc_plugin_abi 0.5.0

Gridcore Plugin API
Documentation
use crate::{GCDatapointID, GCDatapointValue, GCDatapointValueQuality};
use gc_abi::{GCEthernetInterface, GCSerialInterface, raw};
use log::{debug, error, info, warn};
use std::{ffi::CStr, os::raw::c_uint};

pub type PublishDatapointValueIntercept = dyn Fn(&GCDatapointValue) -> bool;
pub type LogIntercept = dyn Fn(c_uint, &CStr);
pub type GetLastDatapointValueIntercept = dyn Fn(GCDatapointID) -> GCDatapointValue;
pub type GetEthernetInterfaceIntercept = dyn Fn(&CStr) -> Option<GCEthernetInterface>;
pub type GetSerialInterfaceIntercept = dyn Fn(&CStr) -> Option<GCSerialInterface>;

pub struct GCGatewayMockInstanceCtx {
    pub(super) publish_datapoint_callback: Box<PublishDatapointValueIntercept>,
    pub(super) log_callback: Box<LogIntercept>,
    pub(super) get_last_datapoint_callback: Box<GetLastDatapointValueIntercept>,
    pub(super) get_ethernet_interface_callback: Box<GetEthernetInterfaceIntercept>,
    pub(super) get_serial_interface_callback: Box<GetSerialInterfaceIntercept>,
}

impl GCGatewayMockInstanceCtx {
    pub fn new() -> Box<Self> {
        Box::new(Self {
            publish_datapoint_callback: Box::new(|_| true),
            log_callback: Box::new(|log_level, line| {
                let log_converted = line.to_string_lossy();
                match log_level {
                    raw::eGCLogLevel_CRITICAL => error!("[PLUGIN] {log_converted}"),
                    raw::eGCLogLevel_ERROR => error!("[PLUGIN] {log_converted}"),
                    raw::eGCLogLevel_WARNING => warn!("[PLUGIN] {log_converted}"),
                    raw::eGCLogLevel_INFO => info!("[PLUGIN] {log_converted}"),
                    raw::eGCLogLevel_DEBUG => debug!("[PLUGIN] {log_converted}"),
                    level => error!("Log level={level} is not implemented in core"),
                }
            }),
            get_last_datapoint_callback: Box::new(|datapoint| {
                GCDatapointValue::new_boolean(datapoint, 0, false, GCDatapointValueQuality::new_good())
            }),
            get_ethernet_interface_callback: Box::new(|_| None),
            get_serial_interface_callback: Box::new(|_| None),
        })
    }
}

impl From<raw::GCCoreCtx> for &GCGatewayMockInstanceCtx {
    fn from(ctx: raw::GCCoreCtx) -> Self {
        // Safety:
        // This assumes that GCCoreCtx is a pointer to PluginCtx
        // It is used for a conversion between the FFI
        let a = ctx as *mut GCGatewayMockInstanceCtx;
        unsafe { &*a }
    }
}