Current section
Files
Jump to
Current section
Files
lib/cli/reefwater.ex
defmodule Reef do
@moduledoc false
require Logger
import IO.ANSI
alias Dutycycle, as: DC
alias Dutycycle.Profile, as: DCP
alias Dutycycle.Server, as: DCS
alias Thermostat.Profile, as: THP
alias Thermostat.Server, as: THS
# def help do
# IO.puts(clear())
# IO.puts(yellow() <> underline() <> "Reef Control CLI" <> reset())
# IO.puts(" ")
#
# [
# %{cmd: "dcs_standby()", desc: "set Dutycycle to standby"},
# %{cmd: "ths_standby()", desc: "set Thermostat to standby"},
# %{cmd: "mix_air(profile)", desc: "set mix air profile"}
# ]
# |> Scribe.print(style: Scribe.Style.NoBorder)
# |> IO.puts()
# end
@add_salt "add salt"
def add_salt do
rmp() |> dc_activate_profile(@add_salt)
rma() |> DCS.activate_profile(@add_salt)
rmrf() |> dc_halt()
swmt() |> THS.activate_profile(standby())
end
def air(profile) when is_binary(profile),
do: dc_activate_profile(rma(), profile)
def air(_), do: print_usage("mix_air", "profile)")
def air_pause,
do: dc_halt(rma())
def air_resume,
do: dc_resume(rma())
def clean(start \\ true) do
if start do
halt_ato()
else
resume_ato()
end
end
def heat_standby do
[
{swmt(), swmt() |> THS.activate_profile(standby())},
{dt(), dt() |> THS.activate_profile(standby())}
]
end
def keep_fresh do
dc_activate_profile(rmp(), "keep fresh")
dc_activate_profile(rma(), "keep fresh")
end
def heat(p) when is_binary(p), do: THS.activate_profile(swmt(), p)
def heat(_), do: print_usage("mix_heat", "profile")
def match_display_tank do
THS.activate_profile(swmt(), "prep for change")
dc_activate_profile(rma(), "salt mix")
dc_activate_profile(rmp(), "salt mix")
status()
end
def pump(p) when is_binary(p), do: utility_pump(p)
def pump(_), do: print_usage("mix_pump", "profile")
def pump_off, do: utility_pump_off()
def pump_pause, do: dc_halt(rmp())
def pump_resume, do: dc_resume(rmp())
def rodi_boost, do: dc_activate_profile(rmrf(), "boost")
def rodi_final_fill, do: dc_activate_profile(rmrf(), "final fill")
def rodi_halt, do: dc_halt(rmrf())
def mix_standby do
dc_halt(rma())
dc_halt(rmp())
THS.standby(swmt())
end
def status(opts \\ []) do
opts = opts ++ [active: true]
Keyword.get(opts, :clear_screen, true) && IO.puts(clear())
print_heading("Reef Subsystem Status")
dcs = for name <- [rmp(), rma(), rmrf(), ato()], do: dc_status(name, opts)
ths = for name <- [swmt(), display_tank()], do: th_status(name, opts)
ss = for name <- [dt_sensor(), swmt_sensor()], do: sensor_status(name)
all = dcs ++ ths
:ok =
Scribe.print(all,
data: [
{"Subsystem", :subsystem},
{"Status", :status},
{"Active", :active}
]
)
|> IO.puts()
Scribe.print(ss,
data: [{"Sensor", :subsystem}, {"Temperature", :status}]
)
|> IO.puts()
end
def halt("display tank ato"), do: dc_activate_profile(ato(), "off")
def halt(name) when is_binary(name), do: dc_halt(name)
def halt_ato, do: dc_activate_profile(ato(), "off")
def halt_air, do: dc_halt(rma())
def halt_display_tank, do: ths_standby(dt())
def halt_pump, do: dc_halt(rmp())
def halt_rodi, do: dc_halt(rmrf())
def resume("display tank ato"), do: dc_halt(ato())
def resume(name) when is_binary(name), do: dc_resume(name)
def resume_ato, do: dc_halt(ato())
def resume_air, do: dc_resume(rma())
def resume_display_tank, do: ths_activate(dt(), "75F")
def resume_pump, do: dc_resume(rmp())
def resume_rodi, do: dc_resume(rmrf())
def ths_activate(th, profile)
when is_binary(th) and is_binary(profile),
do: THS.activate_profile(th, profile)
def ths_standby(th) when is_binary(th), do: THS.standby(th)
def ths_standby(th) when is_binary(th), do: THS.standby(th)
def utility_pump(p) when is_binary(p),
do: dc_activate_profile(rmp(), p)
def utility_pump(_), do: print_usage("utility_pump", "profile")
def utility_pump_off, do: rmp() |> dc_halt()
def water_change_begin(opts \\ [check_diff: true, interactive: true])
def water_change_begin(:help) do
IO.puts(water_change_begin_help())
end
def water_change_begin(opts) when is_list(opts) do
check_diff = Keyword.get(opts, :check_diff, true)
allowed_diff = Keyword.get(opts, :allowed_diff, 0.8)
interactive = Keyword.get(opts, :interactive, true)
mixtank_temp = Sensor.fahrenheit(name: "mixtank", since_secs: 30)
display_temp = Sensor.fahrenheit(name: "display_tank", since_secs: 30)
temp_diff = abs(mixtank_temp - display_temp)
if temp_diff > allowed_diff and check_diff do
if interactive do
IO.puts("--> WARNING <--")
IO.puts([
" Mixtank and Display Tank variance greater than ",
Float.to_string(allowed_diff)
])
IO.puts([
" Display Tank: ",
Float.round(display_temp, 1) |> Float.to_string(),
" Mixtank: ",
Float.round(mixtank_temp, 1) |> Float.to_string()
])
end
{:failed, {:temp_diff, temp_diff}}
else
rmp() |> halt()
rma() |> halt()
ato() |> halt()
swmt() |> THS.activate_profile(standby())
display_tank() |> THS.activate_profile(standby())
status()
{:ok}
end
end
def water_change_end do
rmp() |> halt()
rma() |> halt()
ato() |> halt()
swmt() |> THS.activate_profile(standby())
display_tank() |> THS.activate_profile("75F")
status()
end
def xfer_swmt_to_wst,
do: dc_activate_profile(rmp(), "mx to wst")
def xfer_wst_to_sewer,
do: dc_activate_profile(rmp(), "drain wst")
defp print_heading(text) when is_binary(text) do
IO.puts(" ")
IO.puts(light_yellow() <> underline() <> text <> reset())
IO.puts(" ")
end
defp print_usage(f, p),
do:
IO.puts(
light_green() <>
"USAGE: " <>
light_blue() <>
f <> "(" <> yellow() <> p <> light_blue() <> ")" <> reset()
)
def dc_activate_profile(name, p),
do:
DCS.activate_profile(name, p)
|> DC.status()
def dc_halt(name),
do: DCS.halt(name) |> DC.status()
def dc_resume(name),
do: DCS.resume(name) |> DC.status()
def dc_status(name, opts) do
%{
subsystem: name,
status: DCS.profiles(name, opts) |> DCP.name(),
active: DCS.active?(name)
}
end
defp sensor_status(name) do
temp_format = fn sensor ->
temp = Sensor.fahrenheit(name: sensor, since_secs: 30)
if is_nil(temp) do
temp
else
Float.round(temp, 1)
end
end
%{
subsystem: name,
status: temp_format.(name),
active: "-"
}
end
defp th_status(name, opts),
do: %{
subsystem: name,
status: THS.profiles(name, opts) |> THP.name(),
active: "-"
}
# constants
defp ato, do: "display tank ato"
defp display_tank, do: "display tank"
defp dt, do: display_tank()
defp dt_sensor, do: "display_tank"
defp rmrf, do: "mix rodi"
defp rma, do: "mix air"
defp rmp, do: "mix pump"
defp standby, do: "standby"
defp swmt, do: "mix tank"
defp swmt_sensor, do: "mixtank"
# help text
defp water_change_begin_help do
~S"""
Water Change Begin Help
usage: water_change_begin(opts :: [Keyword.t])
Options:
check_diff: Boolean.t
Default: true
Check the difference between the Display Tank and Mixtank before
beginning water change. If the difference is less than or equal to
allowed difference then proceed. If the difference is greater than
the allowed difference water change is not started.
allowed_diff: Float.t
Default: 0.8
The allowed temperature difference between the Display Tank and Mixtank.
Examples:
water_change_begin(check_diff: false)
water_change_begin(allowed_diff: 0.9)
"""
end
end