This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

cli

Hi,

I am using cli and made my own command like bellow, as you see i have a command with 3 sub commands. But i think my idea is primitive because if i have 1000 sub command so i have to write many functions!!!!

Another problem of using this method is that in putty first i have to write N1 as a sub command and in the next line SEND as a command and then i can see my results. For example :

uart_cli:~$   Do A

uart_cli:~$   DO

But i want  to type like  "SEND N1'' which is contain command and sub command and then get my results. Kindly let me how to do that and let me know if it is possible, how many sub command i can type with that? is there any limitation? For example can i have something like bellow?

uart_cli:~$  DO A L g H Z K

which A, L,H,Z,K are sub commands of DO.

//sub commands
static void cmd_DO_A(nrf_cli_t const * p_cli, size_t argc, char **argv)
      { 
           A = 1;    
      }

static void cmd_DO_B(nrf_cli_t const * p_cli, size_t argc, char **argv)
      { 
          A = 2;
      }

static void cmd_DO_C(nrf_cli_t const * p_cli, size_t argc, char **argv)
      { 
            A = 3;
      }
// Command
static void cmd_DO(nrf_cli_t const * p_cli, size_t argc, char **argv)
{ 
      ASSERT(p_cli);
      //
      //
      //
      //

      switch(A)
      {
        case 1:
                
                break;
         case 2:
             
                break;
         case 3:
                
                break;

Parents
  • What you can do is to implement handler for DO command only which will be checking what subcommands were passed to it using argc and argv.

    To achieve that you need to use dynamic commands concept. It can look more less like that:

    static char m_dynamic_cmd_buffer[10][20] = {"A", "B", "c", "z", "d"};
    
    static void cmd_DO(nrf_cli_t const * p_cli, size_t argc, char **argv)
    {
        for (size_t i = 1; i < argc; i++)
        {
        	if (!strcmp(argv[i], m_dynamic_cmd_buffer[i])
        		{
        		 // do something
        		}
        }
    }
    
    
    static void dynamic_cmd_get(size_t idx, nrf_cli_static_entry_t * p_static)
    {
        ASSERT(p_static);
    
        if (idx < m_dynamic_cmd_cnt)
        {
            /* m_dynamic_cmd_buffer must be sorted alphabetically to ensure correct CLI completion */
            p_static->p_syntax = m_dynamic_cmd_buffer[idx];
            p_static->handler  = NULL;
            p_static->p_subcmd = NULL;
            p_static->p_help = NULl;
        }
        else
        {
            /* if there are no more dynamic commands available p_syntax must be set to NULL */
            p_static->p_syntax = NULL;
        }
    }
    
    NRF_CLI_CREATE_DYNAMIC_CMD(m_sub_dynamic_set, dynamic_cmd_get);
    NRF_CLI_CMD_REGISTER(DO,
                         &m_sub_dynamic_set,
                         "Demonstrate dynamic command usage.",
                         cmd_DO);
    

    I did not compile it, it's only a concept.

    Using this approach you will be able to autocomplete all subcommands.

    CLI is not capable to execute more than 1 handler at a time so you do not have much choice here.

  • Thank you for helpful advises. Could you please let me know about A,B,c,z,d?

    I mean this line:

    static char m_dynamic_cmd_buffer[10][20] = {"A", "B", "c", "z", "d"};

  • This is syntax of your subcommands :). It only means that you can autocomplete commands A, B, c, z, d

    This table could look like that

    static char m_dynamic_cmd_buffer[][20] = {"A_subcommand", "B_subcommand", "c_subcommand"};

    Next you can type in the CLI:

    DO A <TAB> and CLI will autocompleate it to:

    DO A_subcommand

    Next you can tab other (or the same) command.

    DO A_subcommand c <tab> will result in:

    DO A_subcommand c_subcommand

  • Hi

    Thank you for answering and explanation:). But putting char inside of array by this way is impossible and i will face issue with the conflicting types for 'm_dynamic_cmd_buffer'. Any other way?

    Kind regards

  • Hi,

    I do not understand why it is impossible and you will have a conflict types? Please let me know what problems you are facing.

  • Hi,

    Please see the bellow code. this is what i mean. Because i think the problem is in Sub commands definitions.I will appreciate if you give me more guidance.

    Kind regards 

    uint8_t     A= 0;
    
    //sub commands
    static void DO_A (nrf_cli_t const * p_cli, size_t argc, char **argv)
          { 
              A = 1;    
          }
    
    static void DO_B (nrf_cli_t const * p_cli, size_t argc, char **argv)
          { 
              A = 2;
          }
    
    static void DO_C (nrf_cli_t const * p_cli, size_t argc, char **argv)
          { 
              A = 3;
          }
    static char m_dynamic_cmd_buffer[][20] = {"Do_A", "Do_B", "Do_C"};
    
    // Command
    static void cmd_send(nrf_cli_t const * p_cli, size_t argc, char **argv)
    {
        for (size_t i = 1; i < argc; i++)
        {
        	if (!strcmp(argv[i], m_dynamic_cmd_buffer[i]))
        		{
        		//
        		//
        		//
                  switch(A)
                   {
                    case 1:
                        data[0] = 0x19;
                            
                            break;
                     case 2:
                            data[0] = 0x20;
                            
                            break;
                    }
                }    
        }                    
    }
    
    static void dynamic_cmd_get(size_t idx, nrf_cli_static_entry_t * p_static)
    {
        ASSERT(p_static);
    
        if (idx < m_dynamic_cmd_cnt)
        {
            /* m_dynamic_cmd_buffer must be sorted alphabetically to ensure correct CLI completion */
            p_static->p_syntax = m_dynamic_cmd_buffer[idx];
            p_static->handler  = NULL;
            p_static->p_subcmd = NULL;
            p_static->p_help = NULL;
        }
        else
        {
            /* if there are no more dynamic commands available p_syntax must be set to NULL */
            p_static->p_syntax = NULL;
        }
    }
    
    
    NRF_CLI_CREATE_DYNAMIC_CMD(m_sub_dynamic_set, dynamic_cmd_get);
    NRF_CLI_CMD_REGISTER(Do,
                         &m_sub_dynamic_set,
                         "Demonstrate dynamic command usage.",
                         cmd_Do);      

  • This code is not complete. What is data?

    May you please let me know what is exact error message and what compiler you are using? May you share complete project?

    btw.

    Are you aware that functions: DO_A, DO_B, DO_C will not be called so variable A will not be updated?

Reply Children
  • When I think a bit more about your use case I wonder why you need subcommands at all?

    You can have only 1 command and implement it like that:

    static void cmd_Do(nrf_cli_t const * p_cli, size_t argc, char **argv)
    {
        data[0] = atoi(argv[i]);
    }
    

    and you can simply call it like that:

    Do 10

  • Dear Jakub

    Thank you for answering. The code which i sent u to visit was just an example because of my better understanding of using commands and subcommands. in fact in the command i am using pipe (i prefer to use only one pipe not more!) and by the help of the payload data, i am sending data to another two boards. This is the reason that i want to use subcommands because without that i cant choose which board im going to send data. Moreover, i am using SEEGER Embedded Studio. The ''data'' in the code which i sent u is payload.data[0] also. Im eagerly waiting for ur answer. 

    Kind regatds

  • Please share an error message you have. Line no. 18 compiles on my side fine.

  • /**
     * Copyright (c) 2018 - 2018, Nordic Semiconductor ASA
     * 
     * All rights reserved.
     * 
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     * 
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     * 
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     * 
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     * 
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     * 
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     * 
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * 
     */
    #include  "nrf_cli.h"
    #include "nrf_log.h"
    
    #include <ctype.h>
    #include "nrf_delay.h"
    #include "nrf_log.h"
    
    #include "nrf_esb.h"
    
    
    /* commands counter */
    static uint8_t m_dynamic_cmd_cnt;
    
    uint8_t     m_pyload_active = 0;
    
    // INDIVIDUAL ADDRESSES SUBS
    
    //@ Choose Board_1 function
    static void b1(nrf_cli_t const * p_cli, size_t argc, char **argv)
          { 
               m_pyload_active = 1;    
          }
         
    static char m_dynamic_cmd_buffer[][20] = {"b1"};
    static void cmd_send(nrf_cli_t const * p_cli, size_t argc, char **argv)
    {
        for (size_t i = 1; i < argc; i++)
        {
        	if (!strcmp(argv[i], m_dynamic_cmd_buffer[i]))
        		{
        		 
                      // NRF_LOG_DEBUG("Transmitting packet %02x",'payload.data[1]');
                      payload.noack=false;
    
                   if(m_pyload_active == 1){
                               data[0] = 0x19;
                     }           
                 
                      if (nrf_esb_write_payload(&payload) == NRF_SUCCESS){
                        NRF_LOG_DEBUG("Transmiting Successful!");
                       }
                       else {
                        NRF_LOG_WARNING("Sending packet failed");
                       }
    
                        NRF_LOG_FLUSH();
    
        }
    }
    
    
    static void dynamic_cmd_get(size_t idx, nrf_cli_static_entry_t * p_static)
    {
        ASSERT(p_static);
    
        if (idx < m_dynamic_cmd_cnt)
        {
            /* m_dynamic_cmd_buffer must be sorted alphabetically to ensure correct CLI completion */
            p_static->p_syntax = m_dynamic_cmd_buffer[idx];
            p_static->handler  = NULL;
            p_static->p_subcmd = NULL;
            p_static->p_help = NULL;
        }
        else
        {
            /* if there are no more dynamic commands available p_syntax must be set to NULL */
            p_static->p_syntax = NULL;
        }
    }
    NRF_CLI_CREATE_DYNAMIC_CMD(m_sub_dynamic_set, dynamic_cmd_get);
    
    
    
    NRF_CLI_CMD_REGISTER(send,
                         &m_sub_dynamic_set,
                         "Demonstrate dynamic command usage.",
                         cmd_send);
    
    NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_send)
    {
        
        NRF_CLI_CMD(b1, &m_sub_dynamic_set, "Execute a command.", b1),
    };
    
    

Related