Implementations for network related CLI commands.

License#

Copyright 2018 Silicon Laboratories Inc. www.silabs.com

The licensor of this software is Silicon Laboratories Inc. Your use of this software is governed by the terms of Silicon Labs Master Software License Agreement (MSLA) available at www.silabs.com/about-us/legal/master-software-license-agreement. This software is distributed to you in Source Code format and is governed by the sections of the MSLA applicable to Source Code.

/***************************************************************************/
#include "app/framework/include/af.h"
#include "app/framework/util/af-main.h"
#include "app/framework/util/util.h"
#include "app/util/serial/command-interpreter2.h"
#include "app/util/zigbee-framework/zigbee-device-common.h"
#include "network-cli.h"

// emberFindAndRejoinNetworkWithReason
#ifdef EZSP_HOST
  #include "app/util/ezsp/ezsp.h"
#else
  #include "stack/include/network-formation.h"
#endif

//------------------------------------------------------------------------------

void networkJoinCommand(void);
void networkRejoinCommand(void);
void networkFormCommand(void);
void networkExtendedPanIdCommand(void);
void networkLeaveCommand(void);
void networkPermitJoinCommand(void);
void findJoinableNetworkCommand(void);
void findUnusedPanIdCommand(void);
void networkChangeChannelCommand(void);
void networkSetCommand(void);
void networkIdCommand(void);
void networkMultiPhyStartCommand(void);
void networkMultiPhyStopCommand(void);
void networkChangeChildTimeoutOptionMaskCommand(void);
void changeKeepAliveModeCommand(void);
void networkCheckPjoinCommand(void);

// TODO: Gate this again when we have the mechanism for doing so
// with the generated CLI.
//#if defined(EMBER_AF_TC_SWAP_OUT_TEST)
void networkInitCommand(void);
//#endif

#define EMBER_AF_DOXYGEN_CLI__NETWORK_COMMANDS

#ifndef EMBER_AF_GENERATE_CLI

// Form and join library commands.
static EmberCommandEntry findCommands[] = {
  { "joinable", findJoinableNetworkCommand, "" },
  { "unused", findUnusedPanIdCommand, "" },
  { NULL },
};

EmberCommandEntry networkCommands[] = {
  { "form", networkFormCommand, "usv" },
  { "join", networkJoinCommand, "usvu*" },
  { "rejoin", networkRejoinCommand, "uw" },
  { "leave", networkLeaveCommand, "" },
  { "isopen", networkCheckPjoinCommand, "" },
  { "pjoin", networkPermitJoinCommand, "u" },
  { "broad-pjoin", networkPermitJoinCommand, "u" },
  { "extpanid", networkExtendedPanIdCommand, "b" },
  { "find", NULL, (const char *)findCommands },

  emberCommandEntryAction("id",
                          networkIdCommand,
                          "",
                          "Print the current network IDs"),

  { "change-channel", networkChangeChannelCommand, "u" },
  { "multi-phy-start", networkMultiPhyStartCommand, "uusu*" },
  { "multi-phy-stop", networkMultiPhyStopCommand, "" },

#if defined(EMBER_AF_TC_SWAP_OUT_TEST)
  // Do not document this command.
  { "init", networkInitCommand, "" },
#endif

  { "set", networkSetCommand, "u" },
  { "change-keep-alive-mode", changeKeepAliveModeCommand, "u" },
  { "timeout-option-mask", networkChangeChildTimeoutOptionMaskCommand, "v" },

  { NULL }
};

#endif // EMBER_AF_GENERATE_CLI

uint8_t emAfCliNetworkIndex = EMBER_AF_DEFAULT_NETWORK_INDEX;

#ifdef EMBER_AF_PLUGIN_TEST_HARNESS_Z3
extern EmberEventControl emZigbeeLeaveEvent;
#endif

//------------------------------------------------------------------------------

void initNetworkParams(EmberNetworkParameters *networkParams)
{
  MEMSET(networkParams, 0, sizeof(EmberNetworkParameters));
  emberAfGetFormAndJoinExtendedPanIdCallback(networkParams->extendedPanId);
  networkParams->radioChannel = (uint8_t)emberUnsignedCommandArgument(0);
  networkParams->radioTxPower = (int8_t)emberSignedCommandArgument(1);
  networkParams->panId = (uint16_t)emberUnsignedCommandArgument(2);
  if (emberCommandArgumentCount() > 3) {
    // Map the channel page into the channel, if present.
    // Page bits: 7, 6, 5 channel bits: 4...0
    uint8_t page = (uint8_t)emberUnsignedCommandArgument(3);
    networkParams->radioChannel = (uint8_t)((page << 5) | (networkParams->radioChannel & 0x1F));
  }
}

