コード例 #1
0
def playStream(name, casts=CASTS, volume=None):
    '''
    Play the given stream url.

    :param str name: see _STREAMS
    :param list(ChromeCast) casts:
    :return: boolean True if success; False if stream name is invalid.
    '''

    if None != volume and (volume < 0 or volume > 100):
        raise ValueError('volume must be between 0 and 100')

    url = getStreamUrl(name)
    if None != url:
        for cast in casts:
            if None != volume:
                scope.events.sendCommand(cast.getVolumeName(), str(volume))

            if url == cast.getStreamUrl():
                resume([cast])
            else:
                Audio.playStream(cast.getSinkName(), url)
                cast.setStream(name, url)

        return True
    else:
        PE.logInfo("Missing stream URL for '{0}'".format(name))
        return False
コード例 #2
0
                def armAndSendAlert():
                    # Don't know why list comprehension version like below
                    # doesn't work, Jython just hang on this statement:
                    # if not any(z.isOccupied(elapsedTime) for z in zoneManager.getZones()):
                    # Below is a work around.
                    occupied = False
                    activeDevice = None

                    for z in zoneManager.getZones():
                        if z.isExternal():
                            continue

                        # motion sensor switches off after around 3', need to
                        # that into account.
                        motionDelayInSec = 3 * 60
                        delayTimeInSec = self.maxElapsedTimeInSeconds + motionDelayInSec

                        (occupied, activeDevice) = z.isOccupied([],
                                                                delayTimeInSec)
                        if occupied:
                            break

                    if occupied:
                        PE.logInfo(
                            'Auto-arm cancelled (activities detected @ {}).'.
                            format(activeDevice))
                    else:
                        securityPartitions[0].armAway(events)

                        msg = 'The house has been automatically armed-away (front door closed and no activity)'
                        alert = Alert.createWarningAlert(msg)
                        AlertManager.processAlert(alert, zoneManager)
コード例 #3
0
ファイル: weather.py プロジェクト: yfaway/openhab-rules
def alertIfRainInShortermForecast(event):
    forecasts = EnvCanada.retrieveHourlyForecast('Ottawa', 12)
    rainPeriods = [f for f in forecasts if \
                 'High' == f.getPrecipationProbability() or \
                 'Medium' == f.getPrecipationProbability()]
    if len(rainPeriods) > 0:
        if len(rainPeriods) == 1:
            subject = u"Possible precipation at {}".format(
                rainPeriods[0].getUserFriendlyForecastTime())
        else:
            subject = u"Possible precipation from {} to {}".format(
                rainPeriods[0].getUserFriendlyForecastTime(),
                rainPeriods[-1].getUserFriendlyForecastTime())

        body = u'Forecasts:\n'
        body += u"{:5} {:7} {:25} {:6} {:6}\n".format('Hour: ', 'Celsius',
                                                      'Condition', 'Prob.',
                                                      'Wind')
        for f in forecasts:
            body += unicode(f) + '\n'

        alert = Alert.createInfoAlert(subject, body)
        result = AlertManager.processAlert(alert, zm)
        if not result:
            PE.logInfo('Failed to send rain alert')
コード例 #4
0
def sendAlert(event):
    json = items[_ALERT_ITEM_NAME].toString()
    alert = Alert.fromJson(json)

    if AlertManager.processAlert(alert, zm):
        return True
    else:
        PE.logError('Failed to send alert {}'.format(alert.toString()))
        return False
コード例 #5
0
def onDoorOrWindowsChanged(event):
    triggeringItem = itemRegistry.getItem(event.itemName)

    if PE.isInStateOn(triggeringItem.getState()) \
        or PE.isInStateOpen(triggeringItem.getState()):

        dispatchEvent(ZoneEvent.CONTACT_OPEN, event)
    else:
        dispatchEvent(ZoneEvent.CONTACT_CLOSED, event)
コード例 #6
0
def dispatchEvent(zoneEvent, event, enforceItemInZone = True):
    '''
    Dispatches an event to the ZoneManager. If the event is not processed,
    create a debug log.
    '''
    triggeringItem = itemRegistry.getItem(event.itemName)

    if not _mutableZoneManager.dispatchEvent(zoneEvent, events, triggeringItem, enforceItemInZone):
        PE.logDebug('Event {} for item {} is not processed.'.format(zoneEvent,
                    event.itemName))
