Beispiel #1
0
    def __diagNetwork(self):
        try:
            with open("/proc/net/route") as f:
                for line in f:
                    fields = line.strip().split()
                    if fields[
                            1] != "00000000":  # default gateway destination 0.0.0.0
                        continue
                    #log.debug(fields)
                    if int(
                            fields[3], 16
                    ) & 2:  # check route to be UG from the third field which is in base16
                        self.__networkStatus = True
                        try:
                            self.__networkGateway = socket.inet_ntoa(
                                struct.pack("=L", int(fields[2], 16)))
                            #self.__networkGateway = ".".join([str(int(fields[2][i:i+2], 16)) for i in range(0, len(fields[2]), 2)]) # depends on endianess
                        except:
                            self.__networkGateway = None
                            log.debug("Cannot get gateway address.")

                        log.debug("Network gateway (%s) up on interface %s" %
                                  (self.__networkGateway, fields[0]))
                        return
        except:
            log.error("Cannot find /proc entry for network diag")

        self.__networkStatus = False
    def addRecord(self, zone, commit=True):
        if (self.database.isOpen()):
            valuesToInsert = (
                zone.zid,
                zone.SoilIntakeRate,
                zone.AvailableWater,
                zone.MaxAllowedDepletion,
                zone.RootDepth,
                zone.isTallPlant,
                zone.PrecipRate,
                zone.AppEfficiency,
                zone.AllowedSurfaceAcc,
                zone.FieldCapacity,
                zone.PermWilting,
                zone.MaxRuntime,
                ",".join(str(i) for i in zone.DetailedMonthsKc),
                zone.StartWaterLevel,
            )

            if commit:
                try:
                    self.database.execute("INSERT OR REPLACE INTO zones_advanced( zid, SoilIntakeRate, AvailableWater, MaxAllowedDepletion, RootDepth, isTallPlant, PrecipRate, \
                                                        AppEfficiency, AllowedSurfaceAcc, FieldCapacity, PermWilting, MaxRuntime, DetailedMonthsKc, StartWaterLevel) "\
                                                "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", valuesToInsert)
                    self.database.commit()
                except Exception, e:
                    log.error(e)
                    return False
            else:
                self.database.execute("INSERT OR REPLACE INTO zones_advanced( zid, SoilIntakeRate, AvailableWater, MaxAllowedDepletion, RootDepth, isTallPlant, PrecipRate, \
                                    AppEfficiency, AllowedSurfaceAcc, FieldCapacity, PermWilting, MaxRuntime, DetailedMonthsKc, StartWaterLevel) "\
                        "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", valuesToInsert)
    def perform(self):
        s = self.settings

        appKey = self.params.get("appKey", None)
        if appKey is None:
            self.lastKnownError = "Error: No Api Key"
            return

        URL = "https://api.darksky.net/forecast/" + str(appKey) + "/" + str(
            s.location.latitude) + "," + str(s.location.longitude)

        # URLParams = \
        #     [
        #         ("units", "si"),
        #         ("exclude", "currently,minutely,alerts,flags"),
        #         ("extend", "hourly")
        #     ]

        URLParams = \
            [
                ("units", "si"),
                ("exclude", "currently,minutely,alerts,flags, hourly")
            ]

        try:
            d = self.openURL(URL, URLParams)
            if d is None:
                return

            forecast = json.loads(d.read())
            self.__getDailyData(forecast)

        except Exception, e:
            log.error("*** Error running darksky.net parser")
            log.exception(e)
    def perform(self):
        self.apiKey = self.params.get("apiKey", None)
        self.stationID = self.params.get("stationID", None)
        if self.apiKey is None or not self.apiKey or not isinstance(
                self.apiKey, str):
            self.lastKnownError = "Error: No API Key. Please register an account at https://www.willyweather.com.au/info/api.html"
            return

        self.params["_nearbyStationsIDList"] = []
        self.noDays = 7

        if self.params.get("stationLookUp"):
            s = self.settings
            llat = s.location.latitude
            llon = s.location.longitude

            searchURL = "https://api.willyweather.com.au/v2/" + self.apiKey + "/search.json"
            searchURLParams = [("lat", llat), ("lng", llon),
                               ("units", "distance:km")]

            try:
                d = self.openURL(searchURL, searchURLParams)
                if d is None:
                    return

                search = json.loads(d.read())

                if self.parserDebug:
                    log.info(search)

                self.getNearbyStations(search)

            except Exception, e:
                log.error("*** Error finding nearby stations")
                log.exception(e)
 def _log_error(self, message, packet=None):
     if packet is not None:
         self.lastKnownError = message + ' ' + ''.join('\\x%02X' % ord(b)
                                                       for b in packet)
     else:
         self.lastKnownError = message
     log.error(self.lastKnownError)
 def addRecord(self, zone):
     if self.database.isOpen():
         valuesToInsert = (
             zone.uid,
             zone.name,
             zone.valveid,
             zone.ETcoef,
             zone.active,
             zone.type,
             zone.internet,
             zone.savings,
             zone.slope,
             zone.sun,
             zone.soil,
             zone.group_id,
             zone.history,
         )
         try:
             self.database.execute(
                 "INSERT OR REPLACE INTO zones( uid, name, valveid, ETcoef, active, type, internet, savings, slope, sun, soil, group_id, history) "
                 "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
                 valuesToInsert,
             )
             self.zonesAdvancedTable.addRecord(zone, False)
             self.database.commit()
         except Exception, e:
             log.error(e)
             return False
    def perform(self):

        days = self.params["historicDays"]
        intervals = days / self.maxAllowedDays + (days % self.maxAllowedDays !=
                                                  0)
        lastIntervalStartDay = datetime.date.today()

        if intervals > 1:
            days = self.maxAllowedDays

        log.debug("Days: %d Intervals: %d" % (days, intervals))

        for i in range(0, intervals):
            startDay = lastIntervalStartDay - datetime.timedelta(
                days=1)  # CIMIS real data starts from yesterday
            endDay = startDay - datetime.timedelta(days=(days + 1))
            lastIntervalStartDay = endDay
            try:
                self.__retrieveData(
                    endDay, startDay
                )  # we call with startDay/endDay swapped because CIMIS expects historic intervals
            except Exception, e:
                log.error("*** Error running CIMIS parser")
                self.lastKnownError = "Error: Data retrieval failed"
                log.exception(e)
