This document describes the internals of the embeNET demo application running on NUCLEO-WL33CC1 boards and provides information on how to modify and extend the demo.
How does the demo application work
The demo application uses the embeNET Node C API library to join the network and run two network services:
- ENMS: embeNET Network Management service that allows to gather information about the network operation from the nodes
- custom exemplary service, that sends out a simple message every 5 seconds and also reacts to some simple messages
Below is a short explanation of all important steps. Basically the whole application fits into the main function.
Initialization
The initialization part configures STM32 HAL, system clock, GPIOs and USART1:
HAL_Init();
SystemClock_Config();
PeriphCommonClock_Config();
MX_GPIO_Init();
MX_MRSUBG_Init();
MX_USART1_UART_Init();
MX_AES_Init();
MX_RNG_Init();
MX_TIM2_Init();
MX_LPUART1_UART_Init();
BSP_LED_Init(LED_RED);
BSP_LED_Init(LED_GREEN);
BSP_LED_Init(LED_BLUE);
BSP_LED_On(LED_RED);
Next we configure the logging facility of the embeNET:
LOGGER_SetOutput(logOutputWrapper, NULL);
LOGGER_SetRuntimeLevel(LOGGER_LEVEL_TRACE);
LOGGER_Disable();
Next the embeNET stack is initialized with additional code that prints the version number:
.onLeft = onLeft,
.onJoinAttempt = onJoinAttempt,
.onDataOnUnregisteredPort = dataOnUregisteredPort,
.onQuickJoinCredentialsObsolete = onQuickJoinCredentialsObsolete
};
printf(
"embeNET Node v%d.%d.%d initialized\n", ver.
hi, ver.
lo, ver.
rev);
} else {
printf("Failed to initialize embeNET Node\n");
}
EMBENET_Version EMBENET_NODE_GetVersion(void)
EMBENET_Result EMBENET_NODE_Init(EMBENET_NODE_EventHandlers const *eventHandlers)
EMBENET_NODE_OnJoined onJoined
After that the ENMS service is initialized:
uint8_t hardwareId[16] = {0x00};
memcpy(hardwareId, (void const*)UID_BASE, 12);
printf("ENMS service initialized\n");
} else {
printf("Failed to initialize ENMS service!\n");
}
EnmsResult ENMS_NODE_Init(EnmsNode *enmsNode, uint16_t port, uint8_t const hwId[16], EnmsIndicationPolicy const *indicationPolicy)
EnmsIndicationPolicy const * ENMS_NODE_GetSmallScalePolicy(void)
uint16_t ENMS_NODE_GetDefaultPort(void)
We also start a clever LED blinking task, which will show that all the nodes that joined one network are synchronized:
synchronous_led_task_init();
In case of root we just start it:
printf("Root started successfully\n\r");
} else {
printf("Failed to start as root!\n\r");
}
EMBENET_EUI64 EMBENET_NODE_GetUID(void)
EMBENET_Result EMBENET_NODE_RootStart(void const *panData, size_t panDataSize)
In case of nodes we start the custom demo service and MQTT-SN service:
udp_service_init();
mqttsn_client_service_init();
EnmsResult ENMS_NODE_RegisterService(EnmsNode *enmsNode, char const *serviceName, uint8_t initialServiceState)
Joining the network
In order to join the network the node has to setup the required network configuration:
.
k1.
val = { 0xc0, 0x8b, 0x76, 0x62, 0x77, 0x09, 0x9e, 0x7d, 0x7e, 0x9c, 0x02, 0x22, 0xf1, 0x68, 0xcc, 0x9e },
.psk.val = {0x46, 0xd7, 0xdc, 0x94, 0xe8, 0xee, 0x74, 0x96, 0xce, 0xaf, 0x54, 0xa3, 0xab, 0x64, 0xcb, 0xeb },
};
printf("Trying to join a network...\n\r");
EMBENET_Result EMBENET_NODE_Join(EMBENET_NODE_JoinConfig const *config)
The main loop
The application's main loop consists of a call to:
- embeNET Node processing function
- MQTT-SN service process (only needed for polling button status)
while (1) {
#if 1 != IS_ROOT
mqttsn_client_service_proc();
#endif
}
void EMBENET_NODE_Proc(void)
Network join event
Once the node joins the network an event callback will be called. In our demo application this callback simply starts the network services:
printf("Joined network with PANID: x%04" PRIx16 "\n", panId);
printf("Starting ENMS service\n");
if (ENMS_NODE_RESULT_OK != enmsStartStatus) {
printf("ENMS service failed to start with status %d\n", (int) enmsStartStatus);
}
custom_service_start();
mqttsn_client_service_start();
}
EnmsResult ENMS_NODE_Start(EnmsNode *enmsNode)
Network leave event
In case when node gets disconnected from the network, another callback is called. In our demo application this callback stops the network services:
static void onLeft(void) {
printf("Node has left the network\n");
if (ENMS_NODE_RESULT_OK == enmsStopStatus) {
printf("ENMS service stopped\n");
} else {
printf("ENMS service failed to stop with status %d\n", (int)enmsStopStatus);
}
custom_service_stop();
mqttsn_client_service_stop();
}
EnmsResult ENMS_NODE_Stop(EnmsNode *enmsNode)
Handling critical errors
In cases when the embeNET stack detects a critical condition, the following handler is called by the stack, giving a chance to react:
__attribute__((noreturn)) void EXPECT_OnAbortHandler(char const* why, char const* file, int line) {
printf("Program aborted: %s %s:%i\n", why, file, line);
while(1) {
;
}
__builtin_unreachable();
}
Customizing and extending the demo application
The structure of the firmware project embenet_demo_cubeide is mostly generated by STM32CubeMX application. The source *.ioc* file is included in the project. This allows you to easily customize the peripherals for your demo project as needed.
>The only requirement is NOT to change configuration of peripherals used by the port implementation, i.e. RADIO, CRYP, TIM2.
Writing or extending a custom network service.
The best starting point is to look at implementation of the existing custom_service.
Disabling "zero rule"
In order to disable the "zero rule", delete the rule with "uid": 0,
from your config.json file, and add appropriate rules for your nodes, for example:
"join_rules": [
{
"uid": 2,
"psk": "0x1ccd738f70a35be9574738ad190f86f2"
},
{
"uid": 3,
"psk": "0xdc2eafe4016303ebb1aa1b4b2ed4fda0"
}
]
This will allow only nodes with uid = 2 and 3, to join the network, provided that their PSKs match those from config.json file.
Using custom name for network interface
You may specify the name of desired network interface in .json file, by adding on root level:
"interface_name": "your-name"
Limitations of embeNET demo application
The demo version of the embeNET stack allows to connect up to 10 nodes only, with network depth of max. 3 hops.