]> git.basschouten.com Git - openhab-addons.git/commitdiff
[teleinfo] Add support for Standard tic mode (#11375)
authorolivierkeke <olivierkeke@users.noreply.github.com>
Sun, 12 Dec 2021 21:58:36 +0000 (22:58 +0100)
committerGitHub <noreply@github.com>
Sun, 12 Dec 2021 21:58:36 +0000 (22:58 +0100)
* 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>
34 files changed:
bundles/org.openhab.binding.teleinfo/README.md [changed mode: 0644->0755]
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/TeleinfoBindingConstants.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/TeleinfoDiscoveryService.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/data/Evolution.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/data/Frame.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/data/FrameType.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/data/Phase.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/data/Pricing.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/handler/TeleinfoElectricityMeterHandler.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/handler/TeleinfoThingHandlerFactory.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/reader/io/TeleinfoInputStream.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/reader/io/serialport/FrameUtil.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/reader/io/serialport/Label.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/reader/io/serialport/ValueType.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/serial/TeleinfoReceiveThread.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/serial/TeleinfoSerialControllerConfiguration.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/serial/TeleinfoSerialControllerHandler.java
bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/serial/TeleinfoTicMode.java [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/config/config-description.xml
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-channel-group.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-prod-channel-group.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-three-phase-channel-group.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmmElectricityMeter.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmmProdElectricityMeter.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmtElectricityMeter.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmtProdElectricityMeter.xml [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/serialController.xml
bundles/org.openhab.binding.teleinfo/src/test/java/org/openhab/binding/teleinfo/internal/reader/io/TeleinfoInputStreamTest.java
bundles/org.openhab.binding.teleinfo/src/test/java/org/openhab/binding/teleinfo/internal/reader/io/serialport/FrameUtilTest.java [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/test/resources/cbemm-evo-icc-tempo-option-1.raw
bundles/org.openhab.binding.teleinfo/src/test/resources/cbetm-base-option-1.raw
bundles/org.openhab.binding.teleinfo/src/test/resources/cbetm-ejp-option-1.raw
bundles/org.openhab.binding.teleinfo/src/test/resources/linky-tic-mode-standard-single-phase-prod.raw [new file with mode: 0644]
bundles/org.openhab.binding.teleinfo/src/test/resources/linky-tic-mode-standard-three-phase-prod.raw [new file with mode: 0644]

old mode 100644 (file)
new mode 100755 (executable)
index 4a2002a..7ebd4b2
@@ -12,6 +12,10 @@ These values can be used to
 
 ## 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
@@ -34,6 +38,19 @@ The Teleinfo binding provides support for both single-phase and three-phase conn
 | 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.
@@ -49,30 +66,33 @@ Once the serial controller added, electricity meters will automatically appear a
 |----------------------|--------------|---------------------------------------|---------------------------------|
 | `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  |
@@ -88,8 +108,64 @@ Channel availability depends on the electricity connection (single or three-phas
 | 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` :
 
 ```
index 3b942d2c22c39507901b98b6baccfa7db451442e..f2ab5e97e32d457c295b6fb4b6f1c6cdbd7b3e81 100644 (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";
index f3ff6c4bcac81163bcb9636cf0100c38d7cf5722..c6f59a4980e6f7dc53e57c9dd0f840a97795552a 100644 (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();
 
index 158d58a8447836ccd0a950cd1f4e653477d1305d..4a51753f1dafaeed99aac6791afb6b8e64e83806 100644 (file)
  */
 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
index 3594885198abbc971e7b301acadeca4909d1a33e..e83f83efa774729ee380e333fae1dbfcd656b623 100644 (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) {
index a829805b37ffd8c256c43a9ce9e6df64fd03f7af..05a590d9831ad109b507aebf66f7753fff079202 100644 (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;
     }
 }
index 44edb6d0a4e2522fa570449bebb8351192c86f16..dfe0c42d8d5f7f58bb7e65cbba94935573a74f85 100644 (file)
  */
 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
index cef1a504f6e4732c98d0a8350a100a5a48d43b1a..6bc6cabcb670c2162636ab4e372f8450e9c07ddc 100644 (file)
  */
 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,
index 67a8bd8da717b179ab260e7da6690fdc01c04135..ee0a0c24b979ced7a3a5afa6a2d050220fb23300 100644 (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()));
                 }
             }
-        }
-        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());
index bc7755c692ecbb5f86107e2d54f459f39c43739b..2378dddd3b0613c9913d3267330a425f0198475d 100644 (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;
index 270675054f9183d800e626c2d668bf6473f4d596..7152be74dc8b5ab9f79605e47ef85947b37944e1 100644 (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);
     }
index ee8268a1f0e0b5058682bd050a7bbacf1461522f..fd8b623c969aaab186d9bcc9152cc480fcaa3e2a 100644 (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;
+    }
 }
index 433fb136c862a54a18708728d8688f0fa1dd4a62..e2b56d9f3d57b89a88d5c32e2c262ee5df2d1f3e 100644 (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);
+    }
 }
index 62d743565fe005c735f3991736177cd34ee0284f..76519d3b6790a21f55e8103e744331f0b0ab6c8a 100644 (file)
  */
 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
index a3eee6052cf193e705622e62a1ee61bf530a6c03..7228190bf5d9105f91eea493f044b3eef961dd6e 100644 (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) {
index 654a6250d843ffef56a0f90ae8b5836b04765ec6..71711c4dbdee45257bf82ef3c8623703417936b0 100644 (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;
 }
index b5e08d32fbdb50b19cf721c10e6851f156fba4e6..44fe2c15a27b59dc1ad1115e16045c0095cb51b6 100644 (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();
 
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/serial/TeleinfoTicMode.java b/bundles/org.openhab.binding.teleinfo/src/main/java/org/openhab/binding/teleinfo/internal/serial/TeleinfoTicMode.java
new file mode 100644 (file)
index 0000000..77cd6ef
--- /dev/null
@@ -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;
+    }
+}
index 6701d48d220c390de7accaa017413e96f37a539b..34d2a259b042930bbd3215b63c01334c2ecd5ecd 100644 (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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-channel-group.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-channel-group.xml
new file mode 100644 (file)
index 0000000..8a17dd7
--- /dev/null
@@ -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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-prod-channel-group.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-prod-channel-group.xml
new file mode 100644 (file)
index 0000000..6339958
--- /dev/null
@@ -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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-three-phase-channel-group.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/common-lsm-three-phase-channel-group.xml
new file mode 100644 (file)
index 0000000..4086022
--- /dev/null
@@ -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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmmElectricityMeter.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmmElectricityMeter.xml
new file mode 100644 (file)
index 0000000..674173f
--- /dev/null
@@ -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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmmProdElectricityMeter.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmmProdElectricityMeter.xml
new file mode 100644 (file)
index 0000000..d23487f
--- /dev/null
@@ -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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmtElectricityMeter.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmtElectricityMeter.xml
new file mode 100644 (file)
index 0000000..de906e2
--- /dev/null
@@ -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>
diff --git a/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmtProdElectricityMeter.xml b/bundles/org.openhab.binding.teleinfo/src/main/resources/OH-INF/thing/lsmtProdElectricityMeter.xml
new file mode 100644 (file)
index 0000000..b744df2
--- /dev/null
@@ -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>
index 486c94676f538b75a51c4831943cb534fa8ec9c4..22984bc17e98177c0fe61ee16228c0ada9503cc4 100644 (file)
                                <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"
index d17f77c9d25a1be15b43c39af442be3e3802d095..d420013900488dd5a2efdbedb06f62accb93d3a3 100644 (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));
+        }
+    }
 }
diff --git a/bundles/org.openhab.binding.teleinfo/src/test/java/org/openhab/binding/teleinfo/internal/reader/io/serialport/FrameUtilTest.java b/bundles/org.openhab.binding.teleinfo/src/test/java/org/openhab/binding/teleinfo/internal/reader/io/serialport/FrameUtilTest.java
new file mode 100644 (file)
index 0000000..057bc06
--- /dev/null
@@ -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"));
+    }
+}
index e258d50e97c37afa110d8db309f91c740f855079..33fe7015dca6fad50cdf409bde301bef55a10439 100644 (file)
Binary files a/bundles/org.openhab.binding.teleinfo/src/test/resources/cbemm-evo-icc-tempo-option-1.raw and b/bundles/org.openhab.binding.teleinfo/src/test/resources/cbemm-evo-icc-tempo-option-1.raw differ
index 888d21217de8e27652d7d9ae697627ec5b0c1861..687acf04810011225d388c93f54fda5b8734a52d 100644 (file)
@@ -14,6 +14,6 @@ IMAX3 027 ;
 PMAX 07990 ?
 PAPP 00540 *
 MOTDETAT 400000 F
-PPOT 00 #\ 2
+PPOT 00 #
 \ 3\ 2
 ADCO XXXXXXXXXXXX 7
\ No newline at end of file
index 6ce7b6c901739feb4f26f2df9745d969678ea9f2..c080ed2ccb7b1496b5869888311ed5fcdc5ecb8d 100644 (file)
@@ -15,6 +15,6 @@ IMAX3 044 :
 PMAX 17480 :
 PAPP 05800 .
 MOTDETAT 000000 B
-PPOT 00 #\ 2
+PPOT 00 #
 \ 3\ 2
 ADCO XXXXXXXXXX G
\ No newline at end of file
diff --git a/bundles/org.openhab.binding.teleinfo/src/test/resources/linky-tic-mode-standard-single-phase-prod.raw b/bundles/org.openhab.binding.teleinfo/src/test/resources/linky-tic-mode-standard-single-phase-prod.raw
new file mode 100644 (file)
index 0000000..f105718
--- /dev/null
@@ -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
+\ 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
diff --git a/bundles/org.openhab.binding.teleinfo/src/test/resources/linky-tic-mode-standard-three-phase-prod.raw b/bundles/org.openhab.binding.teleinfo/src/test/resources/linky-tic-mode-standard-three-phase-prod.raw
new file mode 100644 (file)
index 0000000..dc0225a
--- /dev/null
@@ -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      .
+\ 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