def setUp(self):
        super(TurnOffAdjacentZonesTest, self).setUp()

        [self.lightItem1, self.lightItem2, self.lightItem3,
         self.fanItem] = self.getItems()

        self.light1 = Light(self.lightItem1, 5)
        self.light2 = Light(self.lightItem2, 5)
        self.light3 = Light(self.lightItem3, 5, ILLUMINANCE_THRESHOLD_IN_LUX,
                            False, "0-23:59")  # always stay on
        self.fan = Fan(self.fanItem, 5)

        self.washroom = Zone('washroom', [self.light1])
        self.shower = Zone('shower', [self.fan])
        self.lobby = Zone('lobby', [self.light2])
        self.foyer = Zone('foyer', [self.light3])
        self.zoneManager = MockedZoneManager(
            [self.washroom, self.shower, self.lobby, self.foyer])

        self.lobby = self.lobby.addNeighbor(
            Neighbor(self.foyer.getId(), NeighborType.OPEN_SPACE))

        self.washroom = self.washroom.addNeighbor(
            Neighbor(self.lobby.getId(), NeighborType.OPEN_SPACE))
        self.washroom = self.washroom.addNeighbor(
            Neighbor(self.shower.getId(), NeighborType.OPEN_SPACE))
Exemplo n.º 2
0
    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())
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
class TurnOffDevicesOnAlarmModeChangeTest(DeviceTest):
    def setUp(self):
        super(TurnOffDevicesOnAlarmModeChangeTest, self).setUp()

        self.audioSink = ChromeCastAudioSink('prefix', 'sinkName')
        self.partition = AlarmPartition(ITEMS[1], ITEMS[2])
        self.light = Light(ITEMS[3], ITEMS[4])

        self.action = TurnOffDevicesOnAlarmModeChange()

        self.audioSink._setTestMode()

        self.audioSink.playStream("http://stream")
        self.light.turnOn(self.getMockedEventDispatcher())
        self.partition.disarm(self.getMockedEventDispatcher())

    def getItems(self, resetState=False):
        return ITEMS

    def testOnAction_armedAwayEvent_turnOffDevicesAndReturnsTrue(self):
        (zone, zm,
         eventInfo) = self.createTestData(ZoneEvent.PARTITION_ARMED_AWAY)
        self.assertTrue(zone.isLightOn())

        self.invokeActionAndAssertDevicesTurnedOff(zone, eventInfo)

    def testOnAction_disarmEvent_turnOffDevicesAndReturnsTrue(self):
        (zone, zm, eventInfo) = self.createTestData(
            ZoneEvent.PARTITION_DISARMED_FROM_AWAY)
        self.assertTrue(zone.isLightOn())

        self.invokeActionAndAssertDevicesTurnedOff(zone, eventInfo)

    def invokeActionAndAssertDevicesTurnedOff(self, zone, eventInfo):
        value = self.action.onAction(eventInfo)
        self.assertTrue(value)

        self.assertFalse(zone.isLightOn())
        self.assertEqual("pause", self.audioSink._getLastTestCommand())

    def createTestData(self, zoneEvent):
        '''
        :return: a list of two zones, the mocked zone manager, and the event dispatcher
        :rtype: list
        '''

        self.partition.armAway(self.getMockedEventDispatcher())

        zone = Zone('porch', [self.partition, self.light, self.audioSink])
        zm = MockedZoneManager([zone])
        eventInfo = EventInfo(zoneEvent, ITEMS[0], zone, zm,
                              self.getMockedEventDispatcher())

        return [zone, zm, eventInfo]
Exemplo n.º 5
0
    def __init__(self, masterControlItem, effectItem, primaryColorItem,
                 secondaryColorItem, durationInMinutes):
        '''
        Constructs a new object.

        :raise ValueError: if any parameter is invalid
        '''
        Light.__init__(self, masterControlItem, durationInMinutes, 0, True)

        self.effectItem = effectItem
        self.effectTimer = None
        self.primaryColorItem = primaryColorItem
        self.secondaryColorItem = secondaryColorItem
