/**
  * Checks the output value of a {@link Device} and return 0, if the output value or slat position
  * is min and 1, if the output value or slat position is max, otherwise it returns -1.
  *
  * @param device
  * @return 0 = output value is min, 1 device value is min, otherwise -1
  */
 private short checkIsAllreadyMinMax(Device device) {
   if (device.isShade()) {
     if (device.getSlatPosition() == device.getMaxSlatPosition()) {
       if (device.isBlind()) {
         if (device.getAnglePosition() == device.getMaxSlatAngle()) {
           return 1;
         } else {
           return -1;
         }
       }
       return 1;
     }
     if (device.getSlatPosition() == device.getMinSlatPosition()) {
       if (device.isBlind()) {
         if (device.getAnglePosition() == device.getMinSlatAngle()) {
           return 0;
         } else {
           return -1;
         }
       }
       return 0;
     }
   } else {
     if (device.getOutputValue() == device.getMaxOutputValue()) {
       return 1;
     }
     if (device.getOutputValue() == device.getMinOutputValue() || device.getOutputValue() <= 0) {
       return 0;
     }
   }
   return -1;
 }
 /**
  * Checks the angle value of a {@link Device} and return 0, if the angle value is min and 1, if
  * the angle value is max, otherwise it returns -1.
  *
  * @param device
  * @return 0 = angle value is min, 1 angle value is min, otherwise -1
  */
 private short checkAngleIsMinMax(Device device) {
   if (device.getAnglePosition() == device.getMaxSlatAngle()) {
     return 1;
   }
   if (device.getAnglePosition() == device.getMinSlatAngle()) {
     return 1;
   }
   return -1;
 }
 private void filterCommand(DeviceStateUpdate deviceStateUpdate, Device device) {
   String stateUpdateType = deviceStateUpdate.getType();
   short newAngle = 0;
   if (stateUpdateType.equals(DeviceStateUpdate.UPDATE_SLAT_ANGLE_INCREASE)
       || stateUpdateType.equals(DeviceStateUpdate.UPDATE_SLAT_ANGLE_DECREASE)) {
     newAngle = device.getAnglePosition();
   }
   DeviceStateUpdate nextDeviceStateUpdate = device.getNextDeviceUpdateState();
   while (nextDeviceStateUpdate != null
       && nextDeviceStateUpdate.getType().equals(stateUpdateType)) {
     switch (stateUpdateType) {
       case DeviceStateUpdate.UPDATE_BRIGHTNESS:
         deviceStateUpdate = nextDeviceStateUpdate;
         nextDeviceStateUpdate = device.getNextDeviceUpdateState();
         break;
       case DeviceStateUpdate.UPDATE_SLAT_ANGLE_INCREASE:
         if (deviceStateUpdate.getValue() == 1) {
           newAngle = (short) (newAngle + DeviceConstants.ANGLE_STEP_SLAT);
         }
         break;
       case DeviceStateUpdate.UPDATE_SLAT_ANGLE_DECREASE:
         if (deviceStateUpdate.getValue() == 1) {
           newAngle = (short) (newAngle - DeviceConstants.ANGLE_STEP_SLAT);
         }
         break;
     }
   }
   if (stateUpdateType.equals(DeviceStateUpdate.UPDATE_SLAT_ANGLE_INCREASE)
       || stateUpdateType.equals(DeviceStateUpdate.UPDATE_SLAT_ANGLE_DECREASE)) {
     if (newAngle > device.getMaxSlatAngle()) {
       newAngle = (short) device.getMaxSlatAngle();
     }
     if (newAngle < device.getMinSlatAngle()) {
       newAngle = (short) device.getMinSlatAngle();
     }
     if (!(stateUpdateType.equals(DeviceStateUpdate.UPDATE_SLAT_ANGLE_INCREASE)
             && checkAngleIsMinMax(device) == 1)
         || !(stateUpdateType.equals(DeviceStateUpdate.UPDATE_SLAT_ANGLE_DECREASE)
             && checkAngleIsMinMax(device) == 0)) {
       deviceStateUpdate =
           new DeviceStateUpdateImpl(DeviceStateUpdate.UPDATE_SLAT_ANGLE, newAngle);
     }
   }
   sendComandsToDSS(device, deviceStateUpdate);
   if (nextDeviceStateUpdate != null) {
     if (deviceStateUpdate.getType() == DeviceStateUpdate.UPDATE_SCENE_CONFIG
         || deviceStateUpdate.getType() == DeviceStateUpdate.UPDATE_SCENE_OUTPUT) {
       updateSceneData(device, deviceStateUpdate);
     } else {
       sendComandsToDSS(device, deviceStateUpdate);
     }
   }
 }
 @Override
 public synchronized void sendComandsToDSS(Device device, DeviceStateUpdate deviceStateUpdate) {
   if (connMan.checkConnection()) {
     boolean requestSuccsessful = false;
     boolean commandHaveNoEffect = false;
     if (deviceStateUpdate != null) {
       switch (deviceStateUpdate.getType()) {
         case DeviceStateUpdate.UPDATE_BRIGHTNESS_DECREASE:
         case DeviceStateUpdate.UPDATE_SLAT_DECREASE:
           if (checkIsAllreadyMinMax(device) != 0) {
             requestSuccsessful =
                 digitalSTROMClient.decreaseValue(connMan.getSessionToken(), device.getDSID());
             if (requestSuccsessful) {
               sceneMan.addEcho(device.getDSID().getValue(), SceneEnum.DECREMENT.getSceneNumber());
             }
           } else {
             commandHaveNoEffect = true;
           }
           break;
         case DeviceStateUpdate.UPDATE_BRIGHTNESS_INCREASE:
         case DeviceStateUpdate.UPDATE_SLAT_INCREASE:
           if (checkIsAllreadyMinMax(device) != 1) {
             requestSuccsessful =
                 digitalSTROMClient.increaseValue(connMan.getSessionToken(), device.getDSID());
             if (requestSuccsessful) {
               sceneMan.addEcho(device.getDSID().getValue(), SceneEnum.INCREMENT.getSceneNumber());
             }
           } else {
             commandHaveNoEffect = true;
           }
           break;
         case DeviceStateUpdate.UPDATE_BRIGHTNESS:
           if (device.getOutputValue() != deviceStateUpdate.getValue()) {
             requestSuccsessful =
                 digitalSTROMClient.setDeviceValue(
                     connMan.getSessionToken(),
                     device.getDSID(),
                     null,
                     deviceStateUpdate.getValue());
           } else {
             commandHaveNoEffect = true;
           }
           break;
         case DeviceStateUpdate.UPDATE_OPEN_CLOSE:
         case DeviceStateUpdate.UPDATE_ON_OFF:
           if (deviceStateUpdate.getValue() > 0) {
             if (checkIsAllreadyMinMax(device) != 1) {
               requestSuccsessful =
                   digitalSTROMClient.turnDeviceOn(
                       connMan.getSessionToken(), device.getDSID(), null);
               if (requestSuccsessful) {
                 sceneMan.addEcho(device.getDSID().getValue(), SceneEnum.MAXIMUM.getSceneNumber());
               }
             } else {
               commandHaveNoEffect = true;
             }
           } else {
             if (checkIsAllreadyMinMax(device) != 0) {
               requestSuccsessful =
                   digitalSTROMClient.turnDeviceOff(
                       connMan.getSessionToken(), device.getDSID(), null);
               if (requestSuccsessful) {
                 sceneMan.addEcho(device.getDSID().getValue(), SceneEnum.MINIMUM.getSceneNumber());
               }
               if (sensorJobExecutor != null) {
                 sensorJobExecutor.removeSensorJobs(device);
               }
             } else {
               commandHaveNoEffect = true;
             }
           }
           break;
         case DeviceStateUpdate.UPDATE_SLATPOSITION:
           if (device.getSlatPosition() != deviceStateUpdate.getValue()) {
             requestSuccsessful =
                 digitalSTROMClient.setDeviceOutputValue(
                     connMan.getSessionToken(),
                     device.getDSID(),
                     null,
                     DeviceConstants.DEVICE_SENSOR_SLAT_POSITION_OUTPUT,
                     deviceStateUpdate.getValue());
           } else {
             commandHaveNoEffect = true;
           }
           break;
         case DeviceStateUpdate.UPDATE_SLAT_STOP:
           this.sendStopComandsToDSS(device);
           break;
         case DeviceStateUpdate.UPDATE_SLAT_MOVE:
           if (deviceStateUpdate.getValue() > 0) {
             requestSuccsessful =
                 digitalSTROMClient.turnDeviceOn(
                     connMan.getSessionToken(), device.getDSID(), null);
             if (requestSuccsessful) {
               sceneMan.addEcho(device.getDSID().getValue(), SceneEnum.MAXIMUM.getSceneNumber());
             }
           } else {
             requestSuccsessful =
                 digitalSTROMClient.turnDeviceOff(
                     connMan.getSessionToken(), device.getDSID(), null);
             if (requestSuccsessful) {
               sceneMan.addEcho(device.getDSID().getValue(), SceneEnum.MINIMUM.getSceneNumber());
             }
             if (sensorJobExecutor != null) {
               sensorJobExecutor.removeSensorJobs(device);
             }
           }
           break;
         case DeviceStateUpdate.UPDATE_CALL_SCENE:
           if (SceneEnum.getScene((short) deviceStateUpdate.getValue()) != null) {
             requestSuccsessful =
                 digitalSTROMClient.callDeviceScene(
                     connMan.getSessionToken(),
                     device.getDSID(),
                     null,
                     SceneEnum.getScene((short) deviceStateUpdate.getValue()),
                     true);
           }
           break;
         case DeviceStateUpdate.UPDATE_UNDO_SCENE:
           if (SceneEnum.getScene((short) deviceStateUpdate.getValue()) != null) {
             requestSuccsessful =
                 digitalSTROMClient.undoDeviceScene(
                     connMan.getSessionToken(),
                     device.getDSID(),
                     SceneEnum.getScene((short) deviceStateUpdate.getValue()));
           }
           break;
         case DeviceStateUpdate.UPDATE_ACTIVE_POWER:
           if (deviceStateUpdate.getValue() == 0) {
             logger.debug("Device need active power SensorData update");
             updateSensorData(
                 new DeviceConsumptionSensorJob(device, SensorEnum.ACTIVE_POWER),
                 device.getActivePowerRefreshPriority());
             return;
           } else {
             int consumption =
                 this.digitalSTROMClient.getDeviceSensorValue(
                     connMan.getSessionToken(), device.getDSID(), null, SensorEnum.ACTIVE_POWER);
             if (consumption >= 0) {
               device.updateInternalDeviceState(
                   new DeviceStateUpdateImpl(DeviceStateUpdate.UPDATE_ACTIVE_POWER, consumption));
               requestSuccsessful = true;
             }
           }
         case DeviceStateUpdate.UPDATE_OUTPUT_CURRENT:
           if (deviceStateUpdate.getValue() == 0) {
             logger.debug("Device need output current SensorData update");
             updateSensorData(
                 new DeviceConsumptionSensorJob(device, SensorEnum.OUTPUT_CURRENT),
                 device.getOutputCurrentRefreshPriority());
             return;
           } else {
             int consumption =
                 this.digitalSTROMClient.getDeviceSensorValue(
                     connMan.getSessionToken(), device.getDSID(), null, SensorEnum.OUTPUT_CURRENT);
             if (consumption >= 0) {
               device.updateInternalDeviceState(
                   new DeviceStateUpdateImpl(
                       DeviceStateUpdate.UPDATE_OUTPUT_CURRENT, consumption));
               requestSuccsessful = true;
             }
           }
         case DeviceStateUpdate.UPDATE_ELECTRIC_METER:
           if (deviceStateUpdate.getValue() == 0) {
             logger.debug("Device need electric meter SensorData update");
             updateSensorData(
                 new DeviceConsumptionSensorJob(device, SensorEnum.ELECTRIC_METER),
                 device.getElectricMeterRefreshPriority());
             return;
           } else {
             int consumption =
                 this.digitalSTROMClient.getDeviceSensorValue(
                     connMan.getSessionToken(), device.getDSID(), null, SensorEnum.ELECTRIC_METER);
             if (consumption >= 0) {
               device.updateInternalDeviceState(
                   new DeviceStateUpdateImpl(
                       DeviceStateUpdate.UPDATE_ELECTRIC_METER, consumption));
               requestSuccsessful = true;
             }
           }
         case DeviceStateUpdate.UPDATE_SLAT_ANGLE_DECREASE:
           // By UPDATE_SLAT_ANGLE_DECREASE, UPDATE_SLAT_ANGLE_INCREASE with value unequal 1 which
           // will
           // handle in the pollingRunnable and UPDATE_OPEN_CLOSE_ANGLE the value will be set
           // without
           // checking, because it was triggered by setting the slat position.
           requestSuccsessful = true;
           break;
         case DeviceStateUpdate.UPDATE_SLAT_ANGLE_INCREASE:
           requestSuccsessful = true;
           break;
         case DeviceStateUpdate.UPDATE_OPEN_CLOSE_ANGLE:
           requestSuccsessful = true;
           break;
         case DeviceStateUpdate.UPDATE_SLAT_ANGLE:
           if (device.getAnglePosition() != deviceStateUpdate.getValue()) {
             requestSuccsessful =
                 digitalSTROMClient.setDeviceOutputValue(
                     connMan.getSessionToken(),
                     device.getDSID(),
                     null,
                     DeviceConstants.DEVICE_SENSOR_SLAT_ANGLE_OUTPUT,
                     deviceStateUpdate.getValue());
           } else {
             commandHaveNoEffect = true;
           }
           break;
         case DeviceStateUpdate.REFRESH_OUTPUT:
           readOutputValue(device);
           logger.debug(
               "Inizalize output value reading for device with dSID {}.",
               device.getDSID().getValue());
           return;
         default:
           return;
       }
       if (commandHaveNoEffect) {
         logger.debug(
             "Command {} for device with dSID {} not send to dSS, because it has no effect!",
             deviceStateUpdate.getType(),
             device.getDSID().getValue());
         return;
       }
       if (requestSuccsessful) {
         logger.debug(
             "Send {} command to dSS and updateInternalDeviceState for device with dSID {}.",
             deviceStateUpdate.getType(),
             device.getDSID().getValue());
         device.updateInternalDeviceState(deviceStateUpdate);
       } else {
         logger.debug(
             "Can't send {} command for device with dSID {} to dSS!",
             deviceStateUpdate.getType(),
             device.getDSID().getValue());
       }
     }
   }
 }