Merge pull request #3306 from ascillato/patch-1

KNX: Add new event and new commands
This commit is contained in:
Theo Arends 2018-07-23 10:24:45 +02:00 committed by GitHub
commit d62cb11227
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 228 additions and 36 deletions

View File

@ -1,14 +1,14 @@
# datatypes
address_t DATA_TYPE
message_t DATA_TYPE
callback_id_t DATA_TYPE
callback_assignment_id_t DATA_TYPE
option_entry_t DATA_TYPE
config_id_t DATA_TYPE
enable_condition_t DATA_TYPE
callback_fptr_t DATA_TYPE
feedback_action_fptr_t DATA_TYPE
knx_command_type_t DATA_TYPE
address_t KEYWORD1 DATA_TYPE
message_t KEYWORD1 DATA_TYPE
callback_id_t KEYWORD1 DATA_TYPE
callback_assignment_id_t KEYWORD1 DATA_TYPE
option_entry_t KEYWORD1 DATA_TYPE
config_id_t KEYWORD1 DATA_TYPE
enable_condition_t KEYWORD1 DATA_TYPE
callback_fptr_t KEYWORD1 DATA_TYPE
feedback_action_fptr_t KEYWORD1 DATA_TYPE
knx_command_type_t KEYWORD1 DATA_TYPE
# methods
setup KEYWORD2
@ -92,13 +92,13 @@ answer_4byte_int KEYWORD2
answer_4byte_uint KEYWORD2
answer_4byte_float KEYWORD2
data_to_1byte_int KEYWORD 2
data_to_2byte_int KEYWORD 2
data_to_2byte_float KEYWORD 2
data_to_4byte_float KEYWORD 2
data_to_3byte_color KEYWORD 2
data_to_3byte_time KEYWORD 2
data_to_3byte_data KEYWORD 2
data_to_1byte_int KEYWORD2
data_to_2byte_int KEYWORD2
data_to_2byte_float KEYWORD2
data_to_4byte_float KEYWORD2
data_to_3byte_color KEYWORD2
data_to_3byte_time KEYWORD2
data_to_3byte_data KEYWORD2
# constants
knx LITERAL1
knx LITERAL1

View File

@ -237,7 +237,8 @@
//#define USE_MQTT_TLS // Use TLS for MQTT connection (+53k code, +15k mem)
// -- KNX IP Protocol -----------------------------
//#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem)
//#define USE_KNX // Enable KNX IP Protocol Support (+9.4k code, +3k7 mem)
#define USE_KNX_WEB_MENU // Enable KNX WEB MENU (+8.3k code, +144 mem)
// -- HTTP ----------------------------------------
#define USE_WEBSERVER // Enable web server and Wifi Manager (+66k code, +8k mem)

View File

@ -204,7 +204,9 @@ const char HTTP_BTN_MENU_MQTT[] PROGMEM =
"";
const char HTTP_BTN_MENU4[] PROGMEM =
#ifdef USE_KNX
#ifdef USE_KNX_WEB_MENU
"<br/><form action='kn' method='get'><button>" D_CONFIGURE_KNX "</button></form>"
#endif // USE_KNX_WEB_MENU
#endif // USE_KNX
"<br/><form action='lg' method='get'><button>" D_CONFIGURE_LOGGING "</button></form>"
"<br/><form action='co' method='get'><button>" D_CONFIGURE_OTHER "</button></form>"
@ -391,7 +393,9 @@ void StartWebserver(int type, IPAddress ipweb)
#endif // USE_DOMOTICZ
}
#ifdef USE_KNX
#ifdef USE_KNX_WEB_MENU
WebServer->on("/kn", HandleKNXConfiguration);
#endif // USE_KNX_WEB_MENU
#endif // USE_KNX
WebServer->on("/lg", HandleLoggingConfiguration);
WebServer->on("/co", HandleOtherConfiguration);

View File

