Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cliConfig (USE_PEGASUS_UI) for 1.0.0 #811

Draft
wants to merge 3 commits into
base: emuflight-1.0.0-master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 280 additions & 0 deletions src/main/cli/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
// FIXME remove this for targets that don't need a CLI. Perhaps use a no-op macro when USE_CLI is not enabled
// signal that we're in cli mode
bool cliMode = false;
bool cliExited = false;

#ifdef USE_CLI

Expand Down Expand Up @@ -3608,6 +3609,24 @@ static void cliExit(const char *cmdName, char *cmdline)
cliReboot();
}

static void cliExitNoReboot(const char *cmdName, char *cmdline)
{
UNUSED(cmdName);
UNUSED(cmdline);

cliPrintHashLine("leaving CLI mode, unsaved changes lost");
cliWriterFlush();

*cliBuffer = '\0';
bufferIndex = 0;
cliMode = false;
cliExited = true;
// incase a motor was left running during motortest, clear it here
mixerResetDisarmedMotors();
waitForSerialPortToFinishTransmitting(cliPort);
motorShutdown();
}

#ifdef USE_GPS
static void cliGpsPassthrough(const char *cmdName, char *cmdline)
{
Expand Down Expand Up @@ -4267,6 +4286,18 @@ static void cliSave(const char *cmdName, char *cmdline)
}
}

static void cliSaveNoReboot(const char *cmdName, char *cmdline)
{
UNUSED(cmdline);

if (tryPrepareSave(cmdName)) {
writeEEPROM();
readEEPROM();
cliPrintHashLine("saving");

}
}

#if defined(USE_CUSTOM_DEFAULTS)
bool resetConfigToCustomDefaults(void)
{
Expand Down Expand Up @@ -4515,6 +4546,247 @@ STATIC_UNIT_TESTED void cliGet(const char *cmdName, char *cmdline)
}
}

#ifdef USE_PEGASUS_UI
static const char * valueSectionMask[] = {
"GLOBAL", "PROFILE", "RATE", "HARDWARE"
};

static const char * valueTypeMask[] = {
"UINT8", "INT8", "UINT16", "INT16"
};

static const char * valueModeMask[] = {
"DIRECT", "LOOKUP", "ARRAY", "BITMASK", "STRING"
};

void cliPrintValueJson(const char *cmdName, int32_t i){
const clivalue_t *var = &valueTable[i];
cliPrintf("\"%s\":{\"scope\":\"%s\",\"type\":\"%s\",\"mode\":\"%s\",\"current\":\"",
var->name,
valueSectionMask[((var->type & VALUE_SECTION_MASK) >> VALUE_SECTION_OFFSET)],
valueTypeMask[((var->type & VALUE_TYPE_MASK) >> VALUE_TYPE_OFFSET)],
valueModeMask[((var->type & VALUE_MODE_MASK) >> VALUE_MODE_OFFSET)]);
cliPrintVar(cmdName, var, 0);
if ((var->type & VALUE_MODE_MASK) == MODE_STRING) {
cliPrintf("\",\"string min length\":\"%d\",\"string max length\":\"%d\"", var->config.string.minlength, var->config.string.maxlength);
// strings have no default
} else {
cliPrint("\",\"default\":\"");
const pgRegistry_t *pg = pgFind(var->pgn);
const int valueOffset = getValueOffset(var);
printValuePointer(cmdName, var, (uint8_t*)pg->address + valueOffset, false);
cliPrint("\"");
if ((var->type & VALUE_MODE_MASK) == MODE_LOOKUP)
{
const lookupTableEntry_t *tableEntry = &lookupTables[var->config.lookup.tableIndex];
cliPrintLine(",\"values\":[");
for (int32_t i = 0; i < tableEntry->valueCount ; i++) {
if (i > 0)
{
cliPrintLine(",");
}
cliPrintf("\"%s\"", tableEntry->values[i]);
}
cliPrint("]");
}

int min;
int max;
getMinMax(var, &min, &max);

if ((var->type & VALUE_MODE_MASK) == MODE_DIRECT) {
cliPrintf(",\"min\":\"%d\",\"max\":\"%d\"", min, max);
}
if ((var->type & VALUE_MODE_MASK) == MODE_ARRAY) {
cliPrintf(",\"min\":\"%d\",\"max\":\"%d\"", min, max);
}
}
cliPrint("}");
}