Beispiel #8
0
    def uploadDiag(self):

        localPath = globalSettings.databasePath
        remotePath = self.__getUploadFolderName()
        filesUploaded = 0
        try:
            self.__connect()
            self.__ftp.mkd(remotePath)
            self.__ftp.cwd(remotePath)

            # Application files
            for file in self.fileList:
                try:
                    self.status = RMDiagUpload.STATUS_UPLOADING
                    if os.path.isabs(file):
                        self.__upload(None, file)
                    else:
                        self.__upload(localPath, file)

                    filesUploaded += 1
                except Exception, e:
                    log.error("uploadDiag: File: %s : %s" % (file, e))

            if filesUploaded > 0:  # rainmachine.log.1.gz might not had been created
                self.status = RMDiagUpload.STATUS_IDLE
            else:
                self.status = RMDiagUpload.STATUS_UPLOAD_ERROR

            self.__ftp.quit()
 def addRecord(self, zone):
     if (self.database.isOpen()):
         valuesToInsert = (
             zone.uid,
             zone.name,
             zone.valveid,
             zone.ETcoef,
             zone.active,
             zone.type,
             zone.internet,
             zone.savings,
             zone.slope,
             zone.sun,
             zone.soil,
             zone.group_id,
             zone.history,
         )
         try:
             self.database.execute("INSERT OR REPLACE INTO zones( uid, name, valveid, ETcoef, active, type, internet, savings, slope, sun, soil, group_id, history) "\
                                         "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", valuesToInsert)
             self.zonesAdvancedTable.addRecord(zone, False)
             self.database.commit()
         except Exception, e:
             log.error(e)
             return False
    def __getSimpleForecast(self):
        try:
            timetuple = datetime.datetime.fromtimestamp(int(
                time.time())).timetuple()
            timestamp = datetime.datetime(timetuple.tm_year, timetuple.tm_mon,
                                          timetuple.tm_mday)
            dayTimestamp = int(time.mktime(timestamp.timetuple()))
            maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400
            simpleForecast = self.jsonResponse["response"][0]

            for key in simpleForecast["periods"]:
                log.debug(key)
                timestamp = self.__toInt(key["timestamp"])
                if timestamp is None:
                    continue

                timestamp = int(timestamp)

                if timestamp < maxDayTimestamp:

                    #tt = self.__toInt(key["timestamp"])
                    #tt = rmGetStartOfDay(tt)
                    #if tt > maxDayTimestamp:
                    #    break
                    #timestamp = self.__toInt(tt)
                    temperatureMax = self.__toFloat(key["maxTempC"])
                    temperatureMin = self.__toFloat(key["minTempC"])
                    wind = self.__toFloat(key["windSpeedKPH"])
                    if wind is not None:
                        wind = wind / 3.6  # convertred from kmetersph to meterps
                    humidity = self.__toFloat(key["humidity"])
                    qpf = self.__toFloat(key["precipMM"])
                    pop = self.convertToPercent(key["pop"])
                    dewpoint = self.__toFloat(key["avgDewpointC"])
                    condition = self.conditionConvert(
                        key["weatherPrimaryCoded"], key["cloudsCoded"])

                    self.addValue(RMParser.dataType.QPF, timestamp, qpf)
                    self.addValue(RMParser.dataType.RH, timestamp, humidity)
                    self.addValue(RMParser.dataType.WIND, timestamp, wind)
                    self.addValue(RMParser.dataType.POP, timestamp, pop)
                    self.addValue(RMParser.dataType.DEWPOINT, timestamp,
                                  dewpoint)
                    self.addValue(RMParser.dataType.MINTEMP, timestamp,
                                  temperatureMin)
                    self.addValue(RMParser.dataType.MAXTEMP, timestamp,
                                  temperatureMax)
                    self.addValue(RMParser.dataType.CONDITION, timestamp,
                                  condition)

                    log.debug(timestamp)
                    log.debug(temperatureMax)
                    log.debug(temperatureMin)
                    log.debug(wind)
                    log.debug(humidity)
                    log.debug(qpf)
                    log.debug(condition)

        except:
            log.error("Failed to get simple forecast")
    def uploadDiag(self):

        localPath = globalSettings.databasePath
        remotePath = self.__getUploadFolderName()
        filesUploaded = 0
        try:
            self.__connect()
            self.__ftp.mkd(remotePath)
            self.__ftp.cwd(remotePath)

            # Application files
            for file in self.fileList:
                try:
                    self.status = RMDiagUpload.STATUS_UPLOADING
                    if os.path.isabs(file):
                        self.__upload(None, file)
                    else:
                        self.__upload(localPath, file)

                    filesUploaded += 1
                except Exception, e:
                    log.error("uploadDiag: File: %s : %s" % (file, e))

            if filesUploaded > 0:   # rainmachine.log.1.gz might not had been created
                self.status = RMDiagUpload.STATUS_IDLE
            else:
                self.status = RMDiagUpload.STATUS_UPLOAD_ERROR

            self.__ftp.quit()
    def __unmanglePassword(self, mangle):
        if not mangle or len(mangle) != 112:
            return None

        tokenSize = len(mangle) / 16
        tokens = [
            "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
        ]

        index = 0
        while index <= 15:
            token = mangle[(index * tokenSize):((index + 1) * tokenSize)]
            if token[0] == '3':
                tokens[0] = token[1:tokenSize]
            elif token[0] == 'b':
                tokens[15] = token[1:tokenSize]

            index += 1

        password = "".join(tokens)

        log.error("Mangle: %s" % mangle)
        log.error("Password: %s" % password)

        return password
Beispiel #13
0
 def getNearbyStationsNoKey(self):
     MIN_STATIONS = 1
     MAX_STATIONS = 20
     s = self.settings
     llat = s.location.latitude
     llon = s.location.longitude
     stationsURL = "https://stationdata.wunderground.com/cgi-bin/stationdata?v=2.0&type=ICAO%2CPWS&units=metric&format=json&maxage=1800&maxstations=" \
                   + str(MAX_STATIONS) + "&minstations=" + str(MIN_STATIONS) + "&centerLat=" + str(llat) + "&centerLon=" \
                   + str(llon) + "&height=400&width=400&iconsize=2&callback=__ng_jsonp__.__req1.finished"
     try:
         # WARNING: WE PROBABLY SHOULD FAIL IF WE CAN'T GET STATIONS IF USER KNOWS STATION_ID
         log.debug("Downloading station data from: %s" % stationsURL)
         d = self.openURL(stationsURL, headers=self.headers)
         if d is None:
             self.lastKnownError = "Cannot download nearby stations"
             log.error(self.lastKnownError)
         # extract object from callback parameter
         stationsData = d.read()
         stationsObj = stationsData[stationsData.
                                    find("{"):stationsData.rfind("}") + 1]
         # log.info(stationsObj)
         stations = json.loads(stationsObj)
         self.parseNearbyStationsNoKey(stations)
     except Exception, e:
         self.lastKnownError = "ERROR: Cannot get nearby stations"
         log.error(self.lastKnownError)
         return
    def __parseStationData(self, jsonContent):
        observations = {}

        try:
            temperature = self.__toFloat(jsonContent.get("temp_c", None))
            rh = self.__toFloat(jsonContent.get("relative_humidity", None))
            wind = self.__toFloat(jsonContent.get("wind_kph", None))
            wind_gust = self.__toFloat(jsonContent.get("wind_gust_kph", None))
            pressure = self.__toFloat(jsonContent.get("pressure_mb", None))
            dew = self.__toFloat(jsonContent.get("dewpoint_c", None))
            heat = self.__toFloat(jsonContent.get("heat_index_c", None))
            rain = self.__toFloat(jsonContent.get("precip_1hr_metric", None))
            # Conversions
            if wind is not None: #kph to mps
                wind = wind / 3.6

            if pressure is not None: # mb to kpa
                pressure = pressure / 10

            observations["temperature"] = temperature
            observations["rh"] = rh
            observations["wind"] = wind
            observations["wind_gust"] = wind_gust
            observations["pressure"] = pressure
            observations["dew"] = dew
            observations["heat"] = heat
            observations["rain"] = rain

        except Exception, e:
            log.error("Can't parse data %s" % e)
            self.lastKnownError = "Error: Can't parse data"
    def __rest(self, type, apiCall, data = None, isBinary = False, extraHeaders = None, majorVersion="", asJSON = True):

        protocol = RMAPIClientProtocol.getAsString(self._protocol)

        apiUrl = protocol + self._host + ":" + self._port + "/api/" + majorVersion + "/"

        if self.token is None:
            url = apiUrl + apiCall
        else:
            url = apiUrl + apiCall + "?access_token=" + self.token

        try:
            req = urllib2.Request(url)
            req.get_method = lambda: type # Force GET/POST depending on type
        except:
            return RMAPIClientErrors.REQ

        if isBinary:
            req.add_data(data=data)
        else:
            req.add_data(data=json.dumps(data))
            req.add_header("Content-type","text/plain")


        if extraHeaders is not None:
            for header in extraHeaders:
                req.add_header(header)

        try:
            log.info("REST: %s : %s" % (req.get_method(), req.get_full_url()))
            r = urllib2.urlopen(req)
            data = r.read()
        except Exception, e:
            log.error("Cannot OPEN URL: %s" % e)
            return RMAPIClientErrors.OPEN
