-
Notifications
You must be signed in to change notification settings - Fork 782
Proposal for a new Sitemap concept #5337
Comments
Many thanks for your elaborate concept, @flaviocosta-net! |
Wow, that's a pretty thorough concept! I very much like this approach. As you said, it's still on an abstract level, but on that level it fully makes sense from my point of view. And judging from the likes it got, I think it is safe to say I'm not the only one 😉 Especially the separation between the definition model and the rendering model is something which will be of great benefit and although we are missing it today, there are similar aspect buried deep in the o.e.sh.ui bundle and the corresponding ui implementation bundles. I only see a few minor details (like e.g. giving enough styling guidance while leaving enough room for UIs to stay responsive, icon set handling with "classic" being only one example) right now which might be worth discussing, but as I also expect that some more will surface as soon as it goes into the implementation phase, I don't think it makes sense to spend any time with them right now. I also spend some time thinking about whether it's good to create "our own" template engine/language, but so far I tend to agree that it is smarter to simply to it here - it's only a very small and limited but at the same time rather specialized subset of what all the available templating frameworks deliver. So with the goal of keeping the overall footprint of ESH as small as possible, I currently agree that it is best like you proposed it. All in all I'm convinced that it's worth a try to implement the basics of this proposal. How should we proceed with this? You outlined some pretty clear steps, of course. Ideally I would like to keep it as simple as possible and rather have multiple iterations on it in order to minimize the overall risks. Limiting the focus on the feature-set of today's sitemaps might be a feasible approach in order to reduce the scope in the first iteration, what do you think? Would you be willing to also start with the implementation? That clearly would be awesome, of course! My apologies, if this sounded like a stupid question - as you don't have a contribution record here I simply can't tell whether you are into coding at all, nor if you are willing (and allowed?) to dedicate the time on it 😄 Either way, I'm happy you spent the time on this concept, it by far supersedes the initial attempt from the ESH Forum. I'm really looking forward to seeing the legacy sitemaps to getting such a great overhaul! |
Hello @SJKA, thanks for the feedback! As I was writing down these ideas, there were many uncertain issues that came to mind: whether icon set handling was being properly considered, if/how we should support sitemap elements with "Default" type or deprecate that, what is the best way to handle languages/i18n, which changes are needed for notifications/SSE, but I assumed that during a first implementation attempt these and other issues would become clearer, and then decisions would have to be made. For the template engine used on prototype expansion, this is something that could also be done completely on Java: we could provide an abstract Java class with a default SmartHome implementation/subclass that basically performs the expansion logic outlined above. Developers can later create their own subclasses to customize the default behavior, and one possible subclass would read the expansion rules from a json file, rather than having them hard-coded on Java, so this declarative expansion customization can be added a bit later if the value becomes more evident. I agree that we should start focused on building the feature set that is equivalent to today's sitemap, and once this is mostly working then we expand to new improvements (the prototype expansion layer would probably be discussed at that moment). I can start working on the implementation (I actually have a binding I've developed running well on my server, soon I should be creating a fork to have it eventually contributed to ESH). Anyway, there is definitely a lot of implementation work to be done for this sitemap concept, and it is essentially composed of two main parts:
What do you think? |
Sure, that makes sense. I also don't have perfect answers for all those detail questions yet. Just some initial thoughts, but overall I share your opinion that it might be easiest to have a look at them individually while working on a PR on code:
Using a completely new UI for show-casing the client-side implementation sounds like a good idea to me. It will have to be "close" to you though, because we might require to change stuff incompatibly in the early stages. Therefore I wouldn't let other "external" UIs adapt to it in the beginning. The next ones indeed should be the ones in ESH, i.e. the Basic UI (and maybe even the Classic UI?) because changes there are easiest to synchronize. With the stuff "buried deep in the o.e.sh.ui bundle" I mainly meant ItemUIRegistryImpl.java. It's been growing a lot over time and has proven to be quite prone to regressions and collateral damages. So I wouldn't be too sad if we will have to rewrite major parts of it 😉 I'm happy to help with this. Also I'd think that @resetnow and @lolodomo might be happy to join in at some point. |
Sounds good, I will start putting some work on the client side and once I have something that would allow some initial testing then I will see how I can help on the server-side, thanks!
|
To give an update on this, I finally have some working code! As expected, it was a very helpful exercise to refine some ideas and get closer to actual implementation. Here is the rendering model being used as an input:
It produces the following UI: When you click on the Multimedia group, it loads the following rendering model:
This is how it looks like in the application: I will just give a final review to the code, especially making sure Javadocs are accurate and help understand the concepts and implementation. I should have it ready to be put somewhere on GitHub soon. Once this is done, I will start having a look on the server-side code, since the client application is just simulating the sitemap with local files and it will need to start talking to REST APIs in order to validate and refine the concepts. |
Cool, thanks for the update! This indeed looks like a really helpful exercise to validate the requirements towards the rendering model. I'm looking forward to seeing the next steps! I'd reckon that will be the definition model and application of the prototypes/templates on the server-side, right? |
Here is the link to the repository: https://github.com/flaviocosta-net/openhab-javafx I am not sure it is organized the best possible way, as it's the first time I push code on GitHub, so please let me know if there is anything to improve on that. For the code itself, it's obviously still very basic and there should be a lot more progress when integration with the REST API is started. It mostly uses plain Java with generics, there are no extra dependencies such as EMF that we see on the server-side model. Comments on the source code itself include more details about the implementation, ideas and pending items. For the next steps, we now need to load the sitemap (DSL?), process it and deliver the rendering model through the API. My understanding is that http://hostname:port/rest/sitemaps should be the entry point for the API, but it should not list new sitemaps for existing (legacy) clients, and new clients should have the option to ignore legacy sitemaps. There are multiple ways of doing this:
What would be the recommended solution for that? Also, on the code that reads the sitemap definition ( |
By the way, how can I use ESH classes on a client application? I would like to use SitemapDTO to deserialize the API response, but I can't find an example on how to have the required dependency on a plain Maven/non-Tycho project. This is the pom.xml I am playing with, it doesn't seem to help resolve any ESH dependencies:
|
@kaikreuzer, thanks for the reference to smarthome-packaging-sample, I adapted my POM and it works like a charm! Indeed The good news is that this new sitemap implementation will probably help reduce some of this coupling, as the information on the rendering model (i.e. what the client sees) is all expressed in terms of Components (Containers and Atoms), there are no direct references to extraneous entities such as Items (these should be fully resolved on the server side). In fact, I must start working on server code as some of the code I put on the client actually belongs on the server - for instance, After considering these points and reading the linked discussions, I think a good implementation approach would be:
|
I'm working with two machines for the same building. (For testing purposes) I don't want to have to make changes manually on a machine. |
I understand that multi-language is something to do after the basic features are done. I don't understand the sentence:
|
A scenario with two servers is not a usual one, and retrieving definitions from a remote location is a completely separate topic.
This is a standard content negotiation mechanism for HTTP, and it will also require clients sending language preferences to the server. This should be part of the new proposal, it just cannot be the first requirement being implemented... |
Anyone who wants to (re) install a new server will run into same issue. I just do this every week, hence I bought me a seconds server to make it easier to install the latest version of openhab, without less risk to have an unstable server.
For me it's not. This is how sitemaps work these days.
Do I understand correctly you will work with a language of the browser/ phone Moreover linking the localisation to the language is very bad. The document you linked to says something similar: "It is not a good idea to use the HTTP Accept-Language header alone to determine the locale of the user. If you use Accept-Language exclusively, you may handcuff the user into a set of choices not to his liking." |
Keeping the sitemap in the local memory cache is the way it's already implemented today, so maybe I didn't completely understand your use case. The idea is to make the new sitemap implementation a superset of the existing one: everything that works today should keep working with no or minimal changes. Before the new implementation is released, please feel free to try it and flag any currently supported features that may be missing.
No, on most standard web browsers the language settings are configurable by the user, the same should apply to sitemap clients. What the link indicates, however, is that multi-language support is just one part of the features required for localization/internationalization, and it should take some good amount of work to get full support for that especially on a multi-user environment that you describe. This doesn't mean that it won't be eventually implemented. |
I use the same browser to acces:
This general means that my main language is English on most of my browsers. My tablet and my phone are also used by my kids so the language is set to Dutch. Yes that can be done using different sitemaps, and that is fine for now, yet when you implement multi-language in sitemaps, i'm telling you it's not usable when it's based on the browser or tablet language setting. y |
@yveshanoulle, I will take that into consideration, although:
For now, I have created a fork to start working on it and see where it goes. |
1)a) We would like to use tablets in our facility to control openhab. Asking users to log in as different users would remove the opportunity to reuse the same tablet for everyone in a room/ building. b) It's only a client problem because you make it one. Many websites/ web applications offer to switch the language and ignore the browsers language. I'm probably more used to these kind of websites because I'm from Belgium where we do have three official languages (and most Belgium alos speak English which is not even an official language, then people who's country only has one language.
Thanks |
I have done some preliminary work on this: now I have a minimal DSL that generates what would be the definition model (with Xtext) and I have some ideas on how the SitemapProvider can be adjusted to provide sitemaps both in the current and the new formats. The big piece missing is what should happen between those two parts: the generation of the rendering model (that is sent to the client) from the definition model (either from a file written in DSL, or as a JSON that can be edited via the REST API). Either way, only the definition model is actually editable, the rendering model is read-only and regenerated whenever a client requests a sitemap view. I still think we need some kind of engine doing that, because it would be used both to customize and reuse component definitions. The idea I originally drafted above is more or less what we see on JSONT, but the concept is somehow old and still I could not find any working Java implementation. Moreover, we probably should not be transforming a definition JSON to rendering JSON, that transformation should ideally be done directly on the Java model, which is an operation that may be performed with an existing Eclipse tool:
It someone here has experience with any of these technologies, that might help guide the selection of the most suitable option... otherwise I will see when I have the time to try out these tools and see which one would be the best fit. |
Hello @maggu2810, the idea is to apply the existing solution used in REST resources, that you mention above, to the new sitemap implementation as well. However, ultimately Yves was raising another, related requirement: to allow users to select the sitemap display language via some component of the sitemap itself - for instance, with a Select element that will dynamically offer all available languages, so once the user selects one of the options, the sitemap is reloaded and the new language becomes effective for that session. This is something easy to do on an HTML web site, but not so much on a REST API which is stateless and has a much more strict contract with its clients. |
To provide an update on this, I have a proof-of-concept implementation showing a basic end-to-end processing almost ready. The new DSL looks very close to what could be its final shape, the transformation from definition models into rendering models has a robust design, and the data to be sent to the client is already accessible on SitemapResource. I started testing based on the demo sitemap that comes with ESH, since it already has the things and items defined to support it. This is how the same sitemap is expressed with the new DSL:
String values may be specified either as a "fixed string" (between quotes), or via an [expression] (within square brackets) that is calculated dynamically. Styles can also be specified via expressions, so they can be calculated and updated based on any combination of item states and functions. For the generation of the rendering model from the definition model, I first experimented with VIATRA - while it has some very cool features such as incremental model transformation, its transformations are specified with graph pattern semantics that is not easy to learn, and the framework works best with off-line/pre-compiled model transformations. Eclipse Epsilon, however, was a great match for what is needed here. Simple syntax and flexible runtime features work helped implementing the required transformation logic. These are the new bundles created so far: org.eclipse.smarthome.model.sitemap.definition.runtime org.eclipse.smarthome.model.sitemap.rendering org.eclipse.smarthome.model.sitemap.rendering.runtime org.eclipse.smarthome.model.sitemap.standard.definition org.eclipse.smarthome.model.sitemap.standard.definition.ide org.eclipse.smarthome.model.sitemap.standard.runtime There are very few changes to existing code on other bundles, the exception being org.eclipse.smarthome.io.rest.sitemap: that requires significant changes to be able to support both old and new sitemaps in the REST API. The next step is to decide how the rendering model will be serialized and sent to the client. I started adjusting the DTOs, but the work got tedious and possibly not even necessary - unlike the other models in ESH, the rendering model is not an EMF model with all the "overhead" added by EMF. It only contains the essential data that needs to be sent to the client, so it already fulfills the purpose for which apparently DTOs were introduced for the other models. Another aspect I am considering is to move away from the "paged navigation" structure of the current API. Instead, the client could retrieve the whole sitemap rendering model once its home page is accessed, and all navigation between pages would happen on the client-side without any additional communication with the server. The subscription mechanism would be used to incrementally notify all subscribed clients of any changes to the sitemap contents. These would be updated asynchronously, so the user on the client application would (almost) always have an up-to-date view of the sitemap being served from the local cache. If this approach is considered acceptable, I will proceed with this part of the implementation as explained above. |
That's indeed a big leap forwards! Thanks for sharing the update. Regarding the drop of the "paged" navigation: I personally don't see an issue with that. The amount of data transferred for the rendering model is so minimal that this kind of optimization is not necessary. It makes things much simpler if we don't have it. Do I understand you correctly that you are using Epsilon currently to transform the current, Xtext-based sitemap definition into the rendering model only? I don't know many details about the project, but it sounds like it makes sense. However, the only thing important to me is that we are able of having other sources for sitemap definitions which then won't require any dependencies on the Xtext/EMF-family. They are great technologies, but in terms of footprint we need solutions to be able to run with without, if they decide against using the DSLs. Just to be on the safe side, I thing that's worth mentioning.
That reflects my expectation. I actually don't think it is worth maintaining backwards-compatibility within io.rest.sitemap - major parts of e.g. Basic UI will need to be rewritten anyway. So it it makes things easier for you, don't hesitate to put another, new REST API next to it. PS: I'm curious to see the some code also - even if it's work-in-progress and still a mess, don't hesitate to push an intermediate state to a branch in your repository fork. |
@SJKA, thanks for the update, very appreciated!
Indeed, the rendering model for the demo sitemap has about 2.1 Kb, even if the sitemap was 100 times bigger it would still be only 210 Kb, still small enough to be completely transferred in one shot without any significant delays. In fact, I finished implementing that part - you can see below the (old) sitemap on the Basic UI and the (new) sitemap as currently displayed by the JavaFX UI, on the right: The new implementation allows the user to navigate between the pages without requesting any data from the server, so the pages are displayed immediately. Any updates (to atom data or component styles) will be pushed to the client asynchronously, via SSE/streaming API - this is probably the next step in the implementation.
It is there to convert the new (also Xtext) definition model into the rendering model. The only bundle where Epsilon is used is org.eclipse.smarthome.model.sitemap.standard.runtime, as it contains the code required to perform this transformation from the standard (new) sitemap implementation into the rendering model. Another bundle can be written to convert the old sitemap model into the rendering model; the client would consume it without really knowing if the respective definition model is specified in a file in a different DSL or JSON stored in a database. The current ESH dependency on EMF is actually hard-coded into the ModelRepository, which explicitly returns models as EObjects. Coincidentally, Epsilon has its own class also named ModelRepository which makes no reference to anything related to EMF, as it is designed to be independent from specific back-end representations.
Lots of existing code will eventually be removed - yes, ItemUIRegistryImpl will become obsolete, being replaced by an Epsilon transformation script such as the one attached here: SitemapRendering.zip Still, there are other important clients such as the ones for Android and iOS, not sure how quickly these will be adjusted, so the existing sitemap REST API may need to keep running for some time. Currently there are no unit tests yet and Javadoc are missing here and there, but otherwise the code developed so far should be relatively presentable already. I will check how to properly put this in a branch, as I want to avoid a mess with that and I don't have much experience with Git. |
…maps This is still work in progress, this commit is being done just before the SSE implementation is started. It may also include some JSON-B code and dependencies that will possibly be removed before this branch is merged into the central master. I also had to revert 'rule' and 'script' model bundles to previous versions because the latest from central master were not working, need to resolve that later.
@SJKA, I have pushed the code into a new branch on my fork repository. I hope it was done more or less correctly, please let me know if you see something that needs to be fixed on that. Obviously, in case you have comments, questions and suggestions regarding the code in its current shape, I would look forward into hearing these so any improvements can be done sooner than later, As mentioned above, I should now proceed with the required SSE implementation. |
@flaviocosta-net I just found this issue and I must say that this already looks amazing, awesome work! OpenHab is awesome (I'm in process of migrating to 2.4) but it is missing UI features that could be used to build UI for demanding users (for example for wifes 😊 ) P.S. |
I was talking about how the sitemap is transferred to the server. Today I create all my configuration in files on a local computer, that get uploaded to a source control system. Then I download them on the openhab server, either The server then gets the files, openhab sees the changes and reloads them in memory. y |
@flaviocosta-net There is quite some interest in the community to drive the new sitemaps forward. As ESH has been terminated, could you port your code over to https://github.com/openhab/openhab-core and possibly directly create a WIP PR with it? |
This issue is a transfer of the respective ESH forum topic to GitHub.
The idea is to propose a new Sitemap concept that would help overcome various problems seen on the current sitemap implementation:
New or Renewed Concepts
Sample Sitemap
I'd like to start with the sample sitemap definition written in the current DSL that we find on the openHAB documentation:
This is the expected visual rendering for this sitemap:
In this proposal, this same sitemap could be specified with the following JSON:
Except for the added "components" and "state" elements, this is almost a 1-to-1 mapping of the DSL to JSON. This approach can make it easier to understand the new concepts and how they can support backwards compatibility with the existing sitemap definition files. The system can easily parse a source file in the sitemap DSL and convert it to the JSON format, using the resulting structure for all further processing while still giving the user the convenience of the shorter DSL syntax.
The idea is to put most of the processing burden on the server side, so content and formatting are added on top of the input JSON (sitemap definition model) to generate a rendering model that is sent to the UI with the contents of the current page. The rendering model for the initial page of the above sitemap could look like this:
Sitemap rendering
In order to convert a definition model into the respective rendering model, a SitemapRenderer service needs the following inputs:
The style definition specifies how containers and atoms will be formatted. The approach used here is similar to the one adopted by JavaFX: while standard CSS syntax is used, it does not support some CSS layout properties such as float, position or overflow. The style actually provides a theme to format the sitemap components and it may be customized by the user. The disposition of the elements is determined by the "layout" attribute seen on the rendering model. This is different from the current sitemap solution, where colors, size, margins and fonts are decided by the client GUI. By following a style definition imposed on the server side, now the sitemap will have a more consistent look on the Basic UI, or on various mobile clients.
The prototype definition determines how the elements in the definition model will be restructured to form the component types in the rendering model. The prototypes can also be customized by the user, by editing the existing prototypes or creating new ones. This flexible abstraction layer allows component definitions reuse across the sitemap.
The following style file should generate output with formatting similar to the sitemap screenshot seen above:
The CSS class name (for instance, .frame seen on the first definition above) needs to match the component type. The SitemapRenderer on the server side adds these style definitions to each component where they apply, so the client doesn't need to bother with stylesheet inheritance - each component specifies on its "style" attribute any formatting options to be applied. If there is no style for a certain component, then the client UI can decide its default formatting. Usage of standard CSS syntax and semantics make it easier to implement web browser-based UIs, which already include built-in support for CSS.
Here is an example of a prototype definition file that would work for the sitemap concepts used in the sample above:
Let's analyze each line of the "sitemap" prototype to understand how it works:
When the "smarthome" element is found in the sitemap definition model, the renderer expands this prototype.
The name of the resulting element will be "sitemap".
The type property will be set to "smarthome". The "$" character is a JSONPath reference to the original element in the definition model, which happens to be "smarthome". We are not using an explicit reference to a JSONPATH transformation, but we may decide that it's better to have that either with a "FUNCTION()" syntax or as a "namespace:".
The data property will be set to a JSON, containing an id and a label copied from the original definition element, also using JSONPath syntax. The lang property is passed to the client to indicate the language of the components in the container. It can be used, for instance, to change text alignment or even rearrange the atoms to better suit a language written from right-to-left, such as Hebrew or Arabic. Based on the specification in the prototype, the renderer will first try to read a lang attribute from the source element in the definition model. If absent, then it retrieves the language from the system settings (i.e. using the system: namespace).
The layout property does not come form the definition model, it is fixed in this prototype. The value "list" is a reference to the Material Design concept of a list, so this is informing the UI that it should arrange the components of the container as a list:
The recursive descent operator (..) followed by the wildcard (*) tells the renderer to recursively retrieve all members contained under components (and expand the relevant prototypes as needed).
There are also some atoms under the "text" prototype using a special syntax that is worth explaining here:
The icon data will have an id and a value. The id will be the icon attribute in the definition model, or if it's missing then it's the icon attribute on the associated item (via the item: namespace), else it will be the icon "text" from the classic iconset (via the classic: namespace). The value attribute is always the state of the associated item.
Once the prototype expander meets an element named "metadata", it knows that the elements immediately below it should not simply be sent to the output, put interpreted in a certain way to decide how the prototype is expanded. On the example above, if there is a member "components" on the definition model, the third (rightmost) atom will be rendered as a "group" atom; if absent, we render it as a regular "text" atom.
We can notice that the "Multimedia" element on our example sitemap does contain components, so it was rendered as a group with data "components:4" (meaning the fourth occurrence of "components" in the definition model). When the user clicks on the arrow on this component, the client makes a REST API call to the server which returns the sitemap view for that specific page, to display the contained components:
On a very high level, the main work performed by the SitemapRenderer is:
The namespaces mentioned in this example are:
Now let's demonstrate "dynamic sitemap" features that match the existing capabilities of the sitemap:
Below we can see the resulting rendering model - you will notice that the visibility and labelcolor definitions are implemented by the renderer as specific CSS styles (e.g. "display:none;color:orange"). Since style processing cannot be implemented via prototype expansion, we would need the Java implementation for the NamespaceReferenceResolver to apply the required logic once it sees smarthome:visibility and visibility:labelcolor elements.
Extension and reuse
One virtue of the proposed solution is the fact that definitions can be added or changed declaratively.
Styles can be adjusted by editing the style file. Alternative style files can also be provided, giving the user the option to select in the UI which theme to use. The API endpoint that lists the available sitemaps can also return the available styles or themes available for each sitemap, for instance:
New prototypes can be created, and they may also be based on existing prototypes. For instance, I may want to have all my smart bulbs to have the same icon and with intensity changed by predefined mapping options:
When the renderer identifies that "lightselection" is mapped to another prototype "selection", it takes the intermediate structure and apply the second prototype to it, which will then generate the atoms and stop the processing of this element. Now we can use our new prototype on the sitemap definition model:
The rendering model will have fully expanded containers and/or atoms:
Another possible customization via the prototypes would be to convert the standard sitemap layout into a dashboard-like interface: instead of "list" layout on the sitemap and "listcontrol" for the inner containers, the layouts "cardcollection" and "card" could be used respectively to display widgets in a very different way:
The prototype expansion functionality is actually generic enough that it could even be used for other purposes not in the sitemap scope, such as allowing the creation of reusable Item definitions.
Other possible new features that are not supported by the current sitemap could be:
This proposal is still on a very abstract level, and some adjustments would likely be needed once certain issues became more obvious during an implementation attempt. Topics such as SSE and notifications are not addressed here yet. There are also some interesting features that I've left aside here, such as the possibility of using an indoor positioning system (e.g. FIND) to automatically set the current page that corresponds to the room the user currently is in.
Implementation
The core steps/modules to accomplish the proposal above could be:
There is also some additional work required for a complete solution:
The text was updated successfully, but these errors were encountered: