ELA T Frame V2 Example

ELA T Frame V2 Example

1. Understanding the Script

This example suits for all “T”, “T EN” and “T Probe” ELA beacons that are running on V2 format data.


1.1. Defines

Initially script generates numerous definitions, primarily intended to define the protocol structure. The first eight protocol definitions pertain to the packet header used by XG devices, which includes the MAC address, advertisement message type, and RSSI. For further details regarding the packet header, please refer to the function documentation: bt_adv_packet_read().

Next three bytes are standard flag data.

Then goes manufacturer data which comprises of manufacturer data header (data type and length), a company identifier, ELA beacon identifier (in this case it’s “T”, “T EN”, “T Probe” identifier) and current temperature data.

The remaining portion of the data contains ELA beacon name header and name itself.

image-20250521-083729.png

1.2. Scan Filter

Next, we specify an ELA identifier to serve as a filter for manufacturer data. In particular, the values 0x07 0x57 represent ELA company identifier (but it’s passed as little-endian 0x57 0x07), and 0x12 denotes the “T”, “T EN”, “T Probe” format type:

/** @brief ela t beacon setup */ new ela_t_v2_identifier[3] = [0x57, 0x07, 0x12];

1.3. Initial Setup

The main function primarily performs the initial setup, including variable initializations and scan configuration.

/** * @brief Main function that initializes the Bluetooth scan, debug peripheral and MQTT callback */ main() { Init(MQTT_PUBLISH_PENDING); Init(RS232, RS232_SPEED, WORD_LENGTH, STOP_BITS, PARITY); debug_init(RS232); bt_init(); bt_scan_init(scan_parameters); bt_scan_filter_add(BT_SCAN_FILTER_TYPE_MANUFACTURER_DATA , ela_t_v2_identifier, sizeof(ela_t_v2_identifier)); bt_scan_filter_enable(BT_SCAN_FILTER_MANUFACTURER_DATA, false); bt_scan_callback_enable(BT_FILTER_MATCH); bt_scan_start(); for(;;) { Delay(10000); } }

1.4. Scan Data Callback

During the execution of the main function, the system initiates a scan for ELA “T”, “T EN”, “T Probe” devices. When an ELA “T”, “T EN”, “T Probe” device is detected, control is transferred to a designated callback function. Within this function, the advertisement packet broadcast by the ELA device is accessed and parsed accordingly.

/** * @brief Device event callback function * * @param event Device event * @return 0 on success */ public callback (event) { switch(event) { case BT_FILTER_MATCH: { memset(scanned_adv_data, 0x00, sizeof(scanned_adv_data)); memset(str_buffer, 0x00, sizeof(str_buffer)); bt_adv_packet_read(scanned_adv_data, BT_FILTER_MATCH); ela_t_parse(); } case MQTT_PUBLISH_PENDING: { ela_t_sensors_publish(); } } }

1.5. Beacon Data Parsing

The ela_t_parse function retrieves and formats the name and parses temperature value. This function employs the debug_print(); function for outputting information. To suppress these print statements, the user must comment out or remove the debug include.

/** * @brief ela t beacon parse function that parses incomming ela t beacon messages */ ela_t_parse() { new Float:temperature = 0.0; debug_print("Beacon name: "); strcopy(str_buffer, scanned_adv_data[ELA_V2_NAME_DATA_1]); debug_print(str_buffer); debug_print("\r\n"); write_buf(SENSOR_ELA_NAME, strlen(str_buffer), str_buffer); if(scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_MSB] & 0x80 == 0x80) // Check if temperature is negative { temperature = floatmul(float((~((scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_MSB] << 8) | scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_LSB]) & 0x0000FFFF) + 1), -0.01); } else { temperature = floatmul(((scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_MSB] << 8) | scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_LSB]), 0.01); } debug_print("Temperature: %f\r\n\r\n", temperature); set_val(SENSOR_ELA_TEMPERATURE, temperature); ela_t_received_flag = true; }

1.6. Sensors For Publishing

