Code Monkey home page Code Monkey logo

Comments (9)

ascillato avatar ascillato commented on August 23, 2024

What do you mean with "buttons to callbacks"? Buttons to issue callbacks from the webui?

Yes! exactly 👍

How would you specify arrangement of objects? xy-coordinates? Some kind of grid?

I'm still thinking on how to order.

But, I think, first of all, could be making everything centered on the page and be able of changing the order with an index or with the order you register them, like:

(1) Title of the page

(2) a Label (like Physical Address config)
(3) Physical Address Config

(4) Separator (a line)

(5) Group Address to Write to (config_register_ga)
(6) config_register_int (like the checkbox of the example - sending updates (ms))
(7) config_register_bool (like the checkbox of the example - sending updates (ms))

(8) Group Address to Read From (callback_register)

(9) Feedbacks
(10) Actions
(11) Links
(12) Buttons

buttons can be configured to run a callback, so there is no need to config on esp-knx-ip-webserver.cpp the buttons REBOOT, EEPROM SAVE, EEPROM RESTORE, etc.

What do you think?

from esp-knx-ip.

ascillato avatar ascillato commented on August 23, 2024

Still Thinking...

What about that the order of elements on the webpage be just the ID, so they will show up in the same order you register them on the main application?

from esp-knx-ip.

envy avatar envy commented on August 23, 2024

What do you mean with "buttons to callbacks"? Buttons to issue callbacks from the webui?

Yes! exactly +1

This is not easily possible. Callbacks can try to read data from the packet. So there are two options:

  1. Just call the callback function without any data. This will render most callbacks useless.
  2. Add a data entry field so we can pass data to the callback. However it would need to either accept arbitrary hex values as data, or another field is added to specify the type of data which would complicate many things.

There already exists the possiblity to add buttons via feedback_register_action. That way, arbitrary functions that don't take any arguments can be registered and are called on button press. I think this should be enough for now.

What about that the order of elements on the webpage be just the ID, so they will show up in the same order you register them on the main application?

They actually are displayed in the order they are registered, just grouped by type/category. Feedback items first, then assigned callbacks + callback assign form, then all config options and lastly the buttons. Order of items is registration order in their respective categories.

from esp-knx-ip.

ascillato avatar ascillato commented on August 23, 2024

Hi

I made the following picture + code as an example of the idea to use the full library with webserver on other proyects like Tasmota. I know that for supporting this, some features should be added to the actual routines of the library, but I think that is going to solve #36, #37, #38, #14, #4.

These are just ideas and I would like to discuss them:

  • All the text is given by the main program, so language translation is part of the main program and not of the library
  • Everything centered
  • Order of items given by the order on which was registered on the code despite what type of item is.
  • Feedback_action buttons are yellow as warning because they can change things (relay outputs, etc)
  • The way to set Group Address for sending data should be similar to Group Address for receiving data.

Idea on how it looks:
knx set page test

Idea on the code to be used on the main program to generate that configuration page:

// KNX WebPage Configuration
// -------------------------

// The order of the knx.***_register_*** code, is the order shown on the web page.

knx.config_register_WebPageTitle("KNX Configuration");

knx.config_register_Title("KNX Parameters");

knx.config_register_line();

knx.config_register_SubTitle("General");

// Names to be displayed on the Physical Address Object. So, translations can be done by the main program
knx.config_register_pa("Physical Address","Set");

// (optional) Set Physical KNX Address of the device
knx.physical_address_set(knx.PA_to_address(1, 1, 1));

knx.config_register_label("(must be unique on the KNX Network)");

knx.config_register_blankspace();

if (Settings.flag.knx_enabled) {
  // On the feedback_register_action can be defined the names to display.
  // knx_disable_pressed is a callback that uses enable_knx_id to call
  // feedback_set_action and modify that feedback action
  enable_knx_id = knx.feedback_register_action("KNX: Enabled", "Disable", knx_disable_pressed);
}
else {
  enable_knx_id = knx.feedback_register_action("KNX: Disabled", "Enable", knx_enable_pressed);
}

