]> git.basschouten.com Git - openhab-addons.git/commitdiff
[mercedesme] Refactor code and fix test (#16897)
authorlsiepel <leosiepel@gmail.com>
Mon, 24 Jun 2024 19:19:51 +0000 (21:19 +0200)
committerGitHub <noreply@github.com>
Mon, 24 Jun 2024 19:19:51 +0000 (21:19 +0200)
Also-by: Bernd Weymann <bernd.weymann@gmail.com>
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/AccountHandler.java
bundles/org.openhab.binding.mercedesme/src/main/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandler.java
bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/StatusTests.java
bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/internal/handler/AccountHandlerMock.java
bundles/org.openhab.binding.mercedesme/src/test/java/org/openhab/binding/mercedesme/internal/handler/VehicleHandlerTest.java

index 7b75b079ad6c2df1b4f5cf4b3ff17c7fa4d6c551..13e1d18710d7d69cf9055ccdd57a9a2c35b6e616 100644 (file)
@@ -227,7 +227,7 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
             // all failed - start manual authorization
             String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
                     + Constants.STATUS_AUTH_NEEDED;
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
                     textKey + " [\"" + thing.getProperties().get("callbackUrl") + "\"]");
         }
     }
index fa515b95a46d883072565318691893d397d69385..70e8a9780be01a6e7fe5d532507b0eb8b7ec8874 100644 (file)
@@ -165,6 +165,15 @@ public class VehicleHandler extends BaseThingHandler {
         }
     }
 
