Example #1
0
def getTheSensor(lbl,
                 never_assume_dead=False,
                 getHighest=False,
                 getLowest=False):
    # Each sensor entry in the configuration file can be a a single item name or a python list where you can
    # define multiple sensor names. The first sensor in that list that has reported within the value set in
    # sensor_dead_after_mins will be used. (Unless never_assume_dead is set to True)
    # When "getHighest" argument is set to True, the sensor name with the highest value is picked.
    # When "getlowest" argument is set to True, the sensor name with the lowest value is picked.

    sensor_dead_after_mins = weatherStationUploader_configuration[
        'sensor_dead_after_mins']  # The time after which a sensor is presumed to be dead

    def isSensorAlive(sName):
        if getLastUpdate(ir.getItem(sName)).isAfter(
                DateTime.now().minusMinutes(sensor_dead_after_mins)):
            return True
        else:
            weatherStationUploader.log.warn(
                "Sensor device {} has not reported since: {}".format(
                    sName,
                    format_date(getLastUpdate(ir.getItem(sName)),
                                customDateTimeFormats['dateTime'])))
            return False

    sensorName = None
    if lbl in weatherStationUploader_configuration[
            'sensors'] and weatherStationUploader_configuration['sensors'][
                lbl] is not None:
        tSens = weatherStationUploader_configuration['sensors'][lbl]
        if isinstance(tSens, list):
            _highestValue = 0
            _lowestValue = 999999999
            for s in tSens:
                if s is None:
                    break
                # Get the first sensor that is not dead and find the sensor with the highest or the lowest value if requested
                if never_assume_dead or isSensorAlive(s):
                    if getHighest:
                        _itemValue = getItemValue(s, 0)
                        if _itemValue > _highestValue:
                            _highestValue = _itemValue
                            sensorName = s
                    elif getLowest:
                        _itemValue = getItemValue(s, 0)
                        if _itemValue < _lowestValue:
                            _lowestValue = _itemValue
                            sensorName = s
                    else:
                        sensorName = s
                        break
        else:
            if never_assume_dead or isSensorAlive(tSens):
                sensorName = tSens

    if sensorName is not None:
        weatherStationUploader.log.debug("Device used for {}: {}".format(
            lbl, sensorName))
    return sensorName
    def __init__(self, parent, zoneNumber, cfg):
        '''
        Initialise the IdeAlarmZone class

        Expects:
         - Parent object
         - zoneNumber (integer) The zone's ordinal number
         - cfg (dictionary) The zone's configuration dictionary
        '''
        self._armingMode = None
        self._zoneStatus = None
        self.zoneNumber = zoneNumber
        self.alertDevices = cfg['alertDevices']
        self.name = cfg['name']
        self.armAwayToggleSwitch = cfg['armAwayToggleSwitch']
        self.armHomeToggleSwitch = cfg['armHomeToggleSwitch']
        self.mainZone = cfg['mainZone']
        self.canArmWithTrippedSensors = cfg['canArmWithTrippedSensors']
        self.alarmTestMode = parent.alarmTestMode
        self.parent = weakref.ref(parent)  # <= garbage-collector safe!
        self.log = logging.getLogger(u"{}.IdeAlarmZone.Zone.{}".format(
            LOG_PREFIX, self.zoneNumber))
        self.sensors = []
        for sensor in cfg['sensors']:
            self.sensors.append(IdeAlarmSensor(self, sensor))
        self.armingModeItem = cfg['armingModeItem']
        self.statusItem = cfg['statusItem']

        self.openSections = self.countOpenSections()
        self.setArmingMode(
            getItemValue(self.armingModeItem, ARMINGMODE['DISARMED'])
        )  # Will also set the zone status to normal
        self.log.info(
            u"ideAlarm Zone {} initialized with {} open sensors".format(
                self.name.decode('utf8'), self.openSections))
    def onSensorChange(self, sensor):
        '''
        Called whenever an enabled sensor has tripped ON or OPEN
        '''
        if self.getArmingMode() not in [ARMINGMODE['ARMED_HOME'], ARMINGMODE['ARMED_AWAY']] \
        or self.getZoneStatus() not in [ZONESTATUS['NORMAL']] \
        or (self.getArmingMode() == ARMINGMODE['ARMED_HOME'] and sensor.sensorClass == 'B') \
        or getItemValue("Z{}_Exit_Timer".format(self.zoneNumber), scope.OFF) == scope.ON:
            self.log.info(u"{} was tripped, but we are ignoring it".format(
                sensor.name.decode('utf8')))
            return

        self.setZoneStatus(ZONESTATUS['TRIPPED'])
        self.log.info(u"{} was tripped, starting entry timer".format(
            sensor.name.decode('utf8')))
        postUpdateCheckFirst("Z{}_Entry_Timer".format(self.zoneNumber),
                             scope.ON)
