## Supported Things
+### Historical TIC mode
+
+Historical TIC mode is the only mode of all telemeters before Linky models and the default mode for Linky telemeters.
+
The Teleinfo binding provides support for both single-phase and three-phase connection, ICC evolution and the following pricing modes:
- HCHP mode
| cbetm_hc_electricitymeter | three-phase | HCHP | |
| cbetm_tempo_electricitymeter | three-phase | Tempo | |
+### Standard TIC mode
+
+Linky telemeters add a new `Standard` mode with more detailed information but still provide information on the legacy format under the `Historical` denomination.
+
+Standard mode doesn't depend on the pricing options, but it adds some useful information for electricity producers.
+
+| Thing type | Connection | Producer mode |
+|--------------------------------------------|--------------|--------------|
+| lsmm_electricitymeter | single-phase | |
+| lsmm_prod_electricitymeter | single-phase | [x] |
+| lstm_electricitymeter | three-phase | |
+| lstm_prod_electricitymeter | three-phase | [x] |
+
## Discovery
Before the binding can be used, a serial controller must be added. This needs to be done manually. Select __Teleinfo Serial Controller__ and enter the serial port.
|----------------------|--------------|---------------------------------------|---------------------------------|
| `serialcontroller` | `serialport` | Path to the serial controller | /dev/ttyXXXX, rfc2217://ip:port |
| `*_electricitymeter` | `adco` | Electricity meter identifier | 12 digits number |
+| | `ticMode` | TIC mode | `STANDARD`, `HISTORICAL` (default) |
## Channels
+### Historical TIC mode
+
Channel availability depends on the electricity connection (single or three-phase) and on the pricing mode (Base, HCHP, EJP or Tempo).
-| Channel | Type | Description | Phase | Mode |
+| Channel | Type | Description | Connection | Mode |
|----------|---------------------------|----------------------------------------------------------|--------|-------|
| isousc | `Number:ElectricCurrent` | Subscribed electric current | All | All |
| ptec | `String` | Current pricing period | All | All |
-| imax | `Number:ElectricCurrent` | Maximum consumed electric current | Single | All |
-| imax1 | `Number:ElectricCurrent` | Maximum consumed electric current on phase 1 | Three | All |
-| imax2 | `Number:ElectricCurrent` | Maximum consumed electric current on phase 2 | Three | All |
-| imax3 | `Number:ElectricCurrent` | Maximum consumed electric current on phase 3 | Three | All |
-| adps | `Number:ElectricCurrent` | Excess electric current warning | Single | All |
-| adir1 | `Number:ElectricCurrent` | Excess electric current on phase 1 warning | Three | All |
-| adir2 | `Number:ElectricCurrent` | Excess electric current on phase 2 warning | Three | All |
-| adir3 | `Number:ElectricCurrent` | Excess electric current on phase 3 warning | Three | All |
-| iinst | `Number:ElectricCurrent` | Instantaneous electric current | Single | All |
-| iinst1 | `Number:ElectricCurrent` | Instantaneous electric current on phase 1 | Three | All |
-| iinst2 | `Number:ElectricCurrent` | Instantaneous electric current on phase 2 | Three | All |
-| iinst3 | `Number:ElectricCurrent` | Instantaneous electric current on phase 3 | Three | All |
-| ppot | `String` | Electrical potential presence | Three | All |
-| pmax | `Number:Energy` | Maximum consumed electric power on all phases | Three | All |
-| papp | `Number:Power` | Instantaneous apparent power | Three, single (ICC evolution only) | All |
+| imax | `Number:ElectricCurrent` | Maximum consumed electric current | Single-phase | All |
+| imax1 | `Number:ElectricCurrent` | Maximum consumed electric current on phase 1 | Three-phase | All |
+| imax2 | `Number:ElectricCurrent` | Maximum consumed electric current on phase 2 | Three-phase | All |
+| imax3 | `Number:ElectricCurrent` | Maximum consumed electric current on phase 3 | Three-phase | All |
+| adps | `Number:ElectricCurrent` | Excess electric current warning | Single-phase | All |
+| adir1 | `Number:ElectricCurrent` | Excess electric current on phase 1 warning | Three-phase | All |
+| adir2 | `Number:ElectricCurrent` | Excess electric current on phase 2 warning | Three-phase | All |
+| adir3 | `Number:ElectricCurrent` | Excess electric current on phase 3 warning | Three-phase | All |
+| iinst | `Number:ElectricCurrent` | Instantaneous electric current | Single-phase | All |
+| iinst1 | `Number:ElectricCurrent` | Instantaneous electric current on phase 1 | Three-phase | All |
+| iinst2 | `Number:ElectricCurrent` | Instantaneous electric current on phase 2 | Three-phase | All |
+| iinst3 | `Number:ElectricCurrent` | Instantaneous electric current on phase 3 | Three-phase | All |
+| ppot | `String` | Electrical potential presence | Three-phase | All |
+| pmax | `Number:Energy` | Maximum consumed electric power on all phases | Three-phase | All |
+| papp | `Number:Power` | Instantaneous apparent power | Three-phase, single-phase (ICC evolution only) | All |
| hhphc | `String` | Pricing schedule group | All | HCHP |
| hchc | `Number:Energy` | Total consumed energy at low rate pricing | All | HCHP |
| hchp | `Number:Energy` | Total consumed energy at high rate pricing | All | HCHP |
| pejp | `Number:Duration` | Prior notice to EJP start | All | EJP |
| demain | `String` | Following day color | All | Tempo |
+### Standard TIC mode
+
+| Channel | Type | Description | Connection | Mode |
+|----------|---------------------------|----------------------------------------------------------|--------|-------|
+| ngtf | `String` | Provider schedule name | All | All |
+| ltarf | `String` | Current pricing label | All | All |
+| east | `Number:Energy` | Total active energy withdrawn | All | All |
+| easf*XX* | `Number:Energy` | Active energy withdrawn from provider on index <img src="https://render.githubusercontent.com/render/math?math=XX \in \{01,\dots,10\}"/> | All | All |
+| easd*XX* | `Number:Energy` | Active energy withdrawn from distributor on index <img src="https://render.githubusercontent.com/render/math?math=XX \in \{01,\dots,04\}"/> | All | All |
+| irms*X* | `Number:ElectricCurrent` | RMS Current on phase *X* | All for <img src="https://render.githubusercontent.com/render/math?math=X=1"/>, Three-phase for <img src="https://render.githubusercontent.com/render/math?math=X\in \{2,3\}"/> | All |
+| urms*X* | `Number:Potential` | RMS Voltage on phase *X* | All for <img src="https://render.githubusercontent.com/render/math?math=X=1"/>, Three-phase for <img src="https://render.githubusercontent.com/render/math?math=X\in \{2,3\}"/> | All |
+| pref | `Number:Power` | Reference apparent power | All | All |
+| pcoup | `Number:Power` | Apparent power rupture capacity | All | All |
+| sinsts | `Number:Power` | Instantaneous withdrawn apparent power | Single-phase | All |
+| smaxsn | `Number:Power` | Maximum withdrawn apparent power of the day | Single-phase | All |
+| smaxsnMinus1 | `Number:Power` | Maximum withdrawn apparent power of the previous day | Single-phase | All |
+| ccasn | `Number:Power` | Active charge point N | All | All |
+| ccasnMinus1 | `Number:Power` | Active charge point N-1 | All | All |
+| umoy*X* | `Number:Potential` | Mean Voltage on phase *X* | All for <img src="https://render.githubusercontent.com/render/math?math=X=1"/>, Three-phase for <img src="https://render.githubusercontent.com/render/math?math=X\in \{2,3\}"/> | All |
+| dpm*X* | `String` | Start of mobile peak period <img src="https://render.githubusercontent.com/render/math?math=X\in \{1,\dots,3\}"/> | All | All |
+| fpm*X* | `String` | End of mobile peak period <img src="https://render.githubusercontent.com/render/math?math=X\in \{1,\dots,3\}"/> | All | All |
+| msg1 | `String` | Short message | All | All |
+| msg2 | `String` | Very short message | All | All |
+| ntarf | `String` | Index of current pricing | All | All |
+| njourf | `String` | Number of current provider schedule | All | All |
+| njourfPlus1 | `String` | Number of next day provider schedule | All | All |
+| pjourfPlus1 | `String` | Profile of next day provider schedule | All | All |
+| ppointe | `String` | Profile of next rush day | All | All |
+| date | `DateTime` | Date and Time | All | All |
+| smaxsnDate | `DateTime` | Timestamp of SMAXSN value | All | All |
+| smaxsnMinus1Date | `DateTime` | Timestamp of SMAXSN-1 value | All | All |
+| ccasnDate | `DateTime` | Timestamp of CCASN value | All | All |
+| ccasnMinus1Date | `DateTime` | Timestamp of CCASN-1 value | All | All |
+| umoy*X*Date | `DateTime` | Timestamp of UMOY*X* value | All for <img src="https://render.githubusercontent.com/render/math?math=X=1"/>, Three-phase for <img src="https://render.githubusercontent.com/render/math?math=X\in \{2,3\}"/> | All |
+| dpm*X*Date | `DateTime` | Date of DPM*X* | All | All |
+| fpm*X*Date | `DateTime` | Date of FPM*X* | All | All |
+| relais*X* | `Switch` | relais status (<img src="https://render.githubusercontent.com/render/math?math=X\in {1,\dots,8}"/> ) | All | All |
+| sinsts*X* | `Number:Power` | Instantaneous withdrawn apparent power on phase *X* | Three-phase | All |
+| smaxsn*X* | `Number:Power` | Maximum withdrawn apparent power of the day on phase *X* | Three-phase | All |
+| smaxsn*X*Minus1 | `Number:Power` | Maximum withdrawn apparent power on the previous day on phase *X* | Three-phase | All |
+| smaxs*X*nDate | `DateTime` | Timestamp of SMAXSN*X* value | Three-phase | All |
+| smaxsn*X*Minus1Date | `DateTime` | Timestamp of SMAXSN*X*-1 value | Three-phase | All |
+| eait | `Number:Energy` | Total active energy withdrawn | All | All |
+| erq*X* | `Number:Energy` | Active energy withdrawn from provider on index <img src="https://render.githubusercontent.com/render/math?math=XX \in \{01,\dots,10\}"/> | All | All |
+| sinsti | `Number:Energy` | Active energy withdrawn from distributor on index <img src="https://render.githubusercontent.com/render/math?math=XX \in \{01,\dots,04\}"/> | All | All |
+| smaxin | `Number:Power` | Maximum injected apparent power of the day | All for <img src="https://render.githubusercontent.com/render/math?math=X=1"/>, Three-phase for <img src="https://render.githubusercontent.com/render/math?math=X\in \{2,3\}"/> | All |
+| smaxinMinus1 | `Number:Power` | Maximum injected apparent power of the previous day | All for <img src="https://render.githubusercontent.com/render/math?math=X=1"/>, Three-phase for <img src="https://render.githubusercontent.com/render/math?math=X\in \{2,3\}"/> | All |
+| ccain | `Number:Power` | Injected active charge point N | All | Producer |
+| ccainMinus1 | `Number:Power` | Injected active charge point N-1 | All | Producer |
+| smaxinDate | `DateTime` | Timestamp of SMAXIN value | All | Producer |
+| smaxinMinus1Date | `DateTime` | Timestamp of SMAXIN-1 value | All | Producer |
+| ccainDate | `DateTime` | Timestamp of CCAIN value | All | Producer |
+| ccainMinus1Date | `DateTime` | Timestamp of CCAIN-1 value | All | Producer |
+
## Full Example
+### Historical TIC mode
+
The following `things` file declare a serial USB controller on `/dev/ttyUSB0` for a Single-phase Electricity meter with HC/HP option - CBEMM Evolution ICC and adco `031528042289` :
```
*/
package org.openhab.binding.teleinfo.internal;
+import java.util.stream.IntStream;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
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";
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 = "";
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";
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;
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;
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());
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();
*/
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
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.
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);
}
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();
}
}
+ 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) {
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;
/**
* @author Olivier MARCEAU - Initial contribution
*
*/
+@NonNullByDefault
public enum FrameType {
CBETM_SHORT(null),
CBETM_LONG_BASE(THING_BASE_CBETM_ELECTRICITY_METER_TYPE_UID),
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;
}
}
*/
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
*/
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,
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;
@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);
}
}
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()));
}
}
- }
- 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()));
+ 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));
+ }
}
- } 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);
+ 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);
+ }
+ 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());
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;
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;
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;
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:
}
frame.put(label, valueString);
+ if (timestampString != null) {
+ frame.putTimestamp(label, timestampString);
+ }
}
}
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);
}
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}.
* 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;
+ }
}
@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),
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() {
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);
+ }
}
*/
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
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) {
public class TeleinfoSerialControllerConfiguration {
public String serialport = "";
+ public String ticMode = "";
+ public boolean verifyChecksum = true;
public boolean autoRepairInvalidADPSgroupLine = true;
}
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) {
}
logger.debug("Starting receive thread");
TeleinfoReceiveThread receiveThread = new TeleinfoReceiveThread(commPort, this,
- config.autoRepairInvalidADPSgroupLine);
+ config.autoRepairInvalidADPSgroupLine, ticMode, config.verifyChecksum);
this.receiveThread = receiveThread;
receiveThread.start();
--- /dev/null
+/**
+ * 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;
+ }
+}
<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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
<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"
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;
/**
*
@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);
@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);
@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);
@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);
@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());
@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);
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));
+ }
+ }
}
--- /dev/null
+/**
+ * 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"));
+ }
+}
PMAX 07990 ?
PAPP 00540 *
MOTDETAT 400000 F
-PPOT 00 #\ 2
+PPOT 00 #
\ 3\ 2
ADCO XXXXXXXXXXXX 7
\ No newline at end of file
PMAX 17480 :
PAPP 05800 .
MOTDETAT 000000 B
-PPOT 00 #\ 2
+PPOT 00 #
\ 3\ 2
ADCO XXXXXXXXXX G
\ No newline at end of file
--- /dev/null
+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
+\ 3\ 2
+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
+\ 3\ 2
+ADSC 123456789012 =
+VTIC 02 J
+DATE E180716103424 C
--- /dev/null
+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 .
+\ 3\ 2
+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 .
+\ 3\ 2
+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 .
+\ 3\ 2
+ADSC 123456789012 =
+VTIC 02 J
+DATE E210414082629 E
\ No newline at end of file