knx.config_register_line();

knx.config_register_SubTitle("Send Data to Group Addresses");

// Register Group Addresses to Send Data to
Relay[0].status_ga_id = knx.config_register_ga("Relay 1 Status", &Relay[0].enabled, "Add"); // "Add" is the text on the Group Address button. True is the Enable/Disable of that Address
Relay[1].status_ga_id = knx.config_register_ga("Relay 2 Status", &Relay[1].enabled);
Relay[2].status_ga_id = knx.config_register_ga("Relay 3 Status", &Relay[2].enabled);
Relay[3].status_ga_id = knx.config_register_ga("Relay 4 Status", &Relay[3].enabled);
Button[0].status_ga_id = knx.config_register_ga("Button 1 Status", &Button[1].enabled);
Button[1].status_ga_id = knx.config_register_ga("Button 2 Status", &Button[2].enabled);
Button[2].status_ga_id = knx.config_register_ga("Button 3 Status", &Button[3].enabled);
Button[3].status_ga_id = knx.config_register_ga("Button 4 Status", &Button[4].enabled);
sensor_temp.ga_id = knx.config_register_ga("Temperature", true);

// (optional) Set Group Addresses to Send Data to
knx.config_set_ga(Relay[0].status_ga_id, knx.GA_to_address(2,2,1));
Relay[0].enabled = true;
knx.config_set_ga(sensor_temp.ga_id, knx.GA_to_address(4,1,1));

knx.config_register_blankspace();

label_test_send_Relay1 = "Relay 1 Status: " + Relay[0].state ? "ON" : "OFF";
knx.feedback_register_action(&label_test_send_Relay1, send_data, "Test Send"); // "Test Send" is the text of the button. label_test_send_Relay1 is going to be updated on void loop()
                                                                               // all feedback action buttons are yellow as warning because they execute things
label_test_send_temp = "Temperature (°C): " + last_temp;
knx.feedback_register_action(&label_test_send_temp, send_data, "Test Send"); // "Test Send" is the text of the button. label_test_send_temp is going to be updated on void loop()

knx.config_register_blankspace();

Relay[0].update_rate_id = knx.config_register_int("Relay 1 Status Update rate (ms)", UPDATE_INTERVAL_RELAY, "Set"); // "Set" is the text on the button
sensor_temp.update_rate_id = knx.config_register_int("Relay 1 Status Update rate (ms)", UPDATE_INTERVAL, "Set"); // "Set" is the text on the button

knx.config_register_label("Set Update Rate to 0 ms for not sending regular updates.");
knx.config_register_label("Updates will be sent only for relay toggle or button press");

knx.config_register_line();

knx.config_register_SubTitle("Receive Data from Group Addresses");

// Register Group Addresses to Receive data from and execute callbacks
Relay[0].callback_id = knx.callback_register("Toggle Relay 1", relay_cb, &Relay[0], &Relay[0].enabled_cb, "Add");
Relay[1].callback_id = knx.callback_register("Toggle Relay 2", relay_cb, &Relay[1], &Relay[1].enabled_cb);
Relay[2].callback_id = knx.callback_register("Toggle Relay 3", relay_cb, &Relay[2], &Relay[2].enabled_cb);
Relay[3].callback_id = knx.callback_register("Toggle Relay 4", relay_cb, &Relay[3], &Relay[3].enabled_cb);
sensor_temp.callback_id = knx.callback_register("Reply Temperature", reply_temp_cb, &sensor_temp, &sensor_temp.enabled_cb);

// (Optional) Set Group Addresses to receive Data from
knx.callback_assign(Relay[0].callback_id, knx.GA_to_address(2,2,1));
Relay[0].enabled_cb = false; // Disabled GA. will not call the callback. Because it has a registered address is going to be shown on the page.
                             // Disabled GA shows the yellow enable button to activate again the use of the callback
