Ottenere terremoti INGV su tema Belchertown

Nel caso in cui si aggiorni la skin, le modifiche al file belchertown.py dovranno essere riapplicate prima di eseguire Weewx, altrimenti andrà in crash!
Arrestare Weewx

Assicurarsi che Weewx non sia in esecuzione:

sudo systemctl stop weewx

Oppure:

sudo /etc/init.d/weewx stop
Modifiche al file belchertown.py

Modificare il file /bin/user/belchertown.py; sostituire il seguente blocco:

        # ==============================================================================
        # Earthquake Data
        # ==============================================================================

        # Only process if Earthquake data is enabled
        if self.generator.skin_dict["Extras"]["earthquake_enabled"] == "1":
            earthquake_file = html_root + "/json/earthquake.json"
            earthquake_stale_timer = self.generator.skin_dict["Extras"][
                "earthquake_stale"
            ]
            latitude = self.generator.config_dict["Station"]["latitude"]
            longitude = self.generator.config_dict["Station"]["longitude"]
            distance_unit = self.generator.converter.group_unit_dict["group_distance"]
            eq_distance_label = self.generator.skin_dict["Units"]["Labels"].get(
                distance_unit, ""
            )
            eq_distance_round = self.generator.skin_dict["Units"]["StringFormats"].get(
                distance_unit, "%.1f"
            )
            earthquake_maxradiuskm = self.generator.skin_dict["Extras"][
                "earthquake_maxradiuskm"
            ]
            # Sample URL from Belchertown Weather:
            # http://earthquake.usgs.gov/fdsnws/event/1/query?limit=1&lat=42.223&lon=-72.374&maxradiuskm=1000&format=geojson&nodata=204&minmag=2
            if self.generator.skin_dict["Extras"]["earthquake_server"] == "USGS":
                earthquake_url = (
                    "http://earthquake.usgs.gov/fdsnws/event/1/query?limit=1&lat=%s&lon=%s&maxradiuskm=%s&format=geojson&nodata=204&minmag=2"
                    % (latitude, longitude, earthquake_maxradiuskm)
                )
            elif self.generator.skin_dict["Extras"]["earthquake_server"] == "GeoNet":
                earthquake_url = (
                    "https://api.geonet.org.nz/quake?MMI=%s"
                    % self.generator.skin_dict["Extras"]["geonet_mmi"]
                )
            elif self.generator.skin_dict["Extras"]["earthquake_server"] == "ReNaSS":
                # Calculate min/max latitude and min/max longitude from radius and station location. https://stackoverflow.com/a/23118314
                lat = float(latitude)
                long = float(longitude)
                radiusInKm = int(earthquake_maxradiuskm)

                kmInLongitudeDegree = 111.320 * cos( lat / 180.0 * pi)

                deltaLat = radiusInKm / 111.1
                deltaLong = radiusInKm / kmInLongitudeDegree

                minLat = lat - deltaLat
                maxLat = lat + deltaLat
                minLong = long - deltaLong
                maxLong = long + deltaLong

                earthquake_url = (
                    "https://api.franceseisme.fr/fdsnws/event/1/query?eventtype=earthquake&minmagnitude=2&minlatitude=%.2f&minlongitude=%.2f&maxlatitude=%.2f&maxlongitude=%.2f&format=json&limit=1&orderby=time"
                    % (minLat, minLong, maxLat, maxLong) 
                )
            earthquake_is_stale = False

            # Determine if the file exists and get it's modified time
            if os.path.isfile(earthquake_file):
                if (int(time.time()) - int(os.path.getmtime(earthquake_file))) > int(
                    earthquake_stale_timer
                ):
                    earthquake_is_stale = True
            else:
                # File doesn't exist, download a new copy
                earthquake_is_stale = True

            # File is stale, download a new copy
            if earthquake_is_stale:
                # Download new earthquake data
                try:
                    if sys.version_info[0] >= 3:
                        from urllib.request import Request, urlopen
                    else:
                        # Python 2
                        from urllib2 import Request, urlopen

                    user_agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3"
                    headers = {"User-Agent": user_agent}
                    req = Request(earthquake_url, None, headers)
                    response = urlopen(req)
                    page = response.read()
                    response.close()
                    if weewx.debug:
                        logdbg(
                            "Downloading earthquake data using urllib2 was successful"
                        )
                except Exception as forecast_error:
                    if weewx.debug:
                        logdbg(
                            "Error downloading earthquake data with urllib2, reverting to curl and subprocess. "
                            "Full error: %s" % forecast_error
                        )
                    # Nested try - only execute if the urllib2 method fails
                    try:
                        import subprocess

                        command = 'curl -L --silent "%s"' % earthquake_url
                        p = subprocess.Popen(
                            command,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                        )
                        page = p.communicate()[0]
                        if weewx.debug:
                            logdbg(
                                "Downloading earthquake data with curl was successful."
                            )
                    except Exception as error:
                        raise Warning(
                            "Error downloading earthquake data using urllib2 and subprocess curl. "
                            "Your software may need to be updated, or the URL is incorrect. "
                            "You are trying to use URL: %s, and the error is: %s"
                            % (earthquake_url, error)
                        )

                # Save earthquake data to file. w+ creates the file if it
                # doesn't exist, and truncates the file and re-writes it
                # everytime
                try:
                    with open(earthquake_file, "wb+") as file:
                        try:
                            # Python 2/3
                            file.write(page.encode("utf-8"))
                        except:
                            # Catch errors caused by ASCII characters in Python2
                            file.write(page)
                        if weewx.debug:
                            logdbg("Earthquake data saved to %s" % earthquake_file)
                except IOError as e:
                    raise Warning(
                        "Error writing earthquake data to %s. Reason: %s"
                        % (earthquake_file, e)
                    )

            # Process the earthquake file
            with open(earthquake_file, "r") as read_file:
                try:
                    eqdata = json.load(read_file)
                except:
                    eqdata = ""

            try:
                if self.generator.skin_dict["Extras"]["earthquake_server"] == "USGS":
                    eqtime = eqdata["features"][0]["properties"]["time"] / 1000
                    equrl = eqdata["features"][0]["properties"]["url"]
                    if distance_unit == "km":
                        eqplace = eqdata["features"][0]["properties"]["place"]
                    else:  # assume miles
                        try:
                            eqmatched = match(
                                "(?P<distance>[0-9]*\.?[0-9]+) km(?P<rest>.*)$",
                                eqdata["features"][0]["properties"]["place"],
                            )
                            eqdist_km = eqmatched.group("distance")
                            eqdist_miles = round(float(eqdist_km) / 1.609, 1)
                            eqplace = (
                                str(eqdist_miles) + " miles" + eqmatched.group("rest")
                            )
                        except:
                            eqplace = eqdata["features"][0]["properties"]["place"]
                    eqmag = locale.format(
                        "%g", float(eqdata["features"][0]["properties"]["mag"])
                    )
                elif (
                    self.generator.skin_dict["Extras"]["earthquake_server"] == "ReNaSS"
                ):
                    eqtime = eqdata["features"][0]["properties"]["time"]
                    # convert time to UNIX format
                    eqtime = datetime.datetime.strptime(eqtime, "%Y-%m-%dT%H:%M:%S.%fZ")
                    eqtime = int(
                        (eqtime - datetime.datetime(1970, 1, 1)).total_seconds()
                    )
                    if match("fr_.*", system_locale):
                        equrl = eqdata["features"][0]["properties"]["url"]["fr"]
                        eqplace = eqdata["features"][0]["properties"]["description"]["fr"]
                    else:
                        equrl = eqdata["features"][0]["properties"]["url"]["en"]
                        eqplace = eqdata["features"][0]["properties"]["description"]["en"]
                    eqmag = format(
                         eqdata["features"][0]["properties"]["mag"], ".1f"
                    )
                elif (
                    self.generator.skin_dict["Extras"]["earthquake_server"] == "GeoNet"
                ):
                    eqtime = eqdata["features"][0]["properties"]["time"]
                    # convert time to UNIX format
                    eqtime = datetime.datetime.strptime(eqtime, "%Y-%m-%dT%H:%M:%S.%fZ")
                    eqtime = int(
                        (eqtime - datetime.datetime(1970, 1, 1)).total_seconds()
                    )
                    equrl = (
                        "https://www.geonet.org.nz/earthquake/"
                        + eqdata["features"][0]["properties"]["publicID"]
                    )
                    eqplace = eqdata["features"][0]["properties"]["locality"]
                    eqmag = locale.format(
                        "%g",
                        float(
                            round(eqdata["features"][0]["properties"]["magnitude"], 1)
                        ),
                    )
                eqlat = str(
                    round(eqdata["features"][0]["geometry"]["coordinates"][1], 4)
                )
                eqlon = str(
                    round(eqdata["features"][0]["geometry"]["coordinates"][0], 4)
                )
                eqdistance_bearing = self.get_gps_distance(
                    (float(latitude), float(longitude)),
                    (float(eqlat), float(eqlon)),
                    distance_unit,
                )
                eqdistance = locale.format(
                    "%g", float(eq_distance_round % eqdistance_bearing[0])
                )
                eqbearing = eqdistance_bearing[1]
                eqbearing_raw = eqdistance_bearing[2]
            except:
                # No earthquake data
                eqtime = label_dict["earthquake_no_data"]
                equrl = ""
                eqplace = ""
                eqmag = ""
                eqlat = ""
                eqlon = ""
                eqdistance = ""
                eqbearing = ""
                eqbearing_raw = ""

        else:
            eqtime = ""
            equrl = ""
            eqplace = ""
            eqmag = ""
            eqlat = ""
            eqlon = ""
            eqdistance = ""
            eqbearing = ""
            eqbearing_raw = ""
            eq_distance_label = ""

