Sample Applications

These sample applications are included with the SDK. Modules are in custom/module and projects are in custom/project. Once you have built a project, find the ROM and other project files in xPico200/work.


Custom Data

The custom_data module demonstrates how to define and access custom configurables, how to embed files in a module, and how to overlay files using embedded files.

Build it from project customDataDemo.

When this project is loaded onto the xPico200 device, a new Custom Data tab appears in Web Manager. Click the tab to go to the Custom Device Configuration page. Bring up the trouble log on a line to watch what is happening. Change Name, Rank, and Serial Number, click Submit, and observe the changes on the trouble Log.

Function Details

The following is an overview of the functions used in the custom_data module.

static bool getXmlValue(
    const struct xml_emit_value_specification *xevs,
    char *buffer,
    size_t size
) {...}

Use ltrx_output_stream_init_to_buffer() to set up an output stream and write the data to the buffer and ltrx_xml_emit_value() to emit the XML value onto the buffer.

static bool getItem(
    const char *desiredItemName,
    char *buffer,
    size_t size
) {...}

Find the desired custom item and write it to the buffer. Use snprintf() to write up to size bytes to str under the control of a format string.

static void customConfigMonitorThread(void *opaque) {...}

Find any new config values and print them out to the trouble log.


BLE Beacon Scanner

The ble_beacon_scanner module demonstrates the device's ability to scan for iBeacons in the vicinity of the device.

This demo creates a Line Protocol called Beacon Scanner. When this Line Protocol is selected for the UART, it can receive results from the scanner. Send the letter s (lowercase) to start receiving results. Once started, send any character to stop receiving results. Each beacon scanned will be on a new line, with the following fields separated by a comma: UUID, Major, Minor, RSSI.

For example:

DB38C9EA-FA47-168C-424A-11B3133291FE,39254,40804,-69

If the UART of the xPico 250 is to be used to scan for beacons as well as to send or receive data over the Wi-Fi or Ethernet networks, then:

  • Configure Line 1 to Mux Protocol
  • Configure Virtual Line 1 to Beacon Scanner Protocol
  • Use the Mux Virtual Line functions to access the data. For example:
    1v1\r
    1sb~\r
    s~\r
    1p\r
    1rb~500\r

The ble_beacon_scanner module is not designed to work with the other included Bluetooth modules without modification. To use multiple modules correctly, you may need to modify the code.

Build it from project bleBeaconScannerDemo.

Function Details

The following is an overview of the functions used in the ble_beacon_scanner module.

static wiced_result_t ble_gatt_demo_management_callback(
    wiced_bt_management_evt_t event,
    wiced_bt_management_evt_data_t *p_event_data
) {...}

Handles all events that the device receives when enabling or disabling Bluetooth, or when scans are started.

void beacon_scanner_start(void) {...}

Uses ltrx_thread_create() to create a thread and start it.

static void bt_thread_func(
    void *arg
) {...}

Uses wiced_bt_stack_init() to initialize the Bluetooth controller and stack. Uses wiced_bt_ble_scan() to scan for beacons.

This thread also receives messages via a queue from subscribers to the scanner. It adds and removes subscribers based on the messages, and restarts the scanner when it sends a message that it has finished.

static wiced_result_t ble_scan_callback(
    wiced_bt_ble_scan_results_t* result,
    uint8_t* p_adv_data
) {...}

This callback is called when a new scan result is available, or when the scanner stops scanning.

If there is a new scan result, it checks that the format matches the iBeacon standard. If it does, then it extracts the UUID, Major, Minor, and RSSI value, and sends a message to all the subscribers with the data.

If it is the last scan, it sends a message to the main thread that the scanner has turned off


BLE GATT Demo

The ble_gatt_demo module demonstrates the device's Bluetooth Low Energy (BLE) capabilities.

The BLE GATT demo creates a Bluetooth connection between the device and a phone and demonstrates reading and writing data. Data transmission is recorded in the TLOG. This demo requires the use of the LightBlue app, which can be found on Google Play and the Apple App Store. The default SSID used by the demo is BLE Gatt Demo.

The ble_gatt_demo module is not designed to work with the other included Bluetooth modules without modification. To use multiple modules correctly, you may need to modify the code.

Build it from project bleGattDemo.

Function Details

The following is an overview of the functions used in the ble_gatt_demo module.

static wiced_result_t ble_gatt_demo_management_callback(
    wiced_bt_management_evt_t event,
    wiced_bt_management_evt_data_t *p_event_data
) {...}

Handles all events that the device receives such as reading, writing, pairing, and bonding. Calls specific functions for each event type. Uses wiced_bt_ble_security_grant() to grant access. Uses wiced_bt_dev_confirm_req_reply() to confirm the numeric value for pairing.

static void ble_gatt_demo_smp_bond_result(
    uint8_t result
) {...}

Copies the Bluetooth address and saves it to the device. Allocates memory using MALLOC_ZEROED().

static void ble_gatt_demo_encryption_changed(
    wiced_result_t result,
    uint8_t* bd_addr
) {...}

Sets the encryption.

static void ble_gatt_demo_send_message(void) {...}

Uses wiced_bt_gatt_send_notification() and wiced_bt_gatt_send_indication() to send data to the phone from the device when the phone is subscribed from LightBlue.

