* Refactor announceDeviceTrigger function to improve parameter handling and documentation for optional device information Fix null pointer references in RFtoMQTTdiscovery and update logging levels for RF signal handling Refactor RF to MQTT discovery functions for improved clarity and parameter handling * Update documentation for RF auto discovery and MQTT integration, correcting terminology and enhancing clarity * Refactor enableRFReceive function to accept parameters for frequency and GPIOs, enhancing flexibility
This commit is contained in:
1 parent
e6443143bb
commit
e683fbbd18
13 files changed
+490
-191
No files matched your search
+1
-1
@@ -144,7 +144,7 @@ void enableActiveReceiver() {
|
||||
# ifdef ZgatewayRF
|
||||
case ACTIVE_RF:
|
||||
initCC1101();
|
||||
enableRFReceive();
|
||||
enableRFReceive(RFConfig.frequency, RF_RECEIVER_GPIO, RF_EMITTER_GPIO);
|
||||
currentReceiver = ACTIVE_RF;
|
||||
break;
|
||||
# endif
|
||||
|
||||
+180
-56
@@ -28,6 +28,8 @@
|
||||
#include "User_config.h"
|
||||
|
||||
#ifdef ZgatewayRF
|
||||
# include <ArduinoJson.h>
|
||||
# include <ArduinoLog.h>
|
||||
|
||||
# ifdef ZradioCC1101
|
||||
# include <ELECHOUSE_CC1101_SRC_DRV.h>
|
||||
@@ -37,7 +39,22 @@
|
||||
|
||||
RCSwitch mySwitch = RCSwitch();
|
||||
|
||||
//SOME CONVERSION function from https://github.com/sui77/rc-switch/tree/master/examples/ReceiveDemo_Advanced
|
||||
/**
|
||||
* @brief Converts a binary string to a tristate string.
|
||||
*
|
||||
* This function takes a binary string as input and converts it to a tristate string.
|
||||
* The tristate string is composed of '0', '1', and 'F' characters, where:
|
||||
* - '0' represents "00" in the binary string
|
||||
* - '1' represents "11" in the binary string
|
||||
* - 'F' represents "01" in the binary string
|
||||
*
|
||||
* If the input binary string contains any other combination, the function returns "-".
|
||||
*
|
||||
* @note CONVERSION function from https://github.com/sui77/rc-switch/tree/master/examples/ReceiveDemo_Advanced
|
||||
*
|
||||
* @param bin The input binary string.
|
||||
* @return A pointer to the tristate string.
|
||||
*/
|
||||
static const char* bin2tristate(const char* bin) {
|
||||
static char returnValue[50];
|
||||
int pos = 0;
|
||||
@@ -59,6 +76,22 @@ static const char* bin2tristate(const char* bin) {
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a decimal number to a binary string with zero fill.
|
||||
*
|
||||
* This function takes an unsigned long decimal number and converts it to a binary string
|
||||
* representation, ensuring that the resulting string is zero-padded to the specified bit length.
|
||||
*
|
||||
* @param Dec The decimal number to be converted.
|
||||
* @param bitLength The length of the resulting binary string, including leading zeros.
|
||||
* @return A pointer to a static character array containing the binary string representation.
|
||||
*
|
||||
* @note The returned string is stored in a static buffer, so it will be overwritten by subsequent
|
||||
* calls to this function. The buffer size is fixed at 64 characters.
|
||||
*
|
||||
* @note CONVERSION function from https://github.com/sui77/rc-switch/tree/master/examples/ReceiveDemo_Advanced
|
||||
*
|
||||
*/
|
||||
static char* dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
|
||||
static char bin[64];
|
||||
unsigned int i = 0;
|
||||
@@ -80,41 +113,67 @@ static char* dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
|
||||
return bin;
|
||||
}
|
||||
|
||||
# if defined(ZmqttDiscovery) && !defined(RF_DISABLE_TRANSMIT) && defined(RFmqttDiscovery)
|
||||
|
||||
void RFtoMQTTdiscovery(uint64_t MQTTvalue) {
|
||||
//on the fly switch creation from received RF values
|
||||
# if defined(ZmqttDiscovery) && defined(RF_on_HAS_as_DeviceTrigger)
|
||||
/**
|
||||
* @brief Announces RF signal data to Home Assistant via MQTT for device trigger configuration.
|
||||
*
|
||||
* This function creates and publishes a Home Assistant configuration message
|
||||
* for an RF signal received by the gateway. It constructs the necessary
|
||||
* MQTT topic and payload to announce the RF signal as a device trigger
|
||||
* in Home Assistant, allowing it to be used as an automation trigger.
|
||||
*
|
||||
* @param MQTTvalue The RF signal value to be published to MQTT.
|
||||
*/
|
||||
void announceGatewayTriggerTypeToHASS(uint64_t MQTTvalue) {
|
||||
char val[11];
|
||||
sprintf(val, "%lu", MQTTvalue);
|
||||
Log.trace(F("RF Entity Discovered, create HA Discovery CFG" CR));
|
||||
char* switchRF[2] = {val, "RF"};
|
||||
Log.trace(F("CreateDiscoverySwitch: %s" CR), switchRF[1]);
|
||||
String iSignal = String(val);
|
||||
# if valueAsATopic
|
||||
String discovery_topic = String(subjectRFtoMQTT) + "/" + String(switchRF[0]);
|
||||
String discovery_topic = String(subjectRFtoMQTT) + "/" + iSignal;
|
||||
# else
|
||||
String discovery_topic = String(subjectRFtoMQTT);
|
||||
# endif
|
||||
|
||||
String theUniqueId = getUniqueId(String(switchRF[0]), "-" + String(switchRF[1]));
|
||||
String subType = String(switchRF[0]);
|
||||
|
||||
announceDeviceTrigger(
|
||||
false,
|
||||
(char*)discovery_topic.c_str(),
|
||||
"received",
|
||||
(char*)subType.c_str(),
|
||||
(char*)theUniqueId.c_str(),
|
||||
"", "", "", "");
|
||||
Log.trace(F("[RF] Entity Discovered, create HA Discovery CFG" CR));
|
||||
announceGatewayTrigger(
|
||||
discovery_topic.c_str(), // topic
|
||||
"Received", // type
|
||||
String("RF-" + iSignal).c_str(), // subtype
|
||||
iSignal.c_str(), //signal id
|
||||
"{{trigger.value.raw}}" // value template
|
||||
);
|
||||
}
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Processes received RF signals and converts them to JSON format for further handling.
|
||||
*
|
||||
* This function checks if an RF signal is available, extracts relevant data from the signal,
|
||||
* and stores it in a JSON object. It also handles duplicate signal detection and optionally
|
||||
* publishes the signal data for MQTT discovery and repetition.
|
||||
*
|
||||
* @note This function is designed to work with both ESP32 and ESP8266 platforms.
|
||||
*
|
||||
* @details The function performs the following steps:
|
||||
* - Checks if an RF signal is available.
|
||||
* - Logs the reception of the RF signal.
|
||||
* - Extracts the value, protocol, length, delay, tristate, and binary representation of the signal.
|
||||
* - For ESP32 and ESP8266, extracts the raw data of the signal.
|
||||
* - If the ZradioCC1101 is defined, includes the frequency in the JSON object.
|
||||
* - Resets the availability status of the RF signal.
|
||||
* - Checks for duplicate signals and processes the signal if it is not a duplicate.
|
||||
* - Optionally publishes the signal data for MQTT discovery and repetition.
|
||||
*
|
||||
* @param None
|
||||
* @return void
|
||||
*/
|
||||
void RFtoX() {
|
||||
if (mySwitch.available()) {
|
||||
StaticJsonDocument<JSON_MSG_BUFFER> RFdataBuffer;
|
||||
JsonObject RFdata = RFdataBuffer.to<JsonObject>();
|
||||
Log.trace(F("Rcv. RF" CR));
|
||||
# ifdef ESP32
|
||||
Log.trace(F("RF Task running on core :%d" CR), xPortGetCoreID());
|
||||
Log.trace(F("[RF] Rcv. RF - Task running on core :%d" CR), xPortGetCoreID());
|
||||
# else
|
||||
Log.trace(F("[RF] Rcv. RF" CR));
|
||||
# endif
|
||||
uint64_t MQTTvalue = mySwitch.getReceivedValue();
|
||||
int length = mySwitch.getReceivedBitlength();
|
||||
@@ -137,36 +196,62 @@ void RFtoX() {
|
||||
}
|
||||
RFdata["raw"] = rawDump;
|
||||
# endif
|
||||
|
||||
# ifdef ZradioCC1101 // set Receive off and Transmitt on
|
||||
RFdata["frequency"] = RFConfig.frequency;
|
||||
# endif
|
||||
|
||||
mySwitch.resetAvailable();
|
||||
|
||||
if (!isAduplicateSignal(MQTTvalue) && MQTTvalue != 0) { // conditions to avoid duplications of RF -->MQTT
|
||||
# if defined(ZmqttDiscovery) && !defined(RF_DISABLE_TRANSMIT) && defined(RFmqttDiscovery) //component creation for HA
|
||||
# if defined(ZmqttDiscovery) && defined(RF_on_HAS_as_DeviceTrigger)
|
||||
if (SYSConfig.discovery)
|
||||
RFtoMQTTdiscovery(MQTTvalue);
|
||||
announceGatewayTriggerTypeToHASS(MQTTvalue);
|
||||
# endif
|
||||
RFdata["origin"] = subjectRFtoMQTT;
|
||||
enqueueJsonObject(RFdata);
|
||||
// Casting "receivedSignal[o].value" to (unsigned long) because ArduinoLog doesn't support uint64_t for ESP's
|
||||
Log.trace(F("Store val: %u" CR), (unsigned long)MQTTvalue);
|
||||
Log.trace(F("[RF] Store val: %u" CR), (unsigned long)MQTTvalue);
|
||||
storeSignalValue(MQTTvalue);
|
||||
if (repeatRFwMQTT) {
|
||||
Log.trace(F("Pub RF for rpt" CR));
|
||||
Log.trace(F("[RF] Pub RF for rpt" CR));
|
||||
RFdata["origin"] = subjectMQTTtoRF;
|
||||
enqueueJsonObject(RFdata);
|
||||
}
|
||||
} else {
|
||||
Log.trace(F("[RF] RF signal received but already managed" CR));
|
||||
}
|
||||
}
|
||||
// else {
|
||||
// No RF signal received
|
||||
// }
|
||||
}
|
||||
|
||||
# if simpleReceiving
|
||||
# if simpleReceiving // FALSE MEAN you don't want to use old way reception analysis
|
||||
/**
|
||||
* @brief Transmits RF signals based on the provided MQTT topic and data.
|
||||
*
|
||||
* This function processes the MQTT topic and data to determine the RF protocol,
|
||||
* pulse length, and number of bits to use for transmission. It then transmits
|
||||
* the RF signal using the specified parameters. If no specific parameters are
|
||||
* provided, default values are used.
|
||||
*
|
||||
* @param topicOri The original MQTT topic string.
|
||||
* @param datacallback The data to be transmitted, provided as a string.
|
||||
*
|
||||
* The function performs the following steps:
|
||||
* 1. Disables the current RF receiver and enables the transmitter if ZradioCC1101 is defined.
|
||||
* 2. Converts the data string to a 64-bit unsigned integer.
|
||||
* 3. Analyzes the topic string to extract RF protocol, pulse length, and bit count.
|
||||
* 4. Transmits the RF signal using the extracted or default parameters.
|
||||
* 5. Publishes an acknowledgment to the GTWRF topic.
|
||||
* 6. Re-enables the RF receiver and disables the transmitter if ZradioCC1101 is defined.
|
||||
*/
|
||||
void XtoRF(const char* topicOri, const char* datacallback) {
|
||||
# ifdef ZradioCC1101 // set Receive off and Transmitt on
|
||||
disableCurrentReceiver();
|
||||
ELECHOUSE_cc1101.SetTx(RFConfig.frequency);
|
||||
Log.notice(F("Transmit frequency: %F" CR), RFConfig.frequency);
|
||||
Log.notice(F("[RF] Transmit frequency: %F" CR), RFConfig.frequency);
|
||||
# endif
|
||||
mySwitch.disableReceive();
|
||||
mySwitch.enableTransmit(RF_EMITTER_GPIO);
|
||||
@@ -196,22 +281,20 @@ void XtoRF(const char* topicOri, const char* datacallback) {
|
||||
}
|
||||
|
||||
if ((cmpToMainTopic(topicOri, subjectMQTTtoRF)) && (valuePRT == 0) && (valuePLSL == 0) && (valueBITS == 0)) {
|
||||
Log.trace(F("MQTTtoRF dflt" CR));
|
||||
Log.trace(F("[RF] MQTTtoRF dflt" CR));
|
||||
mySwitch.setProtocol(1, 350);
|
||||
mySwitch.send(data, 24);
|
||||
// Acknowledgement to the GTWRF topic
|
||||
pub(subjectGTWRFtoMQTT, datacallback);
|
||||
} else if ((valuePRT != 0) || (valuePLSL != 0) || (valueBITS != 0)) {
|
||||
Log.trace(F("MQTTtoRF usr par." CR));
|
||||
Log.trace(F("[RF] MQTTtoRF usr par." CR));
|
||||
if (valuePRT == 0)
|
||||
valuePRT = 1;
|
||||
if (valuePLSL == 0)
|
||||
valuePLSL = 350;
|
||||
if (valueBITS == 0)
|
||||
valueBITS = 24;
|
||||
Log.notice(F("RF Protocol:%d" CR), valuePRT);
|
||||
Log.notice(F("RF Pulse Lgth: %d" CR), valuePLSL);
|
||||
Log.notice(F("Bits nb: %d" CR), valueBITS);
|
||||
Log.notice(F("[RF] Protocol: %d, Pulse Lgth: %d, Bits nb: %d" CR), valuePRT, valuePLSL, valueBITS);
|
||||
mySwitch.setProtocol(valuePRT, valuePLSL);
|
||||
mySwitch.send(data, valueBITS);
|
||||
// Acknowledgement to the GTWRF topic
|
||||
@@ -225,34 +308,53 @@ void XtoRF(const char* topicOri, const char* datacallback) {
|
||||
}
|
||||
# endif
|
||||
|
||||
# if jsonReceiving
|
||||
void XtoRF(const char* topicOri, JsonObject& RFdata) { // json object decoding
|
||||
# if jsonReceiving // FALSE MEAN you don't want to use Json reception analysis
|
||||
/**
|
||||
* @brief Handles the conversion of MQTT messages to RF signals.
|
||||
*
|
||||
* This function decodes a JSON object received via MQTT and transmits the corresponding RF signal.
|
||||
* It supports different RF protocols and configurations.
|
||||
*
|
||||
* @param topicOri The original MQTT topic.
|
||||
* @param RFdata The JSON object containing RF data to be transmitted.
|
||||
*
|
||||
* The JSON object should contain the following fields:
|
||||
* - "value": The RF signal value to be transmitted (required).
|
||||
* - "protocol": The RF protocol to be used (optional, default is 1).
|
||||
* - "delay": The pulse length in microseconds (optional, default is 350).
|
||||
* - "length": The number of bits in the RF signal (optional, default is 24).
|
||||
* - "repeat": The number of times the RF signal should be repeated (optional, default is RF_EMITTER_REPEAT).
|
||||
* - "txpower": The transmission power for CC1101 (optional, default is RF_CC1101_TXPOWER).
|
||||
* - "frequency": The transmission frequency for CC1101 (optional, default is RFConfig.frequency).
|
||||
*
|
||||
* The function logs the transmission details and acknowledges the sending by publishing the value to an acknowledgement topic.
|
||||
* It also restores the default repeat transmit value after sending the signal.
|
||||
*/
|
||||
void XtoRF(const char* topicOri, JsonObject& RFdata) {
|
||||
if (cmpToMainTopic(topicOri, subjectMQTTtoRF)) {
|
||||
Log.trace(F("MQTTtoRF json" CR));
|
||||
Log.trace(F("[RF] MQTTtoRF json" CR));
|
||||
uint64_t data = RFdata["value"];
|
||||
if (data != 0) {
|
||||
int valuePRT = RFdata["protocol"] | 1;
|
||||
int valuePLSL = RFdata["delay"] | 350;
|
||||
int valueBITS = RFdata["length"] | 24;
|
||||
int valueRPT = RFdata["repeat"] | RF_EMITTER_REPEAT;
|
||||
Log.notice(F("RF Protocol:%d" CR), valuePRT);
|
||||
Log.notice(F("RF Pulse Lgth: %d" CR), valuePLSL);
|
||||
Log.notice(F("Bits nb: %d" CR), valueBITS);
|
||||
Log.notice(F("[RF] Protocol:%d, Pulse Lgth: %d, Bits nb: %d" CR), valuePRT, valuePLSL, valueBITS);
|
||||
disableCurrentReceiver();
|
||||
# ifdef ZradioCC1101
|
||||
initCC1101();
|
||||
int txPower = RFdata["txpower"] | RF_CC1101_TXPOWER;
|
||||
ELECHOUSE_cc1101.setPA((int)txPower);
|
||||
Log.notice(F("CC1101 TX Power: %d" CR), txPower);
|
||||
Log.notice(F("[RF] CC1101 TX Power: %d" CR), txPower);
|
||||
float txFrequency = RFdata["frequency"] | RFConfig.frequency;
|
||||
ELECHOUSE_cc1101.SetTx(txFrequency);
|
||||
Log.notice(F("Transmit frequency: %F" CR), txFrequency);
|
||||
Log.notice(F("[RF] Transmit frequency: %F" CR), txFrequency);
|
||||
# endif
|
||||
mySwitch.enableTransmit(RF_EMITTER_GPIO);
|
||||
mySwitch.setRepeatTransmit(valueRPT);
|
||||
mySwitch.setProtocol(valuePRT, valuePLSL);
|
||||
mySwitch.send(data, valueBITS);
|
||||
Log.notice(F("MQTTtoRF OK" CR));
|
||||
Log.notice(F("[RF] MQTTtoRF OK" CR));
|
||||
// we acknowledge the sending by publishing the value to an acknowledgement topic, for the moment even if it is a signal repetition we acknowledge also
|
||||
RFdata["origin"] = subjectGTWRFtoMQTT;
|
||||
enqueueJsonObject(RFdata);
|
||||
@@ -264,28 +366,50 @@ void XtoRF(const char* topicOri, JsonObject& RFdata) { // json object decoding
|
||||
}
|
||||
# endif
|
||||
|
||||
int receiveInterupt = -1;
|
||||
|
||||
/**
|
||||
* @brief Disables the RF receiver.
|
||||
*
|
||||
* This function disables the RF receiver by calling the disableReceive method
|
||||
* on the mySwitch object. It also logs a trace message indicating that the RF
|
||||
* receiver has been disabled, along with the GPIO pin number used for the RF
|
||||
* receiver.
|
||||
*
|
||||
* @note THIS SEEMS LIKE A DEAD CODE. THE FUNCTION IS NOT CALLED ANYWHERE.
|
||||
*/
|
||||
void disableRFReceive() {
|
||||
Log.trace(F("disableRFReceive %d" CR), receiveInterupt);
|
||||
Log.trace(F("[RF] disable RFReceive %d" CR), RF_RECEIVER_GPIO);
|
||||
mySwitch.disableReceive();
|
||||
}
|
||||
|
||||
void enableRFReceive() {
|
||||
Log.notice(F("Enable RF Receiver: %FMhz" CR), RFConfig.frequency);
|
||||
//RF init parameters
|
||||
Log.notice(F("RF_EMITTER_GPIO: %d " CR), RF_EMITTER_GPIO);
|
||||
Log.notice(F("RF_RECEIVER_GPIO: %d " CR), RF_RECEIVER_GPIO);
|
||||
/**
|
||||
* @brief Enables the RF receiver and optionally the RF transmitter.
|
||||
*
|
||||
* This function initializes the RF receiver on the specified GPIO pin and, if not disabled,
|
||||
* initializes the RF transmitter on the specified GPIO pin. It also sets the RF frequency
|
||||
* and logs the configuration details.
|
||||
*
|
||||
* @param rfFrequency The frequency for the RF communication in MHz. Default is RFConfig.frequency.
|
||||
* @param rfReceiverGPIO The GPIO pin number for the RF receiver. Default is RF_RECEIVER_GPIO.
|
||||
* @param rfEmitterGPIO The GPIO pin number for the RF transmitter. Default is RF_EMITTER_GPIO.
|
||||
*
|
||||
* @note If RF_DISABLE_TRANSMIT is defined, the RF transmitter will be disabled.
|
||||
*/
|
||||
void enableRFReceive(
|
||||
float rfFrequency = RFConfig.frequency,
|
||||
int rfReceiverGPIO = RF_RECEIVER_GPIO,
|
||||
int rfEmitterGPIO = RF_EMITTER_GPIO) {
|
||||
Log.notice(F("[RF] Enable RF Receiver: %fMhz, RF_EMITTER_GPIO: %d, RF_RECEIVER_GPIO: %d" CR), rfFrequency, rfEmitterGPIO, rfReceiverGPIO);
|
||||
|
||||
# ifdef RF_DISABLE_TRANSMIT
|
||||
mySwitch.disableTransmit();
|
||||
# else
|
||||
mySwitch.enableTransmit(RF_EMITTER_GPIO);
|
||||
mySwitch.enableTransmit(rfEmitterGPIO);
|
||||
# endif
|
||||
receiveInterupt = RF_RECEIVER_GPIO;
|
||||
mySwitch.setRepeatTransmit(RF_EMITTER_REPEAT);
|
||||
mySwitch.enableReceive(receiveInterupt);
|
||||
Log.trace(F("ZgatewayRF command topic: %s%s%s" CR), mqtt_topic, gateway_name, subjectMQTTtoRF);
|
||||
Log.trace(F("ZgatewayRF setup done" CR));
|
||||
|
||||
mySwitch.setRepeatTransmit(rfEmitterGPIO);
|
||||
mySwitch.enableReceive(rfReceiverGPIO);
|
||||
|
||||
Log.trace(F("[RF] Setup command topic: %s%s%s\n Setup done" CR), (const char*)mqtt_topic, (const char*)gateway_name, (const char*)subjectMQTTtoRF);
|
||||
}
|
||||
|
||||
#endif
|
||||
+115
-70
@@ -23,9 +23,14 @@
|
||||
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 <ArduinoJson.h>
|
||||
#include <ArduinoLog.h>
|
||||
|
||||
#include "User_config.h"
|
||||
|
||||
#ifdef ZmqttDiscovery
|
||||
# include "config_mqttDiscovery.h"
|
||||
|
||||
String getMacAddress() {
|
||||
uint8_t baseMac[6];
|
||||
@@ -89,106 +94,145 @@ void createDiscoveryFromList(const char* mac,
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Create a message for Discovery Device Trigger. For HA @see https://www.home-assistant.io/integrations/device_trigger.mqtt/
|
||||
* @param use_gateway_info Boolean where true mean use the OMG information as Device Information
|
||||
* @param topic The Topic where the trigger will publish the content
|
||||
* @brief Announce that the Gateway have the ability to raise Trigger.
|
||||
* This function provide the configuration of the MQTT Device trigger ( @see https://www.home-assistant.io/integrations/device_trigger.mqtt/ ).
|
||||
* All messages published by this function will be interpreted as configuration messages of Gateway Triggers.
|
||||
* Instead, all messages published on the "triggerTopic" will be interpreted as Gateway trigger.
|
||||
*
|
||||
* @param triggerTopic Mandatory - The MQTT topic subscribed to receive trigger events.
|
||||
* @param type The type of the trigger, e.g. button_short_press. Entries supported by the HA Frontend: button_short_press, button_short_release, button_long_press, button_long_release, button_double_press, button_triple_press, button_quadruple_press, button_quintuple_press. If set to an unsupported value, will render as subtype type, e.g. button_1 spammed with type set to spammed and subtype set to button_1
|
||||
* @param subtype The subtype of the trigger, e.g. button_1. Entries supported by the HA frontend: turn_on, turn_off, button_1, button_2, button_3, button_4, button_5, button_6. If set to an unsupported value, will render as subtype type, e.g. left_button pressed with type set to button_short_press and subtype set to left_button
|
||||
* @param unique_id Valid only if gateway entry is false, The IDs that uniquely identify the device. For example a serial number.
|
||||
* @param device_name Valid only if gateway entry is false, The name of the device.
|
||||
* @param device_manufacturer Valid only if gateway entry is false, The manufacturer of the device.
|
||||
* @param device_model Valid only if gateway entry is false, The model of the device.
|
||||
* @param device_id Valid only if gateway entry is false, The connection of the device to the outside world
|
||||
* @param object_id The object_id of the trigger.
|
||||
* @param value_template The template to render the value of the trigger. The template can use the variables trigger.id, trigger.type, trigger.subtype, trigger.payload, trigger.payload_json, trigger.topic, trigger.timestamp, trigger.value, trigger.value_json. The template can be a string or a JSON object. If the template is a JSON object, it must be a valid JSON object. If the template is a string, it will be rendered as a string. If the template is a JSON object, it will be rendered as a JSON object.
|
||||
*/
|
||||
void announceDeviceTrigger(bool use_gateway_info, char* topic, char* type, char* subtype, char* unique_id, char* device_name, char* device_manufacturer, char* device_model, char* device_id) {
|
||||
void announceGatewayTrigger(const char* triggerTopic,
|
||||
const char* type,
|
||||
const char* subtype,
|
||||
const char* object_id,
|
||||
const char* value_template) {
|
||||
//Create The Json
|
||||
StaticJsonDocument<JSON_MSG_BUFFER> jsonBuffer;
|
||||
JsonObject sensor = jsonBuffer.to<JsonObject>();
|
||||
|
||||
// SET Default Configuration
|
||||
sensor["automation_type"] = "trigger"; // The type of automation, must be ‘trigger’.
|
||||
/**
|
||||
* The type of automation, must be ‘trigger’.
|
||||
* @see https://www.home-assistant.io/integrations/device_trigger.mqtt/#automation_type
|
||||
*/
|
||||
sensor["automation_type"] = "trigger";
|
||||
|
||||
//SET TYPE
|
||||
/**
|
||||
* Must be device_automation. Only allowed and required in MQTT auto discovery device messages.
|
||||
* @see https://www.home-assistant.io/integrations/device_trigger.mqtt/#platform
|
||||
* @see https://www.home-assistant.io/integrations/mqtt/#device-discovery-payload
|
||||
*/
|
||||
sensor["platform "] = "device_automation";
|
||||
|
||||
// The MQTT topic subscribed to receive trigger events.
|
||||
if (triggerTopic && triggerTopic[0]) {
|
||||
char state_topic[mqtt_topic_max_size];
|
||||
|
||||
strcpy(state_topic, mqtt_topic);
|
||||
strcat(state_topic, gateway_name);
|
||||
strcat(state_topic, triggerTopic);
|
||||
|
||||
/**
|
||||
* "info_topic" is not a standard field, for the message is required the filed "topic", but this filed is reserved and it is used to know where to publish the topic.
|
||||
* If we want to send on the message the topic information is usefull to use this "info_topic" that will be not delete by the send function but converted to "topic"
|
||||
*/
|
||||
sensor["info_topic"] = state_topic;
|
||||
} else {
|
||||
Log.error(F("[RF] Error: topic is mandatory for device trigger Discovery" CR));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the trigger, e.g. button_short_press.
|
||||
* Entries supported by the HA frontend: button_short_press, button_short_release, button_long_press, button_long_release, button_double_press, button_triple_press, button_quadruple_press, button_quintuple_press.
|
||||
* If set to an unsupported value, will render as subtype type, e.g. button_1 spammed with type set to spammed and subtype set to button_1
|
||||
*/
|
||||
if (type && type[0] != 0) {
|
||||
sensor["type"] = type;
|
||||
} else {
|
||||
sensor["type"] = "button_short_press";
|
||||
}
|
||||
|
||||
//SET SUBTYPE
|
||||
/**
|
||||
* The subtype of the trigger, e.g. turn_on.
|
||||
* Entries supported by the frontend: turn_on, turn_off, button_1, button_2, button_3, button_4, button_5, button_6.
|
||||
* If set to an unsupported value, will render as subtype type, e.g. left_button pressed with type set to button_short_press and subtype set to left_button
|
||||
*/
|
||||
if (subtype && subtype[0] != 0) {
|
||||
sensor["subtype"] = subtype;
|
||||
} else {
|
||||
sensor["subtype"] = "turn_on";
|
||||
}
|
||||
|
||||
/* Set The topic */
|
||||
if (topic && topic[0]) {
|
||||
char state_topic[mqtt_topic_max_size];
|
||||
// ------------------ START DEVICE DECLARATION --------------------------------------------------
|
||||
// TODO: This section, like the almost identical one in createDiscovery, should be placed in a
|
||||
// separate function and managed specifically to avoid errors in representing the device
|
||||
// in the HASS world.
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
strcpy(state_topic, mqtt_topic);
|
||||
strcat(state_topic, gateway_name);
|
||||
|
||||
strcat(state_topic, topic);
|
||||
sensor["info_topic"] = state_topic;
|
||||
}
|
||||
|
||||
/* Set The Devices */
|
||||
// Information about the device: this device trigger is a part of to tie it into the HA device registry.
|
||||
StaticJsonDocument<JSON_MSG_BUFFER> jsonDeviceBuffer;
|
||||
JsonObject device = jsonDeviceBuffer.to<JsonObject>();
|
||||
JsonArray identifiers = device.createNestedArray("identifiers");
|
||||
|
||||
if (use_gateway_info) {
|
||||
device["name"] = gateway_name;
|
||||
// A link to the webpage that can manage the configuration of this device.
|
||||
if (ethConnected) {
|
||||
# ifdef ESP32_ETHERNET
|
||||
device["configuration_url"] = String("http://") + String(ETH.localIP().toString()) + String("/"); //configuration_url
|
||||
# endif
|
||||
} else {
|
||||
device["configuration_url"] = String("http://") + String(WiFi.localIP().toString()) + String("/"); //configuration_url
|
||||
}
|
||||
|
||||
/*
|
||||
* A list of connections of the device to the outside world as a list of tuples [connection_type, connection_identifier].
|
||||
* For example the MAC address of a network interface: "connections": [["mac", "02:5b:26:a8:dc:12"]].
|
||||
*/
|
||||
JsonArray connections = device.createNestedArray("connections");
|
||||
JsonArray connection_mac = connections.createNestedArray();
|
||||
connection_mac.add("mac");
|
||||
connection_mac.add(getMacAddress());
|
||||
|
||||
// A list of IDs that uniquely identify the device. For example a serial number.
|
||||
String unique_id = String(getMacAddress());
|
||||
JsonArray identifiers = device.createNestedArray("identifiers");
|
||||
identifiers.add(unique_id);
|
||||
|
||||
// The manufacturer of the device.
|
||||
device["mf"] = GATEWAY_MANUFACTURER;
|
||||
|
||||
// The model of the device.
|
||||
# ifndef GATEWAY_MODEL
|
||||
String model = "";
|
||||
serializeJson(modules, model);
|
||||
device["model"] = model;
|
||||
String model = "";
|
||||
serializeJson(modules, model);
|
||||
device["mdl"] = model;
|
||||
# else
|
||||
device["model"] = GATEWAY_MODEL;
|
||||
device["mdl"] = GATEWAY_MODEL;
|
||||
# endif
|
||||
|
||||
device["manufacturer"] = GATEWAY_MANUFACTURER;
|
||||
device["sw_version"] = OMG_VERSION;
|
||||
identifiers.add(getMacAddress());
|
||||
// The name of the device.
|
||||
device["name"] = String(gateway_name);
|
||||
device["sw"] = OMG_VERSION;
|
||||
// ------------------ END DEVICE DECLARATION ------------------ //
|
||||
|
||||
} else {
|
||||
char deviceid[13];
|
||||
memcpy(deviceid, &unique_id[0], 12);
|
||||
deviceid[12] = '\0';
|
||||
|
||||
identifiers.add(deviceid);
|
||||
|
||||
/*Set Connection */
|
||||
if (device_id && device_id[0] != 0) {
|
||||
JsonArray connections = device.createNestedArray("connections");
|
||||
JsonArray connection_mac = connections.createNestedArray();
|
||||
connection_mac.add("mac");
|
||||
connection_mac.add(device_id);
|
||||
}
|
||||
|
||||
//Set manufacturer
|
||||
if (device_manufacturer && device_manufacturer[0]) {
|
||||
device["manufacturer"] = device_manufacturer;
|
||||
}
|
||||
|
||||
//Set name
|
||||
if (device_name && device_name[0]) {
|
||||
device["name"] = device_name;
|
||||
}
|
||||
|
||||
// set The Model
|
||||
if (device_model && device_model[0]) {
|
||||
device["model"] = device_model;
|
||||
}
|
||||
|
||||
device["via_device"] = gateway_name; //device name of the board
|
||||
}
|
||||
sensor["device"] = device; //device representing the board
|
||||
|
||||
/* Publish on the topic */
|
||||
String topic_to_publish = String(discovery_prefix) + "/device_automation/" + String(Gateway_Short_Name) + "/" + String(unique_id) + "/config";
|
||||
Log.trace(F("Announce Device Trigger %s" CR), topic_to_publish.c_str());
|
||||
if (value_template && value_template[0]) {
|
||||
sensor["value_template"] = String(value_template);
|
||||
}
|
||||
|
||||
/* Publish on the topic
|
||||
The discovery topic needs to be: <discovery_prefix>/device_automation/[<node_id>/]<object_id>/config.
|
||||
|
||||
Note that only one trigger may be defined per unique discovery topic.
|
||||
Also note that the combination of type and subtype should be unique for a device.
|
||||
|
||||
*/
|
||||
|
||||
String topic_to_publish = String(discovery_prefix) + "/device_automation/" + String(unique_id) + "/" + object_id + "/config";
|
||||
Log.trace(F("Announce Gatewy Trigger %s" CR), topic_to_publish.c_str());
|
||||
sensor["topic"] = topic_to_publish;
|
||||
sensor["retain"] = true;
|
||||
enqueueJsonObject(sensor);
|
||||
@@ -1061,7 +1105,8 @@ void pubMqttDiscovery() {
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef ZgatewayRF
|
||||
// in addition to the MQTT Device Discovery
|
||||
# if defined(ZgatewayRF) && defined(RF_on_HAS_as_MQTTSensor)
|
||||
// Sensor to display RF received value
|
||||
Log.trace(F("gatewayRFDiscovery" CR));
|
||||
char* gatewayRF[8] = {"sensor", "gatewayRF", "", "", jsonVal, "", "", ""};
|
||||
|
||||
+3
-2
@@ -35,7 +35,7 @@ extern void RFtoX();
|
||||
extern void XtoRF(const char* topicOri, const char* datacallback);
|
||||
extern void XtoRF(const char* topicOri, JsonObject& RFdata);
|
||||
extern void disableRFReceive();
|
||||
extern void enableRFReceive();
|
||||
extern void enableRFReceive(float rfFrequency, int rfReceiverGPIO, int rfEmitterGPIO);
|
||||
#endif
|
||||
#ifdef ZgatewayRF2
|
||||
extern void RF2toX();
|
||||
@@ -159,7 +159,8 @@ const char parameters[51][4][24] = {
|
||||
#define RF_EMITTER_REPEAT 20
|
||||
#define RF2_EMITTER_REPEAT 2 // Actual repeats is 2^R, where R is the here configured amount
|
||||
//#define RF_DISABLE_TRANSMIT //Uncomment this line to disable RF transmissions. (RF Receive will work as normal.)
|
||||
#define RFmqttDiscovery true //uncomment this line so as to create a discovery switch for each RF signal received
|
||||
//#define RF_on_HAS_as_DeviceTrigger //uncomment this line so as to create a Home Assistant device trigger for each RF signal received
|
||||
#define RF_on_HAS_as_MQTTSensor //uncomment this line so as to create a Home Assistant MQTT sensor for each RF signal received
|
||||
|
||||
/*-------------------RF2 topics & parameters----------------------*/
|
||||
//433Mhz newremoteswitch MQTT Subjects and keys
|
||||
|
||||
@@ -92,25 +92,17 @@ extern void createDiscovery(const char* sensor_type,
|
||||
|
||||
/**
|
||||
* @brief Create a message for Discovery Device Trigger. For HA @see https://www.home-assistant.io/integrations/device_trigger.mqtt/
|
||||
* @param use_gateway_info Boolean where true mean use the OMG information as Device Information
|
||||
* @param topic The Topic where the trigger will publish the content
|
||||
* @param topic Mandatory - The MQTT topic subscribed to receive trigger events.
|
||||
* @param type The type of the trigger, e.g. button_short_press. Entries supported by the HA Frontend: button_short_press, button_short_release, button_long_press, button_long_release, button_double_press, button_triple_press, button_quadruple_press, button_quintuple_press. If set to an unsupported value, will render as subtype type, e.g. button_1 spammed with type set to spammed and subtype set to button_1
|
||||
* @param subtype The subtype of the trigger, e.g. button_1. Entries supported by the HA frontend: turn_on, turn_off, button_1, button_2, button_3, button_4, button_5, button_6. If set to an unsupported value, will render as subtype type, e.g. left_button pressed with type set to button_short_press and subtype set to left_button
|
||||
* @param unique_id Valid only if gateway entry is false, The IDs that uniquely identify the device. For example a serial number.
|
||||
* @param device_name Valid only if gateway entry is false, The name of the device.
|
||||
* @param device_manufacturer Valid only if gateway entry is false, The manufacturer of the device.
|
||||
* @param device_model Valid only if gateway entry is false, The model of the device.
|
||||
* @param device_mac Valid only if gateway entry is false, The connection of the device to the outside world
|
||||
* @param object_id The object_id of the trigger.
|
||||
* @param value_template The template to render the value of the trigger. The template can use the variables trigger.id, trigger.type, trigger.subtype, trigger.payload, trigger.payload_json, trigger.topic, trigger.timestamp, trigger.value, trigger.value_json. The template can be a string or a JSON object. If the template is a JSON object, it must be a valid JSON object. If the template is a string, it will be rendered as a string. If the template is a JSON object, it will be rendered as a JSON object.
|
||||
*/
|
||||
void announceDeviceTrigger(bool use_gateway_info,
|
||||
char* topic,
|
||||
char* type,
|
||||
char* subtype,
|
||||
char* unique_id,
|
||||
char* device_name,
|
||||
char* device_manufacturer,
|
||||
char* device_model,
|
||||
char* device_mac);
|
||||
void announceGatewayTrigger(const char* topic,
|
||||
const char* type,
|
||||
const char* subtype,
|
||||
const char* object_id,
|
||||
const char* value_template);
|
||||
|
||||
#ifdef discovery_Topic //Deprecated - use discovery_Prefix instead
|
||||
# pragma message("compiler directive discovery_Topic is deprecated, use discovery_Prefix instead")
|
||||
|
||||
Reference in new issue
Block a user