Con questo:

        # ==============================================================================
        # Earthquake Data
        # ==============================================================================

        # Only process if Earthquake data is enabled
        if self.generator.skin_dict["Extras"]["earthquake_enabled"] == "1":
            earthquake_file = html_root + "/json/earthquake.json"
            earthquake_stale_timer = self.generator.skin_dict["Extras"][
                "earthquake_stale"
            ]
            latitude = self.generator.config_dict["Station"]["latitude"]
            longitude = self.generator.config_dict["Station"]["longitude"]
            distance_unit = self.generator.converter.group_unit_dict["group_distance"]
            eq_distance_label = self.generator.skin_dict["Units"]["Labels"].get(
                distance_unit, ""
            )
            eq_distance_round = self.generator.skin_dict["Units"]["StringFormats"].get(
                distance_unit, "%.1f"
            )
            earthquake_maxradiuskm = self.generator.skin_dict["Extras"][
                "earthquake_maxradiuskm"
            ]
            # Sample URL from Belchertown Weather:
            # http://earthquake.usgs.gov/fdsnws/event/1/query?limit=1&lat=42.223&lon=-72.374&maxradiuskm=1000&format=geojson&nodata=204&minmag=2
            if self.generator.skin_dict["Extras"]["earthquake_server"] == "USGS":
                earthquake_url = (
                    "http://earthquake.usgs.gov/fdsnws/event/1/query?limit=1&lat=%s&lon=%s&maxradiuskm=%s&format=geojson&nodata=204&minmag=2"
                    % (latitude, longitude, earthquake_maxradiuskm)
                )
            elif self.generator.skin_dict["Extras"]["earthquake_server"] == "INGV":
                earthquake_url = (
                    "https://webservices.ingv.it/fdsnws/event/1/query?starttime=2020-01-01&lat=%s&lon=%s&maxradiuskm=%s&minmag=1.5&orderby=time&limit=1&format=geojson"
                    % (latitude, longitude, earthquake_maxradiuskm)
                )
            elif self.generator.skin_dict["Extras"]["earthquake_server"] == "GeoNet":
                earthquake_url = (
                    "https://api.geonet.org.nz/quake?MMI=%s"
                    % self.generator.skin_dict["Extras"]["geonet_mmi"]
                )
            elif self.generator.skin_dict["Extras"]["earthquake_server"] == "ReNaSS":
                # Calculate min/max latitude and min/max longitude from radius and station location. https://stackoverflow.com/a/23118314
                lat = float(latitude)
                long = float(longitude)
                radiusInKm = int(earthquake_maxradiuskm)

                kmInLongitudeDegree = 111.320 * cos( lat / 180.0 * pi)

                deltaLat = radiusInKm / 111.1
                deltaLong = radiusInKm / kmInLongitudeDegree

                minLat = lat - deltaLat
                maxLat = lat + deltaLat
                minLong = long - deltaLong
                maxLong = long + deltaLong

                earthquake_url = (
                    "https://api.franceseisme.fr/fdsnws/event/1/query?eventtype=earthquake&minmagnitude=2&minlatitude=%.2f&minlongitude=%.2f&maxlatitude=%.2f&maxlongitude=%.2f&format=json&limit=1&orderby=time"
                    % (minLat, minLong, maxLat, maxLong) 
                )
            earthquake_is_stale = False

            # Determine if the file exists and get it's modified time
            if os.path.isfile(earthquake_file):
                if (int(time.time()) - int(os.path.getmtime(earthquake_file))) > int(
                    earthquake_stale_timer
                ):
                    earthquake_is_stale = True
            else:
                # File doesn't exist, download a new copy
                earthquake_is_stale = True

            # File is stale, download a new copy
            if earthquake_is_stale:
                # Download new earthquake data
                try:
                    if sys.version_info[0] >= 3:
                        from urllib.request import Request, urlopen
                    else:
                        # Python 2
                        from urllib2 import Request, urlopen

                    user_agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3"
                    headers = {"User-Agent": user_agent}
                    req = Request(earthquake_url, None, headers)
                    response = urlopen(req)
                    page = response.read()
                    response.close()
                    if weewx.debug:
                        logdbg(
                            "Downloading earthquake data using urllib2 was successful"
                        )
                except Exception as forecast_error:
                    if weewx.debug:
                        logdbg(
                            "Error downloading earthquake data with urllib2, reverting to curl and subprocess. "
                            "Full error: %s" % forecast_error
                        )
                    # Nested try - only execute if the urllib2 method fails
                    try:
                        import subprocess

                        command = 'curl -L --silent "%s"' % earthquake_url
                        p = subprocess.Popen(
                            command,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                        )
                        page = p.communicate()[0]
                        if weewx.debug:
                            logdbg(
                                "Downloading earthquake data with curl was successful."
                            )
                    except Exception as error:
                        raise Warning(
                            "Error downloading earthquake data using urllib2 and subprocess curl. "
                            "Your software may need to be updated, or the URL is incorrect. "
                            "You are trying to use URL: %s, and the error is: %s"
                            % (earthquake_url, error)
                        )

                # Save earthquake data to file. w+ creates the file if it
                # doesn't exist, and truncates the file and re-writes it
                # everytime
                try:
                    with open(earthquake_file, "wb+") as file:
                        try:
                            # Python 2/3
                            file.write(page.encode("utf-8"))
                        except:
                            # Catch errors caused by ASCII characters in Python2
                            file.write(page)
                        if weewx.debug:
                            logdbg("Earthquake data saved to %s" % earthquake_file)
                except IOError as e:
                    raise Warning(
                        "Error writing earthquake data to %s. Reason: %s"
                        % (earthquake_file, e)
                    )

            # Process the earthquake file
            with open(earthquake_file, "r") as read_file:
                try:
                    eqdata = json.load(read_file)
                except:
                    eqdata = ""

            try:
                if self.generator.skin_dict["Extras"]["earthquake_server"] == "USGS":
                    eqtime = eqdata["features"][0]["properties"]["time"] / 1000
                    equrl = eqdata["features"][0]["properties"]["url"]
                    if distance_unit == "km":
                        eqplace = eqdata["features"][0]["properties"]["place"]
                    else:  # assume miles
                        try:
                            eqmatched = match(
                                "(?P<distance>[0-9]*\.?[0-9]+) km(?P<rest>.*)$",
                                eqdata["features"][0]["properties"]["place"],
                            )
                            eqdist_km = eqmatched.group("distance")
                            eqdist_miles = round(float(eqdist_km) / 1.609, 1)
                            eqplace = (
                                str(eqdist_miles) + " miles" + eqmatched.group("rest")
                            )
                        except:
                            eqplace = eqdata["features"][0]["properties"]["place"]
                    eqmag = locale.format(
                        "%g", float(eqdata["features"][0]["properties"]["mag"])
                    )
                elif (
                    self.generator.skin_dict["Extras"]["earthquake_server"] == "INGV"
                ):
                    eqtime = eqdata["features"][0]["properties"]["time"]
                    # convert time to UNIX format
                    eqtime = datetime.datetime.strptime(eqtime, "%Y-%m-%dT%H:%M:%S.%f")
                    eqtime = int(
                        (eqtime - datetime.datetime(1970, 1, 1)).total_seconds()
                    )
                    equrl = (
                        "https://terremoti.ingv.it/event/"
                        + str(eqdata["features"][0]["properties"]["eventId"])
                    )
                    eqplace = eqdata["features"][0]["properties"]["place"]
                    eqmag = locale.format(
                        "%g", float(eqdata["features"][0]["properties"]["mag"])
                    )
                elif (
                    self.generator.skin_dict["Extras"]["earthquake_server"] == "ReNaSS"
                ):
                    eqtime = eqdata["features"][0]["properties"]["time"]
                    # convert time to UNIX format
                    eqtime = datetime.datetime.strptime(eqtime, "%Y-%m-%dT%H:%M:%S.%fZ")
                    eqtime = int(
                        (eqtime - datetime.datetime(1970, 1, 1)).total_seconds()
                    )
                    if match("fr_.*", system_locale):
                        equrl = eqdata["features"][0]["properties"]["url"]["fr"]
                        eqplace = eqdata["features"][0]["properties"]["description"]["fr"]
                    else:
                        equrl = eqdata["features"][0]["properties"]["url"]["en"]
                        eqplace = eqdata["features"][0]["properties"]["description"]["en"]
                    eqmag = format(
                         eqdata["features"][0]["properties"]["mag"], ".1f"
                    )
                elif (
                    self.generator.skin_dict["Extras"]["earthquake_server"] == "GeoNet"
                ):
                    eqtime = eqdata["features"][0]["properties"]["time"]
                    # convert time to UNIX format
                    eqtime = datetime.datetime.strptime(eqtime, "%Y-%m-%dT%H:%M:%S.%fZ")
                    eqtime = int(
                        (eqtime - datetime.datetime(1970, 1, 1)).total_seconds()
                    )
                    equrl = (
                        "https://www.geonet.org.nz/earthquake/"
                        + eqdata["features"][0]["properties"]["publicID"]
                    )
                    eqplace = eqdata["features"][0]["properties"]["locality"]
                    eqmag = locale.format(
                        "%g",
                        float(
                            round(eqdata["features"][0]["properties"]["magnitude"], 1)
                        ),
                    )
                eqlat = str(
                    round(eqdata["features"][0]["geometry"]["coordinates"][1], 4)
                )
                eqlon = str(
                    round(eqdata["features"][0]["geometry"]["coordinates"][0], 4)
                )
                eqdistance_bearing = self.get_gps_distance(
                    (float(latitude), float(longitude)),
                    (float(eqlat), float(eqlon)),
                    distance_unit,
                )
                eqdistance = locale.format(
                    "%g", float(eq_distance_round % eqdistance_bearing[0])
                )
                eqbearing = eqdistance_bearing[1]
                eqbearing_raw = eqdistance_bearing[2]
            except:
                # No earthquake data
                eqtime = label_dict["earthquake_no_data"]
                equrl = ""
                eqplace = ""
                eqmag = ""
                eqlat = ""
                eqlon = ""
                eqdistance = ""
                eqbearing = ""
                eqbearing_raw = ""

        else:
            eqtime = ""
            equrl = ""
            eqplace = ""
            eqmag = ""
            eqlat = ""
            eqlon = ""
            eqdistance = ""
            eqbearing = ""
            eqbearing_raw = ""
            eq_distance_label = ""
