bleconfig.c 12.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

/* clang-format off */

#include <stdbool.h>
#include <stdint.h>
#include "boards.h"
#include "sdk_config.h"
#include "app_timer_appsh.h"
#include "app_scheduler.h"
#include "app_button.h"
#include "nordic_common.h"
#include "softdevice_handler_appsh.h"
#include "ble_advdata.h"
#include "ble_srv_common.h"
#include "ble_ipsp.h"
#include "ble_6lowpan.h"
#include "mem_manager.h"
#include "app_trace.h"
#include "lwip/init.h"
#include "lwip/inet6.h"
#include "lwip/ip6.h"
#include "lwip/ip6_addr.h"
#include "lwip/netif.h"
/*lint -save -e607 */
#include "lwip/tcp.h"
/*lint -restore */
#include "lwip/timers.h"
#include "nrf_platform_port.h"
#include "app_util_platform.h"
#include "iot_timer.h"
#include "ipv6_medium.h"
#include "SEGGER_RTT.h"
#include "myboard.h"

#define SCHED_MAX_EVENT_DATA_SIZE           128                                                     /**< Maximum size of scheduler events. */
#define SCHED_QUEUE_SIZE                    12                                                      /**< Maximum number of events in the scheduler queue. */

38
#ifdef COMMISSIONING_ENABLED
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
#define ERASE_BUTTON_PIN_NO                 BSP_BUTTON_3                                            /**< Button used to erase commissioning settings. */
#endif // COMMISSIONING_ENABLED

#define APP_TIMER_OP_QUEUE_SIZE             5
#define LWIP_SYS_TICK_MS                    100                                                     /**< Interval for timer used as trigger to send. */
#define LED_BLINK_INTERVAL_MS               300                                                     /**< LED blinking interval. */

#define MAX_LENGTH_FILENAME                 128                                                     /**< Max length of filename to copy for the debug error handler. */

#define APPL_LOG                            app_trace_log                                           /**< Macro for logging application messages on UART, in case ENABLE_DEBUG_LOG_SUPPORT is not defined, no logging occurs. */
#define APPL_DUMP                           app_trace_dump                                          /**< Macro for dumping application data on UART, in case ENABLE_DEBUG_LOG_SUPPORT is not defined, no logging occurs. */

#define TCP_SERVER_PORT                     9000                                                    /**< TCP server listen port number. */
#define TCP_DATA_SIZE                       8                                                       /**< UDP Data size sent on remote. */

typedef enum
{
  TCP_STATE_IDLE,
  TCP_STATE_REQUEST_CONNECTION,
  TCP_STATE_CONNECTED,
  TCP_STATE_DATA_TX_IN_PROGRESS,
  TCP_STATE_DISCONNECTED
}tcp_state_t;

APP_TIMER_DEF(m_iot_timer_tick_src_id);                                                             /**< System Timer used to service CoAP and LWIP periodically. */
eui64_t                                     eui64_local_iid;                                        /**< Local EUI64 value that is used as the IID for*/
static ipv6_medium_instance_t               m_ipv6_medium;
static struct tcp_pcb                     * mp_tcp_port;                                            /**< TCP Port to listen on. */
static tcp_state_t                          m_tcp_state;                                            /**< TCP State information. */

69
#ifdef COMMISSIONING_ENABLED
70 71 72 73 74 75 76
static bool                                 m_power_off_on_failure = false;
static bool                                 m_identity_mode_active;
#endif // COMMISSIONING_ENABLED

/**@brief Function to handle interface up event. */
void nrf_driver_interface_up(void)
{
77
#ifdef COMMISSIONING_ENABLED
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
  commissioning_joining_mode_timer_ctrl(JOINING_MODE_TIMER_STOP_RESET);
#endif // COMMISSIONING_ENABLED

  APPL_LOG ("[APPL]: IPv6 interface up.\r\n");

  sys_check_timeouts();

  m_tcp_state = TCP_STATE_REQUEST_CONNECTION;

  LEDS_OFF(LED_ONE);
  LEDS_ON(LED_TWO);
}


/**@brief Function to handle interface down event. */
void nrf_driver_interface_down(void)
{
95
#ifdef COMMISSIONING_ENABLED
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
  commissioning_joining_mode_timer_ctrl(JOINING_MODE_TIMER_START);
#endif // COMMISSIONING_ENABLED

  APPL_LOG ("[APPL]: IPv6 interface down.\r\n");

  LEDS_OFF((DISPLAY_LED_0 | DISPLAY_LED_1 | DISPLAY_LED_2 | DISPLAY_LED_3));
  LEDS_ON(LED_ONE);

  m_tcp_state = TCP_STATE_DISCONNECTED;
}

/**@brief Timer callback used for periodic servicing of LwIP protocol timers.
 *
 * @details Timer callback used for periodic servicing of LwIP protocol timers.
 *
 * @param[in]   p_context   Pointer used for passing context. No context used in this application.
 */
