mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-10-26 22:10:45 +00:00
[Build] Use static func. MQTT helper, NWPlugin Helper, NW import/export
This commit is contained in:
1 parent
ff9a7f6150
commit
412a9e64fb
7 files changed
+480
-468
No files matched your search
@@ -33,7 +33,7 @@
|
||||
namespace ESPEasy {
|
||||
namespace net {
|
||||
|
||||
ESPEasy_key_value_store_import_export::LabelStringFunction getLabelFnc(ESPEasy::net::nwpluginID_t nwpluginID)
|
||||
static ESPEasy_key_value_store_import_export::LabelStringFunction getLabelFnc(ESPEasy::net::nwpluginID_t nwpluginID)
|
||||
{
|
||||
|
||||
switch (nwpluginID.value)
|
||||
@@ -67,7 +67,7 @@ ESPEasy_key_value_store_import_export::LabelStringFunction getLabelFnc(ESPEasy::
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ESPEasy_key_value_store_import_export::NextKeyFunction getNextKeyFnc(ESPEasy::net::nwpluginID_t nwpluginID, bool includeCredentials)
|
||||
static ESPEasy_key_value_store_import_export::NextKeyFunction getNextKeyFnc(ESPEasy::net::nwpluginID_t nwpluginID, bool includeCredentials)
|
||||
{
|
||||
|
||||
switch (nwpluginID.value)
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace net {
|
||||
/*********************************************************************************************\
|
||||
* Functions to load and store network settings on the web page.
|
||||
\*********************************************************************************************/
|
||||
const __FlashStringHelper* toString(NetworkSettingsStruct::VarType parameterIdx, bool displayName)
|
||||
static const __FlashStringHelper* toString(NetworkSettingsStruct::VarType parameterIdx, bool displayName)
|
||||
{
|
||||
switch (parameterIdx)
|
||||
{
|
||||
@@ -61,16 +61,16 @@ String getNetworkParameterName(networkDriverIndex_t NetworkDriverIndex
|
||||
return name;
|
||||
}
|
||||
|
||||
String getNetworkParameterInternalName(networkDriverIndex_t NetworkDriverIndex, NetworkSettingsStruct::VarType parameterIdx) {
|
||||
static String getNetworkParameterInternalName(networkDriverIndex_t NetworkDriverIndex, NetworkSettingsStruct::VarType parameterIdx) {
|
||||
bool isAlternative; // Dummy, not needed for internal name
|
||||
bool displayName = false;
|
||||
|
||||
return getNetworkParameterName(NetworkDriverIndex, parameterIdx, displayName, isAlternative);
|
||||
}
|
||||
|
||||
String getNetworkParameterDisplayName(networkDriverIndex_t NetworkDriverIndex,
|
||||
NetworkSettingsStruct::VarType parameterIdx,
|
||||
bool & isAlternative) {
|
||||
static String getNetworkParameterDisplayName(networkDriverIndex_t NetworkDriverIndex,
|
||||
NetworkSettingsStruct::VarType parameterIdx,
|
||||
bool & isAlternative) {
|
||||
bool displayName = true;
|
||||
|
||||
return getNetworkParameterName(NetworkDriverIndex, parameterIdx, displayName, isAlternative);
|
||||
@@ -91,21 +91,22 @@ void addNetworkEnabledForm(networkIndex_t networkindex) {
|
||||
addFormCheckBox(displayName, internalName, Settings.getNetworkEnabled(networkindex));
|
||||
}
|
||||
|
||||
void addNetworkParameterForm(const NetworkSettingsStruct & NetworkSettings,
|
||||
/*
|
||||
void addNetworkParameterForm(const NetworkSettingsStruct & NetworkSettings,
|
||||
networkIndex_t networkindex,
|
||||
NetworkSettingsStruct::VarType varType) {
|
||||
networkDriverIndex_t NetworkDriverIndex = getNetworkDriverIndex_from_NetworkIndex(networkindex);
|
||||
networkDriverIndex_t NetworkDriverIndex = getNetworkDriverIndex_from_NetworkIndex(networkindex);
|
||||
|
||||
if (!validNetworkDriverIndex(NetworkDriverIndex)) {
|
||||
if (!validNetworkDriverIndex(NetworkDriverIndex)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool isAlternativeDisplayName = false;
|
||||
const String displayName = getNetworkParameterDisplayName(NetworkDriverIndex, varType, isAlternativeDisplayName);
|
||||
const String internalName = getNetworkParameterInternalName(NetworkDriverIndex, varType);
|
||||
bool isAlternativeDisplayName = false;
|
||||
const String displayName = getNetworkParameterDisplayName(NetworkDriverIndex, varType, isAlternativeDisplayName);
|
||||
const String internalName = getNetworkParameterInternalName(NetworkDriverIndex, varType);
|
||||
|
||||
switch (varType)
|
||||
{
|
||||
switch (varType)
|
||||
{
|
||||
case NetworkSettingsStruct::NETWORK_IP:
|
||||
{
|
||||
addFormIPBox(displayName, internalName, NetworkSettings.IP);
|
||||
@@ -119,33 +120,32 @@ void addNetworkParameterForm(const NetworkSettingsStruct & NetworkSettings,
|
||||
|
||||
case NetworkSettingsStruct::NETWORK_USER:
|
||||
{
|
||||
/*
|
||||
const size_t fieldMaxLength =
|
||||
NetworkSettings.useExtendedCredentials() ? EXT_SECURITY_MAX_USER_LENGTH : sizeof(SecuritySettings.NetworkUser[0]) - 1;
|
||||
addFormTextBox(displayName,
|
||||
internalName,
|
||||
getNetworkUser(networkindex, NetworkSettings, false),
|
||||
fieldMaxLength);
|
||||
*/
|
||||
break;
|
||||
|
||||
// const size_t fieldMaxLength =
|
||||
// NetworkSettings.useExtendedCredentials() ? EXT_SECURITY_MAX_USER_LENGTH : sizeof(SecuritySettings.NetworkUser[0]) - 1;
|
||||
// addFormTextBox(displayName,
|
||||
// internalName,
|
||||
// getNetworkUser(networkindex, NetworkSettings, false),
|
||||
// fieldMaxLength);
|
||||
break;
|
||||
}
|
||||
case NetworkSettingsStruct::NETWORK_PASS:
|
||||
{
|
||||
/*
|
||||
const size_t fieldMaxLength =
|
||||
NetworkSettings.useExtendedCredentials() ? EXT_SECURITY_MAX_PASS_LENGTH : sizeof(SecuritySettings.NetworkPassword[0]) - 1;
|
||||
|
||||
if (isAlternativeDisplayName) {
|
||||
// const size_t fieldMaxLength =
|
||||
// NetworkSettings.useExtendedCredentials() ? EXT_SECURITY_MAX_PASS_LENGTH : sizeof(SecuritySettings.NetworkPassword[0]) - 1;
|
||||
|
||||
// if (isAlternativeDisplayName) {
|
||||
// It is not a regular password, thus use normal text field.
|
||||
addFormTextBox(displayName, internalName,
|
||||
getNetworkPass(networkindex, NetworkSettings),
|
||||
fieldMaxLength);
|
||||
} else {
|
||||
addFormPasswordBox(displayName, internalName,
|
||||
getNetworkPass(networkindex, NetworkSettings),
|
||||
fieldMaxLength);
|
||||
}
|
||||
*/
|
||||
// addFormTextBox(displayName, internalName,
|
||||
// getNetworkPass(networkindex, NetworkSettings),
|
||||
// fieldMaxLength);
|
||||
// } else {
|
||||
// addFormPasswordBox(displayName, internalName,
|
||||
// getNetworkPass(networkindex, NetworkSettings),
|
||||
// fieldMaxLength);
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -157,9 +157,9 @@ void addNetworkParameterForm(const NetworkSettingsStruct & NetworkSettings,
|
||||
case NetworkSettingsStruct::NETWORK_ENABLED:
|
||||
addFormCheckBox(displayName, internalName, Settings.getNetworkEnabled(networkindex));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
void saveNetworkParameterForm(NetworkSettingsStruct & NetworkSettings,
|
||||
networkIndex_t networkindex,
|
||||
NetworkSettingsStruct::VarType varType) {
|
||||
|
||||
@@ -19,19 +19,15 @@ String getNetworkParameterName(networkDriverIndex_t NetworkDriverIndex
|
||||
bool displayName,
|
||||
bool & isAlternative);
|
||||
|
||||
String getNetworkParameterInternalName(networkDriverIndex_t NetworkDriverIndex,
|
||||
NetworkSettingsStruct::VarType parameterIdx);
|
||||
|
||||
String getNetworkParameterDisplayName(networkDriverIndex_t NetworkDriverIndex,
|
||||
NetworkSettingsStruct::VarType parameterIdx,
|
||||
bool & isAlternative);
|
||||
|
||||
void addNetworkEnabledForm(networkIndex_t networkindex);
|
||||
|
||||
/*
|
||||
void addNetworkParameterForm(const NetworkSettingsStruct & NetworkSettings,
|
||||
networkIndex_t networkindex,
|
||||
NetworkSettingsStruct::VarType varType);
|
||||
|
||||
*/
|
||||
void saveNetworkParameterForm(NetworkSettingsStruct & NetworkSettings,
|
||||
networkIndex_t networkindex,
|
||||
NetworkSettingsStruct::VarType varType);
|
||||
|
||||
@@ -378,21 +378,21 @@ int Plugin_QueryVType_BinarySensorInv(uint8_t value_nr) {
|
||||
return static_cast<int>(Sensor_VType::SENSOR_TYPE_SWITCH_INVERTED) | Sensor_VType_CAN_SET;
|
||||
}
|
||||
|
||||
int Plugin_QueryVType_Analog(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_ANALOG_ONLY); }
|
||||
int Plugin_QueryVType_Analog(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_ANALOG_ONLY); }
|
||||
|
||||
int Plugin_QueryVType_CO2(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_CO2_ONLY); }
|
||||
int Plugin_QueryVType_CO2(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_CO2_ONLY); }
|
||||
|
||||
int Plugin_QueryVType_Distance(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_DISTANCE_ONLY); }
|
||||
int Plugin_QueryVType_Distance(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_DISTANCE_ONLY); }
|
||||
|
||||
int Plugin_QueryVType_DustPM2_5(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_DUSTPM2_5_ONLY); }
|
||||
int Plugin_QueryVType_DustPM2_5(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_DUSTPM2_5_ONLY); }
|
||||
|
||||
int Plugin_QueryVType_Lux(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_LUX_ONLY); }
|
||||
int Plugin_QueryVType_Lux(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_LUX_ONLY); }
|
||||
|
||||
int Plugin_QueryVType_Temperature(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_TEMP_ONLY); }
|
||||
int Plugin_QueryVType_Temperature(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_TEMP_ONLY); }
|
||||
|
||||
int Plugin_QueryVType_Weight(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_WEIGHT_ONLY); }
|
||||
int Plugin_QueryVType_Weight(uint8_t value_nr) { return static_cast<int>(Sensor_VType::SENSOR_TYPE_WEIGHT_ONLY); }
|
||||
|
||||
String makeHomeAssistantCompliantName(const String& name) { return ESPEasy::net::makeRFCCompliantName(name, '_', '_', 0); }
|
||||
static String makeHomeAssistantCompliantName(const String& name) { return ESPEasy::net::makeRFCCompliantName(name, '_', '_', 0); }
|
||||
|
||||
# if FEATURE_MQTT_DEVICECLASS
|
||||
const char mqtt_binary_deviceclass_names[] PROGMEM =
|
||||
@@ -412,7 +412,7 @@ String MQTT_binary_deviceClassName(int devClassIndex) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int MQTT_binary_deviceClassIndex(const String& deviceClassName) {
|
||||
static int MQTT_binary_deviceClassIndex(const String& deviceClassName) {
|
||||
return GetCommandCode(deviceClassName.c_str(), mqtt_binary_deviceclass_names);
|
||||
}
|
||||
|
||||
@@ -468,49 +468,234 @@ const __FlashStringHelper* MQTT_sensor_StateClass(uint8_t index,
|
||||
|
||||
# endif // if FEATURE_MQTT_STATE_CLASS
|
||||
|
||||
bool MQTT_SendAutoDiscovery(controllerIndex_t ControllerIndex, cpluginID_t CPluginID) {
|
||||
bool success = true;
|
||||
static String MQTT_DiscoveryBuildValueTopic(const String & topic,
|
||||
struct EventStruct *event,
|
||||
uint8_t taskValueIndex,
|
||||
const __FlashStringHelper*deviceClass,
|
||||
const String & uniqueId,
|
||||
const String & elementId,
|
||||
const String & valueName) {
|
||||
String tmpTopic(topic);
|
||||
|
||||
MakeControllerSettings(ControllerSettings); // -V522
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
|
||||
if (!AllocatedControllerSettings()) {
|
||||
return false;
|
||||
if (taskValueIndex >= VARS_PER_TASK) {
|
||||
parseValNameVariable(tmpTopic, valueName, false);
|
||||
} else
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
{
|
||||
parseSingleControllerVariable(tmpTopic, event, taskValueIndex, false);
|
||||
}
|
||||
LoadControllerSettings(ControllerIndex, *ControllerSettings);
|
||||
parseDeviceClassVariable(tmpTopic, deviceClass, false);
|
||||
parseUniqueIdVariable(tmpTopic, uniqueId, false);
|
||||
parseElementIdVariable(tmpTopic, elementId, false);
|
||||
parseControllerVariables(tmpTopic, event, false); // Replace this last
|
||||
|
||||
if (ControllerSettings->mqtt_autoDiscovery()
|
||||
while (tmpTopic.endsWith(F("/"))) {
|
||||
tmpTopic = tmpTopic.substring(0, tmpTopic.length() - 1);
|
||||
}
|
||||
|
||||
// && (ControllerSettings->MqttAutoDiscoveryTrigger[0] != 0)
|
||||
&& (ControllerSettings->MqttAutoDiscoveryTopic[0] != 0)) {
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
return tmpTopic;
|
||||
}
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLog(LOG_LEVEL_INFO, concat(strformat(F("MQTT : AutoDiscovery for Controller %d CPlugin %d"),
|
||||
ControllerIndex + 1, CPluginID),
|
||||
validTaskIndex(mqttDiscoverOnlyTask) ?
|
||||
strformat(F(", Task %d"), mqttDiscoverOnlyTask + 1) :
|
||||
EMPTY_STRING));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
static String MQTT_TaskValueUniqueName(const String& taskName,
|
||||
const String& valueName) {
|
||||
String uniqueId = strformat(F("%s_%s_%s"),
|
||||
makeHomeAssistantCompliantName(Settings.getHostname()).c_str(),
|
||||
taskName.c_str(),
|
||||
valueName.c_str());
|
||||
|
||||
uniqueId.toLowerCase();
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
// Dispatch autoDiscovery per supported CPlugin
|
||||
switch (CPluginID)
|
||||
static bool MQTT_DiscoveryPublish(controllerIndex_t ControllerIndex,
|
||||
const String & topic,
|
||||
const String & discoveryMessage,
|
||||
taskIndex_t x,
|
||||
uint8_t v,
|
||||
bool retainDsc) {
|
||||
bool result = false;
|
||||
|
||||
// Send each discovery message separate
|
||||
result = MQTTpublish(ControllerIndex, INVALID_TASK_INDEX, topic.c_str(), discoveryMessage.c_str(), retainDsc);
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(F("MQTT : Discovery %d Task %d '%s': disc.topic: %s"),
|
||||
result, x + 1, getTaskDeviceName(x).c_str(), topic.c_str()));
|
||||
addLog(LOG_LEVEL_INFO, strformat(F("MQTT : Discovery payload: %s"),
|
||||
discoveryMessage.c_str()));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool MQTT_DiscoveryPublishWithStatusAndSet(
|
||||
uint8_t taskValue,
|
||||
const String & valueName,
|
||||
controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings,
|
||||
const __FlashStringHelper*componentClass,
|
||||
const String & deviceClass,
|
||||
const String & unitOfMeasure,
|
||||
struct EventStruct *event,
|
||||
const String & deviceElement,
|
||||
const String & stateClass,
|
||||
bool success,
|
||||
bool hasSet,
|
||||
bool hasIcon,
|
||||
const String & elementName,
|
||||
const String & elementId,
|
||||
bool sendTrigger)
|
||||
{
|
||||
if (!valueName.isEmpty()) {
|
||||
const String taskName = makeHomeAssistantCompliantName(getTaskDeviceName(event->TaskIndex));
|
||||
const String valName = makeHomeAssistantCompliantName(valueName);
|
||||
|
||||
const String uniqueId = elementName.isEmpty() ? MQTT_TaskValueUniqueName(taskName, valName)
|
||||
: Settings.MQTTDiscoverGroupInclTaskname()
|
||||
? strformat(F("%s_%s_%s"), elementId.c_str(), taskName.c_str(), valName.c_str())
|
||||
: strformat(F("%s_%s"), elementId.c_str(), valName.c_str());
|
||||
String message;
|
||||
{
|
||||
case 5: // CPLUGIN_ID_005 : Home assistant/openHAB
|
||||
success = MQTT_HomeAssistant_SendAutoDiscovery(ControllerIndex, *ControllerSettings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
const String publish = MQTT_DiscoveryBuildValueTopic(ControllerSettings.Publish,
|
||||
event,
|
||||
taskValue,
|
||||
componentClass,
|
||||
uniqueId,
|
||||
elementId,
|
||||
valName);
|
||||
|
||||
if (sendTrigger) {
|
||||
// triggerMessage
|
||||
message = strformat(F("{\"atype\":\"trigger\",\"t\":\"%s\","
|
||||
"\"p\":\"device_automation\","
|
||||
"\"type\":\"button_short_press\"," // FIXME ?
|
||||
"\"stype\":\"switch_1\"" // FIXME ?
|
||||
"%s}"), // deviceElement is used to pass in the TriggerState
|
||||
publish.c_str(), deviceElement.c_str());
|
||||
} else {
|
||||
// discoveryMessage
|
||||
const String withSet = hasSet ? F(",\"cmd_t\":\"~/set\"") : EMPTY_STRING;
|
||||
const String schema = hasSet ? EMPTY_STRING : "\"schema\":\"basic\",";
|
||||
const String devOrIcon = hasIcon ? F("ic") : F("dev_cla");
|
||||
const String withUoM = unitOfMeasure.isEmpty() ? EMPTY_STRING :
|
||||
strformat(F(",\"unit_of_meas\":\"%s\""), unitOfMeasure.c_str());
|
||||
const String stateJson = stateClass.isEmpty() ? EMPTY_STRING :
|
||||
strformat(F(",\"stat_cla\":\"%s\""), stateClass.c_str());
|
||||
|
||||
message = strformat(F("{\"~\":\"%s\",\"name\":\"%s %s\",\"uniq_id\":\"%s\",%s"
|
||||
"\"%s\":\"%s\"%s%s%s,\"stat_t\":\"~\""
|
||||
"%s}"), // deviceElement last
|
||||
publish.c_str(), taskName.c_str(), valName.c_str(), uniqueId.c_str(), schema.c_str(),
|
||||
devOrIcon.c_str(), deviceClass.c_str(), withUoM.c_str(), stateJson.c_str(), withSet.c_str(),
|
||||
deviceElement.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
const bool retainDsc = ControllerSettings.mqtt_retainDiscovery();
|
||||
String topic;
|
||||
{
|
||||
const String discoveryUrl = MQTT_DiscoveryBuildValueTopic(ControllerSettings.MqttAutoDiscoveryTopic,
|
||||
event,
|
||||
taskValue,
|
||||
componentClass,
|
||||
uniqueId,
|
||||
elementId,
|
||||
valName);
|
||||
const String discoveryConfig(parseStringKeepCase(ControllerSettings.MqttAutoDiscoveryConfig, 1, '|'));
|
||||
topic = discoveryConfig.isEmpty()
|
||||
? concat(discoveryUrl, F("/config"))
|
||||
: concat(discoveryUrl, discoveryConfig);
|
||||
}
|
||||
|
||||
return MQTT_DiscoveryPublish(ControllerIndex,
|
||||
topic,
|
||||
message,
|
||||
event->TaskIndex,
|
||||
taskValue,
|
||||
retainDsc);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool MQTT_DiscoveryPublishWithStatusAndSet(
|
||||
uint8_t taskValue,
|
||||
const String & valueName,
|
||||
controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings,
|
||||
const __FlashStringHelper*componentClass,
|
||||
const String & deviceClass,
|
||||
const String & unitOfMeasure,
|
||||
struct EventStruct *event,
|
||||
const String & deviceElement,
|
||||
const String & stateClass,
|
||||
bool success,
|
||||
bool hasSet,
|
||||
bool hasIcon,
|
||||
const String & elementName,
|
||||
const String & elementId)
|
||||
{
|
||||
return MQTT_DiscoveryPublishWithStatusAndSet(
|
||||
taskValue,
|
||||
valueName,
|
||||
ControllerIndex,
|
||||
ControllerSettings,
|
||||
componentClass,
|
||||
deviceClass,
|
||||
unitOfMeasure,
|
||||
event,
|
||||
deviceElement,
|
||||
stateClass,
|
||||
success,
|
||||
hasSet,
|
||||
hasIcon,
|
||||
elementName,
|
||||
elementId,
|
||||
false);
|
||||
}
|
||||
|
||||
static String MQTT_DiscoveryHelperGetValueName(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem) {
|
||||
return
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
discoveryItem.varIndex >= VARS_PER_TASK ? discoveryItem.varName :
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
getTaskValueName(taskIndex, taskVarIndex);
|
||||
}
|
||||
|
||||
static String MQTT_DiscoveryHelperGetValueUoM(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem,
|
||||
const String& defaultUoM) {
|
||||
return
|
||||
# if FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
discoveryItem.varIndex >= VARS_PER_TASK ? discoveryItem.uom :
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
toUnitOfMeasureName(Cache.getTaskVarUnitOfMeasure(taskIndex, taskVarIndex), defaultUoM);
|
||||
# else // FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
discoveryItem.varIndex >= VARS_PER_TASK ? discoveryItem.uom :
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
defaultUoM;
|
||||
# endif // FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
}
|
||||
|
||||
static String MQTT_DiscoveryHelperGetValueUoM(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem)
|
||||
{
|
||||
return MQTT_DiscoveryHelperGetValueUoM(taskIndex, taskVarIndex, discoveryItem, EMPTY_STRING);
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* Send MQTT AutoDiscovery in Home Assistant format
|
||||
*******************************************************/
|
||||
bool MQTT_HomeAssistant_SendAutoDiscovery(controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings) {
|
||||
static bool MQTT_HomeAssistant_SendAutoDiscovery(controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings) {
|
||||
bool success = false;
|
||||
|
||||
// Send plugin info
|
||||
@@ -934,6 +1119,44 @@ bool MQTT_HomeAssistant_SendAutoDiscovery(controllerIndex_t ControllerIn
|
||||
return success;
|
||||
}
|
||||
|
||||
bool MQTT_SendAutoDiscovery(controllerIndex_t ControllerIndex, cpluginID_t CPluginID) {
|
||||
bool success = true;
|
||||
|
||||
MakeControllerSettings(ControllerSettings); // -V522
|
||||
|
||||
if (!AllocatedControllerSettings()) {
|
||||
return false;
|
||||
}
|
||||
LoadControllerSettings(ControllerIndex, *ControllerSettings);
|
||||
|
||||
if (ControllerSettings->mqtt_autoDiscovery()
|
||||
|
||||
// && (ControllerSettings->MqttAutoDiscoveryTrigger[0] != 0)
|
||||
&& (ControllerSettings->MqttAutoDiscoveryTopic[0] != 0)) {
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLog(LOG_LEVEL_INFO, concat(strformat(F("MQTT : AutoDiscovery for Controller %d CPlugin %d"),
|
||||
ControllerIndex + 1, CPluginID),
|
||||
validTaskIndex(mqttDiscoverOnlyTask) ?
|
||||
strformat(F(", Task %d"), mqttDiscoverOnlyTask + 1) :
|
||||
EMPTY_STRING));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
|
||||
// Dispatch autoDiscovery per supported CPlugin
|
||||
switch (CPluginID)
|
||||
{
|
||||
case 5: // CPLUGIN_ID_005 : Home assistant/openHAB
|
||||
success = MQTT_HomeAssistant_SendAutoDiscovery(ControllerIndex, *ControllerSettings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool MQTT_DiscoveryGetDeviceVType(taskIndex_t TaskIndex,
|
||||
std::vector<DiscoveryItem>& discoveryItems,
|
||||
int valueCount,
|
||||
@@ -1017,184 +1240,6 @@ bool MQTT_DiscoveryGetDeviceVType(taskIndex_t TaskIndex,
|
||||
return discoveryItems.size() != orgLen; // Something added?
|
||||
}
|
||||
|
||||
String MQTT_TaskValueUniqueName(const String& taskName,
|
||||
const String& valueName) {
|
||||
String uniqueId = strformat(F("%s_%s_%s"),
|
||||
makeHomeAssistantCompliantName(Settings.getHostname()).c_str(),
|
||||
taskName.c_str(),
|
||||
valueName.c_str());
|
||||
|
||||
uniqueId.toLowerCase();
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
String MQTT_DiscoveryBuildValueTopic(const String & topic,
|
||||
struct EventStruct *event,
|
||||
uint8_t taskValueIndex,
|
||||
const __FlashStringHelper*deviceClass,
|
||||
const String & uniqueId,
|
||||
const String & elementId,
|
||||
const String & valueName) {
|
||||
String tmpTopic(topic);
|
||||
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
|
||||
if (taskValueIndex >= VARS_PER_TASK) {
|
||||
parseValNameVariable(tmpTopic, valueName, false);
|
||||
} else
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
{
|
||||
parseSingleControllerVariable(tmpTopic, event, taskValueIndex, false);
|
||||
}
|
||||
parseDeviceClassVariable(tmpTopic, deviceClass, false);
|
||||
parseUniqueIdVariable(tmpTopic, uniqueId, false);
|
||||
parseElementIdVariable(tmpTopic, elementId, false);
|
||||
parseControllerVariables(tmpTopic, event, false); // Replace this last
|
||||
|
||||
while (tmpTopic.endsWith(F("/"))) {
|
||||
tmpTopic = tmpTopic.substring(0, tmpTopic.length() - 1);
|
||||
}
|
||||
|
||||
return tmpTopic;
|
||||
}
|
||||
|
||||
bool MQTT_DiscoveryPublish(controllerIndex_t ControllerIndex,
|
||||
const String & topic,
|
||||
const String & discoveryMessage,
|
||||
taskIndex_t x,
|
||||
uint8_t v,
|
||||
bool retainDsc) {
|
||||
bool result = false;
|
||||
|
||||
// Send each discovery message separate
|
||||
result = MQTTpublish(ControllerIndex, INVALID_TASK_INDEX, topic.c_str(), discoveryMessage.c_str(), retainDsc);
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
addLog(LOG_LEVEL_INFO, strformat(F("MQTT : Discovery %d Task %d '%s': disc.topic: %s"),
|
||||
result, x + 1, getTaskDeviceName(x).c_str(), topic.c_str()));
|
||||
addLog(LOG_LEVEL_INFO, strformat(F("MQTT : Discovery payload: %s"),
|
||||
discoveryMessage.c_str()));
|
||||
}
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
return result;
|
||||
}
|
||||
|
||||
bool MQTT_DiscoveryPublishWithStatusAndSet(uint8_t taskValue,
|
||||
const String & valueName,
|
||||
controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings,
|
||||
const __FlashStringHelper*componentClass,
|
||||
const String & deviceClass,
|
||||
const String & unitOfMeasure,
|
||||
struct EventStruct *event,
|
||||
const String & deviceElement,
|
||||
const String & stateClass,
|
||||
bool success,
|
||||
bool hasSet,
|
||||
bool hasIcon,
|
||||
const String & elementName,
|
||||
const String & elementId,
|
||||
bool sendTrigger) {
|
||||
if (!valueName.isEmpty()) {
|
||||
const String taskName = makeHomeAssistantCompliantName(getTaskDeviceName(event->TaskIndex));
|
||||
const String valName = makeHomeAssistantCompliantName(valueName);
|
||||
|
||||
const String uniqueId = elementName.isEmpty() ? MQTT_TaskValueUniqueName(taskName, valName)
|
||||
: Settings.MQTTDiscoverGroupInclTaskname()
|
||||
? strformat(F("%s_%s_%s"), elementId.c_str(), taskName.c_str(), valName.c_str())
|
||||
: strformat(F("%s_%s"), elementId.c_str(), valName.c_str());
|
||||
String message;
|
||||
{
|
||||
const String publish = MQTT_DiscoveryBuildValueTopic(ControllerSettings.Publish,
|
||||
event,
|
||||
taskValue,
|
||||
componentClass,
|
||||
uniqueId,
|
||||
elementId,
|
||||
valName);
|
||||
|
||||
if (sendTrigger) {
|
||||
// triggerMessage
|
||||
message = strformat(F("{\"atype\":\"trigger\",\"t\":\"%s\","
|
||||
"\"p\":\"device_automation\","
|
||||
"\"type\":\"button_short_press\"," // FIXME ?
|
||||
"\"stype\":\"switch_1\"" // FIXME ?
|
||||
"%s}"), // deviceElement is used to pass in the TriggerState
|
||||
publish.c_str(), deviceElement.c_str());
|
||||
} else {
|
||||
// discoveryMessage
|
||||
const String withSet = hasSet ? F(",\"cmd_t\":\"~/set\"") : EMPTY_STRING;
|
||||
const String schema = hasSet ? EMPTY_STRING : "\"schema\":\"basic\",";
|
||||
const String devOrIcon = hasIcon ? F("ic") : F("dev_cla");
|
||||
const String withUoM = unitOfMeasure.isEmpty() ? EMPTY_STRING :
|
||||
strformat(F(",\"unit_of_meas\":\"%s\""), unitOfMeasure.c_str());
|
||||
const String stateJson = stateClass.isEmpty() ? EMPTY_STRING :
|
||||
strformat(F(",\"stat_cla\":\"%s\""), stateClass.c_str());
|
||||
|
||||
message = strformat(F("{\"~\":\"%s\",\"name\":\"%s %s\",\"uniq_id\":\"%s\",%s"
|
||||
"\"%s\":\"%s\"%s%s%s,\"stat_t\":\"~\""
|
||||
"%s}"), // deviceElement last
|
||||
publish.c_str(), taskName.c_str(), valName.c_str(), uniqueId.c_str(), schema.c_str(),
|
||||
devOrIcon.c_str(), deviceClass.c_str(), withUoM.c_str(), stateJson.c_str(), withSet.c_str(),
|
||||
deviceElement.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
const bool retainDsc = ControllerSettings.mqtt_retainDiscovery();
|
||||
String topic;
|
||||
{
|
||||
const String discoveryUrl = MQTT_DiscoveryBuildValueTopic(ControllerSettings.MqttAutoDiscoveryTopic,
|
||||
event,
|
||||
taskValue,
|
||||
componentClass,
|
||||
uniqueId,
|
||||
elementId,
|
||||
valName);
|
||||
const String discoveryConfig(parseStringKeepCase(ControllerSettings.MqttAutoDiscoveryConfig, 1, '|'));
|
||||
topic = discoveryConfig.isEmpty()
|
||||
? concat(discoveryUrl, F("/config"))
|
||||
: concat(discoveryUrl, discoveryConfig);
|
||||
}
|
||||
|
||||
return MQTT_DiscoveryPublish(ControllerIndex,
|
||||
topic,
|
||||
message,
|
||||
event->TaskIndex,
|
||||
taskValue,
|
||||
retainDsc);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
String MQTT_DiscoveryHelperGetValueName(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem) {
|
||||
return
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
discoveryItem.varIndex >= VARS_PER_TASK ? discoveryItem.varName :
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
getTaskValueName(taskIndex, taskVarIndex);
|
||||
}
|
||||
|
||||
String MQTT_DiscoveryHelperGetValueUoM(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem,
|
||||
const String& defaultUoM) {
|
||||
return
|
||||
# if FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
discoveryItem.varIndex >= VARS_PER_TASK ? discoveryItem.uom :
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
toUnitOfMeasureName(Cache.getTaskVarUnitOfMeasure(taskIndex, taskVarIndex), defaultUoM);
|
||||
# else // FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
# if FEATURE_STRING_VARIABLES
|
||||
discoveryItem.varIndex >= VARS_PER_TASK ? discoveryItem.uom :
|
||||
# endif // if FEATURE_STRING_VARIABLES
|
||||
defaultUoM;
|
||||
# endif // FEATURE_TASKVALUE_UNIT_OF_MEASURE
|
||||
}
|
||||
|
||||
# endif // if FEATURE_MQTT_DISCOVER
|
||||
|
||||
#endif // if FEATURE_MQTT
|
||||
@@ -33,13 +33,10 @@ int Plugin_QueryVType_Lux(uint8_t value_nr);
|
||||
int Plugin_QueryVType_Temperature(uint8_t value_nr);
|
||||
int Plugin_QueryVType_Weight(uint8_t value_nr);
|
||||
|
||||
String makeHomeAssistantCompliantName(const String& name);
|
||||
|
||||
# if FEATURE_MQTT_DEVICECLASS
|
||||
String MQTT_binary_deviceClassName(int devClassIndex);
|
||||
bool MQTT_binary_deviceClassTwoWay(int devClassIndex);
|
||||
bool MQTT_binary_deviceClassSwitch(int devClassIndex);
|
||||
int MQTT_binary_deviceClassIndex(const String& deviceClassName);
|
||||
# endif // if FEATURE_MQTT_DEVICECLASS
|
||||
# if FEATURE_MQTT_STATE_CLASS
|
||||
const __FlashStringHelper* MQTT_sensor_StateClass(uint8_t index,
|
||||
@@ -68,54 +65,11 @@ struct DiscoveryItem {
|
||||
|
||||
bool MQTT_SendAutoDiscovery(controllerIndex_t ControllerIndex,
|
||||
cpluginID_t CPluginID);
|
||||
bool MQTT_HomeAssistant_SendAutoDiscovery(controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings);
|
||||
bool MQTT_DiscoveryGetDeviceVType(taskIndex_t TaskIndex,
|
||||
std::vector<DiscoveryItem>& discoveryItems,
|
||||
int valueCount,
|
||||
String & deviceClass);
|
||||
String MQTT_TaskValueUniqueName(const String& taskName,
|
||||
const String& valueName);
|
||||
String MQTT_DiscoveryBuildValueTopic(const String & topic,
|
||||
struct EventStruct *event,
|
||||
uint8_t taskValueIndex,
|
||||
const __FlashStringHelper*deviceClass,
|
||||
const String & uniqueId,
|
||||
const String & elementId,
|
||||
const String & valueName);
|
||||
|
||||
bool MQTT_DiscoveryPublish(controllerIndex_t ControllerIndex,
|
||||
const String & topic,
|
||||
const String & discoveryMessage,
|
||||
taskIndex_t x,
|
||||
uint8_t v,
|
||||
bool retained = false);
|
||||
|
||||
bool MQTT_DiscoveryPublishWithStatusAndSet(uint8_t taskValue,
|
||||
const String & valueName,
|
||||
controllerIndex_t ControllerIndex,
|
||||
ControllerSettingsStruct& ControllerSettings,
|
||||
const __FlashStringHelper*componentClass,
|
||||
const String & deviceClass,
|
||||
const String & unitOfMeasure,
|
||||
struct EventStruct *event,
|
||||
const String & deviceElement,
|
||||
const String & stateClass,
|
||||
bool success,
|
||||
bool hasSet,
|
||||
bool hasIcon,
|
||||
const String & elementName,
|
||||
const String & elementId,
|
||||
bool sendTrigger = false);
|
||||
|
||||
String MQTT_DiscoveryHelperGetValueName(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem);
|
||||
|
||||
String MQTT_DiscoveryHelperGetValueUoM(taskIndex_t taskIndex,
|
||||
uint8_t taskVarIndex,
|
||||
DiscoveryItem discoveryItem,
|
||||
const String& defaultUoM = EMPTY_STRING);
|
||||
|
||||
# endif // if FEATURE_MQTT_DISCOVER
|
||||
#endif // if FEATURE_MQTT
|
||||
|
||||
+178
-159
@@ -8,7 +8,7 @@
|
||||
#include "../WebServer/HTML_wrappers.h"
|
||||
#include "../WebServer/LoadFromFS.h"
|
||||
|
||||
String generate_external_URL(const String& fname, bool isEmbedded) {
|
||||
static String generate_external_URL(const String& fname, bool isEmbedded) {
|
||||
if (isEmbedded || fileExists(fname)) {
|
||||
// Generate some URL indicating static files which will need to be served with some cache-control header
|
||||
return concat(F("static_"), Cache.fileCacheClearMoment) + '_' + fname;
|
||||
@@ -16,52 +16,54 @@ String generate_external_URL(const String& fname, bool isEmbedded) {
|
||||
|
||||
#if FEATURE_ALTERNATIVE_CDN_URL
|
||||
String cdn = get_CDN_url_custom();
|
||||
|
||||
if (!cdn.isEmpty()) {
|
||||
cdn = parseTemplate(cdn); // Replace system variables.
|
||||
return concat(cdn, fname); // cdn.endsWith('/') check done at save
|
||||
}
|
||||
}
|
||||
#endif // if FEATURE_ALTERNATIVE_CDN_URL
|
||||
|
||||
return concat(get_CDN_url_prefix(), fname);
|
||||
}
|
||||
|
||||
void serve_CDN_CSS(const __FlashStringHelper * fname, const __FlashStringHelper * fname_alt, bool isEmbedded) {
|
||||
static void serve_CDN_CSS(const __FlashStringHelper *fname, const __FlashStringHelper *fname_alt, bool isEmbedded) {
|
||||
const String url = generate_external_URL(fname, isEmbedded);
|
||||
|
||||
// FIXME TD-er: For now just retry loading the same as failed loading the embedded one
|
||||
// may slow down next page loads until the browser finally was able to fetch the embedded one.
|
||||
const String url2 = generate_external_URL(fname, isEmbedded);
|
||||
// const String url2 = generate_external_URL(fname_alt, !isEmbedded);
|
||||
|
||||
// const String url2 = generate_external_URL(fname_alt, !isEmbedded);
|
||||
|
||||
// Use 'onerror' to try to reload the CSS when first attempt loading failed
|
||||
// See: https://developer.mozilla.org/en-US/docs/Web/API/Window/error_event#element.onerror
|
||||
addHtml(strformat(
|
||||
F("<link rel=\"stylesheet\" href=\"%s\" onerror=\"this.onerror=null;this.href='%s';\" />"),
|
||||
url.c_str(),
|
||||
url2.c_str()
|
||||
));
|
||||
F("<link rel=\"stylesheet\" href=\"%s\" onerror=\"this.onerror=null;this.href='%s';\" />"),
|
||||
url.c_str(),
|
||||
url2.c_str()
|
||||
));
|
||||
|
||||
|
||||
// <link rel="stylesheet" href="%s" onerror="this.onerror=null;this.href='%s';" />
|
||||
|
||||
/*
|
||||
// Delay loading CSS till after page has loaded.
|
||||
// Disabled as it adds 'flickering' to the page loading
|
||||
addHtml(strformat(
|
||||
F("<link rel=\"preload\" href=\"%s\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\"><noscript><link rel=\"stylesheet\" href=\"%s\"></noscript>"),
|
||||
url.c_str(), url.c_str()
|
||||
));
|
||||
*/
|
||||
// Delay loading CSS till after page has loaded.
|
||||
// Disabled as it adds 'flickering' to the page loading
|
||||
addHtml(strformat(
|
||||
F("<link rel=\"preload\" href=\"%s\" as=\"style\" onload=\"this.onload=null;this.rel='stylesheet'\"><noscript><link rel=\"stylesheet\"
|
||||
href=\"%s\"></noscript>"),
|
||||
url.c_str(), url.c_str()
|
||||
));
|
||||
*/
|
||||
}
|
||||
|
||||
void serve_CDN_CSS(const __FlashStringHelper * fname, bool isEmbedded) {
|
||||
serve_CDN_CSS(fname, fname, isEmbedded);
|
||||
}
|
||||
static void serve_CDN_CSS(const __FlashStringHelper *fname, bool isEmbedded) { serve_CDN_CSS(fname, fname, isEmbedded); }
|
||||
|
||||
void serve_CDN_JS(const __FlashStringHelper * fname,
|
||||
const __FlashStringHelper * script_arg,
|
||||
bool useDefer) {
|
||||
static void serve_CDN_JS(const __FlashStringHelper *fname,
|
||||
const __FlashStringHelper *script_arg,
|
||||
bool useDefer) {
|
||||
addHtml(F("<script"));
|
||||
|
||||
if (useDefer) {
|
||||
addHtml(F(" defer"));
|
||||
}
|
||||
@@ -72,36 +74,37 @@ void serve_CDN_JS(const __FlashStringHelper * fname,
|
||||
html_add_script_end();
|
||||
}
|
||||
|
||||
|
||||
void serve_CSS(CSSfiles_e cssfile) {
|
||||
const __FlashStringHelper * url = F("");
|
||||
const __FlashStringHelper *url = F("");
|
||||
|
||||
#if !defined(WEBSERVER_CSS)
|
||||
bool useCDN = true;
|
||||
#else
|
||||
bool useCDN = false;
|
||||
#endif
|
||||
#endif // if !defined(WEBSERVER_CSS)
|
||||
|
||||
switch (cssfile) {
|
||||
switch (cssfile)
|
||||
{
|
||||
case CSSfiles_e::ESPEasy_default:
|
||||
// Send CSS in chunks
|
||||
#if defined(EMBED_ESPEASY_DEFAULT_MIN_CSS) || defined(WEBSERVER_EMBED_CUSTOM_CSS)
|
||||
useCDN = false;
|
||||
#endif
|
||||
#endif
|
||||
url = F("espeasy_default.min.css");
|
||||
break;
|
||||
#if FEATURE_RULES_EASY_COLOR_CODE
|
||||
case CSSfiles_e::EasyColorCode_codemirror:
|
||||
url = F("codemirror.min.css");
|
||||
url = F("codemirror.min.css");
|
||||
useCDN = true;
|
||||
break;
|
||||
#endif
|
||||
#endif // if FEATURE_RULES_EASY_COLOR_CODE
|
||||
default:
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
const __FlashStringHelper * cssFile =
|
||||
(cssfile == CSSfiles_e::ESPEasy_default) ?
|
||||
F("esp.css") : url;
|
||||
const __FlashStringHelper *cssFile =
|
||||
(cssfile == CSSfiles_e::ESPEasy_default) ?
|
||||
F("esp.css") : url;
|
||||
|
||||
if (fileExists(cssFile))
|
||||
{
|
||||
@@ -109,18 +112,20 @@ void serve_CSS(CSSfiles_e cssfile) {
|
||||
return;
|
||||
}
|
||||
#if !(defined(EMBED_ESPEASY_DEFAULT_MIN_CSS) || defined(WEBSERVER_EMBED_CUSTOM_CSS)) || FEATURE_RULES_EASY_COLOR_CODE
|
||||
|
||||
if (useCDN) {
|
||||
serve_CDN_CSS(url, false);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif // if !(defined(EMBED_ESPEASY_DEFAULT_MIN_CSS) || defined(WEBSERVER_EMBED_CUSTOM_CSS)) || FEATURE_RULES_EASY_COLOR_CODE
|
||||
#if defined(EMBED_ESPEASY_DEFAULT_MIN_CSS) || defined(WEBSERVER_EMBED_CUSTOM_CSS)
|
||||
|
||||
if (cssfile == CSSfiles_e::ESPEasy_default) {
|
||||
serve_CDN_CSS(cssFile, url, true);
|
||||
} else {
|
||||
serve_CDN_CSS(cssFile, true);
|
||||
}
|
||||
#endif
|
||||
#endif // if defined(EMBED_ESPEASY_DEFAULT_MIN_CSS) || defined(WEBSERVER_EMBED_CUSTOM_CSS)
|
||||
}
|
||||
|
||||
void serve_favicon() {
|
||||
@@ -130,163 +135,177 @@ void serve_favicon() {
|
||||
addHtml(F("'/>"));
|
||||
|
||||
/*
|
||||
addHtml(F("<link"));
|
||||
addHtmlAttribute(F("rel"), F("icon"));
|
||||
addHtmlAttribute(F("type"), F("image/x-icon"));
|
||||
addHtmlAttribute(F("href"), generate_external_URL(F("favicon.ico"), true));
|
||||
addHtml('/', '>');
|
||||
*/
|
||||
#endif
|
||||
addHtml(F("<link"));
|
||||
addHtmlAttribute(F("rel"), F("icon"));
|
||||
addHtmlAttribute(F("type"), F("image/x-icon"));
|
||||
addHtmlAttribute(F("href"), generate_external_URL(F("favicon.ico"), true));
|
||||
addHtml('/', '>');
|
||||
*/
|
||||
#endif // ifdef WEBSERVER_FAVICON_CDN
|
||||
#ifndef LIMIT_BUILD_SIZE
|
||||
addHtml(F("<link"));
|
||||
addHtmlAttribute(F("rel"), F("icon"));
|
||||
addHtmlAttribute(F("rel"), F("icon"));
|
||||
addHtmlAttribute(F("type"), F("image/svg+xml"));
|
||||
addHtmlAttribute(F("href"), F("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='113.392' height='113.392' viewBox='0 0 30.002 30.002'%3E%3Cpath fill='%23f9f9f9' d='M0 24.728V5.272A5.272 5.272 0 0 1 5.272 0h19.456c2.91 0 5.274 2.36 5.274 5.272v19.456a5.276 5.276 0 0 1-5.274 5.274H5.272A5.274 5.274 0 0 1 0 24.728zM30.002 0'/%3E%3Cpath fill='%2307d' stroke='%2307d' stroke-linecap='round' stroke-width='2.636' d='m3.75 11.25 7.5-7.5M3.75 18.75l15-15M3.75 26.25l22.5-22.5M11.25 26.25l15-15'/%3E%3Cpath fill='%2307d' d='M27.374 24.377a2.999 2.999 0 1 0-5.999 0 2.999 2.999 0 0 0 3.002 2.997 2.997 2.997 0 0 0 2.997-2.997zm-2.997 0'/%3E%3C/svg%3E"));
|
||||
addHtmlAttribute(F("href"),
|
||||
F(
|
||||
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='113.392' height='113.392' viewBox='0 0 30.002 30.002'%3E%3Cpath fill='%23f9f9f9' d='M0 24.728V5.272A5.272 5.272 0 0 1 5.272 0h19.456c2.91 0 5.274 2.36 5.274 5.272v19.456a5.276 5.276 0 0 1-5.274 5.274H5.272A5.274 5.274 0 0 1 0 24.728zM30.002 0'/%3E%3Cpath fill='%2307d' stroke='%2307d' stroke-linecap='round' stroke-width='2.636' d='m3.75 11.25 7.5-7.5M3.75 18.75l15-15M3.75 26.25l22.5-22.5M11.25 26.25l15-15'/%3E%3Cpath fill='%2307d' d='M27.374 24.377a2.999 2.999 0 1 0-5.999 0 2.999 2.999 0 0 0 3.002 2.997 2.997 2.997 0 0 0 2.997-2.997zm-2.997 0'/%3E%3C/svg%3E"));
|
||||
addHtml('/', '>');
|
||||
|
||||
/*
|
||||
<link rel="icon" type="image/svg+xml"
|
||||
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='113.392' height='113.392' viewBox='0 0 30.002 30.002'%3E%3Cpath fill='%23f9f9f9' d='M0 24.728V5.272A5.272 5.272 0 0 1 5.272 0h19.456c2.91 0 5.274 2.36 5.274 5.272v19.456a5.276 5.276 0 0 1-5.274 5.274H5.272A5.274 5.274 0 0 1 0 24.728zM30.002 0'/%3E%3Cpath fill='%2307d' stroke='%2307d' stroke-linecap='round' stroke-width='2.636' d='m3.75 11.25 7.5-7.5M3.75 18.75l15-15M3.75 26.25l22.5-22.5M11.25 26.25l15-15'/%3E%3Cpath fill='%2307d' d='M27.374 24.377a2.999 2.999 0 1 0-5.999 0 2.999 2.999 0 0 0 3.002 2.997 2.997 2.997 0 0 0 2.997-2.997zm-2.997 0'/%3E%3C/svg%3E" />
|
||||
*/
|
||||
#endif
|
||||
/*
|
||||
<link rel="icon" type="image/svg+xml"
|
||||
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='113.392' height='113.392' viewBox='0 0 30.002
|
||||
30.002'%3E%3Cpath fill='%23f9f9f9' d='M0 24.728V5.272A5.272 5.272 0 0 1 5.272 0h19.456c2.91 0 5.274 2.36 5.274 5.272v19.456a5.276
|
||||
5.276 0 0 1-5.274 5.274H5.272A5.274 5.274 0 0 1 0 24.728zM30.002 0'/%3E%3Cpath fill='%2307d' stroke='%2307d'
|
||||
stroke-linecap='round' stroke-width='2.636' d='m3.75 11.25 7.5-7.5M3.75 18.75l15-15M3.75 26.25l22.5-22.5M11.25
|
||||
26.25l15-15'/%3E%3Cpath fill='%2307d' d='M27.374 24.377a2.999 2.999 0 1 0-5.999 0 2.999 2.999 0 0 0 3.002 2.997 2.997 2.997 0 0 0
|
||||
2.997-2.997zm-2.997 0'/%3E%3C/svg%3E" />
|
||||
*/
|
||||
#endif // ifndef LIMIT_BUILD_SIZE
|
||||
}
|
||||
|
||||
void serve_JS(JSfiles_e JSfile) {
|
||||
const __FlashStringHelper * url = F("");
|
||||
const __FlashStringHelper * id = F("");
|
||||
bool useDefer = true;
|
||||
const __FlashStringHelper *url = F("");
|
||||
const __FlashStringHelper *id = F("");
|
||||
bool useDefer = true;
|
||||
|
||||
#if defined(WEBSERVER_INCLUDE_JS)
|
||||
bool useCDN = false;
|
||||
bool useCDN = false;
|
||||
#endif
|
||||
|
||||
switch (JSfile) {
|
||||
switch (JSfile)
|
||||
{
|
||||
case JSfiles_e::UpdateSensorValuesDevicePage:
|
||||
url = F("update_sensor_values_device_page.js");
|
||||
break;
|
||||
case JSfiles_e::FetchAndParseLog:
|
||||
url = F("fetch_and_parse_log.js");
|
||||
break;
|
||||
case JSfiles_e::SaveRulesFile:
|
||||
url = F("rules_save.js");
|
||||
break;
|
||||
case JSfiles_e::GitHubClipboard:
|
||||
url = F("github_clipboard.js");
|
||||
break;
|
||||
case JSfiles_e::Reboot:
|
||||
url = F("reboot.js");
|
||||
break;
|
||||
case JSfiles_e::Toasting:
|
||||
url = F("toasting.js");
|
||||
break;
|
||||
case JSfiles_e::SplitPasteInput:
|
||||
url = F("split_paste.js");
|
||||
break;
|
||||
#if FEATURE_RULES_EASY_COLOR_CODE
|
||||
case JSfiles_e::EasyColorCode_codemirror:
|
||||
url = F("codemirror.min.js");
|
||||
useDefer = false;
|
||||
# if defined(WEBSERVER_INCLUDE_JS)
|
||||
useCDN = true;
|
||||
# endif
|
||||
break;
|
||||
case JSfiles_e::EasyColorCode_espeasy:
|
||||
url = F("espeasy.min.js");
|
||||
useDefer = false;
|
||||
# if defined(WEBSERVER_INCLUDE_JS)
|
||||
useCDN = true;
|
||||
# endif
|
||||
break;
|
||||
case JSfiles_e::EasyColorCode_cm_plugins:
|
||||
url = F("cm-plugins.min.js");
|
||||
id = F("id='anyword'");
|
||||
useDefer = false;
|
||||
# if defined(WEBSERVER_INCLUDE_JS)
|
||||
useCDN = true;
|
||||
# endif
|
||||
break;
|
||||
#endif // if FEATURE_RULES_EASY_COLOR_CODE
|
||||
#ifdef USES_P113
|
||||
case JSfiles_e::P113_script:
|
||||
url = F("p113_script.js");
|
||||
break;
|
||||
#endif // ifdef USES_P113
|
||||
#ifdef USES_P165
|
||||
case JSfiles_e::P165_digit:
|
||||
url = F("p165_digit.js");
|
||||
break;
|
||||
#endif // ifdef USES_P165
|
||||
|
||||
}
|
||||
|
||||
// Work-around for shortening the filename when stored on SPIFFS file system
|
||||
// Files cannot be longer than 31 characters
|
||||
const __FlashStringHelper *fname =
|
||||
(JSfile == JSfiles_e::UpdateSensorValuesDevicePage) ?
|
||||
F("upd_values_device_page.js") : url;
|
||||
|
||||
if (!fileExists(fname))
|
||||
{
|
||||
#if defined(WEBSERVER_INCLUDE_JS)
|
||||
|
||||
if (!useCDN) {
|
||||
html_add_script_arg(id, useDefer);
|
||||
|
||||
switch (JSfile)
|
||||
{
|
||||
case JSfiles_e::UpdateSensorValuesDevicePage:
|
||||
url = F("update_sensor_values_device_page.js");
|
||||
# ifdef WEBSERVER_DEVICES
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_UPDATE_SENSOR_VALUES_DEVICE_PAGE_JS));
|
||||
# endif
|
||||
break;
|
||||
case JSfiles_e::FetchAndParseLog:
|
||||
url = F("fetch_and_parse_log.js");
|
||||
# ifdef WEBSERVER_LOG
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_FETCH_AND_PARSE_LOG_JS));
|
||||
# endif
|
||||
break;
|
||||
case JSfiles_e::SaveRulesFile:
|
||||
url = F("rules_save.js");
|
||||
# ifdef WEBSERVER_RULES
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsSaveRules));
|
||||
# endif
|
||||
break;
|
||||
case JSfiles_e::GitHubClipboard:
|
||||
url = F("github_clipboard.js");
|
||||
# ifdef WEBSERVER_GITHUB_COPY
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_GITHUB_CLIPBOARD_JS));
|
||||
# endif
|
||||
break;
|
||||
case JSfiles_e::Reboot:
|
||||
url = F("reboot.js");
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_REBOOT_JS));
|
||||
break;
|
||||
case JSfiles_e::Toasting:
|
||||
url = F("toasting.js");
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsToastMessageBegin));
|
||||
|
||||
// we can push custom messages here in future releases...
|
||||
addHtml(F("Submitted"));
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsToastMessageEnd));
|
||||
break;
|
||||
case JSfiles_e::SplitPasteInput:
|
||||
url = F("split_paste.js");
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsSplitMultipleFields));
|
||||
|
||||
// After this, make sure to call it, like this:
|
||||
// split('$', ".query-input")
|
||||
break;
|
||||
#if FEATURE_RULES_EASY_COLOR_CODE
|
||||
# if FEATURE_RULES_EASY_COLOR_CODE
|
||||
case JSfiles_e::EasyColorCode_codemirror:
|
||||
url = F("codemirror.min.js");
|
||||
useDefer = false;
|
||||
#if defined(WEBSERVER_INCLUDE_JS)
|
||||
useCDN = true;
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::EasyColorCode_espeasy:
|
||||
url = F("espeasy.min.js");
|
||||
useDefer = false;
|
||||
#if defined(WEBSERVER_INCLUDE_JS)
|
||||
useCDN = true;
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::EasyColorCode_cm_plugins:
|
||||
url = F("cm-plugins.min.js");
|
||||
id = F("id='anyword'");
|
||||
useDefer = false;
|
||||
#if defined(WEBSERVER_INCLUDE_JS)
|
||||
useCDN = true;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#ifdef USES_P113
|
||||
# endif // if FEATURE_RULES_EASY_COLOR_CODE
|
||||
# ifdef USES_P113
|
||||
case JSfiles_e::P113_script:
|
||||
url = F("p113_script.js");
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(p113_script));
|
||||
break;
|
||||
#endif // ifdef USES_P113
|
||||
#ifdef USES_P165
|
||||
# endif // ifdef USES_P113
|
||||
# ifdef USES_P165
|
||||
case JSfiles_e::P165_digit:
|
||||
url = F("p165_digit.js");
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_P165_DIGIT_JS));
|
||||
break;
|
||||
#endif // ifdef USES_P165
|
||||
|
||||
}
|
||||
|
||||
// Work-around for shortening the filename when stored on SPIFFS file system
|
||||
// Files cannot be longer than 31 characters
|
||||
const __FlashStringHelper * fname =
|
||||
(JSfile == JSfiles_e::UpdateSensorValuesDevicePage) ?
|
||||
F("upd_values_device_page.js") : url;
|
||||
|
||||
if (!fileExists(fname))
|
||||
{
|
||||
#if defined(WEBSERVER_INCLUDE_JS)
|
||||
if (!useCDN) {
|
||||
html_add_script_arg(id, useDefer);
|
||||
switch (JSfile) {
|
||||
case JSfiles_e::UpdateSensorValuesDevicePage:
|
||||
#ifdef WEBSERVER_DEVICES
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_UPDATE_SENSOR_VALUES_DEVICE_PAGE_JS));
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::FetchAndParseLog:
|
||||
#ifdef WEBSERVER_LOG
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_FETCH_AND_PARSE_LOG_JS));
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::SaveRulesFile:
|
||||
#ifdef WEBSERVER_RULES
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsSaveRules));
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::GitHubClipboard:
|
||||
#ifdef WEBSERVER_GITHUB_COPY
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_GITHUB_CLIPBOARD_JS));
|
||||
#endif
|
||||
break;
|
||||
case JSfiles_e::Reboot:
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_REBOOT_JS));
|
||||
break;
|
||||
case JSfiles_e::Toasting:
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsToastMessageBegin));
|
||||
// we can push custom messages here in future releases...
|
||||
addHtml(F("Submitted"));
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsToastMessageEnd));
|
||||
break;
|
||||
case JSfiles_e::SplitPasteInput:
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(jsSplitMultipleFields));
|
||||
// After this, make sure to call it, like this:
|
||||
// split('$', ".query-input")
|
||||
break;
|
||||
#if FEATURE_RULES_EASY_COLOR_CODE
|
||||
case JSfiles_e::EasyColorCode_codemirror:
|
||||
case JSfiles_e::EasyColorCode_espeasy:
|
||||
case JSfiles_e::EasyColorCode_cm_plugins:
|
||||
break;
|
||||
#endif
|
||||
#ifdef USES_P113
|
||||
case JSfiles_e::P113_script:
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(p113_script));
|
||||
break;
|
||||
#endif // ifdef USES_P113
|
||||
#ifdef USES_P165
|
||||
case JSfiles_e::P165_digit:
|
||||
TXBuffer.addFlashString((PGM_P)FPSTR(DATA_P165_DIGIT_JS));
|
||||
break;
|
||||
#endif // ifdef USES_P165
|
||||
}
|
||||
html_add_script_end();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
serve_CDN_JS(url, id, useDefer);
|
||||
} else {
|
||||
serve_CDN_JS(fname, id, useDefer);
|
||||
# endif // ifdef USES_P165
|
||||
}
|
||||
html_add_script_end();
|
||||
return;
|
||||
}
|
||||
#endif // if defined(WEBSERVER_INCLUDE_JS)
|
||||
serve_CDN_JS(url, id, useDefer);
|
||||
} else {
|
||||
serve_CDN_JS(fname, id, useDefer);
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
//-V::569
|
||||
|
||||
String generate_external_URL(const String& fname);
|
||||
|
||||
void serve_favicon();
|
||||
|
||||
enum class JSfiles_e {
|
||||
|
||||
Reference in new issue
Block a user