void ble_gatt_demo_start(void) {...}

Starts the BLE GATT demo.

bool ble_gatt_demo_thread_init(void) {...}

Uses ltrx_thread_create() to create a thread and start it. Allocates memory using MALLOC_ZEROED().

static void bt_thread_func(
    void *arg
) {...}

Uses wiced_bt_stack_init() to initialize the Bluetooth controller and stack. Uses TLOG() to write to the Trouble Log. Uses ltrx_network_get_mac_address() to retrieve the MAC address.

static void bt_gatt_init(void) {...}

Uses wiced_bt_gatt_register() to register an application callback. Uses TLOG() to write to the Trouble Log. Allocates memory for the GATT server using MALLOC_ZEROED(). Initializes the GATT database using wiced_bt_gatt_db_init(). Starts advertising using wiced_bt_start_advertisements().

static wiced_bt_gatt_status_t bt_gatt_connection_status_handler(
    wiced_bt_gatt_connection_status_t *p_status
) {...}

Checks if the device is connected and calls the appropriate function depending on the connection status.

static wiced_bt_gatt_status_t ble_gatt_demo_gatt_connection_up(
    wiced_bt_gatt_connection_status_t *p_status
) {...}

Stops advertising using wiced_bt_start_advertisements(). Uses TLOG() to write to the Trouble Log.

static wiced_bt_gatt_status_t ble_gatt_demo_gatt_connection_down(
    wiced_bt_gatt_connection_status_t *p_status
) {...}

Starts advertising using wiced_bt_start_advertisements(). Uses TLOG() to write to the Trouble Log.

static wiced_bt_gatt_status_t bt_gatt_request_handler(
    wiced_bt_gatt_attribute_request_t *p_data
) {...}

Calls the appropriate function based on the request type.

static wiced_bt_gatt_status_t ble_gatt_demo_gatts_req_read_handler(
    uint16_t conn_id, wiced_bt_gatt_read_t * p_read_data
) {...}

Processes read requests from the phone.

static attribute_t * ble_gatt_demo_get_attribute(
    uint16_t handle
) {...}

Returns the requested attribute.

void ble_gatt_demo_set_advertisement_data(void) {...}

Uses wiced_bt_ble_set_raw_advertisement_data() to set the advertisement information. Uses wiced_bt_ble_set_raw_scan_response_data() to set the scan response data.

void ble_gatt_demo_advertisement_stopped(void) {...}

Starts advertising using wiced_bt_start_advertisements().

void ble_gatt_demo_save_link_key(
    wiced_bt_device_link_keys_t paired_device_keys
) {...}

Saves the link key from the device.

static wiced_bt_gatt_status_t ble_gatt_demo_gatts_req_conf_handler(
    uint16_t conn_id,
    uint16_t handle
) {...}

Processes confirmations.

wiced_bt_gatt_status_t wiced_bt_gatt_callback(
    wiced_bt_gatt_evt_t event,
    wiced_bt_gatt_event_data_t *p_data
) {...}

Part of the GATT database initialization. Receives an event and calls the applicable function.

static wiced_bt_gatt_status_t ble_gatt_demo_gatts_req_write_handler(
    uint16_t conn_id,
    wiced_bt_gatt_write_t * p_data
) {...}

Writes data from the phone to the device. Uses TLOG() to write to the Trouble Log. If connecting an LED through GPIO to use with the demo, update the code in this function to access the LED. Allocates memory using MALLOC_ZEROED().

void ble_gatt_demo_gatts_increment_notify_value(void) {...}

Sets the counter, counting the number of writes done from the phone to the device.


Bluetooth OEM Provisioning

The bt_oem_provisioning module implements Lantronix proprietary sample Bluetooth provisioning profile. Before running this sample app, make sure the hardware supports Bluetooth.

This sample app runs the xPico 250 device as a Bluetooth peripheral device, with Lantronix Gateway Provisioning mobile app as the central device. See the Lantronix Gateway Provisioning mobile app documentation for iOS or Android for more information. Alternately, LightBlue can be used to connect to the xPico 250 device using Bluetooth. Find it on Google Play or App Store.

The bt_oem_provisioning module is not designed to work with the other included Bluetooth modules without modification. To use multiple modules correctly, you may need to modify the code.

Build it from project btOemProvisioningDemo.

Function Details

The following is an overview of the bt_oem_provisioning module.

The wiced_bt_cfg.c file contains settings, scan, advertisement, and GATT configurations for the Bluetooth stack, while the bt_oem_provisioning.c file contains the following functions.

static const uint8_t bt_prov_gatt_server_database[]

The GATT database defines services, characteristics and descriptors supported by the sensor. Each attribute in the database has a handle, (characteristic has two, one for characteristic itself, another for the value). The handles are used by the peer to access attributes. Definition of characteristics and descriptors has GATT Properties (read, write, notify...) but also has permissions which identify if and how peer is allowed to read or write into it.

 void bt_oem_provisioning_start(void) {...}

Allocate memory using MALLOC_ZEROED() and initiate Bluetooth provisioning thread funtions.

static void bt_thread_func(void *arg) {...}

