Merge pull request #59 from btsimonh/cmnds

Cmnds
This commit is contained in:
openshwprojects
2022-03-06 23:29:40 +01:00
committed by GitHub
11 changed files with 324 additions and 222 deletions

68
src/cmnds/fortest.c Normal file
View File

@@ -0,0 +1,68 @@
#include "../logging/logging.h"
#include "../new_pins.h"
#include "../obk_config.h"
#include <ctype.h>
#include "../new_cmd.h"
#ifdef BK_LITTLEFS
#include "../littlefs/our_lfs.h"
#endif
extern int wal_stricmp(const char *a, const char *b);
extern int wal_strnicmp(const char *a, const char *b, int count);
char *cmds[16] = { NULL };
char *names[16] = { NULL };
// run an aliased command
static int runcmd(const void * context, const char *cmd, const char *args){
char *c = (char *)context;
char *p = c;
while (*p && !isWhiteSpace(*p)) {
p++;
}
if (*p) p++;
return CMD_ExecuteCommand(p);
}
// run an aliased command
static int addcmd(const void * context, const char *cmd, const char *args){
if (!wal_strnicmp(cmd, "addcmd", 6)){
int index = 0;
char cmd[32];
int len;
if (strlen(cmd) > 6) {
index = atoi(cmd+6);
}
if ((index < 0) || (index > 16)){
return 0;
}
if (cmds[index]){
os_free(cmds[index]);
}
if (names[index]){
os_free(names[index]);
}
cmds[index] = os_malloc(strlen(args)+1);
strcpy(cmds[index], args);
len = get_cmd(args, cmd, 32, 1);
names[index] = os_malloc(strlen(cmd)+1);
strcpy(names[index], cmd);
ADDLOG_ERROR(LOG_FEATURE_CMD, "cmd %d set to %s", index, cmd);
CMD_RegisterCommand(names[index], "", runcmd, "custom", cmds[index]);
return 1;
}
return 0;
}
int fortest_commands_init(){
CMD_RegisterCommand("addcmd", "", addcmd, "add a custom command", NULL);
return 0;
}

1
src/cmnds/fortest.h Normal file
View File

@@ -0,0 +1 @@
int fortest_commands_init();

159
src/cmnds/taslike.c Normal file
View File