static void system_timer_callback(iot_timer_time_in_ms_t wall_clock_value)
{
  UNUSED_VARIABLE(wall_clock_value);
  sys_check_timeouts();
}

/**@brief Function for starting connectable mode.
*/
static void connectable_mode_enter(void)
{
  uint32_t err_code = ipv6_medium_connectable_mode_enter(m_ipv6_medium.ipv6_medium_instance_id);
  APP_ERROR_CHECK(err_code);

  APPL_LOG("[APPL]: Physical layer in connectable mode.\r\n");
  LEDS_OFF(LED_TWO);
  LEDS_ON(LED_ONE);
}

/**@brief Function for updating the wall clock of the IoT Timer module.
*/
static void iot_timer_tick_callback(void * p_context)
{
  UNUSED_VARIABLE(p_context);

  uint32_t err_code = iot_timer_update();
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for the LEDs initialization.
 *
 * @details Initializes all LEDs used by this application.
 */
static void leds_init(void)
{
  // Configure application LED pins.
  LEDS_CONFIGURE(ALL_APP_LED);

  // Turn off all LED on initialization.
  LEDS_OFF(ALL_APP_LED);
}

154
#ifdef COMMISSIONING_ENABLED
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
/**@brief Timer callback used for controlling board LEDs to represent application state.
 *
 */
static void blink_timeout_handler(iot_timer_time_in_ms_t wall_clock_value)
{
  UNUSED_PARAMETER(wall_clock_value);
  static bool id_mode_previously_enabled;

  if ((id_mode_previously_enabled == false) && (m_identity_mode_active == true))
  {
    LEDS_OFF(LED_THREE | LED_FOUR);
  }

  if ((id_mode_previously_enabled == true) && (m_identity_mode_active == true))
  {
    LEDS_INVERT(LED_THREE | LED_FOUR);
  }

  if ((id_mode_previously_enabled == true) && (m_identity_mode_active == false))
  {
    LEDS_OFF(LED_THREE | LED_FOUR);
  }

  id_mode_previously_enabled = m_identity_mode_active;
}
#endif // COMMISSIONING_ENABLED

/**@brief Function for the Timer initialization.
 *
 * @details Initializes the timer module. This creates and starts application timers.
 */
static void timers_init(void)
{
  uint32_t err_code;

  // Initialize timer module.
  APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);

  // Create a sys timer.
  err_code = app_timer_create(&m_iot_timer_tick_src_id,
      APP_TIMER_MODE_REPEATED,
      iot_timer_tick_callback);
  APP_ERROR_CHECK(err_code);
}


/**@brief Function for initializing the IoT Timer. */
static void iot_timer_init(void)
{
  uint32_t err_code;

  static const iot_timer_client_t list_of_clients[] =
  {
    {system_timer_callback,   LWIP_SYS_TICK_MS},
209
#ifdef COMMISSIONING_ENABLED
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    {blink_timeout_handler,   LED_BLINK_INTERVAL_MS},
    {commissioning_time_tick, SEC_TO_MILLISEC(COMMISSIONING_TICK_INTERVAL_SEC)}
#endif // COMMISSIONING_ENABLED
  };

  // The list of IoT Timer clients is declared as a constant.
  static const iot_timer_clients_list_t iot_timer_clients =
  {
    (sizeof(list_of_clients) / sizeof(iot_timer_client_t)),
    &(list_of_clients[0]),
  };

  // Passing the list of clients to the IoT Timer module.
  err_code = iot_timer_client_list_set(&iot_timer_clients);
  APP_ERROR_CHECK(err_code);

  // Starting the app timer instance that is the tick source for the IoT Timer.
  err_code = app_timer_start(m_iot_timer_tick_src_id, \
      APP_TIMER_TICKS(IOT_TIMER_RESOLUTION_IN_MS, APP_TIMER_PRESCALER), \
      NULL);
  APP_ERROR_CHECK(err_code);
}

/**@brief Function for initializing IP stack.
 *
 * @details Initialize the IP Stack and its driver.
 */
static void ip_stack_init(void)
{
  uint32_t err_code;

  err_code = ipv6_medium_eui64_get(m_ipv6_medium.ipv6_medium_instance_id, \
      &eui64_local_iid);
  APP_ERROR_CHECK(err_code);

  err_code = nrf_mem_init();
  APP_ERROR_CHECK(err_code);

  //Initialize LwIP stack.
  lwip_init();

  //Initialize LwIP stack driver.
  err_code = nrf_driver_init();
  APP_ERROR_CHECK(err_code);
}

256
#ifdef COMMISSIONING_ENABLED
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
/**@brief Function for handling button events.
 *
 * @param[in]   pin_no         The pin number of the button pressed.
 * @param[in]   button_action  The action performed on button.
 */
static void button_event_handler(uint8_t pin_no, uint8_t button_action)
{
  if ((button_action == APP_BUTTON_PUSH) && (pin_no == ERASE_BUTTON_PIN_NO))
  {
    APPL_LOG("[APPL]: Erasing all commissioning settings from persistent storage... \r\n");
    commissioning_settings_clear();
    return;
  }
  return;
}