+    private boolean supports(final String propertyName) {
+        String supported = thing.getProperties().get(propertyName);
+        return Boolean.TRUE.toString().equals(supported);
+    }
+
+    private ClientMessage createCM(CommandRequest cr) {
+        return ClientMessage.newBuilder().setCommandRequest(cr).build();
+    }
+
     @Override
     public void dispose() {
         accountHandler.get().unregisterVin(config.get().vin);
@@ -177,6 +186,7 @@ public class VehicleHandler extends BaseThingHandler {
          * Commands shall be not that frequent so trace level for identifying problems should be feasible
          */
         logger.trace("Received command {} {} for {}", command.getClass(), command, channelUID);
+
         if (command instanceof RefreshType) {
             if (MB_KEY_FEATURE_CAPABILITIES.equals(channelUID.getIdWithoutGroup())
                     || MB_KEY_COMMAND_CAPABILITIES.equals(channelUID.getIdWithoutGroup())) {
@@ -192,328 +202,312 @@ public class VehicleHandler extends BaseThingHandler {
             }
             // ensure unit update
             unitStorage.remove(channelUID.getIdWithoutGroup());
-        } else if (Constants.GROUP_VEHICLE.equals(channelUID.getGroupId())) {
-            /**
-             * Commands for Vehicle
-             */
-            if (OH_CHANNEL_IGNITION.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_ENGINE_START);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Engine Start/Stop not supported");
-                } else {
-                    int commandValue = ((DecimalType) command).intValue();
-                    if (commandValue == 4) {
-                        String pin = accountHandler.get().config.get().pin;
-                        if (Constants.NOT_SET.equals(pin)) {
-                            logger.trace("Security PIN missing in Account bridge");
-                        } else {
-                            EngineStart eStart = EngineStart.newBuilder().setPin(pin).build();
-                            CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                    .setRequestId(UUID.randomUUID().toString()).setEngineStart(eStart).build();
-                            ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                            accountHandler.get().sendCommand(cm);
+            return;
+        }
+        var crBuilder = CommandRequest.newBuilder().setVin(config.get().vin).setRequestId(UUID.randomUUID().toString());
+        String group = channelUID.getGroupId();
+        String channel = channelUID.getIdWithoutGroup();
+        String pin = accountHandler.get().config.get().pin;
+        if (group == null) {
+            logger.trace("No command {} found for {}", command, channel);
+            return;
+        }
+        switch (group) {
+            case GROUP_VEHICLE:
+                switch (channel) {
+                    case OH_CHANNEL_IGNITION:
+                        if (!supports(MB_KEY_COMMAND_ENGINE_START)) {
+                            logger.trace("Engine Start/Stop not supported");
+                            return;
                         }
-                    } else if (commandValue == 0) {
-                        EngineStop eStop = EngineStop.newBuilder().build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setEngineStop(eStop).build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
-                    }
-                }
-            } else if (OH_CHANNEL_WINDOWS.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_WINDOWS_OPEN);
-                String pin = accountHandler.get().config.get().pin;
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Windows control not supported");
-                } else {
-                    CommandRequest cr;
-                    ClientMessage cm;
-                    switch (((DecimalType) command).intValue()) {
-                        case 0:
+                        int commandValue = ((DecimalType) command).intValue();
+                        if (commandValue == 4) {
                             if (Constants.NOT_SET.equals(pin)) {
                                 logger.trace("Security PIN missing in Account bridge");
-                            } else {
-                                WindowsVentilate wv = WindowsVentilate.newBuilder().setPin(pin).build();
-                                cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                        .setRequestId(UUID.randomUUID().toString()).setWindowsVentilate(wv).build();
-                                cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                                accountHandler.get().sendCommand(cm);
+                                return;
                             }
-                            break;
-                        case 1:
-                            WindowsClose wc = WindowsClose.newBuilder().build();
-                            cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                    .setRequestId(UUID.randomUUID().toString()).setWindowsClose(wc).build();
-                            cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                            accountHandler.get().sendCommand(cm);
-                            break;
-                        case 2:
-                            if (Constants.NOT_SET.equals(pin)) {
-                                logger.trace("Security PIN missing in Account bridge");
-                            } else {
+                            EngineStart eStart = EngineStart.newBuilder().setPin(pin).build();
+                            CommandRequest cr = crBuilder.setEngineStart(eStart).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        } else if (commandValue == 0) {
+                            EngineStop eStop = EngineStop.newBuilder().build();
+                            CommandRequest cr = crBuilder.setEngineStop(eStop).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        }
+                        break;
+                    case OH_CHANNEL_WINDOWS:
+                        if (!supports(MB_KEY_COMMAND_WINDOWS_OPEN)) {
+                            logger.trace("Windows control not supported");
+                            return;
+                        }
+                        CommandRequest cr;
+                        switch (((DecimalType) command).intValue()) {
+                            case 0:
+                                if (Constants.NOT_SET.equals(pin)) {
+                                    logger.trace("Security PIN missing in Account bridge");
+                                    return;
+                                }
+                                WindowsVentilate wv = WindowsVentilate.newBuilder().setPin(pin).build();
+                                cr = crBuilder.setWindowsVentilate(wv).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            case 1:
+                                WindowsClose wc = WindowsClose.newBuilder().build();
+                                cr = crBuilder.setWindowsClose(wc).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            case 2:
+                                if (Constants.NOT_SET.equals(pin)) {
+                                    logger.trace("Security PIN missing in Account bridge");
+                                    return;
+                                }
                                 WindowsOpen wo = WindowsOpen.newBuilder().setPin(pin).build();
-                                cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                        .setRequestId(UUID.randomUUID().toString()).setWindowsOpen(wo).build();
-                                cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                                accountHandler.get().sendCommand(cm);
-                            }
-                            break;
-                        default:
-                            logger.trace("No Windows movement known for {}", command);
-                            break;
-                    }
-                }
-            } else if (OH_CHANNEL_LOCK.equals(channelUID.getIdWithoutGroup())) {
-                String pin = accountHandler.get().config.get().pin;
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_DOORS_LOCK);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Door Lock not supported");
-                } else {
-                    switch (((DecimalType) command).intValue()) {
-                        case 0:
-                            DoorsLock dl = DoorsLock.newBuilder().build();
-                            CommandRequest lockCr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                    .setRequestId(UUID.randomUUID().toString()).setDoorsLock(dl).build();
-                            ClientMessage lockCm = ClientMessage.newBuilder().setCommandRequest(lockCr).build();
-                            accountHandler.get().sendCommand(lockCm);
-                            break;
-                        case 1:
-                            if (Constants.NOT_SET.equals(pin)) {
-                                logger.trace("Security PIN missing in Account bridge");
-                            } else {
+                                cr = crBuilder.setWindowsOpen(wo).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            default:
+                                logger.trace("No Windows movement known for {}", command);
+                                break;
+                        }
+                        break;
+                    case OH_CHANNEL_LOCK:
+                        if (!supports(MB_KEY_COMMAND_DOORS_LOCK)) {
+                            logger.trace("Door Lock not supported");
+                            return;
+                        }
+                        switch (((DecimalType) command).intValue()) {
+                            case 0:
+                                DoorsLock dl = DoorsLock.newBuilder().build();
+                                cr = crBuilder.setDoorsLock(dl).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            case 1:
+                                if (Constants.NOT_SET.equals(pin)) {
+                                    logger.trace("Security PIN missing in Account bridge");
+                                    return;
+                                }
                                 DoorsUnlock du = DoorsUnlock.newBuilder().setPin(pin).build();
-                                CommandRequest unlockCr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                        .setRequestId(UUID.randomUUID().toString()).setDoorsUnlock(du).build();
-                                ClientMessage unlockCm = ClientMessage.newBuilder().setCommandRequest(unlockCr).build();
-                                accountHandler.get().sendCommand(unlockCm);
-                            }
-                            break;
-                        default:
-                            logger.trace("No lock command mapped to {}", command);
-                            break;
-                    }
-                }
-            }
-        } else if (Constants.GROUP_HVAC.equals(channelUID.getGroupId())) {
-            /**
-             * Commands for HVAC
-             */
-            if (OH_CHANNEL_TEMPERATURE.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_ZEV_PRECONDITION_CONFIGURE);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Air Conditioning Temperature Setting not supported");
-                } else {
-                    QuantityType<?> targetTemp = (QuantityType<?>) command;
-                    QuantityType<?> targetTempCelsius = targetTemp.toInvertibleUnit(SIUnits.CELSIUS);
-                    if (targetTempCelsius != null) {
-                        TemperatureConfigure tc = TemperatureConfigure.newBuilder()
-                                .addTemperaturePoints(TemperaturePoint.newBuilder().setZoneValue(activeTemperaturePoint)
-                                        .setTemperatureInCelsius(targetTempCelsius.intValue()).build())
-                                .build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setTemperatureConfigure(tc).build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
-                    }
-                }
-            } else if (OH_CHANNEL_ACTIVE.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_ZEV_PRECONDITIONING_START);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Air Conditioning not supported");
-                } else {
-                    if (OnOffType.ON.equals(command)) {
-                        ZEVPreconditioningStart precondStart = ZEVPreconditioningStart.newBuilder()
-                                .setType(ZEVPreconditioningType.NOW).build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setZevPreconditioningStart(precondStart)
-                                .build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
-                    } else {
-                        ZEVPreconditioningStop precondStop = ZEVPreconditioningStop.newBuilder()
-                                .setType(ZEVPreconditioningType.NOW).build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setZevPreconditioningStop(precondStop)
-                                .build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
-                    }
+                                cr = crBuilder.setDoorsUnlock(du).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            default:
+                                logger.trace("No lock command mapped to {}", command);
+                                break;
+                        }
+                        break;
+                    default:
+                        logger.trace("No command {} found for {}#{}", command, group, channel);
+                        break;
                 }
