From 056b387a1732db3aacec7762a1a67e3b2ee60bb7 Mon Sep 17 00:00:00 2001 From: Jason Reiss Date: Wed, 24 Feb 2016 13:58:31 -0600 Subject: Add commands: node-config, node-add, node-update, node-delete --- main.cpp | 296 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 230 insertions(+), 66 deletions(-) diff --git a/main.cpp b/main.cpp index 33705bb..0e88644 100644 --- a/main.cpp +++ b/main.cpp @@ -40,22 +40,49 @@ #define MAX_RECEIVED_BYTES 2000 #define TIMEOUT 100 /* By default 100 msec */ -int opt_get_stats = 0; +int opt_get_stats = 0; int opt_get_nodelist = 0; int opt_get_json = 0; int opt_stats_reset = 0; -int timeout = TIMEOUT; -const char* cmd_stats = "stats"; +int opt_get_nodeconfig = 0; +int opt_add_node = 0; +int opt_delete_node = 0; +int opt_update_node = 0; + +char* node_get_addr; +char* node_delete_addr; +char* node_config_addr; +char* node_update_addr; +char* node_update_field; +char* node_update_value; +int node_add_count = 0; +char* node_add_args[6]; + +int timeout = TIMEOUT; + +const char* cmd_stats = "stats"; const char* cmd_stats_reset = "stats reset"; -const char* cmd_nodelist = "node list"; +const char* cmd_node_list = "node list"; +const char* cmd_node_config = "node config"; +const char* cmd_node_update = "node update"; +const char* cmd_node_delete = "node delete"; +const char* cmd_nodeadd = "node add"; const std::string lora_network_stats_json("/var/tmp/lora_network_stats.json"); const std::string lora_network_nodelist("/var/tmp/lora_network_nodelist"); const std::string lora_network_nodelist_json("/var/tmp/lora_network_nodelist.json"); +const std::string lora_network_nodeconfig("/var/tmp/lora_network_nodeconfig"); +const std::string lora_network_nodeconfig_json("/var/tmp/lora_network_nodeconfig.json"); std::stringstream receiveStream; -const int nodeSize = 15; +const int nodeSize = 16; +const int configSize = 7; const std::string NODE_ADDR("nodeAddr"); const std::string NODE_DEV_EUI("devEui"); +const std::string NODE_APP_EUI("appEui"); +const std::string NODE_APP_KEY("appKey"); +const std::string NODE_NS_KEY("nsKey"); +const std::string NODE_DS_KEY("dsKey"); +const std::string NODE_CLASS("class"); const std::string NODE_JOINED("joined"); const std::string NODE_SEQ_NUM("seqNum"); const std::string NODE_PKTS_UP("pktsUp"); @@ -70,42 +97,99 @@ const std::string NODE_SNR_MIX("snrMin"); const std::string NODE_SNR_MAX("snrMax"); const std::string NODE_SNR_AVR("snrAvg"); -void getloraData(const char *command); +void runCmd(const char *command); void printStats(void); void printNodeList(void); +void printNodeConfig(void); void saveToFile(const std::string& fileName, const std::string& buffer); void parseOptions(int argc, char** argv); void printHelp(const std::string& sApp); std::string trim(std::string& str); int main(int argc, char**argv) -{ + { parseOptions(argc, argv); if (opt_stats_reset) { - getloraData(cmd_stats_reset); + runCmd(cmd_stats_reset); } if (opt_get_stats) { - getloraData(cmd_stats); + runCmd(cmd_stats); printStats(); } if (opt_get_nodelist) { - getloraData(cmd_nodelist); + runCmd(cmd_node_list); if (opt_get_json) { printNodeList(); } else { - if (receiveStream.str().empty() ) { + if (receiveStream.str().empty()) { return 0; } saveToFile(lora_network_nodelist, receiveStream.str()); std::cout << receiveStream.str(); } } + if (opt_get_nodeconfig) { + char buff[256]; + snprintf(buff, 256, "%s %s", cmd_node_config, node_config_addr); + runCmd(buff); + if (opt_get_json) { + printNodeConfig(); + } else { + if (!receiveStream.str().empty()) { + saveToFile(lora_network_nodelist, receiveStream.str()); + std::cout << receiveStream.str(); + } + } + } + if (opt_add_node) { + if (node_add_count < 4) { + std::cout << "usage: --node-add [CLASS] ([APP-KEY] | [NET-SKEY] [APP-SKEY])\n"; + return 0; + } + + std::stringstream cmd; + cmd << cmd_nodeadd; + + for (int i = 0; i < node_add_count; i++) { + cmd << " " << node_add_args[i]; + } + + runCmd(cmd.str().c_str()); + + if (!receiveStream.str().empty()) { + std::cout << receiveStream.str(); + } + } + if (opt_delete_node) { + char buff[256]; + snprintf(buff, 256, "%s %s", cmd_node_delete, node_delete_addr); + runCmd(buff); + if (!receiveStream.str().empty()) { + std::cout << receiveStream.str(); + } + } + if (opt_update_node) { + + std::stringstream cmd; + cmd << cmd_node_update; + + cmd << " " << node_update_addr; + cmd << " " << node_update_field; + cmd << " " << node_update_value; + + runCmd(cmd.str().c_str()); + + if (!receiveStream.str().empty()) { + std::cout << receiveStream.str(); + } + } + return 0; } -void getloraData(const char *command) { +void runCmd(const char *command) { int sockfd; struct sockaddr_in servaddr; int receiveBytes = 0; @@ -119,15 +203,15 @@ void getloraData(const char *command) { receiveStream.clear(); if (NULL == command) { - printError("Command is null\n"); - return; + printError("Command is null\n"); + return; } - sockfd=socket(AF_INET,SOCK_DGRAM,0); - bzero(&servaddr,sizeof(servaddr)); + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr=inet_addr(INET_ADDR); - servaddr.sin_port=htons(INET_PORT); + servaddr.sin_addr.s_addr = inet_addr(INET_ADDR); + servaddr.sin_port = htons(INET_PORT); memset(receiveMessage, 0, MAX_RECEIVED_BYTES); if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { @@ -135,13 +219,13 @@ void getloraData(const char *command) { return; } - sendto(sockfd, command, strlen(command), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); + sendto(sockfd, command, strlen(command), 0, (struct sockaddr *) &servaddr, sizeof(servaddr)); - while(1) { + while (1) { receiveBytes = recvfrom(sockfd, receiveMessage, MAX_RECEIVED_BYTES, 0, NULL, NULL); - if(receiveBytes < 0) { - /*printf("timeout\n");*/ - break; + if (receiveBytes < 0) { + /*printf("timeout\n");*/ + break; } receiveStream << std::string(receiveMessage, receiveBytes); } @@ -151,7 +235,7 @@ void printStats() { Json::Reader reader; Json::Value stats; - if (receiveStream.str().empty() ) { + if (receiveStream.str().empty()) { return; } @@ -166,7 +250,7 @@ void printStats() { for (Json::Value::Members::iterator it = keys.begin(); it != keys.end(); ++it) { const std::string& key = *it; newKey.clear(); - for (size_t i = 0; i < key.length() ; ++i) { + for (size_t i = 0; i < key.length(); ++i) { if (('_' == key[i]) || ('-' == key[i])) { if ((i + 1) < key.length()) { newKey.push_back(std::toupper(key[++i])); @@ -183,12 +267,50 @@ void printStats() { std::cout << stats.toStyledString(); } +void printNodeConfig() { + std::string line; + std::vector < std::string > parts; + Json::Value nodeList = Json::ValueType::arrayValue; + + if (receiveStream.str().empty()) { + return; + } + + getline(receiveStream, line); + while (1) { + getline(receiveStream, line); + if (line.size() == 0) + break; + + line = trim(line); + parts = MTS::Text::split(line, " "); + + if (configSize == parts.size()) { + Json::Value jNode(Json::objectValue); + int index = 0; + jNode[NODE_ADDR] = parts[index++]; + jNode[NODE_DEV_EUI] = parts[index++]; + jNode[NODE_CLASS] = parts[index++]; + jNode[NODE_APP_EUI] = parts[index++]; + jNode[NODE_APP_KEY] = parts[index++]; + jNode[NODE_NS_KEY] = parts[index++]; + jNode[NODE_DS_KEY] = parts[index++]; + nodeList.append(jNode); + } + else { + printError("Incorrect Node Data! parts.size() = [%d]\n", parts.size()); + } + } + saveToFile(lora_network_nodelist_json, nodeList.toStyledString()); + std::cout << nodeList.toStyledString(); +} + void printNodeList() { std::string line; - std::vector parts; + std::vector < std::string > parts; Json::Value nodeList = Json::ValueType::arrayValue; - if (receiveStream.str().empty() ) { + if (receiveStream.str().empty()) { return; } @@ -203,26 +325,28 @@ void printNodeList() { if (nodeSize == parts.size()) { Json::Value jNode(Json::objectValue); - jNode[NODE_ADDR] = parts[0]; - jNode[NODE_DEV_EUI] = parts[1]; - jNode[NODE_JOINED] = parts[2]; - jNode[NODE_SEQ_NUM] = atoi(parts[3].c_str()); - jNode[NODE_PKTS_UP] = atoi(parts[4].c_str()); - jNode[NODE_PKTS_DOWN] = atoi(parts[5].c_str()); - jNode[NODE_PKTS_1ST] = atoi(parts[6].c_str()); - jNode[NODE_PKTS_2ND] = atoi(parts[7].c_str()); - jNode[NODE_DROPPED] = atoi(parts[8].c_str()); - jNode[NODE_RSSI_MIN] = atoi(parts[9].c_str()); - jNode[NODE_RSSI_MAX] = atoi(parts[10].c_str()); - jNode[NODE_RSSI_AVR] = atoi(parts[11].c_str()); - jNode[NODE_SNR_MIX] = atoi(parts[12].c_str()); - jNode[NODE_SNR_MAX] = atoi(parts[13].c_str()); - jNode[NODE_SNR_AVR] = atoi(parts[14].c_str()); + int index = 0; + jNode[NODE_ADDR] = parts[index++]; + jNode[NODE_DEV_EUI] = parts[index++]; + jNode[NODE_CLASS] = parts[index++]; + jNode[NODE_JOINED] = parts[index++]; + jNode[NODE_SEQ_NUM] = atoi(parts[index++].c_str()); + jNode[NODE_PKTS_UP] = atoi(parts[index++].c_str()); + jNode[NODE_PKTS_DOWN] = atoi(parts[index++].c_str()); + jNode[NODE_PKTS_1ST] = atoi(parts[index++].c_str()); + jNode[NODE_PKTS_2ND] = atoi(parts[index++].c_str()); + jNode[NODE_DROPPED] = atoi(parts[index++].c_str()); + jNode[NODE_RSSI_MIN] = atoi(parts[index++].c_str()); + jNode[NODE_RSSI_MAX] = atoi(parts[index++].c_str()); + jNode[NODE_RSSI_AVR] = atoi(parts[index++].c_str()); + jNode[NODE_SNR_MIX] = atoi(parts[index++].c_str()); + jNode[NODE_SNR_MAX] = atoi(parts[index++].c_str()); + jNode[NODE_SNR_AVR] = atoi(parts[index++].c_str()); nodeList.append(jNode); } else { - printError("Incorrect Node Data! parts.size() = [%d]\n", parts.size()); + printError("Incorrect Node Data! parts.size() = [%d]\n", parts.size()); } } saveToFile(lora_network_nodelist_json, nodeList.toStyledString()); @@ -238,45 +362,74 @@ void saveToFile(const std::string& fileName, const std::string& buffer) { void parseOptions(int argc, char** argv) { - if(argc == 1) { + if (argc == 1) { printHelp(argv[0]); exit(0); } - const char* short_options = "hvsirnjt:"; + const char* short_options = "hvsrnc:a:u:d:jt:"; const struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'v'}, - {"stats", no_argument, 0, 's'}, - {"stats-reset", no_argument, 0, 'r'}, - {"node-list", no_argument, 0, 'n'}, - {"json", no_argument, 0, 'j'}, - {"timeout", required_argument, 0, 't'}, - {0, 0, 0, 0} + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "stats", no_argument, 0, 's' }, + { "stats-reset", no_argument, 0, 'r' }, + { "node-list", no_argument, 0, 'n' }, + { "node-config", required_argument, 0, 'c' }, + { "node-add", required_argument, 0, 'a' }, + { "node-update", required_argument, 0, 'u' }, + { "node-delete", required_argument, 0, 'd' }, + { "json", no_argument, 0, 'j' }, + { "timeout", required_argument, 0, 't' }, + { 0, 0, 0, 0 } }; int rez; int option_index; - while ((rez=getopt_long(argc, argv, short_options, long_options, &option_index))!=-1) { - switch(rez){ + while ((rez = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) { + switch (rez) { case 's': { ++opt_get_stats; break; - }; + } case 'r': { - ++opt_stats_reset; - break; - }; + ++opt_stats_reset; + break; + } case 'n': { ++opt_get_nodelist; break; - }; + } + case 'c': { + ++opt_get_nodeconfig; + node_config_addr = optarg; + break; + } + case 'a': { + ++opt_add_node; + node_add_args[node_add_count++] = optarg; + for (int i = optind; i < argc; i++) { + node_add_args[node_add_count++] = argv[i]; + } + break; + } + case 'u': { + ++opt_update_node; + node_update_addr = optarg; + node_update_field = argv[optind]; + node_update_value = argv[optind + 1]; + break; + } + case 'd': { + ++opt_delete_node; + node_delete_addr = optarg; + break; + } case 'j': { ++opt_get_json; break; - }; + } case 't': { timeout = atoi(optarg); break; @@ -285,13 +438,13 @@ void parseOptions(int argc, char** argv) { printf("Version: %s\n", Version::version.c_str()); exit(0); break; - case 'h': - case '?': - default: { + case 'h': + case '?': + default: { printHelp(argv[0]); exit(0); break; - }; + } }; }; } @@ -303,13 +456,24 @@ void printHelp(const std::string& sApp) { printf("\t--stats (s) : get LoRa Network server statistics\n"); printf("\t--stats-reset (r) : reset LoRa Network server statistics\n"); printf("\t--node-list (n) : get Node List\n"); + printf("\t--node-config (c) : get Node config\n"); + printf("\t\tex: --node-config \n"); + printf("\t--node-add (a) : add node\n"); + printf("\t\tusage: --node-add [CLASS] ([APP-KEY] | [NET-SKEY] [APP-SKEY])\n"); + printf("\t\tex: --node-add 00000001 A 16ea76f6ab663d80 4c194e20d396b5f7d3e1551e4cd320de"); + printf("\t--node-update (u) : update node info\n"); + printf("\t\tusage: --node-update \n"); + printf("\t\tex: --node-update 00000001 class C"); + printf("\t\tex: --node-update 00000001 app-key 4c194e20d396b5f7d3e1551e4cd320de"); + printf("\t--node-delete (d) : delete a Node\n"); + printf("\t\tex: --node-delete \n"); printf("\t--json (j) : data in json format\n"); printf("\t--help (?) : returns this message\n"); printf("\t--version (v) : print version\n"); } std::string trim(std::string& str) { - str.erase(std::unique(str.begin(), str.end(), [](char a, char b) { return a == ' ' && b == ' '; } ), str.end() ); + str.erase(std::unique(str.begin(), str.end(), [](char a, char b) {return a == ' ' && b == ' ';}), str.end()); return str; } -- cgit v1.2.3