コード例 #7
0
def onSwitchIsChanged(event):
    triggeringItem = itemRegistry.getItem(event.itemName)

    if switch_manager.isSwitchOn(triggeringItem):
        if not _mutableZoneManager.onSwitchTurnedOn(events, triggeringItem):
            PE.logDebug('Switch on event for {} is not processed.'.format(
                        event.itemName))
    else:
        if not _mutableZoneManager.onSwitchTurnedOff(events, triggeringItem):
            PE.logDebug('Switch off event for {} is not processed.'.format(
                        event.itemName))
コード例 #8
0
    def startAutoReporWatchDog(self,
                               timerIntervalInSeconds=10 * 60,
                               inactiveIntervalInSeconds=10 * 60):
        '''
        Starts a timer that run every timerIntervalInSeconds. When the timer is
        triggered, it will scan auto-report devices (Devices::isAutoReport),
        and if any of them hasn't been triggered in the last
        inactiveIntervalInSeconds, it will reset the item value.

        This method is safe to call multiple times (a new timer will be started
        and any old timer is cancelled).

        :param int timerIntervalInSeconds: the timer duration
        :param int inactiveIntervalInSeconds: the inactive duration after which
            the device's value will be reset.
        :rtype: None
        '''
        def resetFailedAutoReportDevices():
            devices = []
            for z in self.getZones():
                [devices.append(d) for d in z.getDevices() \
                     if d.isAutoReport() and \
                        not d.wasRecentlyActivated(inactiveIntervalInSeconds)]

            if len(devices) > 0:
                itemNames = []
                for d in devices:
                    itemNames.append(d.getItemName())
                    d.resetValueStates()

                PE.logWarning(
                    "AutoReport Watchdog: {} failed auto-report devices: {}".
                    format(len(devices), itemNames))
            else:
                PE.logDebug(
                    "AutoReport Watchdog: no failed auto-report devices")

            # restart the timer
            self.autoReportWatchDogTimer = Timer(timerIntervalInSeconds,
                                                 resetFailedAutoReportDevices)
            self.autoReportWatchDogTimer.start()

        if None != self.autoReportWatchDogTimer \
                   and self.autoReportWatchDogTimer.isAlive():
            self.autoReportWatchDogTimer.cancel()
            self.autoReportWatchDogTimer = None

        self.autoReportWatchDogTimer = Timer(timerIntervalInSeconds,
                                             resetFailedAutoReportDevices)
        self.autoReportWatchDogTimer.start()
        PE.logInfo("Started auto-report watchdog timer.")
コード例 #9
0
        def turnOffSwitch():
            zone = self.getZoneManager().getContainingZone(self)

            (occupied, device) = zone.isOccupied([Fan, Light], 60)
            if not occupied:
                events.sendCommand(self.getItemName(), "OFF")
                PE.logDebug("{}: turning off {}.".format(
                    zone.getName(), self.getItemName()))
            else:
                self.timer = Timer(self.durationInMinutes * 60, turnOffSwitch)
                self.timer.start()

                PE.logDebug("{}: {} is in use by {}.".format(
                    zone.getName(), self.getItemName(), device))
コード例 #10
0
def playAnnouncementAndMusicInTheMorning(event):
    global morningMusicStartCount
    global inMorningSession

    if isInMorningTimeRange() and \
            morningMusicStartCount < MAX_MORNING_MUSIC_START_COUNT:
        if not inMorningSession:
            PE.logInfo('{} Playing morning annoucement.'.format(LOG_PREFIX))
            inMorningSession = True
            msg = getMorningAnnouncement()
            casts = cast_manager.getFirstFloorCasts()

            cast_manager.playMessage(msg, casts)
            cast_manager.playStream("WWFM Classical", casts, 35)
            morningMusicStartCount += 1