Exemplo n.º 6
0
    def setUp(self):
        super(TurnOffDevicesOnAlarmModeChangeTest, self).setUp()

        self.audioSink = ChromeCastAudioSink('prefix', 'sinkName')
        self.partition = AlarmPartition(ITEMS[1], ITEMS[2])
        self.light = Light(ITEMS[3], ITEMS[4])

        self.action = TurnOffDevicesOnAlarmModeChange()

        self.audioSink._setTestMode()

        self.audioSink.playStream("http://stream")
        self.light.turnOn(self.getMockedEventDispatcher())
        self.partition.disarm(self.getMockedEventDispatcher())
Exemplo n.º 7
0
    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())
Exemplo n.º 8
0
    def setUp(self):
        super(ZoneManagerTest, self).setUp()

        [
            self.lightItem, self.motionSensorItem, self.illuminanceSensorItem,
            self.astroSensorItem, self.dimmerItem, self.fanItem
        ] = self.getItems()

        self.illuminanceSensor = IlluminanceSensor(self.illuminanceSensorItem)
        self.light = Light(self.lightItem, 2, ILLUMINANCE_THRESHOLD_IN_LUX)
        self.motionSensor = MotionSensor(self.motionSensorItem)
        self.astroSensor = AstroSensor(self.astroSensorItem)
        self.dimmer = Dimmer(self.dimmerItem, 2, 100, "0-23:59")
        self.fan = Fan(self.fanItem, 2)

        self.zm = ZoneManager()
Exemplo n.º 9
0
    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])
Exemplo n.º 10
0
    def __init__(self,
                 switchItem,
                 durationInMinutes,
                 dimLevel=5,
                 timeRanges=None,
                 illuminanceLevel=None,
                 disableTrigeringFromMotionSensor=False,
                 noPrematureTurnOffTimeRange=None):
        '''
        Constructs a new object.

        :raise ValueError: if any parameter is invalid
        '''
        Light.__init__(self, switchItem, durationInMinutes, illuminanceLevel,
                       disableTrigeringFromMotionSensor,
                       noPrematureTurnOffTimeRange)

        if dimLevel < 0 or dimLevel > 100:
            raise ValueError('dimLevel must be between 0 and 100 inclusive')

        time_utilities.stringToTimeRangeLists(timeRanges)  # validate

        self.dimLevel = dimLevel
        self.timeRanges = timeRanges
Exemplo n.º 11
0
 def testIsLowIlluminance_currentIlluminanceBelowThreshold_returnsTrue(
         self):
     self.light = Light(self.lightItem, 10, 50)
     self.assertTrue(self.light.isLowIlluminance(10))
Exemplo n.º 12
0
 def testIsLowIlluminance_currentIlluminanceAboveThreshold_returnsFalse(
         self):
     self.light = Light(self.lightItem, 10, 50)
     self.assertFalse(self.light.isLowIlluminance(60))
Exemplo n.º 13
0
 def testIsLowIlluminance_currentIlluminanceNotAvailable_returnsFalse(self):
     self.light = Light(self.lightItem, 10, 50)
     self.assertFalse(self.light.isLowIlluminance(-1))
