Development/ECMD
For general information on ECMD, see ECMD.
The following variables will be used on this page. Replace them for your module.
- COMMAND - how the command will be invoked
- ARGUMENT1...ARGUMENTN - the arguments that will be passed together with COMMAND
- FUNCTIONNAME - the name of the function which will handle the command
- MODULENAME - the name of the module
Contents
Preparations
- Create a new file inside the folder of the module MODULENAME_ecmd.c
- Add this file to the Makefile of the module.
- Open the file and "#include "protocols/ecmd/ecmd-base.h" and other necessary headers.
- Add the header of the module, <string.h> etc.
Create a new command
Start with the following template:
int16_t parse_cmd_FUNCTIONNAME (char *cmd, char *output, uint16_t len)
{
/* Your Code here */
return ECMD_FINAL_OK;
}
Whenever COMMAND is invoked, this function will be called to handle it.
Parameters
- *cmd holds ARGUMENT1...ARGUMENTN which have been passed along with the command. The command text you specified with ecmd_feature macro has already been stripped off, *cmd points to the arguments only. The length of the commandbuffer varies, and may not be zero-terminated properly.
-
len is the length of the command (*cmd). Use this for securely parsing *cmd.len is the length of the output buffer. Do NOT write beyond this limit. Always check the remaining buffersize, or use snprintf_P with proper len param2. The output buffersize depends on the module that called the parser routine: UDP uses the remainder of the UIP buffer (first part of uip_buf holds the command), which is quite large. I2C uses ECMD_I2C_BUFFER_LEN, U(S)ART uses ECMD_SERIAL_USART_BUFFER_LEN and TCP uses ECMD_INPUTBUF_LENGTH (which is wrong, should be ECMD_OUTPUTBUF_LENGTH but both are equal and only 50 chars by default). If you have more text, use the ECMD_AGAIN return value: your routine will get called again in the next cycle. If your text should be continued on the same line, TCP has an ECMD_NO_NEWLINE mechanism at least for the first call, but other channels have not. - *output is the output buffer
which can hold 50 bytes/characters
Return values
ECMD_FINAL_OK | the command has been executed without any errors. "OK" will be written to the caller's output. |
ECMD_FINAL(len) | the command has been executed. len bytes of *output will be written to the caller's output |
ECMD_AGAIN(len) | the command has been executed but needs to be called again. len bytes of *output will be written to the caller's output |
ECMD_ERR_PARSE_ERROR | the command couldn't be executed (missing/wrong arguments etc.) |
ECMD_ERR_READ_ERROR | the command couldn't be executed (not able to read from device/hardware) |
ECMD_ERR_WRITE_ERROR | the command couldn't be executed (not able to write to device/hardware) |
Announce the command
Append this to the bottom of MODULENAME_ecmd.c to let the ECMD parser know about the new command.
/*
-- Ethersex META --
block(MODULENAME)
ecmd_feature(FUNCTIONNAME, "COMMAND", ARGUMENT1...ARGUMENTN , DESCRIPTION)
*/
The COMMAND along with the arguments and the description will show up here
Tips and best practice
Recursive calling a command handler function
If you need to output a lot of data (>50 bytes) , you need to recursivly call the command handler function using ECMD_AGAIN().
Instead of using unsafe static variables to keep track of the current progress you can use the following code:
/* trick: use bytes on cmd as "connection specific static variables" */
if (cmd[0] != 23) { /* indicator flag: real invocation: 0 */
cmd[0] = 23; /* continuing call: 23 */
cmd[1] = 0; /* local variable 1 */
}