Logo
UNICENS V2.3.0-4567
User Manual and API Reference
Node Scripting

Introduction

The idea behind the Node Scripting is to allow execution of custom scripts in remote nodes. That means, the user can specify scripts based on FBlock command syntax and run these on remote nodes by the use of the Node Scripting module (NS).

Attention
The Node Scripting module is designed and intended for the use of I2C and GPIO commands only. Therefore using the scripting module for any other FBlock INIC commands (for example Network, MediaLB, USB, Streaming, Connections, etc.) is expressly prohibited.

Definition of a Node Script

A node script is a data structure (see code snippet), composed of:

  • The amount time [in milliseconds] to pause before sending the Tx command.
  • The command based on INIC FBlock-Syntax to be transmitted
  • The expected result also based on INIC FBlock-Syntax.
/* Structure of a node script */
typedef struct Ucs_Ns_Script_
{
uint16_t pause; /* Pause before sending the Tx message. */
Ucs_Ns_ConfigMsg_t * send_cmd; /* Send command to be transmitted. */
Ucs_Ns_ConfigMsg_t * exp_result; /* Expected result. */

A Ucs_Ns_ConfigMsg_t message is based on INIC FBlock-Syntax and looks like this:

/* Structure of a ConfigMsg */
typedef struct Ucs_Ns_ConfigMsg_
{
uint8_t fblock_id; /* FBlock ID of the config msg. */
uint8_t inst_id; /* Instance ID of the config msg. */
uint16_t funct_id; /* Function ID of the config msg. */
uint8_t op_type; /* Operation type of the config msg. */
uint8_t data_size; /* Size of the data to be transmitted or to be checked. */
uint8_t * data_ptr; /* Reference to the data */

Operation

The user specifies the desired scripts and then calls the function Ucs_Ns_Run() for processing. The scripts can also be bound to the structure of the target node for automatic script execution after network startup.
The result of the Ucs_Ns_Run() operation is reported via the result callback function Ucs_Ns_ResultCb_t, which is passed by user in the arguments list of Ucs_Ns_Run(). It is possible to give unique callback functions for different scripts. In addition to this callback function and the referred UCS instance the function requires a reference to the Node where the script(s) should be executed, a pointer to the script list and the size of the script list.

Ucs_Return_t Ucs_Ns_Run(Ucs_Inst_t *self, Ucs_Rm_Node_t *node_ptr, Ucs_Ns_Script_t *script_list_ptr, uint8_t script_list_size, Ucs_Ns_ResultCb_t result_fptr);

The Ucs_Ns_Run() function starts the process to transmit the script(s) to the node and then checks for the expected results (specified by customer). The Node Scripting module will start a timer of 5200ms before sending the Tx command of each script. That is, if no incoming messages match the expected result of the script during this time the result code UCS_NS_RES_ERR_TIMEOUT is returned via the Ucs_Ns_ResultCb_t user callback function. When the script module couldn't perform the device synchronization of the remote device the result code UCS_NS_RES_ERR_SYNC is returned (this can be read in the detailed error messages, if enabled. See below). Also if the scripts couldn't be transmitted UCS_NS_RES_ERR_TX is returned. To help users to identify errors caused by defective scripts the result codes UCS_NS_RES_ERR_PAYLOAD and UCS_NS_RES_ERR_OPTYPE and the Ucs_Ns_ErrorInfo_t are given to the callback function. The script_count clarifies where the defective script is stored in the script list and funct_id gives the respective function ID. If the incoming message matches the expected result, UCS_NS_RES_SUCCESS is returned.

The Ucs_Ns_Run() function will return UCS_RET_ERR_API_LOCKED when attempting to execute a script in a node that is currently busy with other(s) previous script(s). The Ucs_Ns_Run() function is namely locked for a node when handling script(s) on this node and unlocked after reporting the result of the operation. However processing scripts can be executed on different nodes in parallel.

Note
Also note that the DataPtr member of the exp_result structure in Ucs_Ns_Script_t does not have to contain the full expected information. Since the validation of the data is only done for the expected length, User can either disable the data check on incoming messages by setting the expected length data_size element of Ucs_Ns_ConfigMsg_t to 0x00 or can just specify the maximum amount of data to be checked (Refer to the example below). However to set the expected length to long will effect that the message will be interpreted as incorrect. If the data_ptr is set to NULL the check is also disabled independently of the value of data_size.

The detailed error messages can be read when enabling the error trace output in ucs_cfg.h file as shown below.

/* File: ucs_cfg.h */
/*------------------------------------------------------------------------------------------------*/
/* Tracing & Debugging */
/*------------------------------------------------------------------------------------------------*/
# define UCS_TR_ERROR App_TraceError
extern void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[],
uint16_t vargs_cnt, ...);
/* File: app_trace.c */
void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[],
uint16_t vargs_cnt, ...)
{
if (file_ != NULL)
{
char outbuf[256];
va_list argptr;
uint16_t timestamp = (uint16_t)timeGetTime() - startup_time;
va_start(argptr, vargs_cnt);
(void)vsprintf(outbuf, entry_str, argptr);
va_end(argptr);
(void)fprintf(file_, "%5u | [%u] | Error | %s | %s\n", timestamp, ucs_user_ptr, module_str, outbuf);
(void)fflush(file_);
}
}