@@ -0,0 +1,159 @@
#include "../logging/logging.h"
#include "../new_pins.h"
#include "../obk_config.h"
#include <ctype.h>
#include "../new_cmd.h"
#ifdef BK_LITTLEFS
#include "../littlefs/our_lfs.h"
#endif
extern int wal_stricmp(const char *a, const char *b);
extern int wal_strnicmp(const char *a, const char *b, int count);
static int power(const void *context, const char *cmd, const char *args){
if (!wal_strnicmp(cmd, "POWER", 5)){
int channel = 0;
int iVal = 0;
if (strlen(cmd) > 5) {
channel = atoi(cmd+5);
}
iVal = atoi(args);
CHANNEL_Set(channel, iVal, false);
return 1;
}
return 0;
}
static int color(const void *context, const char *cmd, const char *args){
if (!wal_strnicmp(cmd, "COLOR", 5)){
if (args[0] != '#'){
ADDLOG_ERROR(LOG_FEATURE_CMD, "tasCmnd COLOR expected a # prefixed color");
return 0;
} else {
const char *c = args;
int val = 0;
int channel = 0;
c++;
while (*c){
char tmp[3];
int r;
tmp[0] = *(c++);
if (!*c) break;
tmp[1] = *(c++);
r = sscanf(tmp, "%x", &val);
if (!r) break;
// if this channel is not PWM, find a PWM channel;
while ((channel < 32) && (IOR_PWM != CHANNEL_GetRoleForChannel(channel))) {
channel ++;
}
if (channel >= 32) break;
val = (val * 100)/255;
CHANNEL_Set(channel, val, 0);
// move to next channel.
channel ++;
}
}
return 1;
}
return 0;
}
static int cmnd_backlog(const void * context, const char *cmd, const char *args){
const char *subcmd;
const char *p;
int count = 0;
char copy[128];
char *c;
if (stricmp(cmd, "backlog")){
return -1;
}
ADDLOG_DEBUG(LOG_FEATURE_CMD, "backlog [%s]", args);
subcmd = args;
p = args;
while (*subcmd){
c = copy;
while (*p){
if (*p == ';'){
*c = '\0';
p++;
break;
}
*(c) = *(p++);
if (c - copy < 127){
c++;
}
}
count++;
CMD_ExecuteCommand(copy);
subcmd = p;
}
ADDLOG_DEBUG(LOG_FEATURE_CMD, "backlog executed %d", count);
return 1;
}
static int cmnd_lfsexec(const void * context, const char *cmd, const char *args){
#ifdef BK_LITTLEFS
ADDLOG_DEBUG(LOG_FEATURE_CMD, "exec %s", args);
if (lfs_present()){
lfs_file_t *file = os_malloc(sizeof(lfs_file_t));
if (file){
int lfsres;
char line[256];
const char *fname = "autoexec.bat";
memset(file, 0, sizeof(lfs_file_t));
if (args && *args){
fname = args;
}
lfsres = lfs_file_open(&lfs, file, fname, LFS_O_RDONLY);
if (lfsres >= 0) {
ADDLOG_DEBUG(LOG_FEATURE_CMD, "openned file %s", fname);
do {
char *p = line;
do {
lfsres = lfs_file_read(&lfs, file, p, 1);
if ((lfsres <= 0) || (*p < 0x20) || (p - line) == 255){
*p = 0;
break;
}
p++;
} while ((p - line) < 255);
ADDLOG_DEBUG(LOG_FEATURE_CMD, "line is %s", line);
if (lfsres >= 0){
if (*line && (*line != '#')){
CMD_ExecuteCommand(line);
}
}
} while (lfsres > 0);
lfs_file_close(&lfs, file);
ADDLOG_DEBUG(LOG_FEATURE_CMD, "closed file %s", fname);
} else {
ADDLOG_ERROR(LOG_FEATURE_CMD, "no file %s err %d", fname, lfsres);
}
os_free(file);
file = NULL;
}
} else {
ADDLOG_ERROR(LOG_FEATURE_CMD, "lfs is absent");
}
#endif
return 1;
}
int taslike_commands_init(){
CMD_RegisterCommand("power", "", power, "set output POWERn 0..100", NULL);
CMD_RegisterCommand("color", "", color, "set PWN color using #RRGGBB[cw][ww]", NULL);
CMD_RegisterCommand("backlog", "", cmnd_backlog, "run a sequence of ; separated commands", NULL);
CMD_RegisterCommand("exec", "", cmnd_lfsexec, "exec <file> - run autoexec.bat or other file from LFS if present", NULL);
return 0;
}

2
src/cmnds/taslike.h Normal file
View File

@@ -0,0 +1,2 @@
int taslike_commands_init();

View File