Set the prinicple interface to Ethernet or WLAN, initialize Bluetooth, and set Bluetooth config values. Get the device MAC address and print the MAC address to trouble log. Calls the init_gatt_attributes function.

static void init_gatt_attributes(void) {...}

Initiate GATT attributes; enable Bluetooth low energy applications to configure themselves as a client or server device.

uint8_t calculate_checksum(char* data, uint16_t len) {...}

Calculate the checksum value (for checking for errors introduced during data transmission or storage).

void dummyFunc(
  enum ltrx_user_message_severity severity,
  void *pOpaque
) {...}

A dummy function for the demo. Called by process_xml_data.

void dummyWrFunc(
  const char *message,
  size_t length,
  void *pOpaque
) {...}

A dummy write function for the demo. Called by process_xml_data.

uint8_t process_xml_data(void) {...}

Check for errors by comparing the checksum result with size of the Bluetooth config data and then write message to stream. Finally, import the XML using ltrx_xml_import_from_stream().

bool bt_oem_provisioning_thread_init( void ) {...}

Use ltrx_thread_create() to create a thread and start it.

static void bt_prov_gatt_server_init( void ) {...}

This function is executed in the BTM_ENABLED_EVT management callback. It registers with stack to receive GATT callback, tells stack to use our GATT database, sets the advertising parameters and makes the device discoverable.

void bt_prov_set_advertisement_data(void) {...}

Set up advertisement data with 16 byte UUID and device name. Use wiced_bt_ble_set_raw_advertisement_data() to set advertisement raw data and wiced_bt_ble_set_raw_scan_response_data() to set scan response raw data.

void bt_prov_advertisement_stopped( void ) {...}

If the device is set to stay connected but there is no connection ID, start advertisement again.

void bt_prov_save_link_key(
  wiced_bt_device_link_keys_t paired_device_keys
) {...}

Copy paired device keys to memory.

static wiced_result_t bt_prov_bt_management_callback(
  wiced_bt_management_evt_t event,
  wiced_bt_management_evt_data_t *p_event_data
) {...}

Respond when link event occurs; wifi_introducer bt/ble link management callback.

static void bt_prov_send_message_scanned( void ) {...}

Send notification when scanning. Use wiced_bt_gatt_send_notification() to send connection ID.

static void bt_prov_send_message_joined( void ) {...}

Send notification when joined. Use wiced_bt_gatt_send_notification() to send join value.

static void bt_prov_send_message_xmlcfg_status( void ) {...}

Use wiced_bt_gatt_send_notification() to send the XML value.

static attribute_t * bt_prov_get_attribute( uint16_t handle ) {...}

Find attribute description by handle.

static wiced_bt_gatt_status_t bt_prov_gatt_server_read_request_handler(
  int16_t conn_id,
  wiced_bt_gatt_read_t * p_read_data
) {...}

On read request or command from peer device, process read request or command from peer device.

static void scan_wifi_network(void) {...}

Scan WiFi networks and call bt_prov_send_message_scanned to send a message with the information.

static wiced_bt_gatt_status_t bt_prov_gatt_server_write_request_handler(
  uint16_t conn_id,
  wiced_bt_gatt_write_t * p_data
) {...}

On write request or command from peer device, process write request or write command from peer device.

static wiced_bt_gatt_status_t bt_prov_gatt_server_write_and_execute_request_handler(
  uint16_t conn_id,
  wiced_bt_gatt_exec_flag_t exec_flag
) {...}

Write execute procedure.

static wiced_bt_gatt_status_t bt_prov_gatt_server_mtu_request_handler(
  uint16_t conn_id,
  uint16_t mtu
) {...}

On MTU request, process MTU request from the peer.

static wiced_bt_gatt_status_t bt_prov_gatt_server_confirmation_handler(
  uint16_t conn_id,
  uint16_t handle
) {...}

Server confirmation.

static wiced_bt_gatt_status_t bt_prov_gatt_server_connection_up(
  wiced_bt_gatt_connection_status_t *p_status
) {...}

This function is invoked when connection is established.

static wiced_bt_gatt_status_t bt_prov_gatt_server_connection_down(
  wiced_bt_gatt_connection_status_t *p_status
) {...}

This function is invoked when connection is lost.

static wiced_bt_gatt_status_t bt_prov_gatt_server_connection_status_handler(
  wiced_bt_gatt_connection_status_t *p_status
) {...}

Connection up/down event.

static wiced_bt_gatt_status_t bt_prov_gatt_server_request_handler(
  wiced_bt_gatt_attribute_request_t *p_data
) {...}

Process GATT request from the peer.

static wiced_bt_gatt_status_t bt_prov_gatt_server_callback(
  wiced_bt_gatt_evt_t event,
  wiced_bt_gatt_event_data_t *p_data
) {...}

Callback for various GATT events. As this application performs only as a GATT server, some of the events are omitted.


BT Classic Client

The bt_classic_client module implements a Bluetooth SPP master. This sample application runs the xPico 250 device as a Bluetooth client, allowing connections to Bluetooth slave servers.

The application provides a CLI interface using status actions to drive functionality. From the status CLI menu, the application creates the BT Classic SPP Example menu level. In that menu level, the following actions are available:

Scan

