From 393d99860b90126eca73c8e7f09e0914f1f371e0 Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Sat, 13 Apr 2024 15:20:22 +0200 Subject: [PATCH 1/3] Extend sitemap syntax for switch to support press & release buttons Mappings attribute for switch element now accepts one or two commands for each button. If only one command is provided, the button is a click button, the command is sent to the item when the button is clicked. If two commands are provided (separated by ":"), the button is a press & release button, the first command is sent to the item when the button is pressed and the second when the button is released. Syntax example for a click button: Switch item=DemoSwitch mappings=[ ON="ON" ] Syntax example for a press & release button: Switch item=DemoSwitch mappings=[ ON:OFF="ON" ] Related to #3822 Signed-off-by: Laurent Garnier --- .../openhab/core/io/rest/sitemap/internal/MappingDTO.java | 2 ++ .../core/io/rest/sitemap/internal/SitemapResource.java | 2 ++ .../src/org/openhab/core/model/sitemap/Sitemap.xtext | 2 +- .../ui/internal/components/UIComponentSitemapProvider.java | 5 ++++- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/MappingDTO.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/MappingDTO.java index d7a91db619f..4ba0ca04853 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/MappingDTO.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/MappingDTO.java @@ -18,12 +18,14 @@ * @author Kai Kreuzer - Initial contribution * @author Laurent Garnier - New fields position and icon * @author Laurent Garnier - Replace field position by fields row and column + * @author Laurent Garnier - New field releaseCommand */ public class MappingDTO { public Integer row; public Integer column; public String command; + public String releaseCommand; public String label; public String icon; diff --git a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java index 2a2c82fe546..fd30c6a1c08 100644 --- a/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java +++ b/bundles/org.openhab.core.io.rest.sitemap/src/main/java/org/openhab/core/io/rest/sitemap/internal/SitemapResource.java @@ -139,6 +139,7 @@ * @author Laurent Garnier - Added icon field for mappings used for switch element * @author Laurent Garnier - Support added for multiple AND conditions in labelcolor/valuecolor/visibility * @author Laurent Garnier - New widget icon parameter based on conditional rules + * @author Laurent Garnier - Added releaseCmd field for mappings used for switch element */ @Component(service = { RESTResource.class, EventSubscriber.class }) @JaxrsResource @@ -565,6 +566,7 @@ private PageDTO createPageBean(String sitemapName, @Nullable String title, @Null for (Mapping mapping : switchWidget.getMappings()) { MappingDTO mappingBean = new MappingDTO(); mappingBean.command = mapping.getCmd(); + mappingBean.releaseCommand = mapping.getReleaseCmd(); mappingBean.label = mapping.getLabel(); mappingBean.icon = mapping.getIcon(); bean.mappings.add(mappingBean); diff --git a/bundles/org.openhab.core.model.sitemap/src/org/openhab/core/model/sitemap/Sitemap.xtext b/bundles/org.openhab.core.model.sitemap/src/org/openhab/core/model/sitemap/Sitemap.xtext index 37dad8bd62b..bbb6f4afcb2 100644 --- a/bundles/org.openhab.core.model.sitemap/src/org/openhab/core/model/sitemap/Sitemap.xtext +++ b/bundles/org.openhab.core.model.sitemap/src/org/openhab/core/model/sitemap/Sitemap.xtext @@ -204,7 +204,7 @@ Button: row=INT ':' column=INT ':' cmd=Command '=' label=(ID | STRING) ('=' icon=Icon)?; Mapping: - cmd=Command '=' label=(ID | STRING) ('=' icon=Icon)?; + cmd=Command (':' releaseCmd=Command)? '=' label=(ID | STRING) ('=' icon=Icon)?; VisibilityRule: conditions+=Condition ('AND' conditions+=Condition)*; diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java index f07ef8cdedf..0dc2e185b42 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java @@ -359,11 +359,14 @@ private void addWidgetMappings(EList mappings, UIComponent component) { for (Object sourceMapping : (Collection) sourceMappings) { if (sourceMapping instanceof String) { String[] splitMapping = sourceMapping.toString().split("="); - String cmd = splitMapping[0].trim(); + String[] splitCmd = splitMapping[0].trim().split(":"); + String cmd = splitCmd[0].trim(); + String releaseCmd = splitCmd.length < 2 ? null : splitCmd[1].trim(); String label = splitMapping[1].trim(); String icon = splitMapping.length < 3 ? null : splitMapping[2].trim(); MappingImpl mapping = (MappingImpl) SitemapFactory.eINSTANCE.createMapping(); mapping.setCmd(cmd); + mapping.setReleaseCmd(releaseCmd); mapping.setLabel(label); mapping.setIcon(icon); mappings.add(mapping); From afb350a3e88428d4f5674d28dd39b6763698c6ff Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Fri, 19 Apr 2024 10:22:23 +0200 Subject: [PATCH 2/3] Fix commands parsing for sitemap generator Signed-off-by: Laurent Garnier --- .../UIComponentSitemapProvider.java | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java index 0dc2e185b42..fdc2d4f00a9 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java @@ -99,6 +99,11 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan private static final Pattern CONDITION_PATTERN = Pattern .compile("(?[A-Za-z]\\w*)?\\s*(?==|!=|<=|>=|<|>)?\\s*(?\\+|-)?(?.+)"); + private static final Pattern COMMANDS_PATTERN1 = Pattern.compile("^\"(?[^\"]*)\":\"(?[^\"]*)\"$"); + private static final Pattern COMMANDS_PATTERN2 = Pattern.compile("^\"(?[^\"]*)\":(?.*)$"); + private static final Pattern COMMANDS_PATTERN3 = Pattern.compile("^(?.*):\"(?[^\"]*)\"$"); + private static final Pattern COMMANDS_PATTERN4 = Pattern.compile("^\"(?.*)\"$"); + private static final Pattern COMMANDS_PATTERN5 = Pattern.compile("^(?.*):\"(?.*)$"); private Map sitemaps = new HashMap<>(); private @Nullable UIComponentRegistryFactory componentRegistryFactory; @@ -359,9 +364,36 @@ private void addWidgetMappings(EList mappings, UIComponent component) { for (Object sourceMapping : (Collection) sourceMappings) { if (sourceMapping instanceof String) { String[] splitMapping = sourceMapping.toString().split("="); - String[] splitCmd = splitMapping[0].trim().split(":"); - String cmd = splitCmd[0].trim(); - String releaseCmd = splitCmd.length < 2 ? null : splitCmd[1].trim(); + String cmd = splitMapping[0].trim(); + String releaseCmd = null; + Matcher matcher = COMMANDS_PATTERN1.matcher(cmd); + if (matcher.matches()) { + cmd = matcher.group("cmd1"); + releaseCmd = matcher.group("cmd2"); + } else { + matcher = COMMANDS_PATTERN2.matcher(cmd); + if (matcher.matches()) { + cmd = matcher.group("cmd1"); + releaseCmd = matcher.group("cmd2"); + } else { + matcher = COMMANDS_PATTERN3.matcher(cmd); + if (matcher.matches()) { + cmd = matcher.group("cmd1"); + releaseCmd = matcher.group("cmd2"); + } else { + matcher = COMMANDS_PATTERN4.matcher(cmd); + if (matcher.matches()) { + cmd = matcher.group("cmd"); + } else { + matcher = COMMANDS_PATTERN5.matcher(cmd); + if (matcher.matches()) { + cmd = matcher.group("cmd1"); + releaseCmd = matcher.group("cmd2"); + } + } + } + } + } String label = splitMapping[1].trim(); String icon = splitMapping.length < 3 ? null : splitMapping[2].trim(); MappingImpl mapping = (MappingImpl) SitemapFactory.eINSTANCE.createMapping(); From 6e05d914f04b78898bf5353472e1f6ec22c967ea Mon Sep 17 00:00:00 2001 From: Laurent Garnier Date: Tue, 30 Apr 2024 14:12:14 +0200 Subject: [PATCH 3/3] Remove changes in UIComponentSitemapProvider Changes will be done in a separate PR. Signed-off-by: Laurent Garnier --- .../UIComponentSitemapProvider.java | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java index fdc2d4f00a9..f07ef8cdedf 100644 --- a/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java +++ b/bundles/org.openhab.core.ui/src/main/java/org/openhab/core/ui/internal/components/UIComponentSitemapProvider.java @@ -99,11 +99,6 @@ public class UIComponentSitemapProvider implements SitemapProvider, RegistryChan private static final Pattern CONDITION_PATTERN = Pattern .compile("(?[A-Za-z]\\w*)?\\s*(?==|!=|<=|>=|<|>)?\\s*(?\\+|-)?(?.+)"); - private static final Pattern COMMANDS_PATTERN1 = Pattern.compile("^\"(?[^\"]*)\":\"(?[^\"]*)\"$"); - private static final Pattern COMMANDS_PATTERN2 = Pattern.compile("^\"(?[^\"]*)\":(?.*)$"); - private static final Pattern COMMANDS_PATTERN3 = Pattern.compile("^(?.*):\"(?[^\"]*)\"$"); - private static final Pattern COMMANDS_PATTERN4 = Pattern.compile("^\"(?.*)\"$"); - private static final Pattern COMMANDS_PATTERN5 = Pattern.compile("^(?.*):\"(?.*)$"); private Map sitemaps = new HashMap<>(); private @Nullable UIComponentRegistryFactory componentRegistryFactory; @@ -365,40 +360,10 @@ private void addWidgetMappings(EList mappings, UIComponent component) { if (sourceMapping instanceof String) { String[] splitMapping = sourceMapping.toString().split("="); String cmd = splitMapping[0].trim(); - String releaseCmd = null; - Matcher matcher = COMMANDS_PATTERN1.matcher(cmd); - if (matcher.matches()) { - cmd = matcher.group("cmd1"); - releaseCmd = matcher.group("cmd2"); - } else { - matcher = COMMANDS_PATTERN2.matcher(cmd); - if (matcher.matches()) { - cmd = matcher.group("cmd1"); - releaseCmd = matcher.group("cmd2"); - } else { - matcher = COMMANDS_PATTERN3.matcher(cmd); - if (matcher.matches()) { - cmd = matcher.group("cmd1"); - releaseCmd = matcher.group("cmd2"); - } else { - matcher = COMMANDS_PATTERN4.matcher(cmd); - if (matcher.matches()) { - cmd = matcher.group("cmd"); - } else { - matcher = COMMANDS_PATTERN5.matcher(cmd); - if (matcher.matches()) { - cmd = matcher.group("cmd1"); - releaseCmd = matcher.group("cmd2"); - } - } - } - } - } String label = splitMapping[1].trim(); String icon = splitMapping.length < 3 ? null : splitMapping[2].trim(); MappingImpl mapping = (MappingImpl) SitemapFactory.eINSTANCE.createMapping(); mapping.setCmd(cmd); - mapping.setReleaseCmd(releaseCmd); mapping.setLabel(label); mapping.setIcon(icon); mappings.add(mapping);