These values are stored at predefined sensors at the top of the script with the rest of defines:

/** @brief Data publish setup */ #define SENSOR_ELA_NAME SENSOR_STRING_1 #define SENSOR_ELA_TEMPERATURE SENSOR_F32_USER_DEFINED_1

1.7. Publishing Data

Once the SENSOR_GNSS_COORDINATES is ready to be published, the code will jump to MQTT_PUBLISH_PENDING callback in which we call ela_t_sensors_publish function. Function is used to include the configured sensors with ELA beacon values for publishing:

/** * @brief Sensor publish function that adds data for publishing if ela t beacon was detected */ ela_t_sensors_publish() { if (ela_t_received_flag == true) { MQTT_PublishSensor(SENSOR_ELA_NAME); MQTT_PublishSensor(SENSOR_ELA_TEMPERATURE); ela_t_received_flag = false; } }

1.8. Printed Data

The data output to the RS232 interface using the debug_print() function will appear as follows:

Beacon name: P T EN 80CB80
Temperature: 26.35

Beacon name: P T EN 80CB81
Temperature: 26.31

Beacon name: P T EN 80CB80
Temperature: 26.35

Beacon name: P T EN 80CB81
Temperature: 26.31


2. Full Example Code

/* * Script Name: ELA T frame V2 example * Version: 1.0.0 * Created: 2025-05-14 * Description: This script demonstrates how to configure scanner for ela t beacon scanning, parse ela t beacon * beacons with version 2 frame type and publish parsed data. This script detects all possible ela t beacons in range. * Usage: * - Script automatically parses ela “T”, “T EN” and “T Probe” beacon messages inside 'ela_t_parse' function. * - To configure data publish sensors user should edit defines under 'Data publish setup' * - To remove debug messages user should comment out or remove '#include <debug>' * Prerequisites: Device firmware 01_131 or up. Auxiliary MCU firmware 2.1.7 or up. * Changelog: * 2025-05-14 (1.0.0): */ #include <io> #include <read> #include <float> #include <string> #include <core> #include <write> #include <define> #include <socket> #include <bluetooth> #include <debug> /** @brief Debug peripheral setup */ #define RS232_SPEED 115200 #define WORD_LENGTH WORDLENGTH_8 #define STOP_BITS STOPBITS_1 #define PARITY PARITY_NONE /** @brief Data publish setup */ #define SENSOR_ELA_NAME SENSOR_STRING_1 #define SENSOR_ELA_TEMPERATURE SENSOR_F32_USER_DEFINED_1 /** @brief Scan data */ #define ADV_HEADER_MAC_BYTE_1 0 #define ADV_HEADER_MAC_BYTE_2 1 #define ADV_HEADER_MAC_BYTE_3 2 #define ADV_HEADER_MAC_BYTE_4 3 #define ADV_HEADER_MAC_BYTE_5 4 #define ADV_HEADER_MAC_BYTE_6 5 #define ADV_HEADER_ADV_TYPE 6 #define ADV_HEADER_RSSI 7 #define ELA_V2_FLAGS_DATA_TYPE_LEN 8 #define ELA_V2_FLAGS_DATA_TYPE 9 #define ELA_V2_FLAGS 10 #define ELA_V2_MANUF_DATA_LEN 11 #define ELA_V2_MANUF_DATA_TYPE 12 #define ELA_V2_MANUF_DATA_ELA_CIN_LSB 13 #define ELA_V2_MANUF_DATA_ELA_CIN_MSB 14 #define ELA_V2_MANUF_DATA_TEMP_ID 15 #define ELA_V2_MANUF_DATA_T_DATA_LSB 16 #define ELA_V2_MANUF_DATA_T_DATA_MSB 17 #define ELA_V2_NAME_DATA_LEN 18 #define ELA_V2_NAME_DATA_TYPE 19 #define ELA_V2_NAME_DATA_1 20 #define ELA_V2_NAME_DATA_2 21 #define ELA_V2_NAME_DATA_3 22 #define ELA_V2_NAME_DATA_4 23 #define ELA_V2_NAME_DATA_5 24 #define ELA_V2_NAME_DATA_6 25 #define ELA_V2_NAME_DATA_7 26 #define ELA_V2_NAME_DATA_8 27 #define ELA_V2_NAME_DATA_9 28 #define ELA_V2_NAME_DATA_10 29 #define ELA_V2_NAME_DATA_11 30 #define ELA_V2_NAME_DATA_12 31 #define ELA_V2_NAME_DATA_13 32 #define ELA_V2_NAME_DATA_14 33 #define ELA_V2_NAME_DATA_15 34 /** @brief Convenience defines */ #define SCANNED_DATA_BUFFER_SIZE 40 #define ELA_T_NAME_LENGTH 15 /** @brief ela t beacon setup */ new ela_t_v2_identifier[3] = [0x57, 0x07, 0x12]; new scan_parameters[.type, .options, .interval, .window, .timeout, .interval_coded, .window_coded] = [ BT_SCAN_TYPE_ACTIVE, BT_ADV_OPT_NONE, BT_SCAN_INTERVAL_FAST, BT_SCAN_WINDOW_FAST, 0, 0, 0 ]; new scanned_adv_data[SCANNED_DATA_BUFFER_SIZE]; new str_buffer[ELA_T_NAME_LENGTH+1]; new bool:ela_t_received_flag = false; forward public callback (event); forward ela_t_parse(); /** * @brief Device event callback function * * @param event Device event * @return 0 on success */ public callback (event) { switch(event) { case BT_FILTER_MATCH: { memset(scanned_adv_data, 0x00, sizeof(scanned_adv_data)); memset(str_buffer, 0x00, sizeof(str_buffer)); bt_adv_packet_read(scanned_adv_data, BT_FILTER_MATCH); ela_t_parse(); } case MQTT_PUBLISH_PENDING: { ela_t_sensors_publish(); } } } /** * @brief Sensor publish function that adds data for publishing if ela t beacon was detected */ ela_t_sensors_publish() { if (ela_t_received_flag == true) { MQTT_PublishSensor(SENSOR_ELA_NAME); MQTT_PublishSensor(SENSOR_ELA_TEMPERATURE); ela_t_received_flag = false; } } /** * @brief ela t beacon parse function that parses incomming ela t beacon messages */ ela_t_parse() { new Float:temperature = 0.0; debug_print("Beacon name: "); strcopy(str_buffer, scanned_adv_data[ELA_V2_NAME_DATA_1]); debug_print(str_buffer); debug_print("\r\n"); write_buf(SENSOR_ELA_NAME, strlen(str_buffer), str_buffer); if(scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_MSB] & 0x80 == 0x80) // Check if temperature is negative { temperature = floatmul(float((~((scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_MSB] << 8) | scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_LSB]) & 0x0000FFFF) + 1), -0.01); } else { temperature = floatmul(((scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_MSB] << 8) | scanned_adv_data[ELA_V2_MANUF_DATA_T_DATA_LSB]), 0.01); } debug_print("Temperature: %f\r\n\r\n", temperature); set_val(SENSOR_ELA_TEMPERATURE, temperature); ela_t_received_flag = true; } /** * @brief Main function that initializes the Bluetooth scan, debug peripheral and MQTT callback */ main() { Init(MQTT_PUBLISH_PENDING); Init(RS232, RS232_SPEED, WORD_LENGTH, STOP_BITS, PARITY); debug_init(RS232); bt_init(); bt_scan_init(scan_parameters); bt_scan_filter_add(BT_SCAN_FILTER_TYPE_MANUFACTURER_DATA , ela_t_v2_identifier, sizeof(ela_t_v2_identifier)); bt_scan_filter_enable(BT_SCAN_FILTER_MANUFACTURER_DATA, false); bt_scan_callback_enable(BT_FILTER_MATCH); bt_scan_start(); for(;;) { Delay(10000); } }