Commit d3c7ddf4 authored by Karel Hanák's avatar Karel Hanák
Browse files

added C examples


Signed-off-by: Karel Hanák's avatarKarel Hanák <karel.hanak@iqrf.org>
parent 519e293a
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project("IQRF console")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(cpp)
add_subdirectory(utility)
add_executable(console console.c)
target_link_libraries(console cpp utility)
# JSON-C_FOUND - true if library and headers were found
# JSON-C_INCLUDE_DIRS - include directories
# JSON-C_LIBRARIES - library directories
find_package(PkgConfig)
pkg_check_modules(PC_JSON-C QUIET json-c)
find_path(JSON-C_INCLUDE_DIR json.h
HINTS ${PC_JSON-C_INCLUDEDIR} ${PC_JSON-C_INCLUDE_DIRS} PATH_SUFFIXES json-c json)
find_library(JSON-C_LIBRARY NAMES json-c libjson-c
HINTS ${PC_JSON-C_LIBDIR} ${PC_JSON-C_LIBRARY_DIRS})
set(JSON-C_LIBRARIES ${JSON-C_LIBRARY})
set(JSON-C_INCLUDE_DIRS ${JSON-C_INCLUDE_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(JSON-C DEFAULT_MSG JSON-C_LIBRARY JSON-C_INCLUDE_DIR)
mark_as_advanced(JSON-C_INCLUDE_DIR JSON-C_LIBRARY)
/*
* Console.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include "ccp_commands.h"
#include "utility.h"
#include "Console.h"
#include "DPA.h"
/* data types */
typedef struct { // command decode table item structure
char Com[16];
void (*Func)(__uint16_t);
__uint16_t Param;
} COM;
/* function prototypes */
void ccp_find_command(char *CommandString);
int ccp_read_substring(int *StartPos, char *DestinationString, char *SourceString);
void ccp_exit_cmd(__uint16_t CommandParameter);
void sys_msg_printer(__uint16_t CommandParameter);
int chkin_select(void);
/* global variables */
const COM Commands[] = { // command decode table
{"bond", ccp_coordinator_cmd, 0},
{"unbondc", ccp_coordinator_cmd, CMD_COORDINATOR_REMOVE_BOND},
{"discovery", ccp_coordinator_cmd, CMD_COORDINATOR_DISCOVERY},
{"ledr", ccp_leds_cmd, PNUM_LEDR},
{"ledg", ccp_leds_cmd, PNUM_LEDG},
{"unbondn", ccp_node_cmd, 0},
{"osreset", ccp_os_cmd, CMD_OS_RESET},
{"osrestart", ccp_os_cmd, CMD_OS_RESTART},
{"osinfo", ccp_os_cmd, CMD_OS_READ},
{"exit", ccp_exit_cmd, 0},
};
#define NUM_OF_SYSTEM_MSG 17
#define SIZE_OF_SYSTEM_MSG 26
const char SystemMsg[NUM_OF_SYSTEM_MSG][SIZE_OF_SYSTEM_MSG] = { // error messages
"Command not found ", /* 0 */
"Done !!! ", /* 1 */
"SD card operation ERROR ", /* 2 */
"Uploading .... ", /* 3 */
"Bad command parameter ", /* 4 */
"File not found ", /* 5 */
"Directory not found ", /* 6 */
"Sending request ", /* 7 */
"Confirmation OK ", /* 8 */
"Confirmation ERROR ", /* 9 */
"Response OK ", /* 10 */
"Response ERROR ", /* 11 */
"Command timeout ", /* 12 */
"Code stored successfully ", /* 13 */
"Code store ERROR ", /* 14 */
"TR module not ready ", /* 15 */
"Configuration file ERROR ", /* 16 */
};
char InLine[BUFF];
int InLinePosition;
void (*run_func)(__uint16_t); // pointer to command service function
__uint16_t Parameter; // command service function parameter
int ExitCmd;
int main(int argc, char *argv[])
{
char MyString[BUFF];
int SubstringSize;
int ErrFlag = 0;
if ( argc != 7 ) {/* argc should be 7 for correct execution */
printf( "\nWrong parameters\n");
printf( "Use: ./Console -h MqttHostIp:port -pt MqttPublishTopic -st MqttSubscribeTopic\n\n");
return(-1);
}
if (strcmp(argv[1], "-h") == 0 && strlen(argv[2]) < sizeof(HostIp)) {
strcpy(HostIp, argv[2]);
} else {
ErrFlag = 1;
}
if (strcmp(argv[3], "-pt") == 0 && strlen(argv[4]) < sizeof(PTopic)) {
strcpy(PTopic, argv[4]);
} else {
ErrFlag = 1;
}
if (strcmp(argv[5], "-st") == 0 && strlen(argv[6]) < sizeof(STopic)) {
strcpy(STopic, argv[6]);
} else {
ErrFlag = 1;
}
if (ErrFlag == 1) {
printf( "Wrong parameter.\n\r");
return(-2);
}
ExitCmd = 0;
while(1)
{
printf("cmd> ");
fflush(stdout);
while(!chkin_select()) {
usleep(100000);
}
fgets(InLine, BUFF, stdin);
InLinePosition = 0;
SubstringSize = ccp_read_substring(&InLinePosition, MyString, InLine);
if (SubstringSize != 0) {
ccp_find_command(MyString);
run_func(Parameter);
if (ExitCmd)
break;
} else {
continue;
}
}
return EXIT_SUCCESS;
}
/**
* find command in command table
* - set pointer to command service function
* - initialize parameter of command service function
*/
void ccp_find_command(char *CommandString)
{
__uint8_t CSel;
for (CSel=0; CSel<(sizeof(Commands)/sizeof(COM)); CSel++) { // compare input buffer with existing command patterns
if (strcmp(Commands[CSel].Com, CommandString) == 0) {
run_func = Commands[CSel].Func; // initialize pointer to function to run
Parameter = Commands[CSel].Param; // initialize function parameter
return;
}
}
run_func = sys_msg_printer; // in case of error, run error service function
Parameter = CCP_COMMAND_NOT_FOUND;
}
/**
* find string in SourceSting buffer from StartPos position
* @param StartPos pointer to variable defining starting position to search substring in SourceString buffer
* @param DestinationString pointer to string where substring going to be placed
* @param SourceString pointer to string where substring is looking for
* @return size of DestinationString string / 0 = no substring found
*/
int ccp_read_substring(int *StartPos, char *DestinationString, char *SourceString)
{
int TempCnt = 0;
char TempChar;
InLine[BUFF-1] = 0;
do {
TempChar = SourceString[*StartPos];
if (TempChar == ' ') (*StartPos)++;
} while (TempChar == ' ');
if (TempChar == 0) {
DestinationString[0] = 0;
return(0);
}
do {
TempChar = SourceString[(*StartPos)++];
DestinationString[TempCnt++] = TempChar;
} while(TempChar!=' ' && TempChar!=0x0A && TempChar!=0 && *StartPos<BUFF && TempCnt<BUFF);
DestinationString[--TempCnt] = 0;
(*StartPos)--;
return(TempCnt);
}
/**
* exit console
* @param CommandParameter
* @return none
*/
void ccp_exit_cmd(__uint16_t CommandParameter)
{
puts("Bye ...");
ExitCmd = 1;
}
/**
* print selected system MSG
* @param CommandParameter - number of system MSG
* @return none
*/
void sys_msg_printer(__uint16_t CommandParameter)
{
if (CommandParameter < NUM_OF_SYSTEM_MSG) {
puts(&SystemMsg[CommandParameter][0]);
}
}
/*
select() and pselect() allow a program to monitor multiple file
descriptors, waiting until one or more of the file descriptors become
"ready" for some class of I/O operation (e.g., input possible). A
file descriptor is considered ready if it is possible to perform a
corresponding I/O operation (e.g., read(2) without blocking, or a
sufficiently small write(2)).
*/
int chkin_select(void)
{
fd_set rd;
struct timeval tv={0};
int ret;
FD_ZERO(&rd);
FD_SET(STDIN_FILENO, &rd);
ret=select(1, &rd, NULL, NULL, &tv);
return (ret>0);
}
/*
* Console.h
*
* Created on: Jul 21, 2019
* Author: dudo
*/
#ifndef CONSOLE_H_
#define CONSOLE_H_
#define CCP_COMMAND_NOT_FOUND 0
#define CCP_DONE 1
#define CCP_SD_CARD_ERR 2
#define CCP_UPLOADING 3
#define CCP_BAD_PARAMETER 4
#define CCP_FILE_NOT_FOUND 5
#define CCP_DIR_NOT_FOUND 6
#define CCP_SENDING_REQUEST 7
#define CCP_CONFIRMATION_OK 8
#define CCP_CONFIRMATION_ERR 9
#define CCP_RESPONSE_OK 10
#define CCP_RESPONSE_ERR 11
#define CCP_COMMAND_TIMEOUT 12
#define CCP_CODE_STORED 13
#define CCP_CODE_STORE_ERR 14
#define CCP_TR_NOT_READY 15
#define CCP_CONFIG_FILE_ERR 16
#define BUFF 256
extern char InLine[BUFF];
extern int InLinePosition;
int ccp_read_substring(int *StartPos, char *DestinationString, char *SourceString);
void sys_msg_printer(__uint16_t CommandParameter);
#endif /* CONSOLE_H_ */
add_library(cpp ccp_coordinator_cmd.c
ccp_leds_cmd.c
ccp_node_cmd.c
ccp_os_cmd.c
)
/*
* ccp_commands.h
*/
#ifndef CCP_COMMANDS_H_
#define CCP_COMMANDS_H_
void ccp_leds_cmd (__uint16_t CommandParameter);
void ccp_coordinator_cmd (__uint16_t CommandParameter);
void ccp_node_cmd (__uint16_t CommandParameter);
void ccp_os_cmd (__uint16_t CommandParameter);
#endif /* CCP_COMMANDS_H_ */
/*
* ccp_coordinator_cmd.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "json.h"
#include "utility.h"
#include "Console.h"
void print_disc_bond_info(T_DPA_PACKET *DpaPacket);
/**
* print result of discovery get or bond get commands
*/
void print_disc_bond_info(T_DPA_PACKET *DpaPacket)
{
__uint16_t Mask;
__uint16_t Data;
int X, Y;
printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
for (X=0; X<16; X++) {
Mask = 0x0001;
Data = ((uint16_t)DpaPacket->DpaMessage.Response.PData[2*X+1]<<8) | DpaPacket->DpaMessage.Response.PData[2*X];
printf("%X - ", X);
for (Y=0; Y<16; Y++) {
if (Data & Mask)
printf("x ");
else
printf(". ");
Mask <<= 1;
}
printf("\n");
}
printf("\n");
}
void ccp_coordinator_cmd (__uint16_t CommandParameter)
{
T_DPA_PACKET MyDpaPacket;
int ParameterSize;
char ParameterString[64];
json_object *IqrfRqMsg = NULL;
json_object *IqrfRsMsg = NULL;
int ReqAddr = 0;
int TxPower = 7;
int MaxAddr = 32;
int BondingMask = 0xFF;
int ErrFlag = 0;
// DPA header
MyDpaPacket.NADR = COORDINATOR_ADDRESS;
MyDpaPacket.PNUM = PNUM_COORDINATOR;
MyDpaPacket.HWPID = HWPID_DoNotCheck;
MyDpaPacket.PCMD = 0xFF; // dummy command
switch(CommandParameter) {
case CMD_COORDINATOR_REMOVE_BOND:
MyDpaPacket.PCMD = CommandParameter; // set peripheral cmd
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize) // is any command parameter ?
ReqAddr = atoi(ParameterString); // read command parameter
if (ReqAddr == 0 || ReqAddr > MAX_ADDRESS) { // bad parameter
sys_msg_printer(CCP_BAD_PARAMETER); // if bad parameter, print error message
} else {
MyDpaPacket.DpaMessage.PerCoordinatorRemoveRebondBond_Request.BondAddr = ReqAddr;
IqrfRqMsg = create_json_msg(&MyDpaPacket, sizeof(TPerCoordinatorRemoveRebondBond_Request), 2000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRsMsg != NULL) {
decode_json_msg(&MyDpaPacket, IqrfRsMsg);
printf("Number of bonded nodes = %d\n", MyDpaPacket.DpaMessage.PerCoordinatorRemoveRebondBond_Response.DevNr);
}
}
break;
case CMD_COORDINATOR_DISCOVERY:
// read first command parameter
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize) { // if exist
if (strcmp("get", ParameterString) == 0) { // GET subcommand ?
MyDpaPacket.PCMD = CMD_COORDINATOR_DISCOVERED_DEVICES;
IqrfRqMsg = create_json_msg(&MyDpaPacket, 0, 5000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRsMsg != NULL) {
decode_json_msg(&MyDpaPacket, IqrfRsMsg);
print_disc_bond_info(&MyDpaPacket);
}
} else { // TxPower & MaxAddr parameters
TxPower = atoi(ParameterString); // set TxPower
if (TxPower > 7)
ErrFlag = 1; // check max TxPower
// read MaxAddr
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize) { // if exist
MaxAddr = atoi(ParameterString); // set MaxAddr
if (MaxAddr > 239)
ErrFlag = 1; // check MaxAddr
}
}
}
if (ErrFlag == 1) {
sys_msg_printer(CCP_BAD_PARAMETER); // if bad parameter, print error message
} else {
if (MyDpaPacket.PCMD == 0xFF) { // if command not defined
MyDpaPacket.PCMD = CMD_COORDINATOR_DISCOVERY; // discovery command
MyDpaPacket.DpaMessage.PerCoordinatorDiscovery_Request.TxPower = TxPower; // Command parameters
MyDpaPacket.DpaMessage.PerCoordinatorDiscovery_Request.MaxAddr = MaxAddr;
IqrfRqMsg = create_json_msg(&MyDpaPacket, sizeof(TPerCoordinatorDiscovery_Request), 30000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRsMsg != NULL) {
decode_json_msg(&MyDpaPacket, IqrfRsMsg);
printf("Number of discovered nodes = %d\n", MyDpaPacket.DpaMessage.PerCoordinatorDiscovery_Response.DiscNr);
}
}
}
break;
default:
// read first command parameter
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize) { // if exist
if (strcmp("clear", ParameterString) == 0) {
MyDpaPacket.PCMD = CMD_COORDINATOR_CLEAR_ALL_BONDS;
IqrfRqMsg = create_json_msg(&MyDpaPacket, 0, 2000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRsMsg != NULL) {
printf("All nodes cleared successfully\n");
}
} else {
if (strcmp("get", ParameterString) == 0) {
MyDpaPacket.PCMD = CMD_COORDINATOR_BONDED_DEVICES;
IqrfRqMsg = create_json_msg(&MyDpaPacket, 0, 5000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRsMsg != NULL) {
decode_json_msg(&MyDpaPacket, IqrfRsMsg);
print_disc_bond_info(&MyDpaPacket);
}
} else {
ReqAddr = atoi(ParameterString);
// read bonding mask
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize) // if exist
BondingMask = atoi(ParameterString);
}
}
}
if (MyDpaPacket.PCMD == 0xFF) { // if command not defined
MyDpaPacket.PCMD = CMD_COORDINATOR_BOND_NODE;
MyDpaPacket.DpaMessage.PerCoordinatorBondNode_Request.ReqAddr = ReqAddr; // Command parameters
MyDpaPacket.DpaMessage.PerCoordinatorBondNode_Request.BondingMask = BondingMask;
IqrfRqMsg = create_json_msg(&MyDpaPacket, sizeof(TPerCoordinatorBondNode_Request), 5000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRsMsg != NULL) {
decode_json_msg(&MyDpaPacket, IqrfRsMsg);
printf("Bonded node address = %d\n", MyDpaPacket.DpaMessage.PerCoordinatorBondNode_Response.BondAddr);
printf("Number of bonded nodes = %d\n", MyDpaPacket.DpaMessage.PerCoordinatorBondNode_Response.DevNr);
}
}
}
if (IqrfRqMsg != NULL) // destroy request JSON object, if exist
json_object_put(IqrfRqMsg);
if (IqrfRsMsg != NULL) // destroy response JSON object, if exist
json_object_put(IqrfRsMsg);
}
/*
* ccp_leds_cmd.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "json.h"
#include "utility.h"
#include "Console.h"
#include "DPA.h"
void ccp_leds_cmd (__uint16_t CommandParameter)
{
T_DPA_PACKET MyDpaPacket;
int Message = 0;
int ParameterSize;
char ParameterString[64];
json_object *IqrfRqMsg = NULL;
json_object *IqrfRsMsg = NULL;
// processing of command input parameters
// read required operation
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize) {
if (strcmp("on", ParameterString) == 0)
MyDpaPacket.PCMD = CMD_LED_SET_ON;
else if (strcmp("off", ParameterString) == 0)
MyDpaPacket.PCMD = CMD_LED_SET_OFF;
else if (strcmp("flash", ParameterString) == 0)
MyDpaPacket.PCMD = CMD_LED_PULSE; // PCMD = CMD_LED_FLASHING;
else if (strcmp("pulse", ParameterString) == 0)
MyDpaPacket.PCMD = CMD_LED_PULSE;
else Message = CCP_BAD_PARAMETER;
} else {
Message = CCP_BAD_PARAMETER;
}
// read destination address
ParameterSize = ccp_read_substring(&InLinePosition, ParameterString, InLine);
if (ParameterSize)
MyDpaPacket.NADR = atoi(ParameterString); // set destination address
else
Message = CCP_BAD_PARAMETER; // if address not exist, print error MSG
// sending DPA request and processing response
if (Message) {
sys_msg_printer(Message); // command parameters ERROR
} else {
MyDpaPacket.PNUM = CommandParameter; // select RED or GREEN led
MyDpaPacket.HWPID = HWPID_DoNotCheck; // do not check HWPID
IqrfRqMsg = create_json_msg(&MyDpaPacket, 0, 2000);
IqrfRsMsg = send_json_msg(IqrfRqMsg);
if (IqrfRqMsg != NULL) // destroy request JSON object, if exist
json_object_put(IqrfRqMsg);
if (IqrfRsMsg != NULL) // destroy response JSON object, if exist
json_object_put(IqrfRsMsg);
}
}
/*
* ccp_node_cmd.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include "json.h"
#include "utility.h"
#include "Console.h"
void ccp_node_cmd (__uint16_t CommandParameter)
{
T_DPA_PACKET MyDpaPacket;
int ParameterSize;
char ParameterString[64];
json_object *IqrfRqMsg = NULL;
json_object *IqrfRsMsg = NULL;
// Send Batch command
MyDpaPacket.NADR = 0;
MyDpaPacket.PNUM = PNUM_OS;
MyDpaPacket.PCMD = CMD_OS_BATCH;
MyDpaPacket.HWPID = HWPID_DoNotCheck;
// Remove bond
MyDpaPacket.DpaMessage.Request.PData[0] = 5;
MyDpaPacket.DpaMessage.Request.PData[1] = PNUM_NODE;
MyDpaPacket.DpaMessage.Request.PData[2] = CMD_NODE_REMOVE_BOND;