Exemplo n.º 14
0
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())
Exemplo n.º 15
0
    def _createSwitches(self, deviceName, openHabItem, zone, itemRegistry,
                        neighbors):
        itemName = openHabItem.getName()
        zoneId = zone.getId()

        if 'LightSwitch' == deviceName:
            # open space relationship
            turnOffMeta = MetadataRegistry.get(
                MetadataKey(META_TURN_OFF_OTHER_LIGHT, itemName))
            if None != turnOffMeta:
                neighborZoneId = self._getZoneIdFromItemName(turnOffMeta.value)

                neighbor = [zoneId, neighborZoneId, NeighborType.OPEN_SPACE]
                neighbors.append(neighbor)

            # master-slave open space relationship
            masterSlaveMeta = MetadataRegistry.get(
                MetadataKey(
                    META_DISABLE_MOTION_TRIGGERING_IF_OTHER_LIGHT_IS_ON,
                    itemName))
            if None != masterSlaveMeta:
                masterZoneId = self._getZoneIdFromItemName(
                    masterSlaveMeta.value)

                neighborForward = [
                    masterZoneId, zoneId, NeighborType.OPEN_SPACE_SLAVE
                ]
                neighbors.append(neighborForward)

                neighborReverse = [
                    zoneId, masterZoneId, NeighborType.OPEN_SPACE_MASTER
                ]
                neighbors.append(neighborReverse)

            # noPrematureTurnOffTimeRange
            noPrematureTurnOffTimeRange = None
            noPrematureTurnOffTimeRangeMeta = MetadataRegistry.get(
                MetadataKey(META_NO_PREMATURE_TURN_OFF_TIME_RANGE, itemName))
            if None != noPrematureTurnOffTimeRangeMeta:
                noPrematureTurnOffTimeRange = noPrematureTurnOffTimeRangeMeta.value

            disableMotionSensorTriggering = openHabItem.hasTag(
                TAG_DISABLE_TRIGGERING_FROM_MOTION_SENSOR)

            durationMeta = MetadataRegistry.get(
                MetadataKey('durationInMinutes', itemName))
            if None != durationMeta:
                durationInMinutes = int(durationMeta.value)
            else:
                raise ValueError(
                    'Missing durationInMinutes value for {}'.format(itemName))

            # dimmer setting
            meta = MetadataRegistry.get(
                MetadataKey(META_DIMMING_SETTING, itemName))
            if None != meta:
                config = meta.configuration
                level = config['level'].intValue()
                timeRanges = config['timeRanges']

                switch = Dimmer(openHabItem, durationInMinutes, level,
                                timeRanges, ILLUMINANCE_THRESHOLD_IN_LUX,
                                disableMotionSensorTriggering,
                                noPrematureTurnOffTimeRange)
            else:
                switch = Light(openHabItem, durationInMinutes,
                               ILLUMINANCE_THRESHOLD_IN_LUX,
                               disableMotionSensorTriggering,
                               noPrematureTurnOffTimeRange)

            return switch
        elif 'FanSwitch' == deviceName:
            durationMeta = MetadataRegistry.get(
                MetadataKey('durationInMinutes', itemName))
            if None != durationMeta:
                durationInMinutes = int(durationMeta.value)
            else:
                raise ValueError(
                    'Missing durationInMinutes value for {}'.format(itemName))

            return Fan(openHabItem, durationInMinutes)
        elif 'Wled_MasterControls' in deviceName:
            effectItem = itemRegistry.getItem(
                itemName.replace('MasterControls', 'FX'))
            primaryColorItem = itemRegistry.getItem(
                itemName.replace('MasterControls', 'Primary'))
            secondaryColorItem = itemRegistry.getItem(
                itemName.replace('MasterControls', 'Secondary'))

            durationMeta = MetadataRegistry.get(
                MetadataKey('durationInMinutes', itemName))
            if None != durationMeta:
                durationInMinutes = int(durationMeta.value)
            else:
                raise ValueError(
                    'Missing durationInMinutes value for {}'.format(itemName))

            return Wled(openHabItem, effectItem, primaryColorItem,
                        secondaryColorItem, durationInMinutes)

        elif 'LightSwitch_Illuminance' == deviceName:
            return IlluminanceSensor(openHabItem)
        elif deviceName.endswith('MotionSensor'):
            return MotionSensor(openHabItem)

        return None
