]> git.basschouten.com Git - openhab-addons.git/blob
d2f6295b1da76d2cfeaf915f894a319508be8401
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.mielecloud.internal.config.servlet;
14
15 import java.io.IOException;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.stream.Collectors;
19
20 import javax.servlet.http.HttpServletRequest;
21 import javax.servlet.http.HttpServletResponse;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.openhab.binding.mielecloud.internal.MieleCloudBindingConstants;
25 import org.openhab.binding.mielecloud.internal.config.ThingsTemplateGenerator;
26 import org.openhab.core.config.discovery.DiscoveryResult;
27 import org.openhab.core.config.discovery.inbox.Inbox;
28 import org.openhab.core.thing.Bridge;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingRegistry;
31 import org.openhab.core.thing.ThingStatus;
32
33 /**
34  * Servlet showing the account overview page.
35  *
36  * @author Björn Lange - Initial Contribution
37  */
38 @NonNullByDefault
39 public final class AccountOverviewServlet extends AbstractShowPageServlet {
40     private static final long serialVersionUID = -4551210904923220429L;
41     private static final String ACCOUNTS_SKELETON = "index.html";
42
43     private static final String BRIDGES_TITLE_PLACEHOLDER = "<!-- BRIDGES TITLE -->";
44     private static final String BRIDGES_PLACEHOLDER = "<!-- BRIDGES -->";
45     private static final String NO_SSL_WARNING_PLACEHOLDER = "<!-- NO SSL WARNING -->";
46
47     private final ThingRegistry thingRegistry;
48     private final Inbox inbox;
49     private final ThingsTemplateGenerator templateGenerator;
50
51     /**
52      * Creates a new {@link AccountOverviewServlet}.
53      *
54      * @param resourceLoader Loader to use for resources.
55      * @param thingRegistry openHAB thing registry.
56      * @param inbox openHAB inbox for discovery results.
57      */
58     public AccountOverviewServlet(ResourceLoader resourceLoader, ThingRegistry thingRegistry, Inbox inbox) {
59         super(resourceLoader);
60         this.thingRegistry = thingRegistry;
61         this.inbox = inbox;
62         this.templateGenerator = new ThingsTemplateGenerator();
63     }
64
65     @Override
66     protected String handleGetRequest(HttpServletRequest request, HttpServletResponse response)
67             throws MieleHttpException, IOException {
68         String skeleton = getResourceLoader().loadResourceAsString(ACCOUNTS_SKELETON);
69         skeleton = renderBridges(skeleton);
70         skeleton = renderSslWarning(request, skeleton);
71         return skeleton;
72     }
73
74     private String renderBridges(String skeleton) {
75         List<Thing> bridges = thingRegistry.stream().filter(this::isMieleCloudBridge).collect(Collectors.toList());
76         if (bridges.isEmpty()) {
77             return renderNoBridges(skeleton);
78         } else {
79             return renderBridgesIntoSkeleton(skeleton, bridges);
80         }
81     }
82
83     private String renderNoBridges(String skeleton) {
84         return skeleton.replace(BRIDGES_TITLE_PLACEHOLDER, "There is no account paired at the moment.")
85                 .replace(BRIDGES_PLACEHOLDER, "");
86     }
87
88     private String renderBridgesIntoSkeleton(String skeleton, List<Thing> bridges) {
89         StringBuilder builder = new StringBuilder();
90
91         int index = 0;
92         Iterator<Thing> bridgeIterator = bridges.iterator();
93         while (bridgeIterator.hasNext()) {
94             builder.append(renderBridge(bridgeIterator.next(), index));
95             index++;
96         }
97
98         return skeleton.replace(BRIDGES_TITLE_PLACEHOLDER, "The following bridges are paired")
99                 .replace(BRIDGES_PLACEHOLDER, builder.toString());
100     }
101
102     private String renderBridge(Thing bridge, int index) {
103         StringBuilder builder = new StringBuilder();
104         builder.append("                    <li>\n");
105
106         String thingUid = bridge.getUID().getAsString();
107         String thingId = bridge.getUID().getId();
108         builder.append("                        ");
109         builder.append(thingUid.substring(0, thingUid.length() - thingId.length()));
110         builder.append(" ");
111         builder.append(thingId);
112         builder.append(" ");
113         builder.append(bridge.getConfiguration().get(MieleCloudBindingConstants.CONFIG_PARAM_EMAIL).toString());
114         builder.append("\n");
115
116         builder.append("                        <span class=\"status ");
117         final ThingStatus status = bridge.getStatus();
118         if (status == ThingStatus.ONLINE) {
119             builder.append("online");
120         } else {
121             builder.append("offline");
122         }
123         builder.append("\">");
124         builder.append(status.toString());
125         builder.append("</span>\n");
126
127         builder.append("                        <input class=\"trigger\" id=\"mielecloud-account-");
128         builder.append(thingId);
129         builder.append("\" type=\"checkbox\" name=\"things-file\" />\n");
130
131         builder.append("                        <label for=\"mielecloud-account-");
132         builder.append(thingId);
133         builder.append("\">&lt; &gt;</label>\n");
134
135         builder.append("                        <div class=\"things\">\n");
136         builder.append(
137                 "                            <span class=\"legend\">You can use this things-file template to pair all available devices:</span>\n");
138         builder.append("                            <div class=\"code-container\">\n");
139         builder.append(
140                 "                                <a href=\"#\" onclick=\"copyCodeToClipboard(event, this);\" class=\"btn btn-outline-info btn-sm copy\">Copy</a>\n");
141         builder.append("                                <textarea readonly>");
142         builder.append(generateConfigurationTemplate((Bridge) bridge));
143         builder.append("</textarea>\n");
144         builder.append("                            </div>\n");
145         builder.append("                        </div>\n");
146         builder.append("                    </li>");
147
148         return builder.toString();
149     }
150
151     private String generateConfigurationTemplate(Bridge bridge) {
152         List<Thing> pairedThings = thingRegistry.stream().filter(thing -> isConnectedVia(thing, bridge))
153                 .collect(Collectors.toList());
154         List<DiscoveryResult> discoveryResults = inbox.stream()
155                 .filter(discoveryResult -> willConnectVia(discoveryResult, bridge)).collect(Collectors.toList());
156
157         return templateGenerator.createBridgeAndThingConfigurationTemplate(bridge, pairedThings, discoveryResults);
158     }
159
160     private boolean isConnectedVia(Thing thing, Bridge bridge) {
161         return bridge.getUID().equals(thing.getBridgeUID());
162     }
163
164     private boolean willConnectVia(DiscoveryResult discoveryResult, Bridge bridge) {
165         return bridge.getUID().equals(discoveryResult.getBridgeUID());
166     }
167
168     private boolean isMieleCloudBridge(Thing thing) {
169         return MieleCloudBindingConstants.THING_TYPE_BRIDGE.equals(thing.getThingTypeUID());
170     }
171
172     private String renderSslWarning(HttpServletRequest request, String skeleton) {
173         if (!request.isSecure()) {
174             return skeleton.replace(NO_SSL_WARNING_PLACEHOLDER,
175                     """
176                             <div class="alert alert-danger" role="alert">
177                                                 Warning: We strongly advice to proceed only with SSL enabled for a secure data exchange.
178                                                 See <a href="https://www.openhab.org/docs/installation/security.html">Securing access to openHAB</a> for details.
179                                             </div>\
180                             """);
181         } else {
182             return skeleton.replace(NO_SSL_WARNING_PLACEHOLDER, "");
183         }
184     }
185 }