This starts a BT inquiry and prints the results, including device name (if available), BT address (BDADDR), and reported RSSI value.

Connect <bdaddr>

This command initiates a connection to the device with the specified BDADDR. This is a one-time action with no retries. It is possible for this action to fail, in which case it should be tried again.

Transmit <value>

This command transmits the specified string to the connected peer device.

Loglevel Get

This command displays the current level of debug logging in the application.

Loglevel Set <value>

This command sets the current debug logging level. Valid levels range from 0 to 4.

Higher logging levels will log additional informational TLOG messages. At the highest level (4), the most information is logged, including all I/O with the peer device.

Show

This command displays the results from the scan message, if available, as well as connection status and the total number of bytes transmitted and received to/from the peer device.

In addition to the available CLI commands, by default the application will automatically receive data from the connected peer device and echo it back.

The bt_classic_client module is not designed to work with the other included Bluetooth modules without modification. To use multiple modules correctly, you may need to modify the code.

Build it from btClassicClientDemo.

Function Details

The following is an overview of the functions used in the bt_classic_client module.

static void bt_rfcomm_client_conn_cback(
    wiced_bt_rfcomm_result_t code,
    uint16_t port_handle
) {...}

Use to receive connection status update asynchronously. Use TLOG() to log to the TLOG. Call spp_rfcomm_acceptor_opened(), spp_rfcomm_opened(), or spp_rfcomm_closed() depending on status.

static void bt_classic_client_connect(wiced_bt_device_address_t bd_addr) {...}

Create the Bluetooth connection using wiced_bt_rfcomm_create_connection().

static void bt_classic_client_disconnect(void) {...}

Disconnect the Bluetooth connection using wiced_bt_rfcomm_remove_connection().

static void bt_classic_client_link_key_store(wiced_bt_device_link_keys_t *keys) {...}

Store the Bluetooth key.

static bool bt_classic_client_link_key_load(wiced_bt_device_link_keys_t *keys) {...}

Locate the key. If the key is found and matches the BDADDR of the device, the function returns true. Part of bonding.

static void bt_classic_client_connection_status_change_cback(
    wiced_bt_device_address_t bd_addr,
    uint8_t *p_features,
    wiced_bool_t is_connected,
    uint16_t handle,
    wiced_bt_transport_t transport,
    uint8_t reason
) {...}

Use asynchronously for notifications when the status of the connection changes.

static void bt_classic_client_app_init(void) {...}

Use wiced_bt_sdp_db_init() and wiced_bt_dev_register_connection_status_change() to initialize the Bluetooth connection.

static wiced_result_t bt_classic_client_management_callback(
    wiced_bt_management_evt_t event,
    wiced_bt_management_evt_data_t *data
) {...}

Manages all Bluetooth events and calls corresponding functions. Use bt_classic_client_app_init() if a Bluetooth connection is started. Use wiced_bt_dev_pin_code_reply() if a device is requesting a PIN. Use wiced_bt_dev_confirm_req_reply() if a confirmation request is required. Logs responses.

bool btc_connect(
    wiced_bt_device_address_t bda,
    struct ltrx_trigger *trigger
) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, signal a trigger to connect using ltrx_trigger_signal(), and then use ltrx_preemption_unblock() to allow preemption. This is used to initiate a connection with bt_classic_client_thread_func().

bool btc_disconnect(struct ltrx_trigger *trigger) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, signal a trigger to disconnect using ltrx_trigger_signal(), and then use ltrx_preemption_unblock() to allow preemption. This is used to signal the main thread to call bt_classic_client_disconnect().

bool btc_start_scan(struct ltrx_trigger *trigger) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, use btc_scan_reset() to reset the scanner, signal a trigger to scan for Bluetooth devices using ltrx_trigger_signal(), and then use ltrx_preemption_unblock() to allow preemption. This is used to signal to the main thread to start a scan using btc_scan_start().

bool btc_transmit(
    const uint8_t *data,
    size_t length
) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, use ltrx_trigger_signal() to signal the main thread to call btc_spp_transmit(), and then use ltrx_preemption_unblock() to allow preemption.

bool btc_echoback(uint32_t index) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, use ltrx_trigger_signal() to signal the main thread to echo back asynchronously using btc_spp_echoback(), and then use ltrx_preemption_unblock() to allow preemption.

static void bt_classic_client_thread_func(void *arg) {...}

The main thread. Calls appropriate functions based on received signals. Initialize the Bluetooth stack with ltrx_bt_init() and wiced_bt_stack_init(). Use TLOG() to write to the trouble log. Use LTRX_TRIGGER_WAIT() to get a trigger and ltrx_trigger_clear() to clear the trigger. Use btc_scan_start() if starting a scan. Use bt_classic_client_connect() to connect to a Bluetooth device. Use bt_classic_client_disconnect() to disconnect from a Bluetooth device. Use btc_spp_transmit() to transmit data. Use ltrx_thread_sleep() to sleep the thread.

void bt_classic_client_module_registration(void) {...}

Use ltrx_module_register() to register the module.

void bt_classic_client_module_startup(void) {...}

Start the Bluetooth module. Use ltrx_trigger_create() to create the BT Classic SPP trigger. Use TLOG() to write to the trouble log.

void bt_classic_client_module_shutdown(void) {...}

