官术网_书友最值得收藏!

Exploring the GeoJSON format

GeoJSON is a format for recording geographic data structures, which includes support of geometric definitions, such as points and polygons. For example, the location of an earthquake's epicenter (point) and the area affected (polygon). Part of the GeoJSON can look as follows:

{
 "type":"Point",
 "coordinates":[122.3818333,45.0686667,12.9]
}
,
"id":"uw61022191"

Note

The previous example is a small excerpt from the feed that reports all earthquakes in the past hour (http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson). Take a moment to look at this feed and get a feel for the type of data this format contains.

To kick off this project, we will create a data-monitoring application that will record information from this feed. As this program will be running over a long period, we will want to add a logging feature to ensure it is running smoothly.

Fetching and recording the data

The main function in bin/main.dart will prompt the data to be downloaded each minute using an instance of the DataMonitor class. There are 1440 minutes in a day and the data files average at around 2k, so 3 megabytes of disk space a day is practical:

main() async {
  setupLogging();

  DataMonitor quakeMon = new DataMonitor();
  Duration updateInterval = new Duration(seconds: 60);

  new Timer.periodic(updateInterval, quakeMon.fetchData);
}

The main function is marked async, which gives you a clue that the implementation will make use of the await feature. The call to setupLogging will be covered in the next section of this chapter.

The implementation of DataMonitor is in lib/quakemonitorfs.dart, which contains the key method fetchData:

  fetchData(Timer timerFetch) async {
    try {
      var outDir = new Directory('data');
      if (!await outDir.exists()) {
        outDir.create();
      }

      log.info("Calling web service...");
      HttpClientRequest req = await geoClient.getUrl(Uri.parse(dataUrl));
      HttpClientResponse resp = await req.close();
      String latestFilePath = path.join('data', latestFilename);
      await resp.pipe(new File(latestFilePath).openWrite());
      String fileContents = await new File(latestFilePath).readAsString();

      var dataset = await JSON.decode(fileContents);

      int newId = int.parse(dataset['metadata']['generated'].toString());

      if (idPreviousFetch != newId) {
        idPreviousFetch = newId;
        var f = new File(path.join('data', '${newId}.txt'));
        await f.writeAsString(dataset.toString());
        log.fine("Saved $newId - ${dataset.toString()}");
      }
    } catch (exception, stacktrace) {
      log.severe("Exception fetching JSON.", exception, stacktrace);
    }
  }

Nearly every other line has an await! The program only has to process information every minute or so, therefore it does not require a responsive structure and a more linear approach is sufficient, though the code is still asynchronous.

The remote resource is processed first and the response closed off. The JSON string returned can be put straight into a file. Once this is completed, the fileContents variable is populated with the data from the file, which is then parsed by the JSON to return an object into the dataset.

The Id of the response is checked so that the same response is not saved twice. Note that the generated Id may be different, while the content is the same. The feed is more of a snapshot than a steady stream.

The data is saved off to the data folder using the id of the fetch as a text (.txt) file. To give some feedback, the id and JSON are written to the log file via the call to qlog.fine.

主站蜘蛛池模板: 东山县| 奉新县| 南召县| 乳源| 玉溪市| 祁门县| 宜城市| 山东省| 黎川县| 沾益县| 乌苏市| 平泉县| 武清区| 青岛市| 周宁县| 柳江县| 库伦旗| 彭阳县| 温宿县| 丹江口市| 秦安县| 白山市| 明光市| 赞皇县| 乃东县| 彭山县| 嘉兴市| 青海省| 桐城市| 灵寿县| 九寨沟县| 邹城市| 富民县| 威信县| 瓦房店市| 樟树市| 贞丰县| 龙岩市| 海城市| 全南县| 建瓯市|