#include #include #include #include #include #include static bool showConfigCmd(uint8_t argc, char **args) { bool retCode = true; t_configBlock configBlock; eepromReadConfigBlock(&configBlock); sendString("This is the saved configuration.\n\r"); sendString("It is not necessarily the active configuration.\n\r"); sendFormatString("configMagic: %lx\n\r", configBlock.configMagic); sendFormatString("deviceName: %s\n\r", configBlock.deviceName); sendFormatString("MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n\r", configBlock.macAddress[0], configBlock.macAddress[1], configBlock.macAddress[2], configBlock.macAddress[3], configBlock.macAddress[4], configBlock.macAddress[5]); sendFormatString("frontend threshold: %ld\n\r", configBlock.frontendThreshold); sendFormatString("broker: %s\n\r", configBlock.brokerName); sendFormatString("watchdogTopic: %s\n\r", configBlock.watchdogTopic); sendFormatString("startupTopic: %s\n\r", configBlock.startupTopic); sendFormatString("statusTopic: %s\n\r", configBlock.statusTopic); sendFormatString("mbusDataTopic: %s\n\r", configBlock.mbusDataTopic); sendFormatString("syslog server: %s\n\r", configBlock.syslogServerName); sendFormatString("device block cnt: %d\n\r", configBlock.numOfDeviceBlocks); for (uint8_t i = 0; i < configBlock.numOfDeviceBlocks; i++) { t_deviceBlock tmpDeviceBlock; eepromReadDeviceBlock(i, &tmpDeviceBlock); if (tmpDeviceBlock.deviceMagic == DEVICE_MAGIC) { sendFormatString("device %d: \n\r", i); sendFormatString(" Name: %s, Address: %d, Period: %d\n\r", tmpDeviceBlock.deviceName, tmpDeviceBlock.address, tmpDeviceBlock.period); sendFormatString(" Considered Fields: %d %d %d %d\n\r", tmpDeviceBlock.consideredField[0], tmpDeviceBlock.consideredField[1], tmpDeviceBlock.consideredField[2], tmpDeviceBlock.consideredField[3]); if (tmpDeviceBlock.deviceMagic != DEVICE_MAGIC) { sendString(" DEVICE MAGIC DOES NOT MATCH\n\r"); } } } return retCode; } static bool setStringParameterCmd(uint8_t argc, char **args, size_t offset, size_t length) { bool retCode = true; t_configBlock configBlock; char *parameterName = args[1]; char *newParameterValue = args[2]; if (strlen(newParameterValue) >= length) { sendString("given new value for is too long\n\r"); retCode = false; } else { sendFormatString("set %s to %s\n\r", parameterName, newParameterValue); eepromReadConfigBlock(&configBlock); strcpy((((char*)&configBlock) + offset), newParameterValue); eepromWriteConfigBlock(&configBlock); } return retCode; } static bool setInt32ParameterCmd(uint8_t argc, char **args, size_t offset, int32_t minV, int32_t maxV) { bool retCode = true; t_configBlock configBlock; char *parameterName = args[1]; char *newParameterValue = args[2]; long int value = strtol(newParameterValue, NULL, 10); if (value < minV) { sendString("value is too small\n\r"); retCode = false; } else if (value > maxV) { sendString("value is too large\n\r"); } else { int32_t v = (int32_t) value; sendFormatString("set %s to %ld\n\r", parameterName, v); eepromReadConfigBlock(&configBlock); *((int32_t*)(((uint8_t*)&configBlock) + offset)) = v; eepromWriteConfigBlock(&configBlock); } return retCode; } static bool setDeviceNameCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, deviceName), sizeof(((t_configBlock*)0)->deviceName)); } static bool setBrokerNameCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, brokerName), sizeof(((t_configBlock*)0)->brokerName)); } static bool setSyslogServerCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, syslogServerName), sizeof(((t_configBlock*)0)->syslogServerName)); } static bool setWatchdogTopicCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, watchdogTopic), sizeof(((t_configBlock*)0)->watchdogTopic)); } static bool setStartupTopicCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, startupTopic), sizeof(((t_configBlock*)0)->startupTopic)); } static bool setStatusTopicCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, statusTopic), sizeof(((t_configBlock*)0)->statusTopic)); } static bool setMbusDataTopicCmd(uint8_t argc, char **args) { return setStringParameterCmd(argc, args, offsetof(t_configBlock, mbusDataTopic), sizeof(((t_configBlock*)0)->mbusDataTopic)); } static bool setFrontendThresholdCmd(uint8_t argc, char **args) { return setInt32ParameterCmd(argc, args, offsetof(t_configBlock, frontendThreshold), 0, 1023); } static bool makeDevice(uint8_t argOffset, uint8_t argc, char **args, t_deviceBlock *deviceBlock) { if (strcmp(args[1], "help") == 0) { sendString("deviceName address period field1 field2 field3 field4\n\r"); sendString("deviceName: max. length = 16\n\r"); sendString("address: between 1 and 254\n\r"); sendString("period: in seconds, between 0 (disabled) and 86400 (1 day)\n\r"); sendString("fields: between -1 (not considered) and 254\n\r"); return false; } if ((argc - argOffset) != 8) { sendString("wrong number of arguments\n\r"); return false; } char *deviceName = args[1 + argOffset]; if (strcmp(deviceName, "*") != 0) { if (strlen(deviceName) >= sizeof(deviceBlock->deviceName)) { sendString("devicename too long\n\r"); return false; } strcpy(deviceBlock->deviceName, deviceName); } char *rawAddressStr = args[2 + argOffset]; if (strcmp(rawAddressStr, "*") != 0) { long int rawAddress = strtol(rawAddressStr, NULL, 10); if (rawAddress < 1 || rawAddress > 254) { sendString("illegal address\n\r"); return false; } deviceBlock->address = (uint8_t)rawAddress; } char *rawPeriodStr = args[3 + argOffset]; if (strcmp(rawPeriodStr, "*") != 0) { long int rawPeriod = strtol(rawPeriodStr, NULL, 10); if (rawPeriod < 0 || rawPeriod > 86400) { sendString("illegal period\n\r"); return false; } deviceBlock->period = (int32_t) rawPeriod; } for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) { char *rawFieldNumStr = args[4 + i + argOffset]; if (strcmp(rawFieldNumStr, "*") != 0) { long int rawFieldNum = strtol(rawFieldNumStr, NULL, 10); if (rawFieldNum < -1 || rawFieldNum > 127) { sendString("illegal considered field index\n\r"); return false; } deviceBlock->consideredField[i] = (int8_t) rawFieldNum; } } return true; } static bool addDeviceCmd(uint8_t argc, char **args) { t_deviceBlock deviceBlock = { .deviceName = "", .address = 0, .period = 0, .consideredField = { -1, -1, -1, -1}}; bool retCode = makeDevice(0, argc, args, &deviceBlock); if (retCode) { sendString("New device would be:\n\r"); sendFormatString(" Name: %s, Address: %d, Period: %d\n\r", deviceBlock.deviceName, deviceBlock.address, deviceBlock.period); for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) { sendFormatString(" Considered field: %d\n\r", deviceBlock.consideredField[i]); } } return retCode; } static bool changeDeviceCmd(uint8_t argc, char **args) { if (strcmp(args[1], "help") == 0) { sendString("First argument: index of device in list\n\r"); sendFormatString("Between 0 and %d\n\r", getConfig()->numOfDeviceBlocks); sendString("For further arguments use a * to keep the value\n\r"); return makeDevice(0, argc, args, NULL); } long int rawIndex = strtol(args[1], NULL, 10); if (rawIndex < 0 || rawIndex > getConfig()->numOfDeviceBlocks) { sendFormatString("illegal index, must be greater 0 and less %d\n\r", getConfig()->numOfDeviceBlocks); return false; } uint8_t index = (uint8_t) rawIndex; t_deviceBlock deviceBlock; eepromReadDeviceBlock(index, &deviceBlock); bool retCode = makeDevice(1, argc, args, &deviceBlock); if (retCode) { sendString("Changed device would be:\n\r"); sendFormatString(" Index: %d\n\r", index); sendFormatString(" Name: %s, Address: %d, Period: %d\n\r", deviceBlock.deviceName, deviceBlock.address, deviceBlock.period); for (uint8_t i = 0; i < MBUSDEVICE_NUM_OF_CONSIDEREDFIELDS; i++) { sendFormatString(" Considered field: %d\n\r", deviceBlock.consideredField[i]); } } return retCode; } const static cmd_t SET_COMMANDS[] = { { .name = "devicename", .cmdFunc = setDeviceNameCmd, .help = \ "devicename ........................... Name of this device\n\r" }, { .name = "brokername", .cmdFunc = setBrokerNameCmd, .help = \ "brokername ........................... Hostname of the MQTT broker\n\r" }, { .name = "syslogserver", .cmdFunc = setSyslogServerCmd, .help = \ "syslogserver ......................... Hostname of the Syslog server\n\r" }, { .name = "watchdogtopic", .cmdFunc = setWatchdogTopicCmd, .help = \ "watchdogtopic ........................ Watchdog Topic\n\r" }, { .name = "startuptopic", .cmdFunc = setStartupTopicCmd, .help = \ "startuptopic ......................... Startup Topic\n\r" }, { .name = "statustopic", .cmdFunc = setStatusTopicCmd, .help = \ "statustopic .......................... Status Topic\n\r" }, { .name = "mbusdatatopic", .cmdFunc = setMbusDataTopicCmd, .help = \ "mbusdatatopic ........................ MBus Data Topic\n\r" }, { .name = "frontendthreshold", .cmdFunc = setFrontendThresholdCmd, .help = \ "frontendthreshold .................... Frontend Threshold (default: 240)\n\r" }, { .name = "END_OF_CMDS", .help = "",.cmdFunc = NULL } }; const static char UNKNOWN_PARAMETER[] = "unknown parameter\n\r"; const static char OK_MSG[] = "OK\n\r"; const static char FAILED_MSG[] = "Failed\n\r"; static bool setCmd(uint8_t argc, char **args) { bool retCode = false; uint8_t *messageToSend = NULL; char *cmd = args[1]; if (argc >= 2) { if (0 == strcmp("help", cmd)) { sendString("You can set the following parameters:\n\r"); uint8_t cmdIdx = 0; while (true) { cmd_t command = SET_COMMANDS[cmdIdx]; if (0 == strcmp("END_OF_CMDS", command.name)) { break; } sendString(command.help); cmdIdx++; } retCode = true; } else { uint8_t cmdIdx = 0; while (true) { cmd_t command = SET_COMMANDS[cmdIdx]; if (0 == strcmp("END_OF_CMDS", command.name)) { messageToSend = (uint8_t*) UNKNOWN_PARAMETER; break; } if (0 == strcmp(cmd, command.name)) { retCode = command.cmdFunc(argc, args); messageToSend = retCode ? (uint8_t*)OK_MSG : (uint8_t*)FAILED_MSG; sendString("Remember you need to restart to active this change.\n\r"); break; } cmdIdx++; } sendString((const char*)messageToSend); } } return retCode; } static bool restartCmd(uint8_t argc, char **args) { HAL_NVIC_SystemReset(); // you won't come here ... return true; } const cmd_t CONFIG_COMMANDS[] = { { .name = "show", .cmdFunc = showConfigCmd, .help = \ "show ................................. Show the configuration\n\r" }, { .name = "set", .cmdFunc = setCmd, .help = \ "set .................................. Set configuration parameters\n\r" \ " Argument help gives a list of \n\r" \ " parameters\n\r" }, { .name = "addDevice", .cmdFunc = addDeviceCmd, .help = \ "addDevice ............................ Add a new device to the end of the list\n\r" }, { .name = "changeDevice", .cmdFunc = changeDeviceCmd, .help = \ "changeDevice ......................... Change a new device by index\n\r" }, { .name = "restart", .cmdFunc = restartCmd, .help = \ "restart .............................. Restart the system,\n\r" \ " Required to reload config\n\r" }, { .name = "END_OF_CMDS", .help = "",.cmdFunc = NULL } }; const cmd_t *getConfigCommands() { return CONFIG_COMMANDS; }