Shutdown the module.

static void bt_classic_client_scan_callback(
    wiced_bt_dev_inquiry_scan_result_t *wbdisr,
    uint8_t *eir_data
) {...}

Passed to wiced_bt_start_inquiry(). Call asynchronously as the Bluetooth stack receives scan replies. Device names, addresses, and RSSI values are collected for the scan results.

bool btc_scan_start(void) {...}

Use wiced_bt_start_inquiry() to begin a Bluetooth scan. Use TLOG() to write to the trouble log.

void btc_scan_get_results(
    wiced_bt_dev_inquiry_scan_result_t **resultsp,
    char **namesp[16],
    uint32_t *results_countp
) {...}

Accessor that provides a pointer to the list of scan results.

void btc_scan_reset(void) {...}

Reset the Bluetooth scan results.

static bool spp_send_session_data(
    uint16_t handle,
    const uint8_t *data, uint32_t length
) {...}

Send the session data. Use TLOG() to write to the trouble log.

static bool spp_can_send_more_data(void) {...}

Return true if SPP can send more data.

void spp_connection_up_callback(
    uint16_t handle,
    uint8_t *bda
) {...}

Not used in demo. Can be used to add custom functionality.

void spp_connection_failed_callback(void) {...}

Not used in demo. Can be used to add custom functionality.

void spp_connection_down_callback(uint16_t handle) {...}

Not used in demo. Can be used to add custom functionality.

wiced_bool_t spp_rx_data_callback(
    uint16_t handle,
    uint8_t *data,
    uint32_t data_len
) {...}

This is where you add additional functionality to process the data. Use ltrx_preemption_block() to prevent other threads from preempting this one, and then use ltrx_preemption_unblock() to allow preemption.

static void spp_port_event_cback(
    wiced_bt_rfcomm_port_event_t event,
    uint16_t handle
) {...}

Passed to wiced_bt_rfcomm_set_event_callback() in spp_rfcomm_opened(). After the RFCOMM connection is established, this function is registered to receive asynchronous SPP events. The PORT_EV_RXCHAR events indicates data has been receive. The function then calls spp_rx_data_callback(). If flow control is on when the event PORT_EV_TXEMPTY is received, the function turns off flow control. The PORT_EV_FC event indicates that flow control has been turned on or off by the peer. The internal flow control flag is updated accordingly, which is then checked in spp_can_send_more_data() to determine if it can transmit data to the peer or if it should wait.

void spp_rfcomm_closed(spp_scb_t *p_scb) {...}

Close the RFCOMM.

void spp_rfcomm_opened(spp_scb_t *p_scb) {...}

Open the SPP session.

void spp_rfcomm_acceptor_opened(spp_scb_t *p_scb) {...}

Use TLOG() to write to the trouble log. Use wiced_bt_rfcomm_check_connection() to retrieve the status. Use spp_rfcomm_closed() if the connection failed or spp_rfcomm_opened() if it succeeded.

void btc_spp_transmit(
    const uint8_t *data,
    size_t length
) {...}

Use spp_send_session_data() to transmit data.

void btc_spp_echoback(uint32_t index) {...}

Use spp_send_session_data() to echo back data.

static void btc_status_init(void) {...}

Use ltrx_trigger_create() to initialize status.

static void btc_print_scan_results(
    const struct ltrx_write_user_message_info *lwumi
) {...}

Print the scan results obtained with btc_scan_get_results().

