]> git.basschouten.com Git - openhab-addons.git/blob
9bf50c85156b3c6219ffec1d9cd2e8e18065bc73
[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.teleinfo.internal.data;
14
15 import java.io.Serializable;
16 import java.util.EnumMap;
17 import java.util.Map;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.teleinfo.internal.reader.io.serialport.InvalidFrameException;
22 import org.openhab.binding.teleinfo.internal.reader.io.serialport.Label;
23 import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
24
25 /**
26  * The {@link Frame} class defines common attributes for any Teleinfo frames.
27  *
28  * @author Nicolas SIBERIL - Initial contribution
29  */
30 @NonNullByDefault
31 public class Frame implements Serializable {
32
33     private static final long serialVersionUID = -1934715078822532494L;
34
35     private Map<Label, String> labelToValues = new EnumMap<>(Label.class);
36     private Map<Label, String> labelToTimestamp = new EnumMap<>(Label.class);
37
38     public void put(Label label, String value) {
39         labelToValues.put(label, value);
40     }
41
42     public void putTimestamp(Label label, String timestamp) {
43         labelToTimestamp.put(label, timestamp);
44     }
45
46     public @Nullable String get(Label label) {
47         return labelToValues.get(label);
48     }
49
50     public @Nullable Integer getAsInt(Label label) {
51         String value = labelToValues.get(label);
52         if (value != null) {
53             return Integer.parseInt(value);
54         }
55         return null;
56     }
57
58     public String getAsDateTime(Label label) {
59         String timestamp = labelToTimestamp.get(label);
60         if (timestamp == null) {
61             return "";
62         }
63         return "20" + timestamp.substring(1, 3) + "-" + timestamp.substring(3, 5) + "-" + timestamp.substring(5, 7)
64                 + "T" + timestamp.substring(7, 9) + ":" + timestamp.substring(9, 11) + ":"
65                 + timestamp.substring(11, 13);
66     }
67
68     public Frame() {
69         // default constructor
70     }
71
72     public FrameType getType() throws InvalidFrameException {
73         TeleinfoTicMode ticMode = getTicMode();
74         switch (ticMode) {
75             case HISTORICAL:
76                 return getHistoricalType();
77             case STANDARD:
78                 return getStandardType();
79             default:
80                 throw new InvalidFrameException();
81         }
82     }
83
84     public FrameType getHistoricalType() throws InvalidFrameException {
85         Phase phase = getPhase();
86         Pricing pricing = getPricing();
87         Evolution evolution = getEvolution();
88         switch (phase) {
89             case ONE_PHASED:
90                 switch (evolution) {
91                     case ICC:
92                         switch (pricing) {
93                             case BASE:
94                                 return FrameType.CBEMM_ICC_BASE;
95                             case EJP:
96                                 return FrameType.CBEMM_ICC_EJP;
97                             case HC:
98                                 return FrameType.CBEMM_ICC_HC;
99                             case TEMPO:
100                                 return FrameType.CBEMM_ICC_TEMPO;
101                             default:
102                                 return FrameType.UNKNOWN;
103                         }
104                     case NONE:
105                         switch (pricing) {
106                             case BASE:
107                                 return FrameType.CBEMM_BASE;
108                             case EJP:
109                                 return FrameType.CBEMM_EJP;
110                             case HC:
111                                 return FrameType.CBEMM_HC;
112                             case TEMPO:
113                                 return FrameType.CBEMM_TEMPO;
114                             default:
115                                 return FrameType.UNKNOWN;
116                         }
117                     default:
118                         return FrameType.UNKNOWN;
119
120                 }
121             case THREE_PHASED:
122                 if (isShortFrame()) {
123                     return FrameType.CBETM_SHORT;
124                 } else {
125                     switch (pricing) {
126                         case BASE:
127                             return FrameType.CBETM_LONG_BASE;
128                         case EJP:
129                             return FrameType.CBETM_LONG_EJP;
130                         case HC:
131                             return FrameType.CBETM_LONG_HC;
132                         case TEMPO:
133                             return FrameType.CBETM_LONG_TEMPO;
134                         default:
135                             return FrameType.UNKNOWN;
136                     }
137                 }
138             default:
139                 return FrameType.UNKNOWN;
140         }
141     }
142
143     public Phase getPhase() throws InvalidFrameException {
144         if (labelToValues.containsKey(Label.IINST)) {
145             return Phase.ONE_PHASED;
146         } else if (labelToValues.containsKey(Label.IINST1)) {
147             return Phase.THREE_PHASED;
148         }
149         throw new InvalidFrameException();
150     }
151
152     public boolean isShortFrame() {
153         return !labelToValues.containsKey(Label.ISOUSC);
154     }
155
156     public Evolution getEvolution() {
157         if (labelToValues.containsKey(Label.PAPP)) {
158             return Evolution.ICC;
159         }
160         return Evolution.NONE;
161     }
162
163     public Pricing getPricing() throws InvalidFrameException {
164         String optarif = labelToValues.get(Label.OPTARIF);
165         if (optarif == null) {
166             throw new InvalidFrameException();
167         }
168         switch (optarif) {
169             case "BASE":
170                 return Pricing.BASE;
171             case "EJP.":
172                 return Pricing.EJP;
173             case "HC..":
174                 return Pricing.HC;
175             default:
176                 if (optarif.matches("BBR.")) {
177                     return Pricing.TEMPO;
178                 }
179                 throw new InvalidFrameException();
180         }
181     }
182
183     public TeleinfoTicMode getTicMode() throws InvalidFrameException {
184         if (labelToValues.containsKey(Label.ADCO)) {
185             return TeleinfoTicMode.HISTORICAL;
186         } else if (labelToValues.containsKey(Label.ADSC)) {
187             return TeleinfoTicMode.STANDARD;
188         }
189         throw new InvalidFrameException();
190     }
191
192     public FrameType getStandardType() throws InvalidFrameException {
193         boolean isProd = labelToValues.containsKey(Label.EAIT);
194         boolean isThreePhase = labelToValues.containsKey(Label.IRMS2);
195         if (isProd && isThreePhase) {
196             return FrameType.LSMT_PROD;
197         }
198         if (isProd) {
199             return FrameType.LSMM_PROD;
200         }
201         if (isThreePhase) {
202             return FrameType.LSMT;
203         }
204         return FrameType.LSMM;
205     }
206
207     public void clear() {
208         labelToValues.clear();
209         labelToTimestamp.clear();
210     }
211
212     public Map<Label, String> getLabelToValues() {
213         return labelToValues;
214     }
215
216     public Map<Label, String> getLabelToTimestamp() {
217         return labelToTimestamp;
218     }
219
220     private char getProgrammeChar() {
221         String optarif = labelToValues.get(Label.OPTARIF);
222         if (optarif == null) {
223             throw new IllegalStateException("No OPTARIF field in frame");
224         }
225         return optarif.charAt(3);
226     }
227
228     public String getProgrammeCircuit1() {
229         char program = getProgrammeChar();
230         return convertProgrammeCircuit1(program);
231     }
232
233     public String getProgrammeCircuit2() {
234         char program = getProgrammeChar();
235         return convertProgrammeCircuit2(program);
236     }
237
238     private String convertProgrammeCircuit1(char value) {
239         String prgCircuit1 = computeProgrammeCircuitBinaryValue(value).substring(3, 5);
240         switch (prgCircuit1) {
241             case "01":
242                 return "A";
243             case "10":
244                 return "B";
245             case "11":
246                 return "C";
247             default:
248                 final String error = String.format("Programme circuit 1 '%s' is unknown", prgCircuit1);
249                 throw new IllegalStateException(error);
250         }
251     }
252
253     private String convertProgrammeCircuit2(char value) {
254         String prgCircuit2 = computeProgrammeCircuitBinaryValue(value).substring(5, 8);
255         switch (prgCircuit2) {
256             case "000":
257                 return "P0";
258             case "001":
259                 return "P1";
260             case "010":
261                 return "P2";
262             case "011":
263                 return "P3";
264             case "100":
265                 return "P4";
266             case "101":
267                 return "P5";
268             case "110":
269                 return "P6";
270             case "111":
271                 return "P7";
272             default:
273                 final String error = String.format("Programme circuit 2 '%s' is unknown", prgCircuit2);
274                 throw new IllegalStateException(error);
275         }
276     }
277
278     private String computeProgrammeCircuitBinaryValue(char value) {
279         return String.format("%8s", Integer.toBinaryString(value)).replace(' ', '0');
280     }
281 }