/**@brief Function for the Button initialization.
 *
 * @details Initializes all Buttons used by this application.
 */
static void buttons_init(void)
{
  uint32_t err_code;

  static app_button_cfg_t buttons[] =
  {
284
#ifdef COMMISSIONING_ENABLED
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
    {ERASE_BUTTON_PIN_NO, false, BUTTON_PULL, button_event_handler}
#endif // COMMISSIONING_ENABLED
  };

#define BUTTON_DETECTION_DELAY APP_TIMER_TICKS(50, APP_TIMER_PRESCALER)

  err_code = app_button_init(buttons, \
      sizeof(buttons) / sizeof(buttons[0]), \
      BUTTON_DETECTION_DELAY);
  APP_ERROR_CHECK(err_code);

  err_code = app_button_enable();
  APP_ERROR_CHECK(err_code);
}
#endif // COMMISSIONING_ENABLED

/**@brief Function for the Event Scheduler initialization.
*/
static void scheduler_init(void)
{
  APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
}

static void on_ipv6_medium_evt(ipv6_medium_evt_t * p_ipv6_medium_evt)
{
  switch (p_ipv6_medium_evt->ipv6_medium_evt_id)
  {
    case IPV6_MEDIUM_EVT_CONN_UP:
      {
        APPL_LOG("[APPL]: Physical layer: connected.\r\n");
        LEDS_OFF(LED_ONE);
        LEDS_ON(LED_TWO);
        break;
      }
    case IPV6_MEDIUM_EVT_CONN_DOWN:
      {
        APPL_LOG("[APPL]: Physical layer: disconnected.\r\n");
        connectable_mode_enter();
        break;
      }
    default:
      {
        break;
      }
  }
}


static void on_ipv6_medium_error(ipv6_medium_error_t * p_ipv6_medium_error)
{
  // Do something.
}

338
#ifdef COMMISSIONING_ENABLED
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
void commissioning_id_mode_cb(mode_control_cmd_t control_command)
{
  switch (control_command)
  {
    case CMD_IDENTITY_MODE_ENTER:
      {
        LEDS_OFF(LED_THREE | LED_FOUR);
        m_identity_mode_active = true;

        break;
      }
    case CMD_IDENTITY_MODE_EXIT:
      {
        m_identity_mode_active = false;
        LEDS_OFF((LED_THREE | LED_FOUR));

        break;
      }
    default:
      {

        break;
      }
  }
}


void commissioning_power_off_cb(bool power_off_on_failure)
{
  m_power_off_on_failure = power_off_on_failure;

  APPL_LOG("[APPL]: Commissioning: do power_off on failure: %s.\r\n", \
      m_power_off_on_failure ? "true" : "false");
}
#endif // COMMISSIONING_ENABLED

void bleconfig_init(void) {
  uint32_t err_code;

  //Initialize.
  app_trace_init();
  leds_init();
  timers_init();
  iot_timer_init();

384
#ifdef COMMISSIONING_ENABLED
385 386 387 388 389 390 391 392 393 394 395
  err_code = pstorage_init();
  APP_ERROR_CHECK(err_code);

  buttons_init();
#endif // COMMISSIONING_ENABLED

  static ipv6_medium_init_params_t ipv6_medium_init_params;
  memset(&ipv6_medium_init_params, 0x00, sizeof(ipv6_medium_init_params));
  ipv6_medium_init_params.ipv6_medium_evt_handler    = on_ipv6_medium_evt;
  ipv6_medium_init_params.ipv6_medium_error_handler  = on_ipv6_medium_error;
  ipv6_medium_init_params.use_scheduler              = true;
396
#ifdef COMMISSIONING_ENABLED
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
  ipv6_medium_init_params.commissioning_id_mode_cb   = commissioning_id_mode_cb;
  ipv6_medium_init_params.commissioning_power_off_cb = commissioning_power_off_cb;
#endif // COMMISSIONING_ENABLED

  err_code = ipv6_medium_init(&ipv6_medium_init_params, \
      IPV6_MEDIUM_ID_BLE,       \
      &m_ipv6_medium);
  APP_ERROR_CHECK(err_code);

  eui48_t ipv6_medium_eui48;
  err_code = ipv6_medium_eui48_get(m_ipv6_medium.ipv6_medium_instance_id, \
      &ipv6_medium_eui48);

  ipv6_medium_eui48.identifier[EUI_48_SIZE - 1] = 0x00;

  err_code = ipv6_medium_eui48_set(m_ipv6_medium.ipv6_medium_instance_id, \
      &ipv6_medium_eui48);
  APP_ERROR_CHECK(err_code);

  ip_stack_init();
  scheduler_init();

  //Start execution.
  connectable_mode_enter();

  APPL_LOG(0, "BLE init done\n");
}

void bleconfig_poll(void) {
  //Execute event schedule.
  app_sched_execute();
}