src.dualinventive.com/dinet/sec-multi-proxy/libdi/include/di/can/net/node.h

196 lines
6.8 KiB
C
Executable File

/**
* @file include/di/can/net/node.h
* @brief DI-Net CAN network node maintenaince
* @date Nov 2, 2016
* @author jjacobs
* @copyright 2016 Dual Inventive Technology Centre B.V.
*
* CAN network discovery
*/
#ifndef LIBDI_INCLUDE_DI_CAN_NET_NODE_H_
#define LIBDI_INCLUDE_DI_CAN_NET_NODE_H_
#include <stdbool.h>
#include <di/can/callback.h>
#include <di/can/net/node.h>
#ifdef __cplusplus
extern "C" {
#endif
struct di_can_ctx;
struct di_can_msg;
struct di_can_net;
struct di_can_net_node;
/**
* Node state
*/
enum di_can_net_node_states {
DI_CAN_NET_NODE_STATE_UNKNOWN, /**< Node is in unknown state */
DI_CAN_NET_NODE_STATE_ONLINE, /**< Node is online */
DI_CAN_NET_NODE_STATE_OFFLINE /**< Node is offline */
};
/**
* Node events for callbacks
*/
enum di_can_net_node_events {
DI_CAN_NET_NODE_EVENT_UNKNOWN, /**< Unknown event, never emitted to application callback */
DI_CAN_NET_NODE_EVENT_NEW, /**< New node detected */
DI_CAN_NET_NODE_EVENT_ERROR, /**< Node error change detected */
DI_CAN_NET_NODE_EVENT_ROLE_PASSIVE, /**< Node fulfils the passive role */
DI_CAN_NET_NODE_EVENT_ROLE_FOLLOWER, /**< Node fulfils the follower role */
DI_CAN_NET_NODE_EVENT_ROLE_LEADER, /**< Node fulfils the leader role */
DI_CAN_NET_NODE_EVENT_LEADER_OFFLINE, /**< Leader node went offline (due to heartbeat timeout) */
DI_CAN_NET_NODE_EVENT_LEADER_TAKEOVER_FAILED, /**< Leader takeover failed (application gave up leadership) */
DI_CAN_NET_NODE_EVENT_CONFLICT /**< Node conflict (role, nodeid) */
};
/**
* Node types list
*/
#define DI_CAN_NET_NODE_TYPE_LIST \
DI_CAN_NET_NODE_TYPE(UNKNOWN, "unknown", 0x00) \
DI_CAN_NET_NODE_TYPE(GATEWAY, "gateway", 0x01) \
DI_CAN_NET_NODE_TYPE(ZKL3000RC_MAIN, "zkl3000rc-main", 0x02) \
DI_CAN_NET_NODE_TYPE(ZKL3000RC_SWITCH_CONTROL, "zkl3000rc-switch-control", 0x03) \
DI_CAN_NET_NODE_TYPE(ZKL3000RC_SWITCH_MEAS, "zkl3000rc-switch-meas", 0x04) \
DI_CAN_NET_NODE_TYPE(ZKL3000RC_SWITCH_DRIVE, "zkl3000rc-switch-drive", 0x05) \
DI_CAN_NET_NODE_TYPE(TWS3000_WUM_MAIN, "tws3000-wum-main", 0x06) \
DI_CAN_NET_NODE_TYPE(TWS3000_WUM_MONITOR, "tws3000-wum-monitor", 0x07) \
DI_CAN_NET_NODE_TYPE(TWS3000_DUU, "tws3000-duu", 0x08) \
DI_CAN_NET_NODE_TYPE(TWS3000_DUM, "tws3000-dum", 0x09) \
DI_CAN_NET_NODE_TYPE(RVM_COMBOARD, "rvm-comboard", 0x0A) \
DI_CAN_NET_NODE_TYPE(RVM_SENSOR, "rvm-sensor", 0x0B)
#define DI_CAN_NET_NODE_TYPE(enumerator, str, id) \
DI_CAN_NET_NODE_TYPE_##enumerator = id,
enum di_can_net_node_types {
DI_CAN_NET_NODE_TYPE_LIST
};
#undef DI_CAN_NET_NODE_TYPE
/**
* Node role list
*/
#define DI_CAN_NET_NODE_ROLE_LIST \
DI_CAN_NET_NODE_ROLE(UNKNOWN, "unknown", 0x00) \
DI_CAN_NET_NODE_ROLE(PASSIVE, "passive", 0x01) \
DI_CAN_NET_NODE_ROLE(FOLLOWER, "follower", 0x02) \
DI_CAN_NET_NODE_ROLE(LEADER, "leader", 0x03)
#define DI_CAN_NET_NODE_ROLE(enumerator, str, id) \
DI_CAN_NET_NODE_ROLE_##enumerator = id,
enum di_can_net_node_roles {
DI_CAN_NET_NODE_ROLE_LIST
};
#undef DI_CAN_NET_NODE_ROLE
/**
* @name Callbacks
* @{
*/
/**
* Node event callback (including self), application is responsible for filtering
* @note When the application receives an event, the node type/role is updated AFTER the event
* is processed by the application. This mechanism is chosen so the application is able
* to make decisions based on the event and the previous role. The only exception is the
* DI_CAN_NET_NODE_NEW event which has role/type set before the application callback is
* executed.
* @param ctx CAN net subsystem context
* @param ev Node event
* @param node Node which triggered the event
*/
typedef void (*di_can_net_node_event_cb_t)(const struct di_can_net *ctx,
const enum di_can_net_node_events ev,
const struct di_can_net_node *node);
/**
* Foreach node type callback, used to itterate over the discovered/known nodes and perform some action
* @param ctx CAN context
* @param private_data Callback private data
* @param node Node found which is of searched type
* @retval DNOK when foreach can continue onto the next node, !DNOK when foreach must stop
*/
typedef di_errno_t (*di_can_node_foreach_type_cb)(struct di_can_ctx *ctx, void *private_data,
const struct di_can_net_node *node);
/** @} */
/**
* Update or add node
*/
void di_can_net_node_update(struct di_can_net *ctx, const struct di_can_net_node *data);
/** Update node error field */
di_errno_t di_can_net_node_update_error(struct di_can_net *ctx, const uint32_t nodeid, const di_errno_t err);
/**
* Check if node is self
*/
bool di_can_net_node_is_self(const struct di_can_net *ctx, const struct di_can_net_node *node);
/** Check if the node is of the same type as self (di_can_net_node_type enum) */
bool di_can_net_node_is_same_type_as_self(const struct di_can_net *ctx, const struct di_can_net_node *node);
/**
* Check if the node has the error field set (!DNOK)
* @note The ctx is locked in this function
*/
bool di_can_net_node_has_error(struct di_can_net *ctx, const struct di_can_net_node *node);
/**
* Update leader nodes state (OFFLINE) based on last seen time (heartbeat updates the node->seen time
* @note Must be called after di_can_net_lock
* @note The di_can_ctx is necessary when self becomes the leader
*/
void di_can_net_node_update_leaders_last_seen(struct di_can_ctx *ctx);
/**
* Set node event callback for application
* @note This callback is executed on node state change in di_can_net_execute.
*/
void di_can_net_node_set_event_callback(struct di_can_ctx *ctx, di_can_net_node_event_cb_t cb);
/**
* Run the registered node event callback
*/
void di_can_net_node_run_event_callback(const struct di_can_net *ctx,
const enum di_can_net_node_events ev, const struct di_can_net_node *node);
/**
* Finish the registered node event callback by signalling the application
* di_can_node_wait_for_event_callback_finish.
* @note When finish is called, all node updates should be processed!
*/
void di_can_net_node_run_event_callback_finish(struct di_can_net *ctx);
/**
* Wait for event callback to be finished
* @param ctx CAN context
* @param timeout_ms Timeout for wait in milliseconds
* @return DNOK when callback is finished, DNE_TIMEOUT when not finished
*/
di_errno_t di_can_node_wait_for_event_callback_finish(struct di_can_ctx *ctx, uint32_t timeout_ms);
/**
* Itterate over each node within the node type group
* @param ctx CAN context
* @param private_data Callback private data
* @param cb Callback for each found node
* @param type Nodes for given type to search for
*/
di_errno_t di_can_node_foreach_type(struct di_can_ctx *ctx, void *private_data, di_can_node_foreach_type_cb cb,
const enum di_can_net_node_types type);
#ifdef __cplusplus
}
#endif
#endif /* LIBDI_INCLUDE_DI_CAN_NET_NODE_H_ */