Current section
Files
Jump to
Current section
Files
lib/calculate.ex
defmodule FlowerPower.Calculate do
@moduledoc"""
This module takes the data structure from the parrot flower power api calls and returns data
structures that are more digestable.
Steps to using this module:
1. Query api with a date range to get the data from the parrots web service
2. Pass the data graph to one of these functions to transform the data to a data structure
thats easier to reason about when used for situations like charting
"""
use Timex
@doc """
Calculates the daily soil moisture for the given day in the data graph that is retrieve
when calling the api service. The returned value will be a single number with unspecified
precision: 21.80029710232427
"""
def get_average_soil_moisture([]), do: []
def get_average_soil_moisture(data_graph) do
list_of_timestamps = get_samples_from data_graph
number_of_timestamps = Enum.count list_of_timestamps
total_soil_moisture =
Enum.map(list_of_timestamps, fn(sample_map) -> Dict.get(sample_map, "vwc_percent") end)
|> Enum.sum
total_soil_moisture / number_of_timestamps
end
@doc """
Returns a keyword list with the hour, soil moisture percentage and light intensity.
Example:
[{6, 23.911042707773333, 0.10000000000000002}, {7, 23.34991703012, 0.1}]
"""
def get_light_tempurature([], _), do: []
def get_light_tempurature(data_graph, sensor_read_date) do
get_samples_from(data_graph)
|> Enum.filter(fn sample -> Date.compare(get_date_from_sample(sample), sensor_read_date, :days) == 0 end)
|> Enum.group_by(&get_date_from_sample(&1).hour)
|> Enum.map(&average_hourly_light_tempurature/1)
end
defp average_hourly_light_tempurature(grouped_hourly_map) do
{_, hourly_map} = grouped_hourly_map
read_date = List.first(hourly_map) |> Dict.get "capture_ts"
hour_block = DateFormat.parse(read_date, "{ISOz}") |> extract_hour
number_of_reads = Enum.count hourly_map
total_tempurature = Enum.map(hourly_map, fn(x) -> Dict.get(x, "air_temperature_celsius") end)
|> Enum.sum
total_light = Enum.map(hourly_map, fn(x) -> Dict.get(x, "par_umole_m2s") end)
|> Enum.sum
{hour_block,total_tempurature/number_of_reads, total_light/number_of_reads}
end
@doc """
Gets the lowest moisture measurement of the day based on the day the sensor reading was taken
that's in the garden data graph. The sensor takes a reading every 15 minutes.
It returns a tuple in the following format:
{moisture_rate, timestamp}
"""
def get_lowest_moisture([], _), do: []
def get_lowest_moisture(data_graph, sensor_read_date) do
filter_samples(data_graph, sensor_read_date, fn(filtered_sample) ->
Enum.min_by(filtered_sample, fn sample -> Dict.get(sample, "vwc_percent") end)
end)
end
@doc """
Gets the highest moisture measurement of the day based on the day the sensor reading was taken
that's in the garden data graph. The sensor takes a reading every 15 minutes.
It returns a tuple in the following format:
{moisture_rate, timestamp}
"""
def get_highest_moisture([], _), do: []
def get_highest_moisture(data_graph, sensor_read_date) do
filter_samples(data_graph, sensor_read_date, fn(filtered_sample) ->
Enum.max_by(filtered_sample,fn sample -> Dict.get(sample, "vwc_percent") end)
end)
end
@doc """
Returns a keyword list that has the hour and the soil percentage for that hour in the
following format:
[{6, 22.639327889313865}, {7, 22.3569090340487}]
"""
def get_hourly_avg_soil_percentage([], _), do: []
def get_hourly_avg_soil_percentage(data_graph, sensor_read_date) do
get_samples_from(data_graph)
|> Enum.filter(fn sample -> Date.compare(get_date_from_sample(sample), sensor_read_date, :days) == 0 end)
|> Enum.group_by(&get_date_from_sample(&1).hour)
|> Enum.map(&average_hourly_data/1)
end
defp average_hourly_data(grouped_hourly_map) do
{_, hourly_map} = grouped_hourly_map
read_date = List.first(hourly_map) |> Dict.get "capture_ts"
hour_block = DateFormat.parse(read_date, "{ISOz}") |> extract_hour
number_of_reads = Enum.count hourly_map
total_soil_percentage = Enum.map(hourly_map, fn(x) -> Dict.get(x, "vwc_percent") end)
|> Enum.sum
{hour_block,total_soil_percentage/number_of_reads}
end
defp extract_hour({_, time_stamp}), do: time_stamp.hour
defp filter_samples(graph, sensor_read_date, criteria) do
list_of_timestamps = get_samples_from graph
return_tuple =
list_of_timestamps
|> Enum.filter(fn sample -> Date.compare(get_date_from_sample(sample), sensor_read_date, :days) == 0 end)
|> criteria.()
{Dict.get(return_tuple,"vwc_percent"),Dict.get(return_tuple, "capture_ts")}
end
defp get_date_from_sample(sample) do
{:ok, date} = Dict.get(sample, "capture_ts") |> DateFormat.parse("{ISOz}")
date
end
defp get_samples_from(data_graph), do: data_graph |> Dict.get "samples"
end