farmbot_os/farmbot_os/platform/target/network/utils.ex

142 lines
3.4 KiB
Elixir

defmodule Farmbot.Target.Network.Utils do
import Farmbot.Config, only: [get_config_value: 3]
require Farmbot.Logger
alias Farmbot.Target.Network.ScanResult
def build_hostap_ssid do
{:ok, hostname} = :inet.gethostname()
if String.starts_with?(to_string(hostname), "farmbot-") do
to_string('farmbot-' ++ Enum.take(hostname, -4))
else
to_string(hostname)
end
end
@doc "Scan on an interface."
def scan(iface) do
do_scan(iface)
|> ScanResult.decode()
|> ScanResult.sort_results()
|> ScanResult.decode_security()
|> Enum.filter(&Map.get(&1, :ssid))
|> Enum.map(&Map.update(&1, :ssid, nil, fn ssid -> to_string(ssid) end))
|> Enum.reject(&String.contains?(&1.ssid, "\\x00"))
|> Enum.uniq_by(fn %{ssid: ssid} -> ssid end)
end
defp wait_for_results(pid) do
Nerves.WpaSupplicant.request(pid, :SCAN_RESULTS)
|> String.trim()
|> String.split("\n")
|> tl()
|> Enum.map(&String.split(&1, "\t"))
|> reduce_decode()
|> case do
[] ->
Process.sleep(500)
wait_for_results(pid)
res ->
res
end
end
defp reduce_decode(results, acc \\ [])
defp reduce_decode([], acc), do: Enum.reverse(acc)
defp reduce_decode([[bssid, freq, signal, flags, ssid] | rest], acc) do
decoded = %{
bssid: bssid,
frequency: String.to_integer(freq),
flags: flags,
level: String.to_integer(signal),
ssid: ssid
}
reduce_decode(rest, [decoded | acc])
end
defp reduce_decode([[bssid, freq, signal, flags] | rest], acc) do
decoded = %{
bssid: bssid,
frequency: String.to_integer(freq),
flags: flags,
level: String.to_integer(signal),
ssid: nil
}
reduce_decode(rest, [decoded | acc])
end
defp reduce_decode([_ | rest], acc) do
reduce_decode(rest, acc)
end
def do_scan(iface) do
pid = :"Nerves.WpaSupplicant.#{iface}"
if Process.whereis(pid) do
Nerves.WpaSupplicant.request(pid, :SCAN)
wait_for_results(pid)
else
[]
end
end
def get_level(ifname, ssid) do
r = scan(ifname)
if res = Enum.find(r, &(Map.get(&1, :ssid) == ssid)) do
res.level
end
end
@doc "Tests if we can make dns queries."
def test_dns(hostname \\ nil)
def test_dns(nil) do
case get_config_value(:string, "authorization", "server") do
nil ->
test_dns(get_config_value(:string, "settings", "default_dns_name"))
url when is_binary(url) ->
%URI{host: hostname} = URI.parse(url)
test_dns(hostname)
end
end
def test_dns(hostname) when is_binary(hostname) do
test_dns(to_charlist(hostname))
end
def test_dns(hostname) do
:ok = :inet_db.clear_cache()
# IO.puts "testing dns: #{hostname}"
case :inet.parse_ipv4_address(hostname) do
{:ok, addr} -> {:ok, {:hostent, hostname, [], :inet, 4, [addr]}}
_ -> :inet_res.gethostbyname(hostname)
end
end
@fb_data_dir Farmbot.OS.FileSystem.data_path()
@tzdata_dir Application.app_dir(:tzdata, "priv")
def maybe_hack_tzdata do
case Tzdata.Util.data_dir() do
@fb_data_dir ->
:ok
_ ->
Farmbot.Logger.debug(3, "Hacking tzdata.")
objs_to_cp = Path.wildcard(Path.join(@tzdata_dir, "*"))
for obj <- objs_to_cp do
File.cp_r(obj, @fb_data_dir)
end
Application.put_env(:tzdata, :data_dir, @fb_data_dir)
:ok
end
end
end