Example #4
0
def greeting():
    # To use this, you should set up astro.py as described
    # here https://github.com/OH-Jython-Scripters/Script%20Examples/astro.py
    # It will take care of updating the item 'V_TimeOfDay' for you
    # You can customize and/or translate these greetings in your configuration file.
    timeOfDay = getItemValue('V_TimeOfDay', TIMEOFDAY['DAY'])
    try:
        from configuration import timeofdayGreetings
    except ImportError:
        # No customized greetings found in configuration file. We use the following english greetings then
        timeofdayGreetings = {
            0: 'Good night',
            1: 'Good morning',
            2: 'Good day',
            3: 'Good evening'
        }
    if timeOfDay in timeofdayGreetings:
        return timeofdayGreetings[timeOfDay]
    else:
        return 'good day'
def weatherStationUploader(event):
    weatherStationUploader.log.setLevel(weatherStationUploader_configuration['logLevel'])
    global wu_second_count
    if (not weatherStationUploader_configuration['stationdata']['weather_upload']) \
    or (weatherStationUploader_configuration['stationdata']['weather_upload'] and wu_second_count%weatherStationUploader_configuration['stationdata']['upload_frequency_seconds'] == 0):
        if weatherStationUploader_configuration['stationdata']['weather_upload']:
            weatherStationUploader.log.debug('Uploading data to Weather Underground')
        else:
            weatherStationUploader.log.debug('No data to will be upladed to Weather Underground')

        sdf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
        dateutc = sdf.print(DateTime.now((DateTimeZone.UTC)))

        tempf = None
        temp = None
        sensorName = getTheSensor('tempc', getLowest=True)
        if sensorName is not None:
            temp = Temp(getItemValue(sensorName, 0.0), 'c') # Outdoor temp, c - celsius, f - fahrenheit, k - kelvin
            tempf = str(round(temp.f, 1))

        soiltempf = None
        sensorName = getTheSensor('soiltempc')
        if sensorName is not None:
            _temp = Temp(getItemValue(sensorName, 0.0), 'c') # Soil temp, c - celsius, f - fahrenheit, k - kelvin
            soiltempf = str(round(_temp.f, 1))

        humidity = None
        sensorName = getTheSensor('humidity')
        if sensorName is not None:
            humidity = getItemValue(sensorName, 0.0)

        dewptf = None
        heatidxf = None
        if humidity is not None and temp is not None:
            dewptf = str(round(dew_point(temperature=temp, humidity=humidity).f, 1)) # calculate Dew Point
            heatidxf = str(round(heat_index(temperature=temp, humidity=humidity).f, 1)) # calculate Heat Index

        pressure = None
        sensorName = getTheSensor('pressurembar')
        if sensorName is not None:
            _mbar = getItemValue(sensorName, 0)
            if ((_mbar < 1070) and (_mbar > 920)): 
                pressure = str(mbar_to_inches_mercury(_mbar))

        rainin = None
        sensorName = getTheSensor('rainhour', never_assume_dead=True)
        if sensorName is not None:
            rainin = str(mm_to_inch(getItemValue(sensorName, 0.0)))

        dailyrainin = None
        sensorName = getTheSensor('raintoday', never_assume_dead=True)
        if sensorName is not None:
            dailyrainin = str(mm_to_inch(getItemValue(sensorName, 0.0)))

        soilmoisture = None
        sensorName = getTheSensor('soilmoisture')
        if sensorName is not None:
            soilmoisture = str(int(round(getItemValue(sensorName, 0.0) * 100 / 1023)))

        winddir = None
        sensorName = getTheSensor('winddir')
        if sensorName is not None:
            winddir = str(getItemValue(sensorName, 0))

        windspeedmph = None
        sensorName = getTheSensor('windspeedms')
        if sensorName is not None:
            windspeedmph = str(ms_to_mph(getItemValue(sensorName, 0.0)))

        windgustmph = None
        sensorName = getTheSensor('windgustms')
        if sensorName is not None:
            windgustmph = str(ms_to_mph(getItemValue(sensorName, 0.0)))

        windgustdir = None
        sensorName = getTheSensor('windgustdir')
        if sensorName is not None:
            windgustdir = str(getItemValue(sensorName, 0))

        windspdmph_avg2m = None
        sensorName = getTheSensor('windspeedms_avg2m')
        if sensorName is not None:
            windspdmph_avg2m = str(ms_to_mph(getItemValue(sensorName, 0.0)))

        winddir_avg2m = None
        sensorName = getTheSensor('winddir_avg2m')
        if sensorName is not None:
            winddir_avg2m = str(getItemValue(sensorName, 0))

        windgustmph_10m = None
        sensorName = getTheSensor('windgustms_10m')
        if sensorName is not None:
            windgustmph_10m = str(ms_to_mph(getItemValue(sensorName, 0.0)))

        windgustdir_10m = None
        sensorName = getTheSensor('windgustdir_10m')
        if sensorName is not None:
            windgustdir_10m = str(getItemValue(sensorName, 0))

        solarradiation = None
        sensorName = getTheSensor('solarradiation', getHighest=True)
        if sensorName is not None:
            solarradiation = str(lux_to_watts_m2(getItemValue(sensorName, 0)))

        # From http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol

        cmd = 'curl -s -G "' + WU_URL + '" ' \
            + '--data-urlencode "action=updateraw" ' \
            + ('--data-urlencode "realtime=1" ' if weatherStationUploader_configuration['stationdata']['rapid_fire_mode'] else '') \
            + ('--data-urlencode "rtfreq='+str(weatherStationUploader_configuration['stationdata']['upload_frequency_seconds'])+'" ' if weatherStationUploader_configuration['stationdata']['rapid_fire_mode'] else '') \
            + '--data-urlencode "ID='+weatherStationUploader_configuration['stationdata']['station_id']+'" ' \
            + '--data-urlencode "PASSWORD='******'stationdata']['station_key']+'" ' \
            + '--data-urlencode "dateutc='+dateutc+'" ' \
            + '--data-urlencode "softwaretype=openHAB" '
        weatherStationUploader.log.debug("")

        if weatherStationUploader_configuration['stationdata']['weather_upload']:
            weatherStationUploader.log.debug("Below is the weather data that we will send:")
        else:
            weatherStationUploader.log.debug("Below is the weather data that we would send (if weather_upload was enabled):")

        if tempf is not None:
            cmd += '--data-urlencode "tempf='+tempf+'" '
            weatherStationUploader.log.debug("tempf: "+tempf)
        if humidity is not None:
            cmd += '--data-urlencode "humidity='+str(humidity)+'" '
            weatherStationUploader.log.debug("humidity: "+str(humidity))
        if dewptf is not None:
            cmd += '--data-urlencode "dewptf='+dewptf+'" '
            weatherStationUploader.log.debug("dewptf: "+dewptf)
        if heatidxf is not None:
            cmd += '--data-urlencode "heatidxf='+heatidxf+'" '
            weatherStationUploader.log.debug("heatidxf: "+heatidxf)
        if soiltempf is not None:
            cmd += '--data-urlencode "soiltempf='+soiltempf+'" '
            weatherStationUploader.log.debug("soiltempf: "+soiltempf)
        if soilmoisture is not None:
            cmd += '--data-urlencode "soilmoisture='+soilmoisture+'" '
            weatherStationUploader.log.debug("soilmoisture: "+soilmoisture)
        if pressure is not None:
            cmd += '--data-urlencode "baromin='+pressure+'" '
            weatherStationUploader.log.debug("baromin: "+pressure)
        if rainin is not None:
            cmd += '--data-urlencode "rainin='+rainin+'" '
            weatherStationUploader.log.debug("rainin: "+rainin)
        if dailyrainin is not None:
            cmd += '--data-urlencode "dailyrainin='+dailyrainin+'" '
            weatherStationUploader.log.debug("dailyrainin: "+dailyrainin)
        if winddir is not None:
            cmd += '--data-urlencode "winddir='+winddir+'" '
            weatherStationUploader.log.debug("winddir: "+winddir)
        if windspeedmph is not None:
            cmd += '--data-urlencode "windspeedmph='+windspeedmph+'" '
            weatherStationUploader.log.debug("windspeedmph: "+windspeedmph)
        if windgustmph is not None:
            cmd += '--data-urlencode "windgustmph='+windgustmph+'" '
            weatherStationUploader.log.debug("windgustmph: "+windgustmph)
        if windgustdir is not None:
            cmd += '--data-urlencode "windgustdir='+windgustdir+'" '
            weatherStationUploader.log.debug("windgustdir: "+windgustdir)
        if windspdmph_avg2m is not None:
            cmd += '--data-urlencode "windspdmph_avg2m='+windspdmph_avg2m+'" '
            weatherStationUploader.log.debug("windspdmph_avg2m: "+windspdmph_avg2m)
        if winddir_avg2m is not None:
            cmd += '--data-urlencode "winddir_avg2m='+winddir_avg2m+'" '
            weatherStationUploader.log.debug("winddir_avg2m: "+winddir_avg2m)
        if windgustmph_10m is not None:
            cmd += '--data-urlencode "windgustmph_10m='+windgustmph_10m+'" '
            weatherStationUploader.log.debug("windgustmph_10m: "+windgustmph_10m)
        if windgustdir_10m is not None:
            cmd += '--data-urlencode "windgustdir_10m='+windgustdir_10m+'" '
            weatherStationUploader.log.debug("windgustdir_10m: "+windgustdir_10m)
        if solarradiation is not None:
            cmd += '--data-urlencode "solarradiation='+solarradiation+'" '
            weatherStationUploader.log.debug("solarradiation: "+solarradiation)
        cmd += ' 1>/dev/null 2>&1 &'
        weatherStationUploader.log.debug("")

        if weatherStationUploader_configuration['stationdata']['weather_upload']:
            weatherStationUploader.log.debug("WeatherUpload version {}, performing an upload. (second count is: {})".format(__version__, wu_second_count))
            weatherStationUploader.log.debug("cmd: {}".format(cmd))
            os.system(cmd)
    else:
        weatherStationUploader.log.debug("WeatherUpload version {}, skipping upload. (second count is: {})".format(__version__, wu_second_count))

    if (wu_second_count%weatherStationUploader_configuration['stationdata']['upload_frequency_seconds'] == 0):
        wu_second_count = 0
    wu_second_count = wu_second_count + 10 # Corresponding to CronTrigger(EVERY_10_SECONDS)
