diff --git a/lib/jul b/lib/jul index 99da5bb1cf..6a7a1908ed 160000 --- a/lib/jul +++ b/lib/jul @@ -1 +1 @@ -Subproject commit 99da5bb1cf14550948bbe1cbd484403647724112 +Subproject commit 6a7a1908eda054ac3b8e9cde166be814e439753c diff --git a/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/AbstractTriggerableAgent.java b/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/AbstractTriggerableAgent.java index b59efa4fac..4d554d03de 100644 --- a/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/AbstractTriggerableAgent.java +++ b/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/AbstractTriggerableAgent.java @@ -34,6 +34,7 @@ import org.openbase.jul.pattern.trigger.Trigger; import org.openbase.jul.pattern.trigger.TriggerPool; import org.openbase.jul.pattern.trigger.TriggerPool.TriggerAggregation; +import org.openbase.jul.pattern.trigger.TriggerPriority; import org.openbase.jul.schedule.GlobalCachedExecutorService; import org.openbase.jul.schedule.RecurrenceEventFilter; import org.openbase.jul.schedule.SyncObject; @@ -164,6 +165,11 @@ protected void postInit() throws InitializationException, InterruptedException { */ public void registerActivationTrigger(Trigger trigger, TriggerAggregation aggregation) throws CouldNotPerformException { try { + /* + * We need to take care that agents that schedule new actions are prioritized + * in contrast to the one which cancel their actions. + */ + trigger.setPriority(TriggerPriority.HIGH); activationTriggerPool.addTrigger(trigger, aggregation); } catch (CouldNotPerformException ex) { throw new InitializationException("Could not add agent to agent pool", ex); @@ -172,6 +178,11 @@ public void registerActivationTrigger(Trigger trigger, TriggerAggregation aggreg public void registerDeactivationTrigger(Trigger trigger, TriggerAggregation aggregation) throws CouldNotPerformException { try { + /* + * We need to take care that agents that cancel their actions are handled with low priority + * to avoid termination actions to get accidentally activated. + */ + trigger.setPriority(TriggerPriority.LOW); deactivationTriggerPool.addTrigger(trigger, aggregation); } catch (CouldNotPerformException ex) { throw new InitializationException("Could not add agent to agent pool", ex); diff --git a/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/MasterSlavePowerCycleAgent.kt b/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/MasterSlavePowerCycleAgent.kt index 90d0ff151b..2c307098be 100644 --- a/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/MasterSlavePowerCycleAgent.kt +++ b/module/app/preset/src/main/java/org/openbase/bco/app/preset/agent/MasterSlavePowerCycleAgent.kt @@ -51,18 +51,17 @@ import java.util.concurrent.TimeoutException */ class MasterSlavePowerCycleAgent : AbstractTriggerableAgent() { private var master: PowerConsumptionSensorRemote? = null - private var slave: PowerStateServiceRemote? = null + private var slave: PowerStateServiceRemote = PowerStateServiceRemote() + @Throws(InitializationException::class, InterruptedException::class) override fun init(config: UnitConfig) { super.init(config) try { val variableProvider = MetaConfigVariableProvider("AgentConfig", config.metaConfig) - if (master != null) { - master!!.shutdown() - } - if (slave != null) { - slave!!.shutdown() - } + + master?.shutdown() + slave.shutdown() + slave = PowerStateServiceRemote() // resolve master @@ -74,23 +73,25 @@ class MasterSlavePowerCycleAgent : AbstractTriggerableAgent() { // resolve master try { - slave!!.init(Registries.getUnitRegistry(true).getUnitConfigById(variableProvider.getValue("SLAVE_ID"))) + slave.init(Registries.getUnitRegistry(true).getUnitConfigById(variableProvider.getValue("SLAVE_ID"))) } catch (ex: NotAvailableException) { - slave!!.init( + slave.init( Registries.getUnitRegistry(true).getUnitConfigByAlias(variableProvider.getValue("SLAVE_ALIAS")) ) } // activation trigger - registerActivationTrigger( - GenericBoundedDoubleValueTrigger( - master, - variableProvider.getValue("HIGH_ACTIVE_POWER_THRESHOLD", "1.0").toDouble(), - HIGH_ACTIVE, - POWER_CONSUMPTION_STATE_SERVICE, - "getConsumption" - ), OR - ) + master?.let { master -> + registerActivationTrigger( + GenericBoundedDoubleValueTrigger( + master, + variableProvider.getValue("HIGH_ACTIVE_POWER_THRESHOLD", "1.0").toDouble(), + HIGH_ACTIVE, + POWER_CONSUMPTION_STATE_SERVICE, + "getConsumption" + ), OR + ) + } } catch (ex: CouldNotPerformException) { throw InitializationException(this, ex) } @@ -107,7 +108,7 @@ class MasterSlavePowerCycleAgent : AbstractTriggerableAgent() { // sync slave activationState.value?.let { value -> when (value) { - ACTIVE -> observe(slave!!.setPowerState(ON, getDefaultActionParameter(Timeout.INFINITY_TIMEOUT))) + ACTIVE -> observe(slave.setPowerState(ON, getDefaultActionParameter(Timeout.INFINITY_TIMEOUT))) INACTIVE, UNKNOWN -> cancelAllObservedActions() } } diff --git a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/AbsenceEnergySavingAgentTest.java b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/AbsenceEnergySavingAgentTest.java index 6752388e56..7fdea2bde2 100644 --- a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/AbsenceEnergySavingAgentTest.java +++ b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/AbsenceEnergySavingAgentTest.java @@ -25,11 +25,12 @@ import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import org.openbase.app.test.agent.AbstractBCOAgentManagerTest; import org.openbase.bco.dal.control.layer.unit.MotionDetectorController; +import org.openbase.bco.dal.lib.state.States; +import org.openbase.bco.dal.lib.state.States.Motion; import org.openbase.bco.dal.remote.layer.unit.ColorableLightRemote; import org.openbase.bco.dal.remote.layer.unit.MotionDetectorRemote; import org.openbase.bco.dal.remote.layer.unit.Units; @@ -61,18 +62,12 @@ * * @author Timo Michalski */ -@Disabled public class AbsenceEnergySavingAgentTest extends AbstractBCOAgentManagerTest { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AbsenceEnergySavingAgentTest.class); public static final String ABSENCE_ENERGY_SAVING_AGENT_LABEL = "Absence_Energy_Saving_Agent_Unit_Test"; - private static final PowerState ON = PowerState.newBuilder().setValue(PowerState.State.ON).build(); - - private static final MotionState MOTION = MotionState.newBuilder().setValue(MotionState.State.MOTION).build(); - private static final MotionState NO_MOTION = MotionState.newBuilder().setValue(MotionState.State.NO_MOTION).build(); - /** * Test of activate method, of class PowerStateSynchroniserAgent. * @@ -102,7 +97,7 @@ public void testAbsenceEnergySavingAgent() throws Exception { motionDetectorRemote.waitForData(); // create initial values with motion and lights on - motionDetectorController.applyServiceState(MOTION, ServiceType.MOTION_STATE_SERVICE); + motionDetectorController.applyServiceState(Motion.MOTION, ServiceType.MOTION_STATE_SERVICE); motionDetectorStateAwaiter.waitForState((MotionDetectorData data) -> data.getMotionState().getValue() == MotionState.State.MOTION); locationStateAwaiter.waitForState((LocationData data) -> data.getPresenceState().getValue() == PresenceState.State.PRESENT); @@ -112,7 +107,7 @@ public void testAbsenceEnergySavingAgent() throws Exception { .setExecutionTimePeriod(1000000) .build(); - waitForExecution(locationRemote.setPowerState(ON, lowPriorityActionParameter)); + waitForExecution(locationRemote.setPowerState(States.Power.ON, lowPriorityActionParameter)); locationStateAwaiter.waitForState((LocationData data) -> data.getPowerState().getValue() == PowerState.State.ON); colorableLightStateAwaiter.waitForState((ColorableLightData data) -> data.getPowerState().getValue() == PowerState.State.ON); @@ -122,7 +117,7 @@ public void testAbsenceEnergySavingAgent() throws Exception { assertEquals(PowerState.State.ON, colorableLightRemote.getPowerState().getValue(), "PowerState of ColorableLight[" + colorableLightRemote.getLabel() + "] has not switched to OFF"); // test if on no motion the lights are turned off - motionDetectorController.applyServiceState(NO_MOTION, ServiceType.MOTION_STATE_SERVICE); + motionDetectorController.applyServiceState(Motion.NO_MOTION, ServiceType.MOTION_STATE_SERVICE); motionDetectorStateAwaiter.waitForState((MotionDetectorData data) -> data.getMotionState().getValue() == MotionState.State.NO_MOTION); locationStateAwaiter.waitForState((LocationData data) -> data.getPresenceState().getValue() == PresenceState.State.ABSENT); colorableLightStateAwaiter.waitForState((ColorableLightData data) -> data.getPowerState().getValue() == PowerState.State.OFF); @@ -134,7 +129,7 @@ public void testAbsenceEnergySavingAgent() throws Exception { //assertEquals("PowerState of Location[" + locationRemote.getLabel() + "] has not switched to OFF", PowerState.State.OFF, locationRemote.getPowerState().getValue()); // test if the lights stay off on new motion - motionDetectorController.applyServiceState(MOTION, ServiceType.MOTION_STATE_SERVICE); + motionDetectorController.applyServiceState(Motion.MOTION, ServiceType.MOTION_STATE_SERVICE); motionDetectorStateAwaiter.waitForState((MotionDetectorData data) -> data.getMotionState().getValue() == MotionState.State.MOTION); locationStateAwaiter.waitForState((LocationData data) -> data.getPresenceState().getValue() == PresenceState.State.PRESENT); colorableLightStateAwaiter.waitForState((ColorableLightData data) -> data.getPowerState().getValue() == PowerState.State.OFF); diff --git a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/FireAlarmAgentTest.java b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/FireAlarmAgentTest.java index 4b73559403..c3d78a01c3 100644 --- a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/FireAlarmAgentTest.java +++ b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/FireAlarmAgentTest.java @@ -51,7 +51,6 @@ import org.openbase.type.domotic.unit.location.LocationDataType.LocationData; -@Disabled public class FireAlarmAgentTest extends AbstractBCOAgentManagerTest { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(FireAlarmAgentTest.class); diff --git a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/HeaterEnergySavingAgentTest.java b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/HeaterEnergySavingAgentTest.java index 36da7433e9..63552b9ac9 100644 --- a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/HeaterEnergySavingAgentTest.java +++ b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/HeaterEnergySavingAgentTest.java @@ -58,7 +58,6 @@ * * @author Timo * Michalski */ -@Disabled public class HeaterEnergySavingAgentTest extends AbstractBCOAgentManagerTest { public static final String HEATER_ENERGY_SAVING_AGENT_LABEL = "Heater_Energy_Saving_Agent_Unit_Test"; diff --git a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/IlluminationLightSavingAgentTest.java b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/IlluminationLightSavingAgentTest.java index 47d6aaf6fa..1d75b0a888 100644 --- a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/IlluminationLightSavingAgentTest.java +++ b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/IlluminationLightSavingAgentTest.java @@ -24,7 +24,6 @@ import static org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -61,16 +60,12 @@ * * @author Timo * Michalski */ -@Disabled public class IlluminationLightSavingAgentTest extends AbstractBCOAgentManagerTest { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(IlluminationLightSavingAgentTest.class); public static final String ILLUMINATION_LIGHT_SAVING_AGENT_LABEL = "Illumination_Light_Saving_Agent_Unit_Test"; - public IlluminationLightSavingAgentTest() throws Exception { - } - /** * Test of activate method, of class PowerStateSynchroniserAgent. * diff --git a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PowerStateSynchroniserAgentTest.java b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PowerStateSynchroniserAgentTest.java index 74a9d6f4de..6230420a8e 100644 --- a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PowerStateSynchroniserAgentTest.java +++ b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PowerStateSynchroniserAgentTest.java @@ -58,17 +58,12 @@ /** * * @author Tamino Huxohl */ -@Disabled public class PowerStateSynchroniserAgentTest extends AbstractBCOAgentManagerTest { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(PowerStateSynchroniserAgentTest.class); private static final String AGENT_ALIAS = "Power_State_Sync_Agent_Unit_Test"; private static final long STATE_AWAIT_TIMEOUT = 1000; - - public PowerStateSynchroniserAgentTest() { - } - private String sourceId; private String targetId1; private String targetId2; diff --git a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PresenceLightAgentTest.java b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PresenceLightAgentTest.java index e369c8e682..c3c3be0b05 100644 --- a/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PresenceLightAgentTest.java +++ b/module/app/preset/src/test/java/org/openbase/bco/app/preset/agent/PresenceLightAgentTest.java @@ -63,12 +63,9 @@ import org.openbase.type.domotic.unit.dal.MotionDetectorDataType.MotionDetectorData; import org.openbase.type.domotic.unit.location.LocationDataType.LocationData; - - /** * * @author Timo Michalski */ -@Disabled public class PresenceLightAgentTest extends AbstractBCOAgentManagerTest { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(PresenceLightAgentTest.class); @@ -88,14 +85,6 @@ public class PresenceLightAgentTest extends AbstractBCOAgentManagerTest { private UnitStateAwaiter lightSensorStateAwaiter; private UnitStateAwaiter locationStateAwaiter; - public PresenceLightAgentTest() throws CouldNotPerformException, InterruptedException { - locationRemote = Units.getUnitByAlias(MockRegistry.ALIAS_LOCATION_STAIRWAY_TO_HEAVEN, true, Units.LOCATION); - colorableLightRemote = locationRemote.getUnits(UnitType.COLORABLE_LIGHT, true, Units.COLORABLE_LIGHT).get(0); - motionDetectorRemote = locationRemote.getUnits(UnitType.MOTION_DETECTOR, true, Units.MOTION_DETECTOR).get(0); - lightSensorRemote = locationRemote.getUnits(UnitType.LIGHT_SENSOR, true, Units.LIGHT_SENSOR).get(0); - - } - //@BeforeAll //uncomment to enable debug mode public static void showActionInspector() throws Throwable { @@ -110,6 +99,11 @@ public static void showActionInspector() throws Throwable { @Override public void prepareEnvironment() throws CouldNotPerformException, InterruptedException { + locationRemote = Units.getUnitByAlias(MockRegistry.ALIAS_LOCATION_STAIRWAY_TO_HEAVEN, true, Units.LOCATION); + colorableLightRemote = locationRemote.getUnits(UnitType.COLORABLE_LIGHT, true, Units.COLORABLE_LIGHT).get(0); + motionDetectorRemote = locationRemote.getUnits(UnitType.MOTION_DETECTOR, true, Units.MOTION_DETECTOR).get(0); + lightSensorRemote = locationRemote.getUnits(UnitType.LIGHT_SENSOR, true, Units.LIGHT_SENSOR).get(0); + // set location emphasis to economy to make the agent more responsive on presence changes waitForExecution(locationRemote.setEconomyEmphasis(1)); @@ -147,7 +141,6 @@ public void prepareEnvironment() throws CouldNotPerformException, InterruptedExc */ @Test @Timeout(30) - @Disabled public void testPresenceLightAgent() throws Exception { // test if on motion the lights are turned on diff --git a/module/authentication/test/src/main/java/org/openbase/bco/authentication/mock/MqttIntegrationTest.kt b/module/authentication/test/src/main/java/org/openbase/bco/authentication/mock/MqttIntegrationTest.kt index 941762e72a..3f6a341c73 100644 --- a/module/authentication/test/src/main/java/org/openbase/bco/authentication/mock/MqttIntegrationTest.kt +++ b/module/authentication/test/src/main/java/org/openbase/bco/authentication/mock/MqttIntegrationTest.kt @@ -54,7 +54,7 @@ open class MqttIntegrationTest { synchronized(configLock) { mosquittoConfig = Files.createTempFile("mosquitto_", ".conf") Files.write( - mosquittoConfig, Arrays.asList( + mosquittoConfig, listOf( "allow_anonymous true", "listener " + port ) diff --git a/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/location/LocationControllerImpl.java b/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/location/LocationControllerImpl.java index 85ebc74dc5..3beefbbcd8 100644 --- a/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/location/LocationControllerImpl.java +++ b/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/location/LocationControllerImpl.java @@ -123,6 +123,7 @@ public List getChildLocationList(final boolean waitForData) thro try { childList.add(Units.getUnit(Registries.getUnitRegistry().getUnitConfigById(childId), waitForData, LOCATION)); } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); throw new CouldNotPerformException("Could not get all child locations!", ex); } } diff --git a/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/scene/SceneControllerImpl.java b/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/scene/SceneControllerImpl.java index 8d5b530f22..8d657478f4 100644 --- a/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/scene/SceneControllerImpl.java +++ b/module/dal/control/src/main/java/org/openbase/bco/dal/control/layer/unit/scene/SceneControllerImpl.java @@ -403,6 +403,7 @@ private RequiredActionObserver(final List requiredActionImpact, for (Entry, RequiredServiceDescription> unitActionReferenceEntry : unitAndRequiredServiceStateMap.entrySet()) { try { unitActionReferenceEntry.getKey().addServiceStateObserver(ServiceTempus.CURRENT, unitActionReferenceEntry.getValue().getServiceType(), this); + unitActionReferenceEntry.getKey().addServiceStateObserver(ServiceTempus.REQUESTED, unitActionReferenceEntry.getValue().getServiceType(), this); } catch (CouldNotPerformException ex) { ExceptionPrinter.printHistory("Could not observe service state of action impact!", ex, LOGGER, LogLevel.WARN); } @@ -416,7 +417,7 @@ private RequiredActionObserver(final List requiredActionImpact, } catch (CouldNotPerformException e) { // ignore if this action can not be checks since the validation will at least check its state. } catch (InterruptedException e) { - e.printStackTrace(); + Thread.currentThread().interrupt(); } } @@ -428,7 +429,7 @@ private void verifyAllStates() { try { for (Entry, RequiredServiceDescription> unitActionReferenceEntry : unitAndRequiredServiceStateMap.entrySet()) { try { - // skip unit in case its offline, since than the verification is automatically + // skip unit in case its offline, since then the verification is automatically // performed when its back online but those unnecessary timeouts are avoided. if (unitActionReferenceEntry.getKey().isConnected()) { continue; @@ -479,6 +480,7 @@ public void shutdown() { // deregister observation for (Entry, RequiredServiceDescription> unitActionReferenceEntry : unitAndRequiredServiceStateMap.entrySet()) { unitActionReferenceEntry.getKey().removeServiceStateObserver(ServiceTempus.CURRENT, unitActionReferenceEntry.getValue().getServiceType(), this); + unitActionReferenceEntry.getKey().removeServiceStateObserver(ServiceTempus.REQUESTED, unitActionReferenceEntry.getValue().getServiceType(), this); } } } diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/action/RemoteAction.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/action/RemoteAction.java index b70ffc288f..74cbbf775c 100644 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/action/RemoteAction.java +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/action/RemoteAction.java @@ -1117,6 +1117,8 @@ public void waitForRegistration(final long timeout, final TimeUnit timeUnit) thr } else { futureObservationTask.get(timeSplit.getTime(), timeSplit.getTimeUnit()); } + } catch (CancellationException ex) { + throw new CouldNotPerformException(ex.getCause()); } catch (java.util.concurrent.TimeoutException ex) { throw new org.openbase.jul.exception.TimeoutException(); } @@ -1232,4 +1234,3 @@ public String toString() { return Action.toString(this); } } - diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/AbstractBCOTrigger.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/AbstractBCOTrigger.java deleted file mode 100644 index 816a4dc185..0000000000 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/AbstractBCOTrigger.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.openbase.bco.dal.remote.trigger; - -/*- - * #%L - * BCO DAL Remote - * %% - * Copyright (C) 2014 - 2021 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.protobuf.Message; -import org.openbase.bco.dal.lib.layer.service.Services; -import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.jul.extension.type.processing.TimestampProcessor; -import org.openbase.jul.pattern.Observer; -import org.openbase.jul.pattern.controller.Remote; -import org.openbase.type.domotic.state.ConnectionStateType.ConnectionState; -import org.openbase.jul.pattern.provider.DataProvider; -import org.openbase.jul.pattern.trigger.AbstractTrigger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.openbase.type.domotic.service.ServiceTemplateType.ServiceTemplate.ServiceType; -import org.openbase.type.domotic.state.ActivationStateType.ActivationState; - -import java.lang.reflect.Method; - -/** - * @param UnitRemote - * @param
DataType - * @param StateTypeEnum - * @author Timo Michalski - */ -public abstract class AbstractBCOTrigger, DT extends Message, STE> extends AbstractTrigger { - - protected final Logger LOGGER = LoggerFactory.getLogger(getClass()); - - private final UR unitRemote; - private final STE targetState; - private final ServiceType serviceType; - private final Observer, DT> dataObserver; - private final Observer, ConnectionState.State> connectionObserver; - private boolean active = false; - - public AbstractBCOTrigger(final UR unitRemote, final STE targetState, final ServiceType serviceType) throws InstantiationException { - super(); - this.unitRemote = unitRemote; - this.targetState = targetState; - this.serviceType = serviceType; - - this.dataObserver = (DataProvider
source, DT data) -> { - verifyCondition(data, targetState, serviceType); - }; - - this.connectionObserver = (Remote source, ConnectionState.State data) -> { - if (data.equals(ConnectionState.State.CONNECTED)) { - verifyCondition(unitRemote.getData(), targetState, serviceType); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.UNKNOWN).build())); - } - }; - } - - protected abstract void verifyCondition(final DT data, final STE targetState, final ServiceType serviceType); - - @Override - public void activate() throws CouldNotPerformException, InterruptedException { - unitRemote.addDataObserver(dataObserver); - unitRemote.addConnectionStateObserver(connectionObserver); - active = true; - if (unitRemote.isDataAvailable()) { - verifyCondition(unitRemote.getData(), targetState, serviceType); - } - } - - @Override - public void deactivate() throws CouldNotPerformException, InterruptedException { - unitRemote.removeDataObserver(dataObserver); - unitRemote.removeConnectionStateObserver(connectionObserver); - active = false; - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.UNKNOWN).build())); - } - - @Override - public boolean isActive() { - return active; - } - - @Override - public void shutdown() { - try { - deactivate(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } catch (CouldNotPerformException ex) { - ExceptionPrinter.printHistory("Could not shutdown " + this, ex, LOGGER); - } - super.shutdown(); - } -} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/AbstractBCOTrigger.kt b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/AbstractBCOTrigger.kt new file mode 100644 index 0000000000..ab75f46e4c --- /dev/null +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/AbstractBCOTrigger.kt @@ -0,0 +1,115 @@ +package org.openbase.bco.dal.remote.trigger + +import com.google.protobuf.Message +import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.openbase.jul.extension.type.processing.TimestampProcessor +import org.openbase.jul.pattern.Observer +import org.openbase.jul.pattern.controller.Remote +import org.openbase.jul.pattern.provider.DataProvider +import org.openbase.jul.pattern.trigger.AbstractTrigger +import org.openbase.type.domotic.service.ServiceTemplateType +import org.openbase.type.domotic.state.ActivationStateType +import org.openbase.type.domotic.state.ConnectionStateType +import org.slf4j.LoggerFactory + +/*- + * #%L + * BCO DAL Remote + * %% + * Copyright (C) 2014 - 2021 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ /** + * @param UnitRemote + * @param
DataType + * @param StateTypeEnum + * @author [Timo Michalski](mailto:tmichalski@techfak.uni-bielefeld.de) +
*/ +abstract class AbstractBCOTrigger, DT : Message, STE>( + private val unitRemote: UR, + private val targetState: STE, + private val serviceType: ServiceTemplateType.ServiceTemplate.ServiceType +) : AbstractTrigger() { + protected val LOGGER = LoggerFactory.getLogger(javaClass) + private val dataObserver: Observer, DT> + private val connectionObserver: Observer, ConnectionStateType.ConnectionState.State> + private var active = false + + init { + dataObserver = + Observer { source: DataProvider
, data: DT -> verifyCondition(data, targetState, serviceType) } + connectionObserver = Observer { source: Remote<*>?, data: ConnectionStateType.ConnectionState.State -> + if (data == ConnectionStateType.ConnectionState.State.CONNECTED) { + verifyCondition(unitRemote.data, targetState, serviceType) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.UNKNOWN + ).build() + ) + ) + } + } + } + + protected abstract fun verifyCondition( + data: DT, + targetState: STE, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType? + ) + + @Throws(CouldNotPerformException::class, InterruptedException::class) + override fun activate() { + StateObservationService.registerTrigger(dataObserver, unitRemote, this) + unitRemote.addConnectionStateObserver(connectionObserver) + active = true + if (unitRemote.isDataAvailable) { + verifyCondition(unitRemote.data, targetState, serviceType) + } + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + override fun deactivate() { + StateObservationService.removeTrigger(dataObserver, unitRemote, this) + unitRemote.removeConnectionStateObserver(connectionObserver) + active = false + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.UNKNOWN + ).build() + ) + ) + } + + override fun isActive(): Boolean { + return active + } + + override fun shutdown() { + try { + deactivate() + } catch (ex: InterruptedException) { + Thread.currentThread().interrupt() + } catch (ex: CouldNotPerformException) { + ExceptionPrinter.printHistory("Could not shutdown $this", ex, LOGGER) + } + super.shutdown() + } +} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericBoundedDoubleValueTrigger.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericBoundedDoubleValueTrigger.java deleted file mode 100644 index ba9bda2313..0000000000 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericBoundedDoubleValueTrigger.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.openbase.bco.dal.remote.trigger; - -/*- - * #%L - * BCO DAL Remote - * %% - * Copyright (C) 2014 - 2021 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.protobuf.Message; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.NotAvailableException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.jul.extension.type.processing.TimestampProcessor; -import org.openbase.jul.pattern.Observer; -import org.openbase.jul.pattern.controller.Remote; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.type.domotic.state.ConnectionStateType.ConnectionState; -import org.openbase.jul.pattern.provider.DataProvider; -import org.openbase.type.domotic.state.ConnectionStateType; -import org.slf4j.LoggerFactory; -import org.openbase.type.domotic.service.ServiceTemplateType.ServiceTemplate.ServiceType; -import org.openbase.type.domotic.state.ActivationStateType.ActivationState; -import org.openbase.bco.dal.lib.layer.service.Services; -import org.openbase.jul.pattern.trigger.AbstractTrigger; -import org.slf4j.Logger; - -/** - * @param UnitRemote - * @param
DataType - * - * @author Timo Michalski - */ -public class GenericBoundedDoubleValueTrigger, DT extends Message> extends AbstractBCOTrigger { - - public enum TriggerOperation { - HIGH_ACTIVE, LOW_ACTIVE - } - - private final TriggerOperation triggerOperation; - private final String specificValueCall; - - public GenericBoundedDoubleValueTrigger(final UR unitRemote, final double boundary, final TriggerOperation triggerOperation, ServiceType serviceType, String specificValueCall) throws InstantiationException { - super(unitRemote, boundary, serviceType); - - try { - - if (triggerOperation == null) { - throw new NotAvailableException("triggerOperation"); - } - - this.triggerOperation = triggerOperation; - this.specificValueCall = specificValueCall; - - } catch (CouldNotPerformException ex) { - throw new InstantiationException(this.getClass(), ex); - } - } - - protected void verifyCondition(final DT data, final Double boundary, final ServiceType serviceType) { - try { - Object serviceState = Services.invokeProviderServiceMethod(serviceType, data); - - Method method = serviceState.getClass().getMethod(specificValueCall); - double value = (Double) method.invoke(serviceState); - - if (triggerOperation == TriggerOperation.HIGH_ACTIVE) { - if (value >= boundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - } else { - if (value <= boundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - } - } catch (CouldNotPerformException ex) { - ExceptionPrinter.printHistory("Could not verify condition " + this, ex, LOGGER); - } catch (NoSuchMethodException ex) { - ExceptionPrinter.printHistory("Method not known " + this, ex, LOGGER); - } catch (SecurityException ex) { - ExceptionPrinter.printHistory("Security Exception " + this, ex, LOGGER); - } catch (IllegalAccessException ex) { - ExceptionPrinter.printHistory("Illegal Access Exception " + this, ex, LOGGER); - } catch (IllegalArgumentException ex) { - ExceptionPrinter.printHistory("Illegal Argument Exception " + this, ex, LOGGER); - } catch (InvocationTargetException ex) { - ExceptionPrinter.printHistory("Could not invoke method " + this, ex, LOGGER); - } - } -} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericBoundedDoubleValueTrigger.kt b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericBoundedDoubleValueTrigger.kt new file mode 100644 index 0000000000..13b0936637 --- /dev/null +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericBoundedDoubleValueTrigger.kt @@ -0,0 +1,127 @@ +package org.openbase.bco.dal.remote.trigger + +import com.google.protobuf.Message +import org.openbase.bco.dal.lib.layer.service.Services +import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.InstantiationException +import org.openbase.jul.exception.NotAvailableException +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.openbase.jul.extension.type.processing.TimestampProcessor +import org.openbase.type.domotic.service.ServiceTemplateType +import org.openbase.type.domotic.state.ActivationStateType +import java.lang.reflect.InvocationTargetException + +/*- + * #%L + * BCO DAL Remote + * %% + * Copyright (C) 2014 - 2021 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ /** + * @param UnitRemote + * @param
DataType + * + * @author [Timo Michalski](mailto:tmichalski@techfak.uni-bielefeld.de) +
*/ +class GenericBoundedDoubleValueTrigger, DT : Message>( + unitRemote: UR, + boundary: Double, + triggerOperation: TriggerOperation?, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType, + specificValueCall: String +) : AbstractBCOTrigger(unitRemote, boundary, serviceType) { + enum class TriggerOperation { + HIGH_ACTIVE, LOW_ACTIVE + } + + private var triggerOperation: TriggerOperation + private var specificValueCall: String + + init { + try { + if (triggerOperation == null) { + throw NotAvailableException("triggerOperation") + } + this.triggerOperation = triggerOperation + this.specificValueCall = specificValueCall + } catch (ex: CouldNotPerformException) { + throw InstantiationException(this.javaClass, ex) + } + } + + override fun verifyCondition( + data: DT, + boundary: Double, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType? + ) { + try { + val serviceState: Any = Services.invokeProviderServiceMethod(serviceType, data) + val method = serviceState.javaClass.getMethod(specificValueCall) + val value = method.invoke(serviceState) as Double + if (triggerOperation == TriggerOperation.HIGH_ACTIVE) { + if (value >= boundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + } else { + if (value <= boundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + } + } catch (ex: CouldNotPerformException) { + ExceptionPrinter.printHistory("Could not verify condition $this", ex, LOGGER) + } catch (ex: NoSuchMethodException) { + ExceptionPrinter.printHistory("Method not known $this", ex, LOGGER) + } catch (ex: SecurityException) { + ExceptionPrinter.printHistory("Security Exception $this", ex, LOGGER) + } catch (ex: IllegalAccessException) { + ExceptionPrinter.printHistory("Illegal Access Exception $this", ex, LOGGER) + } catch (ex: IllegalArgumentException) { + ExceptionPrinter.printHistory("Illegal Argument Exception $this", ex, LOGGER) + } catch (ex: InvocationTargetException) { + ExceptionPrinter.printHistory("Could not invoke method $this", ex, LOGGER) + } + } +} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericDualBoundedDoubleValueTrigger.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericDualBoundedDoubleValueTrigger.java deleted file mode 100644 index 98c71a4e95..0000000000 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericDualBoundedDoubleValueTrigger.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.openbase.bco.dal.remote.trigger; - -/*- - * #%L - * BCO DAL Remote - * %% - * Copyright (C) 2014 - 2021 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.protobuf.Message; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.InvalidStateException; -import org.openbase.jul.exception.NotAvailableException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.jul.extension.type.processing.TimestampProcessor; -import org.openbase.jul.pattern.Observer; -import org.openbase.jul.pattern.Pair; -import org.openbase.jul.pattern.controller.Remote; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.jul.pattern.provider.DataProvider; -import org.openbase.type.domotic.state.ConnectionStateType; -import org.slf4j.LoggerFactory; -import org.openbase.type.domotic.service.ServiceTemplateType.ServiceTemplate.ServiceType; -import org.openbase.type.domotic.state.ActivationStateType.ActivationState; -import org.openbase.bco.dal.lib.layer.service.Services; -import org.openbase.jul.pattern.trigger.AbstractTrigger; -import org.slf4j.Logger; - -/** - * @param UnitRemote - * @param
DataType - * - * @author Timo Michalski - */ -public class GenericDualBoundedDoubleValueTrigger, DT extends Message> extends AbstractBCOTrigger> { - - public enum TriggerOperation { - HIGH_ACTIVE, LOW_ACTIVE, INSIDE_ACTIVE, OUTSIDE_ACTIVE - } - - private final TriggerOperation triggerOperation; - private final String specificValueCall; - - public GenericDualBoundedDoubleValueTrigger(final UR unitRemote, final double upperBoundary, final double lowerBoundary, final TriggerOperation triggerOperation, ServiceType serviceType, String specificValueCall) throws InstantiationException { - super(unitRemote, new Pair<>(lowerBoundary, upperBoundary), serviceType); - - try { - if (upperBoundary < lowerBoundary) { - throw new InvalidStateException("upperBoundary below lowerBoundary"); - } - - if (triggerOperation == null) { - throw new NotAvailableException("triggerOperation"); - } - - this.triggerOperation = triggerOperation; - this.specificValueCall = specificValueCall; - } catch (CouldNotPerformException ex) { - throw new InstantiationException(this.getClass(), ex); - } - } - - protected void verifyCondition(final DT data, final Pair lowerUpperBoundaryPair, final ServiceType serviceType) { - try { - Object serviceState = Services.invokeProviderServiceMethod(serviceType, data); - - Method method = serviceState.getClass().getMethod(specificValueCall); - double value = (Double) method.invoke(serviceState); - - final double lowerBoundary = lowerUpperBoundaryPair.getKey(); - final double upperBoundary = lowerUpperBoundaryPair.getValue(); - - switch (triggerOperation) { - case HIGH_ACTIVE: - if (value >= upperBoundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else if (value < lowerBoundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - break; - case LOW_ACTIVE: - if (value > upperBoundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } else if (value <= lowerBoundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } - break; - case INSIDE_ACTIVE: - if (lowerBoundary <= value && value <= upperBoundary) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - break; - case OUTSIDE_ACTIVE: - if (value < lowerBoundary || upperBoundary < value) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - break; - } - } catch (CouldNotPerformException ex) { - ExceptionPrinter.printHistory("Could not verify condition " + this, ex, LOGGER); - } catch (NoSuchMethodException ex) { - ExceptionPrinter.printHistory("Method not known " + this, ex, LOGGER); - } catch (SecurityException ex) { - ExceptionPrinter.printHistory("Security Exception " + this, ex, LOGGER); - } catch (IllegalAccessException ex) { - ExceptionPrinter.printHistory("Illegal Access Exception " + this, ex, LOGGER); - } catch (IllegalArgumentException ex) { - ExceptionPrinter.printHistory("Illegal Argument Exception " + this, ex, LOGGER); - } catch (InvocationTargetException ex) { - ExceptionPrinter.printHistory("Could not invoke method " + this, ex, LOGGER); - } - } -} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericDualBoundedDoubleValueTrigger.kt b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericDualBoundedDoubleValueTrigger.kt new file mode 100644 index 0000000000..a5e1b3bf8d --- /dev/null +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericDualBoundedDoubleValueTrigger.kt @@ -0,0 +1,171 @@ +package org.openbase.bco.dal.remote.trigger + +import com.google.protobuf.Message +import org.openbase.bco.dal.lib.layer.service.Services +import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.InstantiationException +import org.openbase.jul.exception.InvalidStateException +import org.openbase.jul.exception.NotAvailableException +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.openbase.jul.extension.type.processing.TimestampProcessor +import org.openbase.jul.pattern.Pair +import org.openbase.type.domotic.service.ServiceTemplateType +import org.openbase.type.domotic.state.ActivationStateType +import java.lang.reflect.InvocationTargetException + +/*- + * #%L + * BCO DAL Remote + * %% + * Copyright (C) 2014 - 2021 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ /** + * @param UnitRemote + * @param
DataType + * + * @author [Timo Michalski](mailto:tmichalski@techfak.uni-bielefeld.de) +
*/ +open class GenericDualBoundedDoubleValueTrigger, DT : Message>( + unitRemote: UR, + upperBoundary: Double, + lowerBoundary: Double, + triggerOperation: TriggerOperation?, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType, + specificValueCall: String +) : AbstractBCOTrigger>(unitRemote, Pair(lowerBoundary, upperBoundary), serviceType) { + enum class TriggerOperation { + HIGH_ACTIVE, LOW_ACTIVE, INSIDE_ACTIVE, OUTSIDE_ACTIVE + } + + private val triggerOperation: TriggerOperation + private val specificValueCall: String + + init { + try { + if (upperBoundary < lowerBoundary) { + throw InvalidStateException("upperBoundary below lowerBoundary") + } + if (triggerOperation == null) { + throw NotAvailableException("triggerOperation") + } + this.triggerOperation = triggerOperation + this.specificValueCall = specificValueCall + } catch (ex: CouldNotPerformException) { + throw InstantiationException(this.javaClass, ex) + } + } + + override fun verifyCondition( + data: DT, + lowerUpperBoundaryPair: Pair, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType? + ) { + try { + val serviceState: Any = Services.invokeProviderServiceMethod(serviceType, data) + val method = serviceState.javaClass.getMethod(specificValueCall) + val value = method.invoke(serviceState) as Double + val lowerBoundary = lowerUpperBoundaryPair.key + val upperBoundary = lowerUpperBoundaryPair.value + when (triggerOperation) { + TriggerOperation.HIGH_ACTIVE -> if (value >= upperBoundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else if (value < lowerBoundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + + TriggerOperation.LOW_ACTIVE -> if (value > upperBoundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } else if (value <= lowerBoundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } + + TriggerOperation.INSIDE_ACTIVE -> if (lowerBoundary <= value && value <= upperBoundary) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + + TriggerOperation.OUTSIDE_ACTIVE -> if (value < lowerBoundary || upperBoundary < value) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + } + } catch (ex: CouldNotPerformException) { + ExceptionPrinter.printHistory("Could not verify condition $this", ex, LOGGER) + } catch (ex: NoSuchMethodException) { + ExceptionPrinter.printHistory("Method not known $this", ex, LOGGER) + } catch (ex: SecurityException) { + ExceptionPrinter.printHistory("Security Exception $this", ex, LOGGER) + } catch (ex: IllegalAccessException) { + ExceptionPrinter.printHistory("Illegal Access Exception $this", ex, LOGGER) + } catch (ex: IllegalArgumentException) { + ExceptionPrinter.printHistory("Illegal Argument Exception $this", ex, LOGGER) + } catch (ex: InvocationTargetException) { + ExceptionPrinter.printHistory("Could not invoke method $this", ex, LOGGER) + } + } +} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericServiceStateValueTrigger.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericServiceStateValueTrigger.java deleted file mode 100644 index 9cf145497f..0000000000 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericServiceStateValueTrigger.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.openbase.bco.dal.remote.trigger; - -/*- - * #%L - * BCO DAL Remote - * %% - * Copyright (C) 2014 - 2021 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * . - * #L% - */ - -import com.google.protobuf.Message; -import org.openbase.bco.dal.lib.layer.service.Services; -import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.jul.extension.type.processing.TimestampProcessor; -import org.openbase.type.domotic.service.ServiceTemplateType.ServiceTemplate.ServiceType; -import org.openbase.type.domotic.state.ActivationStateType.ActivationState; - -import java.lang.reflect.Method; - -/** - * @param UnitRemote - * @param
DataType - * @param StateTypeEnum - * - * @author Divine Threepwood - */ -public class GenericServiceStateValueTrigger, DT extends Message, STE extends Enum> extends AbstractBCOTrigger { - - public GenericServiceStateValueTrigger(final UR unitRemote, final STE targetState, final ServiceType serviceType) throws InstantiationException, InstantiationException { - super(unitRemote, targetState, serviceType); - } - - @Override - protected void verifyCondition(DT data, STE targetState, ServiceType serviceType) { - try { - Message serviceState = Services.invokeProviderServiceMethod(serviceType, data); - - Method method = serviceState.getClass().getMethod("getValue"); - if (method.invoke(serviceState).equals(targetState)) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - } catch (Exception ex) { - ExceptionPrinter.printHistory("Could not verify condition " + this, ex, LOGGER); - } - } -} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericServiceStateValueTrigger.kt b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericServiceStateValueTrigger.kt new file mode 100644 index 0000000000..a051a2fa29 --- /dev/null +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/GenericServiceStateValueTrigger.kt @@ -0,0 +1,72 @@ +package org.openbase.bco.dal.remote.trigger + +import com.google.protobuf.Message +import org.openbase.bco.dal.lib.layer.service.Services +import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.openbase.jul.extension.type.processing.TimestampProcessor +import org.openbase.type.domotic.service.ServiceTemplateType +import org.openbase.type.domotic.state.ActivationStateType + +/*- + * #%L + * BCO DAL Remote + * %% + * Copyright (C) 2014 - 2021 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ /** + * @param UnitRemote + * @param
DataType + * @param StateTypeEnum + * + * @author [Divine Threepwood](mailto:divine@openbase.org) +
*/ +class GenericServiceStateValueTrigger, DT : Message, STE : Enum>( + unitRemote: UR, + targetState: STE, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType +) : AbstractBCOTrigger(unitRemote, targetState, serviceType) { + override fun verifyCondition( + data: DT, + targetState: STE, + serviceType: ServiceTemplateType.ServiceTemplate.ServiceType? + ) { + try { + val serviceState = Services.invokeProviderServiceMethod(serviceType, data) + val method = serviceState.javaClass.getMethod("getValue") + if (method.invoke(serviceState) == targetState) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + } catch (ex: Exception) { + ExceptionPrinter.printHistory("Could not verify condition $this", ex, LOGGER) + } + } +} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/StateObservationService.kt b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/StateObservationService.kt new file mode 100644 index 0000000000..f8e7721e41 --- /dev/null +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/StateObservationService.kt @@ -0,0 +1,68 @@ +package org.openbase.bco.dal.remote.trigger + +import com.google.protobuf.Message +import org.openbase.bco.dal.lib.layer.unit.UnitRemote +import org.openbase.jul.pattern.Observer +import org.openbase.jul.pattern.provider.DataProvider +import org.openbase.jul.pattern.trigger.Trigger +import org.openbase.jul.pattern.trigger.TriggerPriority + +object StateObservationService { + + private val observerMap = mutableMapOf>() + private val lock = Any() + + fun
registerTrigger( + dataObserver: Observer, DT>, + unitRemote: UnitRemote
, + trigger: Trigger, + ) { + synchronized(lock) { + observerMap + .getOrPut(unitRemote.id) { InternalObserver
().also { unitRemote.addDataObserver(it) } } + .let { it as InternalObserver
} + .also { it.registerTrigger(trigger, dataObserver) } + } + } + + fun
removeTrigger( + dataObserver: Observer, DT>, + unitRemote: UnitRemote
, + trigger: Trigger, + ) { + synchronized(lock) { + observerMap[unitRemote.id] + ?.let { it as InternalObserver
} + ?.also { it.removeTrigger(trigger, dataObserver) } + ?.takeIf { it.noSubscription } + ?.also { unitRemote.removeDataObserver(it) } + ?.also { observerMap.remove(unitRemote.id) } + } + } + + private class InternalObserver
: Observer, DT> { + private var highPrioDataObserver = listOf, DT>>() + private var lowPrioDataObserver = listOf, DT>>() + + override fun update(source: DataProvider
, data: DT) { + highPrioDataObserver.forEach { it.update(source, data) } + lowPrioDataObserver.forEach { it.update(source, data) } + } + + fun registerTrigger(trigger: Trigger, observer: Observer, DT>) { + when (trigger.priority) { + TriggerPriority.HIGH -> highPrioDataObserver = highPrioDataObserver.plus(observer) + TriggerPriority.LOW -> lowPrioDataObserver = lowPrioDataObserver.plus(observer) + } + } + + fun removeTrigger(trigger: Trigger, observer: Observer, DT>) { + when (trigger.priority) { + TriggerPriority.HIGH -> highPrioDataObserver = highPrioDataObserver.minus(observer) + TriggerPriority.LOW -> lowPrioDataObserver = lowPrioDataObserver.minus(observer) + } + } + + val noSubscription = highPrioDataObserver.isEmpty() && lowPrioDataObserver.isEmpty() + } +} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/IlluminanceDualBoundaryTrigger.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/IlluminanceDualBoundaryTrigger.kt similarity index 53% rename from module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/IlluminanceDualBoundaryTrigger.java rename to module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/IlluminanceDualBoundaryTrigger.kt index 1856daecab..404b154459 100644 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/IlluminanceDualBoundaryTrigger.java +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/IlluminanceDualBoundaryTrigger.kt @@ -1,4 +1,9 @@ -package org.openbase.bco.dal.remote.trigger.preset; +package org.openbase.bco.dal.remote.trigger.preset + +import com.google.protobuf.Message +import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote +import org.openbase.bco.dal.remote.trigger.GenericDualBoundedDoubleValueTrigger +import org.openbase.type.domotic.service.ServiceTemplateType /*- * #%L @@ -20,22 +25,22 @@ * License along with this program. If not, see * . * #L% - */ -import com.google.protobuf.Message; -import org.openbase.bco.dal.remote.trigger.GenericDualBoundedDoubleValueTrigger; -import org.openbase.bco.dal.remote.layer.unit.AbstractUnitRemote; -import org.openbase.jul.exception.InstantiationException; -import org.openbase.type.domotic.service.ServiceTemplateType.ServiceTemplate.ServiceType; - -/** + */ /** * - * @author Timo Michalski + * @author [Timo Michalski](mailto:tmichalski@techfak.uni-bielefeld.de) * @param UnitRemote * @param
DataType - */ -public class IlluminanceDualBoundaryTrigger, DT extends Message> extends GenericDualBoundedDoubleValueTrigger { - - public IlluminanceDualBoundaryTrigger(UR unitRemote, double upperBoundary, double lowerIllumination, TriggerOperation triggerOperation) throws InstantiationException { - super(unitRemote, upperBoundary, lowerIllumination, triggerOperation, ServiceType.ILLUMINANCE_STATE_SERVICE, "getIlluminance"); - } -} +
*/ +class IlluminanceDualBoundaryTrigger, DT : Message>( + unitRemote: UR, + upperBoundary: Double, + lowerIllumination: Double, + triggerOperation: TriggerOperation? +) : GenericDualBoundedDoubleValueTrigger( + unitRemote, + upperBoundary, + lowerIllumination, + triggerOperation, + ServiceTemplateType.ServiceTemplate.ServiceType.ILLUMINANCE_STATE_SERVICE, + "getIlluminance" +) diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/NeighborConnectionPresenceTrigger.java b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/NeighborConnectionPresenceTrigger.java deleted file mode 100644 index 0e57fb5e5f..0000000000 --- a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/NeighborConnectionPresenceTrigger.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.openbase.bco.dal.remote.trigger.preset; - -/*- - * #%L - * BCO DAL Remote - * %% - * Copyright (C) 2014 - 2021 openbase.org - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * . - * #L% - */ -import org.openbase.bco.dal.remote.layer.unit.connection.ConnectionRemote; -import org.openbase.bco.dal.remote.layer.unit.location.LocationRemote; -import org.openbase.type.domotic.state.ConnectionStateType; -import org.openbase.type.domotic.state.ConnectionStateType.ConnectionState; -import org.openbase.jul.pattern.trigger.AbstractTrigger; -import org.openbase.jul.exception.CouldNotPerformException; -import org.openbase.jul.exception.printer.ExceptionPrinter; -import org.openbase.jul.extension.type.processing.TimestampProcessor; -import org.openbase.jul.pattern.Observer; -import org.openbase.jul.pattern.controller.Remote; -import org.slf4j.LoggerFactory; -import org.openbase.type.domotic.state.ActivationStateType.ActivationState; -import org.openbase.type.domotic.state.DoorStateType.DoorState; -import org.openbase.type.domotic.state.PresenceStateType.PresenceState; -import org.openbase.type.domotic.state.WindowStateType.WindowState; - -/** - * - * @author Timo Michalski - */ -public class NeighborConnectionPresenceTrigger extends AbstractTrigger { - - private final Observer dataObserver; - private final Observer, ConnectionState.State> connectionObserver; - private final LocationRemote locationRemote; - private final ConnectionRemote connectionRemote; - private boolean active = false; - - public NeighborConnectionPresenceTrigger(final LocationRemote locationRemote, final ConnectionRemote connectionRemote) throws org.openbase.jul.exception.InstantiationException { - super(); - - this.locationRemote = locationRemote; - this.connectionRemote = connectionRemote; - - dataObserver = (source, data) -> { - verifyCondition(); - }; - - connectionObserver = (source, data) -> { - if (data.equals(ConnectionStateType.ConnectionState.State.CONNECTED)) { - verifyCondition(); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.UNKNOWN).build())); - } - }; - } - - @Override - public void activate() throws CouldNotPerformException, InterruptedException { - locationRemote.addDataObserver(dataObserver); - connectionRemote.addDataObserver(dataObserver); - locationRemote.addConnectionStateObserver(connectionObserver); - connectionRemote.addConnectionStateObserver(connectionObserver); - active = true; - verifyCondition(); - } - - @Override - public void deactivate() throws CouldNotPerformException, InterruptedException { - locationRemote.removeDataObserver(dataObserver); - connectionRemote.removeDataObserver(dataObserver); - locationRemote.removeConnectionStateObserver(connectionObserver); - connectionRemote.removeConnectionStateObserver(connectionObserver); - active = false; - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.UNKNOWN).build())); - } - - @Override - public boolean isActive() { - return active; - } - - @Override - public void shutdown() { - try { - deactivate(); - } catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } catch (CouldNotPerformException ex) { - ExceptionPrinter.printHistory("Could not shutdown " + this, ex, LoggerFactory.getLogger(getClass())); - } - super.shutdown(); - } - - private void verifyCondition() { - try { - if (locationRemote.getData().getPresenceState().getValue().equals(PresenceState.State.PRESENT) - && (connectionRemote.getDoorState().getValue().equals(DoorState.State.OPEN) - || connectionRemote.getWindowState().getValue().equals(WindowState.State.OPEN))) { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.ACTIVE).build())); - } else { - notifyChange(TimestampProcessor.updateTimestampWithCurrentTime(ActivationState.newBuilder().setValue(ActivationState.State.INACTIVE).build())); - } - } catch (CouldNotPerformException ex) { - ExceptionPrinter.printHistory("Could not verify trigger state " + this, ex, LoggerFactory.getLogger(getClass())); - } - } -} diff --git a/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/NeighborConnectionPresenceTrigger.kt b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/NeighborConnectionPresenceTrigger.kt new file mode 100644 index 0000000000..c53af7bb28 --- /dev/null +++ b/module/dal/remote/src/main/java/org/openbase/bco/dal/remote/trigger/preset/NeighborConnectionPresenceTrigger.kt @@ -0,0 +1,136 @@ +package org.openbase.bco.dal.remote.trigger.preset + +import org.openbase.bco.dal.remote.layer.unit.connection.ConnectionRemote +import org.openbase.bco.dal.remote.layer.unit.location.LocationRemote +import org.openbase.jul.exception.CouldNotPerformException +import org.openbase.jul.exception.printer.ExceptionPrinter +import org.openbase.jul.extension.type.processing.TimestampProcessor +import org.openbase.jul.pattern.Observer +import org.openbase.jul.pattern.controller.Remote +import org.openbase.jul.pattern.provider.DataProvider +import org.openbase.jul.pattern.trigger.AbstractTrigger +import org.openbase.type.domotic.state.* +import org.openbase.type.domotic.unit.connection.ConnectionDataType +import org.openbase.type.domotic.unit.location.LocationDataType +import org.slf4j.LoggerFactory + +/*- + * #%L + * BCO DAL Remote + * %% + * Copyright (C) 2014 - 2021 openbase.org + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ /** + * + * @author [Timo Michalski](mailto:tmichalski@techfak.uni-bielefeld.de) + */ +class NeighborConnectionPresenceTrigger( + private val locationRemote: LocationRemote, + private val connectionRemote: ConnectionRemote +) : AbstractTrigger() { + private val locationObserver: Observer, LocationDataType.LocationData> + private val connectionObserver: Observer, ConnectionDataType.ConnectionData> + private val connectionStateObserver: Observer, ConnectionStateType.ConnectionState.State> + private var active = false + + init { + locationObserver = Observer { _, _ -> verifyCondition() } + connectionObserver = Observer { _, _ -> verifyCondition() } + connectionStateObserver = Observer { _, data: ConnectionStateType.ConnectionState.State -> + if (data == ConnectionStateType.ConnectionState.State.CONNECTED) { + verifyCondition() + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.UNKNOWN + ).build() + ) + ) + } + } + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + override fun activate() { + locationRemote.addDataObserver(locationObserver) + connectionRemote.addDataObserver(connectionObserver) + locationRemote.addConnectionStateObserver(connectionStateObserver) + connectionRemote.addConnectionStateObserver(connectionStateObserver) + active = true + verifyCondition() + } + + @Throws(CouldNotPerformException::class, InterruptedException::class) + override fun deactivate() { + locationRemote.removeDataObserver(locationObserver) + connectionRemote.removeDataObserver(connectionObserver) + locationRemote.removeConnectionStateObserver(connectionStateObserver) + connectionRemote.removeConnectionStateObserver(connectionStateObserver) + active = false + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.UNKNOWN + ).build() + ) + ) + } + + override fun isActive(): Boolean { + return active + } + + override fun shutdown() { + try { + deactivate() + } catch (ex: InterruptedException) { + Thread.currentThread().interrupt() + } catch (ex: CouldNotPerformException) { + ExceptionPrinter.printHistory("Could not shutdown $this", ex, LoggerFactory.getLogger(javaClass)) + } + super.shutdown() + } + + private fun verifyCondition() { + try { + if (locationRemote.data.presenceState.value == PresenceStateType.PresenceState.State.PRESENT && connectionRemote.doorState.value == DoorStateType.DoorState.State.OPEN || connectionRemote.windowState.value == WindowStateType.WindowState.State.OPEN) { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.ACTIVE + ).build() + ) + ) + } else { + notifyChange( + TimestampProcessor.updateTimestampWithCurrentTime( + ActivationStateType.ActivationState.newBuilder().setValue( + ActivationStateType.ActivationState.State.INACTIVE + ).build() + ) + ) + } + } catch (ex: CouldNotPerformException) { + ExceptionPrinter.printHistory( + "Could not verify trigger state $this", + ex, + LoggerFactory.getLogger(javaClass) + ) + } + } +}