Exemplo n.º 16
0
class ZoneTest(DeviceTest):
    def setUp(self):
        super(ZoneTest, self).setUp()

        [
            self.lightItem, self.motionSensorItem, self.illuminanceSensorItem,
            self.astroSensorItem, self.dimmerItem, self.fanItem, self.plugItem,
            self.plugPowerItem
        ] = self.getItems()

        self.illuminanceSensor = IlluminanceSensor(self.illuminanceSensorItem)
        self.light = Light(self.lightItem, 2)
        self.lightWithIlluminance = Light(self.lightItem, 2,
                                          ILLUMINANCE_THRESHOLD_IN_LUX)
        self.motionSensor = MotionSensor(self.motionSensorItem)
        self.astroSensor = AstroSensor(self.astroSensorItem)
        self.dimmer = Dimmer(self.dimmerItem, 2, 100, "0-23:59")
        self.fan = Fan(self.lightItem, 2)

    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 testZoneCtor_validParams_gettersReturnValidValues(self):
        zoneName = 'bed room'
        zone = Zone(zoneName, [self.light], Level.SECOND_FLOOR)
        self.assertEqual(zoneName, zone.getName())
        self.assertEqual(Level.SECOND_FLOOR, zone.getLevel())
        self.assertEqual(
            str(Level.SECOND_FLOOR) + '_' + zoneName, zone.getId())
        self.assertEqual(1, len(zone.getDevices()))

    def testCreateExternalZone_validParams_returnsAnExternalZone(self):
        zoneName = 'bed room'
        zone = Zone.createExternalZone(zoneName)
        self.assertEqual(zoneName, zone.getName())
        self.assertTrue(zone.isExternal())

    def testCreateFirstFloorZone_validParams_returnsAFirstFloorZone(self):
        zoneName = 'bed room'
        zone = Zone.createFirstFloorZone(zoneName)
        self.assertEqual(zoneName, zone.getName())
        self.assertEqual(Level.FIRST_FLOOR, zone.getLevel())
        self.assertFalse(zone.isExternal())

    def testCreateSecondFloorZone_validParams_returnsASecondFloorZone(self):
        zoneName = 'bed room'
        zone = Zone.createSecondFloorZone(zoneName)
        self.assertEqual(zoneName, zone.getName())
        self.assertEqual(Level.SECOND_FLOOR, zone.getLevel())
        self.assertFalse(zone.isExternal())

    def testContainsOpenHabItem_negativeValue_returnsFalse(self):
        zone = Zone('name', [self.light], Level.SECOND_FLOOR)
        self.assertFalse(zone.containsOpenHabItem(self.fanItem))

    def testContainsOpenHabItem_validNameButWrongType_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor, self.astroSensor])
        self.assertFalse(zone.containsOpenHabItem(self.lightItem,
                                                  MotionSensor))

    def testContainsOpenHabItem_validNameWithNoTypeSpecified_returnsTrue(self):
        zone = Zone('ff', [self.light, self.motionSensor, self.astroSensor])
        self.assertTrue(zone.containsOpenHabItem(self.lightItem))

    def testContainsOpenHabItem_validNameWithTypeSpecified_returnsTrue(self):
        zone = Zone('ff', [self.light, self.motionSensor, self.astroSensor])
        self.assertTrue(zone.containsOpenHabItem(self.lightItem, Light))

    def testAddDevice_validDevice_deviceAdded(self):
        zone = Zone('ff').addDevice(self.light)
        self.assertEqual(1, len(zone.getDevices()))

    def testRemoveDevice_validDevice_deviceRemoved(self):
        zone = Zone('ff', [self.light])
        self.assertEqual(1, len(zone.getDevices()))

        zone = zone.removeDevice(self.light)
        self.assertEqual(0, len(zone.getDevices()))

    def testGetDevicesByType_validType_returnsExpectedDevices(self):
        zone = Zone('ff', [self.light])
        self.assertEqual(1, len(zone.getDevicesByType(Light)))
        self.assertEqual(0, len(zone.getDevicesByType(Dimmer)))

    def testGetDeviceByEvent_validEvent_returnsExpectedDevice(self):
        zone = Zone('ff', [self.light])

        eventInfo = EventInfo(ZoneEvent.MOTION, self.lightItem, zone,
                              MockedZoneManager([zone]),
                              self.getMockedEventDispatcher())
        self.assertEqual(self.light, zone.getDeviceByEvent(eventInfo))

    def testGetDeviceByEvent_invalidEvent_returnsNone(self):
        zone = Zone('ff', [self.light])

        eventInfo = EventInfo(ZoneEvent.MOTION, self.motionSensorItem, zone,
                              MockedZoneManager([zone]),
                              self.getMockedEventDispatcher())
        self.assertEqual(None, zone.getDeviceByEvent(eventInfo))

    def testAddAction_oneValidAction_actionAdded(self):
        zone = Zone('ff').addAction(TurnOnSwitch())
        self.assertEqual(1, len(zone.getActions(ZoneEvent.MOTION)))

        self.assertEqual(0, len(zone.getActions(ZoneEvent.SWITCH_TURNED_ON)))

    def testAddAction_twoValidAction_actionAdded(self):
        zone = Zone('ff').addAction(TurnOnSwitch())
        zone = zone.addAction(TurnOffAdjacentZones())
        self.assertEqual(1, len(zone.getActions(ZoneEvent.MOTION)))
        self.assertEqual(1, len(zone.getActions(ZoneEvent.SWITCH_TURNED_ON)))

    def testIsOccupied_everythingOff_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        (occupied, device) = zone.isOccupied()
        self.assertFalse(occupied)
        self.assertEqual(None, device)

    def testIsOccupied_switchIsOn_returnsTrue(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.light.turnOn(self.getMockedEventDispatcher())

        (occupied, device) = zone.isOccupied()
        self.assertTrue(occupied)
        self.assertEqual(self.light, device)

    def testIsOccupied_switchIsOnAndIgnoreMotionSensor_returnsTrue(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.light.turnOn(self.getMockedEventDispatcher())

        (occupied, device) = zone.isOccupied([MotionSensor])
        self.assertTrue(occupied)
        self.assertEqual(self.light, device)

    def testIsOccupied_switchIsOnAndIgnoreLight_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.light.turnOn(self.getMockedEventDispatcher())

        (occupied, device) = zone.isOccupied([Light])
        self.assertFalse(occupied)
        self.assertEqual(None, device)

    def testIsOccupied_switchIsOnAndIgnoreLightAndMotionSensor_returnsFalse(
            self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.light.turnOn(self.getMockedEventDispatcher())

        (occupied, device) = zone.isOccupied([Light, MotionSensor])
        self.assertFalse(occupied)
        self.assertEqual(None, device)

    def testIsOccupied_motionEventTriggeredButLightIsOff_returnsTrue(self):
        self.assertFalse(self.light.isOn())

        zone = Zone('ff',
                    [self.light, self.motionSensor, self.illuminanceSensor])
        self.motionSensor._updateLastActivatedTimestamp()
        (occupied, device) = zone.isOccupied()
        self.assertTrue(occupied)
        self.assertEqual(self.motionSensor, device)

    def testGetIlluminanceLevel_noSensor_returnsMinusOne(self):
        zone = Zone('ff', [self.lightWithIlluminance, self.motionSensor])
        self.assertEqual(-1, zone.getIlluminanceLevel())

    def testGetIlluminanceLevel_withSensor_returnsPositiveValue(self):
        self.illuminanceSensorItem.setState(
            DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX))

        zone = Zone('ff', [
            self.lightWithIlluminance, self.motionSensor,
            self.illuminanceSensor
        ])
        self.assertEqual(ILLUMINANCE_THRESHOLD_IN_LUX,
                         zone.getIlluminanceLevel())

    def testIsLightOnTime_noSensor_returnsNone(self):
        zone = Zone('ff', [self.lightWithIlluminance, self.motionSensor])
        self.assertEqual(None, zone.isLightOnTime())

    def testIsLightOnTime_withSensorIndicatesDayTime_returnsFalse(self):
        self.astroSensorItem.setState(StringType('MORNING'))
        zone = Zone('ff', [self.lightWithIlluminance, self.astroSensor])
        self.assertFalse(zone.isLightOnTime())

    def testIsLightOnTime_withSensorIndicatesEveningTime_returnsTrue(self):
        self.astroSensorItem.setState(StringType(
            AstroSensor.LIGHT_ON_TIMES[0]))
        zone = Zone('ff', [self.lightWithIlluminance, self.astroSensor])
        self.assertTrue(zone.isLightOnTime())

    def testShareSensorWith_noSharedSensors_returnsFalse(self):
        zone1 = Zone('ff', [self.lightWithIlluminance, self.astroSensor])
        zone2 = Zone('foyer', [])

        self.assertFalse(zone1.shareSensorWith(zone2, Light))

    def testShareSensorWith_sharedSensorsWithNoChannel_returnsFalse(self):
        zone1 = Zone('ff', [self.lightWithIlluminance, self.astroSensor])
        zone2 = Zone('foyer', [self.lightWithIlluminance])

        self.assertFalse(zone1.shareSensorWith(zone2, Light))

    def testShareSensorWith_sharedSensorsWithChannel_returnsTrue(self):
        zone1 = Zone('ff', [self.lightWithIlluminance, self.astroSensor])
        zone2 = Zone('foyer', [self.lightWithIlluminance])

        self.lightWithIlluminance.getChannel = lambda: 'a channel'
        self.assertTrue(zone1.shareSensorWith(zone2, Light))

    def testOnTimerExpired_invalidTimerItem_returnsFalse(self):
        zone = Zone('ff', [self.light])

        isProcessed = zone.onTimerExpired(self.getMockedEventDispatcher(),
                                          PE.createStringItem('dummy name'))
        self.assertFalse(isProcessed)

    def testOnSwitchedTurnedOn_validItemName_returnsTrue(self):
        zone = Zone('ff', [self.light])

        isProcessed = zone.onSwitchTurnedOn(self.getMockedEventDispatcher(),
                                            self.lightItem, None)
        self.assertTrue(isProcessed)

    def testOnSwitchedTurnedOff_validItemName_returnsTrue(self):

        zone = Zone('ff', [self.light])

        isProcessed = zone.onSwitchTurnedOff(self.getMockedEventDispatcher(),
                                             self.lightItem, None)
        self.assertTrue(isProcessed)

    def testOnMotionSensorTurnedOn_validItemNameNoIlluminanceSensorNoAstroSensor_returnsFalse(
            self):
        self.assertFalse(self.light.isOn())

        zone = Zone('ff', [self.light, self.motionSensor])
        zone = zone.addAction(TurnOnSwitch())

        isProcessed = zone.dispatchEvent(ZoneEvent.MOTION,
                                         self.getMockedEventDispatcher(),
                                         self.motionSensor.getItem(),
                                         MockedZoneManager([zone]), True)
        self.assertFalse(isProcessed)

    def testOnMotionSensorTurnedOn_illuminanceAboveThreshold_returnsFalse(
            self):
        self.assertFalse(self.light.isOn())
        self.illuminanceSensorItem.setState(
            DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX + 1))

        zone = Zone('ff', [
            self.lightWithIlluminance, self.motionSensor,
            self.illuminanceSensor
        ])
        zone = zone.addAction(TurnOnSwitch())

        isProcessed = zone.dispatchEvent(ZoneEvent.MOTION,
                                         self.getMockedEventDispatcher(),
                                         self.motionSensor.getItem(),
                                         MockedZoneManager([zone]), True)
        self.assertFalse(isProcessed)
        self.assertFalse(self.light.isOn())

    def testOnMotionSensorTurnedOn_illuminanceBelowThreshold_turnsOnLight(
            self):
        self.assertFalse(self.light.isOn())
        self.illuminanceSensorItem.setState(
            DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1))

        zone = Zone('ff', [
            self.lightWithIlluminance, self.motionSensor,
            self.illuminanceSensor
        ])
        zone = zone.addAction(TurnOnSwitch())

        isProcessed = zone.dispatchEvent(ZoneEvent.MOTION,
                                         self.getMockedEventDispatcher(),
                                         self.motionSensor.getItem(),
                                         MockedZoneManager([zone]), True)
        self.assertTrue(isProcessed)

        self.assertTrue(self.light.isOn())

    def testOnMotionSensorTurnedOn_notLightOnTime_returnsFalse(self):
        self.astroSensorItem.setState(StringType('MORNING'))

        zone = Zone('ff', [self.light, self.astroSensor])
        zone = zone.addAction(TurnOnSwitch())

        isProcessed = zone.dispatchEvent(ZoneEvent.MOTION,
                                         self.getMockedEventDispatcher(),
                                         self.motionSensor.getItem(), None,
                                         True)
        self.assertFalse(isProcessed)

    def testOnMotionSensorTurnedOn_notLightOnTimeButIlluminanceBelowThreshold_turnsOnLight(
            self):
        self.assertFalse(self.light.isOn())
        self.illuminanceSensorItem.setState(
            DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1))
        self.astroSensorItem.setState(StringType('MORNING'))

        zone = Zone('ff', [
            self.lightWithIlluminance, self.motionSensor,
            self.illuminanceSensor, self.astroSensor
        ])
        zone = zone.addAction(TurnOnSwitch())

        isProcessed = zone.dispatchEvent(ZoneEvent.MOTION,
                                         self.getMockedEventDispatcher(),
                                         self.motionSensor.getItem(),
                                         MockedZoneManager([zone]), True)
        self.assertTrue(isProcessed)
        self.assertTrue(self.light.isOn())

    def testOnMotionSensorTurnedOn_lightOnTime_turnsOnLight(self):
        self.assertFalse(self.light.isOn())

        self.astroSensorItem.setState(StringType(
            AstroSensor.LIGHT_ON_TIMES[0]))
        zone = Zone('ff', [self.light, self.motionSensor, self.astroSensor])
        zone = zone.addAction(TurnOnSwitch())

        isProcessed = zone.dispatchEvent(ZoneEvent.MOTION,
                                         self.getMockedEventDispatcher(),
                                         self.motionSensor.getItem(),
                                         MockedZoneManager([zone]), True)
        self.assertTrue(isProcessed)
        self.assertTrue(self.light.isOn())

    def testStr_noParam_returnsNonEmptyString(self):
        zone = Zone('ff', [
            self.light, self.motionSensor, self.astroSensor,
            self.illuminanceSensor, self.dimmer, self.fan
        ])
        info = str(zone)

        self.assertTrue(len(info) > 0)

    def testGetNeighborZones_noZoneManager_throwsException(self):
        zone1 = Zone('ff')
        with self.assertRaises(ValueError) as cm:
            zone1.getNeighborZones(None)

        self.assertEqual('zoneManager must not be None', cm.exception.args[0])

    def testGetNeighborZones_noNeighborTypesSpecified_returnsCorrectList(self):
        zone1 = Zone('foyer')
        zone2 = Zone('porch')
        zone3 = Zone('office')

        zone1 = zone1.addNeighbor(
            Neighbor(zone2.getId(), NeighborType.OPEN_SPACE))
        zone1 = zone1.addNeighbor(
            Neighbor(zone3.getId(), NeighborType.OPEN_SPACE_MASTER))
        zm = MockedZoneManager([zone1, zone2, zone3])

        self.assertEqual(2, len(zone1.getNeighborZones(zm)))

    def testGetNeighborZones_neighborTypeSpecified_returnsCorrectList(self):
        zone1 = Zone('foyer')
        zone2 = Zone('porch')
        zone3 = Zone('office')

        zone1 = zone1.addNeighbor(
            Neighbor(zone2.getId(), NeighborType.OPEN_SPACE))
        zone1 = zone1.addNeighbor(
            Neighbor(zone3.getId(), NeighborType.OPEN_SPACE_MASTER))
        zm = MockedZoneManager([zone1, zone2, zone3])

        zones = zone1.getNeighborZones(zm, [NeighborType.OPEN_SPACE_MASTER])
        self.assertEqual(1, len(zones))
        self.assertEqual(zone3, zones[0])
