Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

DSW BasicOps

DSW BasicOps

Explanation

About the Sample Application Code

This C application code is designed to interact with North Atlantic Industries (NAI) embedded function modules, specifically discrete switch (DSW) modules. The application configures, controls, and reads the state of switch modules using the NAI libraries.

Definitions and Key Components

  1. Includes and Definitions:

    • The code begins by including standard libraries and specific NAI libraries required for accessing and manipulating the DSW modules.

    • CONFIG_FILE is a pointer to the default configuration file used for this operation.

    • Function prototypes for various configuration and display functionalities are declared.

  2. Enumerations and Constants:

    • Enumeration dsw_basicops_commands defines commands for basic operations on DSW modules, such as switching states and setting thresholds.

    • DEF_DSW_CHANNEL sets the default channel used in various operations.

  3. Command Table:

    • DSW_BasicOpMenuCmds is an array of command structures mapping text commands to their corresponding functionalities.

Application Entry Point and Main Loop

The main entry point is either DSW_BasicOps() or main(), depending on the operating system. The application flow is as follows:

  1. Initial Setup:

    • The application starts by running the board menu using naiapp_RunBoardMenu.

    • If the configuration file runs successfully, the application enters the main loop.

  2. User Queries:

    • During each iteration, the application queries the user for the card index and module number.

    • If a valid module is selected, Run_DSW_BasicOps is invoked.

  3. Loop Continuation:

    • The user can choose to quit or restart the application after each iteration.

Core Functionalities

1. Run_DSW_BasicOps This function validates and configures the selected channel if it is a DSW module. It calls Cfg_DSW_Channel to handle configurations and display tasks.

2. Cfg_DSW_Channel This function displays channel configuration using Display_DSW_ChannelCfg and processes user menu commands. It continues to prompt the user until they choose to exit.

3. Display_DSW_ChannelCfg This function retrieves and prints the configuration state of the selected channel, including switch state, input state, thresholds, and measured voltages and currents.

4. Display_DSW_Status This function retrieves and prints the status of the selected channel using the NAI library functions.

5. Configuration Functions: - Configure_DSW_SwitchState: Sets the switch state (open or closed) based on user input. - Configure_DSW_Threshold: Sets various threshold types based on user input. Specific functions like Configure_DSW_MinLoThreshold, Configure_DSW_LowThreshold, etc., act as wrappers to call this function.

Error Handling and Utilities

Throughout the code, check_status is used to verify function calls to the NAI library, which ensures proper error handling and robustness.

Example Output

The application provides an interactive menu for the user to configure and check the status of DSW modules. It allows for setting switch states and thresholds and displays real-time measurements of voltage and current.

printf("\n === Channel %d ===\n\n", chan);
printf(" Switch   Input    ==== Thresholds ( LSB: %1.3fV ) =====     \n", voltageLSB);
printf(" State    State    MinLow     Lower     Upper    Max Hi      \n");
printf(" ------   -----    -------   -------   -------   -------     \n");
// Example output might include values for switch state, input, thresholds, voltage, and current.

This application serves as a comprehensive tool for managing DSW modules, allowing users to interactively configure and monitor their embedded switch modules using the NAI libraries.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_dsw.h"
#include "advanced/nai_ether_adv.h"

static const int8_t *CONFIG_FILE = (int8_t *)"default_DSW_BasicOp.txt";

/* Function prototypes */
int32_t Run_DSW_BasicOps(int32_t cardIndex, int32_t module, int32_t ModuleID);
static void Cfg_DSW_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel);

static void Display_DSW_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID);
static nai_status_t Display_DSW_Status(int32_t paramCount, int32_t* p_params);

