]> git.basschouten.com Git - openhab-addons.git/blob
3594885198abbc971e7b301acadeca4909d1a33e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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
24 /**
25  * The {@link Frame} class defines common attributes for any Teleinfo frames.
26  *
27  * @author Nicolas SIBERIL - Initial contribution
28  */
29 @NonNullByDefault
30 public class Frame implements Serializable {
31
32     private static final long serialVersionUID = -1934715078822532494L;
33
34     private Map<Label, String> labelToValues = new EnumMap<>(Label.class);
35
36     public void put(Label label, String value) {
37         labelToValues.put(label, value);
38     }
39
40     public @Nullable String get(Label label) {
41         return labelToValues.get(label);
42     }
43
44     public @Nullable Integer getAsInt(Label label) {
45         String value = labelToValues.get(label);
46         if (value != null) {
47             return Integer.parseInt(value);
48         }
49         return null;
50     }
51
52     public Frame() {
53         // default constructor
54     }
55
56     public FrameType getType() throws InvalidFrameException {
57         Phase phase = getPhase();
58         Pricing pricing = getPricing();
59         Evolution evolution = getEvolution();
60         switch (phase) {
61             case ONE_PHASED:
62                 switch (evolution) {
63                     case ICC:
64                         switch (pricing) {
65                             case BASE:
66                                 return FrameType.CBEMM_ICC_BASE;
67                             case EJP:
68                                 return FrameType.CBEMM_ICC_EJP;
69                             case HC:
70                                 return FrameType.CBEMM_ICC_HC;
71                             case TEMPO:
72                                 return FrameType.CBEMM_ICC_TEMPO;
73                             default:
74                                 return FrameType.UNKNOWN;
75                         }
76                     case NONE:
77                         switch (pricing) {
78                             case BASE:
79                                 return FrameType.CBEMM_BASE;
80                             case EJP:
81                                 return FrameType.CBEMM_EJP;
82                             case HC:
83                                 return FrameType.CBEMM_HC;
84                             case TEMPO:
85                                 return FrameType.CBEMM_TEMPO;
86                             default:
87                                 return FrameType.UNKNOWN;
88                         }
89                     default:
90                         return FrameType.UNKNOWN;
91
92                 }
93             case THREE_PHASED:
94                 if (isShortFrame()) {
95                     return FrameType.CBETM_SHORT;
96                 } else {
97                     switch (pricing) {
98                         case BASE:
99                             return FrameType.CBETM_LONG_BASE;
100                         case EJP:
101                             return FrameType.CBETM_LONG_EJP;
102                         case HC:
103                             return FrameType.CBETM_LONG_HC;
104                         case TEMPO:
105                             return FrameType.CBETM_LONG_TEMPO;
106                         default:
107                             return FrameType.UNKNOWN;
108                     }
109                 }
110             default:
111                 return FrameType.UNKNOWN;
112         }
113     }
114
115     public Phase getPhase() throws InvalidFrameException {
116         if (labelToValues.containsKey(Label.IINST)) {
117             return Phase.ONE_PHASED;
118         } else if (labelToValues.containsKey(Label.IINST1)) {
119             return Phase.THREE_PHASED;
120         }
121         throw new InvalidFrameException();
122     }
123
124     public boolean isShortFrame() {
125         return !labelToValues.containsKey(Label.ISOUSC);
126     }
127
128     public Evolution getEvolution() {
129         if (labelToValues.containsKey(Label.PAPP)) {
130             return Evolution.ICC;
131         }
132         return Evolution.NONE;
133     }
134
135     public Pricing getPricing() throws InvalidFrameException {
136         String optarif = labelToValues.get(Label.OPTARIF);
137         if (optarif == null) {
138             throw new InvalidFrameException();
139         }
140         switch (optarif) {
141             case "BASE":
142                 return Pricing.BASE;
143             case "EJP.":
144                 return Pricing.EJP;
145             case "HC..":
146                 return Pricing.HC;
147             default:
148                 if (optarif.matches("BBR.")) {
149                     return Pricing.TEMPO;
150                 }
151                 throw new InvalidFrameException();
152         }
153     }
154
155     public void clear() {
156         labelToValues.clear();
157     }
158
159     public Map<Label, String> getLabelToValues() {
160         return labelToValues;
161     }
162
163     private char getProgrammeChar() {
164         String optarif = labelToValues.get(Label.OPTARIF);
165         if (optarif == null) {
166             throw new IllegalStateException("No OPTARIF field in frame");
167         }
168         return optarif.charAt(3);
169     }
170
171     public String getProgrammeCircuit1() {
172         char program = getProgrammeChar();
173         return convertProgrammeCircuit1(program);
174     }
175
176     public String getProgrammeCircuit2() {
177         char program = getProgrammeChar();
178         return convertProgrammeCircuit2(program);
179     }
180
181     private String convertProgrammeCircuit1(char value) {
182         String prgCircuit1 = computeProgrammeCircuitBinaryValue(value).substring(3, 5);
183         switch (prgCircuit1) {
184             case "01":
185                 return "A";
186             case "10":
187                 return "B";
188             case "11":
189                 return "C";
190             default:
191                 final String error = String.format("Programme circuit 1 '%s' is unknown", prgCircuit1);
192                 throw new IllegalStateException(error);
193         }
194     }
195
196     private String convertProgrammeCircuit2(char value) {
197         String prgCircuit2 = computeProgrammeCircuitBinaryValue(value).substring(5, 8);
198         switch (prgCircuit2) {
199             case "000":
200                 return "P0";
201             case "001":
202                 return "P1";
203             case "010":
204                 return "P2";
205             case "011":
206                 return "P3";
207             case "100":
208                 return "P4";
209             case "101":
210                 return "P5";
211             case "110":
212                 return "P6";
213             case "111":
214                 return "P7";
215             default:
216                 final String error = String.format("Programme circuit 2 '%s' is unknown", prgCircuit2);
217                 throw new IllegalStateException(error);
218         }
219     }
220
221     private String computeProgrammeCircuitBinaryValue(char value) {
222         return String.format("%8s", Integer.toBinaryString(value)).replace(' ', '0');
223     }
224 }