@ -196,9 +196,15 @@ const char *device_param_cb[] = {
// Commands
#define D_CMND_KNXTXCMND "KnxTx_Cmnd"
#define D_CMND_KNXTXVAL "KnxTx_Val"
enum KnxCommands { CMND_KNXTXCMND, CMND_KNXTXVAL };
const char kKnxCommands[] PROGMEM = D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL ;
#define D_CMND_KNX_ENABLED "Knx_Enabled"
#define D_CMND_KNX_ENHANCED "Knx_Enhanced"
#define D_CMND_KNX_PA "Knx_PA"
#define D_CMND_KNX_GA "Knx_GA"
#define D_CMND_KNX_CB "Knx_CB"
enum KnxCommands { CMND_KNXTXCMND, CMND_KNXTXVAL, CMND_KNX_ENABLED, CMND_KNX_ENHANCED, CMND_KNX_PA,
CMND_KNX_GA, CMND_KNX_CB } ;
const char kKnxCommands[] PROGMEM = D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|"
D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ;
byte KNX_GA_Search( byte param, byte start = 0 )
{
@ -517,14 +523,27 @@ void KNX_INIT()
void KNX_CB_Action(message_t const &msg, void *arg)
{
device_parameters_t *chan = (device_parameters_t *)arg;
if (!(Settings.flag.knx_enabled)) { return; }
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %d " D_TO " %s"),
msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member,
(msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER,
msg.data[0],
device_param_cb[(chan->type)-1]);
char tempchar[25];
if (msg.data_len == 1) {
// COMMAND
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %d " D_TO " %s"),
msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member,
(msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER,
msg.data[0],
device_param_cb[(chan->type)-1]);
} else {
// VALUE
float tempvar = knx.data_to_2byte_float(msg.data);
dtostrfd(tempvar,2,tempchar);
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_RECEIVED_FROM " %d.%d.%d " D_COMMAND " %s: %s " D_TO " %s"),
msg.received_on.ga.area, msg.received_on.ga.line, msg.received_on.ga.member,
(msg.ct == KNX_CT_WRITE) ? D_KNX_COMMAND_WRITE : (msg.ct == KNX_CT_READ) ? D_KNX_COMMAND_READ : D_KNX_COMMAND_OTHER,
tempchar,
device_param_cb[(chan->type)-1]);
}
AddLog(LOG_LEVEL_INFO);
switch (msg.ct)
@ -548,7 +567,13 @@ void KNX_CB_Action(message_t const &msg, void *arg)
{
if (!toggle_inhibit) {
char command[25];
snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]);
if (msg.data_len == 1) {
// Command received
snprintf_P(command, sizeof(command), PSTR("event KNXRX_CMND%d=%d"), ((chan->type) - KNX_SLOT1 + 1 ), msg.data[0]);
} else {
// Value received
snprintf_P(command, sizeof(command), PSTR("event KNXRX_VAL%d=%s"), ((chan->type) - KNX_SLOT1 + 1 ), tempchar);
}
ExecuteCommand(command, SRC_KNX);
if (Settings.flag.knx_enable_enhancement) {
toggle_inhibit = TOGGLE_INHIBIT_TIME;
@ -697,6 +722,7 @@ void KnxSensor(byte sensor_type, float value)
\*********************************************************************************************/
#ifdef USE_WEBSERVER
#ifdef USE_KNX_WEB_MENU
const char S_CONFIGURE_KNX[] PROGMEM = D_CONFIGURE_KNX;
const char HTTP_FORM_KNX[] PROGMEM =
@ -1001,6 +1027,7 @@ void KNX_Save_Settings()
}
}
#endif // USE_KNX_WEB_MENU
#endif // USE_WEBSERVER
@ -1010,14 +1037,12 @@ boolean KnxCommand()
uint8_t index = XdrvMailbox.index;
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kKnxCommands);
if (!(Settings.flag.knx_enabled)) { return false; }
if (-1 == command_code) { return false; } // Unknown command
else if ((CMND_KNXTXCMND == command_code) && (index > 0) && (index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0)) {
// index <- KNX SLOT to use
// XdrvMailbox.payload <- data to send
if (!(Settings.flag.knx_enabled)) { return false; }
// Search all the registered GA that has that output (variable: KNX SLOTx) as parameter
byte i = KNX_GA_Search(index + KNX_SLOT1 -1);
while ( i != KNX_Empty ) {
@ -1035,12 +1060,14 @@ boolean KnxCommand()
i = KNX_GA_Search(index + KNX_SLOT1 -1, i + 1);
}
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
command, index, XdrvMailbox.data );
}
else if ((CMND_KNXTXVAL == command_code) && (index > 0) && (index <= MAX_KNXTX_CMNDS) && (XdrvMailbox.data_len > 0)) {
// index <- KNX SLOT to use
// XdrvMailbox.payload <- data to send
if (!(Settings.flag.knx_enabled)) { return false; }
// Search all the registered GA that has that output (variable: KNX SLOTx) as parameter
byte i = KNX_GA_Search(index + KNX_SLOT1 -1);
while ( i != KNX_Empty ) {
@ -1062,13 +1089,173 @@ boolean KnxCommand()
i = KNX_GA_Search(index + KNX_SLOT1 -1, i + 1);
}
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
command, index, XdrvMailbox.data );
}
else if (CMND_KNX_ENABLED == command_code) {
if (!XdrvMailbox.data_len) {
if (Settings.flag.knx_enabled) {
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("1"));
} else {
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("0"));
}
} else {
if (XdrvMailbox.payload == 1) {
Settings.flag.knx_enabled = 1;
} else if (XdrvMailbox.payload == 0) {
Settings.flag.knx_enabled = 0;
} else { return false; } // Incomplete command
}
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),
command, XdrvMailbox.data );
}
else if (CMND_KNX_ENHANCED == command_code) {
if (!XdrvMailbox.data_len) {
if (Settings.flag.knx_enable_enhancement) {
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("1"));
} else {
snprintf_P(XdrvMailbox.data, sizeof(XdrvMailbox.data), PSTR("0"));
}
} else {
if (XdrvMailbox.payload == 1) {
Settings.flag.knx_enable_enhancement = 1;
} else if (XdrvMailbox.payload == 0) {
Settings.flag.knx_enable_enhancement = 0;
} else { return false; } // Incomplete command
}
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\"}"),
command, XdrvMailbox.data );
}
else if (CMND_KNX_PA == command_code) {
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, ".")) { // Process parameter entry
char sub_string[XdrvMailbox.data_len +1];
int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1));
int pa_line = atoi(subStr(sub_string, XdrvMailbox.data, ".", 2));
int pa_member = atoi(subStr(sub_string, XdrvMailbox.data, ".", 3));
if ( ((pa_area == 0) && (pa_line == 0) && (pa_member == 0))
|| (pa_area > 15) || (pa_line > 15) || (pa_member > 255) ) {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"),
command );
return true;
} // Invalid command
KNX_addr.pa.area = pa_area;
KNX_addr.pa.line = pa_line;
KNX_addr.pa.member = pa_member;
Settings.knx_physsical_addr = KNX_addr.value;
}
}
KNX_addr.value = Settings.knx_physsical_addr;
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%d.%d.%d\"}"),
command, KNX_addr.pa.area, KNX_addr.pa.line, KNX_addr.pa.member );
}
else if ((CMND_KNX_GA == command_code) && (index > 0) && (index <= MAX_KNX_GA)) {
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
char sub_string[XdrvMailbox.data_len +1];
int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
int ga_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2));
int ga_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3));
int ga_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4));
if ( ((ga_area == 0) && (ga_line == 0) && (ga_member == 0))
|| (ga_area > 31) || (ga_line > 7) || (ga_member > 255)
|| (ga_option < 0) || ((ga_option > KNX_MAX_device_param ) && (ga_option != KNX_Empty))
|| (!device_param[ga_option-1].show) ) {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
return true;
} // Invalid command
KNX_addr.ga.area = ga_area;
KNX_addr.ga.line = ga_line;
KNX_addr.ga.member = ga_member;
if ( index > Settings.knx_GA_registered ) {
Settings.knx_GA_registered ++;
index = Settings.knx_GA_registered;
}
Settings.knx_GA_addr[index -1] = KNX_addr.value;
Settings.knx_GA_param[index -1] = ga_option;
} else {
if ( (XdrvMailbox.payload <= Settings.knx_GA_registered) && (XdrvMailbox.payload > 0) ) {
index = XdrvMailbox.payload;
} else {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
return true;
}
}
if ( index <= Settings.knx_GA_registered ) {
KNX_addr.value = Settings.knx_GA_addr[index -1];
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"),
command, index, device_param_ga[Settings.knx_GA_param[index-1]-1],
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
}
} else {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%d\"}"),
command, Settings.knx_GA_registered );
}
}
else if ((CMND_KNX_CB == command_code) && (index > 0) && (index <= MAX_KNX_CB)) {
if (XdrvMailbox.data_len) {
if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry
char sub_string[XdrvMailbox.data_len +1];
int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1));
int cb_area = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2));
int cb_line = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3));
int cb_member = atoi(subStr(sub_string, XdrvMailbox.data, ",", 4));
if ( ((cb_area == 0) && (cb_line == 0) && (cb_member == 0))
|| (cb_area > 31) || (cb_line > 7) || (cb_member > 255)
|| (cb_option < 0) || ((cb_option > KNX_MAX_device_param ) && (cb_option != KNX_Empty))
|| (!device_param[cb_option-1].show) ) {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
return true;
} // Invalid command
KNX_addr.ga.area = cb_area;
KNX_addr.ga.line = cb_line;
KNX_addr.ga.member = cb_member;
if ( index > Settings.knx_CB_registered ) {
Settings.knx_CB_registered ++;
index = Settings.knx_CB_registered;
}
Settings.knx_CB_addr[index -1] = KNX_addr.value;
Settings.knx_CB_param[index -1] = cb_option;
} else {
if ( (XdrvMailbox.payload <= Settings.knx_CB_registered) && (XdrvMailbox.payload > 0) ) {
index = XdrvMailbox.payload;
} else {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_ERROR "\"}"), command );
return true;
}
}
if ( index <= Settings.knx_CB_registered ) {
KNX_addr.value = Settings.knx_CB_addr[index -1];
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s, %d/%d/%d\"}"),
command, index, device_param_cb[Settings.knx_CB_param[index-1]-1],
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member );
}
} else {
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%d\"}"),
command, Settings.knx_CB_registered );
}
}
else { return false; } // Incomplete command
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\"}"),
command, index, XdrvMailbox.data );
return true;
}