static nai_status_t Configure_DSW_SwitchState(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DSW_MinLoThreshold(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DSW_LowThreshold(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DSW_UpperThreshold(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DSW_MaxHiThreshold(int32_t paramCount, int32_t* p_params);
nai_status_t Configure_DSW_Threshold(int32_t cardIndex, int32_t module, int32_t chan, nai_dsw_thresh_type_t thresholdtype, int8_t* thresholdtext);

static const int32_t DEF_DSW_CHANNEL       = 1;

/****** Command Table *******/
enum dsw_basicops_commands
{
   DSW_BASICOP_CMD_SWITCHSTATE,
   DSW_BASICOP_CMD_THRESHOLD_MIN_LO,
   DSW_BASICOP_CMD_THRESHOLD_LOWER,
   DSW_BASICOP_CMD_THRESHOLD_UPPER,
   DSW_BASICOP_CMD_THRESHOLD_MAX_HI,
   DSW_BASICOP_CMD_STATUS,
   DSW_BASICOP_CMD_COUNT
};

/****** Command Tables *******/
naiapp_cmdtbl_params_t DSW_BasicOpMenuCmds[] = {
   {"Switch",  "DSW Set Switch State",       DSW_BASICOP_CMD_SWITCHSTATE,       Configure_DSW_SwitchState},
   {"ML",      "DSW Set Min Low Threshold",  DSW_BASICOP_CMD_THRESHOLD_MIN_LO,  Configure_DSW_MinLoThreshold},
   {"L",       "DSW Set Lower Threshold",    DSW_BASICOP_CMD_THRESHOLD_LOWER,   Configure_DSW_LowThreshold},
   {"U",       "DSW Set Upper Threshold",    DSW_BASICOP_CMD_THRESHOLD_UPPER,   Configure_DSW_UpperThreshold},
   {"MH",      "DSW Set Max High Threshold", DSW_BASICOP_CMD_THRESHOLD_UPPER,   Configure_DSW_MaxHiThreshold},
   {"STAT",    "DSW Display Status",         DSW_BASICOP_CMD_STATUS,            Display_DSW_Status},
};

/**************************************************************************************************************/
/**
<summary>
The purpose of the DSW_BasicOps is to illustrate the methods to call in the naibrd library to perform basic
 operations with the discrete switch modules for configuration setup, controlling the switch closure state, and reading
 the channels.

The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd DT routines.
 - ClearDeviceCfg
 - QuerySystemCfg
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DSW_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_DSW_BasicOps(cardIndex, module, moduleID);
               }
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/**
<summary>
Run_DSW_BasicOps prompts the user for the card, module and channel to use for the application and calls
Cfg_DSW_Channel if the card, module, channel is valid for as a discrete switch module.
</summary>
*/
/**************************************************************************************************************/
int32_t Run_DSW_BasicOps(int32_t cardIndex, int32_t module, int32_t ModuleID)
{
   int32_t MaxChannel;

   MaxChannel = naibrd_DSW_GetChannelCount(ModuleID);

   if (MaxChannel == 0)
   {
      printf(" *** Module selection not recognized as DSW module. ***\n\n");
   }
   else
   {
      Cfg_DSW_Channel(cardIndex, module, ModuleID, MaxChannel);
   }
   return cardIndex;
}

/**************************************************************************************************************/
/**
<summary>
Cfg_DSW_Channel handles calling the Display_DSW_ChannelCfg routine to display the discrete channel configuration
and calling the routines associated with the user's menu commands.
</summary>
*/
/**************************************************************************************************************/
static void Cfg_DSW_Channel(int32_t cardIndex, int32_t module, uint32_t ModuleID, int32_t MaxChannel)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   int32_t chan, defaultchan = 1;
   int32_t cmd;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   naiapp_AppParameters_t  dsw_params;
   p_naiapp_AppParameters_t dsw_basicops_params = &dsw_params;
   dsw_basicops_params->cardIndex = cardIndex;
   dsw_basicops_params->module = module;
   dsw_basicops_params->modId = ModuleID;
   while (bContinue)
   {
      printf("    \r\n\r\n");
      printf("Channel selection \r\n");
      printf("================= \r\n");
      defaultchan = DEF_DSW_CHANNEL;
      bQuit = naiapp_query_ChannelNumber(MaxChannel, defaultchan, &chan);
      dsw_basicops_params->channel = chan;

      naiapp_utils_LoadParamMenuCommands(DSW_BASICOP_CMD_COUNT, DSW_BasicOpMenuCmds);
      while (bContinue)
      {
         Display_DSW_ChannelCfg(cardIndex, module, chan, ModuleID);
         naiapp_display_ParamMenuCommands((int8_t *)"DSW Basic Operation Menu");
         printf("\nType DSW command or %c to return : ", NAI_QUIT_CHAR);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
               if (bCmdFound)
               {
                  switch (cmd)
                  {
                  case DSW_BASICOP_CMD_SWITCHSTATE:
                  case DSW_BASICOP_CMD_THRESHOLD_MIN_LO:
                  case DSW_BASICOP_CMD_THRESHOLD_LOWER:
                  case DSW_BASICOP_CMD_THRESHOLD_UPPER:
                  case DSW_BASICOP_CMD_THRESHOLD_MAX_HI:
                  case DSW_BASICOP_CMD_STATUS:
                     DSW_BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)dsw_basicops_params);
                     break;
                  default:
                     printf("Invalid command entered\n");
                     break;
                  }
               }
               else
                  printf("Invalid command entered\n");
            }
         }
         else
            bContinue = FALSE;
      }
   }
}