Beispiel #16
0
    def perform(self):
        URL = self.params.get("urlPath", None)
        d = self.openURL(URL)
        if d is None:
            return
        pwsContent = d.read()
        if pwsContent is None:
            return

        pwsContent = pwsContent.strip()
        pwsArray = pwsContent.split(" ")

        lat = float(pwsArray[160])
        lon = -float(pwsArray[161])

        distToPWS = self.distanceToStation(lat, lon)
        maxDist = self.params.get("maxAllowedDistance")
        if (distToPWS > maxDist):
            log.error("*** PWS Station too far from home!")
            return

        temperature = self.__toFloat(pwsArray[4])
        mintemp = self.__toFloat(pwsArray[47])
        maxtemp = self.__toFloat(pwsArray[46])
        rh = self.__toFloat(pwsArray[5])
        minrh = self.__toFloat(pwsArray[164])
        maxrh = self.__toFloat(pwsArray[163])
        wind = self.__toFloat(convertKnotsToMS(
            pwsArray[1]))  # converted from knos to m/s
        solarradiation = self.__toFloat(
            pwsArray[127]
        )  # needs to be converted from watt/sqm*h to Joule/sqm

        if solarradiation is not None:
            solarradiation *= 0.0864

        rain = self.__toFloat(pwsArray[7])
        dewpoint = self.__toFloat(pwsArray[72])
        pressure = self.__toFloat(pwsArray[50])
        conditionIcon = self.conditionConvert(self.__toFloat(pwsArray[48]))
        #skycover ?

        timestamp = rmCurrentTimestamp()
        self.addValue(RMParser.dataType.TEMPERATURE, timestamp, temperature)
        self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp)
        self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp)
        self.addValue(RMParser.dataType.RH, timestamp, rh)
        self.addValue(RMParser.dataType.MINRH, timestamp, minrh)
        self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh)
        self.addValue(RMParser.dataType.WIND, timestamp, wind)
        self.addValue(RMParser.dataType.RAIN, timestamp, rain)
        self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint)
        self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure)
        self.addValue(RMParser.dataType.CONDITION, timestamp, conditionIcon)
        self.addValue(RMParser.dataType.SOLARRADIATION, timestamp,
                      solarradiation)

        print self.result
        return
 def __checkFactoryReset(self):
     factoryReset = os.path.exists("/tmp/factory-reset")
     if factoryReset and self.__mainManager:
         try:
             os.remove("/tmp/factory-reset")
         except Exception, e:
             log.error(e)
         self.__mainManager.factoryReset()
 def __checkFactoryReset(self):
     factoryReset = os.path.exists("/tmp/factory-reset")
     if factoryReset and self.__mainManager:
         try:
             os.remove("/tmp/factory-reset")
         except Exception, e:
             log.error(e)
         self.__mainManager.factoryReset()
 def unregisterThread(self):
     ### Call this method from the thread you want to unregister.
     with self.__lock:
         key = thread.get_ident()
         entry = self.__data.pop(key, None)
         if entry is None:
             log.error("Thread key %s not found. unregister failed" % key)
             return False
         return True
 def unregisterThread(self):
     ### Call this method from the thread you want to unregister.
     with self.__lock:
         key = thread.get_ident()
         entry = self.__data.pop(key, None)
         if entry is None:
             log.error("Thread key %s not found. unregister failed" % key)
             return False
         return True
 def __setWatchdogMaxTimeout(self):
         WDIOC_SETTIMEOUT = 0xC0045706 # direction(3 RW) << 30 | size (4 int) << 16 | type ( 'W') << 8 | number (6)
         timeout = ctypes.c_int(120) # seconds
         if self.__watchDogDescriptor is not None:
             fd = self.__watchDogDescriptor.fileno()
             ioctl(fd, WDIOC_SETTIMEOUT, timeout)
             self.__watchDogDescriptor.close()
         else:
             log.error("Can't set watchdog max timeout. Device not opened")
Beispiel #22
0
    def perform(self):
        s = self.settings
        headers = [{ "User-Agent": "RainMachine.com v2" },
                   { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36"}]

        URL = "https://api.met.no/weatherapi/locationforecast/2.0/classic"

        URLParams = [("lat", s.location.latitude),
                     ("lon",  s.location.longitude),
                     ("altitude", int(round(s.location.elevation)))]


        #-----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        d = self.openURL(URL, URLParams, headers=headers[random.randint(0, 1)])
        if d is None:
            return

        tree = e.parse(d)
        #tree = e.parse("/tmp/MET.NO/forecast.xml")

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Error: No hourly information found"

            tree.getroot().clear()
            del tree
            tree = None
        else:
            data = self.__parseXMLData(tree)

            # Free memory
            tree.getroot().clear()
            del tree
            tree = None

            temp        = self.__extractTagData(data, 'temperature')
            mintemp     = self.__extractTagData(data, 'minTemperature')
            maxtemp     = self.__extractTagData(data, 'maxTemperature')
            dewpoint    = self.__extractTagData(data, 'dewpointTemperature')
            wind        = self.__extractTagData(data, 'windSpeed')
            humidity    = self.__extractTagData(data, 'humidity')
            pressure    = self.__extractTagData(data, 'pressure')
            qpf         = self.__extractTagData(data, 'precipitation')
            condition   = self.__extractTagData(data, 'symbol')

            self.addValues(RMParser.dataType.TEMPERATURE, temp)
            self.addValues(RMParser.dataType.MINTEMP, mintemp)
            self.addValues(RMParser.dataType.MAXTEMP, maxtemp)
            self.addValues(RMParser.dataType.DEWPOINT, dewpoint)
            self.addValues(RMParser.dataType.WIND, wind)
            self.addValues(RMParser.dataType.RH, humidity)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.PRESSURE, pressure)
            self.addValues(RMParser.dataType.CONDITION, condition)
 def __setWatchdogMaxTimeout(self):
     WDIOC_SETTIMEOUT = 0xC0045706  # direction(3 RW) << 30 | size (4 int) << 16 | type ( 'W') << 8 | number (6)
     timeout = ctypes.c_int(120)  # seconds
     if self.__watchDogDescriptor is not None:
         fd = self.__watchDogDescriptor.fileno()
         ioctl(fd, WDIOC_SETTIMEOUT, timeout)
         self.__watchDogDescriptor.close()
     else:
         log.error("Can't set watchdog max timeout. Device not opened")
    def __refreshWIFI(self):
        timestamp = rmCurrentTimestamp()
        lastWIFICheckTimestamp = globalWIFI.wifiInterface.lastWIFICheckTimestamp
        oldIP = globalWIFI.wifiInterface.ipAddress

        if lastWIFICheckTimestamp is None or oldIP is None or (
                timestamp -
                lastWIFICheckTimestamp) >= self.__wifiRefreshTimeout:
            try:
                globalWIFI.detect()

                if oldIP != globalWIFI.wifiInterface.ipAddress:
                    log.info(
                        "Refreshed WIFI Information. (old: %s new ip: %s)" %
                        ( ` oldIP `, ` globalWIFI.wifiInterface.ipAddress `))

                if RMOSPlatform().AUTODETECTED == RMOSPlatform.ANDROID:
                    return

                # Handle None IP
                if globalWIFI.wifiInterface.ipAddress is None:
                    if self.__lastNoneIpTimestamp is None or (
                            timestamp - self.__lastNoneIpTimestamp
                    ) < self.__wifiNoneIpTimeout:
                        # First occurrence of None IP     OR    we can wait some more time.
                        if self.__lastNoneIpTimestamp is None:
                            self.__lastNoneIpTimestamp = timestamp
                        log.debug(
                            "Refreshed WIFI Information - no IP detected. Give it some more time: %d seconds!"
                            % (self.__wifiNoneIpTimeout -
                               (timestamp - self.__lastNoneIpTimestamp), ))
                        return
                    else:
                        globalWIFI.restart()
                        log.warn(
                            "Refreshed WIFI Information - WIFI quick reloaded because no IP detected. New IP is %s"
                            % ` globalWIFI.wifiInterface.ipAddress `)

                self.__lastNoneIpTimestamp = None  # Reset None IP timestamp.

                # Check if we never connected to this AP, set back AP mode and restart app
                if globalWIFI.wifiInterface.mode == "managed" and not globalWIFI.hasConnectedOnce(
                ):
                    if globalWIFI.wifiInterface.hasClientLink:
                        globalWIFI.saveHasConnectedOnce(True)
                    else:
                        log.warning(
                            "WIFI Watcher Client IP (%s) configuration failed, restarting in AP mode."
                            % oldIP)
                        globalWIFI.setDefaultAP()
                        globalWIFI.saveHasConnectedOnce(False)
                        globalWIFI.restart()
                        self.__mainManager.touchWakeMessage()

            except Exception, e:
                log.error(e)
    def perform(self):
        URL = self.params.get("urlPath", None)
        d = self.openURL(URL)
        if d is None:
             return
        pwsContent = d.read()
        if pwsContent is None:
             return

        pwsContent = pwsContent.strip()
        pwsArray = pwsContent.split(" ")

        lat = float(pwsArray[160])
        lon = -float(pwsArray[161])

        distToPWS = self.distanceToStation(lat, lon)
        maxDist = self.params.get("maxAllowedDistance")
        if(distToPWS > maxDist):
             log.error("*** PWS Station too far from home!")
             return


        temperature = self.__toFloat(pwsArray[4])
        mintemp = self.__toFloat(pwsArray[47])
        maxtemp = self.__toFloat(pwsArray[46])
        rh = self.__toFloat(pwsArray[5])
        minrh = self.__toFloat(pwsArray[164])
        maxrh = self.__toFloat(pwsArray[163])
        wind = self.__toFloat(convertKnotsToMS(pwsArray[1]))  # converted from knos to m/s
        solarradiation = self.__toFloat(pwsArray[127])  # needs to be converted from watt/sqm*h to Joule/sqm

        if solarradiation is not None:
                    solarradiation *= 0.0864

        rain = self.__toFloat(pwsArray[7])
        dewpoint = self.__toFloat(pwsArray[72])
        pressure = self.__toFloat(pwsArray[50])
        conditionIcon = self.conditionConvert(self.__toFloat(pwsArray[48]))
        #skycover ?

        timestamp = rmCurrentTimestamp()
        self.addValue(RMParser.dataType.TEMPERATURE, timestamp, temperature)
        self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp)
        self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp)
        self.addValue(RMParser.dataType.RH, timestamp, rh)
        self.addValue(RMParser.dataType.MINRH, timestamp, minrh)
        self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh)
        self.addValue(RMParser.dataType.WIND, timestamp, wind)
        self.addValue(RMParser.dataType.RAIN, timestamp, rain)
        self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint)
        self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure)
        self.addValue(RMParser.dataType.CONDITION, timestamp, conditionIcon)
        self.addValue(RMParser.dataType.SOLARRADIATION, timestamp, solarradiation)

        print self.result
        return