-            } else if (OH_CHANNEL_FRONT_LEFT.equals(channelUID.getIdWithoutGroup())) {
-                configureSeats(channelUID, (State) command);
-            } else if (OH_CHANNEL_FRONT_RIGHT.equals(channelUID.getIdWithoutGroup())) {
-                configureSeats(channelUID, (State) command);
-            } else if (OH_CHANNEL_REAR_LEFT.equals(channelUID.getIdWithoutGroup())) {
-                configureSeats(channelUID, (State) command);
-            } else if (OH_CHANNEL_REAR_RIGHT.equals(channelUID.getIdWithoutGroup())) {
-                configureSeats(channelUID, (State) command);
-            } else if (OH_CHANNEL_AUX_HEAT.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_FEATURE_AUX_HEAT);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Auxiliary Heating not supported");
-                } else {
-                    if (OnOffType.ON.equals(command)) {
-                        AuxheatStart auxHeatStart = AuxheatStart.newBuilder().build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setAuxheatStart(auxHeatStart).build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
-                    } else {
-                        AuxheatStop auxHeatStop = AuxheatStop.newBuilder().build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setAuxheatStop(auxHeatStop).build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
-                    }
+                break; // vehicle group
+            case GROUP_HVAC:
+                switch (channel) {
+                    case OH_CHANNEL_TEMPERATURE:
+                        if (!supports(MB_KEY_COMMAND_ZEV_PRECONDITION_CONFIGURE)) {
+                            logger.trace("Air Conditioning Temperature Setting not supported");
+                            return;
+                        }
+                        if (command instanceof QuantityType<?> quantityTypeCommand) {
+                            QuantityType<?> targetTempCelsius = quantityTypeCommand.toInvertibleUnit(SIUnits.CELSIUS);
+                            if (targetTempCelsius == null) {
+                                logger.trace("Cannot handle temperature command {}", quantityTypeCommand);
+                                return;
+                            }
+                            TemperatureConfigure tc = TemperatureConfigure.newBuilder()
+                                    .addTemperaturePoints(
+                                            TemperaturePoint.newBuilder().setZoneValue(activeTemperaturePoint)
+                                                    .setTemperatureInCelsius(targetTempCelsius.intValue()).build())
+                                    .build();
+                            CommandRequest cr = crBuilder.setTemperatureConfigure(tc).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        } else {
+                            logger.trace("Temperature {} shall be QuantityType with degree Celsius or Fahrenheit",
+                                    command);
+                        }
+                        break;
+                    case OH_CHANNEL_ACTIVE:
+                        if (!supports(MB_KEY_COMMAND_ZEV_PRECONDITIONING_START)) {
+                            logger.trace("Air Conditioning not supported");
+                            return;
+                        }
+                        if (OnOffType.ON.equals(command)) {
+                            ZEVPreconditioningStart precondStart = ZEVPreconditioningStart.newBuilder()
+                                    .setType(ZEVPreconditioningType.NOW).build();
+                            CommandRequest cr = crBuilder.setZevPreconditioningStart(precondStart).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        } else {
+                            ZEVPreconditioningStop precondStop = ZEVPreconditioningStop.newBuilder()
+                                    .setType(ZEVPreconditioningType.NOW).build();
+                            CommandRequest cr = crBuilder.setZevPreconditioningStop(precondStop).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        }
+                        break;
+                    case OH_CHANNEL_FRONT_LEFT:
+                    case OH_CHANNEL_FRONT_RIGHT:
+                    case OH_CHANNEL_REAR_LEFT:
+                    case OH_CHANNEL_REAR_RIGHT:
+                        configureSeats(channelUID, (State) command);
+                        break;
+                    case OH_CHANNEL_AUX_HEAT:
+                        if (!supports(MB_KEY_FEATURE_AUX_HEAT)) {
+                            logger.trace("Auxiliary Heating not supported");
+                            return;
+                        }
+                        if (OnOffType.ON.equals(command)) {
+                            AuxheatStart auxHeatStart = AuxheatStart.newBuilder().build();
+                            CommandRequest cr = crBuilder.setAuxheatStart(auxHeatStart).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        } else {
+                            AuxheatStop auxHeatStop = AuxheatStop.newBuilder().build();
+                            CommandRequest cr = crBuilder.setAuxheatStop(auxHeatStop).build();
+                            accountHandler.get().sendCommand(createCM(cr));
+                        }
+                        break;
+                    case OH_CHANNEL_ZONE:
+                        int zone = ((DecimalType) command).intValue();
+                        if (!temperaturePointsStorage.containsKey(zone)) {
+                            logger.trace("No Temperature Zone found for {}", command);
+                            return;
+                        }
+                        ChannelStateMap zoneMap = new ChannelStateMap(OH_CHANNEL_ZONE, GROUP_HVAC,
+                                (DecimalType) command);
+                        updateChannel(zoneMap);
+                        QuantityType<Temperature> selectedTemp = temperaturePointsStorage.get(zone);
+                        if (selectedTemp != null) {
+                            ChannelStateMap tempCSM = new ChannelStateMap(OH_CHANNEL_TEMPERATURE, GROUP_HVAC,
+                                    selectedTemp);
+                            updateChannel(tempCSM);
+                        }
+                    default:
+                        logger.trace("No command {} found for {}#{}", command, group, channel);
+                        break;
                 }
-            } else if (OH_CHANNEL_ZONE.equals(channelUID.getIdWithoutGroup())) {
-                int zone = ((DecimalType) command).intValue();
-                if (temperaturePointsStorage.containsKey(zone)) {
-                    ChannelStateMap zoneMap = new ChannelStateMap(OH_CHANNEL_ZONE, GROUP_HVAC, (DecimalType) command);
-                    updateChannel(zoneMap);
-                    QuantityType<Temperature> selectedTemp = temperaturePointsStorage.get(zone);
-                    if (selectedTemp != null) {
-                        ChannelStateMap tempCSM = new ChannelStateMap(OH_CHANNEL_TEMPERATURE, GROUP_HVAC, selectedTemp);
-                        updateChannel(tempCSM);
-                    }
-                } else {
-                    logger.trace("No Temperature Zone found for {}", command);
+                break; // hvac group
+            case GROUP_POSITION:
+                switch (channel) {
+                    case OH_CHANNEL_SIGNAL:
+                        if (!supports(MB_KEY_COMMAND_SIGPOS_START)) {
+                            logger.trace("Signal Position not supported");
+                            return;
+                        }
+                        SigPosStart sps;
+                        CommandRequest cr;
+                        switch (((DecimalType) command).intValue()) {
+                            case 0: // light
+                                sps = SigPosStart.newBuilder().setSigposType(SigposType.LIGHT_ONLY)
+                                        .setLightType(LightType.DIPPED_HEAD_LIGHT).setSigposDuration(10).build();
+                                cr = crBuilder.setSigposStart(sps).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            case 1: // horn
+                                sps = SigPosStart.newBuilder().setSigposType(SigposType.HORN_ONLY).setHornRepeat(3)
+                                        .setHornType(HornType.HORN_LOW_VOLUME).build();
+                                cr = crBuilder.setSigposStart(sps).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            default:
+                                logger.trace("No Positioning known for {}", command);
+                        }
+                        break;
+                    default:
+                        logger.trace("No command {} found for {}#{}", command, group, channel);
+                        break;
                 }
-            }
-        } else if (Constants.GROUP_POSITION.equals(channelUID.getGroupId())) {
-            /**
-             * Commands for Positioning
-             */
-            if (OH_CHANNEL_SIGNAL.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_SIGPOS_START);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Signal Position not supported");
-                } else {
-                    SigPosStart sps;
-                    CommandRequest cr;
-                    ClientMessage cm;
-                    switch (((DecimalType) command).intValue()) {
-                        case 0: // light
-                            sps = SigPosStart.newBuilder().setSigposType(SigposType.LIGHT_ONLY)
-                                    .setLightType(LightType.DIPPED_HEAD_LIGHT).setSigposDuration(10).build();
-                            cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                    .setRequestId(UUID.randomUUID().toString()).setSigposStart(sps).build();
-                            cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                            accountHandler.get().sendCommand(cm);
-                            break;
-                        case 1: // horn
-                            sps = SigPosStart.newBuilder().setSigposType(SigposType.HORN_ONLY).setHornRepeat(3)
-                                    .setHornType(HornType.HORN_LOW_VOLUME).build();
-                            cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                    .setRequestId(UUID.randomUUID().toString()).setSigposStart(sps).build();
-                            cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                            accountHandler.get().sendCommand(cm);
-                            break;
-                        default:
-                            logger.trace("No Positioning known for {}", command);
-                    }
+                break; // position group
+            case GROUP_CHARGE:
+                if (!supports(MB_KEY_COMMAND_CHARGE_PROGRAM_CONFIGURE)) {
+                    logger.trace("Charge Program Configure not supported");
+                    return;
                 }
-            }
-        } else if (Constants.GROUP_CHARGE.equals(channelUID.getGroupId())) {
-            /**
-             * Commands for Charging
-             */
-            synchronized (chargeGroupValueStorage) {
                 int maxSocToSelect = 80;
                 boolean autoUnlockToSelect = false;
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_CHARGE_PROGRAM_CONFIGURE);
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Charge Program Configure not supported");
-                } else {
-                    boolean sendCommand = false;
-                    if (OH_CHANNEL_PROGRAM.equals(channelUID.getIdWithoutGroup())) {
-                        selectedChargeProgram = ((DecimalType) command).intValue();
-                        if (chargeGroupValueStorage.has(Integer.toString(selectedChargeProgram))) {
-                            maxSocToSelect = chargeGroupValueStorage
-                                    .getJSONObject(Integer.toString(selectedChargeProgram))
-                                    .getInt(Constants.MAX_SOC_KEY);
-                            autoUnlockToSelect = chargeGroupValueStorage
-                                    .getJSONObject(Integer.toString(selectedChargeProgram))
-                                    .getBoolean(Constants.AUTO_UNLOCK_KEY);
-                            updateChannel(new ChannelStateMap(OH_CHANNEL_MAX_SOC, GROUP_CHARGE,
-                                    QuantityType.valueOf(maxSocToSelect, Units.PERCENT)));
-                            updateChannel(new ChannelStateMap(OH_CHANNEL_AUTO_UNLOCK, GROUP_CHARGE,
-                                    OnOffType.from(autoUnlockToSelect)));
+                boolean sendCommand = false;
+
+                synchronized (chargeGroupValueStorage) {
+                    switch (channel) {
+                        case OH_CHANNEL_PROGRAM:
+                            selectedChargeProgram = ((DecimalType) command).intValue();
+                            if (chargeGroupValueStorage.has(Integer.toString(selectedChargeProgram))) {
+                                maxSocToSelect = chargeGroupValueStorage
+                                        .getJSONObject(Integer.toString(selectedChargeProgram))
+                                        .getInt(Constants.MAX_SOC_KEY);
+                                autoUnlockToSelect = chargeGroupValueStorage
+                                        .getJSONObject(Integer.toString(selectedChargeProgram))
+                                        .getBoolean(Constants.AUTO_UNLOCK_KEY);
+                                updateChannel(new ChannelStateMap(OH_CHANNEL_MAX_SOC, GROUP_CHARGE,
+                                        QuantityType.valueOf(maxSocToSelect, Units.PERCENT)));
+                                updateChannel(new ChannelStateMap(OH_CHANNEL_AUTO_UNLOCK, GROUP_CHARGE,
+                                        OnOffType.from(autoUnlockToSelect)));
+                                sendCommand = true;
+                            } else {
+                                logger.trace("No charge program found for {}", selectedChargeProgram);
+                            }
+                            break;
+                        case OH_CHANNEL_AUTO_UNLOCK:
+                            autoUnlockToSelect = OnOffType.ON.equals(command);
                             sendCommand = true;
-                        } else {
-                            logger.trace("No charge program found for {}", selectedChargeProgram);
-                        }
+                            break;
+                        case OH_CHANNEL_MAX_SOC:
+                            maxSocToSelect = ((QuantityType<?>) command).intValue();
+                            sendCommand = true;
+                            break;
+                        default:
+                            logger.trace("No command {} found for {}#{}", command, group, channel);
+                            break;
                     }
-                    if (OH_CHANNEL_AUTO_UNLOCK.equals(channelUID.getIdWithoutGroup())) {
-                        autoUnlockToSelect = ((OnOffType) command).equals(OnOffType.ON);
-                        sendCommand = true;
-                    } else if (OH_CHANNEL_MAX_SOC.equals(channelUID.getIdWithoutGroup())) {
-                        maxSocToSelect = ((QuantityType<?>) command).intValue();
-                        sendCommand = true;
-                    } // else - nothing to be sent
                     if (sendCommand) {
                         Int32Value maxSocValue = Int32Value.newBuilder().setValue(maxSocToSelect).build();
                         BoolValue autoUnlockValue = BoolValue.newBuilder().setValue(autoUnlockToSelect).build();
                         ChargeProgramConfigure cpc = ChargeProgramConfigure.newBuilder()
                                 .setChargeProgramValue(selectedChargeProgram).setMaxSoc(maxSocValue)
                                 .setAutoUnlock(autoUnlockValue).build();
-                        CommandRequest cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                .setRequestId(UUID.randomUUID().toString()).setChargeProgramConfigure(cpc).build();
-                        ClientMessage cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                        accountHandler.get().sendCommand(cm);
+                        CommandRequest cr = crBuilder.setChargeProgramConfigure(cpc).build();
+                        accountHandler.get().sendCommand(createCM(cr));
                     }
                 }
-            }
-        } else if (Constants.GROUP_DOORS.equals(channelUID.getGroupId())) {
-            /**
-             * Commands for Doors
-             */
-            if (OH_CHANNEL_SUNROOF.equals(channelUID.getIdWithoutGroup())) {
-                String supported = thing.getProperties().get(MB_KEY_COMMAND_SUNROOF_OPEN);
-                String pin = accountHandler.get().config.get().pin;
-                if (Boolean.FALSE.toString().equals(supported)) {
-                    logger.trace("Sunroof control not supported");
-                } else {
-                    CommandRequest cr;
-                    ClientMessage cm;
-                    switch (((DecimalType) command).intValue()) {
-                        case 0:
-                            SunroofClose sc = SunroofClose.newBuilder().build();
-                            cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                    .setRequestId(UUID.randomUUID().toString()).setSunroofClose(sc).build();
-                            cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                            accountHandler.get().sendCommand(cm);
-                            break;
-                        case 1:
-                            if (Constants.NOT_SET.equals(pin)) {
-                                logger.trace("Security PIN missing in Account bridge");
-                            } else {
+                break; // charge group
+            case GROUP_DOORS:
+                switch (channel) {
+                    case OH_CHANNEL_SUNROOF:
+                        if (!supports(MB_KEY_COMMAND_SUNROOF_OPEN)) {
+                            logger.trace("Sunroof control not supported");
+                            return;
+                        }
+                        CommandRequest cr;
+                        switch (((DecimalType) command).intValue()) {
+                            case 0:
+                                SunroofClose sc = SunroofClose.newBuilder().build();
+                                cr = crBuilder.setSunroofClose(sc).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            case 1:
+                                if (Constants.NOT_SET.equals(pin)) {
+                                    logger.trace("Security PIN missing in Account bridge");
+                                    return;
+                                }
                                 SunroofOpen so = SunroofOpen.newBuilder().setPin(pin).build();
-                                cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                        .setRequestId(UUID.randomUUID().toString()).setSunroofOpen(so).build();
-                                cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                                accountHandler.get().sendCommand(cm);
-                            }
-                            break;
-                        case 2:
-                            if (Constants.NOT_SET.equals(pin)) {
-                                logger.trace("Security PIN missing in Account bridge");
-                            } else {
+                                cr = crBuilder.setSunroofOpen(so).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            case 2:
+                                if (Constants.NOT_SET.equals(pin)) {
+                                    logger.trace("Security PIN missing in Account bridge");
+                                }
                                 SunroofLift sl = SunroofLift.newBuilder().setPin(pin).build();
-                                cr = CommandRequest.newBuilder().setVin(config.get().vin)
-                                        .setRequestId(UUID.randomUUID().toString()).setSunroofLift(sl).build();
-                                cm = ClientMessage.newBuilder().setCommandRequest(cr).build();
-                                accountHandler.get().sendCommand(cm);
-                            }
-                            break;
-                        default:
-                            logger.trace("No Sunroof movement known for {}", command);
-                    }
+                                cr = crBuilder.setSunroofLift(sl).build();
+                                accountHandler.get().sendCommand(createCM(cr));
+                                break;
+                            default:
+                                logger.trace("No Sunroof movement known for {}", command);
+                        }
+                    default:
+                        logger.trace("No command {} found for {}#{}", command, group, channel);
+                        break;
                 }
-            }
-        } else {
-            logger.trace("No command {} found for {}", command, channelUID.getAsString());
+                break; // doors group
+            default: // no group matching
+                logger.trace("No command {} found for {}#{}", command, group, channel);
+                break;
         }
     }
 