/**************************************************************************************************************/
/**
<summary>
Display_DSW_ChannelCfg illustrate the methods to call in the naibrd library to retrieve the configuration states
for basic operation.
</summary>
*/
/**************************************************************************************************************/
static void Display_DSW_ChannelCfg(int32_t cardIndex, int32_t module, int32_t chan, uint32_t ModuleID)
{
   nai_dsw_state_t switchstate = 0;
   nai_dsw_state_t inputstate = 0;
   float64_t voltageLSB = 0.0;
   float64_t minlo= 0.0, lower = 0.0, upper = 0.0, maxhi = 0.0;
   float64_t voltage = 0.0, RMSvoltage = 0.0, current = 0.0, RMScurrent = 0.0;
   uint32_t ModuleVer;
   uint32_t ModuleRev;
   uint32_t ModInfo_Special;
   naibrd_GetModuleInfo(cardIndex, module, &ModuleID, &ModuleVer, &ModuleRev, &ModInfo_Special);
   check_status(naibrd_DSW_GetSwitchState(cardIndex, module, chan, &switchstate));
   check_status(naibrd_DSW_GetInputState(cardIndex, module, chan, &inputstate));
   check_status(naibrd_DSW_GetThreshold(cardIndex, module, chan, NAI_DSW_THRESH_MIN_LO, &minlo));
   check_status(naibrd_DSW_GetThreshold(cardIndex, module, chan, NAI_DSW_THRESH_LOWER, &lower));
   check_status(naibrd_DSW_GetThreshold(cardIndex, module, chan, NAI_DSW_THRESH_UPPER, &upper));
   check_status(naibrd_DSW_GetThreshold(cardIndex, module, chan, NAI_DSW_THRESH_MAX_HI, &maxhi));

   check_status(naibrd_DSW_GetVoltageLSB(cardIndex, module, &voltageLSB));

   /*read channel voltage and current*/
   check_status(naibrd_DSW_GetVoltage(cardIndex, module, chan, &voltage));
   check_status(naibrd_DSW_GetCurrent(cardIndex, module, chan, &current));
   check_status(naibrd_DSW_GetAvgVoltage(cardIndex, module, chan, &RMSvoltage));
   check_status(naibrd_DSW_GetAvgCurrent(cardIndex, module, chan, &RMScurrent));

   printf("\n === Channel %d ===\n\n", chan);
   printf(" Switch   Input    ==== Thresholds ( LSB: %1.3fV ) =====     \n", voltageLSB);
   printf(" State    State    MinLow     Lower     Upper    Max Hi      \n");
   printf(" ------   -----    -------   -------   -------   -------     \n");

   switch (switchstate)
   {
      case NAI_DSW_STATE_LO:
      printf(" Open ");
      break;
      case NAI_DSW_STATE_HI:
      printf("Closed");
      break;
      /* undefined value read back */
      default:
      printf(" UNK  ");
      break;
   }

   printf("    %3i     ", inputstate);
   printf("%+8.3f  %+8.3f  %+8.3f  %+8.3f    ", minlo, lower, upper, maxhi);

   printf("\n\n\n  =====Meas.======    ======RMS=======");
   printf("\n  V         mA        V          mA ");
   printf("\n  ------    ------    ------    ------");

   printf("\n%+8.3f  ", voltage);
   printf("%+8.3f  ", current*1000);      /*display in mA units*/
   printf("%+8.3f  ", RMSvoltage);
   printf("%+8.3f  ", RMScurrent*1000);   /*display in mA units*/
}

