Skip to content

Commit

Permalink
Merge pull request #1863 from MichaelDvP/dev
Browse files Browse the repository at this point in the history
add CMD to api/mqtt to show it in ioBroker, etc.
  • Loading branch information
proddy authored Jul 15, 2024
2 parents 96bb220 + ce33ec4 commit 686ed20
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 45 deletions.
2 changes: 1 addition & 1 deletion interface/src/project/Sensors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ const Sensors: FC = () => {
onClose={onTemperatureDialogClose}
onSave={onTemperatureDialogSave}
selectedItem={selectedTemperatureSensor}
validator={temperatureSensorItemValidation()}
validator={temperatureSensorItemValidation(sensorData.ts)}
/>
)}
{sensorData?.analog_enabled === true && (
Expand Down
57 changes: 43 additions & 14 deletions interface/src/project/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import type {
DeviceValue,
EntityItem,
ScheduleItem,
Settings
Settings,
TemperatureSensor
} from './types';

export const GPIO_VALIDATOR = {
Expand Down Expand Up @@ -288,8 +289,8 @@ export const uniqueNameValidator = (schedule: ScheduleItem[], o_name?: string) =
) {
if (
name !== '' &&
(o_name === undefined || o_name !== name) &&
schedule.find((si) => si.name === name)
(o_name === undefined || o_name.toLowerCase() !== name.toLowerCase()) &&
schedule.find((si) => si.name.toLowerCase() === name.toLowerCase())
) {
callback('Name already in use');
} else {
Expand All @@ -306,8 +307,8 @@ export const schedulerItemValidation = (
name: [
{
type: 'string',
pattern: /^[a-zA-Z0-9_\\.]{0,15}$/,
message: "Must be <15 characters: alpha numeric, '_' or '.'"
pattern: /^[a-zA-Z0-9_\\.]{0,19}$/,
message: "Must be <20 characters: alpha numeric, '_' or '.'"
},
...[uniqueNameValidator(schedule, scheduleItem.o_name)]
],
Expand All @@ -332,8 +333,8 @@ export const uniqueCustomNameValidator = (
callback: (error?: string) => void
) {
if (
(o_name === undefined || o_name !== name) &&
entity.find((ei) => ei.name === name)
(o_name === undefined || o_name.toLowerCase() !== name.toLowerCase()) &&
entity.find((ei) => ei.name.toLowerCase() === name.toLowerCase())
) {
callback('Name already in use');
} else {
Expand All @@ -348,8 +349,8 @@ export const entityItemValidation = (entity: EntityItem[], entityItem: EntityIte
{ required: true, message: 'Name is required' },
{
type: 'string',
pattern: /^[a-zA-Z0-9_\\.]{1,15}$/,
message: "Must be <15 characters: alpha numeric, '_' or '.'"
pattern: /^[a-zA-Z0-9_\\.]{1,19}$/,
message: "Must be <20 characters: alpha numeric, '_' or '.'"
},
...[uniqueCustomNameValidator(entity, entityItem.o_name)]
],
Expand Down Expand Up @@ -387,14 +388,25 @@ export const entityItemValidation = (entity: EntityItem[], entityItem: EntityIte
]
});

export const temperatureSensorItemValidation = () =>
export const uniqueTemperatureNameValidator = (sensors: TemperatureSensor[]) => ({
validator(rule: InternalRuleItem, n: string, callback: (error?: string) => void) {
if (n !== '' && sensors.find((ts) => ts.n.toLowerCase() === n.toLowerCase())) {
callback('Name already in use');
} else {
callback();
}
}
});

export const temperatureSensorItemValidation = (sensors: TemperatureSensor[]) =>
new Schema({
n: [
{
type: 'string',
pattern: /^[a-zA-Z0-9_\\.]{0,17}$/,
message: "Must be <18 characters: alpha numeric, '_' or '.'"
}
pattern: /^[a-zA-Z0-9_\\.]{0,19}$/,
message: "Must be <20 characters: alpha numeric, '_' or '.'"
},
...[uniqueTemperatureNameValidator(sensors)]
]
});

Expand All @@ -412,13 +424,30 @@ export const isGPIOUniqueValidator = (sensors: AnalogSensor[]) => ({
}
});

export const uniqueAnalogNameValidator = (sensors: AnalogSensor[]) => ({
validator(rule: InternalRuleItem, n: string, callback: (error?: string) => void) {
if (n !== '' && sensors.find((as) => as.n.toLowerCase() === n.toLowerCase())) {
callback('Name already in use');
} else {
callback();
}
}
});

export const analogSensorItemValidation = (
sensors: AnalogSensor[],
creating: boolean,
platform: string
) =>
new Schema({
n: [{ required: true, message: 'Name is required' }],
n: [
{
type: 'string',
pattern: /^[a-zA-Z0-9_\\.]{0,19}$/,
message: "Must be <20 characters: alpha numeric, '_' or '.'"
},
...[uniqueAnalogNameValidator(sensors)]
],
g: [
{ required: true, message: 'GPIO is required' },
platform === 'ESP32-S3'
Expand Down
6 changes: 3 additions & 3 deletions src/analogsensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int
}
}

return EMSESP::return_not_found(output, "analog sensor", cmd); // not found
return EMSESP::return_not_found(output, cmd, F_(analogsensor)); // not found
}

void AnalogSensor::addSensorJson(JsonObject output, const Sensor & sensor) {
Expand Down Expand Up @@ -759,8 +759,8 @@ AnalogSensor::Sensor::Sensor(const uint8_t gpio, const std::string & name, const
// returns name of the analog sensor or creates one if its empty
std::string AnalogSensor::Sensor::name() const {
if (name_.empty()) {
char name[50];
snprintf(name, sizeof(name), "Analog Sensor GPIO %02d", gpio_);
char name[20];
snprintf(name, sizeof(name), "%s_%02d", FL_(AnalogTypeName)[type_], gpio_);
return name;
}
return name_;
Expand Down
3 changes: 3 additions & 0 deletions src/analogsensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@

namespace emsesp {

// names, same order as AnalogType
MAKE_ENUM_FIXED(AnalogTypeName, "disabled", "dig_in", "counter", "adc", "timer", "rate", "pwm0", "pwm1", "pwm2")

class AnalogSensor {
public:
class Sensor {
Expand Down
20 changes: 11 additions & 9 deletions src/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,17 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char *

// determine flags based on id (which is the tag)
uint8_t flag = CommandFlag::CMD_FLAG_DEFAULT;
int8_t tag = id;
if (tag >= DeviceValueTAG::TAG_HC1 && tag <= DeviceValueTAG::TAG_HC8) {
flag = CommandFlag::CMD_FLAG_HC;
} else if (tag >= DeviceValueTAG::TAG_DHW1 && tag <= DeviceValueTAG::TAG_DHW10) {
flag = CommandFlag::CMD_FLAG_DHW;
} else if (tag >= DeviceValueTAG::TAG_HS1 && tag <= DeviceValueTAG::TAG_HS16) {
flag = CommandFlag::CMD_FLAG_HS;
} else if (tag >= DeviceValueTAG::TAG_AHS1 && tag <= DeviceValueTAG::TAG_AHS1) {
flag = CommandFlag::CMD_FLAG_AHS;
// info and values works with all tags, keep it default
if (std::string(cmd) != F_(values) && std::string(cmd) != F_(info)) {
if (id >= DeviceValueTAG::TAG_HC1 && id <= DeviceValueTAG::TAG_HC8) {
flag = CommandFlag::CMD_FLAG_HC;
} else if (id >= DeviceValueTAG::TAG_DHW1 && id <= DeviceValueTAG::TAG_DHW10) {
flag = CommandFlag::CMD_FLAG_DHW;
} else if (id >= DeviceValueTAG::TAG_HS1 && id <= DeviceValueTAG::TAG_HS16) {
flag = CommandFlag::CMD_FLAG_HS;
} else if (id >= DeviceValueTAG::TAG_AHS1 && id <= DeviceValueTAG::TAG_AHS1) {
flag = CommandFlag::CMD_FLAG_AHS;
}
}

// first see if there is a command registered and it's valid
Expand Down
26 changes: 17 additions & 9 deletions src/emsdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,6 @@ void EMSdevice::add_device_value(int8_t tag, // to b
uint32_t max // max allowed value
) {
// initialize the device value depending on it's type
// ignoring DeviceValueType::CMD

if (type == DeviceValueType::STRING) {
*(char *)(value_p) = {'\0'}; // this is important for string functions like strlen() to work later
Expand Down Expand Up @@ -1549,12 +1548,16 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t
break;

case DeviceValueType::CMD:
json[type] = F_(command);
if (dv.options_size > 1) {
json[type] = F_(enum);
JsonArray enum_ = json[F_(enum)].to<JsonArray>();
for (uint8_t i = 0; i < dv.options_size; i++) {
enum_.add(Helpers::translated_word(dv.options[i]));
}
} else if (dv.uom != DeviceValueUOM::NONE) {
json[type] = F_(number);
} else {
json[type] = F_(command);
}
break;

Expand Down Expand Up @@ -1585,10 +1588,11 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t
// TODO refactor to remove containsKey as it's costly and not advisable to use it
// https://arduinojson.org/v7/api/jsonobject/containskey/#avoid

// commented out, leads to issues if type is set to number
// if there is no value, mention it
if (!json.containsKey(value)) {
json[value] = "not set";
}
// if (!json.containsKey(value)) {
// json[value] = "not set";
// }

// if we're filtering on an attribute, go find it
if (attribute_s) {
Expand Down Expand Up @@ -1756,10 +1760,14 @@ bool EMSdevice::generate_values(JsonObject output, const int8_t tag_filter, cons
}
}

// commenting out as we don't want Commands in Console ('show values')
// else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::MQTT) {
// json[name] = "";
// }
// we don't want Commands in Console ('show values')
else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::CONSOLE) {
if (dv.uom == DeviceValueUOM::NONE) {
json[name] = "";
} else {
json[name] = NAN;
}
}

// check for value outside min/max range and adapt the limits to avoid HA complains
// Should this also check for api output?
Expand Down
2 changes: 1 addition & 1 deletion src/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,7 +1302,7 @@ bool System::get_value_info(JsonObject root, const char * command) {
}

char cmd[COMMAND_MAX_LENGTH];
strlcpy(cmd, command, sizeof(cmd));
strlcpy(cmd, Helpers::toLower(command).c_str(), sizeof(cmd));
char * val = strstr(cmd, "/value");
if (val) {
val[0] = '\0';
Expand Down
2 changes: 1 addition & 1 deletion src/temperaturesensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons
}
}

return EMSESP::return_not_found(output, "temperature sensor", cmd); // not found
return EMSESP::return_not_found(output, cmd, F_(temperaturesensor)); // not found
}

void TemperatureSensor::addSensorJson(JsonObject output, const Sensor & sensor) {
Expand Down
2 changes: 1 addition & 1 deletion src/web/WebCustomEntityService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd)
}
}

return EMSESP::return_not_found(output, "custom entity", cmd); // not found
return EMSESP::return_not_found(output, cmd, F_(custom)); // not found
}

// publish single value
Expand Down
8 changes: 2 additions & 6 deletions src/web/WebSchedulerService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
}
}

if (output.size()) {
return true;
}

return EMSESP::return_not_found(output, "schedule", cmd); // not found
return true;
}

char command_s[COMMAND_MAX_LENGTH];
Expand Down Expand Up @@ -210,7 +206,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) {
return true;
}

return EMSESP::return_not_found(output, "schedule", cmd); // not found
return EMSESP::return_not_found(output, cmd, F_(scheduler)); // not found
}

// publish single value
Expand Down

0 comments on commit 686ed20

Please sign in to comment.