Skip to content

file /Users/ios_developer/workspace/coldwave-os/build/_deps/libcoldwave-src/commissioning/wifi_commissioning.cpp

Functions Overview

Name
LOG_MODULE(wifi_commissioning )
intwifi_commissioning_join(PropArray & params, PropArray & outProps)
intwifi_commissioning_get_scan_results(PropArray & params, PropArray & outProps)
intwifi_commissioning_end_requested(PropArray & params, PropArray & outProps)
intwifi_commissioning_scan(void )
voidwifi_commissioning_rssi_sort(wlan_ap_info_t * scan_result, int first, int last)
intwifi_commissioning_try_join(wifi_commissioning_data_t * data)
intwifi_commissioning_ap_start(int wifi_dev, const char * ssid, const void * passphrase, int passphrase_len)
intwifi_commissioning_ap_stop(int wifi_dev)
intwifi_commissioning_start(int commissioning_type, wifi_commissioning_init_t * init)
voidwifi_commissioning_end(void * p)
voidwifi_commissioning_end_async()
voidwifi_commissioning_try_join_async(void * p)
voidwifi_commissioning_broadcast_scan_results(void * p)

Attributes

Name
intwifi_commissioning_running
intwifi_commissioning_wifi_dev
intwifi_commissioning_commissioner_dev
intwifi_commissioning_ap_started
volatile uint16_twifi_join_action_token
volatile uint16_twifi_scan_action_token
wlan_ap_info_t *wifi_commissioning_scan_results
uint32_twifi_commissioning_num_scan_results
wifi_commissioning_data_callback_twifi_commissioning_data_callback
osTimerId_twifi_commissioning_timeout_tmr
Service *coldwave_device_service

Defines

Name
WC_TIMER_EXPIRED

Function Details

function LOG_MODULE

cpp
LOG_MODULE(
    wifi_commissioning 
)

function wifi_commissioning_join

cpp
static int wifi_commissioning_join(
    PropArray & params,
    PropArray & outProps
)

function wifi_commissioning_get_scan_results

cpp
static int wifi_commissioning_get_scan_results(
    PropArray & params,
    PropArray & outProps
)

function wifi_commissioning_end_requested

cpp
static int wifi_commissioning_end_requested(
    PropArray & params,
    PropArray & outProps
)

function wifi_commissioning_scan

cpp
static int wifi_commissioning_scan(
    void 
)

function wifi_commissioning_rssi_sort

cpp
static void wifi_commissioning_rssi_sort(
    wlan_ap_info_t * scan_result,
    int first,
    int last
)

function wifi_commissioning_try_join

cpp
static int wifi_commissioning_try_join(
    wifi_commissioning_data_t * data
)

function wifi_commissioning_ap_start

cpp
static int wifi_commissioning_ap_start(
    int wifi_dev,
    const char * ssid,
    const void * passphrase,
    int passphrase_len
)

function wifi_commissioning_ap_stop

cpp
static int wifi_commissioning_ap_stop(
    int wifi_dev
)

function wifi_commissioning_start

cpp
int wifi_commissioning_start(
    int commissioning_type,
    wifi_commissioning_init_t * init
)

function wifi_commissioning_end

cpp
void wifi_commissioning_end(
    void * p
)

function wifi_commissioning_end_async

cpp
void wifi_commissioning_end_async()

function wifi_commissioning_try_join_async

cpp
void wifi_commissioning_try_join_async(
    void * p
)

function wifi_commissioning_broadcast_scan_results

cpp
void wifi_commissioning_broadcast_scan_results(
    void * p
)

Attributes Documentation

variable wifi_commissioning_running

cpp
static int wifi_commissioning_running

variable wifi_commissioning_wifi_dev

cpp
static int wifi_commissioning_wifi_dev

variable wifi_commissioning_commissioner_dev

cpp
static int wifi_commissioning_commissioner_dev

variable wifi_commissioning_ap_started

cpp
static int wifi_commissioning_ap_started

variable wifi_join_action_token

cpp
static volatile uint16_t wifi_join_action_token

variable wifi_scan_action_token

cpp
static volatile uint16_t wifi_scan_action_token

variable wifi_commissioning_scan_results

cpp
static wlan_ap_info_t* wifi_commissioning_scan_results

variable wifi_commissioning_num_scan_results

cpp
static uint32_t wifi_commissioning_num_scan_results

variable wifi_commissioning_data_callback