Example: Running node internal and external scripts

The example below outlines the execution of a script within a node with address 0x200. It shows the option to run the node internal script and how to run any other script which is not included in the node structure. This example is inserted as a guide and may not contain all of the necessary details and information.

/* Flag that checks whether node with address 0x200 is discovered by Node Discovering */
static bool node200_discovered = false;
/* Forward declaration of result callback function */
static void App_OnScriptingResult(uint16_t node_address, Ucs_Ns_ResultCode_t result, void *user_ptr);
/* Configuration Msg specification */
static uint8_t tx_data_1[] = { 0x00, 0x40, 0x01, 0x01 };
static uint8_t rx_data_1[] = { 0x0F, 0x00 };
static uint8_t tx_data_2[] = { 0x0F, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x0A, 0xAD, 0xAC, 0xBE, 0xEF };
//static uint8_t rx_data_2[] = { 0x0F, 0x00, 0x20, 0x04 }; /* Data Check is disabled */
static Ucs_Ns_ConfigMsg_t tx_msg_1 = { 0x00, 0x00, 0x6C1, 0x2, 4U, &tx_data };
static Ucs_Ns_ConfigMsg_t rx_msg_1 = { 0x00, 0x01, 0x6C1, 0xC, 2U, &rx_data };
static Ucs_Ns_ConfigMsg_t tx_msg_2 = { 0x00, 0x00, 0x6C4, 0x2, 12U, &tx_data_2 };
static Ucs_Ns_ConfigMsg_t rx_msg_2 = { 0x00, 0x01, 0x6C4, 0xC, 0x00U, NULL }; /* Set DataLen to 0x00 will skip data check on result */
/* Scripts specification */
#define SCRIPTS_200_SZ 2
static Ucs_Ns_Script_t scripts_200[SCRIPTS_200_SZ] = { { 0U, &tx_msg_1, &rx_msg_1 },
{ 50U, &tx_msg_2, &rx_msg_2 } };
/* Signature specification */
Ucs_Signature_t sig_200 = { 200U };
/* Nodes objects Specification */
static Ucs_Rm_Node_t node_200 = { &sig_200, &scripts_200[0], 2U, {0} };
/* Main function */
void main(uint8_t argc, char *argv[])
{
/* ... */
if (node200_discovered)
{
/* Run node internal script */
(void)Ucs_Ns_Run( ucs_inst_ptr,
0x200U, node_200.init_script_list_ptr,
&App_OnScriptingResult );
/* Run any script */
(void)Ucs_Ns_Run( ucs_inst_ptr, 0x200U,
any_script_list_ptr,
any_script_list_size,
&App_OnScriptingResult );
}
/* ... */
}
/* The result callback function */
static void App_OnScriptingResult( uint16_t node_address,
Ucs_Ns_ErrorInfo_t error_info,
void *user_ptr )
{
switch (result)
{
/* Do whatever is necessary here */
break;
/* Do whatever is necessary here */
break;
/* Do whatever is necessary here */
break;
/* Do whatever is necessary here */
break;
/* Do whatever is necessary here */
break;
/* Do whatever is necessary here */
break;
default:
/* Do whatever is necessary here */
break;
}
}