class LightTest(unittest.TestCase): def setUp(self): scope.itemRegistry.remove(LIGHT_SWITCH_NAME) scope.itemRegistry.remove(TIMER_NAME) self.lightItem = SwitchItem(LIGHT_SWITCH_NAME) scope.itemRegistry.add(self.lightItem) self.lightItem.setState(scope.OnOffType.OFF) self.light = Light(self.lightItem, 10) def tearDown(self): scope.itemRegistry.remove(self.lightItem.getName()) def testTurnOn_lightWasOff_returnsExpected(self): self.light.turnOn(MockedEventDispatcher(scope.itemRegistry)) self.assertEqual(scope.OnOffType.ON, self.lightItem.getState()) def testTurnOn_lightWasAlreadyOn_timerIsRenewed(self): self.lightItem.setState(scope.OnOffType.ON) self.assertFalse(self.light._isTimerActive()) self.light.turnOn(MockedEventDispatcher(scope.itemRegistry)) self.assertEqual(scope.OnOffType.ON, self.lightItem.getState()) self.assertTrue(self.light._isTimerActive()) def testOnSwitchTurnedOn_validParams_timerIsTurnedOn(self): self.lightItem.setState(scope.OnOffType.ON) isProcessed = self.light.onSwitchTurnedOn( MockedEventDispatcher(scope.itemRegistry), self.lightItem.getName()) self.assertTrue(isProcessed) self.assertTrue(self.light._isTimerActive()) def testOnSwitchTurnedOn_invalidItemName_returnsFalse(self): isProcessed = self.light.onSwitchTurnedOn( MockedEventDispatcher(scope.itemRegistry), "wrong name") self.assertFalse(isProcessed) def testTurnOff_bothLightAndTimerOn_timerIsRenewed(self): self.lightItem.setState(scope.OnOffType.ON) self.light._startTimer(MockedEventDispatcher(scope.itemRegistry)) self.assertTrue(self.light._isTimerActive()) self.light.turnOff(MockedEventDispatcher(scope.itemRegistry)) self.assertFalse(self.light._isTimerActive()) def testOnSwitchTurnedOff_validParams_timerIsTurnedOn(self): self.lightItem.setState(scope.OnOffType.ON) self.light._startTimer(MockedEventDispatcher(scope.itemRegistry)) isProcessed = self.light.onSwitchTurnedOff( MockedEventDispatcher(scope.itemRegistry), self.lightItem.getName()) self.assertTrue(isProcessed) self.assertFalse(self.light._isTimerActive()) def testOnSwitchTurnedOff_invalidItemName_returnsFalse(self): isProcessed = self.light.onSwitchTurnedOff( MockedEventDispatcher(scope.itemRegistry), "wrong name") self.assertFalse(isProcessed) def testIsLowIlluminance_noThresholdSet_returnsFalse(self): self.assertFalse(self.light.isLowIlluminance(10)) def testIsLowIlluminance_currentIlluminanceNotAvailable_returnsFalse(self): self.light = Light(self.lightItem, 10, 50) self.assertFalse(self.light.isLowIlluminance(-1)) def testIsLowIlluminance_currentIlluminanceAboveThreshold_returnsFalse( self): self.light = Light(self.lightItem, 10, 50) self.assertFalse(self.light.isLowIlluminance(60)) def testIsLowIlluminance_currentIlluminanceBelowThreshold_returnsTrue( self): self.light = Light(self.lightItem, 10, 50) self.assertTrue(self.light.isLowIlluminance(10)) def testTimerTurnedOff_validParams_switchIsOff(self): zm = ZoneManager() self.light = Light(self.lightItem, 0.004) # makes it 0.24 sec self.light = self.light.setZoneManager(zm._createImmutableInstance()) zone = Zone('ff', [self.light]) zm.addZone(zone) self.lightItem.setState(scope.OnOffType.ON) self.light._startTimer(MockedEventDispatcher(scope.itemRegistry)) self.assertTrue(self.light._isTimerActive()) time.sleep(0.3) self.assertFalse(self.light._isTimerActive()) self.assertFalse(self.light.isOn())
class TurnOnSwitchTest(DeviceTest): def setUp(self): super(TurnOnSwitchTest, self).setUp() [ self.lightItem1, self.lightItem2, self.illuminanceSensorItem, self.motionSensorItem1, self.motionSensorItem2, self.lightItem3 ] = self.getItems() self.illuminanceSensor = IlluminanceSensor(self.illuminanceSensorItem) self.light1 = Light(self.lightItem1, 30, ILLUMINANCE_THRESHOLD_IN_LUX) self.light2 = Light(self.lightItem2, 30, ILLUMINANCE_THRESHOLD_IN_LUX) self.light3 = Light(self.lightItem3, 30, ILLUMINANCE_THRESHOLD_IN_LUX) self.motionSensor1 = MotionSensor(self.motionSensorItem1) self.motionSensor2 = MotionSensor(self.motionSensorItem2) self.zone1 = Zone( 'great room', [self.light1, self.illuminanceSensor, self.motionSensor1]) self.zone2 = Zone( 'kitchen', [self.light2, self.illuminanceSensor, self.motionSensor2]) self.zone3 = Zone('foyer', [self.light3, self.illuminanceSensor]) def getItems(self, resetState=False): if resetState: for item in ITEMS: if isinstance(item, SwitchItem): item.setState(scope.OnOffType.OFF) elif isinstance(item, SwitchItem): item.setState(UndefState) return ITEMS def testOnAction_illuminanceBelowThreshold_turnsOnLight(self): self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) self.assertTrue(self.turnOn()) def testOnAction_illuminanceAboveThreshold_returnsFalse(self): self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX + 1)) self.assertFalse(self.turnOn()) def testOnAction_renewTimerIfLightIsAlreadyOnEvenIfIlluminanceIsAboveThreshold_returnsTrue( self): self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX + 1)) self.light1.turnOn(self.getMockedEventDispatcher()) self.assertTrue(self.turnOn()) def testOnAction_switchDisablesTriggeringByMotionSensor_returnsFalse(self): self.light1 = Light(self.lightItem1, 30, ILLUMINANCE_THRESHOLD_IN_LUX, True) self.zone1 = Zone('foyer', [self.light1, self.illuminanceSensor]) self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) self.assertFalse(self.turnOn()) def testOnAction_switchWasJustTurnedOff_returnsFalse(self): self.light1.onSwitchTurnedOff(self.getMockedEventDispatcher(), self.light1.getItemName()) self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) self.assertFalse(self.turnOn()) def testOnAction_adjacentZoneWasNotOn_returnsTrue(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE, True) # shared channel self.motionSensor1.getChannel = lambda: 'a channel' self.motionSensor2.getChannel = lambda: 'a channel' self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) self.assertTrue(self.turnOn()) def testOnAction_adjacentZoneWasJustTurnedOff_returnsFalse(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE, True) # shared channel self.motionSensor1.getChannel = lambda: 'a channel' self.motionSensor2.getChannel = lambda: 'a channel' self.light2.onSwitchTurnedOff(self.getMockedEventDispatcher(), self.light2.getItemName()) self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) self.assertFalse(self.turnOn()) def testOnAction_openSpaceMasterNeighborIsOn_returnsFalse(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE_MASTER, True) self.assertFalse(self.turnOn()) def testOnAction_openSpaceMasterNeighborIsOff_returnsFalse(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE_MASTER, False) self.assertTrue(self.turnOn()) def testOnAction_openSpaceNeighborIsOn_returnsTrueAndTurnOffNeighbor(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE, True) self.assertTrue(self.zone2.isLightOn()) self.assertTrue(self.turnOn()) self.assertFalse(self.zone2.isLightOn()) def testOnAction_openSpaceNeighborIsOff_returnsTrue(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE, False) self.assertFalse(self.zone2.isLightOn()) self.assertTrue(self.turnOn()) self.assertTrue(self.zone1.isLightOn()) self.assertFalse(self.zone2.isLightOn()) def testOnAction_openSpaceSlaveNeighborIsOn_returnsTrueAndTurnOffNeighbor( self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE_SLAVE, True) self.assertTrue(self.zone2.isLightOn()) self.assertTrue(self.turnOn()) self.assertFalse(self.zone2.isLightOn()) def testOnAction_openSpaceSlaveNeighborIsOff_returnsTrue(self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE_SLAVE, False) self.assertFalse(self.zone2.isLightOn()) self.assertTrue(self.turnOn()) self.assertTrue(self.zone1.isLightOn()) self.assertFalse(self.zone2.isLightOn()) def testOnAction_renewTimerWhenBothMasterAndSlaveAreOn_returnsTrueAndNotTurningOffNeighbor( self): self.setUpNeighborRelationship(self.zone2, NeighborType.OPEN_SPACE_SLAVE, True) self.lightItem1.setState(scope.OnOffType.ON) self.assertTrue(self.turnOn()) self.assertTrue(self.zone2.isLightOn()) def testOnAction_masterIsOn_returnsTrueAndNotTurningOffOpenSpaceNeighbor( self): self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) # zone3 (foyer) is an open space neighbor with zone2 self.zone2 = self.zone2.addNeighbor( Neighbor(self.zone3.getId(), NeighborType.OPEN_SPACE)) # zone2 (kitchen) is an open space slave with zone1 (great room) self.zone2 = self.zone2.addNeighbor( Neighbor(self.zone1.getId(), NeighborType.OPEN_SPACE_MASTER)) # Turn on the light in the great room and the foyer. # We want to make sure that when the motion sensor in the kitchen is # triggered, it won't be turn on, and also the foyer light must not # be turned off. # The rationale is that someone just open the door to come to the foyer # area. However, as the great room light was already on, that indicates # someone is already in that area. As such, any movement in that # area must not prematurely turn off the the foyer light. self.lightItem1.setState(scope.OnOffType.ON) self.lightItem3.setState(scope.OnOffType.ON) eventInfo = EventInfo(ZoneEvent.MOTION, ITEMS[0], self.zone2, self.createMockedZoneManager(), self.getMockedEventDispatcher()) returnVal = TurnOnSwitch().onAction(eventInfo) self.assertFalse(returnVal) self.assertFalse(self.zone2.isLightOn()) self.assertTrue(self.zone3.isLightOn()) def turnOn(self): eventInfo = EventInfo(ZoneEvent.MOTION, ITEMS[0], self.zone1, self.createMockedZoneManager(), self.getMockedEventDispatcher()) return TurnOnSwitch().onAction(eventInfo) # Helper method to set up the relationship between the provided zone and zone1. def setUpNeighborRelationship(self, zone, type, neighborLightOn): self.illuminanceSensorItem.setState( DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1)) self.zone1 = self.zone1.addNeighbor(Neighbor(zone.getId(), type)) if neighborLightOn: self.lightItem2.setState(scope.OnOffType.ON) def createMockedZoneManager(self): return MockedZoneManager([self.zone1, self.zone2, self.zone3])