// network join <channel> <power> <panid>
void networkJoinCommand(void)
{
  EmberStatus status;
  EmberNetworkParameters networkParams = { 0 };
  initNetworkParams(&networkParams);
  status = emberAfJoinNetwork(&networkParams);
  UNUSED_VAR(status);
  emberAfAppPrintln("%p 0x%x", "join", status);
}

// network rejoin <haveCurrentNetworkKey:1>
void networkRejoinCommand(void)
{
  bool haveCurrentNetworkKey = (bool)emberUnsignedCommandArgument(0);
  uint32_t channelMask = (uint32_t)emberUnsignedCommandArgument(1);
  if (channelMask == 0) {
    channelMask = EMBER_ALL_802_15_4_CHANNELS_MASK;
  }
  EmberStatus status = emberFindAndRejoinNetworkWithReason(haveCurrentNetworkKey,
                                                           channelMask,
                                                           EMBER_AF_REJOIN_DUE_TO_CLI_COMMAND);
  emberAfAppPrintln("%p 0x%x", "rejoin", status);
}

void networkRejoinDiffDeviceTypeCommand(void)
{
  bool haveCurrentNetworkKey = (uint8_t)emberUnsignedCommandArgument(0);
  uint32_t channelMask = (uint32_t)emberUnsignedCommandArgument(1);
  uint8_t emberNodeType = (uint8_t)emberUnsignedCommandArgument(2);
  EmberStatus status = emberFindAndRejoinNetworkWithNodeType(haveCurrentNetworkKey,
                                                             channelMask,
                                                             emberNodeType);
  emberAfAppPrintln("%p 0x%x", "rejoinDiffDeviceType", status);
}

// network form <channel> <power> <panid>
void networkFormCommand(void)
{
#ifdef EMBER_AF_HAS_COORDINATOR_NETWORK
  EmberStatus status;
  EmberNetworkParameters networkParams;
  initNetworkParams(&networkParams);
  status = emberAfFormNetwork(&networkParams);
  emberAfAppPrintln("%p 0x%x", "form", status);
  emberAfAppFlush();
#else
  emberAfAppPrintln("only coordinators can form");
#endif
}

// network extpanid <8 BYTES>
void networkExtendedPanIdCommand(void)
{
  emberCopyBigEndianEui64Argument(0, emAfExtendedPanId);
  emberAfSetFormAndJoinExtendedPanIdCallback(emAfExtendedPanId);
  emberAfAppPrint("ext. PAN ID: ");
  emberAfAppDebugExec(emberAfPrintBigEndianEui64(emAfExtendedPanId));
  emberAfAppPrintln("");
}

// network leave
void networkLeaveCommand(void)
{
  EmberStatus status;
  status = emberLeaveNetwork();
#ifdef EMBER_AF_PLUGIN_TEST_HARNESS_Z3
  // Complete the leave immediately without the usual delay.
  emberEventControlSetActive(emZigbeeLeaveEvent);
#endif
  UNUSED_VAR(status);
  emberAfAppPrintln("%p 0x%x", "leave", status);
}

// check pjoin status
void networkCheckPjoinCommand(void)
{
  uint8_t open_duration = emberAfGetOpenNetworkDurationSec();
  if (open_duration > 0) {
    emberAfAppPrintln("NWK open: %u sec", open_duration);
  } else {
    emberAfAppPrintln("NWK closed");
  }
}

// network pjoin <time>
// network broad-pjoin <time>
void networkPermitJoinCommand(void)
{
  uint8_t duration = (uint8_t)emberUnsignedCommandArgument(0);
  emAfPermitJoin(duration,
                 ('b'
                  == emberStringCommandArgument(-1,
                                                NULL)[0]));  // broadcast permit join?
}

void findJoinableNetworkCommand(void)
{
  EmberStatus status = emberAfStartSearchForJoinableNetwork();
  emberAfCorePrintln("find joinable: 0x%X", status);
}

void findUnusedPanIdCommand(void)
{
  EmberStatus status = emberAfFindUnusedPanIdAndForm();
  emberAfCorePrintln("find unused: 0x%X", status);
}

void networkChangeChannelCommand(void)
{
  uint8_t channel = (uint8_t)emberUnsignedCommandArgument(0);
  EmberStatus status = emberChannelChangeRequest(channel);
  emberAfAppPrintln("Changing to channel %d: 0x%X",
                    channel,
                    status);
}