knx.callback_assign(sensor_temp.callback_id, knx.GA_to_address(4,1,1));
sensor_temp.enabled_cb = true;

knx.config_register_blankspace();

label_test_action_Relay1 = "Toggle Relay 1 (Actual: " + Relay[0].state ? "ON)" : "OFF)";
knx.feedback_register_action(&label_test_action_Relay1, relay_cb_1, "Test Action"); // "Test Action" is the text of the button.

label_test_action_temp = "Reply Temperature (" + last_temp + " °C)";
knx.feedback_register_action(&label_test_action_temp, reply_temp_cb, "Test Action"); // "Test Action" is the text of the button. label_test_send_temp is going to be updated on void loop()

knx.config_register_line();

knx.feedback_register_custom_button("Save", KNXSaveSettings); // KNXSaveSettings is a subroutine on the main program. custom_button are yellow
knx.feedback_register_return_button("Return", "/"); // "/" is the address to return.

// END KNX WebPage Configuration

from esp-knx-ip.

ascillato avatar ascillato commented on August 23, 2024

@envy,

What do you think of the above approach?

In which:

Everything is shown in the order where the functions xxxx_register_xxxx where used.

New functions:

  • Set webpage title: knx.config_register_WebPageTitle("KNX Configuration");
  • Make a <h2> text: knx.config_register_Title("KNX Parameters");
  • Insert a <hr>: knx.config_register_line();
  • Make a <h4> text: knx.config_register_SubTitle("General");
  • Set Text for Physical Address Config and Set button: knx.config_register_pa("Physical Address","Set");
  • Set a text: knx.config_register_label("(must be unique on the KNX Network)");
  • Set a <br>: knx.config_register_blankspace();
  • Set a return button: knx.feedback_register_return_button("Return", "/");
  • Set a custom button: knx.feedback_register_custom_button("Save", KNXSaveSettings);
    This one can be also a feedback_register_action ("", "Save", KNXSaveSettings), where the blank text means just the button without the label. 😄

Modification to functions:

  • knx.config_register_xxxxx have text for the button

  • feedback_register_action has text for the button knx.feedback_register_action("KNX: Enabled", "Disable", knx_disable_pressed);

  • knx.config_register_ga has text for the button and works like knx.callback_register that has a main object to choose actions and can set addresses. And below that, you see the already set ones.

    So, knx.config_register_ga register a device parameter (->) to an address to write
    and, knx.callback_register register an address to receive (->) a comand

from esp-knx-ip.

envy avatar envy commented on August 23, 2024

I currently don't have the time to take a look at this. I'll come back in 2-3 weeks.

from esp-knx-ip.

ascillato avatar ascillato commented on August 23, 2024

from esp-knx-ip.

ascillato avatar ascillato commented on August 23, 2024

Hi @envy ,

First of all, thanks a lot for your time and patience!
This library is really good. I'm using it a lot.

What do you think of this simpified approach (following graph):

image

With the translations done by knx.config_web_UI(config_webUI); where config_webUI is

typedef struct __config_webUI
{
  const char *WebPageTitle;
  const char *PhysAddrLabel;
  const char *Set;
  const char *Add;
  const char *Delete;
} config_webUI_t;

So, the code for making that Webpage:

// Web Page Translations
#define D_CONFIGURE_KNX "Configure KNX"
#define D_KNX_PARAMETERS "KNX parameters"
#define D_KNX_GENERAL_CONFIG "General"
#define D_KNX_PHYSICAL_ADDRESS "Physical Address"
#define D_KNX_SET "Set"
#define D_KNX_ADD "Add"
#define D_DELETE "Delete"
#define D_REPLY "Reply"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Must be unique on the KNX network)"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Group Addresses to Send Data to"
#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from"
#define D_KNX_PARAMETER_TO_SEND "Parameter to Send"
#define D_KNX_UPDATE_INTERVAL "Sensor Update Interval (sec)"

