2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.teleinfo.internal.data;
15 import java.io.Serializable;
16 import java.util.EnumMap;
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;
26 * The {@link Frame} class defines common attributes for any Teleinfo frames.
28 * @author Nicolas SIBERIL - Initial contribution
31 public class Frame implements Serializable {
33 private static final long serialVersionUID = -1934715078822532494L;
35 private Map<Label, String> labelToValues = new EnumMap<>(Label.class);
36 private Map<Label, String> labelToTimestamp = new EnumMap<>(Label.class);
38 public void put(Label label, String value) {
39 labelToValues.put(label, value);
42 public void putTimestamp(Label label, String timestamp) {
43 labelToTimestamp.put(label, timestamp);
46 public @Nullable String get(Label label) {
47 return labelToValues.get(label);
50 public @Nullable Integer getAsInt(Label label) {
51 String value = labelToValues.get(label);
53 return Integer.parseInt(value);
58 public String getAsDateTime(Label label) {
59 String timestamp = labelToTimestamp.get(label);
60 if (timestamp == null) {
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);
69 // default constructor
72 public FrameType getType() throws InvalidFrameException {
73 TeleinfoTicMode ticMode = getTicMode();
76 return getHistoricalType();
78 return getStandardType();
80 throw new InvalidFrameException();
84 public FrameType getHistoricalType() throws InvalidFrameException {
85 Phase phase = getPhase();
86 Pricing pricing = getPricing();
87 Evolution evolution = getEvolution();
94 return FrameType.CBEMM_ICC_BASE;
96 return FrameType.CBEMM_ICC_EJP;
98 return FrameType.CBEMM_ICC_HC;
100 return FrameType.CBEMM_ICC_TEMPO;
102 return FrameType.UNKNOWN;
107 return FrameType.CBEMM_BASE;
109 return FrameType.CBEMM_EJP;
111 return FrameType.CBEMM_HC;
113 return FrameType.CBEMM_TEMPO;
115 return FrameType.UNKNOWN;
118 return FrameType.UNKNOWN;
122 if (isShortFrame()) {
123 return FrameType.CBETM_SHORT;
127 return FrameType.CBETM_LONG_BASE;
129 return FrameType.CBETM_LONG_EJP;
131 return FrameType.CBETM_LONG_HC;
133 return FrameType.CBETM_LONG_TEMPO;
135 return FrameType.UNKNOWN;
139 return FrameType.UNKNOWN;
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;
149 throw new InvalidFrameException();
152 public boolean isShortFrame() {
153 return !labelToValues.containsKey(Label.ISOUSC);
156 public Evolution getEvolution() {
157 if (labelToValues.containsKey(Label.PAPP)) {
158 return Evolution.ICC;
160 return Evolution.NONE;
163 public Pricing getPricing() throws InvalidFrameException {
164 String optarif = labelToValues.get(Label.OPTARIF);
165 if (optarif == null) {
166 throw new InvalidFrameException();
176 if (optarif.matches("BBR.")) {
177 return Pricing.TEMPO;
179 throw new InvalidFrameException();
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;
189 throw new InvalidFrameException();
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;
199 return FrameType.LSMM_PROD;
202 return FrameType.LSMT;
204 return FrameType.LSMM;
207 public void clear() {
208 labelToValues.clear();
209 labelToTimestamp.clear();
212 public Map<Label, String> getLabelToValues() {
213 return labelToValues;
216 public Map<Label, String> getLabelToTimestamp() {
217 return labelToTimestamp;
220 private char getProgrammeChar() {
221 String optarif = labelToValues.get(Label.OPTARIF);
222 if (optarif == null) {
223 throw new IllegalStateException("No OPTARIF field in frame");
225 return optarif.charAt(3);
228 public String getProgrammeCircuit1() {
229 char program = getProgrammeChar();
230 return convertProgrammeCircuit1(program);
233 public String getProgrammeCircuit2() {
234 char program = getProgrammeChar();
235 return convertProgrammeCircuit2(program);
238 private String convertProgrammeCircuit1(char value) {
239 String prgCircuit1 = computeProgrammeCircuitBinaryValue(value).substring(3, 5);
240 switch (prgCircuit1) {
248 final String error = String.format("Programme circuit 1 '%s' is unknown", prgCircuit1);
249 throw new IllegalStateException(error);
253 private String convertProgrammeCircuit2(char value) {
254 String prgCircuit2 = computeProgrammeCircuitBinaryValue(value).substring(5, 8);
255 switch (prgCircuit2) {
273 final String error = String.format("Programme circuit 2 '%s' is unknown", prgCircuit2);
274 throw new IllegalStateException(error);
278 private String computeProgrammeCircuitBinaryValue(char value) {
279 return String.format("%8s", Integer.toBinaryString(value)).replace(' ', '0');