// TODO: Put gating back in after we have a mechanism in place to do so
// for the generated CLI.
//#if defined(EMBER_AF_TC_SWAP_OUT_TEST)
void networkInitCommand(void)
{
  EmberNetworkInitStruct networkInitStruct = {
    EMBER_AF_CUSTOM_NETWORK_INIT_OPTIONS   // EmberNetworkInitBitmask value
  };
  EmberStatus status = emberNetworkInit(&networkInitStruct);
  emberAfAppPrintln("Network Init returned: 0x%X", status);
}
//#endif

void networkSetCommand(void)
{
  uint8_t index = (uint8_t)emberUnsignedCommandArgument(0);
  if (EMBER_SUPPORTED_NETWORKS <= index) {
    emberAfCorePrintln("invalid network index");
    return;
  }
  emAfCliNetworkIndex = index;
}

void networkIdCommand(void)
{
  EmberEUI64 eui64;
  emberAfGetEui64(eui64);
  emberAfCorePrint("Short ID: 0x%2X, EUI64: ", emberAfGetNodeId());
  emberAfPrintBigEndianEui64(eui64);
  emberAfCorePrintln(", Pan ID: 0x%2X", emberAfGetPanId());
}

void networkMultiPhyStartCommand(void)
{
  EmberStatus status;
  uint8_t page = emberUnsignedCommandArgument(0);
  uint8_t channel = emberUnsignedCommandArgument(1);
  int8_t power = (int8_t)emberSignedCommandArgument(2);
  uint8_t optionsMask = 0;

  if (emberCommandArgumentCount() > 3) {
    optionsMask = (uint8_t) emberUnsignedCommandArgument(3);
  }

  status = emberMultiPhyStart(PHY_INDEX_PRO2PLUS, page, channel, power, optionsMask);

  if (status == EMBER_SUCCESS) {
    emberAfCorePrintln("Started multi-phy interface");
  } else {
    emberAfCorePrintln("Failed to %s %s 0x%X",
                       "start",
                       "multi-phy interface",
                       status);
  }
}

void networkMultiPhyStopCommand(void)
{
  uint8_t status = emberMultiPhyStop(PHY_INDEX_PRO2PLUS);

  if (status == EMBER_SUCCESS) {
    emberAfCorePrintln("Terminated %s 0x%X",
                       "multi-phy interface",
                       status);
  } else {
    emberAfCorePrintln("Failed to %s %s 0x%X",
                       "stop",
                       "multi-phy interface",
                       status);
  }
}

/* ToDo: keep or remove? needed for testing. no ezsp support. */
void changeKeepAliveModeCommand(void)
{
  uint8_t keepAliveMode = emberUnsignedCommandArgument(0);
  if (!emberSetKeepAliveMode(keepAliveMode)) {
    emberAfAppPrintln("Keep alive support enabled.");
  } else {
    emberAfAppPrintln("failed to set keep alive mode.");
  }
}

void networkChangeChildTimeoutOptionMaskCommand(void)
{
  uint16_t mask = (uint16_t)emberUnsignedCommandArgument(0);
  if (!emberSetChildTimeoutOptionMask(mask)) {
    emberAfAppPrintln("successfully set the child timeout option mask.");
  } else {
    emberAfAppPrintln("failed to set the child timeout option mask.");
  }
}

Macros#

#define

network form <channel> <power> <panid>

Variables#

EmberCommandEntry
EmberCommandEntry

Macro Definition Documentation#

EMBER_AF_DOXYGEN_CLI__NETWORK_COMMANDS#

#define EMBER_AF_DOXYGEN_CLI__NETWORK_COMMANDS

network form <channel> <power> <panid>

  • Form a network on a given channel, with a given TX Power and PAN ID.

    • channel - uint8_t. The channel on which to form the network.

    • power - int8_t. One byte signed value indicating the TX Power that the radio should be set to.

    • panId - uint16_t. The PAN ID on which to form the network.

network join <channel> <power> <panid>

  • Join a network on a given channel, with a given TX Power and PAN ID.

    • channel - uint8_t. The channel on which to join the network.

    • power - int8_t. One byte signed value indicating the TX Power that the radio should be set to.

    • panId - uint16_t. The PAN ID on which to join the network.

network rejoin <encrypted>

  • Find and rejoin the previous network the device was connected to.

    • encrypted - uint8_t. A single byte boolean 0 or 1 indicating whether or not the rejoin should be done with encryption.

network leave

  • Leave the current network that the device is connected to.

network pjoin <seconds>

  • Turn permit joining on for the amount of time indicated.

    • seconds - uint8_t. A single byte indicating how long the device should have permit joining turn on for. A value of 0xff turns permit join indefinitely.