コード例 #11
0
    def onAction(self, eventInfo):
        zone = eventInfo.getZone()
        zoneManager = eventInfo.getZoneManager()

        securityPartitions = zoneManager.getDevicesByType(AlarmPartition)
        if len(securityPartitions) == 0:
            return False

        if not securityPartitions[0].isArmedAway():
            return False

        # Get an audio sink from the first floor.
        audioSink = None
        zones = [
            z for z in zoneManager.getZones()
            if z.getLevel() == Level.FIRST_FLOOR
        ]
        for z in zones:
            sinks = z.getDevicesByType(ChromeCastAudioSink)
            if len(sinks) > 0:
                audioSink = sinks[0]
                break

        if None == audioSink:
            return False

        activities = zoneManager.getDevicesByType(ActivityTimes)
        if len(activities) > 0:
            if activities[0].isSleepTime():
                return False

        audioSink.playStream(self.musicUrl, self.musicVolume)

        if None != self.timer:
            self.timer.cancel()

        durationInSeconds = self.playDurationInSeconds
        if None == durationInSeconds:
            durationInSeconds = random.randint(3 * 60, 10 * 60)

        self.timer = Timer(durationInSeconds, lambda: audioSink.pause())
        self.timer.start()

        PE.logInfo(
            "Simulate daytime presence by playing music for {} seconds".format(
                durationInSeconds))

        return True
コード例 #12
0
 def isTriggered(self):
     '''
     :return: true if the gas sensor has detected a high level of
          concentration
     :rtype: bool
     '''
     return PE.isInStateOn(self.stateItem.getState())
コード例 #13
0
def _checkAndSendAlert(zoneManager, checkFunction, deviceTypeString, thresholdInSeconds):
    inactiveDevices = checkFunction(zm, thresholdInSeconds)

    if len(inactiveDevices) > 0:
        subject = "{} inactive {} devices".format(
                len(inactiveDevices), deviceTypeString)
        body = "The following devices haven't triggered "\
               "in the last {} hours\r\n  - ".format(
                       thresholdInSeconds / 3600)
        body += "\r\n  - ".join(inactiveDevices)

        alert = Alert.createInfoAlert(subject, body)
        if not AlertManager.processAdminAlert(alert):
            PE.logInfo('Failed to send inactive {} device alert'.format(deviceTypeString))
    else:
        PE.logInfo("No inactive {} devices detected.".format(deviceTypeString))
コード例 #14
0
    def __init__(self, prefix, sinkName):
        '''
        Ctor

        :param str prefix: the item name prefix, as defined in the .item file. By\
            convention, other channels of this device will have this naming \
            pattern: {prefix}Idling, {prefix}Title, {prefix}Player, and so on.
        :param str sinkName: the sink name for voice and audio play. The sink \
            name can be retrieved by running "openhab-cli console" and then \
            "smarthome:audio sinks".
        :raise ValueError: if any parameter is invalid
        '''
        Device.__init__(self, PE.createStringItem(
                    'Chromecast-{}-{}'.format(prefix, sinkName)))

        self.sinkName = sinkName
        self.prefix = prefix
        self.streamUrl = None
        self.lastTtsMessage = None

        self._testMode = False
        self._testLastCommand = None

        self._lastCommandTimestamp = time.time()
        self._lastCommand = None
コード例 #15
0
    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)))
コード例 #16
0
    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)))
コード例 #17
0
 def getIlluminanceLevel(self):
     '''
     Returns an positive integer representing the LUX value.
     '''
     if PE.isStateAvailable(self.getItem().getState()):
         return self.getItem().getState().intValue()
     else:
         return 0