// Translations
config_webUI_t config_webUI = {
  D_CONFIGURE_KNX,
  D_KNX_PHYSICAL_ADDRESS,
  D_KNX_SET,
  D_KNX_ADD,
  D_DELETE
};

// KNX WebPage Configuration
// -------------------------
// The order of the knx.***_register_*** code, is the order that is going to be shown on the web page.

// Translations
knx.config_web_UI(config_webUI);

knx.config_register_Title( D_KNX_PARAMETERS );

knx.config_register_line();

//Set Physical KNX Address of the device
knx.config_register_pa(); // to position physical address config at top of page
knx.physical_address_set(knx.PA_to_address(1, 1, 1));

knx.config_register_label( D_KNX_PHYSICAL_ADDRESS_NOTE );

knx.config_register_blankspace();

knx.feedback_register_action("KNX: " D_ON, knx_toggle_flag_enabled, D_STOP, nullptr, knx_status_enabled);
knx.feedback_register_action("KNX: " D_OFF, knx_toggle_flag_enabled, D_START, nullptr, knx_status_disabled);

knx.config_register_line();

knx.config_register_SubTitle( D_KNX_GROUP_ADDRESS_TO_WRITE );

// Register Group Addresses to Send Data to
for (int i = 0; i < Settings.knx_Registered_GA; ++i)
{
  if (device_param[i].show)
  {
    device_param[i].id = knx.config_register_ga(String(device_param[i].name));
    knx.config_set_ga(device_param[i].id, Settings.knx_GA_addr(i));
  }
}

knx.config_register_blankspace();

update_rate_id = knx.config_register_int( D_KNX_UPDATE_INTERVAL , Settings.knx_update_rate);

knx.config_register_line();

knx.config_register_SubTitle( D_KNX_GROUP_ADDRESS_TO_READ );

// Register Group Addresses to Receive data from and execute callbacks
for (int i = 0; i < Settings.knx_Registered_CB; ++i)
{
  if (device_param[i].show)
  {
    cb_conf_id = knx.callback_register( String( device_param_cb[i] ), action_cb, &device_param[i]);
    //////buscar en la config el param para setearlo
    //knx.callback_assign(ga_conf, Settings.knx_CB_addr(i));
    if (i==0)
    {
      //knx.callback_assign(cb_conf_id, knx.GA_to_address(2,2,1));
    }
  }
}

knx.config_register_line();

knx.feedback_register_action("", KNXSaveSettings, D_SAVE); // Save Button

knx.feedback_register_action("", KNX_Return_button, D_CONFIGURATION); // return to previous configuration menu

// END KNX WebPage Configuration

So, as a summary, the modifications proposed are:

Add web_ui_config functions for:

  • Webpage Title
  • Title
  • Subtitle
  • Label
  • Line
  • Blanckspace
  • config_web_ui(translations)
  • box init
  • box end

Modifications to actual functions:

  • feedback action (add the text label parameter)
  • config_set_ga (can add multiple assignations for the same relay, button, etc as callback_assign does)
    this is handy for knx scenes configurations
  • config_get_ga (as the config_set_ga can assign multiple address to the same relay, config_get_ga now can return the first address of the configured GA or the second or the one asked by param)
  • all config functions should be config_id_t so the order on the webpage is the same order in which where configured on the main program.

Add new functions:

  • Register_PA (to assing the order of physical address set on the webpage)
  • callback_get (id, seq) (when saving the configuration, it is needed for the main program to know which new assignments where done by the user, so a new function to look for callback assignments is needed)

So, what do you think?

Please, let me know where I can help you.

from esp-knx-ip.

ascillato avatar ascillato commented on August 23, 2024

Made the PR #45, #46, #47 with the knx.config_web_UI function and the modified feedback_action function with the text label added parameter.

from esp-knx-ip.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.