Send Status Strings to the Border Router on UDP Port 1237#

Status strings are prepared as in JSON Connection Strings, getting ready to be sent to the Border Router or any other IPv6 address. To send them to their destination, the following steps are needed.

Note: This is all done in app.c, which you can use as a replacement for the original code.

Set the Destination IPv6#

IPv6 Declaration#

What you want is to automatically select the Border Router IPv6, which the device will only know once it is connected, or set a static IPv6 if your system is set with a different destination for network monitoring messages.

  • A text string is defined in app.c. It can be either "border_router" or a valid IPv6.

#define UDP_NOTIFICATION_DEST  "border_router" // "border_router" or fixed IPv6 string
  • Once connected, a part of app.c/_select_destinations() takes care of setting the intended IPv6.

  // Set the UDP notification destination (Border Router by default)
  printfBothTime("UDP_NOTIFICATION_DEST: %s\n", UDP_NOTIFICATION_DEST);
  if (sl_strcasecmp(UDP_NOTIFICATION_DEST, "border_router") == 0) {
    memcpy(udp_notification_ipv6.address,   border_router_ipv6.address, sizeof(device_global_ipv6.address));
  } else {
    sl_wisun_stoip6(UDP_NOTIFICATION_DEST    , SL_WISUN_IP_ADDRESS_SIZE, udp_notification_ipv6.address);
  }
  sl_wisun_ip6tos(udp_notification_ipv6.address       , udp_notification_ipv6_string);
  printfBothTime("UDP  Notification destination: %s\n", udp_notification_ipv6_string);

Convenience functions sl_wisun_stoip6() and sl_wisun_ip6tos() are used here to convert between IPv6s and strings. Both are defined in sl_wisun_ipv6string.h.

Set the Destination UDP Port#

The destination port is hardcoded in app.c as UDP_NOTIFICATION_PORT. It can be customized here:

#define UDP_NOTIFICATION_PORT  1237

Open and Connect the UDP Socket#

Each socket id is stored in a sl_wisun_socket_id_t, so udp_notification_socket_id is declared in app.c:

// Notification sockets
sl_wisun_socket_id_t udp_notification_socket_id = 0;

Once the device is connected to the Wi-SUN network, it becomes possible to open the UDP socket and connect it to the desired destination and port, as in app.c/_open_udp_sockets_with_Border_Router():

  // UDP Notifications (autonomously sent by the device)
  ret = sl_wisun_open_socket (SL_WISUN_SOCKET_PROTOCOL_UDP, &udp_notification_socket_id);
  NO_ERROR(ret, "Opened    the UDP  notification socket (%ld)\n", udp_notification_socket_id);
  IF_ERROR_RETURN(ret, "[Failed: unable to open the UDP notification socket: 0x%04x]\n", (uint16_t)ret);

  ret = sl_wisun_connect_socket(udp_notification_socket_id, &udp_notification_ipv6, UDP_NOTIFICATION_PORT);
  NO_ERROR(ret, "Connected the UDP  notification socket (%ld %s/%d)]\n",
           udp_notification_socket_id, udp_notification_ipv6_string, UDP_NOTIFICATION_PORT);
  IF_ERROR_RETURN(ret, "[Failed: unable to connect the UDP notification socket: 0x%04x]\n", (uint16_t)ret);

Print and Send Status Messages#

Auto Send Loop#

In app.c/app_task(), the code enters an endless loop after initial connection, with a pause of auto_send_sec seconds after each loop. Inside this loop, a call to _print_and_send_messages() is used to send the string formatted by _status_json_string():

void app_task(void *args)
{
. . .
  bool with_time, to_console, to_rtt, to_udp, to_coap;
. . .
  with_time = to_console = to_rtt = true;
  to_udp = to_coap = false;
. . .
  while (1) {
    ///////////////////////////////////////////////////////////////////////////
    // Put your application code here!                                       //
    ///////////////////////////////////////////////////////////////////////////

    // We can only send messages outside if connected
    if (join_state == SL_WISUN_JOIN_STATE_OPERATIONAL) {
      to_udp = to_coap = true;
    } else {
      to_udp = to_coap = false;
    }

    // Print status message every auto_send_sec seconds
    _print_and_send_messages (_status_json_string(""),
               with_time, to_console, to_rtt, to_udp, to_coap);
    osDelay(auto_send_sec*1000);

  }
}

Messages Print Out and Transmission#

In app.c/_print_and_send_messages(), the flags are used to select where to send the message, including to the selected UDP port:

uint8_t _print_and_send_messages (char *in_msg, bool with_time,
                            bool to_console, bool to_rtt, bool to_udp, bool to_coap) {
  sl_status_t ret = SL_STATUS_OK;
  uint8_t messages_processed = 0;
  uint16_t udp_msg_len;
  uint16_t coap_msg_len;

  if (to_console == true) { // Print to console
      if (with_time == true) {
        printfTime(in_msg);
      } else {
        printf(in_msg);
      }
    messages_processed++;
  }
  if (to_rtt == true) {     // Print to RTT traces
      if (with_time == true) {
        printfTimeRTT(in_msg);
      } else {
        printfRTT(in_msg);
      }
    messages_processed++;
  }
  if (to_udp == true) {     // Send to UDP port
    udp_msg_len  = snprintf(udp_msg,  1024, "%s", in_msg);
    ret = sl_wisun_send_on_socket(udp_notification_socket_id, udp_msg_len, (uint8_t *)udp_msg);
    IF_ERROR(ret, "[Failed (line %d): unable to send to the UDP notification socket (%ld %s/%d): 0x%04x. Check sl_status.h] udp_msg_len %d\n",
             __LINE__, udp_notification_socket_id, udp_notification_ipv6_string , UDP_NOTIFICATION_PORT, (uint16_t)ret, udp_msg_len);
    if (ret == SL_STATUS_OK) messages_processed++;
  }
. . .
  return messages_processed;
}