network broad-pjoin <seconds>

  • Turn permit joining on for the amount of time indicated AND broadcast a ZDO Mgmt Permit Joining request to all routers.

    • seconds - uint8_t. A single byte indicating how long the device should have permit joining turn on for. A value of 0xff turns permit join indefinitely.

network isopen

  • Check if the network has permit joining on and if yes report the remaining time for which the network will be open.

    • seconds - uint8_t. A single byte indicating how long the device will have permit joining turn on for.

network extpanid <bytes>

  • Write the extended PAN ID of the device.

    • bytes - byte array. An array of bytes which represents the extended PAN ID for the device.

network find unused

  • Begins a search for an unused Channel and PAN ID. Will automatically form a network on the first unused Channel and PAN ID it finds.

network find joinable

  • Begins a search for a joinable network. Will automatically attempt to join the first network it finds.


Definition at line 117 of file ./app/framework/cli/network-cli.c

Variable Documentation#

findCommands#

EmberCommandEntry findCommands[]

Definition at line 123 of file ./app/framework/cli/network-cli.c

networkCommands#

EmberCommandEntry networkCommands[]

Definition at line 129 of file ./app/framework/cli/network-cli.c

emAfCliNetworkIndex#

uint8_t emAfCliNetworkIndex

Definition at line 163 of file ./app/framework/cli/network-cli.c

Function Documentation#

networkJoinCommand#

void networkJoinCommand (void )
Parameters
N/A

Definition at line 187 of file ./app/framework/cli/network-cli.c

networkRejoinCommand#

void networkRejoinCommand (void )
Parameters
N/A

Definition at line 198 of file ./app/framework/cli/network-cli.c

networkFormCommand#

void networkFormCommand (void )
Parameters
N/A

Definition at line 223 of file ./app/framework/cli/network-cli.c

networkExtendedPanIdCommand#

void networkExtendedPanIdCommand (void )
Parameters
N/A

Definition at line 238 of file ./app/framework/cli/network-cli.c

networkLeaveCommand#

void networkLeaveCommand (void )
Parameters
N/A

Definition at line 248 of file ./app/framework/cli/network-cli.c

networkPermitJoinCommand#

void networkPermitJoinCommand (void )
Parameters
N/A

Definition at line 273 of file ./app/framework/cli/network-cli.c

findJoinableNetworkCommand#

void findJoinableNetworkCommand (void )
Parameters
N/A

Definition at line 282 of file ./app/framework/cli/network-cli.c

findUnusedPanIdCommand#

void findUnusedPanIdCommand (void )
Parameters
N/A

Definition at line 288 of file ./app/framework/cli/network-cli.c

networkChangeChannelCommand#

void networkChangeChannelCommand (void )
Parameters
N/A

Definition at line 294 of file ./app/framework/cli/network-cli.c

networkSetCommand#

void networkSetCommand (void )
Parameters
N/A

Definition at line 316 of file ./app/framework/cli/network-cli.c

networkIdCommand#

void networkIdCommand (void )
Parameters
N/A

Definition at line 326 of file ./app/framework/cli/network-cli.c

networkMultiPhyStartCommand#

void networkMultiPhyStartCommand (void )
Parameters
N/A

Definition at line 335 of file ./app/framework/cli/network-cli.c

networkMultiPhyStopCommand#

void networkMultiPhyStopCommand (void )
Parameters
N/A

Definition at line 359 of file ./app/framework/cli/network-cli.c

networkChangeChildTimeoutOptionMaskCommand#

void networkChangeChildTimeoutOptionMaskCommand (void )
Parameters
N/A

Definition at line 386 of file ./app/framework/cli/network-cli.c

changeKeepAliveModeCommand#

void changeKeepAliveModeCommand (void )
Parameters
N/A

Definition at line 376 of file ./app/framework/cli/network-cli.c

networkCheckPjoinCommand#

void networkCheckPjoinCommand (void )
Parameters
N/A

Definition at line 261 of file ./app/framework/cli/network-cli.c

networkInitCommand#

void networkInitCommand (void )
Parameters
N/A

Definition at line 306 of file ./app/framework/cli/network-cli.c

initNetworkParams#

void initNetworkParams (EmberNetworkParameters * networkParams)
Parameters
N/AnetworkParams

Definition at line 171 of file ./app/framework/cli/network-cli.c

networkRejoinDiffDeviceTypeCommand#

void networkRejoinDiffDeviceTypeCommand (void )
Parameters
N/A

Definition at line 211 of file ./app/framework/cli/network-cli.c