added weather tracker json endpoint including controller, changeset and context; removed swoosh, added decimal dependency

master
Stefan Haslinger (root) 2022-03-22 11:10:40 +01:00
parent 46c537c308
commit c28848d811
9 changed files with 118 additions and 96 deletions

View File

@ -1,36 +1,15 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
# General application configuration
import Config
config :weather_tracker,
ecto_repos: [WeatherTracker.Repo],
generators: [binary_id: true]
# Configures the endpoint
config :weather_tracker, WeatherTrackerWeb.Endpoint,
url: [host: "localhost"],
render_errors: [view: WeatherTrackerWeb.ErrorView, accepts: ~w(json), layout: false],
pubsub_server: WeatherTracker.PubSub,
live_view: [signing_salt: "Fsg8to5A"]
# Configures the mailer
#
# By default it uses the "Local" adapter which stores the emails
# locally. You can see the emails in your browser, at "/dev/mailbox".
#
# For production it's recommended to configure a different adapter
# at the `config/runtime.exs`.
config :weather_tracker, WeatherTracker.Mailer, adapter: Swoosh.Adapters.Local
# Swoosh API client is needed for adapters other than SMTP.
config :swoosh, :api_client, false
# Configure esbuild (the version is required)
config :esbuild,
version: "0.14.0",
default: [
@ -40,14 +19,10 @@ config :esbuild,
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"

View File

@ -1,6 +1,5 @@
import Config
# Configure your database
config :weather_tracker, WeatherTracker.Repo,
username: "postgres",
password: "postgres",
@ -10,55 +9,16 @@ config :weather_tracker, WeatherTracker.Repo,
show_sensitive_data_on_connection_error: true,
pool_size: 10
# For development, we disable any cache and enable
# debugging and code reloading.
#
# The watchers configuration can be used to run external
# watchers to your application. For example, we use it
# with esbuild to bundle .js and .css sources.
config :weather_tracker, WeatherTrackerWeb.Endpoint,
# Binding to loopback ipv4 address prevents access from other machines.
# Change to `ip: {0, 0, 0, 0}` to allow access from other machines.
http: [ip: {127, 0, 0, 1}, port: 4000],
http: [ip: {0, 0, 0, 0}, port: 4000],
check_origin: false,
code_reloader: true,
debug_errors: true,
secret_key_base: "B2lyyYo7TXCmYFhzSYG/oXfEnwIqUBu47pd53IT1HNSHzHqsdjQu5GXzFUPAjYgd",
watchers: [
# Start the esbuild watcher by calling Esbuild.install_and_run(:default, args)
esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
]
# ## SSL Support
#
# In order to use HTTPS in development, a self-signed
# certificate can be generated by running the following
# Mix task:
#
# mix phx.gen.cert
#
# Note that this task requires Erlang/OTP 20 or later.
# Run `mix help phx.gen.cert` for more information.
#
# The `http:` config above can be replaced with:
#
# https: [
# port: 4001,
# cipher_suite: :strong,
# keyfile: "priv/cert/selfsigned_key.pem",
# certfile: "priv/cert/selfsigned.pem"
# ],
#
# If desired, both `http:` and `https:` keys can be
# configured to run both http and https servers on
# different ports.
# Do not include metadata nor timestamps in development logs
config :logger, :console, format: "[$level] $message\n"
# Set a higher stacktrace during development. Avoid configuring such
# in production as building large stacktraces may be expensive.
config :phoenix, :stacktrace_depth, 20
# Initialize plugs at runtime for faster development compilation
config :phoenix, :plug_init_mode, :runtime

View File

@ -1,3 +0,0 @@
defmodule WeatherTracker.Mailer do
use Swoosh.Mailer, otp_app: :weather_tracker
end

View File

@ -0,0 +1,12 @@
defmodule WeatherTracker.WeatherConditions do
alias WeatherTracker.{
Repo,
WeatherConditions.WeatherCondition
}
def create_entry(attrs) do
%WeatherCondition{}
|> WeatherCondition.create_changeset(attrs)
|> Repo.insert()
end
end

View File

@ -0,0 +1,44 @@
defmodule WeatherTracker.WeatherConditions.WeatherCondition do
use Ecto.Schema
import Ecto.Changeset
@allowed_fields [
:altitude_m,
:pressure_pa,
:temperature_c,
:co2_eq_ppm,
:tvoc_ppb,
:uva_raw,
:uvb_raw,
:uvia,
:uvib,
:uvi
]
@derive {Jason.Encoder, only: @allowed_fields}
@primary_key false
schema "weather_conditions" do
field :timestamp, :naive_datetime
field :altitude_m, :decimal
field :pressure_pa, :decimal
field :temperature_c, :decimal
field :co2_eq_ppm, :decimal
field :tvoc_ppb, :decimal
field :uva_raw, :decimal
field :uvb_raw, :decimal
field :uvia, :decimal
field :uvib, :decimal
field :uvi, :decimal
end
def create_changeset(weather_condition = %__MODULE__{}, attrs) do
timestamp =
NaiveDateTime.utc_now()
|> NaiveDateTime.truncate(:second)
weather_condition
|> cast(attrs, @allowed_fields)
|> validate_required(@allowed_fields)
|> put_change(:timestamp, timestamp)
end
end

View File

@ -0,0 +1,30 @@
defmodule WeatherTrackerWeb.WeatherConditionsController do
use WeatherTrackerWeb, :controller
require Logger
alias WeatherTracker.{
WeatherConditions,
WeatherConditions.WeatherCondition
}
def create(conn, params) do
IO.inspect(params)
case WeatherConditions.create_entry(params) do
{:ok, weather_condition = %WeatherCondition{}} ->
Logger.debug("Successfully created a weather condition entry")
conn
|> put_status(:created)
|> json(weather_condition)
error ->
Logger.warn("Failed to create a weather entry: #{inspect(error)}")
conn
|> put_status(:unprocessable_entity)
|> json(%{message: "Poorly formatted payload"})
end
end
end

View File

@ -7,17 +7,6 @@ defmodule WeatherTrackerWeb.Router do
scope "/api", WeatherTrackerWeb do
pipe_through :api
end
# Enables the Swoosh mailbox preview in development.
#
# Note that preview only shows emails that were sent by the same
# node running the Phoenix server.
if Mix.env() == :dev do
scope "/dev" do
pipe_through [:fetch_session, :protect_from_forgery]
forward "/mailbox", Plug.Swoosh.MailboxPreview
end
post "/weather-conditions", WeatherConditionsController, :create
end
end

17
mix.exs
View File

@ -14,9 +14,6 @@ defmodule WeatherTracker.MixProject do
]
end
# Configuration for the OTP application.
#
# Type `mix help compile.app` for more information.
def application do
[
mod: {WeatherTracker.Application, []},
@ -24,13 +21,9 @@ defmodule WeatherTracker.MixProject do
]
end
# Specifies which paths to compile per environment.
defp elixirc_paths(:test), do: ["lib", "test/support"]
defp elixirc_paths(_), do: ["lib"]
# Specifies your project dependencies.
#
# Type `mix help deps` for examples and options.
defp deps do
[
{:phoenix, "~> 1.6.6"},
@ -38,20 +31,14 @@ defmodule WeatherTracker.MixProject do
{:ecto_sql, "~> 3.6"},
{:postgrex, ">= 0.0.0"},
{:esbuild, "~> 0.3", runtime: Mix.env() == :dev},
{:swoosh, "~> 1.3"},
{:telemetry_metrics, "~> 0.6"},
{:telemetry_poller, "~> 1.0"},
{:jason, "~> 1.2"},
{:plug_cowboy, "~> 2.5"}
{:plug_cowboy, "~> 2.5"},
{:decimal, "~> 2.0.0"}
]
end
# Aliases are shortcuts or tasks specific to the current project.
# For example, to install project dependencies and perform other setup tasks, run:
#
# $ mix setup
#
# See the documentation for `Mix` for more info on aliases.
defp aliases do
[
setup: ["deps.get", "ecto.setup"],

View File

@ -0,0 +1,28 @@
defmodule WeatherTracker.Repo.Migrations.SetUpWeatherDataTable do
use Ecto.Migration
def up do
execute("CREATE EXTENSION IF NOT EXISTS timescaledb")
create table(:weather_conditions, primary_key: false) do
add :timestamp, :naive_datetime, null: false
add :altitude_m, :decimal, null: false
add :pressure_pa, :decimal, null: false
add :temperature_c, :decimal, null: false
add :co2_eq_ppm, :decimal, null: false
add :tvoc_ppb, :decimal, null: false
add :uva_raw, :decimal, null: false
add :uvb_raw, :decimal, null: false
add :uvia, :decimal, null: false
add :uvib, :decimal, null: false
add :uvi, :decimal, null: false
end
execute("SELECT create_hypertable('weather_conditions', 'timestamp')")
end
def down do
drop table(:weather_conditions)
execute("DROP EXTENSION IF EXISTS timescaledb")
end
end