Home Posts Tags Post Search Tag Search

Post 65

Weather App 12 - Publishing Sensor Data 01

Published on: 2025-08-27 Tags: elixir, Generators , Blog, Side Project, Phoenix, Nerves, Weather App, Poncho
Chapter 4 Publishing Sensor Data (47)
    Adding PostgreSQL to the Stack
        Starting off we need to create a new phoenix weather_tracker app we will use the command
            mix phx.new weather_tracker \
                --binary-id --no-webpack --no-html --no-gettext --no-dashboard

        With this being said you will need to have the right generator installed so if that doesn't work be sure to run this command within you linux console
            mix archive.install hex phx_new 1.5.8

        Once that is all setup we need to created the yml file and get into the proper location
            cd weather_tracker && touch docker-compose.yml
    
        Okay so now we can populate the file with
            version: '3.3'
                services:
                    postgres:
                        image: timescale/timescaledb:2.1.0-pg13
                        ports:
                        - '5432:5432'
                        volumes:
                        - postgres-data:/var/lib/postgresql/data
                        environment:
                        POSTGRES_PASSWORD: postgres
                        POSTGRES_USER: postgres
                volumes:
                    postgres-data: {}

        Starting the Docker Compose Stack
            docker-compose up

            With that we will have the docker container up and running we will need to do some work to it so leave it up if you need to close it you can just crtl+calculated
    
    Creating the Phoenix Application
        We will need to run some migrations so that we can persist the data from the sensors
            mix ecto.gen.migration set_up_weather_data_table
        
        We can now setup the migrations for that data table with the following. It should have created a file with a time stamp and the file name appended to the time stamp.
            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 :temperature_c, :decimal, null: false
                    add :pressure_pa, :decimal, null: false
                    add :humidity_rh, :decimal, null: false
                    add :light_lumens, :decimal, null: false
                    add :voc_index, :decimal, null: false
                    add :uv_index, :decimal, null: false
                    add :als_lux, :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

        This will setup the data table with the correct :atoms as names and will say what to do when we rool forward or what happens when we want to roll the database backwards. This will also make sure that we are running the timescale DB as the data table type.
            mix ecto.setup

        This is where I ran into issues with the timescale not being installed so I went to this website and then followed all the instructions
            https://docs.tigerdata.com/self-hosted/latest/install/installation-linux/

    Creating our Ecto Schema
        Now we need to set the way in which we add the correct values to the database. It will be in and called: 
            sensor_hub_poncho/weather_tracker/lib/weather_tracker/weather_conditions/weather_condition.ex

        defmodule WeatherTracker.WeatherConditions.WeatherCondition do
            use Ecto.Schema
            import Ecto.Changeset

            @allowed_fields [
                :temperature_c,
                :pressure_pa,
                :humidity_rh,
                :light_lumens,
                :voc_index,
                :uv_index,
                :als_lux
            ]

            @derive {Jason.Encoder, only: @allowed_fields}
            @primary_key false

            schema "weather_conditions" do
                field :timestamp, :naive_datetime
                field :temperature_c, :decimal
                field :pressure_pa, :decimal
                field :humidity_rh, :decimal
                field :light_lumens, :decimal
                field :voc_index, :decimal
                field :uv_index, :decimal
                field :als_lux, :decimal
            end

            def create_changset(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

    Creating the Phoenix Context Module
        Now we need the commands and code to instert any data to the database. This will be at: lib/weather_tracker/weather_conditions.ex and will be very simple as we don't need much from it. 
        defmodule WeatherTracker.WeatherConditions do
            alias WeatherTracker.{WeatherConditions.WeatherCondition, Repo}

            def create_weather_condition(attrs) do
                %WeatherCondition{}
                |> WeatherCondition.create_changeset(attrs)
                |> Repo.insert()
            end
        end