cpp
static wifi_commissioning_data_callback_t wifi_commissioning_data_callback

variable wifi_commissioning_timeout_tmr

cpp
static osTimerId_t wifi_commissioning_timeout_tmr

variable coldwave_device_service

cpp
static Service* coldwave_device_service

Macros Documentation

define WC_TIMER_EXPIRED

cpp
#define WC_TIMER_EXPIRED ((void*)0xffffU)

Source code

cpp
/*******************************************************************************
 * @file       wifi_commissioning.cpp
 * @license    This file is part of the ImagineOn Coldwave eOS software package
 *             licensed under the ImagineOn software-licensing terms available
 *             under https://www.imagineon.de/de/info/licensing-terms
 * @copyright  Copyright (c) 2023. ImagineOn GmbH. www.imagineon.de.
 ******************************************************************************/

#include "wifi_commissioning.h"
#include "wifi_commissioning_legacy.h"

#include <wlan.h>
#include <kernel.h>
#include <ble.h>
#include <sys/ioctl.h>
#include <logging.h>

LOG_MODULE(wifi_commissioning)

#define WC_TIMER_EXPIRED ((void*)0xffffU)

static int wifi_commissioning_type = -1;
static int wifi_commissioning_running = 0;
static int wifi_commissioning_wifi_dev = -1;
static int wifi_commissioning_commissioner_dev = -1;
static int wifi_commissioning_ap_started = 0;

static volatile uint16_t wifi_join_action_token = 0;
static volatile uint16_t wifi_scan_action_token = 0;

static wlan_ap_info_t *wifi_commissioning_scan_results = nullptr;
static uint32_t wifi_commissioning_num_scan_results = 0;
static wifi_commissioning_data_callback_t wifi_commissioning_data_callback;
static osTimerId_t wifi_commissioning_timeout_tmr = 0;

static Service *coldwave_device_service = nullptr;

static int
wifi_commissioning_join (PropArray& params, PropArray& outProps);

static int
wifi_commissioning_get_scan_results (PropArray& params, PropArray& outProps);

static int
wifi_commissioning_end_requested (PropArray& params, PropArray& outProps);

static int
wifi_commissioning_scan (void);

static void
wifi_commissioning_rssi_sort (wlan_ap_info_t *scan_result, int first, int last);

static int
wifi_commissioning_try_join (wifi_commissioning_data_t *data);

static int
wifi_commissioning_ap_start (int wifi_dev, const char *ssid, const void *passphrase, int passphrase_len);

static int
wifi_commissioning_ap_stop (int wifi_dev);