void BTClassicSPPExampleGetStatus(
    uint32_t zeroBasedIndex,
    struct statusdef_values_bt_classic_spp_example *status,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Use btc_print_scan_results() to print the scan results.

bool BTClassicSPPExampleConnect(
    uint32_t zeroBasedIndex,
    const char *value,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Connect over Bluetooth. Use btc_is_connected() to check if the connection is already open. Use btc_status_init() to initialize the Bluetooth status. Use ltrx_trigger_clear() to clear the trigger. Write status messages. Use btc_connect() to start connection. Use ltrx_thread_sleep() to sleep the thread and LTRX_TRIGGER_WAIT() to wait for a trigger.

bool BTClassicSPPExampleLogLevelGet(
    uint32_t zeroBasedIndex,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Display the debug log level.

bool BTClassicSPPExampleLogLevelSet(
    uint32_t zeroBasedIndex,
    const char *value,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Set the debug log level.

bool BTClassicSPPExampleTransmit(
    uint32_t zeroBasedIndex,
    const char *value,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Use btc_status_init() to initialize the Bluetooth status. Use btc_transmit() to transmit data over the Bluetooth connection. Use ltrx_thread_sleep() to sleep the thread.

bool BTClassicSPPExampleDisconnect(
    uint32_t zeroBasedIndex,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Use btc_status_init() to initialize the Bluetooth status. Use ltrx_trigger_clear() to clear the trigger. Use btc_disconnect() to close the Bluetooth connection. Use ltrx_thread_sleep() to sleep the thread.

bool BTClassicSPPExampleScan(
    uint32_t zeroBasedIndex,
    const struct ltrx_write_user_message_info *lwumi
) {...}

Use btc_status_init() to initialize the Bluetooth status. Use ltrx_trigger_clear() to clear the trigger. Write the status. Use btc_start_scan() to start a Bluetooth scan. Use ltrx_thread_sleep() to sleep the thread. Use LTRX_TRIGGER_WAIT() to wait for a trigger. Use btc_print_scan_results() to print the results of the scan.


Mach10 Serial API

The mach10_serial_api module implements a line protocol. When this protocol is chosen by a line, it interprets data received on the line in terms of Mach10 Serial API command names and parameters. When a full Mach10 Serial API command name (with parameter(s)) is recognized, the command is serviced by the Mach10 module. The response is then written back to the line.

Build it from project Mach10SerialAPIDemo.

Function Details

The following is an overview of the functions used in the mach10_serial_api module.

mach10_serial_api_strerror(int rc) {...}

Return either success message or error info.

static void mach10_serial_api_message_write(
    const char *message, size_t length,
    void *pOpaque
) {...}

Use ltrx_output_stream_write_binary() to write binary data to the buffer.

static void mach10_serial_api_message_end(
    enum ltrx_user_message_severity severity,
    void *pOpaque
)  {...}

Use ltrx_output_stream_write_without_ending_line() to write data without a new line, or alternately write data with a new line.

static void mach10_serial_api_message_begin(
    enum ltrx_user_message_severity severity,
    void *pOpaque
)  {...}

Use ltrx_output_stream_write_without_ending_line() to write data without a new line when prefix is present.

static void m10ci_initialize_message(
    struct message_to_output_stream *mtos,
    struct output_stream *os
)  {...}

Set mtos properties.

static void lineThread(void *opaque) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Initialize a message.

Use ltrx_line_get_registered_name() to get the registered name of the line and then print a <Protocol> started on Line: <line> message to the trouble log. If not successful, get error message from mach10_serial_api_strerror().

Then use ltrx_thread_yield() to yield control to other threads, allowing other threads to run if they are ready, and then print a <Protocol> stopped on Line: <line> message to the trouble log.

Use ltrx_input_stream_close() to close the input stream and ltrx_output_stream_close() to close the output stream.

static bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

static void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, assign the thread to a serial line, and then use ltrx_preemption_unblock() to allow preemption.


XML Access

The xml_access module demonstrates how to read device status and configuration values via XML.

Build it from project xmlAccessDemo.

Function Details

The following is an overview of the functions used in the xml_access module.

static bool getXmlValue(
    const struct xml_emit_value_specification *xevs,
    char *buffer,
    size_t size
) {...}

Use ltrx_output_stream_init_to_buffer() to set up an output stream to buffer and ltrx_xml_emit_value() to emit an XML value onto the buffer.

static void xmlAccessThread(void *opaque) {...}

Use ltrx_ip_address_state() to check if the IP interfaces are up, and while there is no connection, use ltrx_thread_sleep() to pause the thread. While there is a connection, get firmware version, MAC address, current WLAN0 IP address, and configured dynamic power mode and print related information to the trouble log, and then pause the thread.


Secure Tunnel

The secure_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via TLS out on the line. It sends data received on the line out via TLS when it receives Enter or fills its 80 character buffer.

As delivered in the SDK, the module listens for a TLS connection on both the AP0 and WLAN0 interface addressed to LOCAL_PORT 10001. When the connection is established, it sends Connected to the line. Subsequently, it listens to the line for data to send out via TLS. #define REMOTE_ADDRESS must be commented out to operate in this listening mode.

Note

You must add TLS Credential called secure_tunnel. Log in to Web Manager and click TLS Credentials. For more information, see Creating a TLS Credential in the xPico 200 Series User Guide.

https://docs.lantronix.com/products/xpico-200/ug/1.6.0.0/cli-ref/#config-tls-credential-level

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set the #define REMOTE_PORT. When the connection is established, it sends Connected to the line.

Build it from project secureTunnelDemo.

Function Details

The following is an overview of the functions used in the secure_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

If there is data, use ltrx_output_stream_write_binary() to write binary data to the buffer. If there is not, use ltrx_tcp_socket_is_eof() to check if all receive data has been read and a FIN has been received. If so, use ltrx_output_stream_write_line() to write "Disconnected" ending with a new line. Then use ltrx_tcp_socket_close() to close the socket.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, send the data and then use ltrx_tcp_socket_close() to close the socket and then close the connection.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

Use ltrx_network_lookup_network_protocol() to get the protocol structure for "TLS".

If REMOTE_ADDRESS is defined and there is no socket open for the thread, use ltrx_tcp_listener_begin() to initialize the listener and start listening.

If REMOTE_ADDRESS is defined and there is a socket open for the thread, use ltrx_output_stream_write_line() to print "Connected" with a new line.

If REMOTE_ADDRESS is not defined and there is no socket open and no listener in use, use ltrx_tcp_listener_begin() to initialize listener and begin listening.

If REMOTE_ADDRESS is not defined and there is no socket open but a listener is in use, use ltrx_tcp_accept() to accept a connection request and then ltrx_ip_socket_get_peer_information() to get peer information (IP address and port of the remote device). Then use ltrx_ip_and_port_display() to print the IP address and port. Use ltrx_output_stream_write_without_ending_line() to writes "Accepted from" (no new line) followed by ltrx_output_stream_write_line() to the remote address and port, with a new line. Finally, use ltrx_tcp_listener_end() to stop listening.

If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

If REMOTE_ADDRESS is not defined and there is a listener in use, use ltrx_tcp_listener_end() to stop listening.

Close the socket with ltrx_tcp_socket_close().

static void lineThread(void *opaque) {...}

Attempt to create trigger using ltrx_trigger_create(). If it returns false (failed), return. Otherwise keep going. While the thread is running, use ltrx_line_open() to open a line. If it returns false (failed), wait 1000 ms and try again.

If the line is running, print to trouble log and then use ltrx_line_set_dtr() to set the DTR value.

Use ltrx_line_close() tp relinquish the line and then ltrx_trigger_destroy() to destroy the trigger.

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

If a thread is already running, print message to the trouble log. Otherwise, use ltrx_thread_create() to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Pause the thread with ltrx_thread_sleep().


Programmatic Scan

The programmatic_scan module demonstrates how to run a CLI command from your program and capture its output for program use.

Build it from project programmaticScanDemo.

Function Details

The following is an overview of the functions used in the programmatic_scan module.

static void processScanResults(
    const char *ssid,
    uint8_t *bssid,
    uint8_t channel,
    int rssi,
    const char *securitySuite
) {...}

Print debug information to trouble log.

static void parseScanLine(const char *scanLine) {...}

Read formatted input from a string and send to processScanResults().

static bool writeData(
    struct output_stream *outStream,
    const char *data, size_t length
) {...}

Write the data to the scan line and then yield control to other threads using ltrx_thread_yield().

static bool writeNewline(struct output_stream *outStream) {...}

Determine if the scan is completed, and if so, write the new line. Then, yield control to other threads using ltrx_thread_yield().

static bool flushData(struct output_stream *outStream) {...}

Flush data from the output stream.

static bool outputClose(struct output_stream *outStream) {...}

Close the output stream.

static void programmaticScanThread(void *opaque) {...}

Use ltrx_ip_address_state() to see if the IP interface is up. If not, use ltrx_thread_sleep() to pause the thread for 1000 ms to allow time for WLAN0 to come up.

Use ltrx_input_stream_init_from_const_char() to construct input stream from const character, and when up, send "Starting scan." message to trouble log.

Use ltrx_cli_command_loop() to enter command line interface.

Closes the input stream with ltrx_input_stream_close() and pause the thread with ltrx_thread_sleep().


Configurable Pins

The config_pin module implements an output role, which can be assigned to any configurable pin (CP).

Build it from project configurablePinDemo.

Use either Web Manager or Command Line Interface to set up configuration in group configurable pin manager (CPM). Under Roles, find your role of Blinker. Assign it a CP of your choice and set State to Enabled.

Tip

If using the evaluation board, you must jumper your selected configurable pin on J2 to an external LED (and current limiting resistor) -- if some other role is enabled using your selected CP, this will fail. Observe the blinking with an LED or scope connected to your selected CP.

Function Details

The following is an overview of the functions used in the config_pin module.

static void blinkerThread(void *opaque) {...}

Look up role index using ltrx_cp_role_index_get() and print the role name and roll index to trouble log. While there is a thread, use ltrx_cp_write() to write to a configurable pin and then pause the thread with ltrx_thread_sleep().

void config_pin_module_startup(void) {...}

Notice use of the macro STACK_SIZE_GREEN_FROM_MAX_OBSERVED_STACK_USED when calling ltrx_thread_create() in the startup function. It was originally built with 2000 bytes of stack. Then the module was built and run. The actual stack was observed either via the Web Manager or the Command Line Interface under Diagnostics Threads. Find the Blinker thread, and the Stack used is shown. That value was plugged into the macro in the sample code.


UDP Tunnel

The udp_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via UDP out on the line. It sends data received on the line out via UDP when it receives Enter or fills its 80 character buffer.

As delivered in the SDK, the module listens for UDP packets on interface WLAN0 addressed to the LOCAL_PORT 10001. When the first packet is received, it sends Connected to the line. Subsequently, it listens to the line for data to send out via UDP. #define REMOTE_ADDRESS may be AP0 or WLAN0 to operate in this listening mode.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set the #define REMOTE_PORT. When the interface is established and resolves the name or address, it sends Connected to the line.

Build it from project udpTunnelDemo.

Function Details

The following is an overview of the functions used in the udp_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

Receive data from the socket using ltrx_ip_socket_receive(). If the length of the received data is greater than zero, use ltrx_output_stream_write_binary() to write the binary data to the buffer.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, use ltrx_ip_socket_send() to send the data and then ltrx_tcp_socket_close() to close the socket.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

While the thread is running, there is no socket open, and ltrx_udp_socket_open_with_options() to open a socket returns false (failed), wait and try again. Otherwise, call networkReadAndSerialWrite() and then, if ltrx_udp_socket_is_active() returns true, and the thread is not connected, use ltrx_output_stream_write_line() to write "" and a new line, follwed by "Connected" and a new line. If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

static void lineThread(void *opaque) {...}

Attempt to create trigger using ltrx_trigger_create(). If it returns false (failed), return. Otherwise keep going. While the thread is running, use ltrx_line_open() to open a line. If it returns false (failed), wait 1000 ms and try again.

If the line is running, print to trouble log and then use ltrx_line_set_dtr() to set the DTR value.

Use ltrx_line_close() tp relinquish the line and then ltrx_trigger_destroy() to destroy the trigger.

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Pause the thread with ltrx_thread_sleep().


TCP Tunnel

The tcp_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via TCP out on the line. It sends data received on the line out via TCP when it receives Enter or fills its 80 character buffer.

As delivered in the SDK, the module listens for a TCP connection on both the AP0 and WLAN0 interface addressed to LOCAL_PORT 10001. When the connection is established, it sends Connected to the line. Subsequently, it listens to the line for data to send out via TCP. #define REMOTE_ADDRESS must be commented out to operate in this listening mode.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set #define REMOTE_PORT. When the connection is established, it sends Connected to the line.

Build it from project tcpTunnelDemo.

For connecting out, fill in REMOTE_ADDRESS with either an IP address or a host name. For listening, comment out the definition of REMOTE_ADDRESS. The REMOTE_PORT is only used if "connecting out" according to REMOTE_ADDRESS.

#define REMOTE_ADDRESS "remote_host_goes_here"

Function Details

The following is an overview of the functions used in the tcp_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

Receive data from the socket using ltrx_ip_socket_receive(). If there is data, use ltrx_output_stream_write_binary() to write binary data to the buffer. If there is not, use ltrx_tcp_socket_is_eof() to check if all receive data has been read and a FIN has been received. If so, use ltrx_output_stream_write_line() to write "" ending with a new line and then "Disconnected" ending with a new line. Then use ltrx_tcp_socket_close() to close the socket.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, use ltrx_ip_socket_send() to send the data and then ltrx_tcp_socket_close() to close the socket.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

While the thread is running, REMOTE_ADDRESS is defined, and there is no socket, use ltrx_tcp_connect() to connect. If there is a socket, print "Connected".

While the thread is running, REMOTE_ADDRESS is not defined, and there is no socket and no listener, use ltrx_tcp_listener_begin() to initialize a listener and start listening.

If REMOTE_ADDRESS is not defined and there is no socket open but a listener is in use, use ltrx_tcp_accept() to accept a connection request and then ltrx_ip_socket_get_peer_information() to get peer information (IP address and port of the remote device). Then use ltrx_ip_and_port_display() to print the IP address and port. Use ltrx_output_stream_write_without_ending_line() to writes "Accepted from" (no new line) followed by ltrx_output_stream_write_line() to the remote address and port, with a new line. Finally, use ltrx_tcp_listener_end() to stop listening.

If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Otherwise, pause the thread for 100ms with ltrx_thread_sleep().


Power Down

The power_down module demonstrates how an application program can place restrictions on when the device powers down.

Build it from project powerDownDemo.

Function Details

The following is an overview of the functions used in the power_down module.

static void powerDownThread(void *opaque) {...}

Use ltrx_ip_address_state() to check if the IP interfaces are up, and while there is no connection, use ltrx_thread_sleep() to pause the thread for 100 ms to give WLAN0 time to come up.

When there is a connection, use ltrx_power_level_application_request_full_power() to request full power until further notice, then use ltrx_timemark() to get a time mark.

Use ltrx_elapsed_time_current_ms() to find the time since the time mark. If the elapsed time is less than the duration specified in s_timeBetweenWorkStartInMilliseconds, calculate the difference between the elapsed time and remaining time. If the difference is greater that 1000 ms, print a message indicating the permitted shutdown time to the trouble log and then permit shutdown for specified time duration using ltrx_power_level_application_permit_shutdown().

Pause the thread with ltrx_thread_sleep() and yeild control using ltrx_thread_yield().


SPI Log

The spi_log module implements a rudimentary serial peripheral interface (SPI) protocol. When this protocol is chosen by a SPI, it logs whatever it receives on the SPI.

To run it you will need to select protocol Log under SPI Configuration.

Also, you will need to enable the SPI configurable pins (CPs): Under CPM Roles Configuration, enable the SPI group of CPs.

Tip

If using the evaluation board, you may place a jumper between J2 pins CP3 and CP4 to effect a loopback of your SPI data. Note that the SPI group of CPs is ganged, so when you enable one, you enable them all. Also note that all the other CPM Roles referring to any of the SPI CPs must be disabled.

Build it from project spiLogDemo.

Function Details

The following is an overview of the functions used in the power_down module.

static void spiLoop(struct thread_info *ti) {...}

While the thread is running, use ltrx_spi_transfer() to transfer data and then confirm "Sent" in the trouble log. Then use ltrx_thread_sleep() to pause the thread for 5000 ms.

static void spiThread(void *opaque) {...}

Wheile the thread is running and calling ltrx_spi_open() to open a serial peripheral interface returns false (failed), wait 1000 ms and try again. Print start message to trouble log and call spiLoop().

Relinquish the SPI using ltrx_spi_close().

bool StartSpiLog(uint16_t zeroBasedIndex) {...}

If a thread is already running, print message to the trouble log. Otherwise, use ltrx_thread_create() to create a thread and start it.

void StopSpiLog(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, change wasRunning to true, Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, pause the thread with ltrx_thread_sleep().