]> git.basschouten.com Git - openhab-addons.git/blob
c073813bc15ee624a57392d66f2eca4d150e4c57
[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.networkupstools.internal.nut;
14
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Util class to process NUT List results.
26  *
27  * @author Hilbrand Bouwkamp - Initial contribution
28  */
29 @NonNullByDefault
30 final class NutResponseReader {
31
32     private static final String BEGIN_LIST = "BEGIN LIST %s";
33     private static final String END_LIST = "END LIST %s";
34     private static final Pattern LIST_ROW_RESPONSE_PATTERN = Pattern.compile("([^\"]+)\"(.+)\"$");
35     private static final Pattern GET_VAR_RESPONSE_PATTERN = Pattern.compile("VAR ([^\\s]+) ([^\"]+)\"(.+)\"$");
36
37     private final Logger logger = LoggerFactory.getLogger(NutResponseReader.class);
38
39     /**
40      * Parses a NUT returned VAR.
41      *
42      * @param ups The ups the variable is for
43      * @param nut The name of the variable
44      * @param reader The reader containing the data
45      * @return variable value for given nut variable name
46      * @throws NutException Exception thrown in case of read errors
47      */
48     public String parseVariable(final String ups, final String nut, final NutSupplier<String> reader)
49             throws NutException {
50         final String line = reader.get();
51
52         if (line == null) {
53             throw new NutException(
54                     String.format("Variable '%s' for ups '%s' could not be read because nothing received", nut, ups));
55         }
56         logger.trace("Line read:{}", line);
57         final Matcher matcher = GET_VAR_RESPONSE_PATTERN.matcher(line);
58
59         if (matcher.find() && matcher.groupCount() == 3) {
60             final String matchedUps = matcher.group(1).trim();
61             final String matchedNut = matcher.group(2).trim();
62             final String value = stripVariable(matcher.group(3));
63
64             if (!ups.equals(matchedUps)) {
65                 throw new NutException(
66                         String.format("Returned value '%s' didn't match expected ups '%s'", matchedUps, ups));
67             }
68             if (!nut.equals(matchedNut)) {
69                 throw new NutException(
70                         String.format("Returned value '%s' didn't match expected nut '%s'", matchedNut, nut));
71             }
72             return value;
73         }
74         throw new NutException(String.format("Variable '%s' for ups '%s' could not be read: %s", nut, ups, line));
75     }
76
77     /**
78      * Parses a NUT returned LIST.
79      *
80      * @param type nut data type to expect in the data
81      * @param reader The reader containing the data
82      * @param variables The map to store the read nut variables
83      * @return Map of variable name and variable value pairs
84      * @throws NutException Exception thrown in case of read errors
85      */
86     public Map<String, String> parseList(final String type, final NutSupplier<String> reader) throws NutException {
87         final Map<String, String> variables = new HashMap<>();
88         logger.trace("Reading {}", type);
89         validateBegin(type, reader);
90         final int stripBeginLength = type.length() + 1;
91         final String endString = String.format(END_LIST, type);
92         String line = null;
93         boolean endFound = false;
94
95         while (!endFound) {
96             line = reader.get();
97             if (line == null) {
98                 throw new NutException("Unexpected end of data while reading " + type);
99             }
100             logger.trace("Line read:{}", line);
101             endFound = endString.equals(line);
102             if (!endFound) {
103                 addRow(variables, line, stripBeginLength);
104             }
105         }
106         if (logger.isTraceEnabled()) {
107             logger.trace("List '{}' read. {} variables read", type, variables.size());
108         }
109         return variables;
110     }
111
112     private void validateBegin(final String type, final NutSupplier<String> reader) throws NutException {
113         final String beginString = String.format(BEGIN_LIST, type);
114         String line;
115
116         do {
117             line = reader.get();
118             logger.trace("Line read:{}", line);
119             if (line == null) {
120                 throw new NutException("Could not find the begin string pattern in the data while reading " + type);
121             }
122         } while (!beginString.equals(line));
123         logger.trace("Begin of list '{}' found", type);
124     }
125
126     private void addRow(final Map<String, String> map, final String row, final int offset) {
127         final String substring = row.substring(offset);
128         final Matcher matcher = LIST_ROW_RESPONSE_PATTERN.matcher(substring);
129
130         if (matcher.find() && matcher.groupCount() == 2) {
131             final String nut = matcher.group(1).trim();
132             final String value = stripVariable(matcher.group(2));
133
134             map.put(nut, value);
135             logger.trace("Read nut variable '{}':{}", nut, value);
136         } else {
137             logger.debug("Unrecognized nut results: {}", row);
138         }
139     }
140
141     private String stripVariable(final String rawVariable) {
142         return rawVariable.replaceAll("\\\\\"", "\"").replaceAll("\\\\\\\\", "\\\\").trim();
143     }
144 }