int wifi_commissioning_start (int commissioning_type, wifi_commissioning_init_t *init)
{
  if (init == nullptr)
    {
      return E_FAILED;
    }

  if ((init->wifi_dev == -1) || (init->device_srv == nullptr))
    {
      return E_FAILED;
    }

  if (commissioning_type == WCT_AP)
    {
      wifi_commissioning_type = WCT_AP;
    }
  else if (commissioning_type == WCT_BLE)
    {
      wifi_commissioning_type = WCT_BLE;
    }
  else if (commissioning_type == WCT_LEGACY)
    {
      wifi_commissioning_type = WCT_LEGACY;
    }
  else
    {
      return E_FAILED;
    }

  if (wifi_commissioning_running == 1)
    {
      return E_RUNNING;
    }

  wifi_commissioning_commissioner_dev = init->commissioner_dev;
  wifi_commissioning_data_callback = init->data_callback;
  wifi_commissioning_running = 1;

  wifi_commissioning_wifi_dev = init->wifi_dev;
  coldwave_device_service = init->device_srv;
  coldwave_device_service->set (PropMakeU8 (P_WIFI_CAPABILITIES, WIFI_CAP_JOIN | WIFI_CAP_SCAN));
  coldwave_device_service->set (PropMakeBool (P_WIFI_IS_SCANNING, false));
  coldwave_device_service->set (PropMakeString (P_WIFI_CURR_SSID, nullptr));
  coldwave_device_service->set (PropMakeU8 (P_WIFI_STATE, CW_WIFI_DISCONNECTED));
  coldwave_device_service->set (PropMakeU32 (P_WIFI_IF_IP, 0));

  coldwave_device_service->onMessage ("WIFI_JOIN", wifi_commissioning_join);
  coldwave_device_service->onMessage ("WIFI_SCAN", wifi_commissioning_get_scan_results);
  coldwave_device_service->onMessage ("WIFI_END_COMMISSIONING", wifi_commissioning_end_requested);

  if (E_OK != wifi_commissioning_scan ())
    {
      return E_SCAN;
    }

  Property pWifiCaps (P_WIFI_CAPABILITIES);

  int res = E_OK;

  if (wifi_commissioning_type == WCT_AP)
    {

      pWifiCaps.u8 = WIFI_CAP_JOIN | WIFI_CAP_SCAN;
      res = wifi_commissioning_ap_start (wifi_commissioning_commissioner_dev,
                                         init->commissioner_name, init->commissioner_password,
                                         strlen (init->commissioner_password));
    }
  else if (wifi_commissioning_type == WCT_LEGACY)
    {

      wifi_commissioning_ble_start (init->wifi_dev, wifi_commissioning_commissioner_dev, init->commissioner_name,
                                    wifi_commissioning_try_join, wifi_commissioning_end);

      wifi_commissioning_ble_update_ssids (wifi_commissioning_scan_results, wifi_commissioning_num_scan_results);
    }
  else if (wifi_commissioning_type == WCT_BLE)
    {
      pWifiCaps.u8 = WIFI_CAP_JOIN | WIFI_CAP_SCAN;

      flakeSerialWireCallbacks_t wire_cb;

      flakeRouterAddSerialServerWire (wifi_commissioning_commissioner_dev, &wire_cb);

      ioctl (wifi_commissioning_commissioner_dev, BLE_IOCTL_SET_CONNECT_CALLBACK, (void *) wire_cb.onConnect);
      ioctl (wifi_commissioning_commissioner_dev, BLE_IOCTL_SET_DISCONNECT_CALLBACK, (void *) wire_cb.onDisconnect);
      ioctl (wifi_commissioning_commissioner_dev, BLE_IOCTL_START_ADVERTISING, 0);
      ioctl (wifi_commissioning_commissioner_dev, BLE_IOCTL_AUTO_RECONNECT, (void *) 1);
    }

  if (res != E_OK)
    {
      return res;
    }

  wifi_commissioning_timeout_tmr = osTimerNew (wifi_commissioning_end, osTimerOnce, WC_TIMER_EXPIRED, 0);
  osTimerStart (wifi_commissioning_timeout_tmr, init->timeout_ms);

  coldwave_device_service->set (pWifiCaps);

  return res;

}

void wifi_commissioning_end (void *p)
{
  if (p == WC_TIMER_EXPIRED)
    {
      wifi_commissioning_data_callback (E_TIMEOUT, nullptr);
    }

  wifi_commissioning_running = 0;

  if (osTimerIsRunning (wifi_commissioning_timeout_tmr))
    {
      osTimerStop (wifi_commissioning_timeout_tmr);
    }

  if (wifi_commissioning_type == WCT_BLE)
    {
#if WIFI_COMMISSIONING_BLE_LEGACY
      wifi_commissioning_ble_stop (wifi_commissioning_ble_dev);
#else
      ioctl (wifi_commissioning_commissioner_dev, BLE_IOCTL_AUTO_RECONNECT, 0);
      ioctl (wifi_commissioning_commissioner_dev, BLE_IOCTL_DISCONNECT, 0);
#endif
    }
  else
    {
      if (E_OK != wifi_commissioning_ap_stop (wifi_commissioning_wifi_dev))
        {
          return;
        }
    }

  Property pWifiCaps (P_WIFI_CAPABILITIES);
  pWifiCaps.u8 = WIFI_CAP_JOIN | WIFI_CAP_SCAN;
  coldwave_device_service->set (pWifiCaps);

}

int wifi_commissioning_scan ()
{

  wifi_commissioning_num_scan_results = 0;
  wifi_commissioning_scan_results = (wlan_ap_info_t *) malloc (sizeof (wlan_ap_info_t) * WIFI_MAX_SCAN_RESULTS);

  int32_t err = wlan_scan (wifi_commissioning_wifi_dev, NULL, 0, wifi_commissioning_scan_results, &wifi_commissioning_num_scan_results, WIFI_MAX_SCAN_RESULTS);
  if (err != 0)
    {
      return E_FAILED;
    }

  wifi_commissioning_rssi_sort (wifi_commissioning_scan_results, 0, wifi_commissioning_num_scan_results - 1);

  return E_OK;

};