Beispiel #26
0
    def parseStationYesterdayDataNoKey(self, data):
        #daily summary for yesterday
        try:
            l = RMWeatherDataLimits()

            temperature = self.__toFloat(data["TemperatureAvgC"])
            mintemp = self.__toFloat(data["TemperatureLowC"])
            maxtemp = self.__toFloat(data["TemperatureHighC"])
            rh = self.__toFloat(data["HumidityAvg"])
            minrh = self.__toFloat(data["HumidityLow"])
            maxrh = self.__toFloat(data["HumidityHigh"])
            dewpoint = self.__toFloat(data["DewpointAvgC"])
            wind = self.__toFloat(data["WindSpeedAvgKMH"])
            maxpressure = self.__toFloat(data["PressureMaxhPa"])
            minpressure = self.__toFloat(data["PressureMinhPa"])
            rain = self.__toFloat(
                data["PrecipitationSumCM"]) * 10.0  # from cm to mm

            if wind is not None:
                wind = wind / 3.6  # converted from kmetersph to mps

            if maxpressure is not None:
                maxpressure = l.sanitize(RMWeatherDataType.PRESSURE,
                                         maxpressure /
                                         10.0)  # converted to from hpa to kpa

            if minpressure is not None:
                minpressure = l.sanitize(RMWeatherDataType.PRESSURE,
                                         minpressure / 10.0)

            pressure = None
            if maxpressure is not None and minpressure is not None:
                pressure = (maxpressure + minpressure) / 2.0

            #log.info("rh:%s minrh: %s maxrh: %s pressure: %s temp: %s mintemp: %s maxtemp: %s" % (rh, minrh, maxrh, pressure, temperature, mintemp, maxtemp))

            timestamp = rmCurrentDayTimestamp()
            timestamp = rmGetStartOfDay(timestamp - 12 * 3600)

            self.addValue(RMParser.dataType.TEMPERATURE, timestamp,
                          temperature, False)
            self.addValue(RMParser.dataType.MINTEMP, timestamp, mintemp, False)
            self.addValue(RMParser.dataType.MAXTEMP, timestamp, maxtemp, False)
            self.addValue(RMParser.dataType.RH, timestamp, rh, False)
            self.addValue(RMParser.dataType.MINRH, timestamp, minrh, False)
            self.addValue(RMParser.dataType.MAXRH, timestamp, maxrh, False)
            self.addValue(RMParser.dataType.WIND, timestamp, wind, False)
            self.addValue(RMParser.dataType.RAIN, timestamp, rain, False)
            self.addValue(RMParser.dataType.DEWPOINT, timestamp, dewpoint,
                          False)
            self.addValue(RMParser.dataType.PRESSURE, timestamp, pressure,
                          False)

        except Exception, e:
            self.lastKnownError = "ERROR: Failed to get historical data"
            log.error("%s: %s" % (self.lastKnownError, e))
 def __getStationData(self, URL):
     try:
         d = self.openURL(URL)
         jsonResponse = d.read()
         jsonContent = json.loads(jsonResponse)
         jsonContent = jsonContent["current_observation"]
     except Exception, e:
         log.error("Invalid data received %s" % e)
         self.lastKnownError = "Error: Invalid data received"
         return None
Beispiel #28
0
 def doRun(self):
     #-------------------------------------------------------------------------
     # Handle the events / commands.
     command = None
     while True:
         try:
             if not self.doHandleMessages():
                 break
         except Exception, e:
             log.error(e)
    def __getDailyData(self, forecast):
        dayTimestamp = rmCurrentDayTimestamp()
        maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400

        daily = []
        try:
            daily = forecast["daily"]["data"]
        except Exception, e:
            log.error("*** No daily information found in response!")
            self.lastKnownError = "Warning: No daily information"
            log.exception(e)