Il codice sostituito preserva comunque la possibilità di scegliere gli altri 3 provider forniti dal tema Belchertown, anche se non utilizzabili in Italia (per mantenerne la compatibilità).

La query starttime=2020-01-01 serve come fallback per evitare lo scaricamento del file earthquake.json vuoto e di conseguenza mandare in crash Weewx quando non sono disponibili eventi sismici nell'ultima ora.

Per impostazione predefinita, il sistema scaricherà l'ultimo terremoto occorso, in ordine di tempo, con magnitudo maggiore o uguale a 1.5 sulla scala Richter; se si desidera modificare il limite minimo, cambiare questo valore nella query:

&minmag=1.5

con quello desiderato.

Modificare il file skin.conf

È ora possibile impostare il nuovo provider: aprire il file (...)/skins/Belchertown/skin.conf e modificare le seguenti stringhe come indicato:

    # Earthquake defaults
    earthquake_enabled = 1
    earthquake_maxradiuskm = 1000
    earthquake_stale = 3600
    earthquake_server = INGV

In questo caso il sistema scaricherà ogni ora l'ultimo evento nel raggio di 1000 km dal punto segnato nel file weewx.conf nella sezione relativa all'impostazione della latitudine/longitudine; è sempre possibile modificare i valori earthquake_maxradiuskm e earthquake_stale come desiderato.