void wifi_commissioning_rssi_sort (wlan_ap_info_t *scan_result, int first, int last)
{
  int i, j, pivot;
  wlan_ap_info_t temp;

  if (first < last)
    {
      pivot = first;
      i = first;
      j = last;

      while (i < j)
        {
          while (abs (scan_result[i].rssi_val) <= abs (scan_result[pivot].rssi_val) && i < last)
            i++;
          while (abs (scan_result[j].rssi_val) > abs (scan_result[pivot].rssi_val))
            j--;
          if (i < j)
            {
              memcpy (&temp, &scan_result[i], sizeof (wlan_ap_info_t));
              memcpy (&scan_result[i], &scan_result[j], sizeof (wlan_ap_info_t));
              memcpy (&scan_result[j], &temp, sizeof (wlan_ap_info_t));
            }
        }

      memcpy (&temp, &scan_result[pivot], sizeof (wlan_ap_info_t));
      memcpy (&scan_result[pivot], &scan_result[j], sizeof (wlan_ap_info_t));
      memcpy (&scan_result[j], &temp, sizeof (wlan_ap_info_t));

      wifi_commissioning_rssi_sort (scan_result, first, j - 1);
      wifi_commissioning_rssi_sort (scan_result, j + 1, last);

    }
}

void wifi_commissioning_end_async ()
{
  osDispatchAsync (wifi_commissioning_end, 0);
}

void wifi_commissioning_try_join_async (void *p)
{

  wifi_commissioning_data_t *commissioning_data = (wifi_commissioning_data_t *) p;

  (void) wifi_commissioning_try_join (commissioning_data);

  free (commissioning_data);

}

int wifi_commissioning_try_join (wifi_commissioning_data_t *data)
{
  PropArray props;

  Property pRes (P_RESULT);

  pRes.i8 = E_FAILED;

  if (data->sec_type != WLAN_SEC_MODE_WPA2
      && data->sec_type != WLAN_SEC_MODE_WPA3)
    {
      pRes.i8 = E_REFUSED;
    }
  else
    {
      int res = wlan_connect (wifi_commissioning_wifi_dev, (uint8_t *) data->ssid, (uint8_t *) data->bssid,
                              (wlan_security_mode) data->sec_type,
                              (void *) data->passphrase, false);
      if (res == 0)
        {

        wlan_connection_state_t wcs;
        wlan_connection_state(wifi_commissioning_wifi_dev, &wcs);

          while (wcs == WLAN_STATE_CONNECTING)
            {
              Property pWifiState (P_WIFI_STATE);
              pWifiState.u8 = CW_WIFI_CONNECTING;
              coldwave_device_service->set (pWifiState);
              osDelay (10);
              wlan_connection_state(wifi_commissioning_wifi_dev, &wcs);
            }

          if (wcs != WLAN_STATE_CONNECTED)
            {
              Property pWifiState (P_WIFI_STATE);
              pWifiState.u8 = CW_WIFI_DISCONNECTED;
              coldwave_device_service->set (pWifiState);
            }
          else
            {
              Property pWifiState (P_WIFI_STATE);
              pWifiState.u8 = CW_WIFI_CONNECTED;
              coldwave_device_service->set (pWifiState);
              pRes.i8 = E_OK;
            }
        }
    }

  props.set (pRes);

  Property pActionToken (P_ACTIONTOKEN);
  pActionToken.u16 = wifi_join_action_token;
  props.set (pActionToken);

  coldwave_device_service->broadcast ("WIFI_JOIN_RESULT", props);

  if ((wifi_commissioning_type == WCT_AP) && (pRes.i8 == E_OK))
    {
      wifi_commissioning_data_callback (E_OK, data);
    }

  return pRes.i8;

}

int wifi_commissioning_join (PropArray& params, PropArray& outProps)
{
  UNUSED(outProps);

  if (!params.has (P_ACTIONTOKEN))
    {
      return E_INCOMPLETE;
    }

  wifi_join_action_token = params.get (P_ACTIONTOKEN).u16;

  wifi_commissioning_data_t *commissioning_data = (wifi_commissioning_data_t *) malloc (sizeof (wifi_commissioning_data_t));
  commissioning_data->sec_type = params.get (P_SECTYPE).u8;
  // add +1 to also copy '\0'
  commissioning_data->ssid_length = strlen (params.get (P_SSID).str) + 1;
  commissioning_data->passphrase_length = strlen (params.get (P_PASSKEY).str) + 1;

  memcpy (commissioning_data->ssid, params.get (P_SSID).str, MIN(commissioning_data->ssid_length, 32));
  memcpy (commissioning_data->passphrase, params.get (P_PASSKEY).str, MIN(commissioning_data->passphrase_length, 63));
  memcpy (commissioning_data->bssid, params.get (P_BSSID).bin.lpb, 6);

  osDispatchAsync (wifi_commissioning_try_join_async, commissioning_data);

  return E_PENDING;
}

