class PurpleAirApi::V1::GetSensors

Class for requesting sensor data. This will return different response formats from the API.

Constants

DEFAULT_FIELDS

The default value for fields that will be returned by PurpleAir

DEFAULT_LOCATION_TYPE

The default location type for the sensor

URL

The endpoint URL

Attributes

data[RW]
data_fields[RW]
http_client[R]
http_response[RW]
parsed_response[W]
request_options[RW]

Public Class Methods

call(...) click to toggle source

Calls initializes the class and requests the data from PurpleAir. @!method call(…)

# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 23
def self.call(...)
  new(...).request
end
new(client:, **options) click to toggle source

Creates a HTTP friendly options hash depending on your inputs @!method initialize(client:, **options) @param client [Faraday::Connection] Your HTTP client initialized in Client @param options [Hash] Your HTTP options for the request.

# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 32
def initialize(client:, **options)
  @http_client = client
  @request_options = {}
  create_options_hash(options)
end

Public Instance Methods

json_response() click to toggle source

Takes the raw response from PurpleAir and parses the JSON into a Hash. @!method json_response @return [Hash] @example json_response example

response.json_response
{
  :api_version=>"V1.0.6-0.0.9",
  :time_stamp=>1614787814,
  :data_time_stamp=>1614787807,
  :location_type=>0,
  :max_age=>3600,
  :fields=>["sensor_index", "name", "icon", "latitude", "longitude", "altitude", "pm2.5"],
  :data=>[
            [20, "Oakdale", 0, 40.6031, -111.8361, 4636, 0.0],
            [47, "OZONE TEST", 0, 40.4762, -111.8826, nil, nil]
         ]
}
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 91
def json_response
  @json_response ||= FastJsonparser.parse(http_response.body)
end
parsed_response() click to toggle source

Takes the raw response from PurpleAir and generates a hash indexed by sensor index. You can use this response like a normal hash object. This GetSensorsClass.parsed_response would return a hash of data for sensor 47 with each hash key labelling the associated data. @!method parsed_response @return [Hash] @example parsed_response example

response.parsed_response
{
  :fields=>["sensor_index", "name", "icon", "latitude", "longitude", "altitude", "pm2.5"],
  :api_version=>"V1.0.6-0.0.9",
  :time_stamp=>1614787814,
  :data_time_stamp=>nil,
  :max_age=>3600,
  :data=>
  {
    20=>{"sensor_index"=>20, "name"=>"Oakdale", "icon"=>0, "latitude"=>40.6031,
         "longitude"=>-111.8361, "altitude"=>4636, "pm2.5"=>0.0},
    47=>{"sensor_index"=>47, "name"=>"OZONE TEST", "icon"=>0, "latitude"=>40.4762,
         "longitude"=>-111.8826, "altitude"=>nil, "pm2.5"=>nil}
  }
}
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 69
def parsed_response
  @parsed_response ||= parse_response
end
request() click to toggle source

Makes a get request to the PurpleAir Get Sensors Data endpoint api.purpleair.com/v1/sensors. @!method request @return [PurpleAirApi::V1::GetSensors]

# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 42
def request
  self.http_response = http_client.get(URL, request_options)
  self
end

Private Instance Methods

bounding_box(coordinates) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 165
def bounding_box(coordinates)
  return {} if coordinates.nil?

  unless coordinates.instance_of?(Hash) && coordinates[:nw].length == 2 && coordinates[:se].length == 2
    raise OptionsError, 'coordinates must be a Hash with a :nw and :se array containing [lat, long]'
  end

  {
    nwlat: coordinates[:nw][0], nwlng: coordinates[:nw][1], selat: coordinates[:se][0], selng: coordinates[:se][1]
  }
end
create_options_hash(options) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 99
def create_options_hash(options)
  request_options.merge!(
    fields(options[:fields] || DEFAULT_FIELDS),
    location_type(options[:location_type]),
    show_only(options[:show_only]),
    modified_since(options[:modified_since]),
    max_age(options[:max_age]),
    bounding_box(options[:bounding_box]),
    read_keys(options[:read_keys])
  )
end
fields(fields_array) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 111
def fields(fields_array)
  unless fields_array.instance_of?(Array) && fields_array.first.instance_of?(String)
    raise OptionsError, 'fields must be an array of strings specifying the fields you want returned'
  end

  { fields: fields_array.join(',') }
end
generate_data_hash() click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 215
def generate_data_hash
  data_hash = {}
  data.each do |sensor|
    sensor_index = sensor.first
    data_hash.merge!(sensor_index => {})
    sensor.each_with_index do |data_point, index|
      data_hash[sensor_index].merge!(data_fields[index] => data_point)
    end
  end
  data_hash
end
generate_response_hash(response_hash) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 198
def generate_response_hash(response_hash)
  fields, api_version,
    time_stamp, date_time_stamp, max_age = response_hash.values_at(:fields, :api_version, :time_stamp,
                                                                   :date_time_stamp, :max_age)
  self.parsed_response = {
    fields: fields,
    api_version: api_version,
    time_stamp: time_stamp,
    data_time_stamp: date_time_stamp,
    max_age: max_age
  }
end
location_type(location_type) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 130
def location_type(location_type)
  return {} if location_type.nil?

  location_type_error unless location_type.instance_of?(Array) && location_type.first.instance_of?(String)

  location_type_parameter(location_type.map(&:downcase))
end
location_type_error() click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 146
def location_type_error
  raise OptionsError,
        "location_type must be an array of strings specifying either ['inside'], ['outside'], or both"
end
location_type_parameter(location_type) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 138
def location_type_parameter(location_type)
  return {} if location_type.include?('outside') && location_type.include?('inside')
  return { location_type: 1 } if location_type.include?('inside')
  return { location_type: 0 } if location_type.include?('outside')

  location_type_error
end
max_age(seconds) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 158
def max_age(seconds)
  return {} if seconds.nil?
  raise OptionsError, 'seconds must be a valid Integer' unless seconds.instance_of?(Integer)

  { max_age: seconds.to_i }
end
merge_data_hash() click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 211
def merge_data_hash
  parsed_response.merge!({ data: generate_data_hash })
end
modified_since(timestamp) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 151
def modified_since(timestamp)
  return {} if timestamp.nil?
  raise OptionsError, 'timestamp must be a valid Integer' unless timestamp.instance_of?(Integer)

  { modified_since: timestamp }
end
parse_response() click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 187
def parse_response
  response = json_response

  generate_response_hash(response)

  self.data = response[:data]
  self.data_fields = response[:fields]

  merge_data_hash
end
read_keys(keys) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 177
def read_keys(keys)
  return {} if keys.nil?

  unless keys.instance_of?(Array) && keys.first.instance_of?(String)
    raise OptionsError, 'read_keys must be an Array of Strings'
  end

  { read_keys: keys.join(',') }
end
show_only(sensor_indices) click to toggle source
# File lib/purple_air_api/V1/sensors/get_sensors.rb, line 119
def show_only(sensor_indices)
  return {} if sensor_indices.nil?

  unless sensor_indices.instance_of?(Array) && sensor_indices.first.instance_of?(Integer)
    raise OptionsError,
          'show_only must be an array of integers specifying the sensor indices you data returned for'
  end

  { show_only: sensor_indices.join(',') }
end