[teleinfo] Add support for Standard tic mode (#11375)

* Add a ticMode parameter to serial controller

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Improve checksum verification

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add parameter to deactivate checksum verification

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add standard field labels

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add things and channels for standard tic mode

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add standard tic mode timestamp

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Fix typo

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add some required null annotation

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add parser for relais states

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add relais channels and refactor standard mode channels

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add @NonNullByDefault on enum

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Update documentation

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Fix formula in documentation

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Fix code issues

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Move channel type description in same file than channel group type description

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add pattern specification to dateTime channel type

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add missing channelGroup id in channel UID

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Add trace log

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Fix group labels

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Make labels uppercase

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Make options lowercase

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>

* Simplify group label

Signed-off-by: Olivier Marceau <hollysaiqs@marceau.ovh>
This commit is contained in:
olivierkeke
2021-12-12 22:58:36 +01:00
committed by GitHub
parent f8a6522100
commit 5d52435dea
34 changed files with 1765 additions and 90 deletions

View File

@@ -12,6 +12,8 @@
*/
package org.openhab.binding.teleinfo.internal;
import java.util.stream.IntStream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
@@ -68,7 +70,6 @@ public class TeleinfoBindingConstants {
public static final String CHANNEL_CBETM_IINST1 = "iinst1";
public static final String CHANNEL_CBETM_IINST2 = "iinst2";
public static final String CHANNEL_CBETM_IINST3 = "iinst3";
public static final String CHANNEL_CBETM_FRAME_TYPE = "frameType";
public static final String CHANNEL_CBETM_LONG_IMAX1 = "imax1";
public static final String CHANNEL_CBETM_LONG_IMAX2 = "imax2";
public static final String CHANNEL_CBETM_LONG_IMAX3 = "imax3";
@@ -77,6 +78,105 @@ public class TeleinfoBindingConstants {
public static final String CHANNEL_CBETM_SHORT_ADIR1 = "adir1";
public static final String CHANNEL_CBETM_SHORT_ADIR2 = "adir2";
public static final String CHANNEL_CBETM_SHORT_ADIR3 = "adir3";
// List of Linky standard mode channel ids
public static final String CHANNEL_LSM_NGTF = "commonLSMGroup#ngtf";
public static final String CHANNEL_LSM_LTARF = "commonLSMGroup#ltarf";
public static final String CHANNEL_LSM_EAST = "commonLSMGroup#east";
public static final String CHANNEL_LSM_EASF01 = "commonLSMGroup#easf01";
public static final String CHANNEL_LSM_EASF02 = "commonLSMGroup#easf02";
public static final String CHANNEL_LSM_EASF03 = "commonLSMGroup#easf03";
public static final String CHANNEL_LSM_EASF04 = "commonLSMGroup#easf04";
public static final String CHANNEL_LSM_EASF05 = "commonLSMGroup#easf05";
public static final String CHANNEL_LSM_EASF06 = "commonLSMGroup#easf06";
public static final String CHANNEL_LSM_EASF07 = "commonLSMGroup#easf07";
public static final String CHANNEL_LSM_EASF08 = "commonLSMGroup#easf08";
public static final String CHANNEL_LSM_EASF09 = "commonLSMGroup#easf09";
public static final String CHANNEL_LSM_EASF10 = "commonLSMGroup#easf10";
public static final String CHANNEL_LSM_EASD01 = "commonLSMGroup#easd01";
public static final String CHANNEL_LSM_EASD02 = "commonLSMGroup#easd02";
public static final String CHANNEL_LSM_EASD03 = "commonLSMGroup#easd03";
public static final String CHANNEL_LSM_EASD04 = "commonLSMGroup#easd04";
public static final String CHANNEL_LSM_IRMS1 = "commonLSMGroup#irms1";
public static final String CHANNEL_LSM_URMS1 = "commonLSMGroup#urms1";
public static final String CHANNEL_LSM_PREF = "commonLSMGroup#pref";
public static final String CHANNEL_LSM_PCOUP = "commonLSMGroup#pcoup";
public static final String CHANNEL_LSM_SINSTS = "commonLSMGroup#sinsts";
public static final String CHANNEL_LSM_SMAXSN = "commonLSMGroup#smaxsn";
public static final String CHANNEL_LSM_SMAXSN_MINUS_1 = "commonLSMGroup#smaxsnMinus1";
public static final String CHANNEL_LSM_CCASN = "commonLSMGroup#ccasn";
public static final String CHANNEL_LSM_CCASN_MINUS_1 = "commonLSMGroup#ccasnMinus1";
public static final String CHANNEL_LSM_UMOY1 = "commonLSMGroup#umoy1";
public static final String CHANNEL_LSM_STGE = "commonLSMGroup#stge";
public static final String CHANNEL_LSM_DPM1 = "commonLSMGroup#dpm1";
public static final String CHANNEL_LSM_FPM1 = "commonLSMGroup#fpm1";
public static final String CHANNEL_LSM_DPM2 = "commonLSMGroup#dpm2";
public static final String CHANNEL_LSM_FPM2 = "commonLSMGroup#fpm2";
public static final String CHANNEL_LSM_DPM3 = "commonLSMGroup#dpm3";
public static final String CHANNEL_LSM_FPM3 = "commonLSMGroup#fpm3";
public static final String CHANNEL_LSM_MSG1 = "commonLSMGroup#msg1";
public static final String CHANNEL_LSM_MSG2 = "commonLSMGroup#msg2";
public static final String CHANNEL_LSM_PRM = "commonLSMGroup#prm";
public static final String[] CHANNELS_LSM_RELAIS = IntStream.range(1, 9).mapToObj(i -> "commonLSMGroup#relais" + i)
.toArray(String[]::new);
public static final String CHANNEL_LSM_NTARF = "commonLSMGroup#ntarf";
public static final String CHANNEL_LSM_NJOURF = "commonLSMGroup#njourf";
public static final String CHANNEL_LSM_NJOURF_PLUS_1 = "commonLSMGroup#njourfPlus1";
public static final String CHANNEL_LSM_PJOURF_PLUS_1 = "commonLSMGroup#pjourfPlus1";
public static final String CHANNEL_LSM_PPOINTE = "commonLSMGroup#ppointe";
public static final String CHANNEL_LSM_IRMS2 = "threePhasedLSMGroup#irms2";
public static final String CHANNEL_LSM_IRMS3 = "threePhasedLSMGroup#irms3";
public static final String CHANNEL_LSM_URMS2 = "threePhasedLSMGroup#urms2";
public static final String CHANNEL_LSM_URMS3 = "threePhasedLSMGroup#urms3";
public static final String CHANNEL_LSM_SINSTS1 = "threePhasedLSMGroup#sinsts1";
public static final String CHANNEL_LSM_SINSTS2 = "threePhasedLSMGroup#sinsts2";
public static final String CHANNEL_LSM_SINSTS3 = "threePhasedLSMGroup#sinsts3";
public static final String CHANNEL_LSM_SMAXSN1 = "threePhasedLSMGroup#smaxsn1";
public static final String CHANNEL_LSM_SMAXSN2 = "threePhasedLSMGroup#smaxsn2";
public static final String CHANNEL_LSM_SMAXSN3 = "threePhasedLSMGroup#smaxsn3";
public static final String CHANNEL_LSM_SMAXSN1_MINUS_1 = "threePhasedLSMGroup#smaxsn1Minus1";
public static final String CHANNEL_LSM_SMAXSN2_MINUS_1 = "threePhasedLSMGroup#smaxsn2Minus1";
public static final String CHANNEL_LSM_SMAXSN3_MINUS_1 = "threePhasedLSMGroup#smaxsn3Minus1";
public static final String CHANNEL_LSM_UMOY2 = "threePhasedLSMGroup#umoy2";
public static final String CHANNEL_LSM_UMOY3 = "threePhasedLSMGroup#umoy3";
public static final String CHANNEL_LSM_EAIT = "producerLSMGroup#eait";
public static final String CHANNEL_LSM_ERQ1 = "producerLSMGroup#erq1";
public static final String CHANNEL_LSM_ERQ2 = "producerLSMGroup#erq2";
public static final String CHANNEL_LSM_ERQ3 = "producerLSMGroup#erq3";
public static final String CHANNEL_LSM_ERQ4 = "producerLSMGroup#erq4";
public static final String CHANNEL_LSM_SINSTI = "producerLSMGroup#sinsti";
public static final String CHANNEL_LSM_SMAXIN = "producerLSMGroup#smaxin";
public static final String CHANNEL_LSM_SMAXIN_MINUS_1 = "producerLSMGroup#smaxinMinus1";
public static final String CHANNEL_LSM_CCAIN = "producerLSMGroup#ccain";
public static final String CHANNEL_LSM_CCAIN_MINUS_1 = "producerLSMGroup#ccainMinus1";
public static final String CHANNEL_LSM_DATE = "commonLSMGroup#date";
public static final String CHANNEL_LSM_SMAXSN_DATE = "commonLSMGroup#smaxsnDate";
public static final String CHANNEL_LSM_SMAXSN_MINUS_1_DATE = "commonLSMGroup#smaxsnMinus1Date";
public static final String CHANNEL_LSM_CCASN_DATE = "commonLSMGroup#ccasnDate";
public static final String CHANNEL_LSM_CCASN_MINUS_1_DATE = "commonLSMGroup#ccasnMinus1Date";
public static final String CHANNEL_LSM_UMOY1_DATE = "commonLSMGroup#umoy1Date";
public static final String CHANNEL_LSM_DPM1_DATE = "commonLSMGroup#dpm1Date";
public static final String CHANNEL_LSM_FPM1_DATE = "commonLSMGroup#fpm1Date";
public static final String CHANNEL_LSM_DPM2_DATE = "commonLSMGroup#dpm2Date";
public static final String CHANNEL_LSM_FPM2_DATE = "commonLSMGroup#fpm2Date";
public static final String CHANNEL_LSM_DPM3_DATE = "commonLSMGroup#dpm3Date";
public static final String CHANNEL_LSM_FPM3_DATE = "commonLSMGroup#fpm3Date";
public static final String CHANNEL_LSM_SMAXIN_DATE = "producerLSMGroup#smaxinDate";
public static final String CHANNEL_LSM_SMAXIN_MINUS_1_DATE = "producerLSMGroup#smaxinMinus1Date";
public static final String CHANNEL_LSM_CCAIN_DATE = "producerLSMGroup#ccainDate";
public static final String CHANNEL_LSM_CCAIN_MINUS_1_DATE = "producerLSMGroup#ccainMinus1Date";
public static final String CHANNEL_LSM_SMAXSN1_DATE = "threePhasedLSMGroup#smaxsn1Date";
public static final String CHANNEL_LSM_SMAXSN2_DATE = "threePhasedLSMGroup#smaxsn2Date";
public static final String CHANNEL_LSM_SMAXSN3_DATE = "threePhasedLSMGroup#smaxsn3Date";
public static final String CHANNEL_LSM_SMAXSN1_MINUS_1_DATE = "threePhasedLSMGroup#smaxsn1Minus1Date";
public static final String CHANNEL_LSM_SMAXSN2_MINUS_1_DATE = "threePhasedLSMGroup#smaxsn2Minus1Date";
public static final String CHANNEL_LSM_SMAXSN3_MINUS_1_DATE = "threePhasedLSMGroup#smaxsn3Minus1Date";
public static final String CHANNEL_LSM_UMOY2_DATE = "threePhasedLSMGroup#umoy2Date";
public static final String CHANNEL_LSM_UMOY3_DATE = "threePhasedLSMGroup#umoy3Date";
public static final String NOT_A_CHANNEL = "";
@@ -118,6 +218,18 @@ public class TeleinfoBindingConstants {
public static final ThingTypeUID THING_TEMPO_CBETM_ELECTRICITY_METER_TYPE_UID = new ThingTypeUID(BINDING_ID,
"cbetm_tempo_electricitymeter");
public static final ThingTypeUID THING_LSMT_PROD_ELECTRICITY_METER_TYPE_UID = new ThingTypeUID(BINDING_ID,
"lsmt_prod_electricitymeter");
public static final ThingTypeUID THING_LSMM_PROD_ELECTRICITY_METER_TYPE_UID = new ThingTypeUID(BINDING_ID,
"lsmm_prod_electricitymeter");
public static final ThingTypeUID THING_LSMT_ELECTRICITY_METER_TYPE_UID = new ThingTypeUID(BINDING_ID,
"lsmt_electricitymeter");
public static final ThingTypeUID THING_LSMM_ELECTRICITY_METER_TYPE_UID = new ThingTypeUID(BINDING_ID,
"lsmm_electricitymeter");
public static final String ERROR_OFFLINE_SERIAL_NOT_FOUND = "@text/teleinfo.thingstate.serial_notfound";
public static final String ERROR_OFFLINE_SERIAL_INUSE = "@text/teleinfo.thingstate.serial_inuse";
public static final String ERROR_OFFLINE_SERIAL_UNSUPPORTED = "@text/teleinfo.thingstate.serial_unsupported";

View File

@@ -17,8 +17,6 @@ import static org.openhab.binding.teleinfo.internal.TeleinfoBindingConstants.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -47,13 +45,15 @@ import org.slf4j.LoggerFactory;
public class TeleinfoDiscoveryService extends AbstractDiscoveryService
implements TeleinfoControllerHandlerListener, ThingHandlerService, DiscoveryService {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Stream.of(THING_HC_CBEMM_ELECTRICITY_METER_TYPE_UID,
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_HC_CBEMM_ELECTRICITY_METER_TYPE_UID,
THING_BASE_CBEMM_ELECTRICITY_METER_TYPE_UID, THING_TEMPO_CBEMM_ELECTRICITY_METER_TYPE_UID,
THING_EJP_CBEMM_ELECTRICITY_METER_TYPE_UID, THING_HC_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID,
THING_BASE_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID, THING_TEMPO_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID,
THING_EJP_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID, THING_HC_CBETM_ELECTRICITY_METER_TYPE_UID,
THING_BASE_CBETM_ELECTRICITY_METER_TYPE_UID, THING_TEMPO_CBETM_ELECTRICITY_METER_TYPE_UID,
THING_EJP_CBETM_ELECTRICITY_METER_TYPE_UID).collect(Collectors.toSet());
THING_EJP_CBETM_ELECTRICITY_METER_TYPE_UID, THING_LSMT_PROD_ELECTRICITY_METER_TYPE_UID,
THING_LSMT_ELECTRICITY_METER_TYPE_UID, THING_LSMM_PROD_ELECTRICITY_METER_TYPE_UID,
THING_LSMM_ELECTRICITY_METER_TYPE_UID);
private static final int SCAN_DURATION_IN_S = 60;
@@ -140,11 +140,12 @@ public class TeleinfoDiscoveryService extends AbstractDiscoveryService
TeleinfoAbstractControllerHandler controllerHandlerRef = controllerHandler;
if (controllerHandlerRef != null) {
logger.debug("New eletricity meter detection from frame {}", frameSample);
if (frameSample.get(Label.ADCO) == null) {
throw new IllegalStateException("Missing ADCO key");
if (frameSample.get(Label.ADCO) == null && frameSample.get(Label.ADSC) == null) {
throw new IllegalStateException("Missing ADCO or ADSC key");
}
String adco = frameSample.get(Label.ADCO);
String adco = frameSample.get(Label.ADCO) != null ? frameSample.get(Label.ADCO)
: frameSample.get(Label.ADSC);
if (adco != null) {
ThingUID thingUID = new ThingUID(getThingTypeUID(frameSample), adco,
controllerHandlerRef.getThing().getUID().getId());
@@ -152,7 +153,7 @@ public class TeleinfoDiscoveryService extends AbstractDiscoveryService
final Map<String, Object> properties = getThingProperties(adco);
final String representationProperty = THING_ELECTRICITY_METER_PROPERTY_ADCO;
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
.withLabel("Teleinfo ADCO " + adco).withThingType(getThingTypeUID(frameSample))
.withLabel("Teleinfo ADCO/ADSC " + adco).withThingType(getThingTypeUID(frameSample))
.withBridge(controllerHandlerRef.getThing().getUID())
.withRepresentationProperty(representationProperty).build();

View File

@@ -12,12 +12,15 @@
*/
package org.openhab.binding.teleinfo.internal.data;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Define the evolution option values
*
* @author Olivier MARCEAU - Initial contribution
*
*/
@NonNullByDefault
public enum Evolution {
ICC,
NONE

View File

@@ -20,6 +20,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.InvalidFrameException;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.Label;
import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
/**
* The {@link Frame} class defines common attributes for any Teleinfo frames.
@@ -32,11 +33,16 @@ public class Frame implements Serializable {
private static final long serialVersionUID = -1934715078822532494L;
private Map<Label, String> labelToValues = new EnumMap<>(Label.class);
private Map<Label, String> labelToTimestamp = new EnumMap<>(Label.class);
public void put(Label label, String value) {
labelToValues.put(label, value);
}
public void putTimestamp(Label label, String timestamp) {
labelToTimestamp.put(label, timestamp);
}
public @Nullable String get(Label label) {
return labelToValues.get(label);
}
@@ -49,11 +55,33 @@ public class Frame implements Serializable {
return null;
}
public String getAsDateTime(Label label) {
String timestamp = labelToTimestamp.get(label);
if (timestamp == null) {
return "";
}
return "20" + timestamp.substring(1, 3) + "-" + timestamp.substring(3, 5) + "-" + timestamp.substring(5, 7)
+ "T" + timestamp.substring(7, 9) + ":" + timestamp.substring(9, 11) + ":"
+ timestamp.substring(11, 13);
}
public Frame() {
// default constructor
}
public FrameType getType() throws InvalidFrameException {
TeleinfoTicMode ticMode = getTicMode();
switch (ticMode) {
case HISTORICAL:
return getHistoricalType();
case STANDARD:
return getStandardType();
default:
throw new InvalidFrameException();
}
}
public FrameType getHistoricalType() throws InvalidFrameException {
Phase phase = getPhase();
Pricing pricing = getPricing();
Evolution evolution = getEvolution();
@@ -152,14 +180,43 @@ public class Frame implements Serializable {
}
}
public TeleinfoTicMode getTicMode() throws InvalidFrameException {
if (labelToValues.containsKey(Label.ADCO)) {
return TeleinfoTicMode.HISTORICAL;
} else if (labelToValues.containsKey(Label.ADSC)) {
return TeleinfoTicMode.STANDARD;
}
throw new InvalidFrameException();
}
public FrameType getStandardType() throws InvalidFrameException {
boolean isProd = labelToValues.containsKey(Label.EAIT);
boolean isThreePhase = labelToValues.containsKey(Label.IRMS2);
if (isProd && isThreePhase) {
return FrameType.LSMT_PROD;
}
if (isProd) {
return FrameType.LSMM_PROD;
}
if (isThreePhase) {
return FrameType.LSMT;
}
return FrameType.LSMM;
}
public void clear() {
labelToValues.clear();
labelToTimestamp.clear();
}
public Map<Label, String> getLabelToValues() {
return labelToValues;
}
public Map<Label, String> getLabelToTimestamp() {
return labelToTimestamp;
}
private char getProgrammeChar() {
String optarif = labelToValues.get(Label.OPTARIF);
if (optarif == null) {

View File

@@ -14,6 +14,8 @@ package org.openhab.binding.teleinfo.internal.data;
import static org.openhab.binding.teleinfo.internal.TeleinfoBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.ThingTypeUID;
/**
@@ -22,6 +24,7 @@ import org.openhab.core.thing.ThingTypeUID;
* @author Olivier MARCEAU - Initial contribution
*
*/
@NonNullByDefault
public enum FrameType {
CBETM_SHORT(null),
CBETM_LONG_BASE(THING_BASE_CBETM_ELECTRICITY_METER_TYPE_UID),
@@ -36,15 +39,19 @@ public enum FrameType {
CBEMM_ICC_EJP(THING_EJP_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID),
CBEMM_ICC_TEMPO(THING_TEMPO_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID),
CBEMM_ICC_HC(THING_HC_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID),
LSMT_PROD(THING_LSMT_PROD_ELECTRICITY_METER_TYPE_UID),
LSMM_PROD(THING_LSMM_PROD_ELECTRICITY_METER_TYPE_UID),
LSMM(THING_LSMM_ELECTRICITY_METER_TYPE_UID),
LSMT(THING_LSMT_ELECTRICITY_METER_TYPE_UID),
UNKNOWN(null);
private ThingTypeUID thingTypeUid;
private @Nullable ThingTypeUID thingTypeUid;
FrameType(ThingTypeUID thingTypeUid) {
FrameType(@Nullable ThingTypeUID thingTypeUid) {
this.thingTypeUid = thingTypeUid;
}
public ThingTypeUID getThingTypeUid() {
public @Nullable ThingTypeUID getThingTypeUid() {
return thingTypeUid;
}
}

View File

@@ -12,12 +12,15 @@
*/
package org.openhab.binding.teleinfo.internal.data;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Define all the phase values
*
* @author Olivier MARCEAU - Initial contribution
*
*/
@NonNullByDefault
public enum Phase {
ONE_PHASED,
THREE_PHASED

View File

@@ -12,12 +12,15 @@
*/
package org.openhab.binding.teleinfo.internal.data;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Define all the pricing option values
*
* @author Olivier MARCEAU - Initial contribution
*
*/
@NonNullByDefault
public enum Pricing {
BASE,
TEMPO,

View File

@@ -21,10 +21,13 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.teleinfo.internal.data.Frame;
import org.openhab.binding.teleinfo.internal.data.Phase;
import org.openhab.binding.teleinfo.internal.data.Pricing;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.FrameUtil;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.InvalidFrameException;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.Label;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.ValueType;
import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.Bridge;
@@ -130,7 +133,7 @@ public class TeleinfoElectricityMeterHandler extends BaseThingHandler implements
@Override
public void onFrameReceived(Frame frame) {
String adco = configuration.getAdco();
if (adco.equalsIgnoreCase(frame.get(Label.ADCO))) {
if (adco.equalsIgnoreCase(frame.get(Label.ADCO)) || adco.equalsIgnoreCase(frame.get(Label.ADSC))) {
updateStatesForChannels(frame);
}
}
@@ -139,39 +142,65 @@ public class TeleinfoElectricityMeterHandler extends BaseThingHandler implements
for (Entry<Label, String> entry : frame.getLabelToValues().entrySet()) {
Label label = entry.getKey();
if (!label.getChannelName().equals(NOT_A_CHANNEL)) {
logger.trace("Update channel {} to value {}", label.getChannelName(), entry.getValue());
if (label == Label.PTEC) {
updateState(label.getChannelName(), StringType.valueOf(entry.getValue().replace(".", "")));
} else if (label.getType() == ValueType.STRING) {
updateState(label.getChannelName(), StringType.valueOf(entry.getValue()));
} else if (label.getType() == ValueType.INTEGER) {
updateState(label.getChannelName(),
QuantityType.valueOf(Integer.parseInt(entry.getValue()), label.getUnit()));
updateState(label.getChannelName(), QuantityType
.valueOf(label.getFactor() * Integer.parseInt(entry.getValue()), label.getUnit()));
}
}
if (!label.getTimestampChannelName().equals(NOT_A_CHANNEL)) {
String timestamp = frame.getAsDateTime(label);
if (!timestamp.isEmpty()) {
logger.trace("Update channel {} to value {}", label.getTimestampChannelName(), timestamp);
updateState(label.getTimestampChannelName(), DateTimeType.valueOf(timestamp));
}
}
}
try {
if (frame.getPricing() == Pricing.TEMPO) {
updateState(CHANNEL_TEMPO_FRAME_PROGRAMME_CIRCUIT_1, StringType.valueOf(frame.getProgrammeCircuit1()));
updateState(CHANNEL_TEMPO_FRAME_PROGRAMME_CIRCUIT_2, StringType.valueOf(frame.getProgrammeCircuit2()));
}
} catch (InvalidFrameException e) {
logger.warn("Can not find pricing option.");
}
if (frame.getTicMode() == TeleinfoTicMode.HISTORICAL) {
try {
if (frame.getPricing() == Pricing.TEMPO) {
updateState(CHANNEL_TEMPO_FRAME_PROGRAMME_CIRCUIT_1,
StringType.valueOf(frame.getProgrammeCircuit1()));
updateState(CHANNEL_TEMPO_FRAME_PROGRAMME_CIRCUIT_2,
StringType.valueOf(frame.getProgrammeCircuit2()));
}
} catch (InvalidFrameException e) {
logger.warn("Can not find pricing option.");
}
try {
Phase phase = frame.getPhase();
if (phase == Phase.ONE_PHASED) {
updateStateForMissingAlert(frame, Label.ADPS);
} else if (phase == Phase.THREE_PHASED) {
if (!wasLastFrameShort) {
updateStateForMissingAlert(frame, Label.ADIR1);
updateStateForMissingAlert(frame, Label.ADIR2);
updateStateForMissingAlert(frame, Label.ADIR3);
try {
Phase phase = frame.getPhase();
if (phase == Phase.ONE_PHASED) {
updateStateForMissingAlert(frame, Label.ADPS);
} else if (phase == Phase.THREE_PHASED) {
if (!wasLastFrameShort) {
updateStateForMissingAlert(frame, Label.ADIR1);
updateStateForMissingAlert(frame, Label.ADIR2);
updateStateForMissingAlert(frame, Label.ADIR3);
}
wasLastFrameShort = frame.isShortFrame();
}
} catch (InvalidFrameException e) {
logger.warn("Can not find phase.");
}
} else {
if (frame.getLabelToValues().containsKey(Label.RELAIS)) {
String relaisString = frame.get(Label.RELAIS);
if (relaisString != null) {
boolean[] relaisStates = FrameUtil.parseRelaisStates(relaisString);
for (int i = 0; i <= 7; i++) {
updateState(CHANNELS_LSM_RELAIS[i], OnOffType.from(relaisStates[i]));
}
}
}
wasLastFrameShort = frame.isShortFrame();
}
} catch (InvalidFrameException e) {
logger.warn("Can not find phase.");
logger.warn("Can not find TIC mode.");
}
updateState(CHANNEL_LAST_UPDATE, new DateTimeType());

View File

@@ -48,7 +48,9 @@ public class TeleinfoThingHandlerFactory extends BaseThingHandlerFactory {
THING_HC_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID, THING_BASE_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID,
THING_TEMPO_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID, THING_EJP_CBEMM_EVO_ICC_ELECTRICITY_METER_TYPE_UID,
THING_HC_CBETM_ELECTRICITY_METER_TYPE_UID, THING_BASE_CBETM_ELECTRICITY_METER_TYPE_UID,
THING_TEMPO_CBETM_ELECTRICITY_METER_TYPE_UID, THING_EJP_CBETM_ELECTRICITY_METER_TYPE_UID)
THING_TEMPO_CBETM_ELECTRICITY_METER_TYPE_UID, THING_EJP_CBETM_ELECTRICITY_METER_TYPE_UID,
THING_LSMM_ELECTRICITY_METER_TYPE_UID, THING_LSMM_PROD_ELECTRICITY_METER_TYPE_UID,
THING_LSMT_ELECTRICITY_METER_TYPE_UID, THING_LSMT_PROD_ELECTRICITY_METER_TYPE_UID)
.collect(Collectors.toSet());
private final SerialPortManager serialPortManager;

View File

@@ -24,6 +24,7 @@ import org.openhab.binding.teleinfo.internal.data.Frame;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.FrameUtil;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.InvalidFrameException;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.Label;
import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -43,19 +44,32 @@ public class TeleinfoInputStream extends InputStream {
private BufferedReader bufferedReader;
private @Nullable String groupLine;
private boolean autoRepairInvalidADPSgroupLine;
private final TeleinfoTicMode ticMode;
private final boolean verifyChecksum;
private final Frame frame = new Frame();
public TeleinfoInputStream(final InputStream teleinfoInputStream) {
this(teleinfoInputStream, false);
public TeleinfoInputStream(final InputStream teleinfoInputStream, TeleinfoTicMode ticMode) {
this(teleinfoInputStream, false, ticMode, true);
}
public TeleinfoInputStream(final @Nullable InputStream teleinfoInputStream,
boolean autoRepairInvalidADPSgroupLine) {
public TeleinfoInputStream(final InputStream teleinfoInputStream, boolean autoRepairInvalidADPSgroupLine,
TeleinfoTicMode ticMode) {
this(teleinfoInputStream, autoRepairInvalidADPSgroupLine, ticMode, true);
}
public TeleinfoInputStream(final InputStream teleinfoInputStream, TeleinfoTicMode ticMode, boolean verifyChecksum) {
this(teleinfoInputStream, false, ticMode, verifyChecksum);
}
public TeleinfoInputStream(final @Nullable InputStream teleinfoInputStream, boolean autoRepairInvalidADPSgroupLine,
TeleinfoTicMode ticMode, boolean verifyChecksum) {
if (teleinfoInputStream == null) {
throw new IllegalArgumentException("Teleinfo inputStream is null");
}
this.autoRepairInvalidADPSgroupLine = autoRepairInvalidADPSgroupLine;
this.ticMode = ticMode;
this.verifyChecksum = verifyChecksum;
this.bufferedReader = new BufferedReader(new InputStreamReader(teleinfoInputStream, StandardCharsets.US_ASCII));
groupLine = null;
@@ -96,29 +110,48 @@ public class TeleinfoInputStream extends InputStream {
logger.trace("groupLine = {}", groupLine);
String groupLineRef = groupLine;
if (groupLineRef != null) {
String[] groupLineTokens = groupLineRef.split("\\s");
if (groupLineTokens.length != 2 && groupLineTokens.length != 3) {
String[] groupLineTokens = groupLineRef.split(ticMode.getSeparator());
if (ticMode == TeleinfoTicMode.HISTORICAL && groupLineTokens.length != 2 && groupLineTokens.length != 3
|| ticMode == TeleinfoTicMode.STANDARD && groupLineTokens.length != 3
&& groupLineTokens.length != 4) {
final String error = String.format("The groupLine '%1$s' is incomplete", groupLineRef);
throw new InvalidFrameException(error);
}
String labelStr = groupLineTokens[0];
String valueString = groupLineTokens[1];
String valueString;
String timestampString = null;
switch (ticMode) {
default:
valueString = groupLineTokens[1];
break;
case STANDARD:
if (groupLineTokens.length == 3) {
valueString = groupLineTokens[1];
} else {
timestampString = groupLineTokens[1];
valueString = groupLineTokens[2];
}
break;
}
// verify integrity (through checksum)
char checksum = (groupLineTokens.length == 3 ? groupLineTokens[2].charAt(0) : ' ');
char computedChecksum = FrameUtil.computeGroupLineChecksum(labelStr, valueString);
if (computedChecksum != checksum) {
logger.trace("computedChecksum = {}", computedChecksum);
logger.trace("checksum = {}", checksum);
final String error = String.format(
"The groupLine '%s' is corrupted (integrity not checked). Actual checksum: '%s' / Expected checksum: '%s'",
groupLineRef, checksum, computedChecksum);
throw new InvalidFrameException(error);
if (verifyChecksum) {
char checksum = groupLineRef.charAt(groupLineRef.length() - 1);
char computedChecksum = FrameUtil
.computeGroupLineChecksum(groupLineRef.substring(0, groupLineRef.length() - 2), ticMode);
if (computedChecksum != checksum) {
logger.trace("computedChecksum = {}", computedChecksum);
logger.trace("checksum = {}", checksum);
final String error = String.format(
"The groupLine '%s' is corrupted (integrity not checked). Actual checksum: '%s' / Expected checksum: '%s'",
groupLineRef, checksum, computedChecksum);
throw new InvalidFrameException(error);
}
}
Label label;
try {
label = Label.valueOf(labelStr);
label = Label.getEnum(labelStr);
} catch (IllegalArgumentException e) {
if (autoRepairInvalidADPSgroupLine && labelStr.startsWith(Label.ADPS.name())) {
// in this hardware issue, label variable is composed by label name and value. E.g:
@@ -133,6 +166,9 @@ public class TeleinfoInputStream extends InputStream {
}
frame.put(label, valueString);
if (timestampString != null) {
frame.putTimestamp(label, timestampString);
}
}
}
@@ -152,7 +188,7 @@ public class TeleinfoInputStream extends InputStream {
throw new UnsupportedOperationException("The 'read()' is not supported");
}
private boolean isHeaderFrame(final @Nullable String line) {
public static boolean isHeaderFrame(final @Nullable String line) {
// A new teleinfo trame begin with '3' and '2' bytes (END OF TEXT et START OF TEXT)
return (line != null && line.length() > 1 && line.codePointAt(0) == 3 && line.codePointAt(1) == 2);
}

View File

@@ -13,6 +13,7 @@
package org.openhab.binding.teleinfo.internal.reader.io.serialport;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
/**
* The {@link FrameUtil} class defines a utility class for {@link FrameCbetmLong}.
@@ -33,14 +34,31 @@ public class FrameUtil {
* must not include in checksum computation.
* @return the checksum of the given group line.
*/
public static char computeGroupLineChecksum(final String label, final String value) {
final String groupLine = label + " " + value;
public static char computeGroupLineChecksum(final String groupLine, TeleinfoTicMode ticMode) {
int sum = 0;
for (int i = 0; i < groupLine.length(); i++) {
sum = sum + groupLine.codePointAt(i);
sum += groupLine.codePointAt(i);
}
if (ticMode == TeleinfoTicMode.STANDARD) {
sum += 0x09;
}
sum = (sum & 0x3F) + 0x20;
return (char) sum;
}
/**
* Parse relais states.
*
* @param relais integer string
* @return State of each relais
*/
public static boolean[] parseRelaisStates(String relais) {
boolean[] relaisState = new boolean[8];
int value = Integer.parseInt(relais);
for (int i = 0; i <= 7; i++) {
relaisState[i] = (value & 1) == 1;
value >>= 1;
}
return relaisState;
}
}

View File

@@ -27,13 +27,14 @@ import org.openhab.core.library.unit.Units;
@NonNullByDefault
public enum Label {
// Historical labels
ADCO(ValueType.STRING, NOT_A_CHANNEL, Units.ONE),
OPTARIF(ValueType.STRING, NOT_A_CHANNEL, Units.ONE),
BASE(ValueType.INTEGER, CHANNEL_BASE_FRAME_BASE, Units.WATT_HOUR),
HCHC(ValueType.INTEGER, CHANNEL_HC_FRAME_HCHC, Units.WATT_HOUR),
HCHP(ValueType.INTEGER, CHANNEL_HC_FRAME_HCHP, Units.WATT_HOUR),
EJPHN(ValueType.INTEGER, CHANNEL_EJP_FRAME_EJPHN, Units.WATT_HOUR),
EJPHPM(ValueType.INTEGER, CHANNEL_EJP_FRAME_EJPHN, Units.WATT_HOUR),
EJPHPM(ValueType.INTEGER, CHANNEL_EJP_FRAME_EJPHPM, Units.WATT_HOUR),
PTEC(ValueType.STRING, CHANNEL_PTEC, Units.ONE),
MOTDETAT(ValueType.STRING, CHANNEL_MOTDETAT, Units.AMPERE),
ISOUSC(ValueType.INTEGER, CHANNEL_ISOUSC, Units.AMPERE),
@@ -60,16 +61,108 @@ public enum Label {
BBRHCJR(ValueType.INTEGER, CHANNEL_TEMPO_FRAME_BBRHCJR, Units.WATT_HOUR),
BBRHPJR(ValueType.INTEGER, CHANNEL_TEMPO_FRAME_BBRHPJR, Units.WATT_HOUR),
PEJP(ValueType.INTEGER, CHANNEL_EJP_FRAME_PEJP, Units.MINUTE),
DEMAIN(ValueType.STRING, CHANNEL_TEMPO_FRAME_DEMAIN, Units.ONE);
DEMAIN(ValueType.STRING, CHANNEL_TEMPO_FRAME_DEMAIN, Units.ONE),
private ValueType type;
private String channelName;
private Unit<?> unit;
// Standard TIC mode labels
ADSC(ValueType.STRING, NOT_A_CHANNEL, Units.ONE),
VTIC(ValueType.INTEGER, NOT_A_CHANNEL, Units.ONE),
DATE(ValueType.STRING, NOT_A_CHANNEL, CHANNEL_LSM_DATE, Units.ONE),
NGTF(ValueType.STRING, CHANNEL_LSM_NGTF, Units.ONE),
LTARF(ValueType.STRING, CHANNEL_LSM_LTARF, Units.ONE),
EAST(ValueType.INTEGER, CHANNEL_LSM_EAST, Units.WATT_HOUR),
EASF01(ValueType.INTEGER, CHANNEL_LSM_EASF01, Units.WATT_HOUR),
EASF02(ValueType.INTEGER, CHANNEL_LSM_EASF02, Units.WATT_HOUR),
EASF03(ValueType.INTEGER, CHANNEL_LSM_EASF03, Units.WATT_HOUR),
EASF04(ValueType.INTEGER, CHANNEL_LSM_EASF04, Units.WATT_HOUR),
EASF05(ValueType.INTEGER, CHANNEL_LSM_EASF05, Units.WATT_HOUR),
EASF06(ValueType.INTEGER, CHANNEL_LSM_EASF06, Units.WATT_HOUR),
EASF07(ValueType.INTEGER, CHANNEL_LSM_EASF07, Units.WATT_HOUR),
EASF08(ValueType.INTEGER, CHANNEL_LSM_EASF08, Units.WATT_HOUR),
EASF09(ValueType.INTEGER, CHANNEL_LSM_EASF09, Units.WATT_HOUR),
EASF10(ValueType.INTEGER, CHANNEL_LSM_EASF10, Units.WATT_HOUR),
EASD01(ValueType.INTEGER, CHANNEL_LSM_EASD01, Units.WATT_HOUR),
EASD02(ValueType.INTEGER, CHANNEL_LSM_EASD02, Units.WATT_HOUR),
EASD03(ValueType.INTEGER, CHANNEL_LSM_EASD03, Units.WATT_HOUR),
EASD04(ValueType.INTEGER, CHANNEL_LSM_EASD04, Units.WATT_HOUR),
EAIT(ValueType.INTEGER, CHANNEL_LSM_EAIT, Units.WATT_HOUR),
ERQ1(ValueType.INTEGER, CHANNEL_LSM_ERQ1, Units.VOLT_AMPERE_HOUR),
ERQ2(ValueType.INTEGER, CHANNEL_LSM_ERQ2, Units.VOLT_AMPERE_HOUR),
ERQ3(ValueType.INTEGER, CHANNEL_LSM_ERQ3, Units.VOLT_AMPERE_HOUR),
ERQ4(ValueType.INTEGER, CHANNEL_LSM_ERQ4, Units.VOLT_AMPERE_HOUR),
IRMS1(ValueType.INTEGER, CHANNEL_LSM_IRMS1, Units.AMPERE),
IRMS2(ValueType.INTEGER, CHANNEL_LSM_IRMS2, Units.AMPERE),
IRMS3(ValueType.INTEGER, CHANNEL_LSM_IRMS3, Units.AMPERE),
URMS1(ValueType.INTEGER, CHANNEL_LSM_URMS1, Units.VOLT),
URMS2(ValueType.INTEGER, CHANNEL_LSM_URMS2, Units.VOLT),
URMS3(ValueType.INTEGER, CHANNEL_LSM_URMS3, Units.VOLT),
PREF(ValueType.INTEGER, CHANNEL_LSM_PREF, Units.VOLT_AMPERE, 1000),
PCOUP(ValueType.INTEGER, CHANNEL_LSM_PCOUP, Units.VOLT_AMPERE, 1000),
SINSTS(ValueType.INTEGER, CHANNEL_LSM_SINSTS, Units.VOLT_AMPERE),
SINSTS1(ValueType.INTEGER, CHANNEL_LSM_SINSTS1, Units.VOLT_AMPERE),
SINSTS2(ValueType.INTEGER, CHANNEL_LSM_SINSTS2, Units.VOLT_AMPERE),
SINSTS3(ValueType.INTEGER, CHANNEL_LSM_SINSTS3, Units.VOLT_AMPERE),
SMAXSN(ValueType.INTEGER, CHANNEL_LSM_SMAXSN, CHANNEL_LSM_SMAXSN_DATE, Units.VOLT_AMPERE),
SMAXSN1(ValueType.INTEGER, CHANNEL_LSM_SMAXSN1, CHANNEL_LSM_SMAXSN1_DATE, Units.VOLT_AMPERE),
SMAXSN2(ValueType.INTEGER, CHANNEL_LSM_SMAXSN2, CHANNEL_LSM_SMAXSN2_DATE, Units.VOLT_AMPERE),
SMAXSN3(ValueType.INTEGER, CHANNEL_LSM_SMAXSN3, CHANNEL_LSM_SMAXSN3_DATE, Units.VOLT_AMPERE),
SMAXSN_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_SMAXSN_MINUS_1, CHANNEL_LSM_SMAXSN_MINUS_1_DATE, Units.VOLT_AMPERE),
SMAXSN1_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_SMAXSN1_MINUS_1, CHANNEL_LSM_SMAXSN1_MINUS_1_DATE,
Units.VOLT_AMPERE),
SMAXSN2_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_SMAXSN2_MINUS_1, CHANNEL_LSM_SMAXSN2_MINUS_1_DATE,
Units.VOLT_AMPERE),
SMAXSN3_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_SMAXSN3_MINUS_1, CHANNEL_LSM_SMAXSN3_MINUS_1_DATE,
Units.VOLT_AMPERE),
SINSTI(ValueType.INTEGER, CHANNEL_LSM_SINSTI, Units.VOLT_AMPERE),
SMAXIN(ValueType.INTEGER, CHANNEL_LSM_SMAXIN, CHANNEL_LSM_SMAXIN_DATE, Units.VOLT_AMPERE),
SMAXIN_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_SMAXIN_MINUS_1, CHANNEL_LSM_SMAXIN_MINUS_1_DATE, Units.VOLT_AMPERE),
CCASN(ValueType.INTEGER, CHANNEL_LSM_CCASN, CHANNEL_LSM_CCASN_DATE, Units.WATT),
CCASN_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_CCASN_MINUS_1, CHANNEL_LSM_CCASN_MINUS_1_DATE, Units.WATT),
CCAIN(ValueType.INTEGER, CHANNEL_LSM_CCAIN, CHANNEL_LSM_CCAIN_DATE, Units.WATT),
CCAIN_MINUS_1(ValueType.INTEGER, CHANNEL_LSM_CCAIN_MINUS_1, CHANNEL_LSM_CCAIN_MINUS_1_DATE, Units.WATT),
UMOY1(ValueType.INTEGER, CHANNEL_LSM_UMOY1, CHANNEL_LSM_UMOY1_DATE, Units.VOLT),
UMOY2(ValueType.INTEGER, CHANNEL_LSM_UMOY2, CHANNEL_LSM_UMOY2_DATE, Units.VOLT),
UMOY3(ValueType.INTEGER, CHANNEL_LSM_UMOY3, CHANNEL_LSM_UMOY3_DATE, Units.VOLT),
STGE(ValueType.STRING, CHANNEL_LSM_STGE, Units.ONE),
DPM1(ValueType.STRING, CHANNEL_LSM_DPM1, CHANNEL_LSM_DPM1_DATE, Units.ONE),
FPM1(ValueType.STRING, CHANNEL_LSM_FPM1, CHANNEL_LSM_FPM1_DATE, Units.ONE),
DPM2(ValueType.STRING, CHANNEL_LSM_DPM2, CHANNEL_LSM_DPM2_DATE, Units.ONE),
FPM2(ValueType.STRING, CHANNEL_LSM_FPM2, CHANNEL_LSM_FPM2_DATE, Units.ONE),
DPM3(ValueType.STRING, CHANNEL_LSM_DPM3, CHANNEL_LSM_DPM3_DATE, Units.ONE),
FPM3(ValueType.STRING, CHANNEL_LSM_FPM3, CHANNEL_LSM_FPM3_DATE, Units.ONE),
MSG1(ValueType.STRING, CHANNEL_LSM_MSG1, Units.ONE),
MSG2(ValueType.STRING, CHANNEL_LSM_MSG2, Units.ONE),
PRM(ValueType.STRING, CHANNEL_LSM_PRM, Units.ONE),
RELAIS(ValueType.STRING, NOT_A_CHANNEL, Units.ONE),
NTARF(ValueType.STRING, CHANNEL_LSM_NTARF, Units.ONE),
NJOURF(ValueType.STRING, CHANNEL_LSM_NJOURF, Units.ONE),
NJOURF_PLUS_1(ValueType.STRING, CHANNEL_LSM_NJOURF_PLUS_1, Units.ONE),
PJOURF_PLUS_1(ValueType.STRING, CHANNEL_LSM_PJOURF_PLUS_1, Units.ONE),
PPOINTE(ValueType.STRING, CHANNEL_LSM_PPOINTE, Units.ONE);
private final ValueType type;
private final String channelName;
private final String timestampChannelName;
private final Unit<?> unit;
private final int factor;
Label(ValueType type, String channelName, Unit<?> unit) {
this(type, channelName, NOT_A_CHANNEL, unit, 1);
}
Label(ValueType type, String channelName, String timestampChannelName, Unit<?> unit) {
this(type, channelName, timestampChannelName, unit, 1);
}
Label(ValueType type, String channelName, Unit<?> unit, int factor) {
this(type, channelName, NOT_A_CHANNEL, unit, factor);
}
Label(ValueType type, String channelName, String timestampChannelName, Unit<?> unit, int factor) {
this.type = type;
this.channelName = channelName;
this.timestampChannelName = timestampChannelName;
this.unit = unit;
this.factor = factor;
}
public ValueType getType() {
@@ -80,7 +173,21 @@ public enum Label {
return channelName;
}
public String getTimestampChannelName() {
return timestampChannelName;
}
public Unit<?> getUnit() {
return unit;
}
public int getFactor() {
return factor;
}
public static Label getEnum(String label) {
String modifiedLabel = label.replace("-", "_MINUS_");
modifiedLabel = modifiedLabel.replace("+", "_PLUS_");
return valueOf(modifiedLabel);
}
}

View File

@@ -12,12 +12,15 @@
*/
package org.openhab.binding.teleinfo.internal.reader.io.serialport;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Defines all the type of values
*
* @author Olivier MARCEAU - Initial contribution
*
*/
@NonNullByDefault
public enum ValueType {
INTEGER,
STRING

View File

@@ -36,20 +36,24 @@ public class TeleinfoReceiveThread extends Thread {
private SerialPort serialPort;
private @Nullable TeleinfoReceiveThreadListener listener;
private boolean autoRepairInvalidADPSgroupLine;
private final TeleinfoTicMode ticMode;
private final boolean verifyChecksum;
public TeleinfoReceiveThread(SerialPort serialPort, final TeleinfoSerialControllerHandler listener,
boolean autoRepairInvalidADPSgroupLine) {
boolean autoRepairInvalidADPSgroupLine, TeleinfoTicMode ticMode, boolean verifyChecksum) {
super("OH-binding-TeleinfoReceiveThread-" + listener.getThing().getUID().getId());
setDaemon(true);
this.serialPort = serialPort;
this.listener = listener;
this.autoRepairInvalidADPSgroupLine = autoRepairInvalidADPSgroupLine;
this.ticMode = ticMode;
this.verifyChecksum = verifyChecksum;
}
@Override
public void run() {
try (TeleinfoInputStream teleinfoStream = new TeleinfoInputStream(serialPort.getInputStream(),
autoRepairInvalidADPSgroupLine)) {
autoRepairInvalidADPSgroupLine, ticMode, verifyChecksum)) {
while (!interrupted()) {
TeleinfoReceiveThreadListener listener = this.listener;
if (listener != null) {

View File

@@ -23,5 +23,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
public class TeleinfoSerialControllerConfiguration {
public String serialport = "";
public String ticMode = "";
public boolean verifyChecksum = true;
public boolean autoRepairInvalidADPSgroupLine = true;
}

View File

@@ -148,7 +148,9 @@ public class TeleinfoSerialControllerHandler extends TeleinfoAbstractControllerH
SerialPort commPort = portIdentifier.open("org.openhab.binding.teleinfo", 5000);
serialPort = commPort;
commPort.setSerialPortParams(1200, SerialPort.DATABITS_7, SerialPort.STOPBITS_1, SerialPort.PARITY_EVEN);
TeleinfoTicMode ticMode = TeleinfoTicMode.valueOf(config.ticMode);
commPort.setSerialPortParams(ticMode.getBitrate(), SerialPort.DATABITS_7, SerialPort.STOPBITS_1,
SerialPort.PARITY_EVEN);
try {
commPort.enableReceiveThreshold(1);
} catch (UnsupportedCommOperationException e) {
@@ -161,7 +163,7 @@ public class TeleinfoSerialControllerHandler extends TeleinfoAbstractControllerH
}
logger.debug("Starting receive thread");
TeleinfoReceiveThread receiveThread = new TeleinfoReceiveThread(commPort, this,
config.autoRepairInvalidADPSgroupLine);
config.autoRepairInvalidADPSgroupLine, ticMode, config.verifyChecksum);
this.receiveThread = receiveThread;
receiveThread.start();

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.teleinfo.internal.serial;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Define an enum for TIC mode of Linky telemeters
*
* @author Olivier MARCEAU - Initial contribution
*/
@NonNullByDefault
public enum TeleinfoTicMode {
HISTORICAL(1200, "\\s"),
STANDARD(9600, "\\t");
private final int bitrate;
private final String separator;
TeleinfoTicMode(int bitrate, String separator) {
this.bitrate = bitrate;
this.separator = separator;
}
public int getBitrate() {
return bitrate;
}
public String getSeparator() {
return separator;
}
}

View File

@@ -7,7 +7,7 @@
<config-description uri="thing-type:teleinfo:adco">
<parameter name="adco" type="text" required="true" pattern="^\w{12}$">
<label>ADCO</label>
<label>ADCO/ADSC</label>
<description>Electricity meter identifier (format: 12 characters / e.g: '031528042289')</description>
<limitToOptions>false</limitToOptions>
</parameter>

View File

@@ -0,0 +1,362 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<channel-group-type id="commonLSMGroupType">
<label>Common</label>
<description>Common channels for Linky telemeter in standard teleinformation mode</description>
<category>Energy</category>
<channels>
<channel id="ngtf" typeId="stringType">
<label>NGTF</label>
<description>Provider schedule name</description>
</channel>
<channel id="ltarf" typeId="stringType">
<label>LTARF</label>
<description>Current pricing label</description>
</channel>
<channel id="east" typeId="energyType">
<label>EAST</label>
<description>Total active energy withdrawn</description>
</channel>
<channel id="easf01" typeId="energyType">
<label>EASF01</label>
<description>Active energy withdrawn from provider on index 01</description>
</channel>
<channel id="easf02" typeId="energyType">
<label>EASF02</label>
<description>Active energy withdrawn from provider on index 02</description>
</channel>
<channel id="easf03" typeId="energyType">
<label>EASF03</label>
<description>Active energy withdrawn from provider on index 03</description>
</channel>
<channel id="easf04" typeId="energyType">
<label>EASF04</label>
<description>Active energy withdrawn from provider on index 04</description>
</channel>
<channel id="easf05" typeId="energyType">
<label>EASF05</label>
<description>Active energy withdrawn from provider on index 05</description>
</channel>
<channel id="easf06" typeId="energyType">
<label>EASF06</label>
<description>Active energy withdrawn from provider on index 06</description>
</channel>
<channel id="easf07" typeId="energyType">
<label>EASF07</label>
<description>Active energy withdrawn from provider on index 07</description>
</channel>
<channel id="easf08" typeId="energyType">
<label>EASF08</label>
<description>Active energy withdrawn from provider on index 08</description>
</channel>
<channel id="easf09" typeId="energyType">
<label>EASF09</label>
<description>Active energy withdrawn from provider on index 09</description>
</channel>
<channel id="easf10" typeId="energyType">
<label>EASF10</label>
<description>Active energy withdrawn from provider on index 10</description>
</channel>
<channel id="easd01" typeId="energyType">
<label>EASD01</label>
<description>Active energy withdrawn from distributor on index 01</description>
</channel>
<channel id="easd02" typeId="energyType">
<label>EASD02</label>
<description>Active energy withdrawn from distributor on index 02</description>
</channel>
<channel id="easd03" typeId="energyType">
<label>EASD03</label>
<description>Active energy withdrawn from distributor on index 03</description>
</channel>
<channel id="easd04" typeId="energyType">
<label>EASD04</label>
<description>Active energy withdrawn from distributor on index 04</description>
</channel>
<channel id="irms1" typeId="currentType">
<label>IRMS1</label>
<description>RMS Current on phase 1</description>
</channel>
<channel id="urms1" typeId="potentialType">
<label>URMS1</label>
<description>RMS Voltage on phase 1</description>
</channel>
<channel id="pref" typeId="powerType">
<label>PREF</label>
<description>Reference apparent power</description>
</channel>
<channel id="pcoup" typeId="powerType">
<label>PCOUP</label>
<description>Apparent power rupture capacity</description>
</channel>
<channel id="sinsts" typeId="powerType">
<label>SINSTS</label>
<description>Instantaneous withdrawn apparent power</description>
</channel>
<channel id="smaxsn" typeId="powerType">
<label>SMAXSN</label>
<description>Maximum withdrawn apparent power of the day</description>
</channel>
<channel id="smaxsnMinus1" typeId="powerType">
<label>SMAXSN-1</label>
<description>Maximum withdrawn apparent power of the previous day</description>
</channel>
<channel id="ccasn" typeId="powerType">
<label>CCASN</label>
<description>Active charge point N</description>
</channel>
<channel id="ccasnMinus1" typeId="powerType">
<label>CCASN-1</label>
<description>Active charge point N-1</description>
</channel>
<channel id="umoy1" typeId="potentialType">
<label>UMOY1</label>
<description>Mean Voltage on phase 1</description>
</channel>
<channel id="stge" typeId="stringType">
<label>STGE</label>
<description>Status registry</description>
</channel>
<channel id="dpm1" typeId="stringType">
<label>DPM1</label>
<description>Start of mobile peak period 1</description>
</channel>
<channel id="fpm1" typeId="stringType">
<label>FPM1</label>
<description>End of mobile peak period 1</description>
</channel>
<channel id="dpm2" typeId="stringType">
<label>DPM2</label>
<description>Start of mobile peak period 2</description>
</channel>
<channel id="fpm2" typeId="stringType">
<label>FPM2</label>
<description>End of mobile peak period 2</description>
</channel>
<channel id="dpm3" typeId="stringType">
<label>DPM3</label>
<description>Start of mobile peak period 3</description>
</channel>
<channel id="fpm3" typeId="stringType">
<label>FPM3</label>
<description>End of mobile peak period 3</description>
</channel>
<channel id="msg1" typeId="stringType">
<label>MSG1</label>
<description>Short message</description>
</channel>
<channel id="msg2" typeId="stringType">
<label>MSG2</label>
<description>Very short message</description>
</channel>
<channel id="prm" typeId="stringType">
<label>PRM</label>
<description>PRM</description>
</channel>
<channel id="ntarf" typeId="stringType">
<label>NTARF</label>
<description>Index of current pricing</description>
</channel>
<channel id="njourf" typeId="stringType">
<label>NJOURF</label>
<description>Number of current provider schedule</description>
</channel>
<channel id="njourfPlus1" typeId="stringType">
<label>NJOURF+1</label>
<description>Number of next day provider schedule</description>
</channel>
<channel id="pjourfPlus1" typeId="stringType">
<label>PJOURF+1</label>
<description>Profile of next day provider schedule</description>
</channel>
<channel id="ppointe" typeId="stringType">
<label>PPOINTE</label>
<description>Profile of next rush day</description>
</channel>
<channel id="date" typeId="dateTimeType">
<label>DATE</label>
<description>Date and Time</description>
</channel>
<channel id="smaxsnDate" typeId="dateTimeType">
<label>SMAXSN TIMESTAMP</label>
<description>Timestamp of SMAXSN value</description>
</channel>
<channel id="smaxsnMinus1Date" typeId="dateTimeType">
<label>SMAXSN-1 TIMESTAMP</label>
<description>Timestamp of SMAXSN-1 value</description>
</channel>
<channel id="ccasnDate" typeId="dateTimeType">
<label>CCASN TIMESTAMP</label>
<description>Timestamp of CCASN value</description>
</channel>
<channel id="ccasnMinus1Date" typeId="dateTimeType">
<label>CCASN-1 TIMESTAMP</label>
<description>Timestamp of CCASN-1 value</description>
</channel>
<channel id="umoy1Date" typeId="dateTimeType">
<label>UMOY1 TIMESTAMP</label>
<description>Timestamp of UMOY1 value</description>
</channel>
<channel id="dpm1Date" typeId="dateTimeType">
<label>DPM1 TIMESTAMP</label>
<description>Date of DPM1</description>
</channel>
<channel id="fpm1Date" typeId="dateTimeType">
<label>FPM1 TIMESTAMP</label>
<description>Date of FPM1</description>
</channel>
<channel id="dpm2Date" typeId="dateTimeType">
<label>DPM2 TIMESTAMP</label>
<description>Date of DPM2</description>
</channel>
<channel id="fpm2Date" typeId="dateTimeType">
<label>FPM2 TIMESTAMP</label>
<description>Date of FPM2</description>
</channel>
<channel id="dpm3Date" typeId="dateTimeType">
<label>DPM3 TIMESTAMP</label>
<description>Date of DPM3</description>
</channel>
<channel id="fpm3Date" typeId="dateTimeType">
<label>FPM3 TIMESTAMP</label>
<description>Date of FPM3</description>
</channel>
<channel id="relais1" typeId="switchType">
<label>Relais 1</label>
</channel>
<channel id="relais2" typeId="switchType">
<label>Relais 2</label>
</channel>
<channel id="relais3" typeId="switchType">
<label>Relais 3</label>
</channel>
<channel id="relais4" typeId="switchType">
<label>Relais 4</label>
</channel>
<channel id="relais5" typeId="switchType">
<label>Relais 5</label>
</channel>
<channel id="relais6" typeId="switchType">
<label>Relais 6</label>
</channel>
<channel id="relais7" typeId="switchType">
<label>Relais 7</label>
</channel>
<channel id="relais8" typeId="switchType">
<label>Relais 8</label>
</channel>
</channels>
</channel-group-type>
<channel-type id="stringType">
<item-type>String</item-type>
<label>Teleinfo String Type</label>
<category>Energy</category>
<state pattern="%s" readOnly="true"/>
</channel-type>
<channel-type id="energyType">
<item-type>Number:Energy</item-type>
<label>Teleinfo Energy Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="currentType">
<item-type>Number:ElectricCurrent</item-type>
<label>Teleinfo Current Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="potentialType">
<item-type>Number:ElectricPotential</item-type>
<label>Teleinfo Potential Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="powerType">
<item-type>Number:Power</item-type>
<label>Teleinfo Power Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="switchType">
<item-type>Switch</item-type>
<label>Teleinfo Switch Type</label>
<category>Energy</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="dateTimeType">
<item-type>DateTime</item-type>
<label>Teleinfo DateTime Type</label>
<category>Energy</category>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<channel-group-type id="producerLSMGroupType">
<label>Producer</label>
<description>Producer channels for Linky telemeter in standard teleinformation mode</description>
<category>Energy</category>
<channels>
<channel id="eait" typeId="energyType">
<label>EAIT</label>
<description>Total active energy injected</description>
</channel>
<channel id="erq1" typeId="energyType">
<label>ERQ1</label>
<description>Total reactive energy Q1</description>
</channel>
<channel id="erq2" typeId="energyType">
<label>ERQ2</label>
<description>Total reactive energy Q2</description>
</channel>
<channel id="erq3" typeId="energyType">
<label>ERQ3</label>
<description>Total reactive energy Q3</description>
</channel>
<channel id="erq4" typeId="energyType">
<label>ERQ4</label>
<description>Total reactive energy Q4</description>
</channel>
<channel id="sinsti" typeId="powerType">
<label>SINSTI</label>
<description>Instantaneous injected apparent power</description>
</channel>
<channel id="smaxin" typeId="powerType">
<label>SMAXIN</label>
<description>Maximum injected apparent power of the day</description>
</channel>
<channel id="smaxinMinus1" typeId="powerType">
<label>SMAXIN-1</label>
<description>Maximum injected apparent power of the previous day</description>
</channel>
<channel id="ccain" typeId="powerType">
<label>CCAIN</label>
<description>Injected active charge point N</description>
</channel>
<channel id="ccainMinus1" typeId="powerType">
<label>CCAIN-1</label>
<description>Injected active charge point N-1</description>
</channel>
<channel id="smaxinDate" typeId="dateTimeType">
<label>SMAXIN TIMESTAMP</label>
<description>Timestamp of SMAXIN value</description>
</channel>
<channel id="smaxinMinus1Date" typeId="dateTimeType">
<label>SMAXIN-1 TIMESTAMP</label>
<description>Timestamp of SMAXIN-1 value</description>
</channel>
<channel id="ccainDate" typeId="dateTimeType">
<label>CCAIN TIMESTAMP</label>
<description>Timestamp of CCAIN value</description>
</channel>
<channel id="ccainMinus1Date" typeId="dateTimeType">
<label>CCAIN-1 TIMESTAMP</label>
<description>Timestamp of CCAIN-1 value</description>
</channel>
</channels>
</channel-group-type>
<channel-type id="stringType">
<item-type>String</item-type>
<label>Teleinfo String Type</label>
<category>Energy</category>
<state pattern="%s" readOnly="true"/>
</channel-type>
<channel-type id="energyType">
<item-type>Number:Energy</item-type>
<label>Teleinfo Energy Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="currentType">
<item-type>Number:ElectricCurrent</item-type>
<label>Teleinfo Current Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="potentialType">
<item-type>Number:ElectricPotential</item-type>
<label>Teleinfo Potential Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="powerType">
<item-type>Number:Power</item-type>
<label>Teleinfo Power Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="switchType">
<item-type>Switch</item-type>
<label>Teleinfo Switch Type</label>
<category>Energy</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="dateTimeType">
<item-type>DateTime</item-type>
<label>Teleinfo DateTime Type</label>
<category>Energy</category>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<channel-group-type id="threePhasedLSMGroupType">
<label>Three-phase</label>
<description>Three-phased channels for Linky telemeter in standard teleinformation mode</description>
<category>Energy</category>
<channels>
<channel id="irms2" typeId="currentType">
<label>IRMS2</label>
<description>RMS Current on phase 2</description>
</channel>
<channel id="irms3" typeId="currentType">
<label>IRMS3</label>
<description>RMS Current on phase 3</description>
</channel>
<channel id="urms2" typeId="potentialType">
<label>URMS2</label>
<description>RMS Voltage on phase 2</description>
</channel>
<channel id="urms3" typeId="potentialType">
<label>URMS3</label>
<description>RMS Voltage on phase 3</description>
</channel>
<channel id="sinsts1" typeId="powerType">
<label>SINSTS1</label>
<description>Instantaneous withdrawn apparent power on phase 1</description>
</channel>
<channel id="sinsts2" typeId="powerType">
<label>SINSTS2</label>
<description>Instantaneous withdrawn apparent power on phase 2</description>
</channel>
<channel id="sinsts3" typeId="powerType">
<label>SINSTS3</label>
<description>Instantaneous withdrawn apparent power on phase 3</description>
</channel>
<channel id="smaxsn1" typeId="powerType">
<label>SMAXSN1</label>
<description>Maximum withdrawn apparent power of the day on phase 1</description>
</channel>
<channel id="smaxsn2" typeId="powerType">
<label>SMAXSN2</label>
<description>Maximum withdrawn apparent power of the day on phase 2</description>
</channel>
<channel id="smaxsn3" typeId="powerType">
<label>SMAXSN3</label>
<description>Maximum withdrawn apparent power of the day on phase 3</description>
</channel>
<channel id="smaxsn1Minus1" typeId="powerType">
<label>SMAXSN1-1</label>
<description>Maximum withdrawn apparent power of the previous day on phase 1</description>
</channel>
<channel id="smaxsn2Minus1" typeId="powerType">
<label>SMAXSN2-1</label>
<description>Maximum withdrawn apparent power of the previous day on phase 2</description>
</channel>
<channel id="smaxsn3Minus1" typeId="powerType">
<label>SMAXSN3-1</label>
<description>Maximum withdrawn apparent power of the previous day on phase 3</description>
</channel>
<channel id="umoy2" typeId="potentialType">
<label>UMOY2</label>
<description>Mean Voltage on phase 2</description>
</channel>
<channel id="umoy3" typeId="potentialType">
<label>UMOY3</label>
<description>Mean Voltage on phase 3</description>
</channel>
<channel id="smaxsn1Date" typeId="dateTimeType">
<label>SMAXSN1 TIMESTAMP</label>
<description>Timestamp of SMAXSN1 value</description>
</channel>
<channel id="smaxsn2Date" typeId="dateTimeType">
<label>SMAXSN2 TIMESTAMP</label>
<description>Timestamp of SMAXSN2 value</description>
</channel>
<channel id="smaxsn3Date" typeId="dateTimeType">
<label>SMAXSN3 TIMESTAMP</label>
<description>Timestamp of SMAXSN3 value</description>
</channel>
<channel id="smaxsn1Minus1Date" typeId="dateTimeType">
<label>SMAXSN1-1 TIMESTAMP</label>
<description>Timestamp of SMAXSN1-1 value</description>
</channel>
<channel id="smaxsn2Minus1Date" typeId="dateTimeType">
<label>SMAXSN2-1 TIMESTAMP</label>
<description>Timestamp of SMAXSN2-1 value</description>
</channel>
<channel id="smaxsn3Minus1Date" typeId="dateTimeType">
<label>SMAXSN3-1 TIMESTAMP</label>
<description>Timestamp of SMAXSN3-1 value</description>
</channel>
<channel id="umoy2Date" typeId="dateTimeType">
<label>UMOY2 TIMESTAMP</label>
<description>Timestamp of UMOY2 value</description>
</channel>
<channel id="umoy3Date" typeId="dateTimeType">
<label>UMOY3 TIMESTAMP</label>
<description>Timestamp of UMOY3 value</description>
</channel>
</channels>
</channel-group-type>
<channel-type id="stringType">
<item-type>String</item-type>
<label>Teleinfo String Type</label>
<category>Energy</category>
<state pattern="%s" readOnly="true"/>
</channel-type>
<channel-type id="energyType">
<item-type>Number:Energy</item-type>
<label>Teleinfo Energy Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="currentType">
<item-type>Number:ElectricCurrent</item-type>
<label>Teleinfo Current Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="potentialType">
<item-type>Number:ElectricPotential</item-type>
<label>Teleinfo Potential Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="powerType">
<item-type>Number:Power</item-type>
<label>Teleinfo Power Type</label>
<category>Energy</category>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="switchType">
<item-type>Switch</item-type>
<label>Teleinfo Switch Type</label>
<category>Energy</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="dateTimeType">
<item-type>DateTime</item-type>
<label>Teleinfo DateTime Type</label>
<category>Energy</category>
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lsmm_electricitymeter" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="serialcontroller"/>
</supported-bridge-type-refs>
<label>Linky Single-phase</label>
<description>Single-phase Linky Electricity meter in standard mode</description>
<channel-groups>
<channel-group id="commonLSMGroup" typeId="commonLSMGroupType"/>
</channel-groups>
<config-description-ref uri="thing-type:teleinfo:adco"/>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lsmm_prod_electricitymeter" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="serialcontroller"/>
</supported-bridge-type-refs>
<label>Linky Single-phase Producer</label>
<description>Single-phase producer Linky Electricity meter in standard mode</description>
<channel-groups>
<channel-group id="commonLSMGroup" typeId="commonLSMGroupType"/>
<channel-group id="producerLSMGroup" typeId="producerLSMGroupType"/>
</channel-groups>
<config-description-ref uri="thing-type:teleinfo:adco"/>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lsmt_electricitymeter" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="serialcontroller"/>
</supported-bridge-type-refs>
<label>Linky Three-phase</label>
<description>Three-phase Linky Electricity meter in standard mode</description>
<channel-groups>
<channel-group id="commonLSMGroup" typeId="commonLSMGroupType"/>
<channel-group id="threePhasedLSMGroup" typeId="threePhasedLSMGroupType"/>
</channel-groups>
<config-description-ref uri="thing-type:teleinfo:adco"/>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="teleinfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="lsmt_prod_electricitymeter" listed="false">
<supported-bridge-type-refs>
<bridge-type-ref id="serialcontroller"/>
</supported-bridge-type-refs>
<label>Linky Three-phase Producer</label>
<description>Three-phase producer Linky Electricity meter in standard mode</description>
<channel-groups>
<channel-group id="commonLSMGroup" typeId="commonLSMGroupType"/>
<channel-group id="producerLSMGroup" typeId="producerLSMGroupType"/>
<channel-group id="threePhasedLSMGroup" typeId="threePhasedLSMGroupType"/>
</channel-groups>
<config-description-ref uri="thing-type:teleinfo:adco"/>
</thing-type>
</thing:thing-descriptions>

View File

@@ -19,6 +19,22 @@
<description>Serial port of Teleinfo device (e.g.: /dev/ttyUSB0 on Linux, COM1 on Windows)</description>
<limitToOptions>false</limitToOptions>
</parameter>
<parameter name="ticMode" type="text" required="true">
<label>TIC mode</label>
<description>TIC Mode of the telemeter (Standard TIC mode is only available on Linky telemeters)</description>
<default>HISTORICAL</default>
<options>
<option value="HISTORICAL">Historical</option>
<option value="STANDARD">Standard</option>
</options>
<limitToOptions>true</limitToOptions>
</parameter>
<parameter name="verifyChecksum" type="boolean" required="true">
<label>Checksum Verification</label>
<description>Activate checksum verification</description>
<default>true</default>
<advanced>true</advanced>
</parameter>
<parameter name="autoRepairInvalidADPSgroupLine" type="boolean" required="false">
<label>Auto Repair Malformed ADPS Data</label>
<description>Try to auto repair malformed ADPS data from hardware issues (e.g: "ADPS032" instead of "ADPS 032"

View File

@@ -15,13 +15,17 @@ package org.openhab.binding.teleinfo.internal.reader.io;
import static org.junit.jupiter.api.Assertions.*;
import java.io.FileInputStream;
import java.time.Month;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
import org.openhab.binding.teleinfo.internal.TeleinfoBindingConstants;
import org.openhab.binding.teleinfo.internal.data.Frame;
import org.openhab.binding.teleinfo.internal.data.FrameType;
import org.openhab.binding.teleinfo.internal.reader.io.serialport.Label;
import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
import org.openhab.binding.teleinfo.util.TestUtils;
import org.openhab.core.library.types.DateTimeType;
/**
*
@@ -33,7 +37,8 @@ public class TeleinfoInputStreamTest {
@Test
public void testReadNextFrameCbetmBase1() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("cbetm-base-option-1.raw")), false)) {
new FileInputStream(TestUtils.getTestFile("cbetm-base-option-1.raw")), false,
TeleinfoTicMode.HISTORICAL)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
@@ -57,7 +62,8 @@ public class TeleinfoInputStreamTest {
@Test
public void testReadNextFrameCbemmEvoIccHc1() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("cbemm-evo-icc-hc-option-1.raw")), false)) {
new FileInputStream(TestUtils.getTestFile("cbemm-evo-icc-hc-option-1.raw")), false,
TeleinfoTicMode.HISTORICAL)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
@@ -78,7 +84,8 @@ public class TeleinfoInputStreamTest {
@Test
public void testReadNextFrameCbetmEjp1() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("cbetm-ejp-option-1.raw")), false)) {
new FileInputStream(TestUtils.getTestFile("cbetm-ejp-option-1.raw")), false,
TeleinfoTicMode.HISTORICAL)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
@@ -104,7 +111,8 @@ public class TeleinfoInputStreamTest {
@Test
public void testReadNextFrameCbemmEvoIccTempo1() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("cbemm-evo-icc-tempo-option-1.raw")), false)) {
new FileInputStream(TestUtils.getTestFile("cbemm-evo-icc-tempo-option-1.raw")), false,
TeleinfoTicMode.HISTORICAL)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
@@ -133,7 +141,8 @@ public class TeleinfoInputStreamTest {
@Test
public void testReadNextFrameCbemmEvoIccBase1() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("cbemm-evo-icc-base-option-1.raw")), false)) {
new FileInputStream(TestUtils.getTestFile("cbemm-evo-icc-base-option-1.raw")), false,
TeleinfoTicMode.HISTORICAL)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
assertEquals(FrameType.CBEMM_ICC_BASE, frame.getType());
@@ -151,7 +160,8 @@ public class TeleinfoInputStreamTest {
@Test
public void testInvalidADPSgrouplineWithAutoRepairActivated() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("invalid-adps-groupline.raw")), true)) {
new FileInputStream(TestUtils.getTestFile("invalid-adps-groupline.raw")), true,
TeleinfoTicMode.HISTORICAL)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
@@ -159,4 +169,60 @@ public class TeleinfoInputStreamTest {
assertEquals(37, frame.getAsInt(Label.ADPS));
}
}
@Test
public void testReadNextFrameLinkyTICModeStandardThreePhaseProd() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("linky-tic-mode-standard-three-phase-prod.raw")), false,
TeleinfoTicMode.STANDARD, true)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
assertEquals(FrameType.LSMT_PROD, frame.getType());
assertEquals("123456789012", frame.get(Label.ADSC));
assertEquals("02", frame.get(Label.VTIC));
assertEquals("", frame.get(Label.DATE));
assertEquals(" TEMPO ", frame.get(Label.NGTF));
assertEquals(" HP BLEU ", frame.get(Label.LTARF));
assertEquals(11604109, frame.getAsInt(Label.EAST));
assertEquals(2741488, frame.getAsInt(Label.EASF01));
assertEquals(18, frame.getAsInt(Label.PCOUP));
assertEquals("2021-04-14T08:26:25", frame.getAsDateTime(Label.DATE));
DateTimeType dateTime = DateTimeType.valueOf(frame.getAsDateTime(Label.DATE));
assertEquals(2021, dateTime.getZonedDateTime().getYear());
assertEquals(Month.APRIL, dateTime.getZonedDateTime().getMonth());
assertEquals(14, dateTime.getZonedDateTime().getDayOfMonth());
assertEquals(8, dateTime.getZonedDateTime().getHour());
assertEquals(26, dateTime.getZonedDateTime().getMinute());
assertEquals(25, dateTime.getZonedDateTime().getSecond());
assertNotEquals(TeleinfoBindingConstants.NOT_A_CHANNEL, Label.CCASN.getTimestampChannelName());
assertEquals("2021-04-14T08:00:00", frame.getAsDateTime(Label.CCASN));
dateTime = DateTimeType.valueOf(frame.getAsDateTime(Label.CCASN));
assertEquals(2021, dateTime.getZonedDateTime().getYear());
assertEquals(Month.APRIL, dateTime.getZonedDateTime().getMonth());
assertEquals(14, dateTime.getZonedDateTime().getDayOfMonth());
assertEquals(8, dateTime.getZonedDateTime().getHour());
assertEquals(0, dateTime.getZonedDateTime().getMinute());
assertEquals(0, dateTime.getZonedDateTime().getSecond());
}
}
@Test
public void testReadNextFrameLinkyTICModeStandardSinglePhaseProd() throws Exception {
try (TeleinfoInputStream in = new TeleinfoInputStream(
new FileInputStream(TestUtils.getTestFile("linky-tic-mode-standard-single-phase-prod.raw")),
TeleinfoTicMode.STANDARD, true)) {
Frame frame = in.readNextFrame();
assertNotNull(frame);
assertEquals(FrameType.LSMM_PROD, frame.getType());
assertEquals("123456789012", frame.get(Label.ADSC));
assertEquals("02", frame.get(Label.VTIC));
assertEquals("", frame.get(Label.DATE));
assertEquals("PRODUCTEUR", frame.get(Label.NGTF));
assertEquals("INDEX NON CONSO ", frame.get(Label.LTARF));
assertEquals(0, frame.getAsInt(Label.EAST));
assertEquals(0, frame.getAsInt(Label.EASF01));
assertEquals(32781, frame.getAsInt(Label.EAIT));
}
}
}

View File

@@ -0,0 +1,75 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.teleinfo.internal.reader.io.serialport;
import static org.junit.jupiter.api.Assertions.*;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
import org.openhab.binding.teleinfo.internal.reader.io.TeleinfoInputStream;
import org.openhab.binding.teleinfo.internal.serial.TeleinfoTicMode;
import org.openhab.binding.teleinfo.util.TestUtils;
/**
*
* @author Olivier MARCEAU - Initial contribution
*/
@NonNullByDefault
public class FrameUtilTest {
@Test
public void testComputeGroupLineChecksumThreePhaseProd() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
new FileInputStream(TestUtils.getTestFile("linky-tic-mode-standard-three-phase-prod.raw"))));
String groupLine;
int i = 0;
while ((groupLine = bufferedReader.readLine()) != null) {
if (i >= 1 && !TeleinfoInputStream.isHeaderFrame(groupLine)) {
char expected = groupLine.charAt(groupLine.length() - 1);
char actual = FrameUtil.computeGroupLineChecksum(groupLine.substring(0, groupLine.length() - 2),
TeleinfoTicMode.STANDARD);
assertEquals(expected, actual, i + " " + groupLine + " " + (int) expected + " " + (int) actual);
}
i++;
}
}
@Test
public void testComputeGroupLineChecksumSinglePhaseProd() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
new FileInputStream(TestUtils.getTestFile("linky-tic-mode-standard-single-phase-prod.raw"))));
String groupLine;
int i = 0;
while ((groupLine = bufferedReader.readLine()) != null) {
if (i >= 1 && !TeleinfoInputStream.isHeaderFrame(groupLine)) {
char expected = groupLine.charAt(groupLine.length() - 1);
char actual = FrameUtil.computeGroupLineChecksum(groupLine.substring(0, groupLine.length() - 2),
TeleinfoTicMode.STANDARD);
assertEquals(expected, actual, i + " " + groupLine + " " + (int) expected + " " + (int) actual);
}
i++;
}
}
@Test
public void testComputeRelaisStates() {
assertArrayEquals(new boolean[] { true, false, false, false, false, false, false, false },
FrameUtil.parseRelaisStates("001"));
assertArrayEquals(new boolean[] { false, false, true, true, false, false, false, true },
FrameUtil.parseRelaisStates("140"));
}
}

View File

@@ -14,6 +14,6 @@ IMAX3 027 ;
PMAX 07990 ?
PAPP 00540 *
MOTDETAT 400000 F
PPOT 00 #
PPOT 00 #

ADCO XXXXXXXXXXXX 7

View File

@@ -15,6 +15,6 @@ IMAX3 044 :
PMAX 17480 :
PAPP 05800 .
MOTDETAT 000000 B
PPOT 00 #
PPOT 00 #

ADCO XXXXXXXXXX G

View File

@@ -0,0 +1,70 @@
EP*PREF 03 B
PCOUP 03 \
SINSTS 00000 F
SMAXSN E180716063417 00021 9
SMAXSN-1 E180715064903 00023 Y
SINSTI 01258 L
SMAXIN E180716103316 01423 /
SMAXIN-1 E180715144229 01971 \
CCASN E180716100000 00000 0
CCASN-1 E180716090000 00000 V
UMOY1 E180716103000 230 +
STGE 002A0301 <
MSG1 PAS DE MESSAGE <
PRM 12345678901234 8
RELAIS 000 B
NTARF 01 N
NJOURF 00 &
NJOURF+1 00 B
PJOURF+1 00008001 NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE 9

ADSC 123456789012 =
VTIC 02 J
DATE E180716103423 B
NGTF PRODUCTEUR .
LTARF INDEX NON CONSO 0
EAST 000000000 O
EASF01 000000000 "
EASF02 000000000 #
EASF03 000000000 $
EASF04 000000000 %
EASF05 000000000 &
EASF06 000000000 '
EASF07 000000000 (
EASF08 000000000 )
EASF09 000000000 *
EASF10 000000000 "
EASD01 000000000
EASD02 000000000 !
EASD03 000000000 "
EASD04 000000000 #
EAIT 000032781 Z
ERQ1 000000000 ;
ERQ2 000000890 M
ERQ3 000002546 N
ERQ4 000000000 >
IRMS1 005 3
URMS1 228 F
PREF 03 B
PCOUP 03 \
SINSTS 00000 F
SMAXSN E180716063417 00021 9
SMAXSN-1 E180715064903 00023 Y
SINSTI 01253 G
SMAXIN E180716103316 01423 /
SMAXIN-1 E180715144229 01971 \
CCASN E180716100000 00000 0
CCASN-1 E180716090000 00000 V
UMOY1 E180716103000 230 +
STGE 002A0301 <
MSG1 PAS DE MESSAGE <
PRM 12345678901234 8
RELAIS 000 B
NTARF 01 N
NJOURF 00 &
NJOURF+1 00 B
PJOURF+1 00008001 NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE 9

ADSC 123456789012 =
VTIC 02 J
DATE E180716103424 C

View File

@@ -0,0 +1,171 @@
774332 X
IRMS1 001 /
IRMS2 002 1
IRMS3 001 1
URMS1 234 C
URMS2 240 A
URMS3 242 D
PREF 18 H
PCOUP 18 "
SINSTS 00046 P
SINSTS1 00000 7
SINSTS2 00531 A
SINSTS3 00000 9
SMAXSN E210414070239 02636 <
SMAXSN1 E210414060632 00405 !
SMAXSN2 E210414070239 02194 -
SMAXSN3 E210414054725 00565 0
SMAXSN-1 E210413195606 06560 _
SMAXSN1-1 E210413111148 01084 A
SMAXSN2-1 E210413195606 03275 Q
SMAXSN3-1 E210413195814 02904 Q
SINSTI 00000 <
SMAXIN E210414000000 00000 L
SMAXIN-1 E210413141848 03861 U
CCASN E210414080000 00806 :
CCASN-1 E210414073000 01152 U
CCAIN E210414080000 00000 "
CCAIN-1 E210414073000 00000 B
UMOY1 E210414082000 230 &
UMOY2 E210414082000 239 0
UMOY3 E210414082000 243 ,
STGE 013A0501 @
MSG1 PAS DE MESSAGE <
PRM 12345678901234 8
RELAIS 000 B
NTARF 02 O
NJOURF 00 &
NJOURF+1 00 B
PJOURF+1 00004001 06004002 22004001 NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE .

ADSC 123456789012 =
VTIC 02 J
DATE E210414082625 A
NGTF TEMPO F
LTARF HP BLEU +
EAST 011604109 %
EASF01 002741488 D
EASF02 005905500 ;
EASF03 000624053 8
EASF04 001070566 >
EASF05 000524151 8
EASF06 000738351 B
EASF07 000000000 (
EASF08 000000000 )
EASF09 000000000 *
EASF10 000000000 "
EASD01 011604109 6
EASD02 000000000 !
EASD03 000000000 "
EASD04 000000000 #
EAIT 000671631 ]
ERQ1 002970842 [
ERQ2 000204084 N
ERQ3 000084948 ^
ERQ4 000774332 X
IRMS1 001 /
IRMS2 002 1
IRMS3 001 1
URMS1 234 C
URMS2 240 A
URMS3 242 D
PREF 18 H
PCOUP 18 "
SINSTS 00013 J
SINSTS1 00000 7
SINSTS2 00568 K
SINSTS3 00000 9
SMAXSN E210414070239 02636 <
SMAXSN1 E210414060632 00405 !
SMAXSN2 E210414070239 02194 -
SMAXSN3 E210414054725 00565 0
SMAXSN-1 E210413195606 06560 _
SMAXSN1-1 E210413111148 01084 A
SMAXSN2-1 E210413195606 03275 Q
SMAXSN3-1 E210413195814 02904 Q
SINSTI 00000 <
SMAXIN E210414000000 00000 L
SMAXIN-1 E210413141848 03861 U
CCASN E210414080000 00806 :
CCASN-1 E210414073000 01152 U
CCAIN E210414080000 00000 "
CCAIN-1 E210414073000 00000 B
UMOY1 E210414082000 230 &
UMOY2 E210414082000 239 0
UMOY3 E210414082000 243 ,
STGE 013A0501 @
MSG1 PAS DE MESSAGE <
PRM 12345678901234 8
RELAIS 000 B
NTARF 02 O
NJOURF 00 &
NJOURF+1 00 B
PJOURF+1 00004001 06004002 22004001 NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE .

ADSC 123456789012 =
VTIC 02 J
DATE E210414082627 C
NGTF TEMPO F
LTARF HP BLEU +
EAST 011604109 %
EASF01 002741488 D
EASF02 005905500 ;
EASF03 000624053 8
EASF04 001070566 >
EASF05 000524151 8
EASF06 000738351 B
EASF07 000000000 (
EASF08 000000000 )
EASF09 000000000 *
EASF10 000000000 "
EASD01 011604109 6
EASD02 000000000 !
EASD03 000000000 "
EASD04 000000000 #
EAIT 000671631 ]
ERQ1 002970842 [
ERQ2 000204084 N
ERQ3 000084948 ^
ERQ4 000774332 X
IRMS1 001 /
IRMS2 002 1
IRMS3 001 1
URMS1 234 C
URMS2 240 A
URMS3 242 D
PREF 18 H
PCOUP 18 "
SINSTS 00018 O
SINSTS1 00000 7
SINSTS2 00565 H
SINSTS3 00000 9
SMAXSN E210414070239 02636 <
SMAXSN1 E210414060632 00405 !
SMAXSN2 E210414070239 02194 -
SMAXSN3 E210414054725 00565 0
SMAXSN-1 E210413195606 06560 _
SMAXSN1-1 E210413111148 01084 A
SMAXSN2-1 E210413195606 03275 Q
SMAXSN3-1 E210413195814 02904 Q
SINSTI 00000 <
SMAXIN E210414000000 00000 L
SMAXIN-1 E210413141848 03861 U
CCASN E210414080000 00806 :
CCASN-1 E210414073000 01152 U
CCAIN E210414080000 00000 "
CCAIN-1 E210414073000 00000 B
UMOY1 E210414082000 230 &
UMOY2 E210414082000 239 0
UMOY3 E210414082000 243 ,
STGE 013A0501 @
MSG1 PAS DE MESSAGE <
PRM 12345678901234 8
RELAIS 000 B
NTARF 02 O
NJOURF 00 &
NJOURF+1 00 B
PJOURF+1 00004001 06004002 22004001 NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE NONUTILE .

ADSC 123456789012 =
VTIC 02 J
DATE E210414082629 E