int wifi_commissioning_end_requested (PropArray& params, PropArray& outProps)
{
  UNUSED(outProps);
  UNUSED(params);

  wifi_commissioning_end_async ();

  return E_OK;

}

void wifi_commissioning_broadcast_scan_results (void *p)
{
  UNUSED(p);

  uint32_t action_token = wifi_scan_action_token;
  PropArray props;

  int32_t err = wlan_scan (wifi_commissioning_wifi_dev, NULL, 0, wifi_commissioning_scan_results, &wifi_commissioning_num_scan_results, WIFI_MAX_SCAN_RESULTS);

  if (err == 0)
    {

      wifi_commissioning_rssi_sort (wifi_commissioning_scan_results, 0, wifi_commissioning_num_scan_results - 1);

      for (uint8_t i = 0; i < wifi_commissioning_num_scan_results; i++)
        {
          Property pSSID (P_SSID);
          pSSID.str = (char *) wifi_commissioning_scan_results[i].ssid;
          props.set (pSSID);

          Property pBSSID (P_BSSID);
          pBSSID.bin.cb = sizeof (wifi_commissioning_scan_results[i].bssid);
          pBSSID.bin.lpb = new byte[6];

          for (uint8_t j = 0; j < 6; j++)
            {
              pBSSID.bin.lpb[j] = wifi_commissioning_scan_results[i].bssid[j];
            }

          props.set (pBSSID);

          Property pSecType (P_SECTYPE);
          pSecType.u8 = wifi_commissioning_scan_results[i].security_mode;
          props.set (pSecType);

          Property pRSSI (P_RSSI);
          pRSSI.i16 = wifi_commissioning_scan_results[i].rssi_val;
          props.set (pRSSI);

          int res = coldwave_device_service->broadcast ("WIFI_SCAN_RESULT", props);

          if (res != E_OK) {
              LOG_ERROR ("brodacast error %d at msg. %d", res, i);
          }

          props.clear ();
          osDelay (200);
        }

    }

  Property pActionToken (P_ACTIONTOKEN);
  pActionToken.u16 = action_token;
  props.set (pActionToken);

  Property result (P_RESULT);
  result.u8 = 0;
  props.set (result);

  coldwave_device_service->broadcast ("WIFI_SCAN_FINISHED", props);
  props.clear ();

  wifi_scan_action_token = 0;

}

int wifi_commissioning_get_scan_results (PropArray& params, PropArray& outProps)
{
  // this just broadcasts the previously scanned networks (because we can't re-scan in AP
  // actual scanning has to be started outside in application
  //
  UNUSED(outProps);

  if (wifi_scan_action_token != 0)
    {
      return E_FAILED;
    }

  if (!params.has (P_ACTIONTOKEN))
    {
      return E_INCOMPLETE;
    }

  wifi_scan_action_token = params.get (P_ACTIONTOKEN).u16;

  osDispatchAsync (wifi_commissioning_broadcast_scan_results, 0);

  return E_PENDING;

}

int wifi_commissioning_ap_start (int wifi_dev, const char *ssid, const void *passphrase, int passphrase_len)
{

  if (wifi_commissioning_ap_started == 1)
    {
      return E_RUNNING;
    }

  wlan_disconnect (wifi_dev);
  wifi_commissioning_ap_started = 1;

  char _ssid[SSID_MAX_LEN] = {0};
  uint32_t ssid_len = MIN(SSID_MAX_LEN, strlen (ssid));
  memcpy (_ssid, ssid, ssid_len);

  wlan_start_ap (wifi_dev, 6, (uint8_t *) ssid, ssid_len, 0, WLAN_SEC_MODE_WPA2, (uint8_t *) passphrase, passphrase_len);

  return E_OK;

}

int wifi_commissioning_ap_stop (int wifi_dev)
{

  if (wifi_commissioning_ap_started == 0)
    {
      return E_OK;
    }

  int res = wlan_stop_ap (wifi_dev);
  if (res != 0)
    {
      return E_FAILED;
    }

  wifi_commissioning_ap_started = 0;

  return E_OK;

}