Exemplo n.º 17
0
class ZoneManagerTest(DeviceTest):
    def setUp(self):
        super(ZoneManagerTest, self).setUp()

        [
            self.lightItem, self.motionSensorItem, self.illuminanceSensorItem,
            self.astroSensorItem, self.dimmerItem, self.fanItem
        ] = self.getItems()

        self.illuminanceSensor = IlluminanceSensor(self.illuminanceSensorItem)
        self.light = Light(self.lightItem, 2, ILLUMINANCE_THRESHOLD_IN_LUX)
        self.motionSensor = MotionSensor(self.motionSensorItem)
        self.astroSensor = AstroSensor(self.astroSensorItem)
        self.dimmer = Dimmer(self.dimmerItem, 2, 100, "0-23:59")
        self.fan = Fan(self.fanItem, 2)

        self.zm = ZoneManager()

    def tearDown(self):
        pass

    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 testAddZone_validZone_zoneAdded(self):
        zone1 = Zone('ff')
        self.zm.addZone(zone1)
        self.assertEqual(1, len(self.zm.getZones()))

        zone2 = Zone('2f')
        self.zm.addZone(zone2)
        self.assertEqual(2, len(self.zm.getZones()))

    def testGetZoneById_validZoneId_returnValidZone(self):
        zone1 = Zone('ff')
        self.zm.addZone(zone1)

        zone2 = Zone('2f')
        self.zm.addZone(zone2)

        self.assertEqual(zone1.getName(),
                         self.zm.getZoneById(zone1.getId()).getName())
        self.assertEqual(zone2.getName(),
                         self.zm.getZoneById(zone2.getId()).getName())

    def testGetZoneById_invalidZoneId_returnNone(self):
        self.assertTrue(None == self.zm.getZoneById('invalid zone id'))

    def testRemoveZone_validZone_zoneRemoved(self):
        zone1 = Zone('ff')
        self.zm.addZone(zone1)

        zone2 = Zone('2f')
        self.zm.addZone(zone2)

        self.assertEqual(2, len(self.zm.getZones()))

        self.zm.removeZone(zone1)
        self.assertEqual(1, len(self.zm.getZones()))

        self.zm.removeZone(zone2)
        self.assertEqual(0, len(self.zm.getZones()))

    def testContainingZone_validDevice_returnsCorrectZone(self):
        zone1 = Zone('ff').addDevice(self.light)
        zone2 = Zone('sf').addDevice(self.fan)

        self.zm.addZone(zone1)
        self.zm.addZone(zone2)
        self.assertEqual(
            zone1,
            self.zm._createImmutableInstance().getContainingZone(self.light))
        self.assertEqual(
            zone2,
            self.zm._createImmutableInstance().getContainingZone(self.fan))

    def testContainingZone_invalidDevice_returnsNone(self):
        zone1 = Zone('ff').addDevice(self.light)

        self.zm.addZone(zone1)
        self.assertEqual(
            None,
            self.zm._createImmutableInstance().getContainingZone(self.fan))

    def testGetDevicesByType_variousScenarios_returnsCorrectList(self):
        zone1 = Zone('ff').addDevice(self.light)
        zone2 = Zone('sf').addDevice(self.fan)

        self.zm.addZone(zone1)
        self.zm.addZone(zone2)
        self.assertEqual(2, len(self.zm.getZones()))

        self.assertEqual(1, len(self.zm.getDevicesByType(Light)))
        self.assertEqual(2, len(self.zm.getDevicesByType(Switch)))

        self.assertEqual(0, len(self.zm.getDevicesByType(AstroSensor)))

    def testOnMotionSensorTurnedOn_noZone_returnsFalse(self):
        self.assertFalse(
            self.zm.dispatchEvent(ZoneEvent.MOTION, scope.events,
                                  PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnMotionSensorTurnedOn_withNonApplicableZone_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.zm.addZone(zone)

        self.assertFalse(
            self.zm.dispatchEvent(ZoneEvent.MOTION, scope.events,
                                  PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnMotionSensorTurnedOn_withApplicableZone_returnsTrue(self):
        self.assertFalse(self.light.isOn())
        self.illuminanceSensorItem.setState(
            DecimalType(ILLUMINANCE_THRESHOLD_IN_LUX - 1))

        zone = Zone('ff',
                    [self.light, self.motionSensor, self.illuminanceSensor])
        zone = zone.addAction(TurnOnSwitch())
        self.zm.addZone(zone)

        self.assertTrue(
            self.zm.dispatchEvent(ZoneEvent.MOTION, scope.events,
                                  self.motionSensor.getItem()))

    def testOnTimerExpired_noZone_returnsFalse(self):
        self.assertFalse(
            self.zm.onTimerExpired(scope.events,
                                   PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnTimerExpired_withNonApplicableZone_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.zm.addZone(zone)

        self.assertFalse(
            self.zm.onTimerExpired(scope.events,
                                   PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnSwitchTurnedOn_noZone_returnsFalse(self):
        self.assertFalse(
            self.zm.onSwitchTurnedOn(scope.events,
                                     PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnSwitchTurnedOn_withNonApplicableZone_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.zm.addZone(zone)

        self.assertFalse(
            self.zm.onSwitchTurnedOn(scope.events,
                                     PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnSwitchTurnedOn_withApplicableZone_returnsTrue(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.zm.addZone(zone)

        self.assertTrue(
            self.zm.onSwitchTurnedOn(scope.events, self.light.getItem()))

    def testOnSwitchTurnedOff_noZone_returnsFalse(self):
        self.assertFalse(
            self.zm.onSwitchTurnedOff(scope.events,
                                      PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnSwitchTurnedOff_withNonApplicableZone_returnsFalse(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.zm.addZone(zone)

        self.assertFalse(
            self.zm.onSwitchTurnedOff(scope.events,
                                      PE.createStringItem(INVALID_ITEM_NAME)))

    def testOnSwitchTurnedOff_withApplicableZone_returnsTrue(self):
        zone = Zone('ff', [self.light, self.motionSensor])
        self.zm.addZone(zone)

        self.assertTrue(
            self.zm.onSwitchTurnedOff(scope.events, self.light.getItem()))
Exemplo n.º 18
0
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])