diff --git a/bundles/org.openhab.binding.mercedesme/README.md b/bundles/org.openhab.binding.mercedesme/README.md index 880801824b2f8..bc0f395a97fba 100644 --- a/bundles/org.openhab.binding.mercedesme/README.md +++ b/bundles/org.openhab.binding.mercedesme/README.md @@ -1,6 +1,6 @@ # MercedesMe Binding -This binding provides access to your Mercedes Benz vehicle like _Mercedes Me_ Smartphone App . +This binding provides access to your Mercedes Benz vehicle like _Mercedes Me_ Smartphone App. ## Installation Instructions @@ -41,8 +41,8 @@ Bridge needs configuration in order to connect properly to your Mercedes Me acco | pin | text | Mercedes Me Smartphone App PIN | N/A | no | no | | region | text | Your region | EU | yes | no | | refreshInterval | integer | API refresh interval | 15 | yes | no | -| callbackIP | text | Your region | N/A | yes | yes | -| callbackPort | integer | API refresh interval | N/A | yes | yes | +| callbackIP | text | IP Address of openHAB Device | N/A | yes | yes | +| callbackPort | integer | Port Number of openHAB Device | N/A | yes | yes | Set `region` to your location @@ -135,10 +135,6 @@ Channels are separated in groups: | [position](#position) | Positioning Data | | [tires](#tires) | Tire Information | -## Actions - -See [Vehicle Actions](#vehicle-actions) which can be used in rules. - ### Vehicle Group name: `vehicle` @@ -327,14 +323,16 @@ States and controls are depending on your vehicle capabilities. | Channel | Type | Description | Read | Write | |---------------------|----------------------|----------------------------------|------|-------| -| front-left | Switch | Front Left Seat Climatization | X | | -| front-right | Switch | Front Left Seat Climatization | X | | -| rear-left | Switch | Front Left Seat Climatization | X | | -| rear-right | Switch | Front Left Seat Climatization | X | | -| zone | Number | Selected Climatization Zone | X | X | -| temperature | Number:Temperature | Desired Temperature for Zone | X | X | -| activate | Switch | Start/Stop Climatization | X | X | +| front-left | Switch | AC Seat Front Left | X | | +| front-right | Switch | AC Seat Front Right | X | | +| rear-left | Switch | AC Seat Rear Left | X | | +| rear-right | Switch | AC Seat Rear Right | X | | +| zone | Number | AC Zone | X | X | +| temperature | Number:Temperature | AC Desired Temperature | X | X | +| activate | Switch | AC Precondition Control | X | X | +| ac-status | Number | AC Precondition Status | X | | | aux-heat | Switch | Auxiliary Heating | X | X | +| aux-status | Number | Auxiliary Status | X | | #### Zone Mapping @@ -374,14 +372,35 @@ Fahrenheit Triggers `TEMPERATURECONFIGURE` from [Command Name Mapping](#command-name-mapping) -#### Activate Switch +#### AC Precondition Control Triggers `PRECONDSTART` and `PRECONDSTOP` from [Command Name Mapping](#command-name-mapping) -#### Auxiliary Heat Switch +#### AC Precondition Status Mapping + +- 0 : No Request +- 1 : Battery or Fuel Low +- 2 : Available after Restart Engine +- 3 : Not Possible, Charging not Finished +- 4 : General Error + +#### Auxiliary Heating Switch Triggers `AUXHEATSTART` and `AUXHEATSTOP` from [Command Name Mapping](#command-name-mapping) +#### Auxiliary Status Mapping + +- 0 : None +- 1 : No Budget +- 2 : Budget Empty +- 4 : System Error +- 8 : Running Error +- 16 : Fuel on Reserve +- 32 : Reserve Reached +- 64 : Low Voltage +- 128 : Low Voltage Operation +- 256 : Communication Error + ### Service Group name: `service` @@ -408,6 +427,16 @@ Traffic light status of the starter battery - 0 : Green - 1 : Yellow - 2 : Red +- 3 : Service Disabled +- 4 : Vehicle Not Available + +#### Tire Pressure Warnings Mapping + +- 0 : No warning +- 1 : Soft warning +- 2 : Low warning +- 3 : Deflation +- 4 : Unknown warning ### Range @@ -449,6 +478,8 @@ States and controls are depending on your vehicle capabilities. | coupler-dc | Number | Coupler DC Status | X | | | coupler-lock | Number | Coupler Lock Status | X | | | active | Switch | Charging Active | X | | +| status | Number | Charge Status | X | | +| error | Number | Charge Error | X | | | power | Number:Power | Current Charging Power | X | | | end-time | DateTime | Estimated Charging End | X | | | program | Number | Selected Charge Program | X | X | @@ -475,6 +506,25 @@ States and controls are depending on your vehicle capabilities. - 0 : Locked - 1 : Unlocked +#### Charge Status Mapping + +- 0 : Charging +- 1 : End of Charge +- 2 : Charge Break +- 3 : Charge Cable Unplugged +- 4 : Charging Failure +- 5 : Slow Charging +- 6 : Fast Charging +- 7 : Discharging + +#### Charge Error Mapping + +- 0 : None +- 1 : Cable +- 2 : Charging Disorder +- 3 : Charging Station +- 4 : Charging Type + #### Program Mapping - 0 : DEFAULT_CHARGE_PROGRAM @@ -540,11 +590,32 @@ In your Mercedes Me App front page -### Trip Duration +#### Trip Duration Shown as String in format `d days, HH:mm`. If duration is below 24 hours format is `HH:mm`. +### ECO Score + +Group name: `eco` + +All channels `read-only` + +| Channel | Type | Description | +|---------------------|------------------------|-------------------------| +| accel | Number:Dimensionless | Acceleration Score | +| coasting | Number:Dimensionless | Coasting Score | +| constant | Number:Dimensionless | Constant Score | +| bonus | Number:Length | Bonus Range | + +The Mercedes ECO Score is aimed to improve your driving behavior. + +- Acceleration Score: smooth acceleration e.g. use *eco driving setting* +- Coasting Score: ideally use only *recuperation* instead of brake +- Constant Score: drive at constant speed e.g. use *cruise control* +- Bonus Range: assumed bonus range vs. a *very sportive driver* + + ### Position Group name: `position` @@ -553,8 +624,18 @@ Group name: `position` |---------------------|----------------------|-------------------------------------------------|------|-------| | heading | Number:Angle | Heading of Vehicle | X | | | gps | Point | GPS Location Point of Vehicle | X | | +| status | Number | Status Positioning | X | | | signal | Number | Request Light or Horn Signal to find Vehicle | | X | +#### Status Mapping + +- 0 : Unknown +- 1 : Service Inactive +- 2 : Tracking Inactive +- 3 : Parked +- 4 : Ignition On +- 5 : Ok + #### Signal Settings Command Options @@ -585,11 +666,18 @@ All channels `read-only` #### Sensor Available Mapping -- Not available yet +- 0 : All Sensors Located +- 1 : 1-3 Sensors are Missing +- 2 : All Sensors Missing +- 3 : System Error #### Tire Marker Mapping -- Not available yet +- 0 : No warning +- 1 : Soft warning +- 2 : Low warning +- 3 : Deflation +- 4 : Unknown warning ### Commands diff --git a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/Constants.java b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/Constants.java index 3adf9364de095..50d799cb67ebf 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/Constants.java +++ b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/Constants.java @@ -60,6 +60,8 @@ public class Constants { public static final String MB_KEY_CHARGE_COUPLER_DC_STATUS = "chargeCouplerDCStatus"; public static final String MB_KEY_CHARGE_COUPLER_AC_STATUS = "chargeCouplerACStatus"; public static final String MB_KEY_CHARGE_FLAP_DC_STATUS = "chargeFlapDCStatus"; + public static final String MB_KEY_CHARGE_STATUS = "chargingstatus"; + public static final String MB_KEY_CHARGE_ERROR = "chargingErrorDetails"; public static final String MB_KEY_SERVICEINTERVALDAYS = "serviceintervaldays"; public static final String MB_KEY_TIREWARNINGSRDK = "tirewarningsrdk"; public static final String MB_KEY_STARTER_BATTERY_STATE = "starterBatteryState"; @@ -149,6 +151,13 @@ public class Constants { public static final String MB_KEY_COMMAND_DOORS_LOCK = "commandDoorsLock"; public static final String MB_KEY_COMMAND_WINDOWS_OPEN = "commandWindowsOpen"; public static final String MB_KEY_COMMAND_ENGINE_START = "commandEngineStart"; + public static final String MB_KEY_POSITION_ERROR = "vehiclePositionErrorCode"; + public static final String MB_KEY_AUXILIARY_WARNINGS = "auxheatwarnings"; + public static final String MB_KEY_PRECOND_NOW_ERROR = "precondNowError"; + public static final String MB_KEY_ECOSCORE_ACCEL = "ecoscoreaccel"; + public static final String MB_KEY_ECOSCORE_CONSTANT = "ecoscoreconst"; + public static final String MB_KEY_ECOSCORE_COASTING = "ecoscorefreewhl"; + public static final String MB_KEY_ECOSCORE_BONUS = "ecoscorebonusrange"; public static final String GROUP_VEHICLE = "vehicle"; public static final String GROUP_DOORS = "doors"; @@ -159,6 +168,7 @@ public class Constants { public static final String GROUP_RANGE = "range"; public static final String GROUP_CHARGE = "charge"; public static final String GROUP_TRIP = "trip"; + public static final String GROUP_ECO = "eco"; public static final String GROUP_POSITION = "position"; public static final String GROUP_TIRES = "tires"; public static final String GROUP_COMMAND = "command"; @@ -247,6 +257,14 @@ public class Constants { public static final String OH_CHANNEL_GPS = "gps"; public static final String OH_CHANNEL_CONS_CONV_UNIT = "cons-conv-unit"; public static final String OH_CHANNEL_CONS_EV_UNIT = "cons-ev-unit"; + public static final String OH_CHANNEL_STATUS = "status"; + public static final String OH_CHANNEL_ERROR = "error"; + public static final String OH_CHANNEL_AC_STATUS = "ac-status"; + public static final String OH_CHANNEL_AUX_STATUS = "aux-status"; + public static final String OH_CHANNEL_ACCEL = "accel"; + public static final String OH_CHANNEL_COASTING = "coasting"; + public static final String OH_CHANNEL_CONSTANT = "constant"; + public static final String OH_CHANNEL_BONUS_RANGE = "bonus"; public static final String CALLBACK_ENDPOINT = "/mb-auth"; // https://developer.mercedes-benz.com/content-page/api_migration_guide diff --git a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/MercedesMeMetadataAdjuster.java b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/MercedesMeMetadataAdjuster.java index 902d605b4a742..c256015918e97 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/MercedesMeMetadataAdjuster.java +++ b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/MercedesMeMetadataAdjuster.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.mercedesme.internal; +import static org.openhab.binding.mercedesme.internal.Constants.*; + import javax.measure.Unit; import javax.measure.quantity.Length; @@ -56,16 +58,17 @@ public void added(ItemChannelLink element) { if (Constants.BINDING_ID.equals(cuid.getBindingId())) { MetadataKey key = new MetadataKey("unit", itemName); switch (cuid.getId()) { - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "mileage": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "range-electric": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "radius-electric": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "range-fuel": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "radius-fuel": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "range-hybrid": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "radius-hybrid": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "home-distance": - case Constants.GROUP_TRIP + ChannelUID.CHANNEL_GROUP_SEPARATOR + "distance": - case Constants.GROUP_TRIP + ChannelUID.CHANNEL_GROUP_SEPARATOR + "distance-reset": + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_MILEAGE: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_RANGE_ELECTRIC: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_RADIUS_ELECTRIC: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_RANGE_FUEL: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_RADIUS_FUEL: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_RANGE_HYBRID: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_RADIUS_HYBRID: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_HOME_DISTANCE: + case GROUP_TRIP + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_DISTANCE: + case GROUP_TRIP + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_DISTANCE_RESET: + case GROUP_ECO + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_BONUS_RANGE: if (metadataRegistry.get(key) == null) { Unit lengthUnit = unitProvider.getUnit(Length.class); if (ImperialUnits.FOOT.equals(lengthUnit)) { @@ -75,17 +78,20 @@ public void added(ItemChannelLink element) { } } break; - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "soc": - case Constants.GROUP_CHARGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "max-soc": - case Constants.GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + "fuel-level": + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_SOC: + case GROUP_CHARGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_MAX_SOC: + case GROUP_RANGE + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_FUEL_LEVEL: + case GROUP_ECO + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_ACCEL: + case GROUP_ECO + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_COASTING: + case GROUP_ECO + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_CONSTANT: if (metadataRegistry.get(key) == null) { metadataRegistry.add(new Metadata(key, Units.PERCENT.getSymbol(), null)); } break; - case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-front-left": - case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-front-right": - case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-rear-left": - case Constants.GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + "pressure-rear-right": + case GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_PRESSURE_FRONT_LEFT: + case GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_PRESSURE_FRONT_RIGHT: + case GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_PRESSURE_REAR_LEFT: + case GROUP_TIRES + ChannelUID.CHANNEL_GROUP_SEPARATOR + OH_CHANNEL_PRESSURE_REAR_RIGHT: if (metadataRegistry.get(key) == null) { Unit lengthUnit = unitProvider.getUnit(Length.class); if (ImperialUnits.FOOT.equals(lengthUnit)) { diff --git a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandler.java b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandler.java index be48a9d12d72e..4716708ea37bd 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandler.java +++ b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandler.java @@ -178,7 +178,9 @@ private ClientMessage createCM(CommandRequest cr) { @Override public void dispose() { - accountHandler.get().unregisterVin(config.get().vin); + accountHandler.ifPresent(ah -> { + ah.unregisterVin(config.get().vin); + }); super.dispose(); } diff --git a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/utils/Mapper.java b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/utils/Mapper.java index c12f5b9fa8c86..4a8ff1127431f 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/utils/Mapper.java +++ b/bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/utils/Mapper.java @@ -93,6 +93,7 @@ public static ChannelStateMap getChannelStateMap(String key, VehicleAttributeSta case MB_KEY_RANGELIQUID: case MB_KEY_DISTANCE_START: case MB_KEY_DISTANCE_RESET: + case MB_KEY_ECOSCORE_BONUS: Unit lengthUnit = defaultLengthUnit; if (value.hasDistanceUnit()) { observer = new UOMObserver(value.getDistanceUnit().toString()); @@ -196,6 +197,9 @@ public static ChannelStateMap getChannelStateMap(String key, VehicleAttributeSta // Percentages case MB_KEY_SOC: case MB_KEY_TANKLEVELPERCENT: + case MB_KEY_ECOSCORE_ACCEL: + case MB_KEY_ECOSCORE_CONSTANT: + case MB_KEY_ECOSCORE_COASTING: double level = Utils.getDouble(value); state = QuantityType.valueOf(level, Units.PERCENT); return new ChannelStateMap(ch[0], ch[1], state); @@ -239,23 +243,20 @@ public static ChannelStateMap getChannelStateMap(String key, VehicleAttributeSta case MB_KEY_CHARGE_COUPLER_DC_STATUS: case MB_KEY_CHARGE_COUPLER_DC_LOCK_STATUS: case MB_KEY_TIRE_SENSOR_AVAILABLE: - int stateNumberInteger = Utils.getInt(value); - if (stateNumberInteger < 0) { - state = UnDefType.UNDEF; - } else { - state = new DecimalType(stateNumberInteger); - } - return new ChannelStateMap(ch[0], ch[1], state); - + case MB_KEY_CHARGE_STATUS: + case MB_KEY_CHARGE_ERROR: case MB_KEY_TIRE_MARKER_FRONT_RIGHT: case MB_KEY_TIRE_MARKER_FRONT_LEFT: case MB_KEY_TIRE_MARKER_REAR_RIGHT: case MB_KEY_TIRE_MARKER_REAR_LEFT: - double stateNumberDouble = Utils.getDouble(value); - if (stateNumberDouble < 0) { + case MB_KEY_POSITION_ERROR: + case MB_KEY_AUXILIARY_WARNINGS: + case MB_KEY_PRECOND_NOW_ERROR: + int stateNumberInteger = Utils.getInt(value); + if (stateNumberInteger < 0) { state = UnDefType.UNDEF; } else { - state = new DecimalType(stateNumberDouble); + state = new DecimalType(stateNumberInteger); } return new ChannelStateMap(ch[0], ch[1], state); @@ -384,6 +385,8 @@ private static void init() { CHANNELS.put(MB_KEY_PRECOND_SEAT_FRONT_LEFT, new String[] { OH_CHANNEL_FRONT_LEFT, GROUP_HVAC }); CHANNELS.put(MB_KEY_PRECOND_SEAT_REAR_RIGHT, new String[] { OH_CHANNEL_REAR_RIGHT, GROUP_HVAC }); CHANNELS.put(MB_KEY_PRECOND_SEAT_REAR_LEFT, new String[] { OH_CHANNEL_REAR_LEFT, GROUP_HVAC }); + CHANNELS.put(MB_KEY_AUXILIARY_WARNINGS, new String[] { OH_CHANNEL_AUX_STATUS, GROUP_HVAC }); + CHANNELS.put(MB_KEY_PRECOND_NOW_ERROR, new String[] { OH_CHANNEL_AC_STATUS, GROUP_HVAC }); // temperaturePoints - special handling: sets zone & temperature CHANNELS.put(MB_KEY_STARTER_BATTERY_STATE, new String[] { OH_CHANNEL_STARTER_BATTERY, GROUP_SERVICE }); @@ -407,10 +410,13 @@ private static void init() { CHANNELS.put(MB_KEY_CHARGE_COUPLER_DC_STATUS, new String[] { OH_CHANNEL_COUPLER_DC, GROUP_CHARGE }); CHANNELS.put(MB_KEY_CHARGE_COUPLER_DC_LOCK_STATUS, new String[] { OH_CHANNEL_COUPLER_LOCK, GROUP_CHARGE }); CHANNELS.put(MB_KEY_CHARGINGACTIVE, new String[] { OH_CHANNEL_ACTIVE, GROUP_CHARGE }); + CHANNELS.put(MB_KEY_CHARGE_STATUS, new String[] { OH_CHANNEL_STATUS, GROUP_CHARGE }); + CHANNELS.put(MB_KEY_CHARGE_ERROR, new String[] { OH_CHANNEL_ERROR, GROUP_CHARGE }); CHANNELS.put(MB_KEY_CHARGING_POWER, new String[] { OH_CHANNEL_POWER, GROUP_CHARGE }); CHANNELS.put(MB_KEY_ENDOFCHARGETIME, new String[] { OH_CHANNEL_END_TIME, GROUP_CHARGE }); CHANNELS.put(MB_KEY_POSITION_HEADING, new String[] { OH_CHANNEL_HEADING, GROUP_POSITION }); + CHANNELS.put(MB_KEY_POSITION_ERROR, new String[] { OH_CHANNEL_STATUS, GROUP_POSITION }); CHANNELS.put(MB_KEY_DISTANCE_START, new String[] { OH_CHANNEL_DISTANCE, GROUP_TRIP }); CHANNELS.put(MB_KEY_DRIVEN_TIME_START, new String[] { OH_CHANNEL_TIME, GROUP_TRIP }); @@ -423,6 +429,11 @@ private static void init() { CHANNELS.put(MB_KEY_ELECTRICCONSUMPTIONRESET, new String[] { OH_CHANNEL_CONS_EV_RESET, GROUP_TRIP }); CHANNELS.put(MB_KEY_LIQUIDCONSUMPTIONRESET, new String[] { OH_CHANNEL_CONS_CONV_RESET, GROUP_TRIP }); + CHANNELS.put(MB_KEY_ECOSCORE_ACCEL, new String[] { OH_CHANNEL_ACCEL, GROUP_ECO }); + CHANNELS.put(MB_KEY_ECOSCORE_CONSTANT, new String[] { OH_CHANNEL_CONSTANT, GROUP_ECO }); + CHANNELS.put(MB_KEY_ECOSCORE_COASTING, new String[] { OH_CHANNEL_COASTING, GROUP_ECO }); + CHANNELS.put(MB_KEY_ECOSCORE_BONUS, new String[] { OH_CHANNEL_BONUS_RANGE, GROUP_ECO }); + CHANNELS.put(MB_KEY_TIREPRESSURE_REAR_RIGHT, new String[] { OH_CHANNEL_PRESSURE_REAR_RIGHT, GROUP_TIRES }); CHANNELS.put(MB_KEY_TIREPRESSURE_FRONT_RIGHT, new String[] { OH_CHANNEL_PRESSURE_FRONT_RIGHT, GROUP_TIRES }); CHANNELS.put(MB_KEY_TIREPRESSURE_REAR_LEFT, new String[] { OH_CHANNEL_PRESSURE_REAR_LEFT, GROUP_TIRES }); diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/i18n/mercedesme.properties b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/i18n/mercedesme.properties index 1260417c915a3..e3638f30acfd8 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/i18n/mercedesme.properties +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/i18n/mercedesme.properties @@ -49,6 +49,8 @@ channel-group-type.mercedesme.charge-values.label = Charging Data channel-group-type.mercedesme.command-values.label = Status of Last Command channel-group-type.mercedesme.door-values.label = Detailed Door Status channel-group-type.mercedesme.door-values.description = Detailed Status of all Doors and Windows +channel-group-type.mercedesme.eco-values.label = ECO Score +channel-group-type.mercedesme.eco-values.description = Economic score for acceleration, coasting and constant driving plus bonus range channel-group-type.mercedesme.hvac-values.label = Vehicle Climate Control channel-group-type.mercedesme.lock-ev-values.label = Lock Status channel-group-type.mercedesme.lock-ev-values.description = Door Lock Status @@ -77,14 +79,39 @@ channel-group-type.mercedesme.window-values.description = Detailed Status Window # channel types -channel-type.mercedesme.active-hvac.label = AC Control +channel-type.mercedesme.ac-status.label = AC Precondition Status +channel-type.mercedesme.ac-status.description = Status of precondition air conditioning +channel-type.mercedesme.ac-status.state.option.0 = No Request +channel-type.mercedesme.ac-status.state.option.1 = Battery or Fuel Low +channel-type.mercedesme.ac-status.state.option.2 = Available after Restart Engine +channel-type.mercedesme.ac-status.state.option.3 = Not Possible, Charging not Finished +channel-type.mercedesme.ac-status.state.option.4 = General Error +channel-type.mercedesme.accel.label = Acceleration Score +channel-type.mercedesme.accel.description = Score for smooth acceleration +channel-type.mercedesme.active-hvac.label = AC Precondition Control +channel-type.mercedesme.active-hvac.description = Switch on/off precondition air conditioning channel-type.mercedesme.active.label = Charge Active channel-type.mercedesme.auto-unlock.label = Coupler Auto Unlock channel-type.mercedesme.auto-unlock.description = Auto unlock coupler after charging channel-type.mercedesme.aux-heat.label = Auxiliary Heating Control +channel-type.mercedesme.aux-heat.description = Switch on/off auxiliary heating +channel-type.mercedesme.aux-status.label = Auxiliary Heating Status +channel-type.mercedesme.aux-status.description = Auxiliary heating status +channel-type.mercedesme.aux-status.state.option.0 = None +channel-type.mercedesme.aux-status.state.option.1 = No Budget +channel-type.mercedesme.aux-status.state.option.2 = Budget Empty +channel-type.mercedesme.aux-status.state.option.4 = System Error +channel-type.mercedesme.aux-status.state.option.8 = Running Error +channel-type.mercedesme.aux-status.state.option.16 = Fuel on Reserve +channel-type.mercedesme.aux-status.state.option.32 = Reserve Reached +channel-type.mercedesme.aux-status.state.option.64 = Low Voltage +channel-type.mercedesme.aux-status.state.option.128 = Low Voltage Operation +channel-type.mercedesme.aux-status.state.option.256 = Communication Error channel-type.mercedesme.avg-speed-reset.label = Rst Average Speed channel-type.mercedesme.avg-speed-reset.description = Average speed since last Reset channel-type.mercedesme.avg-speed.label = Trip Average Speed +channel-type.mercedesme.bonus.label = Bonus Range +channel-type.mercedesme.bonus.description = Additional range vs. very sportive driver channel-type.mercedesme.brake-fluid.label = Brake Fluid channel-type.mercedesme.brake-lining-wear.label = Brake Lining Wear channel-type.mercedesme.charge-flap.label = Charge Flap @@ -96,7 +123,11 @@ channel-type.mercedesme.cmd-last-update.label = Command Updated channel-type.mercedesme.cmd-last-update.state.pattern = %1$tA, %1$td.%1$tm. %1$tH:%1$tM channel-type.mercedesme.cmd-name.label = Command Name channel-type.mercedesme.cmd-state.label = Command State +channel-type.mercedesme.coasting.label = Coasting Score +channel-type.mercedesme.coasting.description = Score for driving without braking channel-type.mercedesme.command-capabilities.label = Command Capabilities +channel-type.mercedesme.constant.label = Constant Score +channel-type.mercedesme.constant.description = Score for driving with constant speed channel-type.mercedesme.consumption-conv-reset.label = Avg Cons Rst Fuel channel-type.mercedesme.consumption-conv-reset.description = Average consumption since last reset fuel channel-type.mercedesme.consumption-conv-unit.label = Avg Cons Unit Fuel @@ -134,9 +165,16 @@ channel-type.mercedesme.driven-time-reset.label = Rst Driving Time channel-type.mercedesme.driven-time-reset.description = Driving time since last Reset channel-type.mercedesme.driven-time.label = Trip String Time channel-type.mercedesme.end-time.label = Charge End Estimation -channel-type.mercedesme.end-time.state.pattern = %1$tH:%1$tM +channel-type.mercedesme.end-time.state.pattern = %1$td.%1$tm. %1$tH:%1$tM channel-type.mercedesme.engine-hood.label = Engine Hood channel-type.mercedesme.engine.label = Engine Warning +channel-type.mercedesme.error-charge.label = Charge Error +channel-type.mercedesme.error-charge.description = Actual charging error if available +channel-type.mercedesme.error-charge.state.option.0 = None +channel-type.mercedesme.error-charge.state.option.1 = Cable +channel-type.mercedesme.error-charge.state.option.2 = Charging Disorder +channel-type.mercedesme.error-charge.state.option.3 = Charging Station +channel-type.mercedesme.error-charge.state.option.4 = Charging Type channel-type.mercedesme.feature-capabilities.label = Feature Capabilities channel-type.mercedesme.flip-window.label = Flip Window channel-type.mercedesme.front-left-hvac.label = AC Seat Front Left @@ -256,6 +294,10 @@ channel-type.mercedesme.rooftop.state.option.0 = Unlocked channel-type.mercedesme.rooftop.state.option.1 = Open and locked channel-type.mercedesme.rooftop.state.option.2 = Closed and locked channel-type.mercedesme.sensor-available.label = Tire Sensor Available +channel-type.mercedesme.sensor-available.state.option.0 = All Sensors Located +channel-type.mercedesme.sensor-available.state.option.1 = 1-3 Sensors are Missing +channel-type.mercedesme.sensor-available.state.option.2 = All Sensors Missing +channel-type.mercedesme.sensor-available.state.option.3 = System Error channel-type.mercedesme.service-days.label = Service in Days channel-type.mercedesme.signal.label = Position Signal channel-type.mercedesme.signal.state.option.0 = Position Lights @@ -267,6 +309,25 @@ channel-type.mercedesme.starter-battery.label = Starter Battery Status channel-type.mercedesme.starter-battery.state.option.0 = Green channel-type.mercedesme.starter-battery.state.option.1 = Yellow channel-type.mercedesme.starter-battery.state.option.2 = Red +channel-type.mercedesme.starter-battery.state.option.3 = Service Disabled +channel-type.mercedesme.starter-battery.state.option.4 = Vehicle Not Available +channel-type.mercedesme.status-charge.label = Charge Status +channel-type.mercedesme.status-charge.description = Actual charging status +channel-type.mercedesme.status-charge.state.option.0 = Charging +channel-type.mercedesme.status-charge.state.option.1 = End of Charge +channel-type.mercedesme.status-charge.state.option.2 = Charge Break +channel-type.mercedesme.status-charge.state.option.3 = Charge Cable Unplugged +channel-type.mercedesme.status-charge.state.option.4 = Charging Failure +channel-type.mercedesme.status-charge.state.option.5 = Slow Charging +channel-type.mercedesme.status-charge.state.option.6 = Fast Charging +channel-type.mercedesme.status-charge.state.option.7 = Discharging +channel-type.mercedesme.status-pos.label = Status Positioning +channel-type.mercedesme.status-pos.state.option.0 = Unknown +channel-type.mercedesme.status-pos.state.option.1 = Service Inactive +channel-type.mercedesme.status-pos.state.option.2 = Tracking Inactive +channel-type.mercedesme.status-pos.state.option.3 = Parked +channel-type.mercedesme.status-pos.state.option.4 = Ignition On +channel-type.mercedesme.status-pos.state.option.5 = Ok channel-type.mercedesme.sunroof-front-blind.label = Sun Roof Front Blind channel-type.mercedesme.sunroof-rear-blind.label = Sun Roof Rear Blind channel-type.mercedesme.sunroof.label = Sun Roof @@ -280,8 +341,13 @@ channel-type.mercedesme.sunroof.state.option.6 = Closing channel-type.mercedesme.sunroof.command.option.0 = Close channel-type.mercedesme.sunroof.command.option.1 = Open channel-type.mercedesme.sunroof.command.option.2 = Lift -channel-type.mercedesme.temperature-hvac.label = AC Temperature +channel-type.mercedesme.temperature-hvac.label = AC Setpoint Temperature channel-type.mercedesme.tires-rdk.label = Tire Pressure Warnings +channel-type.mercedesme.tires-rdk.state.option.0 = No warning +channel-type.mercedesme.tires-rdk.state.option.1 = Soft warning +channel-type.mercedesme.tires-rdk.state.option.2 = Low warning +channel-type.mercedesme.tires-rdk.state.option.3 = Deflation +channel-type.mercedesme.tires-rdk.state.option.4 = Unknown warning channel-type.mercedesme.uncharged.label = Uncharged Battery Energy channel-type.mercedesme.wash-water.label = Wash Water Low channel-type.mercedesme.windows.label = Windows Status/Control @@ -293,7 +359,7 @@ channel-type.mercedesme.windows.command.option.1 = Close channel-type.mercedesme.windows.command.option.2 = Open channel-type.mercedesme.zone-hvac.label = AC Zone -# channel types +# action types actionPoiLabel = Send POI to Vehicle actionPoiDescription = Send POI with name, latitude and longitude @@ -303,6 +369,9 @@ latitudeLabel = Latitude latitudeDescription = Latitude of the location longitudeLabel = Longitude longitudeDescription = Longitude of the location + +# thing status types + mercedesme.account.status.authorization-needed = Manual Authorization needed at {0} mercedesme.account.status.email-missing = EMail missing mercedesme.account.status.region-missing = Region missing diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-channel-types.xml index adbcce18cd6fe..b7d329715bc3b 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-channel-types.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-channel-types.xml @@ -52,6 +52,39 @@ + + Number + + Actual charging status + + + + + + + + + + + + + + + + Number + + Actual charging error if available + + + + + + + + + + + Number:Power diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-group.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-group.xml index 54711f1b99b8b..5817e9e8875ba 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-group.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/charge-group.xml @@ -11,6 +11,8 @@ + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/eco-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/eco-channel-types.xml new file mode 100644 index 0000000000000..11217dae27c67 --- /dev/null +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/eco-channel-types.xml @@ -0,0 +1,30 @@ + + + + Number:Dimensionless + + Score for smooth acceleration + + + + Number:Dimensionless + + Score for driving without braking + + + + Number:Dimensionless + + Score for driving with constant speed + + + + Number:Length + + Additional range vs. very sportive driver + + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/eco-group.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/eco-group.xml new file mode 100644 index 0000000000000..47b94897f8411 --- /dev/null +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/eco-group.xml @@ -0,0 +1,16 @@ + + + + + Economic score for acceleration, coasting and constant driving plus bonus range + + + + + + + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-channel-types.xml index adbb8795916d0..eb1090ff30250 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-channel-types.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-channel-types.xml @@ -10,14 +10,30 @@ Number:Temperature - + veto Switch - + + Switch on/off precondition air conditioning veto + + Number + + Status of precondition air conditioning + + + + + + + + + + + Switch @@ -41,6 +57,27 @@ Switch + Switch on/off auxiliary heating veto + + Number + + Auxiliary heating status + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-group.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-group.xml index 20a5d26ebbe8a..27713059ded58 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-group.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/hvac-group.xml @@ -13,7 +13,9 @@ + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-group.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-group.xml index 5541d1200c455..eaa39538bd909 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-group.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-group.xml @@ -9,6 +9,7 @@ + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-types.xml index e33569638f5fb..0f7ae617bb280 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-types.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/position-channel-types.xml @@ -12,6 +12,21 @@ Location + + Number + + + + + + + + + + + + + Number diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/range-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/range-channel-types.xml index a523f926bf2ff..8861216318cd3 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/range-channel-types.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/range-channel-types.xml @@ -26,7 +26,7 @@ Number:Dimensionless - + Number:Energy diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/service-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/service-channel-types.xml index cc0e54ce10edd..2229bea2e3aad 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/service-channel-types.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/service-channel-types.xml @@ -7,10 +7,13 @@ Number + + + @@ -43,6 +46,14 @@ Number + + + + + + + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-bev.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-bev.xml index 357d492e68d5b..92f087b12abe0 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-bev.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-bev.xml @@ -22,11 +22,16 @@ + + + 1 + + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-combustion.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-combustion.xml index 977dd7af64264..dbfe23533d5ef 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-combustion.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-combustion.xml @@ -21,13 +21,14 @@ + - 1 + 2 diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-hybrid.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-hybrid.xml index e55fa8d1c07de..907f8009f4712 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-hybrid.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/thing-hybrid.xml @@ -22,13 +22,14 @@ + - 1 + 2 diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/tires-channel-types.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/tires-channel-types.xml index ace31ffb7860a..a5da9c209bf83 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/tires-channel-types.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/thing/tires-channel-types.xml @@ -26,12 +26,21 @@ Number - + + + + + + + + + Number + @@ -45,6 +54,7 @@ Number + @@ -58,6 +68,7 @@ Number + @@ -71,6 +82,7 @@ Number + diff --git a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/update/instructions.xml b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/update/instructions.xml index 744a25359b913..f95be9a969dd6 100644 --- a/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/update/instructions.xml +++ b/bundles/org.openhab.binding.mercedesme/src/main/resources/OH-INF/update/instructions.xml @@ -3,12 +3,135 @@ xmlns:update="https://openhab.org/schemas/update-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd"> + + + + mercedesme:aux-heat + + Switch on/off auxiliary heating + + + mercedesme:aux-status + + Auxiliary heating status + + + mercedesme:ac-status + + Switch on/off precondition air conditioning + + + mercedesme:temperature-hvac + + + + mercedesme:ac-status + + Status of precondition air conditioning + + + mercedesme:status-charge + + Actual charging status + + + mercedesme:error-charge + + Actual charging error if available + + + mercedesme:accel + + Score for smooth acceleration + + + mercedesme:coasting + + Score for driving without braking + + + mercedesme:constant + + Score for driving with constant speed + + + mercedesme:bonus + + Additional range vs. very sportive driver + + + mercedesme:status-pos + + + + + mercedesme:consumption-conv-reset + + + mercedesme:aux-heat + + Switch on/off auxiliary heating + + + mercedesme:aux-status + + Auxiliary heating status + + + mercedesme:ac-status + + Switch on/off precondition air conditioning + + + mercedesme:temperature-hvac + + + + mercedesme:ac-status + + Status of precondition air conditioning + + + mercedesme:status-charge + + Actual charging status + + + mercedesme:error-charge + + Actual charging error if available + + + mercedesme:accel + + Score for smooth acceleration + + + mercedesme:coasting + + Score for driving without braking + + + mercedesme:constant + + Score for driving with constant speed + + + mercedesme:bonus + + Additional range vs. very sportive driver + + + mercedesme:status-pos + + + @@ -41,6 +164,56 @@ mercedesme:consumption-conv-unit + + + mercedesme:aux-heat + + Switch on/off auxiliary heating + + + mercedesme:aux-status + + Auxiliary heating status + + + mercedesme:ac-status + + Switch on/off precondition air conditioning + + + mercedesme:temperature-hvac + + + + mercedesme:ac-status + + Status of precondition air conditioning + + + mercedesme:accel + + Score for smooth acceleration + + + mercedesme:coasting + + Score for driving without braking + + + mercedesme:constant + + Score for driving with constant speed + + + mercedesme:bonus + + Additional range vs. very sportive driver + + + mercedesme:status-pos + + + diff --git a/bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandlerTest.java b/bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandlerTest.java index ce2b93766d213..92e5f009c0de5 100644 --- a/bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandlerTest.java +++ b/bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandlerTest.java @@ -16,6 +16,7 @@ import static org.mockito.Mockito.*; import static org.openhab.binding.mercedesme.internal.Constants.*; +import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -37,6 +38,7 @@ import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService; import org.openhab.core.thing.link.ItemChannelLinkRegistry; import org.openhab.core.types.RefreshType; +import org.openhab.core.types.UnDefType; import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate; import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatus; @@ -50,6 +52,34 @@ */ @NonNullByDefault class VehicleHandlerTest { + public static final int GROUP_COUNT = 12; + + public static final int ECOSCORE_UPDATE_COUNT = 4; + public static final int HVAC_UPDATE_COUNT = 9; + public static final int POSITIONING_UPDATE_COUNT = 3; + + private static final int EVENT_STORAGE_COUNT = HVAC_UPDATE_COUNT + POSITIONING_UPDATE_COUNT + ECOSCORE_UPDATE_COUNT + + 76; + + public static Map createBEV() { + Thing thingMock = mock(Thing.class); + when(thingMock.getThingTypeUID()).thenReturn(Constants.THING_TYPE_BEV); + when(thingMock.getUID()).thenReturn(new ThingUID("test", Constants.BEV)); + when(thingMock.getProperties()).thenReturn(Map.of(MB_KEY_COMMAND_CHARGE_PROGRAM_CONFIGURE, "true")); + AccountHandlerMock ahm = new AccountHandlerMock(); + VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(), + mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class)); + vh.accountHandler = Optional.of(ahm); + VehicleConfiguration vehicleConfig = new VehicleConfiguration(); + vh.config = Optional.of(vehicleConfig); + ThingCallbackListener updateListener = new ThingCallbackListener(); + vh.setCallback(updateListener); + Map instances = new HashMap<>(); + instances.put(ThingCallbackListener.class.getCanonicalName(), updateListener); + instances.put(VehicleHandler.class.getCanonicalName(), vh); + instances.put(AccountHandlerMock.class.getCanonicalName(), ahm); + return instances; + } @Test public void testBEVFullUpdateNoCapacities() { @@ -68,7 +98,7 @@ public void testBEVFullUpdateNoCapacities() { VEPUpdate update = ProtoConverter.json2Proto(json, true); vh.distributeContent(update); - assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count"); + assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count"); assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count"); assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count"); @@ -76,10 +106,10 @@ public void testBEVFullUpdateNoCapacities() { assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count"); assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count"); assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count"); - assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count"); + assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count"); - assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); - assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); + assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); + assertEquals(12, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); } @Test @@ -104,7 +134,7 @@ public void testBEVImperialUnits() { VEPUpdate update = ProtoConverter.json2Proto(json, true); vh.distributeContent(update); - assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count"); + assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count"); assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count"); assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count"); @@ -112,10 +142,14 @@ public void testBEVImperialUnits() { assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count"); assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count"); assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count"); - assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count"); + assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count"); - assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); - assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); + assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); + assertEquals(12, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); + // Cable unplugged = 3 + assertEquals("3", updateListener.getResponse("test::bev:charge#status").toFullString(), "Charge Error"); + // No Error = 0 + assertEquals("0", updateListener.getResponse("test::bev:charge#error").toFullString(), "Charge Error"); assertTrue(updateListener.getResponse("test::bev:range#mileage").toFullString().endsWith("mi"), "Mileague Unit"); assertTrue(updateListener.getResponse("test::bev:range#range-electric").toFullString().endsWith("mi"), @@ -158,7 +192,7 @@ public void testBEVCharging() { VEPUpdate update = ProtoConverter.json2Proto(json, true); vh.distributeContent(update); - assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count"); + assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count"); assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count"); assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count"); @@ -166,12 +200,16 @@ public void testBEVCharging() { assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count"); assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count"); assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count"); - assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count"); + assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count"); - assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); - assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); + assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); + assertEquals(12, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); assertEquals("2023-09-06 13:55", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time")) .format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time"); + // Charging = 0 + assertEquals("0", updateListener.getResponse("test::bev:charge#status").toFullString(), "Charge Status"); + // No Error = 0 + assertEquals("0", updateListener.getResponse("test::bev:charge#error").toFullString(), "Charge Error"); } @Test @@ -286,7 +324,7 @@ public void testHybridFullUpdateNoCapacities() { VEPUpdate update = ProtoConverter.json2Proto(json, true); vh.distributeContent(update); - assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count"); + assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count"); assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count"); assertEquals(8, updateListener.getUpdatesForGroup("windows"), "Windows Update Count"); @@ -294,10 +332,10 @@ public void testHybridFullUpdateNoCapacities() { assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Trip Update Count"); assertEquals(8, updateListener.getUpdatesForGroup("service"), "Trip Update Count"); assertEquals(14, updateListener.getUpdatesForGroup("range"), "Update Upadte Count"); - assertEquals(2, updateListener.getUpdatesForGroup("position"), "Update Upadte Count"); + assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Update Upadte Count"); assertEquals(6, updateListener.getUpdatesForGroup("lock"), "Lock Update Count"); - assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); - assertEquals(7, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); + assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); + assertEquals(9, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); } @Test @@ -348,7 +386,7 @@ public void testEventStorage() { VEPUpdate update = ProtoConverter.json2Proto(json, true); vh.distributeContent(update); - assertEquals(11, updateListener.updatesPerGroupMap.size(), "Group Update Count"); + assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count"); assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count"); // 1 update more due to proto channel connected // assertEquals(6, updateListener.getUpdatesForGroup("vehicle"), "Vehcile Update Count"); @@ -357,18 +395,18 @@ public void testEventStorage() { assertEquals(10, updateListener.getUpdatesForGroup("tires"), "Tire Update Count"); assertEquals(6, updateListener.getUpdatesForGroup("service"), "Service Update Count"); assertEquals(7, updateListener.getUpdatesForGroup("range"), "Range Update Count"); - assertEquals(2, updateListener.getUpdatesForGroup("position"), "Position Update Count"); + assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count"); assertEquals(5, updateListener.getUpdatesForGroup("lock"), "Lock Update Count"); - assertEquals(7, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); - assertEquals(10, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); + assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); + assertEquals(12, updateListener.getUpdatesForGroup("charge"), "Charge Update Count"); /** * VehicleHandler fully updated eventStorage shall contain all data * Let's simulate an item ad causing a RefreshType command * Shall deliver data immediately */ - assertEquals(83, vh.eventStorage.size()); - assertEquals(83, updateListener.updatesReceived.size()); + assertEquals(EVENT_STORAGE_COUNT, vh.eventStorage.size()); + assertEquals(EVENT_STORAGE_COUNT, updateListener.updatesReceived.size()); updateListener = new ThingCallbackListener(); vh.setCallback(updateListener); ChannelUID mileageChannelUID = new ChannelUID(new ThingUID("test", Constants.BEV), Constants.GROUP_RANGE, @@ -517,4 +555,65 @@ public void testCommandDistribution() { fail(); } } + + @Test + public void testPositioning() { + Map instances = createBEV(); + ThingCallbackListener updateListener = (ThingCallbackListener) instances + .get(ThingCallbackListener.class.getCanonicalName()); + VehicleHandler vHandler = (VehicleHandler) instances.get(VehicleHandler.class.getCanonicalName()); + assertNotNull(updateListener); + assertNotNull(vHandler); + + String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json"); + VEPUpdate update = ProtoConverter.json2Proto(json, true); + vHandler.distributeContent(update); + + assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count"); + assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(), + "Positioning GPS"); + assertEquals("44.5 °", updateListener.getResponse("test::bev:position#heading").toFullString(), + "Positioning Heading"); + assertEquals(5, ((DecimalType) updateListener.getResponse("test::bev:position#status")).intValue(), + "Positioning Status"); + } + + @Test + public void testHVAC() { + Map instances = createBEV(); + ThingCallbackListener updateListener = (ThingCallbackListener) instances + .get(ThingCallbackListener.class.getCanonicalName()); + VehicleHandler vHandler = (VehicleHandler) instances.get(VehicleHandler.class.getCanonicalName()); + assertNotNull(updateListener); + assertNotNull(vHandler); + + String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json"); + VEPUpdate update = ProtoConverter.json2Proto(json, true); + vHandler.distributeContent(update); + + assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count"); + assertEquals(0, ((DecimalType) updateListener.getResponse("test::bev:hvac#ac-status")).intValue(), + "AC Statuns"); + assertEquals(UnDefType.UNDEF, updateListener.getResponse("test::bev:hvac#aux-status"), "Aux Heating Status"); + } + + @Test + public void testEcoScore() { + Map instances = createBEV(); + ThingCallbackListener updateListener = (ThingCallbackListener) instances + .get(ThingCallbackListener.class.getCanonicalName()); + VehicleHandler vHandler = (VehicleHandler) instances.get(VehicleHandler.class.getCanonicalName()); + assertNotNull(updateListener); + assertNotNull(vHandler); + + String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json"); + VEPUpdate update = ProtoConverter.json2Proto(json, true); + vHandler.distributeContent(update); + + assertEquals("72 %", updateListener.getResponse("test::bev:eco#accel").toFullString(), "Eco Acceleration"); + assertEquals("81 %", updateListener.getResponse("test::bev:eco#coasting").toFullString(), "Eco Coasting"); + assertEquals("60 %", updateListener.getResponse("test::bev:eco#constant").toFullString(), "Eco Constant"); + assertEquals("10.2 km", updateListener.getResponse("test::bev:eco#bonus").toFullString(), "Eco Bonus"); + assertEquals(ECOSCORE_UPDATE_COUNT, updateListener.getUpdatesForGroup("eco"), "ECO Update Count"); + } } diff --git a/bundles/org.openhab.binding.mercedesme/src/test/resources/info/AttributeGroupDistribution.json b/bundles/org.openhab.binding.mercedesme/src/test/resources/info/AttributeGroupDistribution.json index cee4dbb265d49..850049ab86bc9 100644 --- a/bundles/org.openhab.binding.mercedesme/src/test/resources/info/AttributeGroupDistribution.json +++ b/bundles/org.openhab.binding.mercedesme/src/test/resources/info/AttributeGroupDistribution.json @@ -71,7 +71,8 @@ "chargeCouplerDCStatus", "chargeCouplerDCLockStatus", "chargingactive", - "chargingstatus", + "chargingstatus", + "chargingErrorDetails", "chargingPower", "endofchargetime", "chargePrograms",