index ba4a8f53c3bd82c64c63d714e12888f604165260..d363c05a284a2627b6d0343ec05861075a3d4387 100644 (file)
@@ -28,6 +28,7 @@ import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
 import org.openhab.core.config.core.Configuration;
 import org.openhab.core.thing.ThingStatus;
 import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.ThingStatusInfo;
 import org.openhab.core.thing.ThingTypeUID;
 import org.openhab.core.thing.internal.BridgeImpl;
 
@@ -60,29 +61,42 @@ class StatusTests {
         ThingCallbackListener tcl = new ThingCallbackListener();
         ahm.setCallback(tcl);
         ahm.initialize();
-        assertEquals(ThingStatus.OFFLINE, tcl.getThingStatus().getStatus(), "EMail offline");
-        assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tcl.getThingStatus().getStatusDetail(), "EMail config");
-        assertEquals("@text/mercedesme.account.status.email-missing", tcl.getThingStatus().getDescription(),
-                "EMail text");
+        ThingStatusInfo tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "EMail offline");
+        assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "EMail config");
+        assertEquals("@text/mercedesme.account.status.email-missing", tsi.getDescription(), "EMail text");
+        tearDown(ahm);
+
         config.put("email", "a@b.c");
         bi.setConfiguration(new Configuration(config));