static void printFeatureJson(const featureConfig_t *configCopy)
{
const uint32_t mask = configCopy->enabledFeatures;
const uint32_t defaultMask = featureConfig()->enabledFeatures;
cliPrintLine(",");
cliPrintf("\"features\":{\"scope\":\"GLOBAL\",\"type\":\"UINT8\",\"mode\":\"ARRAY\",\"current\":\"%d\",\"values\":[", mask);
cliPrintLine("");
for (uint32_t i = 0; featureNames[i]; i++) { // disabled features first
if (strcmp(featureNames[i], emptyString) != 0) { //Skip unused
if (i > 0)
{
cliPrintLine(",");
}
if ((~defaultMask | mask) & (1 << i)) {
cliPrintf("\"-%s\"", featureNames[i]);
} else {
cliPrintf("\"%s\"", featureNames[i]);
}
}
}
cliPrintf("]}");
}
static void printSerialJson(const serialConfig_t *serialConfig)
{
cliPrintLine(",");
cliPrintLine("\"ports\":{\"scope\":\"GLOBAL\",\"type\":\"UINT16\",\"mode\":\"ARRAY\",\"values\":[");
for (uint32_t i = 0; i < SERIAL_PORT_COUNT; i++) {
if (!serialIsPortAvailable(serialConfig->portConfigs[i].identifier)) {
continue;
};
if (i > 0)
{
cliPrintLine(",");
}
cliPrintf("\"%d|%d|%ld|%ld|%ld|%ld\"",
serialConfig->portConfigs[i].identifier,
serialConfig->portConfigs[i].functionMask,
baudRates[serialConfig->portConfigs[i].msp_baudrateIndex],
baudRates[serialConfig->portConfigs[i].gps_baudrateIndex],
baudRates[serialConfig->portConfigs[i].telemetry_baudrateIndex],
baudRates[serialConfig->portConfigs[i].blackbox_baudrateIndex]);
}
cliPrintf("]}");
}

static void printAuxJson(const modeActivationCondition_t *modeActivationConditions)
{
cliPrintLine(",");
cliPrintLine("\"modes\":{\"scope\":\"GLOBAL\",\"type\":\"UINT16\",\"mode\":\"ARRAY\",\"values\":[");
for (uint32_t i = 0; i < MAX_MODE_ACTIVATION_CONDITION_COUNT; i++) {
if (i > 0)
{
cliPrintLine(",");
}
const modeActivationCondition_t *mac = &modeActivationConditions[i];
const box_t *box = findBoxByBoxId(mac->modeId);
if (box) {
cliPrintf("\"%u|%u|%u|%u|%u|%u\"",
i,
box->permanentId,
mac->auxChannelIndex,
MODE_STEP_TO_CHANNEL_VALUE(mac->range.startStep),
MODE_STEP_TO_CHANNEL_VALUE(mac->range.endStep),
mac->modeLogic
);
}
}
cliPrintf("]}");
}

static void printResourceJson()
{
cliPrintLine(",");
cliPrintLine("\"resources\":{\"scope\":\"GLOBAL\",\"type\":\"string\",\"mode\":\"ARRAY\",\"values\":[");
for (int i = 0; i < DEFIO_IO_USED_COUNT; i++) {
if (i > 0)
{
cliPrintLine(",");
}
const char* owner;
owner = ownerNames[ioRecs[i].owner];

cliPrintf("\"%c%02d|%s|", IO_GPIOPortIdx(ioRecs + i) + 'A', IO_GPIOPinIdx(ioRecs + i), owner);
if (ioRecs[i].index > 0) {
cliPrintf("%d", ioRecs[i].index);
} else {
cliPrintf("0");
}
cliPrintf("\"");
//cliPrintLinefeed();
}
cliPrintf("]}");
}

#define PROFILE_JSON_STRING "\"%s_profile\":{\"scope\":\"GLOBAL\",\"type\":\"UINT8\",\"mode\":\"LOOKUP\",\"current\":\"%d\",\"values\":[{"

static void dumpProfileValueJson(const char *cmdName, uint16_t valueSection)
{
bool foundFirst = false;
for (uint32_t i = 0; i < valueTableEntryCount; i++) {
const clivalue_t *value = &valueTable[i];
if ((value->type & VALUE_SECTION_MASK) == valueSection) {
if (foundFirst)
{
cliPrintLine(",");
}
cliPrintValueJson(cmdName, i);
foundFirst = true;
}
}
}

static void cliPidProfilesJson(const char *cmdName)
{
cliPrintLine(",");
cliPrintf(PROFILE_JSON_STRING, "pid", getCurrentPidProfileIndex());
const uint8_t saved = systemConfig_Copy.pidProfileIndex;
for (uint32_t i = 0; i < PID_PROFILE_COUNT; i++) {
changePidProfile(i);
if (i > 0)
{
cliPrintLine("},");
cliPrint("{");
}
dumpProfileValueJson(cmdName, PROFILE_VALUE);
}
changePidProfile(saved);
cliPrint("}]}");
}