@@ -260,7 +260,7 @@ void TuyaMCU_Send_SetTime(rtcc_t *pTime) {
TuyaMCU_SendCommandWithData(TUYA_CMD_SET_TIME, payload_buffer, 8);
}
int TuyaMCU_Send_Hex(const void *context, const char *cmd, char *args) {
int TuyaMCU_Send_Hex(const void *context, const char *cmd, const char *args) {
//const char *args = CMD_GetArg(1);
if(!(*args)) {
printf("TuyaMCU_Send_Hex: requires 1 argument (hex string, like FFAABB00CCDD\n");
@@ -277,7 +277,7 @@ int TuyaMCU_Send_Hex(const void *context, const char *cmd, char *args) {
return 1;
}
int TuyaMCU_Send_SetTime_Example(const void *context, const char *cmd, char *args) {
int TuyaMCU_Send_SetTime_Example(const void *context, const char *cmd, const char *args) {
rtcc_t testTime;
testTime.year = 2012;

View File

@@ -547,7 +547,7 @@ static int http_getlog(http_request_t *request){
}
int log_command(const void *context, const char *cmd, char *args){
int log_command(const void *context, const char *cmd, const char *args){
int result = 0;
if (!cmd) return -1;
if (!args) return -1;

View File

@@ -17,7 +17,7 @@
void addLog(char *fmt, ...);
void addLogAdv(int level, int feature, char *fmt, ...);
int log_command(const void *context, const char *cmd, char *args);
int log_command(const void *context, const char *cmd, const char *args);
#define ADDLOG_ERROR(x, fmt, ...) addLogAdv(LOG_ERROR, x, fmt, ##__VA_ARGS__)
#define ADDLOG_WARN(x, fmt, ...) addLogAdv(LOG_WARN, x, fmt, ##__VA_ARGS__)

View File

@@ -4,6 +4,7 @@
#include "../new_cfg.h"
#include "../logging/logging.h"
#include <ctype.h>
#include "../new_cmd.h"
#undef os_printf
@@ -279,9 +280,7 @@ int tasCmnd(mqtt_request_t* request){
// we only need a few bytes to receive a decimal number 0-100
char copy[64];
int len = request->receivedLen;
char *p = request->topic;
int channel = 0;
int iValue = 0;
const char *p = request->topic;
// assume a string input here, copy and terminate
if(len > sizeof(copy)-1) {
@@ -291,8 +290,6 @@ int tasCmnd(mqtt_request_t* request){
// strncpy does not terminate??!!!!
copy[len] = '\0';
PR_NOTICE("tas? data is %s for ch %s\n", copy, request->topic);
// TODO: better
// skip to after second forward slash
while(*p != '/') { if(*p == 0) return 0; p++; }
@@ -300,61 +297,8 @@ int tasCmnd(mqtt_request_t* request){
while(*p != '/') { if(*p == 0) return 0; p++; }
p++;
do{
// accept POWER and POWER0-n
if (!wal_strnicmp(p, "POWER", 5)){
p += 5;
if ((*p - '0' >= 0) && (*p - '0' <= 9)){
channel = atoi(p);
} else {
channel = 0;
}
// if channel out of range, stop here.
if ((channel < 0) || (channel > 32)) return 0;
//PR_NOTICE("MQTT client in mqtt_incoming_data_cb\n");
PR_NOTICE("MQTT client in tasCmnd data is %s for ch %i\n", copy, channel);
iValue = atoi((char *)copy);
CHANNEL_Set(channel,iValue,0);
break;
}
if (!wal_strnicmp(p, "COLOR", 5)){
p += 5;
if (copy[0] != '#'){
PR_NOTICE("tasCmnd COLOR expected a # prefixed color");
} else {
char *c = copy;
int val = 0;
int channel = 0;
c++;
while (*c){
char tmp[3];
int r;
tmp[0] = *(c++);
if (!*c) break;
tmp[1] = *(c++);
r = sscanf(tmp, "%x", &val);
if (!r) break;
// if this channel is not PWM, find a PWM channel;
while ((channel < 32) && (IOR_PWM != CHANNEL_GetRoleForChannel(channel))) {
channel ++;
}
if (channel >= 32) break;
val = (val * 100)/255;
CHANNEL_Set(channel, val, 0);
// move to next channel.
channel ++;
}
}
break;
}
PR_NOTICE("MQTT client unprocessed in tasCmnd data is %s for topic \n", copy, request->topic);
break;
} while (0);
// use command executor....
CMD_ExecuteCommandArgs(p, copy);
// return 1 to stop processing callbacks here.
// return 0 to allow later callbacks to process this topic.

View File

@@ -1,9 +1,9 @@
#include "new_cmd.h"
#include "new_pins.h"
#include "new_cfg.h"
#include "logging/logging.h"
#include "obk_config.h"
#include <ctype.h>
#include "new_cmd.h"
#ifdef BK_LITTLEFS
#include "littlefs/our_lfs.h"
#endif
@@ -29,15 +29,8 @@ static int generateHashValue(const char *fname) {
}
command_t *g_commands[HASH_SIZE] = { NULL };
static int cmnd_backlog(const void * context, const char *cmd, char *args);
static int cmnd_lfsexec(const void * context, const char *cmd, char *args);
void CMD_Init(int runautoexec) {
CMD_RegisterCommand("backlog", "", cmnd_backlog, "run a sequence of ; separated commands", NULL);
CMD_RegisterCommand("exec", "", cmnd_lfsexec, "exec <file> - run autoexec.bat or other file from LFS if present", NULL);
if (runautoexec){
cmnd_lfsexec(NULL, "exec", "autoexec.bat");
}
void CMD_Init() {
}
@@ -61,9 +54,10 @@ void CMD_RegisterCommand(const char *name, const char *args, commandHandler_t ha
// check
newCmd = CMD_Find(name);
if(newCmd != 0) {
printf("ERROR: command with name %s already exists!\n",name);
ADDLOG_ERROR(LOG_FEATURE_CMD, "command with name %s already exists!",name);
return;
}
ADDLOG_DEBUG(LOG_FEATURE_CMD, "Adding command %s",name);
hash = generateHashValue(name);
newCmd = (command_t*)malloc(sizeof(command_t));
@@ -87,7 +81,8 @@ command_t *CMD_Find(const char *name) {
if(!stricmp(newCmd->name,name)) {
return newCmd;
}
}
newCmd = newCmd->next;
}
return 0;
}
@@ -118,163 +113,84 @@ bool isWhiteSpace(char ch) {
// return g_args[i];
//}
int CMD_ExecuteCommand(char *s) {
//int r = 0;
char *p;
//int i;
char *cmd;
char *args;
// get a string up to whitespace.
// if stripnum is set, stop at numbers.
int get_cmd(const char *s, char *dest, int maxlen, int stripnum){
int i;
int count = 0;
for (i = 0; i < maxlen-1; i++){
if (isWhiteSpace(*s)) {
break;
}
if (stripnum && *s >= '0' && *s <= '9'){
break;
}
*(dest++) = *(s++);
count++;
}
*dest = '\0';
return count;
}
// execute a command from cmd and args - used below and in MQTT
int CMD_ExecuteCommandArgs(const char *cmd, const char *args) {
command_t *newCmd;
int len;
// look for complete commmand
newCmd = CMD_Find(cmd);
if (!newCmd) {
// not found, so...
char nonums[32];
// get the complete string up to numbers.
len = get_cmd(cmd, nonums, 32, 1);
newCmd = CMD_Find(nonums);
if (!newCmd) {
// if still not found, then error
ADDLOG_ERROR(LOG_FEATURE_CMD, "cmd %s NOT found", cmd);
return 0;
}
} else {
}
if (newCmd->handler){
int res;
res = newCmd->handler(newCmd->context, cmd, args);
return res;
}
return 0;
}
// execute a raw command - single string
int CMD_ExecuteCommand(const char *s) {
const char *p;
const char *args;
char copy[32];
int len;
const char *org;
ADDLOG_DEBUG(LOG_FEATURE_CMD, "cmd [%s]", s);
while(isWhiteSpace(*s)) {
s++;
}
org = s;
// get the complete string up to whitespace.
len = get_cmd(s, copy, 32, 0);
s += len;
cmd = s;
p = s;
while(*p != 0) {
if(isWhiteSpace(*p)) {
*p = 0;
p++;
break;
}
p++;
}
while(*p && isWhiteSpace(*p)) {
p++;
}
args = p;
newCmd = CMD_Find(cmd);
if (!newCmd) {
ADDLOG_ERROR(LOG_FEATURE_CMD, "cmd %s not found", cmd);
return 0;
}
if (newCmd->handler){
return newCmd->handler(newCmd->context, cmd, args);
}
return 0;
/*
strcpy(g_buffer,s);
p = g_buffer;
g_numArgs = 0;
g_args[g_numArgs] = p;
g_numArgs++;
while(*p != 0) {
if(isWhiteSpace(*p)) {
*p = 0;
if((p[1] != 0)) {
g_args[g_numArgs] = p+1;
g_numArgs++;
}
}
if(*p == ',') {
*p = 0;
g_args[g_numArgs] = p+1;
g_numArgs++;
}
p++;
}
if(1){
printf("Command parsed debug out! %i args\n",g_numArgs);
for(i = 0; i < g_numArgs; i++) {
printf("Arg %i is %s\n",i,g_args[i]);
}
}
newCmd = CMD_Find(g_args[0]);
if(newCmd != 0) {
r++;
newCmd->handler();
}
return r;
*/
return CMD_ExecuteCommandArgs(copy, args);
}
static int cmnd_backlog(const void * context, const char *cmd, char *args){
char *subcmd;
char *p;
int count = 0;
if (stricmp(cmd, "backlog")){
return -1;
}
ADDLOG_DEBUG(LOG_FEATURE_CMD, "backlog [%s]", args);
subcmd = args;
p = args;
while (*subcmd){
while (*p){
if (*p == ';'){
*p = '\0';
p++;
break;
}
p++;
}
count++;
CMD_ExecuteCommand(subcmd);
subcmd = p;
}
ADDLOG_DEBUG(LOG_FEATURE_CMD, "backlog executed %d", count);
return 1;
}
static int cmnd_lfsexec(const void * context, const char *cmd, char *args){
#ifdef BK_LITTLEFS
ADDLOG_DEBUG(LOG_FEATURE_CMD, "exec %s", args);
if (lfs_present()){
lfs_file_t *file = os_malloc(sizeof(lfs_file_t));
if (file){
int lfsres;
char line[256];
char *fname = "autoexec.bat";
memset(file, 0, sizeof(lfs_file_t));
if (args && *args){
fname = args;
}
lfsres = lfs_file_open(&lfs, file, fname, LFS_O_RDONLY);
if (lfsres >= 0) {
ADDLOG_DEBUG(LOG_FEATURE_CMD, "openned file %s", fname);
do {
char *p = line;
do {
lfsres = lfs_file_read(&lfs, file, p, 1);
if ((lfsres <= 0) || (*p < 0x20) || (p - line) == 255){
*p = 0;
break;
}
p++;
} while ((p - line) < 255);
ADDLOG_DEBUG(LOG_FEATURE_CMD, "line is %s", line);
if (lfsres >= 0){
if (*line && (*line != '#')){
CMD_ExecuteCommand(line);
}
}
} while (lfsres > 0);
lfs_file_close(&lfs, file);
ADDLOG_DEBUG(LOG_FEATURE_CMD, "closed file %s", fname);
} else {
ADDLOG_ERROR(LOG_FEATURE_CMD, "no file %s err %d", fname, lfsres);
}
os_free(file);
file = NULL;
}
} else {
ADDLOG_ERROR(LOG_FEATURE_CMD, "lfs is absent");
}
#endif
return 1;
}

View File

@@ -1,6 +1,6 @@
typedef int (*commandHandler_t)(const void *context, const char *cmd, char *args);
typedef int (*commandHandler_t)(const void *context, const char *cmd, const char *args);
typedef struct command_s {
const char *name;
@@ -11,17 +11,19 @@ typedef struct command_s {
struct command_s *next;
} command_t;
void CMD_Init(int runautoexec);
void CMD_Init();
command_t *CMD_Find(const char *name);
void CMD_RegisterCommand(const char *name, const char *args, commandHandler_t handler, const char *userDesc, void *context);
// allow modification of s
int CMD_ExecuteCommand(char *s);
int CMD_ExecuteCommand(const char *s);
int CMD_ExecuteCommandArgs(const char *cmd, const char *args);
// NOTE: argsCount includes commands name, so 1 tells "only command"
int CMD_GetArgsCount() ;
// NOTE: arg0 is command name
const char *CMD_GetArg(int i);
// for autocompletion?
void CMD_ListAllCommands(void *userData, void (*callback)(command_t *cmd, void *userData));
int get_cmd(const char *s, char *dest, int maxlen, int stripnum);
bool isWhiteSpace(char ch);

View File

@@ -59,6 +59,8 @@
#include "ntp_time.h"
#include "new_cmd.h"
#include "cmnds/taslike.h"
#include "cmnds/fortest.h"
#undef Malloc
#undef Free
@@ -416,11 +418,19 @@ void user_main(void)
// all MQTT happens in timer thread?
MQTT_init();
// add some commands...
taslike_commands_init();
fortest_commands_init();
// NOTE: this will try to read autoexec.bat,
// so ALL commands expected in autoexec.bat should have been registered by now...
// but DON't run autoexec if we have had 2+ boot failures
CMD_Init(bootFailures < 2);
CMD_Init();
if (bootFailures < 2){
CMD_ExecuteCommand("exec autoexec.bat");
}
err = rtos_init_timer(&led_timer,
1 * 1000,