+        tcl = new ThingCallbackListener();
+        ahm.setCallback(tcl);
         ahm.initialize();
-        assertEquals(ThingStatus.OFFLINE, tcl.getThingStatus().getStatus(), "Region offline");
-        assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tcl.getThingStatus().getStatusDetail(), "Region config");
-        assertEquals("@text/mercedesme.account.status.region-missing", tcl.getThingStatus().getDescription(),
-                "Region text");
+        tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Region offline");
+        assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "Region config");
+        assertEquals("@text/mercedesme.account.status.region-missing", tsi.getDescription(), "Region text");
+        tearDown(ahm);
+
         config.put("region", "row");
         bi.setConfiguration(new Configuration(config));
+        tcl = new ThingCallbackListener();
+        ahm.setCallback(tcl);
         ahm.initialize();
-        assertEquals(ThingStatus.OFFLINE, tcl.getThingStatus().getStatus(), "Auth offline");
-        assertEquals(ThingStatusDetail.NONE, tcl.getThingStatus().getStatusDetail(), "Auth detail");
+        tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Auth offline");
+        assertEquals(ThingStatusDetail.COMMUNICATION_ERROR, tsi.getStatusDetail(), "Auth detail");
+        tearDown(ahm);
+
         config.put("refreshInterval", 0);
         bi.setConfiguration(new Configuration(config));