コード例 #18
0
ファイル: alert_manager.py プロジェクト: yfaway/openhab-rules
    def processAlert(alert, zoneManager=None):
        '''
        Processes the provided alert.
        If the alert's level is WARNING or CRITICAL, the TTS subject will be played
        on the ChromeCasts.

        :param Alert alert: the alert to be processed
        :param ImmutableZoneManager zoneManager: used to retrieve the ActivityTimes
        :return: True if alert was processed; False otherwise.
        :raise: ValueError if alert is None
        '''

        if None == alert:
            raise ValueError('Invalid alert.')

        PE.logInfo(u"Processing alert\n{}".format(alert.toString()))

        if AlertManager._isThrottled(alert):
            return False

        if not alert.isAudioAlertOnly():
            AlertManager._emailAlert(alert,
                                     AlertManager._getOwnerEmailAddresses())

        # Play an audio message if the alert is warning or critical.
        # Determine the volume based on the current zone activity.
        volume = 0
        if alert.isCriticalLevel():
            volume = 60
        elif alert.isWarningLevel():
            if None == zoneManager:
                volume = 60
            else:
                activity = zoneManager.getDevicesByType(ActivityTimes)[0]
                if activity.isSleepTime():
                    volume = 0
                elif activity.isQuietTime():
                    volume = 40
                else:
                    volume = 60

        if volume > 0:
            casts = cast_manager.getAllCasts()
            cast_manager.playMessage(alert.getSubject(), casts, volume)

        return True
コード例 #19
0
    def getWattage(self):
        '''
        :return: the current wattage of the plug
        :rtype: int or None if the plug has no power reading
        '''
        if None == self.powerReadingItem:
            raise ValueError("Plug has no power reading capability")

        return PE.getIntegerStateValue(self.powerReadingItem, 0)
コード例 #20
0
    def onAction(self, eventInfo):
        zone = eventInfo.getZone()
        zoneManager = eventInfo.getZoneManager()

        currentEpoch = time.time()

        doorOpenPeriodInSeconds = 10
        for door in zone.getDevicesByType(Door):
            if door.wasRecentlyActivated(doorOpenPeriodInSeconds):
                PE.logInfo(
                    "A door was just open for zone {}; ignore motion event.".
                    format(zone.getName()))
                return

        cameras = zone.getDevicesByType(Camera)
        if len(cameras) == 0:
            PE.logInfo("No camera found for zone {}".format(zone.getName()))
            return

        camera = cameras[0]
        if not camera.hasMotionEvent():
            PE.logInfo(
                "Camera doesn't indicate motion event; likely a false positive PIR event."
            )
            return

        time.sleep(10)  # wait for a bit to retrieve more images

        offsetSeconds = 5
        maxNumberOfSeconds = 15
        attachmentUrls = camera.getSnapshotUrls(currentEpoch,
                                                maxNumberOfSeconds,
                                                offsetSeconds)

        if len(attachmentUrls) > 0:
            timeStruct = time.localtime()
            hour = timeStruct[3]

            msg = 'Activity detected at the {} area.'.format(
                zone.getName(), len(attachmentUrls))

            if SM.isArmedAway(zm) or hour <= 6:
                alert = Alert.createWarningAlert(msg, None, attachmentUrls)
            else:
                alert = Alert.createAudioWarningAlert(msg)

            AlertManager.processAlert(alert)

            return True
        else:
            PE.logInfo("No images from {} camera.".format(zone.getName()))

        return False
コード例 #21
0
ファイル: alert_manager.py プロジェクト: yfaway/openhab-rules
    def processAdminAlert(alert):
        '''
        Processes the provided alert by sending an email to the administrator.

        :param Alert alert: the alert to be processed
        :return: True if alert was processed; False otherwise.
        :raise: ValueError if alert is None
        '''

        if None == alert:
            raise ValueError('Invalid alert.')

        PE.logInfo(u"Processing admin alert\n{}".format(alert.toString()))

        if AlertManager._isThrottled(alert):
            return False

        AlertManager._emailAlert(alert, AlertManager._getAdminEmailAddresses())

        return True
