Class: SmoSepaKiwis::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/smo_sepa_kiwis/client.rb

Constant Summary collapse

DEFAULT_BASE_URL =
"https://timeseries.sepa.org.uk/KiWIS/KiWIS"

Instance Method Summary collapse

Constructor Details

#initialize(base_url: DEFAULT_BASE_URL, timeout: 60, user_agent: "smo_sepa_kiwis/#{VERSION}") ⇒ Client

Returns a new instance of Client.



12
13
14
15
16
17
18
19
20
# File 'lib/smo_sepa_kiwis/client.rb', line 12

def initialize(
  base_url: DEFAULT_BASE_URL,
  timeout: 60,
  user_agent: "smo_sepa_kiwis/#{VERSION}"
)
  @uri      = URI.parse(base_url)
  @timeout  = timeout
  @user_agent = user_agent
end

Instance Method Details

#rainfall_15min_inventoryObject

Returns Array<Hash> with combined station and timeseries fields. Uses two API calls (getTimeseriesList + getStationList) and joins in Ruby, because getTimeseriesList on SEPA’s instance rejects station detail fields.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/smo_sepa_kiwis/client.rb', line 46

def rainfall_15min_inventory
  ts_rows = request("getTimeseriesList",
    parametertype_name: "Precipitation",
    ts_path: "1/*/RE/15*",
    returnfields: "ts_id,ts_path,ts_name,station_no,coverage"
  )

  station_map = rainfall_stations.each_with_object({}) { |s, m| m[s.no] = s }

  ts_rows.map do |h|
    s      = station_map[h[:station_no].to_s]
    from_t = safe_parse_time(h[:from])
    to_t   = safe_parse_time(h[:to])
    {
      station_no:    presence(h[:station_no]),
      station_name:  s&.name,
      lat:           s&.lat,
      lon:           s&.lon,
      catchment:     s&.catchment,
      river:         s&.river,
      ts_id:         to_integer(h[:ts_id]),
      ts_path:       presence(h[:ts_path]),
      coverage_from: from_t,
      coverage_to:   to_t
    }
  end
end

#rainfall_15min_inventory_to_csv(path) ⇒ Object

Writes the full rainfall 15-min inventory to a CSV file.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/smo_sepa_kiwis/client.rb', line 88

def rainfall_15min_inventory_to_csv(path)
  rows = rainfall_15min_inventory
  CSV.open(path, "w") do |csv|
    csv << %w[station_no station_name lat lon catchment river ts_id ts_path coverage_from coverage_to]
    rows.each do |r|
      csv << [
        r[:station_no], r[:station_name], r[:lat], r[:lon],
        r[:catchment], r[:river],
        r[:ts_id], r[:ts_path],
        r[:coverage_from]&.strftime("%Y-%m-%dT%H:%M:%SZ"),
        r[:coverage_to]&.strftime("%Y-%m-%dT%H:%M:%SZ")
      ]
    end
  end
end

#rainfall_15min_timeseries(station_no:) ⇒ Object

Returns Array<Timeseries> for a given station_no.



33
34
35
36
37
38
39
40
41
# File 'lib/smo_sepa_kiwis/client.rb', line 33

def rainfall_15min_timeseries(station_no:)
  rows = request("getTimeseriesList",
    station_no: station_no,
    parametertype_name: "Precipitation",
    ts_path: "1/*/RE/15*",
    returnfields: "ts_id,ts_path,ts_name,station_no,coverage"
  )
  rows.map { |h| build_timeseries(h) }
end

#rainfall_stationsObject

Returns Array<Station>. Fetches all rainfall stations from SEPA.



23
24
25
26
27
28
29
30
# File 'lib/smo_sepa_kiwis/client.rb', line 23

def rainfall_stations
  rows = request("getStationList",
    stationparameter_no: "RE",
    returnfields: "station_no,station_name,station_latitude,station_longitude," \
                  "catchment_name,river_name"
  )
  rows.map { |h| build_station(h) }
end

#timeseries_values(ts_id:, from:, to:, chunk_days: nil) ⇒ Object

Returns Array<Value>. Accepts String/Date/Time/DateTime for from/to. If chunk_days is set, splits the window into N-day chunks and concatenates results.



76
77
78
79
80
81
82
83
84
85
# File 'lib/smo_sepa_kiwis/client.rb', line 76

def timeseries_values(ts_id:, from:, to:, chunk_days: nil)
  from_time = parse_time_arg(from)
  to_time   = parse_time_arg(to)

  if chunk_days
    fetch_chunked(ts_id: ts_id, from: from_time, to: to_time, chunk_days: chunk_days)
  else
    fetch_values(ts_id: ts_id, from: from_time, to: to_time)
  end
end

#timeseries_values_to_csv(ts_id:, from:, to:, path:, chunk_days: nil) ⇒ Object

Writes timeseries values to a CSV file.



105
106
107
108
109
110
111
112
113
# File 'lib/smo_sepa_kiwis/client.rb', line 105

def timeseries_values_to_csv(ts_id:, from:, to:, path:, chunk_days: nil)
  values = timeseries_values(ts_id: ts_id, from: from, to: to, chunk_days: chunk_days)
  CSV.open(path, "w") do |csv|
    csv << %w[timestamp value quality_code]
    values.each do |v|
      csv << [v.timestamp.strftime("%Y-%m-%dT%H:%M:%SZ"), v.value, v.quality_code]
    end
  end
end