static void cliRateProfilesJson(const char *cmdName)
{
cliPrintLine(",");
cliPrintf(PROFILE_JSON_STRING, "rate", getCurrentControlRateProfileIndex());
const uint8_t saved = systemConfig_Copy.activeRateProfile;
for (uint32_t i = 0; i < CONTROL_RATE_PROFILE_COUNT; i++) {
changeControlRateProfile(i);
if (i > 0)
{
cliPrintLine("},");
cliPrint("{");
}
dumpProfileValueJson(cmdName, PROFILE_RATE_VALUE);
}
changeControlRateProfile(saved);
cliPrint("}]}");
}

static void cliConfig(const char *cmdName, char *cmdline)
{
UNUSED(cmdline);
cliPrintLine("----- CONFIG START -----");
cliPrintLine("{");
for (uint32_t i = 0; i < valueTableEntryCount; i++)
{
if (i > 0)
{
cliPrintLine(",");
}
cliPrintValueJson(cmdName, i);
}
cliPidProfilesJson(cmdName);
cliRateProfilesJson(cmdName);
printFeatureJson(&featureConfig_Copy);
printSerialJson(serialConfig());
printAuxJson(modeActivationConditions(0));
printResourceJson();
cliPrintLine(",");
cliPrintf("\"name\":\"%s\"", pilotConfig()->name);
cliPrintf(",\"version\":\"%s|%s|%s|%s\"",
FC_FIRMWARE_NAME,
targetName,
systemConfig()->boardIdentifier,
FC_VERSION_STRING
);
#ifdef USE_GYRO_IMUF9001
cliPrintf(",\"imuf\":\"%lu\"", imufCurrentVersion);
#endif
cliPrintLine("}");
cliPrintLine("----- CONFIG END -----");
}
#endif

static uint8_t getWordLength(char *bufBegin, char *bufEnd)
{
while (*(bufEnd - 1) == ' ') {
Expand Down Expand Up @@ -6546,6 +6818,7 @@ const clicmd_t cmdTable[] = {
CLI_COMMAND_DEF("escprog", "passthrough esc to serial", "<mode [sk/bl/ki/cc]> <index>", cliEscPassthrough),
#endif
CLI_COMMAND_DEF("exit", NULL, NULL, cliExit),
CLI_COMMAND_DEF("exit_no_reboot", NULL, NULL, cliExitNoReboot),
CLI_COMMAND_DEF("feature", "configure features",
"list\r\n"
"\t<->[name]", cliFeature),
Expand All @@ -6559,6 +6832,9 @@ const clicmd_t cmdTable[] = {
#endif
#endif
CLI_COMMAND_DEF("get", "get variable value", "[name]", cliGet),
#ifdef USE_PEGASUS_UI
CLI_COMMAND_DEF("config", "get all configuration information", NULL, cliConfig),
#endif
#ifdef USE_GPS
CLI_COMMAND_DEF("gpspassthrough", "passthrough gps to serial", NULL, cliGpsPassthrough),
#endif
Expand Down Expand Up @@ -6603,6 +6879,7 @@ const clicmd_t cmdTable[] = {
CLI_COMMAND_DEF("rxfail", "show/set rx failsafe settings", NULL, cliRxFailsafe),
CLI_COMMAND_DEF("rxrange", "configure rx channel ranges", NULL, cliRxRange),
CLI_COMMAND_DEF("save", "save and reboot", NULL, cliSave),
CLI_COMMAND_DEF("save_no_reboot", "save without reboot", NULL, cliSaveNoReboot),
#ifdef USE_SDCARD
CLI_COMMAND_DEF("sd_info", "sdcard info", NULL, cliSdInfo),
#endif
Expand Down Expand Up @@ -6871,6 +7148,9 @@ static bool cliProcessCustomDefaults(bool quiet)

void cliEnter(serialPort_t *serialPort)
{
if (cliExited) { // required for exit_no_reboot
return;
}
cliMode = true;
cliPort = serialPort;
setPrintfSerialPort(cliPort);
Expand Down
1 change: 1 addition & 0 deletions src/main/cli/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <stdbool.h>

extern bool cliMode;
extern bool cliExited;

void cliProcess(void);
bool hasCustomDefaults(void);
Expand Down
1 change: 1 addition & 0 deletions src/main/msp/msp_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ static void mspEvaluateNonMspData(mspPort_t * mspPort, uint8_t receivedChar)
mspPort->pendingRequest = MSP_PENDING_BOOTLOADER_ROM;
#ifdef USE_CLI
} else if (receivedChar == '#') {
cliExited = false;
mspPort->pendingRequest = MSP_PENDING_CLI;
#endif
#if defined(USE_FLASH_BOOT_LOADER)
Expand Down
1 change: 1 addition & 0 deletions src/main/target/common_pre.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ extern uint8_t _dmaram_end__;
#define USE_MSP_OVER_TELEMETRY
#define USE_OSD_OVER_MSP_DISPLAYPORT
#define USE_LED_STRIP
#define USE_PEGASUS_UI
#endif

#if ((TARGET_FLASH_SIZE > 256) || (FEATURE_CUT_LEVEL < 11))
Expand Down