コード例 #22
0
def retrieveSnapshots(itemPrefix, snapshotCount):
    '''
    Retrieve the supplied number of snapshots.

    :param str itemPrefix: the camera item prefix; the items Image and\
    UpdateImage are created from the prefix.
    :param int snapshotCount: the # of snapshot images to retrieve
    :return: list of snapshot URLs
    :rtype: list(str)
    '''
    attachmentUrls = []

    imageItemName = itemPrefix + '_Image'
    updateItemName = itemPrefix + '_UpdateImage'

    PE.logInfo('Retrieving {} snapshots'.format(snapshotCount))
    previousRawBytes = []
    for idx in range(snapshotCount):
        # Flip the state of the update channel to force retrieval of new image
        if scope.items[updateItemName] == scope.OnOffType.ON:
            scope.events.sendCommand(updateItemName, "OFF")
        else:
            scope.events.sendCommand(updateItemName, "ON")

        time.sleep(_WAIT_TIME_AFTER_FORCE_IMAGE_UPDATE_IN_SECONDS)

        imageState = scope.items[imageItemName]
        if scope.UnDefType.UNDEF != imageState and scope.UnDefType.NULL != imageState:
            rawBytes = imageState.getBytes()
            if rawBytes != previousRawBytes:
                fileName = '{}/{}-{}.jpg'.format(_SNAPSHOT_PATH, itemPrefix,
                                                 idx)
                file = io.open(fileName, 'wb')
                file.write(rawBytes)
                file.close()

                attachmentUrls.append('file://' + fileName)

                previousRawBytes = rawBytes

    return attachmentUrls
コード例 #23
0
    def resume(self):
        '''
        Resumes playing.
        '''

        if self._testMode:
            self._testLastCommand = 'resume'
            return

        if PE.isInStateOn(scope.items[self.getIdleItemName()]):
            Audio.playStream(self.getSinkName(), self.getStreamUrl())
        else:
            Audio.playStream(self.getSinkName(), self.getStreamUrl())
            scope.events.sendCommand(self.getPlayerName(), "PLAY")
コード例 #24
0
        def resetFailedAutoReportDevices():
            devices = []
            for z in self.getZones():
                [devices.append(d) for d in z.getDevices() \
                     if d.isAutoReport() and \
                        not d.wasRecentlyActivated(inactiveIntervalInSeconds)]

            if len(devices) > 0:
                itemNames = []
                for d in devices:
                    itemNames.append(d.getItemName())
                    d.resetValueStates()

                PE.logWarning(
                    "AutoReport Watchdog: {} failed auto-report devices: {}".
                    format(len(devices), itemNames))
            else:
                PE.logDebug(
                    "AutoReport Watchdog: no failed auto-report devices")

            # restart the timer
            self.autoReportWatchDogTimer = Timer(timerIntervalInSeconds,
                                                 resetFailedAutoReportDevices)
            self.autoReportWatchDogTimer.start()
コード例 #25
0
    def __init__(self, timeRangeMap):
        '''
        Ctor

        :param dictionary timeRangeMap: a map from activity string to time \
            range string \
            The supported activities are 'lunch', 'dinner', 'sleep', 'quiet', \
            'wakeup'.
            A time range string can be a single or multiple \
            ranges in the 24-hour format.\
            Example: '10-12', or '6-9, 7-7, 8:30 - 14:45', or '19 - 8' \
            (wrap around)
        :raise ValueError: if any parameter is invalid
        '''
        Device.__init__(self, PE.createStringItem('ActivityTimesItem'))

        acceptableKeys = ['lunch', 'dinner', 'sleep', 'quiet', 'wakeup']
        for key in timeRangeMap.keys():
            if key not in acceptableKeys:
                raise ValueError('Invalid time range key {}'.format(key))

        self.timeRangeMap = timeRangeMap
コード例 #26
0
ファイル: motion_sensor.py プロジェクト: yfaway/openhab-rules
 def isOn(self):
     '''
     Returns true if the motion sensor's state is on; false otherwise.
     '''
     return PE.isInStateOn(self.getItem().getState())
コード例 #27
0
        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())


PE.runUnitTest(LightTest)
コード例 #28
0
 def isOn(self):
     '''
     Returns true if the TV is on; false otherwise.
     '''
     return PE.isInStateOn(self.getItem().getState())
コード例 #29
0
def isInVacation(items):
    '''
    :param scope.items items:
    :return: True if the house is set to vacation mode.
    '''
    return PE.isInStateOn(items['VT_In_Vacation'])
コード例 #30
0
 def isOn(self):
     '''
     :return: True if the partition is in alarm; False otherwise
     :rtype: bool
     '''
     return PE.isInStateOn(self.getItem().getState())