def tts(ttsSay, ttsPrio=PRIO['MODERATE'], **keywords):
    '''
    Text To Speak function. First argument is positional and mandatory.
    Remaining arguments are optionally keyword arguments.

    Examples:
        .. code-block::

            tts("Hello")
            tts("Hello", PRIO['HIGH'], ttsRoom='Kitchen', ttsVol=42, ttsLang='en-GB', ttsVoice='Brian')

    Args:
        ttsSay (str): text to speak
        ttsPrio (str): (optional) priority as defined by PRIO (defaults to
            PRIO['MODERATE'])
        **keywords: ``ttsRoom`` (room to speak in), ``ttsVol`` (volume),
            ``ttsLang`` (language), ``ttsVoice`` (voice), ``ttsEngine``
            (engine)

    Returns:
        bool: ``True``, if sound was sent, else ``False``
    '''
    log = logging.getLogger(LOG_PREFIX + ".community.sonos.speak")

    def getDefaultRoom():
        # Search for the default room to speak in
        for the_key, the_value in sonos['rooms'].iteritems():
            if the_value['defaultttsdevice']:
                return the_key
        return 'All'

    if getItemValue(customItemNames['allowTTSSwitch'],
                    scope.ON) != scope.ON and ttsPrio <= PRIO['MODERATE']:
        log.info(
            u"[{}] is OFF and ttsPrio is too low to speak [{}] at this moment".
            format(customItemNames['allowTTSSwitch'].decode('utf8'), ttsSay))
        return False

    ttsRoom = getDefaultRoom(
    ) if 'ttsRoom' not in keywords else keywords['ttsRoom']

    ttsRooms = []
    if ttsRoom == 'All' or ttsRoom is None:
        for the_key, the_value in sonos['rooms'].iteritems():
            ttsRooms.append(sonos['rooms'][the_key])
            log.debug(u"TTS room found: [{}]".format(
                sonos['rooms'][the_key]['name'].decode('utf8')))
    else:
        sonosSpeaker = sonos['rooms'].get(ttsRoom, None)
        if sonosSpeaker is None:
            log.warn(
                u"Room [{}] wasn't found in the sonos rooms dictionary".format(
                    ttsRoom.decode('utf8')))
            return
        ttsRooms.append(sonosSpeaker)
        log.debug(u"TTS room found: [{}]".format(
            sonosSpeaker['name'].decode('utf8')))

    for room in ttsRooms:
        ttsVol = None if 'ttsVol' not in keywords else keywords['ttsVol']
        if not ttsVol or ttsVol >= 70:
            if ttsPrio == PRIO['LOW']:
                ttsVol = 30
            elif ttsPrio == PRIO['MODERATE']:
                ttsVol = 40
            elif ttsPrio == PRIO['HIGH']:
                ttsVol = 60
            elif ttsPrio == PRIO['EMERGENCY']:
                ttsVol = 70
            else:
                ttsVol = room['ttsvolume']

        ttsLang = room['ttslang'] if 'ttsLang' not in keywords else keywords[
            'ttsLang']
        ttsVoice = room[
            'ttsvoice'] if 'ttsVoice' not in keywords else keywords['ttsVoice']
        ttsEngine = room[
            'ttsengine'] if 'ttsEngine' not in keywords else keywords[
                'ttsEngine']
        #Voice.say(ttsSay, "{}:{}".format(ttsEngine, ttsVoice), room['audiosink'])
        Voice.say(ttsSay, "{}:{}".format(ttsEngine,
                                         ttsVoice), room['audiosink'],
                  scope.PercentType(ttsVol))  # Volume is not well implemented
        log.info(u"TTS: Speaking [{}] in room [{}] at volume [{}]".format(
            ttsSay, room['name'].decode('utf8'), ttsVol))

    return True