Beispiel #30
0
    def perform(self):
        station = self.params.get("station", None)

        if station is None:
            self.lastKnownError = "No station number configured."
            log.error(self.lastKnownError)
            return

        res = self.performWithDataFeeds(station)
        if not res:
            self.performWithReport(station)
    def perform(self):
        s = self.settings
        URLHourly = "http://fawn.ifas.ufl.edu/controller.php/lastHour/summary/json"
        URLDaily = "http://fawn.ifas.ufl.edu/controller.php/lastDay/summary/json"
        URLParams = []

        useHourly = self.params.get("useHourly", False)

        # -----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        if useHourly:
            try:
                d = self.openURL(URLHourly, URLParams)
                if d is None:
                    return

                json_data = d.read()
                json_data = json_data.replace("'", '"')
                hourly = json.loads(json_data)

                for entry in hourly:
                    # only selected station
                    if int(entry.get("StationID")) == self.params.get("station"):
                        dateString = entry.get("startTime")
                        # timestamp = rmTimestampFromDateAsStringWithOffset(dateString)
                        timestamp = rmTimestampFromDateAsString(dateString[:-6], "%Y-%m-%dT%H:%M:%S")
                        if timestamp is None:
                            log.debug("Cannot convert hourly data startTime: %s to unix timestamp" % dateString)
                            continue

                        # Add 12h in the future for FAWN timestamp to fix badly reported offset and make it middle of the day UTC (Dragos)
                        timestamp += 12 * 60 * 60

                        self.addValue(RMParser.dataType.TEMPERATURE, timestamp, self.__toFloat(entry.get("t2m_avg")))
                        self.addValue(RMParser.dataType.MINTEMP, timestamp, self.__toFloat(entry.get("t2m_min")))
                        self.addValue(RMParser.dataType.MAXTEMP, timestamp, self.__toFloat(entry.get("t2m_max")))
                        # km/h -> m/s
                        self.addValue(
                            RMParser.dataType.WIND, timestamp, 0.27777777777778 * self.__toFloat(entry.get("ws_avg"))
                        )
                        # cm -> mm
                        self.addValue(RMParser.dataType.RAIN, timestamp, 10 * self.__toFloat(entry.get("rain_sum")))
                        self.addValue(RMParser.dataType.DEWPOINT, timestamp, self.__toFloat(entry.get("dp_avg")))
                        self.addValue(RMParser.dataType.RH, timestamp, self.__toFloat(entry.get("rh_avg")))

                if self.parserDebug:
                    log.debug(self.result)

            except Exception, e:
                log.error("*** Error retrieving hourly data from FAWN")
                log.exception(e)
    def perform(self):
        url = 'https://api.ambientweather.net/v1/devices/' + str(
            self.params["macAddress"])
        parameterList = [("apiKey", str(self.params["apiKey"])),
                         ("applicationKey",
                          str(self.params["applicationKey"])), ("limit", "1")]

        log.info('Getting data from {0}'.format(str(url)))
        data = self.openURL(url, parameterList)

        if data is None:
            self.lastKnownError = "Error: No data received from server"
            log.error(self.lastKnownError)
            return

        station = json.loads(data.read())
        for entry in station:
            dateutc = entry["dateutc"] / 1000  # from milliseconds

            if 'tempf' in entry:
                temp = convertFahrenheitToCelsius(entry["tempf"])
                self.addValue(RMParser.dataType.TEMPERATURE, dateutc, temp,
                              False)

            if 'humidity' in entry:
                self.addValue(RMParser.dataType.RH, dateutc, entry["humidity"],
                              False)

            if 'windspeedmph' in entry:
                windspeed = entry["windspeedmph"] * 0.44704  # to meters/sec
                self.addValue(RMParser.dataType.WIND, dateutc, windspeed,
                              False)

            if 'solarradiation' in entry:
                solarrad = convertRadiationFromWattsToMegaJoules(
                    entry["solarradiation"])
                self.addValue(RMParser.dataType.SOLARRADIATION, dateutc,
                              solarrad, False)

            if 'dailyrainin' in entry:
                rain = convertInchesToMM(entry["dailyrainin"])
                self.addValue(RMParser.dataType.RAIN, dateutc, rain, False)

            if 'baromrelin' in entry:
                pressure = entry["baromrelin"] * 3.38639  # to kPa
                self.addValue(RMParser.dataType.PRESSURE, dateutc, pressure,
                              False)

            if 'dewPoint' in entry:
                dewpoint = convertFahrenheitToCelsius(entry["dewPoint"])
                self.addValue(RMParser.dataType.DEWPOINT, dateutc, dewpoint,
                              False)
        return True
    def addRecord(self, zid, timestamp, day, startWaterLevel):
        if (self.database.isOpen()):
            try:
                self.database.execute("INSERT OR REPLACE INTO %s(zid, timestamp, day, startWaterLevel) "\
                                            "VALUES(?, ?, ?, ?)" % self._tableName,
                                      (zid, timestamp, day, startWaterLevel))

                self.database.commit()

                return True
            except Exception, e:
                log.error(e)
Beispiel #34
0
    def performWithDataFeeds(self, station):
        s = self.settings
        URLHourly = "http://fawn.ifas.ufl.edu/controller.php/lastHour/summary/json"
        URLDaily = "http://fawn.ifas.ufl.edu/controller.php/lastDay/summary/json"
        URLParams = []

        useHourly = self.params.get("useHourly", False)
        
        #-----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        if useHourly:
            try:
                log.info("Retrieving data from: %s" % URLHourly)
                d = self.openURL(URLHourly, URLParams)
                if d is None:
                    return

                json_data = d.read()
                json_data = json_data.replace("'","\"")
                hourly = json.loads(json_data)

                for entry in hourly:
                    # only selected station
                    if int(entry.get("StationID")) == station:
                        dateString = entry.get("startTime")
                        #timestamp = rmTimestampFromDateAsStringWithOffset(dateString)
                        timestamp = rmTimestampFromDateAsString(dateString[:-6], '%Y-%m-%dT%H:%M:%S')
                        if timestamp is None:
                            log.debug("Cannot convert hourly data startTime: %s to unix timestamp" % dateString)
                            continue

                        # Add 12h in the future for FAWN timestamp to fix badly reported offset and make it middle of the day UTC (Dragos)
                        timestamp += 12 * 60 *60

                        self.addValue(RMParser.dataType.TEMPERATURE, timestamp, self.__toFloat(entry.get("t2m_avg")))
                        self.addValue(RMParser.dataType.MINTEMP, timestamp, self.__toFloat(entry.get("t2m_min")))
                        self.addValue(RMParser.dataType.MAXTEMP, timestamp, self.__toFloat(entry.get("t2m_max")))
                        # km/h -> m/s
                        self.addValue(RMParser.dataType.WIND, timestamp, 0.27777777777778 * self.__toFloat(entry.get("ws_avg")))
                        # cm -> mm
                        self.addValue(RMParser.dataType.RAIN, timestamp, 10 * self.__toFloat(entry.get("rain_sum")))
                        self.addValue(RMParser.dataType.DEWPOINT, timestamp, self.__toFloat(entry.get("dp_avg")))
                        self.addValue(RMParser.dataType.RH, timestamp, self.__toFloat(entry.get("rh_avg")))

                if self.parserDebug:
                    log.debug(self.result)

            except Exception, e:
                self.lastKnownError = "Error retrieving hourly data."
                log.error(self.lastKnownError)
                log.exception(e)
