Develop a CoAP-based Environmental Monitoring System that retrieves weather and air quality data from the Open-Meteo API on demand, displays the data on a client dashboard using CoAP GET requests, and stores the retrieved data in Cloud DB.

Weather API
https://api.open-meteo.com/v1/forecast?latitude=10.0159&longitude=76.3419&current=temperature_
2m,relative_humidity_2m,weather_code

Air Quality API
https://air-quality-api.open-meteo.com/v1/air-quality?latitude=10.0159&longitude=76.3419&current=pm10,pm2_5,carbon_
monoxide,nitrogen_
dioxide,ozone,european_aqi

CoAP_Environmental_Monitoring/
│
├── server.py
├── dashboard.py
└── requirements.txt

pip install aiocoap requests streamlit pandas streamlit-autorefresh

server.py

import asyncio
import requests
import json

from aiocoap import *
from aiocoap.resource import Resource, Site

# Weather API
weather_url = "https://api.open-meteo.com/v1/forecast"

# Air Quality API
air_url = "https://air-quality-api.open-meteo.com/v1/air-quality"


# Create CoAP resource
class EnvironmentResource(Resource):

    async def render_get(self, request):

        print("\nFetching environmental data...")

        try:

            # Get weather data
            weather_response = requests.get(
                weather_url,
                params={
                    "latitude": 10.0159,
                    "longitude": 76.3419,
                    "current": "temperature_2m,relative_humidity_2m,weather_code"
                },
                timeout=20
            )

            weather_response.raise_for_status()

            weather = weather_response.json()

            # Get air quality data
            air_response = requests.get(
                air_url,
                params={
                    "latitude": 10.0159,
                    "longitude": 76.3419,
                    "current": "pm2_5,pm10,us_aqi"
                },
                timeout=20
            )

            air_response.raise_for_status()

            air = air_response.json()

            # Extract current values
            weather_data = weather["current"]
            air_data = air["current"]

            # Combine data
            data = {
                "temperature": weather_data["temperature_2m"],
                "humidity": weather_data["relative_humidity_2m"],
                "weather_code": weather_data["weather_code"],
                "pm2_5": air_data["pm2_5"],
                "pm10": air_data["pm10"],
                "us_aqi": air_data["us_aqi"],
                "recorded_at": weather_data["time"]
            }

            print("Environmental Data:")
            print(data)

            # Convert dictionary to JSON
            payload = json.dumps(data).encode("utf-8")

            # Send CoAP response
            return Message(
                payload=payload,
                content_format=ContentFormat.JSON
            )

        except Exception as e:

            print("Error:", e)

            return Message(
                code=INTERNAL_SERVER_ERROR,
                payload=str(e).encode("utf-8")
            )


# Start CoAP server
async def main():

    site = Site()

    # Register resource
    site.add_resource(
        ["environment"],
        EnvironmentResource()
    )

    # Start server
    await Context.create_server_context(
        site,
        bind=("127.0.0.1", 5683)
    )

    print("Environmental CoAP Server Started")
    print("Waiting for client requests...")

    # Keep server running
    await asyncio.get_running_loop().create_future()


if __name__ == "__main__":
    asyncio.run(main())

Open Supabase Dashboard.
Open your existing project or create a new project.
Go to SQL Editor → New Query.
Execute the following SQL:

CREATE TABLE environment_data (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    temperature FLOAT,
    humidity FLOAT,
    weather_code INTEGER,
    pm2_5 FLOAT,
    pm10 FLOAT,
    us_aqi FLOAT,
    recorded_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

dashboard.py

import streamlit as st
import pandas as pd
import requests
import json
import asyncio

from aiocoap import *
from streamlit_autorefresh import st_autorefresh

# Dashboard title
st.title("Environmental Monitoring Dashboard")

st.write("Weather and Air Quality Monitoring")

# Supabase configuration
URL = "YOUR_URL/rest/v1/environment_data"
API_KEY = "YOUR_API"

headers = {
    "apikey": API_KEY,
    "Authorization": "Bearer " + API_KEY,
    "Content-Type": "application/json",
    "Prefer": "return=minimal"
}

# Automatic refresh every 60 seconds
st_autorefresh(
    interval=60000,
    key="refresh"
)

# Function to get data from CoAP server
async def get_data():

    context = await Context.create_client_context()

    try:

        # CoAP GET request
        request = Message(
            code=GET,
            uri="coap://127.0.0.1:5683/environment"
        )

        response = await context.request(request).response

        if response.code != CONTENT:
            raise Exception("CoAP server returned an error")

        # Convert JSON response
        data = json.loads(
            response.payload.decode("utf-8")
        )

        return data

    finally:
        await context.shutdown()


# Fetch data from CoAP server
try:

    st.subheader("Fetching Environmental Data")

    data = asyncio.run(get_data())

    st.success("Data received from CoAP Server")

    # Store data in Supabase
    response = requests.post(
        URL,
        headers=headers,
        json=data,
        timeout=15
    )

    if response.status_code not in [200, 201]:
        st.error("Database Error: " + response.text)

    else:
        st.success("Data stored in Supabase")

    # Display latest readings
    st.subheader("Current Weather Information")

    col1, col2, col3 = st.columns(3)

    col1.metric(
        "Temperature",
        str(data["temperature"]) + " °C"
    )

    col2.metric(
        "Humidity",
        str(data["humidity"]) + " %"
    )

    col3.metric(
        "Weather Code",
        str(data["weather_code"])
    )

    st.subheader("Air Quality Information")

    col1, col2, col3 = st.columns(3)

    col1.metric(
        "PM2.5",
        str(data["pm2_5"]) + " µg/m³"
    )

    col2.metric(
        "PM10",
        str(data["pm10"]) + " µg/m³"
    )

    col3.metric(
        "US AQI",
        str(data["us_aqi"])
    )

    st.write("Last API observation:", data["recorded_at"])

except Exception as e:

    st.error("Unable to retrieve environmental data")
    st.write(str(e))


# Retrieve stored records from Supabase
st.subheader("Environmental Data History")

try:

    history_response = requests.get(
        URL,
        headers=headers,
        params={
            "select": "*",
            "order": "created_at.desc",
            "limit": "100"
        },
        timeout=15
    )

    if history_response.status_code == 200:

        df = pd.DataFrame(history_response.json())

        if not df.empty:

            st.dataframe(df)

            # Temperature graph
            st.subheader("Temperature History")

            st.line_chart(
                df.sort_values("created_at").set_index("created_at")[
                    ["temperature"]
                ]
            )

            # Humidity graph
            st.subheader("Humidity History")

            st.line_chart(
                df.sort_values("created_at").set_index("created_at")[
                    ["humidity"]
                ]
            )

            # Air Quality graph
            st.subheader("Air Quality History")

            st.line_chart(
                df.sort_values("created_at").set_index("created_at")[
                    ["pm2_5", "pm10"]
                ]
            )

        else:
            st.info("No historical data available.")

    else:
        st.error("Unable to retrieve database records.")

except requests.exceptions.RequestException as e:

    st.error("Database connection error")
    st.write(str(e))