Example #7
0
def playsound(fileName, ttsPrio=PRIO['MODERATE'], **keywords):
    '''
    Play a sound mp3 file function. First argument is positional and mandatory.
    Remaining arguments are optionally keyword arguments.
    Example: playsound("Hello.mp3")
    Example: playsound("Hello.mp3", PRIO['HIGH'], room='Kitchen', volume=42)
    @param param1: Sound file name to play (positional argument) (files need to be put in the folder conf/sounds)
    @param param2: Priority as defined by PRIO. Defaults to PRIO['MODERATE']
    @param room: Room to play in. Defaults to "All".
    @return: this is a description of what is returned
    '''
    log = logging.getLogger(LOG_PREFIX + ".community.sonos.playsound")

    def getDefaultRoom():
        # Search for the default room to speak in
        for the_key, the_value in sonos['rooms'].iteritems():
            if the_value['defaultttsdevice']:
                return the_key
        return 'All'

    if getItemValue(customItemNames['allowTTSSwitch'],
                    scope.ON) != scope.ON and ttsPrio <= PRIO['MODERATE']:
        log.info(
            "[{}] is OFF and ttsPrio is too low to play the sound [{}] at this moment"
            .format(customItemNames['allowTTSSwitch'], fileName))
        return False

    room = getDefaultRoom() if 'room' not in keywords else keywords['room']

    rooms = []
    if room == 'All' or room is None:
        for the_key, the_value in sonos['rooms'].iteritems():
            rooms.append(sonos['rooms'][the_key])
            log.debug(u"Room found: [{}]".format(
                sonos['rooms'][the_key]['name'].decode('utf8')))
    else:
        sonosSpeaker = sonos['rooms'].get(room, None)
        if sonosSpeaker is None:
            log.warn(
                u"Room [{}] wasn't found in the sonos rooms dictionary".format(
                    room.decode('utf8')))
            return
        rooms.append(sonosSpeaker)
        log.debug(u"Room found: [{}]".format(
            sonosSpeaker['name'].decode('utf8')))

    for aRoom in rooms:
        ttsVol = None if 'ttsVol' not in keywords else keywords['ttsVol']
        if not ttsVol or ttsVol >= 70:
            if ttsPrio == PRIO['LOW']:
                ttsVol = 30
            elif ttsPrio == PRIO['MODERATE']:
                ttsVol = 40
            elif ttsPrio == PRIO['HIGH']:
                ttsVol = 60
            elif ttsPrio == PRIO['EMERGENCY']:
                ttsVol = 70
            else:
                ttsVol = aRoom['ttsvolume']

        Audio.playSound(aRoom['audiosink'], fileName)
        log.info(u"playSound: Playing [{}] in room [{}] at volume [{}]".format(
            fileName.decode('utf8'), aRoom['name'].decode('utf8'), ttsVol))

    return True
Example #8
0
 def __call__(self, event):
     log.debug("rule {} triggered by {}, state {}".format(
         self.__class__.__name__, event.itemName, event.itemState))
     events.postUpdate(self.item2.name,
                       str(2 * getItemValue(self.item1.name, 0.1)))