Beispiel #35
0
    def perform(self):
        s = self.settings
        URL = "https://api.met.no/weatherapi/locationforecastlts/1.3/"
        URLParams = [("lat", s.location.latitude),
                     ("lon", s.location.longitude),
                     ("msl", int(round(s.location.elevation)))]

        #-----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        d = self.openURL(URL, URLParams)
        if d is None:
            return

        tree = e.parse(d)
        #tree = e.parse("/tmp/MET.NO/forecast.xml")

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Error: No hourly information found"

            tree.getroot().clear()
            del tree
            tree = None
        else:
            data = self.__parseXMLData(tree)

            # Free memory
            tree.getroot().clear()
            del tree
            tree = None

            temp = self.__extractTagData(data, 'temperature')
            mintemp = self.__extractTagData(data, 'minTemperature')
            maxtemp = self.__extractTagData(data, 'maxTemperature')
            dewpoint = self.__extractTagData(data, 'dewpointTemperature')
            wind = self.__extractTagData(data, 'windSpeed')
            humidity = self.__extractTagData(data, 'humidity')
            pressure = self.__extractTagData(data, 'pressure')
            qpf = self.__extractTagData(data, 'precipitation')
            condition = self.__extractTagData(data, 'symbol')

            self.addValues(RMParser.dataType.TEMPERATURE, temp)
            self.addValues(RMParser.dataType.MINTEMP, mintemp)
            self.addValues(RMParser.dataType.MAXTEMP, maxtemp)
            self.addValues(RMParser.dataType.DEWPOINT, dewpoint)
            self.addValues(RMParser.dataType.WIND, wind)
            self.addValues(RMParser.dataType.RH, humidity)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.PRESSURE, pressure)
            self.addValues(RMParser.dataType.CONDITION, condition)
    def installParser(self, tempFilePath, fileName):
        filePath = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), "parsers",
                         fileName))
        shutil.move(tempFilePath, filePath)

        try:
            module = imp.load_source(fileName, filePath)

            log.info("  * Parser %s successful loaded from file '%s'" %
                     (fileName, filePath))
            parser = RMParser.parsers[-1]  # Last added parser
            enabled = parser.isEnabledForLocation(globalSettings.location.timezone, \
                                                  globalSettings.location.latitude, \
                                                  globalSettings.location.longitude
                                                  )

            parserConfig, isNew = self.parserTable.addParser(
                fileName, parser.parserName, enabled, parser.params)
            if not isNew:
                params = self.parserTable.getParserParams(parserConfig.dbID)
                if params:
                    parser.params = params
                RMParser.parsers.pop()
                #delete old entry
                pkeys = self.parsers.keys()
                for pkey in pkeys:
                    if parserConfig.dbID is pkey.dbID:
                        del self.parsers[pkey]

            self.parsers[parserConfig] = parser

            parserConfig.userDataTypes = self.userDataTypeTable.addRecords(
                parser.userDataTypes)
            self.parserUserDataTypeTable.addRecords(parserConfig.dbID,
                                                    parserConfig.userDataTypes)

            log.debug(parserConfig)

            return True

        except Exception as e:
            try:
                if os.path.exists(filePath):
                    os.remove(filePath)
            except Exception, e:
                log.exception(e)

            log.error("  * Error installing/loading parser %s from file '%s'" %
                      (fileName, filePath))
            log.exception(e)
    def __getSimpleForecast(self):
        try:
            tuple = datetime.datetime.fromtimestamp(int(
                time.time())).timetuple()
            dayTimestamp = int(
                datetime.datetime(tuple.tm_year, tuple.tm_mon,
                                  tuple.tm_mday).strftime("%s"))
            maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400
            simpleForecast = self.jsonResponse["forecast"]["simpleforecast"][
                "forecastday"]

            timestamp = []
            temperatureMax = []
            temperatureMin = []
            wind = []
            humidity = []
            qpf = []
            condition = []

            for dayF in simpleForecast:
                tt = self.__toInt(dayF["date"]["epoch"])
                tt = rmGetStartOfDay(tt)
                if tt > maxDayTimestamp:
                    break
                timestamp.append(self.__toInt(tt))
                temperatureMax.append(self.__toFloat(dayF["high"]["celsius"]))
                temperatureMin.append(self.__toFloat(dayF["low"]["celsius"]))
                windValue = self.__toFloat(dayF["avewind"]["kph"])
                if windValue is not None:
                    wind.append(windValue /
                                3.6)  # convertred from kmetersph to meterps
                humidity.append(self.__toFloat(dayF["avehumidity"]))
                qpf.append(self.__toFloat(dayF["qpf_allday"]["mm"]))
                condition.append(self.conditionConvert(dayF["conditions"]))

            temperatureMax = zip(timestamp, temperatureMax)
            temperatureMin = zip(timestamp, temperatureMin)
            wind = zip(timestamp, wind)
            humidity = zip(timestamp, humidity)
            qpf = zip(timestamp, qpf)
            condition = zip(timestamp, condition)

            self.addValues(RMParser.dataType.RH, humidity)
            self.addValues(RMParser.dataType.MAXTEMP, temperatureMax)
            self.addValues(RMParser.dataType.MINTEMP, temperatureMin)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.WIND, wind)
            self.addValues(RMParser.dataType.CONDITION, condition)

        except:
            log.error("Failed to get simple forecast")
    def __getForecastHourly(self, jsonData):
        try:
            #forecast hourly
            tuple = datetime.datetime.fromtimestamp(int(
                time.time())).timetuple()
            dayTimestamp = int(
                datetime.datetime(tuple.tm_year, tuple.tm_mon,
                                  tuple.tm_mday).strftime("%s"))
            maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400
            forecastArrray = jsonData["hourly_forecast"]

            timestampF = []
            temperatureF = []
            depointF = []
            windF = []
            humidityF = []
            qpf = []
            conditionF = []

            for hourF in forecastArrray:
                tt = self.__toInt(hourF["FCTTIME"]["epoch"])
                if tt > maxDayTimestamp:
                    break
                timestampF.append(self.__toInt(tt))
                temperatureF.append(self.__toFloat(hourF["temp"]["metric"]))
                depointF.append(self.__toFloat(hourF["dewpoint"]["metric"]))
                wind = self.__toFloat(hourF["wspd"]["metric"])
                if wind is not None:
                    windF.append(wind /
                                 3.6)  # convertred from kmetersph to meterps
                humidityF.append(self.__toFloat(hourF["humidity"]))
                qpf.append(self.__toFloat(hourF["qpf"]["metric"]))
                conditionF.append(self.conditionConvert(hourF["condition"]))

            temperatureF = zip(timestampF, temperatureF)
            depointF = zip(timestampF, depointF)
            windF = zip(timestampF, windF)
            humidityF = zip(timestampF, humidityF)
            qpf = zip(timestampF, qpf)
            conditionF = zip(timestampF, conditionF)

            self.addValues(RMParser.dataType.RH, humidityF)
            self.addValues(RMParser.dataType.TEMPERATURE, temperatureF)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.DEWPOINT, depointF)
            self.addValues(RMParser.dataType.WIND, windF)
            self.addValues(RMParser.dataType.CONDITION, conditionF)

        except:
            log.error("Failed to get hourly forecast!")
            self.lastKnownError = "Error: Failed to get forecast"
Beispiel #39
0
    def _randRange(self, min, max, step):
        factor = 100.0
        min = int(min * factor)
        max = int(max * factor)
        step = int(step * factor)

        try:
            if min == max:
                return min / factor
            if step == 0:
                return random.randrange(min, max) / factor
            return random.randrange(min, max, step) / factor
        except Exception, e:
            log.error(e)
Beispiel #40
0
 def doExecuteCommand(self, command):
     log.debug(command.name)
     try:
         if command.args is None and command.kwargs is None:
             command.result = command.command()
         elif command.kwargs is None:
             command.result = command.command(*command.args)
         elif command.args is None:
             command.result = command.command(**command.kwargs)
         else:
             command.result = command.command(*command.args, **command.kwargs)
     except Exception, e:
         log.error(command.name)
         log.error(e)
    def addRecord(self, zid, timestamp, day, startWaterLevel):
        if self.database.isOpen():
            try:
                self.database.execute(
                    "INSERT OR REPLACE INTO %s(zid, timestamp, day, startWaterLevel) "
                    "VALUES(?, ?, ?, ?)" % self._tableName,
                    (zid, timestamp, day, startWaterLevel),
                )

                self.database.commit()

                return True
            except Exception, e:
                log.error(e)
    def _randRange(self, min, max, step):
        factor = 100.0
        min = int(min * factor)
        max = int(max * factor)
        step = int(step * factor)

        try:
            if min == max:
                return min / factor
            if step == 0:
                return random.randrange(min, max) / factor
            return random.randrange(min, max, step) / factor
        except Exception, e:
            log.error(e)