+        tcl = new ThingCallbackListener();
+        ahm.setCallback(tcl);
         ahm.initialize();
-        assertEquals(ThingStatus.OFFLINE, tcl.getThingStatus().getStatus(), "Refresh offline");
-        assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tcl.getThingStatus().getStatusDetail(), "Refresh config");
-        assertEquals("@text/mercedesme.account.status.refresh-invalid", tcl.getThingStatus().getDescription(),
-                "Refresh text");
+        tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Refresh offline");
+        assertEquals(ThingStatusDetail.CONFIGURATION_ERROR, tsi.getStatusDetail(), "Refresh config");
+        assertEquals("@text/mercedesme.account.status.refresh-invalid", tsi.getDescription(), "Refresh text");
         tearDown(ahm);
     }
 
@@ -100,18 +114,22 @@ class StatusTests {
         ThingCallbackListener tcl = new ThingCallbackListener();
         ahm.setCallback(tcl);
         ahm.initialize();
-        assertEquals(ThingStatus.OFFLINE, tcl.getThingStatus().getStatus(), "Auth Offline");
-        assertEquals(ThingStatusDetail.COMMUNICATION_ERROR, tcl.getThingStatus().getStatusDetail(), "Auth details");
-        String statusDescription = tcl.getThingStatus().getDescription();
+        ThingStatusInfo tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.OFFLINE, tsi.getStatus(), "Auth Offline");
+        assertEquals(ThingStatusDetail.COMMUNICATION_ERROR, tsi.getStatusDetail(), "Auth details");
+        String statusDescription = tsi.getDescription();
         assertNotNull(statusDescription);
         assertTrue(statusDescription.contains("@text/mercedesme.account.status.authorization-needed"), "Auth text");
