command default id=-1, command_check, add "warm water" to long names

This commit is contained in:
MichaelDvP
2021-05-10 15:30:10 +02:00
parent 5cccfacbc4
commit a9fca73f2d
10 changed files with 101 additions and 46 deletions

View File

@@ -69,7 +69,7 @@ void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVari
}
// make sure we have a value. There must always be a value
if (!body.containsKey("value")) {
if (!body.containsKey(F_(value))) {
send_message_response(request, 400, "Problems parsing JSON"); // Bad Request
return;
}
@@ -114,8 +114,8 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_
if (request->hasParam(F_(data))) {
value_s = request->getParam(F_(data))->value().c_str();
}
if (request->hasParam("value")) {
value_s = request->getParam("value")->value().c_str();
if (request->hasParam(F_(value))) {
value_s = request->getParam(F_(value))->value().c_str();
}
// get id (or hc), which is optional
@@ -134,15 +134,15 @@ void WebAPIService::parse(AsyncWebServerRequest * request, std::string & device_
auto num_paths = p.paths().size();
if (num_paths == 1) {
// if there are no more paths parameters, default to 'info'
cmd_s = "info_short";
// cmd_s = "info_short";
// check empty command in Command::find_command and set the default there!
} else if (num_paths == 2) {
cmd_s = p.paths()[1];
} else if (num_paths > 2) {
// command-check makes prefix to TAG
// check in Command::find_command makes prefix to TAG
cmd_s = p.paths()[1] + "/" + p.paths()[2];
}
}
// now go and validate everything
// device check

View File

@@ -30,14 +30,13 @@ std::vector<Command::CmdFunction> Command::cmdfunctions_;
// id may be used to represent a heating circuit for example, it's optional
// returns false if error or not found
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id) {
std::string dname = EMSdevice::device_type_2_device_name(device_type);
int8_t id_new = id;
char cmd_new[20];
int8_t id_new = id;
char cmd_new[20] = {'\0'};
strlcpy(cmd_new, cmd, 20);
check_command(cmd_new, cmd, id_new);
auto cf = find_command(device_type, cmd_new);
auto cf = find_command(device_type, cmd_new, id_new);
if ((cf == nullptr) || (cf->cmdfunction_json_)) {
LOG_WARNING(F("Command %s on %s not found"), cmd, dname.c_str());
LOG_WARNING(F("Command %s on %s not found"), cmd, EMSdevice::device_type_2_device_name(device_type).c_str());
return false; // command not found, or requires a json
}
@@ -58,11 +57,11 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
// id may be used to represent a heating circuit for example
// returns false if error or not found
bool Command::call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json) {
int8_t id_new = id;
char cmd_new[20];
int8_t id_new = id;
char cmd_new[20] = {'\0'};
strlcpy(cmd_new, cmd, 20);
check_command(cmd_new, cmd, id_new);
auto cf = find_command(device_type, cmd_new);
auto cf = find_command(device_type, cmd_new, id_new);
#ifdef EMSESP_DEBUG
std::string dname = EMSdevice::device_type_2_device_name(device_type);
@@ -95,18 +94,27 @@ bool Command::call(const uint8_t device_type, const char * cmd, const char * val
}
}
// set the id if there are prefixes
char * Command::check_command(char * out, const char * cmd, int8_t & id) {
// strip prefixes, check, and find command
Command::CmdFunction * Command::find_command(const uint8_t device_type, char * cmd, int8_t & id) {
// no command for id0
if (id == 0) {
return nullptr;
}
// empty command is info with id0 or info_short
if (cmd[0] == '\0') {
// strcpy(cmd, "info_short");
strcpy(cmd, "info");
id = 0;
}
// convert cmd to lowercase
strlcpy(out, cmd, 20);
for (char * p = out; *p; p++) {
for (char * p = cmd; *p; p++) {
*p = tolower(*p);
}
// scan for prefix hc.
for (uint8_t i = DeviceValueTAG::TAG_HC1; i <= DeviceValueTAG::TAG_HC4; i++) {
if ((strncmp(out, EMSdevice::tag_to_string(i).c_str(), 3) == 0) && (strlen(out) > 4)) {
strcpy(out, &out[4]);
if ((strncmp(cmd, EMSdevice::tag_to_string(i).c_str(), 3) == 0) && (strlen(cmd) > 3)) {
strcpy(cmd, &cmd[4]);
id = 1 + i - DeviceValueTAG::TAG_HC1;
break;
}
@@ -114,14 +122,19 @@ char * Command::check_command(char * out, const char * cmd, int8_t & id) {
// scan for prefix wwc.
for (uint8_t i = DeviceValueTAG::TAG_WWC1; i <= DeviceValueTAG::TAG_WWC4; i++) {
if ((strncmp(out, EMSdevice::tag_to_string(i).c_str(), 4) == 0) && (strlen(out) > 5)) {
strcpy(out, &out[5]);
if ((strncmp(cmd, EMSdevice::tag_to_string(i).c_str(), 4) == 0) && (strlen(cmd) > 4)) {
strcpy(cmd, &cmd[5]);
id = 8 + i - DeviceValueTAG::TAG_WWC1;
break;
}
}
return out;
// empty command after processing prefix is info
if (cmd[0] == '\0') {
strlcpy(cmd, "info", 20);
}
return find_command(device_type ,cmd);
}
// add a command to the list, which does not return json
@@ -196,7 +209,11 @@ bool Command::list(const uint8_t device_type, JsonObject & json) {
for (auto & cl : sorted_cmds) {
for (const auto & cf : cmdfunctions_) {
if ((cf.device_type_ == device_type) && !cf.hidden_ && cf.description_ && (cl == uuid::read_flash_string(cf.cmd_))) {
json[cl] = cf.description_;
if (cf.flag_ == FLAG_WW) {
json[cl] = EMSdevice::tag_to_string(TAG_DEVICE_DATA_WW) + " " + uuid::read_flash_string(cf.description_);
} else {
json[cl] = cf.description_;
}
}
}
}
@@ -233,16 +250,28 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo
// verbose mode
shell.println();
for (auto & cl : sorted_cmds) {
shell.print(" ");
shell.print(cl);
// find and print the description
for (const auto & cf : cmdfunctions_) {
if ((cf.device_type_ == device_type) && !cf.hidden_ && cf.description_ && (cl == uuid::read_flash_string(cf.cmd_))) {
uint8_t i = cl.length();
shell.print(" ");
if (cf.flag_ == FLAG_HC) {
shell.print("[hc] ");
i += 5;
} else if (cf.flag_ == FLAG_WWC) {
shell.print("[wwc] ");
i += 6;
}
shell.print(cl);
// pad with spaces
for (uint8_t i = cl.length(); i++ < 22;) {
while (i++ < 22) {
shell.print(' ');
}
shell.print(COLOR_BRIGHT_CYAN);
if (cf.flag_ == FLAG_WW) {
shell.print(EMSdevice::tag_to_string(TAG_DEVICE_DATA_WW));
shell.print(' ');
}
shell.print(uuid::read_flash_string(cf.description_));
shell.print(COLOR_RESET);
}

View File

@@ -70,13 +70,13 @@ class Command {
}
static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id, JsonObject & json);
static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id = 0);
static bool call(const uint8_t device_type, const char * cmd, const char * value, const int8_t id = -1);
static void add(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_p cb, const __FlashStringHelper * description, uint8_t flag = 0);
static void
add_with_json(const uint8_t device_type, const __FlashStringHelper * cmd, cmdfunction_json_p cb, const __FlashStringHelper * description, bool hidden = false);
static void show_all(uuid::console::Shell & shell);
static Command::CmdFunction * find_command(const uint8_t device_type, const char * cmd);
static char * check_command(char * out, const char * cmd, int8_t & id);
static Command::CmdFunction * find_command(const uint8_t device_type, char * cmd, int8_t & id);
static void show(uuid::console::Shell & shell, uint8_t device_type, bool verbose);
static void show_devices(uuid::console::Shell & shell);

View File

@@ -373,8 +373,18 @@ void EMSESPShell::add_console_commands() {
return;
}
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN);
JsonObject json = doc.to<JsonObject>();
bool ok = false;
// validate the command
if (arguments.size() < 2) {
// no cmd specified, default to empty command
if (Command::call(device_type, "", "", -1, json)) {
serializeJsonPretty(doc, shell);
shell.println();
return;
}
shell.print(F("Missing command. Available commands are: "));
Command::show(shell, device_type, false); // non-verbose mode
return;
@@ -382,10 +392,6 @@ void EMSESPShell::add_console_commands() {
const char * cmd = arguments[1].c_str();
DynamicJsonDocument doc(EMSESP_JSON_SIZE_XLARGE_DYN);
JsonObject json = doc.to<JsonObject>();
bool ok = false;
if (arguments.size() == 2) {
// no value specified, just the cmd
ok = Command::call(device_type, cmd, nullptr, -1, json);

View File

@@ -44,8 +44,6 @@ using uuid::log::Level;
#define LOG_WARNING(...) logger_.warning(__VA_ARGS__)
#define LOG_ERROR(...) logger_.err(__VA_ARGS__)
#define MQTT_TOPIC(list_name) (__pstr__##list_name[0])
// clang-format off
// strings stored 32 bit aligned on ESP8266/ESP32
#define MAKE_PSTR(string_name, string_literal) static const char __pstr__##string_name[] __attribute__((__aligned__(sizeof(uint32_t)))) PROGMEM = string_literal;

View File

@@ -134,6 +134,7 @@ void DallasSensor::loop() {
int16_t t;
t = get_temperature_c(addr);
if ((t >= -550) && (t <= 1250)) {
sensorreads_++;
// check if we have this sensor already
bool found = false;
for (auto & sensor : sensors_) {
@@ -322,7 +323,7 @@ bool DallasSensor::command_commands(const char * value, const int8_t id, JsonObj
// returns false if empty
// e.g. dallassensor_data = {"sensor1":{"id":"28-EA41-9497-0E03-5F","temp":23.30},"sensor2":{"id":"28-233D-9497-0C03-8B","temp":24.0}}
bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject & json) {
if (sensors_.size() == 0 || id != -1) {
if (sensors_.size() == 0) {
return false;
}
@@ -330,10 +331,18 @@ bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject
for (const auto & sensor : sensors_) {
char sensorID[10]; // sensor{1-n}
snprintf_P(sensorID, 10, PSTR("sensor%d"), i++);
if (Mqtt::dallas_format() == Mqtt::Dallas_Format::SENSORID && Helpers::hasValue(sensor.temperature_c)) {
json[sensor.to_string()] = (float)(sensor.temperature_c) / 10;
} else if (Helpers::hasValue(sensor.temperature_c)) {
json[sensorID] = (float)(sensor.temperature_c) / 10;
if (id == -1) { // show number and id
JsonObject dataSensor = json.createNestedObject(sensorID);
dataSensor["id"] = sensor.to_string();
if (Helpers::hasValue(sensor.temperature_c)) {
dataSensor["temp"] = (float)(sensor.temperature_c) / 10;
}
} else { // show according to format
if (Mqtt::dallas_format() == Mqtt::Dallas_Format::SENSORID && Helpers::hasValue(sensor.temperature_c)) {
json[sensor.to_string()] = (float)(sensor.temperature_c) / 10;
} else if (Helpers::hasValue(sensor.temperature_c)) {
json[sensorID] = (float)(sensor.temperature_c) / 10;
}
}
}

View File

@@ -64,6 +64,10 @@ class DallasSensor {
const std::vector<Sensor> sensors() const;
uint32_t reads() {
return sensorreads_;
}
uint32_t fails() {
return sensorfails_;
}
@@ -128,6 +132,7 @@ class DallasSensor {
bool parasite_ = false;
bool changed_ = false;
uint32_t sensorfails_ = 0;
uint32_t sensorreads_ = 0;
int8_t scanretry_ = 0;
};

View File

@@ -492,6 +492,10 @@ void EMSdevice::register_device_value(uint8_t tag,
if (f != nullptr) {
if (tag >= TAG_HC1 && tag <= TAG_HC4) {
Command::add(device_type_, name[0], f, name[1], FLAG_HC);
} else if (tag >= TAG_WWC1 && tag <= TAG_WWC4) {
Command::add(device_type_, name[0], f, name[1], FLAG_WWC);
} else if (tag == TAG_DEVICE_DATA_WW) {
Command::add(device_type_, name[0], f, name[1], FLAG_WW);
} else {
Command::add(device_type_, name[0], f, name[1], 0);
}
@@ -687,7 +691,11 @@ bool EMSdevice::get_value_info(JsonObject & root, const char * cmd, const int8_t
json["name"] = dv.short_name;
if (dv.full_name != nullptr) {
json["fullname"] = dv.full_name;
if (dv.tag == TAG_DEVICE_DATA_WW) {
json["fullname"] = tag_to_string(dv.tag) + " " + uuid::read_flash_string(dv.full_name);
} else {
json["fullname"] = dv.full_name;
}
}
if (!tag_to_mqtt(dv.tag).empty()) {
json["circuit"] = tag_to_mqtt(dv.tag);

View File

@@ -94,7 +94,7 @@ enum DeviceValueTAG : uint8_t {
};
// mqtt flags for command subscriptions
enum MqttSubFlag : uint8_t { FLAG_NORMAL = 0, FLAG_HC, FLAG_WWC, FLAG_NOSUB };
enum MqttSubFlag : uint8_t { FLAG_NORMAL = 0, FLAG_HC, FLAG_WWC, FLAG_WW, FLAG_NOSUB };
// mqtt-HA flags
enum DeviceValueHA : uint8_t { HA_NONE = 0, HA_VALUE, HA_DONE };

View File

@@ -1008,7 +1008,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & json, const int8_t i
tag = DeviceValueTAG::TAG_HC1 + id - 1;
} else if (id >= 9 && id <= 10) {
tag = DeviceValueTAG::TAG_WWC1 + id - 9;
} else if (id == -1) {
} else if (id == -1 || id == 0) {
tag = DeviceValueTAG::TAG_NONE;
} else {
return false;
@@ -1017,7 +1017,7 @@ bool EMSESP::command_info(uint8_t device_type, JsonObject & json, const int8_t i
for (const auto & emsdevice : emsdevices) {
if (emsdevice && (emsdevice->device_type() == device_type)
&& ((device_type != DeviceType::THERMOSTAT) || (emsdevice->device_id() == EMSESP::actual_master_thermostat()))) {
has_value |= emsdevice->generate_values_json(json, tag, (id == -1), verbose); // nested for id -1,0 & console for id -1
has_value |= emsdevice->generate_values_json(json, tag, (id < 1), verbose && (id == -1)); // nested for id -1,0 & console for id -1
}
}