def rmNTPFetch(server = "pool.ntp.org", withRequestDrift = False):

    import struct
    from socket import socket, AF_INET, SOCK_DGRAM

    requestPacket = '\x1b' + 47 * '\0'
    startTime = time.time()

    try:
        sock = socket(AF_INET, SOCK_DGRAM)
        sock.settimeout(5)
    except Exception, e:
        log.error("NTPFetch: Can't create socket")
        return None
    def perform(self):
        s = self.settings

        # Direct Forecast.io
        #URL = "https://api.forecast.io/forecast/d1deb05ce0bf3858054236e0171077e5/" + \
        #        `s.location.latitude` + "," + `s.location.longitude`

        appKey = self.params.get("appKey", None)
        if appKey is None:
            return

        if self.params["useProxy"]:
            # RainMachine Forecast.io proxy
            URL = s.doyDownloadUrl + "/api/forecast_io/forecast/" + appKey + "/" + \
                    str(s.location.latitude) + "," + str(s.location.longitude)
        else:
            URL = "https://api.forecast.io/forecast/" + appKey + "/" + \
                    str(s.location.latitude) + "," + str(s.location.longitude)

        URLParams = \
            [
                ("units", "si"),
                ("exclude", "currently,minutely,alerts,flags"),
                ("extend", "hourly")
            ]
        try:
            d = self.openURL(URL, URLParams)
            if d is None:
                return

            forecast = json.loads(d.read())

            dayTimestamp = rmCurrentDayTimestamp()
            maxDayTimestamp = dayTimestamp + globalSettings.parserDataSizeInDays * 86400

            hourly = []
            daily = []

            try:
                hourly = forecast["hourly"]["data"]
            except Exception, e:
                log.error("*** No hourly information found in response!")
                log.exception(e)

            try:
                daily = forecast["daily"]["data"]
            except Exception, e:
                log.error("*** No daily information found in response!")
                log.exception(e)
    def __refreshWatchDog(self):
        timestamp = rmCurrentTimestamp()

        if self.__lastWatchdogTimestamp is None or (timestamp - self.__lastWatchdogTimestamp) >= self.__watchDogTimeout:
            if self.__watchDogDescriptor is None:
                try:
                    self.__watchDogDescriptor = open(self.__watchDogFile, 'w')
                    log.info("Opened system watchdog file %s with timeout %d" % (self.__watchDogFile, self.__watchDogTimeout))
                except Exception, e:
                    log.error(e)
            try:
                self.__watchDogDescriptor.write(`timestamp`)
                self.__watchDogDescriptor.flush()
                log.debug("PING Hardware Watchdog")
            except Exception, e:
                log.error(e)
    def __buildUrl(self):
        apiKey =  self.params.get("apiKey", None)
        station = self.params.get("stationName", None)

        if apiKey is None or not apiKey or not isinstance(apiKey, str):
            log.error("No API Key provided")
            self.lastKnownError = "Error: No API Key provided"
            return None

        if station is None:
            log.error("No station name provided")
            self.lastKnownError = "Error: No station name provided"
            return None

        URL = "http://api.wunderground.com/api/" + str(apiKey) + "/conditions/q/pws:" + str(station) + ".json"

        return URL
    def sanitize(self, key, value):
        interval = self.limits.get(key, None)
        if interval is None:
            log.info("%s key not found in our limits definitions" % key)
            return value

        min = interval["min"]
        max = interval["max"]
        if min is not None and value < min:
            log.error("%s value %s less than limits minimum of %s" % (key, value, interval["min"]))
            return None

        if max is not None and value > max:
            log.error("%s value %s more than limits maximum of %s" % (key, value, interval["max"]))
            return None

        return value
    def __diagWifi(self):
        try:
            with open("/proc/net/wireless") as f:
                for line in f:
                    fields = line.strip().split()
                    #log.debug(fields)
                    if not fields[0].endswith(":"):
                        continue

                    log.debug("Wireless interface %s up" % fields[0])
                    self.__hasWifi = True
                    return
        except:
            log.error("Cannot find /proc entry for wireless diag")


        self.__hasWifi= False
    def installParser(self, tempFilePath, fileName):
        filePath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "parsers", fileName))
        shutil.move(tempFilePath, filePath)

        try:
            module = imp.load_source(fileName, filePath)

            log.info("  * Parser %s successful loaded from file '%s'" % (fileName, filePath))
            parser = RMParser.parsers[-1] # Last added parser
            enabled = parser.isEnabledForLocation(globalSettings.location.timezone, \
                                                  globalSettings.location.latitude, \
                                                  globalSettings.location.longitude
                                                  )

            parserConfig, isNew = self.parserTable.addParser(fileName, parser.parserName, enabled, parser.params)
            if not isNew:
                params = self.parserTable.getParserParams(parserConfig.dbID)
                if params:
                    parser.params = params
                RMParser.parsers.pop()
                #delete old entry
                pkeys = self.parsers.keys()
                for pkey in pkeys:
                    if parserConfig.dbID is pkey.dbID:
                        del self.parsers[pkey]

            self.parsers[parserConfig] = parser

            parserConfig.userDataTypes = self.userDataTypeTable.addRecords(parser.userDataTypes)
            self.parserUserDataTypeTable.addRecords(parserConfig.dbID, parserConfig.userDataTypes)

            log.debug(parserConfig)

            return True

        except Exception as e:
            try:
                if os.path.exists(filePath):
                    os.remove(filePath)
            except Exception, e:
                log.exception(e)

            log.error("  * Error installing/loading parser %s from file '%s'" % (fileName, filePath))
            log.exception(e)
    def perform(self):
        s = self.settings
        URL = "http://api.met.no/weatherapi/locationforecastlts/1.2/"
        URLParams = [("lat", s.location.latitude),
                  ("lon", s.location.longitude),
                  ("msl", int(round(s.location.elevation)))]
        #-----------------------------------------------------------------------------------------------
        #
        # Get hourly data.
        #
        d = self.openURL(URL, URLParams)
        if d is None:
            return

        tree = e.parse(d)

        if tree.getroot().tag == 'error':
            log.error("*** No hourly information found in response!")
            self.lastKnownError = "Error: No hourly information found"

            tree.getroot().clear()
            del tree
            tree = None
        else:
            temp = self.__parseWeatherTag(tree, 'temperature')
            dewpoint = self.__parseWeatherTag(tree, 'dewpointTemperature')
            wind = self.__parseWeatherTag(tree, 'windSpeed')
            humidity = self.__parseWeatherTag(tree, 'humidity')
            pressure = self.__parseWeatherTag(tree, 'pressure', 'float')
            qpf = self.__parseWeatherTag(tree, 'precipitation')
            condition = self.__parseWeatherTag(tree, 'symbol')

            tree.getroot().clear()
            del tree
            tree = None

            self.addValues(RMParser.dataType.TEMPERATURE, temp)
            self.addValues(RMParser.dataType.DEWPOINT, dewpoint)
            self.addValues(RMParser.dataType.WIND, wind)
            self.addValues(RMParser.dataType.RH, humidity)
            self.addValues(RMParser.dataType.QPF, qpf)
            self.addValues(RMParser.dataType.PRESSURE, pressure)
            self.addValues(RMParser.dataType.CONDITION, condition)
    def __refreshWIFI(self):
        timestamp = rmCurrentTimestamp()
        lastWIFICheckTimestamp = globalWIFI.wifiInterface.lastWIFICheckTimestamp
        oldIP = globalWIFI.wifiInterface.ipAddress

        if lastWIFICheckTimestamp is None or oldIP is None or (timestamp - lastWIFICheckTimestamp) >= self.__wifiRefreshTimeout:
            try:
                globalWIFI.detect()

                if oldIP != globalWIFI.wifiInterface.ipAddress:
                    log.info("Refreshed WIFI Information. (old: %s new ip: %s)" % (`oldIP`, `globalWIFI.wifiInterface.ipAddress`))

                if RMOSPlatform().AUTODETECTED == RMOSPlatform.ANDROID:
                    return

                # Handle None IP
                if globalWIFI.wifiInterface.ipAddress is None:
                    if self.__lastNoneIpTimestamp is None or (timestamp - self.__lastNoneIpTimestamp) < self.__wifiNoneIpTimeout:
                        # First occurrence of None IP     OR    we can wait some more time.
                        if self.__lastNoneIpTimestamp is None:
                            self.__lastNoneIpTimestamp = timestamp
                        log.debug("Refreshed WIFI Information - no IP detected. Give it some more time: %d seconds!" % (self.__wifiNoneIpTimeout - (timestamp - self.__lastNoneIpTimestamp), ))
                        return
                    else:
                        globalWIFI.restart()
                        log.warn("Refreshed WIFI Information - WIFI quick reloaded because no IP detected. New IP is %s" % `globalWIFI.wifiInterface.ipAddress`)

                self.__lastNoneIpTimestamp = None # Reset None IP timestamp.

                # Check if we never connected to this AP, set back AP mode and restart app
                if globalWIFI.wifiInterface.mode == "managed" and not globalWIFI.hasConnectedOnce():
                    if globalWIFI.wifiInterface.hasClientLink:
                        globalWIFI.saveHasConnectedOnce(True)
                    else:
                        log.warning("WIFI Watcher Client IP (%s) configuration failed, restarting in AP mode." % oldIP)
                        globalWIFI.setDefaultAP()
                        globalWIFI.saveHasConnectedOnce(False)
                        globalWIFI.restart()
                        self.__mainManager.touchWakeMessage()

            except Exception, e:
                log.error(e)
    def newHourlyRestriction(self, dayMinuteStart, minuteDuration, dayList=None):  # dayList all 1 - Daily

        if dayList is None:
            dayList = [1] * 7

        if len(dayList) < 7:
            log.error("Invalid day list received")
            return False

        r = RMUserSettingsHourlyRestriction()
        r.dayStartMinute = dayMinuteStart
        r.minuteDuration = minuteDuration
        r.onWeekDays = [d for d in dayList]

        # Save the restriction
        result = self.__hourlyRestrictionsTable.saveRestriction(r)

        self.hourlyRestrictions[r.uid] = r

        return r
    def run(self):

        restartApp = False

        while self.__running:
            #if RMOSPlatform().AUTODETECTED != RMOSPlatform.SIMULATED:
            #    self.__refreshWatchDog()

            if not self.__pause and self.__lock.acquire(False):
                try:
                    if self.__checkFactoryReset():
                        break

                    if not self.__checkThreads():
                        restartApp = True
                        break

                except Exception, e:
                    log.error(e)
                finally:
                    self.__lock.release()
    def perform(self):

        days = self.params["historicDays"]
        intervals = days / self.maxAllowedDays + (days % self.maxAllowedDays != 0)
        lastIntervalStartDay = datetime.date.today()

        if intervals > 1:
            days = self.maxAllowedDays

        log.debug("Days: %d Intervals: %d" % (days, intervals))

        for i in range(0, intervals):
            startDay = lastIntervalStartDay - datetime.timedelta(days=1) #CIMIS real data starts from yesterday
            endDay = startDay - datetime.timedelta(days=(days + 1))
            lastIntervalStartDay = endDay
            try:
                log.debug("Running CIMIS for startDay: %s endDay: %s" % (startDay, endDay))
                self.__retrieveData(endDay, startDay) # we call with startDay/endDay swapped because CIMIS expects historic intervals
            except Exception, e:
                log.error("*** Error running cimis parser")
                log.exception(e)
    def doHandleMessages(self, limit = None):
        if not limit is None:
            messageCount = 0

        while True:
            try:
                command = self.messageQueue.get(True, self.waitTimeout)
                if command.name == "shutdown":
                    return False
                else:
                    self.doExecuteCommand(command)

                    if not limit is None:
                        messageCount += 1
                        if limit <= messageCount:
                            break

            except Empty, e:
                break
            except Exception, e:
                log.error(e)
    def getPercentage(self):
        usage = 0
        try:
            startUsage = self.get()
            time.sleep(1)
            finalUsage = self.get()
            try:
                prevActive = startUsage['active']
                prevIdle = startUsage['idle']
                active = finalUsage['active']
                idle = finalUsage['idle']

                deltaActive = active - prevActive
                deltaIdle = idle - prevIdle

                usage = (float(deltaActive) / (deltaActive + deltaIdle)) * 100
            except ZeroDivisionError:
                pass

        except Exception, e:
            log.error("Cannot read cpu stats from %s because %s" % (self.statpath, str(e)))
    def getAll(self, programDict, programClass, programZonesClass):
        if self.database.isOpen():
            cursor = self.database.execute("SELECT * FROM %s ORDER BY uid ASC" % self._tableNamePrograms)
            for row in cursor:
                program = programClass(row["uid"])
                program.name = row["name"]
                program.type = row["type"]
                program.param = row["param"]
                program.active = row["active"]
                program.start_time = row["start_time"]
                program.start_date = row["start_date"]
                program.updated = row["updated"]
                program.cs_cycles = row["cs_cycles"]
                program.cs_min = row["cs_min"]
                program.delay = row["delay"]
                program.ignoreInternetWeather = row["ignoreInternetWeather"]
                program.futureField1 = row["futureField1"]
                program.freq_modified = row["freq_modified"]
                program.cs_on = row["cs_on"]
                program.delay_on = row["delay_on"]
                program.useWaterSense = row["useWaterSense"]

                programDict[row["uid"]] = program

            cursor = self.database.execute("SELECT * FROM %s ORDER BY pid ASC" % self._tableNameProgZones)
            for row in cursor:
                program = programDict.get(row["pid"])
                if program is None:
                    log.error("Missing Program entry for pid %s" % row["pid"])
                    continue
                zid = row["zid"]
                if zid is None:
                    log.error("No zid defined")
                    continue
                program.zoneLines[zid] = programZonesClass(zid)
                program.zoneLines[zid].duration = row["duration"]
                program.zoneLines[zid].active = row["active"]

            return True
        return False
    def perform(self):

        timeNow = rmNowDateTime()
        timeNow = rmNowDateTime().fromordinal(timeNow.toordinal()-1)
        yyyy = timeNow.year
        mm = timeNow.month
        dd = timeNow.day

        log.debug("Wunderground parser - perform")

        self.params["_nearbyStationsIDList"] = []
        self.params["_airportStationsIDList"] = []

        apiKey =  self.params.get("apiKey", None)
        if(apiKey is None or not apiKey or not isinstance(apiKey, str)):
            #TODO: implement xml WUnderground parser
            log.error("No API Key provided")
            self.lastKnownError = "Error: No API Key provided"
            return

        self.apiURL = "http://api.wunderground.com/api/" + str(apiKey) + "/geolookup/conditions/hourly10day/history_" + str(yyyy) + str(mm).zfill(2) + str(dd).zfill(2) +"/q/"

        if (self.params.get("useCustomStation")):
            stationName = self.params.get("customStationName")
            if(stationName is None or not stationName or not isinstance(stationName, str)):
                log.error("Station ID cannot be empty")
                self.lastKnownError = "Error: Station ID cannot be empty"
                return
            log.debug("getting data from specified station")
            if len(stationName) > 4:
                self.apiURL += "pws:" + stationName + ".json" #url for pws
            else:
                self.apiURL += stationName + ".json" #url for pws
        else:
            s = self.settings
            llat = s.location.latitude
            llon = s.location.longitude
            self.apiURL +=  str(llat) + "," + str(llon) + ".json"

        # self.params["useCustomStation"] = False

        log.debug(self.apiURL)
        d = self.openURL(self.apiURL)
        jsonContent = d.read()
        if jsonContent is None:
            log.error("Failed to get WUnderground JSON contents")
            self.lastKnownError = "Error: Bad response"
            return

        self.jsonResponse = json.loads(jsonContent)

        #populate nearby stations
        log.debug("Wunderground parser - get nearby stations")
        self.getNearbyStations(self.jsonResponse)

        log.debug("Wunderground parser - get data")
        self.getStationData(self.jsonResponse)

        return