+        tearDown(ahm);
+
         AccessTokenResponse token = new AccessTokenResponse();
         token.setExpiresIn(3000);
         token.setAccessToken(Constants.JUNIT_TOKEN);
         token.setRefreshToken(Constants.JUNIT_REFRESH_TOKEN);
         ahm.onAccessTokenResponse(token);
         ahm.connect();
-        assertEquals(ThingStatus.ONLINE, tcl.getThingStatus().getStatus(), "Auth Online");
+        tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.ONLINE, tsi.getStatus(), "Auth Online");
         tearDown(ahm);
     }
 
@@ -136,10 +154,12 @@ class StatusTests {
         ThingCallbackListener tcl = new ThingCallbackListener();
         ahm.setCallback(tcl);
         ahm.initialize();
-        assertEquals(ThingStatus.UNKNOWN, tcl.getThingStatus().getStatus(), "Socket Unknown "
-                + tcl.getThingStatus().getStatusDetail() + " " + tcl.getThingStatus().getDescription());
+        ThingStatusInfo tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.UNKNOWN, tsi.getStatus(),
+                "Socket Unknown " + tsi.getStatusDetail() + " " + tsi.getDescription());
         ahm.connect();
-        assertEquals(ThingStatus.ONLINE, tcl.getThingStatus().getStatus(), "Spcket Online");
+        tsi = tcl.getThingStatus();
+        assertEquals(ThingStatus.ONLINE, tsi.getStatus(), "Socket Online");
         tearDown(ahm);
     }
 }