/**************************************************************************************************************/
/**
<summary>
Display_DSW_Status illustrate the methods to call in the naibrd library to retrieve the status states.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Display_DSW_Status(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;

   nai_status_bit_t status;
   /* Available status:
         NAI_DSW_STATUS_BIT,
         NAI_DSW_STATUS_OVERCURRENT,
         NAI_DSW_STATUS_MAX_HI,
         NAI_DSW_STATUS_MIN_LO,
         NAI_DSW_STATUS_MID_RANGE,
         NAI_DSW_STATUS_LO_HI_TRANS,
         NAI_DSW_STATUS_HI_LO_TRANS,
   */
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   printf("\n");
   printf("  ----------------- Status ----------------------------\n");
   printf("  MinLo   MidRng  MaxHi  Low-Hi   Hi-Lo    BIT     OC\n");
   printf(" ------- -------- ------ ------- -------- ------ ------\n");

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_MIN_LO_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_MID_RANGE_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_MAX_HI_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_LO_HI_TRANS_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_HI_LO_TRANS_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_BIT_LATCHED, &status));
   printf("  %3i   ", status);

   check_status(naibrd_DSW_GetStatus(cardIndex, module, chan, NAI_DSW_STATUS_OVERCURRENT_LATCHED, &status));
   printf("  %3i   ", status);

   printf("\n\n");

   return NAI_ERROR_UNKNOWN;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DSW_SwitchState handles the user request to change the switch state for the selected
channel and calls the method in the naibrd library to set the state.
</summary>
*/
/**************************************************************************************************************/
static nai_status_t Configure_DSW_SwitchState(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   bool_t bUpdateOutput = FALSE;
   nai_dsw_state_t switchstate = 0;
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   /* Set the switch state (open or closed).
   */
   printf("\n Type the desired switch state, Open or Closed (i.e. NO-COM Contact closure)\n ");
   printf(" Enter Open or Closed: ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         switch (toupper(inputBuffer[0]))
         {
         case 'O':
            switchstate = 0;
            bUpdateOutput = TRUE;
            break;
         case 'C':
            switchstate=  1;
            bUpdateOutput = TRUE;
            break;
         default:
            printf("ERROR: Invalid switch state selection\n");
            break;
         }
      }
   }
   if (!bQuit)
   {
      if (bUpdateOutput)
         check_status(naibrd_DSW_SetSwitchState(cardIndex, module, chan, switchstate));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

/**************************************************************************************************************/
/**
<summary>
Configure_DSW_MinLoThreshold calls the Configure_DSW_Threshold() routine for Min Low Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DSW_MinLoThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   return Configure_DSW_Threshold(cardIndex, module, chan, NAI_DSW_THRESH_MIN_LO, (int8_t *)"Min Low");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DSW_LowThreshold calls the Configure_DSW_Threshold() routine for Lower Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DSW_LowThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   return Configure_DSW_Threshold(cardIndex, module, chan, NAI_DSW_THRESH_LOWER, (int8_t *)"Lower");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DSW_UpperThreshold calls the Configure_DSW_Threshold() routine for Upper Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DSW_UpperThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   return Configure_DSW_Threshold(cardIndex, module, chan, NAI_DSW_THRESH_UPPER, (int8_t *)"Upper");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DSW_MaxHiThreshold calls the Configure_DSW_Threshold() routine for Max High Threshold configuration.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DSW_MaxHiThreshold(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_dsw_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_dsw_params->cardIndex;
   int32_t module = p_dsw_params->module;
   int32_t chan = p_dsw_params->channel;
#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif
   return Configure_DSW_Threshold(cardIndex, module, chan, NAI_DSW_THRESH_MAX_HI, (int8_t *)"Max High");
}

/**************************************************************************************************************/
/**
<summary>
Configure_DSW_Threshold handles the user request to configure the selected threshold configuration and
channel and calls the method in the naibrd library to set the threshold voltage.
</summary>
*/
/**************************************************************************************************************/
nai_status_t Configure_DSW_Threshold(int32_t cardIndex, int32_t module, int32_t chan, nai_dsw_thresh_type_t thresholdtype, int8_t* thresholdtext)
{
   bool_t bQuit = FALSE;
   float64_t threshold= 0.0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter the desired %s threshold voltage : ", thresholdtext);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt > 0)
      {
         threshold = atof((const char *)inputBuffer);
         check_status(naibrd_DSW_SetThreshold(cardIndex, module, chan, thresholdtype, threshold));
      }
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

Help Bot

X