Nel caso in cui il sistema non dovesse scaricare i dati all'intervallo desiderato (come accaduto a noi), impostare un crontab.
Ad esempio, per forzarne lo scaricamento ogni ora (installazione di Weewx da pacchetto Debian), inserire la seguente stringa:
00 * * * *  sudo rm /var/www/html/weewx/json/earthquake.json
Consultare questa pagina per trovare il percorso del file in base alla propria installazione, e questa pagina per maggiori informazioni sul crontab.
Variabili

• Per visualizzare la magnitudo (dell'ultimo terremoto):

$earthquake_magnitude

• Per visualizzare la data e l'ora (dell'ultimo terremoto):

$current(timestamp=$earthquake_time, max_delta=60).dateTime.format("%d/%m/%Y - %H:%M")

• Per visualizzare la località (dell'ultimo terremoto):

$earthquake_place

• Per visualizzare la distanza (dal punto dell'ultimo terremoto):

$earthquake_distance_away

• Per visualizzare la direzione (dal punto dell'ultimo terremoto):

$earthquake_bearing
La direzione ordinale dal punto dell'ultimo terremoto è visualizzata in inglese. Se la si desidera in italiano, inserire questo codice:
#if $earthquake_bearing == "N" 
                <span>N</span>
#else if $earthquake_bearing == "NNE"
                <span>NNE</span>
#else if $earthquake_bearing == "NE"
                <span>NE</span>
#else if $earthquake_bearing == "ENE"
                <span>ENE</span>
#else if $earthquake_bearing == "E"
                <span>E</span>
#else if $earthquake_bearing == "ESE"
                <span>ESE</span>
#else if $earthquake_bearing == "SE"
                <span>SE</span>
#else if $earthquake_bearing == "SSE"
                <span>SSE</span>
#else if $earthquake_bearing == "S"
                <span>S</span>
#else if $earthquake_bearing == "SSW"
                <span>SSO</span>
#else if $earthquake_bearing == "SW"
                <span>SO</span>
#else if $earthquake_bearing == "WSW"
                <span>OSO</span>
#else if $earthquake_bearing == "W"
                <span>O</span>
#else if $earthquake_bearing == "WNW"
                <span>ONO</span>
#else if $earthquake_bearing == "NW"
                <span>NO</span>
#else if $earthquake_bearing == "NNW"
                <span>NNO</span>
#end if
Autore: Meteo Ponte San Nicolò Admin