index 81e794eeedec7b19a1b1ad743d78917f4878826f..3e2ee2f380060b540f8508cedd35185f5ee3d12d 100644 (file)
@@ -15,6 +15,7 @@ package org.openhab.binding.mercedesme.internal.handler;
 import static org.mockito.Mockito.mock;
 
 import java.util.Locale;
+import java.util.Optional;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
@@ -54,6 +55,7 @@ public class AccountHandlerMock extends AccountHandler {
     public AccountHandlerMock() {
         super(mock(Bridge.class), mock(MercedesMeDiscoveryService.class), mock(HttpClient.class),
                 mock(LocaleProvider.class), mock(StorageService.class), mock(NetworkAddressService.class));
+        config = Optional.of(new AccountConfiguration());
     }
 
     public AccountHandlerMock(Bridge b, @Nullable String storedObject) {
@@ -63,6 +65,7 @@ public class AccountHandlerMock extends AccountHandler {
             Storage<String> storage = storageService.getStorage(Constants.BINDING_ID);
             storage.put("a@b.c", storedObject);
         }
+        config = Optional.of(new AccountConfiguration());
     }
 
     @Override
index ade56576842ce8927883a119362997c0c3084085..5aab32f86e9e60ace19530da297b41aeb7bb5715 100644 (file)
@@ -14,7 +14,9 @@ package org.openhab.binding.mercedesme.internal.handler;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.*;
+import static org.openhab.binding.mercedesme.internal.Constants.*;
 
+import java.util.Map;
 import java.util.Optional;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -382,6 +384,8 @@ class VehicleHandlerTest {
         vh.accountHandler = Optional.of(mock(AccountHandler.class));
         VehicleConfiguration vehicleConfig = new VehicleConfiguration();
         vh.config = Optional.of(vehicleConfig);
+        AccountHandlerMock ahm = new AccountHandlerMock();
+        vh.accountHandler = Optional.of(ahm);
         ThingCallbackListener updateListener = new ThingCallbackListener();
         vh.setCallback(updateListener);
 
@@ -407,6 +411,7 @@ class VehicleHandlerTest {
         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_ZEV_PRECONDITION_CONFIGURE, "true"));
         AccountHandlerMock ahm = new AccountHandlerMock();
         VehicleHandler vh = new VehicleHandler(thingMock, new LocationProviderMock(),
                 mock(MercedesMeCommandOptionProvider.class), mock(MercedesMeStateOptionProvider.class));
@@ -435,6 +440,7 @@ class VehicleHandlerTest {
         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));