Files
CuboBmsFirmware/firmware/Core/Src/modTerminal.c
2023-04-06 21:23:19 +03:00

596 lines
23 KiB
C

/*
Copyright 2016 Benjamin Vedder benjamin@vedder.se
Copyright 2017 - 2018 Danny Bokma danny@diebie.nl
Copyright 2019 - 2020 Kevin Dionne kevin.dionne@ennoid.me
This file is part of the VESC/DieBieMS/ENNOID-BMS firmware.
The VESC/DieBieMS/ENNOID-BMS firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The VESC/DieBieMS/ENNOID-BMS firmware is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "modTerminal.h"
#include "main.h"
#include "time.h"
#include "rtc.h"
#include "modStateOfCharge.h"
#include "can_messenger.h"
// Private types
typedef struct _terminal_callback_struct {
const char *command;
const char *help;
const char *arg_names;
void(*cbf)(int argc, const char **argv);
} terminal_callback_struct;
// Private variables
static terminal_callback_struct callbacks[CALLBACK_LEN];
static int callback_write = 0;
extern modConfigGeneralConfigStructTypedef *generalConfig;
extern modStateOfChargeStructTypeDef *generalStateOfCharge;
extern modPowerElectronicsPackStateTypedef packState;
extern OperationalStateTypedef modOperationalStateCurrentState;
extern SIM800_Global_Struct SIM800_Struct;
extern bool jumpBootloaderTrue;
void modTerminalProcessString(char *str) {
struct tm tm_PC_Time = {0};
Time_Struct PC_time;
uint64_t NewSerial;
enum { kMaxArgs = 64 };
int argc = 0;
char *argv[kMaxArgs];
char* ptr;
char *p2 = strtok(str, " ");
while (p2 && argc < kMaxArgs) {
argv[argc++] = p2;
p2 = strtok(0, " ");
}
if (argc == 0) {
modCommandsPrintf("No command received\n");
return;
}
if (strcmp(argv[0], "ping") == 0) {
modCommandsPrintf("pong\n");
} else if (strcmp(argv[0], "status") == 0) {
bool disChargeEnabled = packState.disChargeDesired && packState.disChargeLCAllowed;
bool chargeEnabled = packState.chargeDesired && packState.chargeAllowed;
/*
static float real_capacity = 0;
static float previous_capacity = 0;
static float previous_SoC = 0;
//static float current_SoC = 0;
static float soc_diff = 0;
static float capacity_diff = 0;
static uint8_t SoC_Save_Flag = 0;
*/
/*
*
uint8_t Pilot_Status = 0;
uint8_t Maximum_Charge_Current_Status = 0;
uint8_t Maximum_Voltage_Status = 0;
uint8_t Maximum_Temp_Status = 0;
uint8_t Maximum_Load_Current_Status = 0;
uint8_t Minimum_Voltage_Status = 0;
*/
modCommandsPrintf(" ");
modCommandsPrintf("-----Battery Pack Status-----");
//modPowerElectronicsPackStateHandle->cellModuleBalanceResistorEnableMask
modCommandsPrintf("Balance mask : 0x%x ",packState.cellModuleBalanceResistorEnableMask[0]);
modCommandsPrintf("Pack voltage Direct : %.2fV",packState.packVoltage);
modCommandsPrintf("Pack voltage CVAverage: %.2fV",packState.cellVoltageAverage*generalConfig->noOfCellsSeries);
modCommandsPrintf("Pack current : %.2fA",packState.packCurrent);
//modCommandsPrintf("LC Load voltage : %.2fV",packState.loCurrentLoadVoltage);
//modCommandsPrintf("Low current : %.2fA",packState.loCurrentLoadCurrent);
modCommandsPrintf("State of charge : %.1f%%",generalStateOfCharge->generalStateOfCharge);
modCommandsPrintf("Remaining capacity : %.2fAh",generalStateOfCharge->remainingCapacityAh);
modCommandsPrintf("Real calculated capacity : %fAh",export_real_capacity);
//modCommandsPrintf("previous_capacity : %.2fAh",previous_capacity);
// modCommandsPrintf("previous_SoC : %.2fAh",previous_SoC);
// modCommandsPrintf("soc_diff : %.2fAh",soc_diff);
// modCommandsPrintf("capacity_diff : %.2fAh",capacity_diff);
// modCommandsPrintf("SoC_Save_Flag : %.2fAh",SoC_Save_Flag);
modCommandsPrintf(" ");
modCommandsPrintf("Pilot_Status: %s",Pilot_Status ? "Charging" : "No charging");
modCommandsPrintf("Maximum_Charge_Current_Status: %s",Maximum_Charge_Current_Status ? "Good" : "Too high charge current!");
modCommandsPrintf("Maximum_Voltage_Status: %s",Maximum_Voltage_Status ? "Good" : "Too high voltage!");
modCommandsPrintf("Maximum_Temp_Status: %s",Maximum_Temp_Status ? "Good" : "Too high temperature!");
modCommandsPrintf("Maximum_Load_Current_Status: %s",Maximum_Load_Current_Status ? "Good" : "Too high load current!");
modCommandsPrintf("Minimum_Voltage_Status: %s",Minimum_Voltage_Status ? "Good" : "Too low voltage!");
modCommandsPrintf("Deep_Discharge_Status: %s",Deep_Discharge_Status ? "Good" : "Deep discharge!");
modCommandsPrintf("ADC_Current: %d",export_adc_average_res);
modCommandsPrintf("Current Zero Value: %f",generalConfig->shuntLCFactor);
modCommandsPrintf(" ");
modCommandsPrintf("Charge Switch State: %s",charge_switch_state ? "ON" : "OFF");
modCommandsPrintf("Load Switch State: %s",load_switch_state ? "ON" : "OFF");
modCommandsPrintf("Charge Permission: %s",packState.chargeAllowed ? "YES" : "NO");
// modCommandsPrintf("dummy: %s",get_dummy_soc() ? "YES" : "NO");
//generalConfig->shuntLCFactor
//export_adc_average_res
//export_real_capacity
// switch(modOperationalStateCurrentState) {
// case OP_STATE_CHARGING:
// modCommandsPrintf("Operational state : %s","Charging");
// break;
// case OP_STATE_LOAD_ENABLED:
// modCommandsPrintf("Operational state : %s","Load enabled");
// break;
// case OP_STATE_CHARGED:
// modCommandsPrintf("Operational state : %s","Charged");
// break;
// case OP_STATE_BALANCING:
// modCommandsPrintf("Operational state : %s","Balancing");
// break;
// case OP_STATE_ERROR_PRECHARGE:
// modCommandsPrintf("Operational state : %s","Pre charge error");
// break;
// case OP_STATE_ERROR:
// modCommandsPrintf("Operational state : %s","Error");
// break;
// case OP_STATE_FORCEON:
// modCommandsPrintf("Operational state : %s","Forced on");
// break;
// case OP_STATE_POWER_DOWN:
// modCommandsPrintf("Operational state : %s","Power down");
// break;
// case OP_STATE_EXTERNAL:
// modCommandsPrintf("Operational state : %s","External (USB or CAN)");
// break;
// default:
// modCommandsPrintf("Operational state : %s","Unknown");
// break;
// }
// modCommandsPrintf("Cell voltage high : %.3fV",packState.cellVoltageHigh);
// modCommandsPrintf("Cell voltage low : %.3fV",packState.cellVoltageLow);
// modCommandsPrintf("Cell voltage average : %.3fV",packState.cellVoltageAverage);
// modCommandsPrintf("Cell voltage mismatch : %.3fV",packState.cellVoltageMisMatch);
// modCommandsPrintf("Discharge enabled : %s",disChargeEnabled ? "True" : "False");
// modCommandsPrintf("Charge enabled : %s",chargeEnabled ? "True" : "False");
//ni modCommandsPrintf("Power button pressed : %s",packState.powerButtonActuated ? "True" : "False");
//ni modCommandsPrintf("CAN safety state : %s",packState.safetyOverCANHCSafeNSafe ? "True" : "False");
//ni modCommandsPrintf("---End Battery Pack Status---");
//ni modCommandsPrintf(" ");
/*
uint8_t cellVoltageLow_Minimum = 0;
uint8_t cellVoltageLow_Minimum_Hyst = 0;
uint8_t cellVoltageHigh_Maximum = 0;
uint8_t cellVoltageHigh_Maximum_Hyst = 0;
uint8_t maxChargeCurrent = 0;
uint8_t maxLoadCurrent = 0;
*/
} else if (strcmp(argv[0], "socJOPA") == 0) { // Dummy SoC = 100%
can_set_dummy_soc();
// modCommandsPrintf("durak");
} else if (strcmp(argv[0], "setZeroCurrent") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- setZeroCurrent -----");
// print temperatures
modCommandsPrintf("ADC Value: %.3f V",export_adc_average_res);
generalConfig->shuntLCFactor = export_adc_average_res;
modCommandsPrintf("Config Zero Value in EEPROM: %.3f V",generalConfig->shuntLCFactor);
modCommandsPrintf("Config Zero Value in RAM: %.3f V",currentZero_config);
modCommandsPrintf("Current Zero Value Updated! Remember to save EEPROM!");
modCommandsPrintf(" ");
/*
*
Brush_Minimum_SoC = generalConfig->minimalPrechargePercentage;
Brush_Default_State = generalConfig->timeoutLCPreCharge;
*/
} else if (strcmp(argv[0], "Outputs") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- Outputs -----");
// print temperatures
modCommandsPrintf("Output 2 minimum SoC: %.3f",Brush_Minimum_SoC);
modCommandsPrintf("Output 2 default state: %d",Brush_Default_State);
modCommandsPrintf(" ");
}else if (strcmp(argv[0], "limits") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- Limits -----");
// print temperatures
modCommandsPrintf("Minimum Cell Voltage: %.3f V",cellVoltageLow_Minimum);
modCommandsPrintf("Minimum Cell Voltage Hyst: %.3f V",cellVoltageLow_Minimum_Hyst);
modCommandsPrintf("Maximum Cell Voltage: %.3f V",cellVoltageHigh_Maximum);
modCommandsPrintf("Maximum Cell Voltage Hyst: %.3f V",cellVoltageHigh_Maximum_Hyst);
modCommandsPrintf(" ");
modCommandsPrintf("Maximum Charge Current: %.3f A",maxChargeCurrent);
modCommandsPrintf("Maximum Load Current: %.3f A",maxLoadCurrent);
modCommandsPrintf(" ");
modCommandsPrintf("Maximum Temperature: %.3f C",maxTemperature);
modCommandsPrintf("Maximum Temperature Hyst: %.3f C",maxTemperature_Hyst);
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "sens") == 0) {
modCommandsPrintf("----- Sensors -----");
// print temperatures
modCommandsPrintf("Sensor[0] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[0]);
modCommandsPrintf("Sensor[1] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[1]);
modCommandsPrintf("Sensor[2] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[2]);
modCommandsPrintf("Sensor[3] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[3]);
modCommandsPrintf("Sensor[4] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[4]);
modCommandsPrintf("Sensor[5] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[5]);
modCommandsPrintf("Sensor[6] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[6]);
modCommandsPrintf("Sensor[7] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[7]);
modCommandsPrintf("Sensor[8] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[8]);
modCommandsPrintf("Sensor[9] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[9]);
modCommandsPrintf("Sensor[10] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[10]);
modCommandsPrintf("Sensor[11] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[11]);
modCommandsPrintf("Sensor[12] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[12]);
modCommandsPrintf("Sensor[2] : % 3.1f C - I - 'LTC Internal'",packState.temperatures[2]);
modCommandsPrintf("Sensor[3] : % 3.1f C - I - 'STM NTC'",packState.temperatures[3]);
modCommandsPrintf("----- End sensors -----");
modCommandsPrintf("----- E=External I=Internal -----");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "cells") == 0) {
uint8_t cellPointer = 0;
modCommandsPrintf("----- Cell voltages -----");
modCommandsPrintf("Cell in series : %d ",generalConfig->noOfCellsSeries);
modCommandsPrintf("Number of ICs : %d ",generalConfig->cellMonitorICCount);
modCommandsPrintf("Cells per IC : %d ",generalConfig->noOfCellsPerModule);
for(cellPointer = 0 ; cellPointer < generalConfig->noOfCellsSeries ; cellPointer++) {
// test 01.11.2021 //
//for(cellPointer = 0 ; cellPointer < 20 ; cellPointer++) {
modCommandsPrintf("Cell voltage%3d : %.3f V",cellPointer,packState.cellVoltagesIndividual[cellPointer].cellVoltage);
}
modCommandsPrintf("Cell voltage high : %.3f V",packState.cellVoltageHigh);
modCommandsPrintf("Cell voltage low : %.3f V",packState.cellVoltageLow);
modCommandsPrintf("Cell voltage average : %.3f V",packState.cellVoltageAverage);
modCommandsPrintf("Cell voltage mismatch : %.3f V",packState.cellVoltageMisMatch);
modCommandsPrintf("----- End Cell voltages -----");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "config") == 0) {
modCommandsPrintf("--- BMS Configuration ---");
//modCommandsPrintf("serialNumber : %u",generalConfig->serialNumber);
modCommandsPrintf("NoOfCells : %u",generalConfig->noOfCellsSeries);
modCommandsPrintf("batteryCapacity : %.2fAh",generalConfig->batteryCapacity);
modCommandsPrintf("cellHardUnderVoltage : %.3fV",generalConfig->cellHardUnderVoltage);
modCommandsPrintf("cellHardOverVoltage : %.3fV",generalConfig->cellHardOverVoltage);
modCommandsPrintf("cellLCSoftUnderVoltage : %.3fV",generalConfig->cellLCSoftUnderVoltage);
modCommandsPrintf("cellSoftOverVoltage : %.3fV",generalConfig->cellSoftOverVoltage);
modCommandsPrintf("cellBalanceStart : %.3fV",generalConfig->cellBalanceStart);
//modCommandsPrintf("cellBalanceDiffThreshold : %.3fV",generalConfig->cellBalanceDifferenceThreshold);
modCommandsPrintf("CAN ID : %u",generalConfig->CANID);
modCommandsPrintf("--- End BMS Configuration ---");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "config_default") == 0) {
modCommandsPrintf("--Restoring default config--");
if(modConfigStoreDefaultConfig())
modCommandsPrintf("Succesfully restored config, new config wil be used on powercycle (or use config_read to apply it now).");
else
modCommandsPrintf("Error restored config.");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "config_write") == 0) {
modCommandsPrintf("--- Writing config ---");
if(modConfigStoreConfig())
modCommandsPrintf("Succesfully written config.");
else
modCommandsPrintf("Error writing config.");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "config_read") == 0) {
modCommandsPrintf("--- Reading config ---");
if(modConfigLoadConfig())
modCommandsPrintf("Succesfully read config.");
else
modCommandsPrintf("Error reading config.");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "config_set_cells") == 0) {
modCommandsPrintf("---Setting new cell count---");
if (argc == 2) {
uint32_t newNumberOfCells = 0;
sscanf(argv[1], "%u", &newNumberOfCells);
if(newNumberOfCells < 13 && newNumberOfCells > 2) {
modCommandsPrintf("Number of cells is set to: %u.",newNumberOfCells);
generalConfig->noOfCellsSeries = newNumberOfCells;
} else {
modCommandsPrintf("Invalid number of cells (should be anything from 3 to 12).");
}
} else {
modCommandsPrintf("This command requires one argument.");
}
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "hwinfo") == 0) {
modCommandsPrintf("------- BMS Info -------");
modCommandsPrintf("Firmware: %s", FW_REAL_VERSION);
modCommandsPrintf("Name : %s", HW_NAME);
modCommandsPrintf("UUID: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
STM32_UUID_8[0], STM32_UUID_8[1], STM32_UUID_8[2], STM32_UUID_8[3],
STM32_UUID_8[4], STM32_UUID_8[5], STM32_UUID_8[6], STM32_UUID_8[7],
STM32_UUID_8[8], STM32_UUID_8[9], STM32_UUID_8[10], STM32_UUID_8[11]);
modCommandsPrintf("------- End BMS Info -------");
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "reboot") == 0) {
modCommandsPrintf("------ Rebooting BMS ------");
NVIC_SystemReset();
} else if (strcmp(argv[0], "bootloader_erase") == 0) {
modCommandsPrintf("------ erasing new app space ------");
//ni if(modFlashEraseNewAppData(0x00002000) == HAL_OK)
if(1)
modCommandsPrintf("--Erase done.");
else
modCommandsPrintf("--Erase error.");
} else if (strcmp(argv[0], "bootloader_jump") == 0) {
//ni modFlashJumpToBootloader();
} else if (strcmp(argv[0], "help") == 0) {
modCommandsPrintf("------- Start of help -------");
modCommandsPrintf("Valid commands for CUBO-BMS are:");
modCommandsPrintf("help");
modCommandsPrintf(" Show this help.");
modCommandsPrintf("setZeroCurrent");
modCommandsPrintf(" Set Zero for current sensor");
modCommandsPrintf("ping");
modCommandsPrintf(" Print pong here to see if the reply works.");
modCommandsPrintf("slave_scan");
modCommandsPrintf(" Scan the I2C devices on the slave.");
modCommandsPrintf("status");
modCommandsPrintf(" Print battery measurements summary.");
modCommandsPrintf("sens");
modCommandsPrintf(" Print all sensor values.");
modCommandsPrintf("cells");
modCommandsPrintf(" Print cell voltage measurements.");
modCommandsPrintf("config");
modCommandsPrintf(" Print BMS configuration.");
modCommandsPrintf("config_default");
modCommandsPrintf(" Load default BMS configuration.");
modCommandsPrintf("config_write");
modCommandsPrintf(" Store current BMS configuration to EEPROM.");
modCommandsPrintf("config_read");
modCommandsPrintf(" Read BMS configuration from EEPROM.");
modCommandsPrintf("hwinfo");
modCommandsPrintf(" Print some hardware information.");
modCommandsPrintf("GSM");
modCommandsPrintf(" Print some GSM information.");
modCommandsPrintf("setUnixTime [Value]");
modCommandsPrintf(" Set RTC Time from TimeStamp. [Value] - uint64 unixtime value ");
modCommandsPrintf("checkUnixTime");
modCommandsPrintf(" Check actual RTC time ");
modCommandsPrintf("setSerialNumber [Value]");
modCommandsPrintf(" Set Serial [Value] - uint64 value ");
modCommandsPrintf("checkSerialNumber");
modCommandsPrintf(" Check actual Serial ");
modCommandsPrintf("SDcard");
modCommandsPrintf(" Switch to SD storage");
for (int i = 0;i < callback_write;i++) {
if (callbacks[i].arg_names) {
modCommandsPrintf("%s %s", callbacks[i].command, callbacks[i].arg_names);
} else {
modCommandsPrintf(callbacks[i].command);
}
if (callbacks[i].help) {
modCommandsPrintf(" %s", callbacks[i].help);
} else {
modCommandsPrintf(" There is no help available for this command.");
}
}
modCommandsPrintf(" ");
} else if (strcmp(argv[0], "GSM") == 0) {
uint8_t cellPointer = 0;
modCommandsPrintf("----- GSM STATE -----");
modCommandsPrintf("GPRS Connected : %d ", SIM800_Struct.Sim_Main_States.GPRS_Established);
ptr = &SIM800_Struct.Sim_Answer.SIM_answer[0];
modCommandsPrintf("Last received msg : %s ", ptr);
modCommandsPrintf("----- End GSM STATE -----");
modCommandsPrintf(" ");
}else if (strcmp(argv[0], "setUnixTime") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- set Unix Time -----");
time_t Time_rcvd;
Time_rcvd = strtol(argv[1], NULL, 16);
tm_PC_Time = *(localtime(&Time_rcvd));
if(Time_rcvd < 0x386D4380){
PC_time.year = 0;
PC_time.month = 1;
PC_time.day = 1;
PC_time.hour = 0;
PC_time.minute = 0;
PC_time.second = 0;
} else {
PC_time.year = tm_PC_Time.tm_year+1900-2000;
PC_time.month = tm_PC_Time.tm_mon+1;
PC_time.day = tm_PC_Time.tm_mday;
PC_time.hour = tm_PC_Time.tm_hour;
PC_time.minute = tm_PC_Time.tm_min;
PC_time.second = tm_PC_Time.tm_sec;
}
RTC_Set_Values(&PC_time);
// print temperatures
modCommandsPrintf("RTC Updated!");
modCommandsPrintf("Actual RTC:");
modCommandsPrintf("Year : %d", PC_time.year);
modCommandsPrintf("Month : %d", PC_time.month);
modCommandsPrintf("Day : %d", PC_time.day);
modCommandsPrintf("Hours : %d", PC_time.hour);
modCommandsPrintf("Minutes : %d", PC_time.minute);
modCommandsPrintf("Seconds : %d", PC_time.second);
modCommandsPrintf(" ");
}else if (strcmp(argv[0], "checkUnixTime") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- check Unix Time -----");
RTC_Get_Values(&PC_time);
modCommandsPrintf("Actual RTC:");
modCommandsPrintf("Year : %d", PC_time.year);
modCommandsPrintf("Month : %d", PC_time.month);
modCommandsPrintf("Day : %d", PC_time.day);
modCommandsPrintf("Hours : %d", PC_time.hour);
modCommandsPrintf("Minutes : %d", PC_time.minute);
modCommandsPrintf("Seconds : %d", PC_time.second);
modCommandsPrintf("----- end Unix Time -----");
modCommandsPrintf(" ");
}
else if (strcmp(argv[0], "checkSerialNumber") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- check Serial -----");
modCommandsPrintf("Actual Serial:");
modCommandsPrintf("Serial : %lu %lu", generalConfig->serialNumber);
modCommandsPrintf("Serial : %.8f", generalConfig->notUsedCurrentThreshold);
modCommandsPrintf("----- end Serial -----");
modCommandsPrintf(" ");
}
else if (strcmp(argv[0], "setSerialNumber") == 0) {
modCommandsPrintf(" ");
modCommandsPrintf("----- Set Serial -----");
NewSerial = strtol(argv[1], NULL, 10);
generalConfig->serialNumber = NewSerial;
modCommandsPrintf("New Serial : %lu %lu", NewSerial);
modCommandsPrintf("----- end Serial -----");
modCommandsPrintf(" ");
}
else if (strcmp(argv[0], "SDcard") == 0) {
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR11, 1);
jumpBootloaderTrue = 1;
}
else {
bool found = false;
for (int i = 0;i < callback_write;i++) {
if (strcmp(argv[0], callbacks[i].command) == 0) {
callbacks[i].cbf(argc, (const char**)argv);
found = true;
break;
}
}
if (!found) {
modCommandsPrintf("Invalid command: %s\n type help to list all available commands\n", argv[0]);
}
}
}
/**
* Register a custom command callback to the terminal. If the command
* is already registered the old command callback will be replaced.
*
* @param command
* The command name.
*
* @param help
* A help text for the command. Can be NULL.
*
* @param arg_names
* The argument names for the command, e.g. [arg_a] [arg_b]
* Can be NULL.
*
* @param cbf
* The callback function for the command.
*/
void modTerminalRegisterCommandCallBack(
const char* command,
const char *help,
const char *arg_names,
void(*cbf)(int argc, const char **argv)) {
int callback_num = callback_write;
for (int i = 0;i < callback_write;i++) {
// First check the address in case the same callback is registered more than once.
if (callbacks[i].command == command) {
callback_num = i;
break;
}
// Check by string comparison.
if (strcmp(callbacks[i].command, command) == 0) {
callback_num = i;
break;
}
}
callbacks[callback_num].command = command;
callbacks[callback_num].help = help;
callbacks[callback_num].arg_names = arg_names;
callbacks[callback_num].cbf = cbf;
if (callback_num == callback_write) {
callback_write++;
if (callback_write >= CALLBACK_LEN) {
callback_write = 0;
}
}
}
/*
defaultConfig.cellBalanceDifferenceThreshold = 0.01f; // Start balancing @ 5mV difference, stop if below
*/