Chuyển tới nội dung chính

Data Models

Mô hình dữ liệu NGSI-LD và cấu trúc database của Smart Forecast.


NGSI-LD Overview

Smart Forecast sử dụng NGSI-LD (Next Generation Service Interface - Linked Data) làm chuẩn dữ liệu cho dữ liệu môi trường. NGSI-LD là tiêu chuẩn của ETSI, được FIWARE Foundation phát triển.

Tại sao NGSI-LD?

  • Tiêu chuẩn quốc tế - ETSI NGSI-LD specification
  • Linked Data - JSON-LD format với ngữ cảnh (context)
  • Smart Data Models - Sử dụng models chuẩn của FIWARE
  • Interoperability - Dễ tích hợp với các hệ thống Smart City khác

Context Broker

Orion-LD là Context Broker chính, lưu trữ và quản lý các NGSI-LD entities.

┌─────────────────┐
│ Data Source │
│ (OpenWeatherMap)│
└────────┬────────┘


┌─────────────────┐ ┌─────────────────┐
│ Ingestion │────►│ Orion-LD │
│ Service │ │ Context Broker │
└─────────────────┘ └────────┬────────┘

┌────────┴────────┐
│ │
▼ ▼
┌─────────┐ ┌──────────┐
│ MongoDB │ │PostgreSQL│
│(entities)│ │(history) │
└─────────┘ └──────────┘

WeatherObserved

Entity type cho dữ liệu thời tiết quan trắc được.

Schema

interface WeatherObserved {
id: string; // "urn:ngsi-ld:WeatherObserved:{stationId}-{timestamp}"
type: 'WeatherObserved';

// Location
location: GeoProperty; // GeoJSON Point
address?: {
addressLocality: string;
addressCountry: string;
};

// Time
dateObserved: DateTime;

// Temperature
temperature: number; // °C

// Humidity
relativeHumidity: number; // 0-1 (percentage)

// Pressure
atmosphericPressure: number; // hPa
pressureTendency?: number;

// Wind
windSpeed: number; // m/s
windDirection: number; // degrees (0-360)

// Precipitation
precipitation: number; // mm
snowHeight?: number; // cm

// Other
illuminance?: number; // lux
uVIndexMax?: number;

// Metadata
source: string;
dataProvider: string;
refDevice?: string; // Relationship to Device entity
}

Ví dụ NGSI-LD (Normalized)

{
"id": "urn:ngsi-ld:WeatherObserved:hanoi-01-2025-01-15T10:00:00Z",
"type": "WeatherObserved",
"location": {
"type": "GeoProperty",
"value": {
"type": "Point",
"coordinates": [105.8542, 21.0285]
}
},
"address": {
"type": "Property",
"value": {
"addressLocality": "Hà Nội",
"addressCountry": "VN"
}
},
"dateObserved": {
"type": "Property",
"value": "2025-01-15T10:00:00Z"
},
"temperature": {
"type": "Property",
"value": 25.5,
"unitCode": "CEL"
},
"relativeHumidity": {
"type": "Property",
"value": 0.75
},
"atmosphericPressure": {
"type": "Property",
"value": 1013.25,
"unitCode": "HPA"
},
"windSpeed": {
"type": "Property",
"value": 12.5,
"unitCode": "MTS"
},
"windDirection": {
"type": "Property",
"value": 180
},
"precipitation": {
"type": "Property",
"value": 0,
"unitCode": "MMT"
},
"source": {
"type": "Property",
"value": "OpenWeatherMap"
},
"@context": [
"https://raw.githubusercontent.com/smart-data-models/dataModel.Weather/master/context.jsonld"
]
}

Ví dụ NGSI-LD (Key-Values)

{
"id": "urn:ngsi-ld:WeatherObserved:hanoi-01-2025-01-15T10:00:00Z",
"type": "WeatherObserved",
"location": {
"type": "Point",
"coordinates": [105.8542, 21.0285]
},
"dateObserved": "2025-01-15T10:00:00Z",
"temperature": 25.5,
"relativeHumidity": 0.75,
"atmosphericPressure": 1013.25,
"windSpeed": 12.5,
"windDirection": 180,
"precipitation": 0,
"@context": ["https://smart-data-models.github.io/dataModel.Weather/context.jsonld"]
}

AirQualityObserved

Entity type cho dữ liệu chất lượng không khí.

Schema

interface AirQualityObserved {
id: string; // "urn:ngsi-ld:AirQualityObserved:{stationId}-{timestamp}"
type: 'AirQualityObserved';

// Location
location: GeoProperty;
address?: PostalAddress;

// Time
dateObserved: DateTime;

// Air Quality Index
airQualityIndex: number; // 0-500
airQualityLevel: 'good' | 'moderate' | 'unhealthy' | 'very_unhealthy' | 'hazardous';

// Particulate Matter
pm25?: number; // µg/m³
pm10?: number; // µg/m³
pm4?: number;

// Gases
no2?: number; // µg/m³
no?: number;
nox?: number;
so2?: number;
co?: number; // mg/m³
o3?: number;

// Weather conditions
temperature?: number;
relativeHumidity?: number;
windSpeed?: number;
windDirection?: number;

// Metadata
source: string;
reliability?: number; // 0-1
typeOfLocation: 'indoor' | 'outdoor';
}

Ví dụ NGSI-LD

{
"id": "urn:ngsi-ld:AirQualityObserved:hanoi-01-2025-01-15T10:00:00Z",
"type": "AirQualityObserved",
"location": {
"type": "GeoProperty",
"value": {
"type": "Point",
"coordinates": [105.8542, 21.0285]
}
},
"dateObserved": {
"type": "Property",
"value": "2025-01-15T10:00:00Z"
},
"airQualityIndex": {
"type": "Property",
"value": 85
},
"airQualityLevel": {
"type": "Property",
"value": "moderate"
},
"pm25": {
"type": "Property",
"value": 35.2,
"unitCode": "GQ"
},
"pm10": {
"type": "Property",
"value": 65.8,
"unitCode": "GQ"
},
"no2": {
"type": "Property",
"value": 28.5,
"unitCode": "GQ"
},
"so2": {
"type": "Property",
"value": 12.3,
"unitCode": "GQ"
},
"co": {
"type": "Property",
"value": 0.8,
"unitCode": "GP"
},
"@context": [
"https://raw.githubusercontent.com/smart-data-models/dataModel.Environment/master/context.jsonld"
]
}

AirQualityForecast

Entity type cho dự báo chất lượng không khí.

Schema

interface AirQualityForecast {
id: string; // "urn:ngsi-ld:AirQualityForecast:{stationId}-{timestamp}"
type: 'AirQualityForecast';

// Location
location: GeoProperty;
address?: PostalAddress;

// Time
dateIssued: DateTime; // Thời điểm phát hành dự báo
validFrom: DateTime; // Thời điểm bắt đầu hiệu lực
validTo: DateTime; // Thời điểm kết thúc hiệu lực

// Air Quality Index Forecast
airQualityIndex: number; // 0-500
airQualityLevel: 'good' | 'moderate' | 'unhealthy' | 'very_unhealthy' | 'hazardous';

// Particulate Matter Forecast
pm25?: number; // µg/m³
pm10?: number; // µg/m³

// Gases Forecast
no2?: number; // µg/m³
so2?: number;
co?: number; // mg/m³
o3?: number;

// Confidence
reliability?: number; // 0-1 (độ tin cậy của dự báo)

// Metadata
source: string;
dataProvider: string;
}

Ví dụ NGSI-LD

{
"id": "urn:ngsi-ld:AirQualityForecast:hanoi-01-2025-01-16T00:00:00Z",
"type": "AirQualityForecast",
"location": {
"type": "GeoProperty",
"value": {
"type": "Point",
"coordinates": [105.8542, 21.0285]
}
},
"dateIssued": {
"type": "Property",
"value": "2025-01-15T12:00:00Z"
},
"validFrom": {
"type": "Property",
"value": "2025-01-16T00:00:00Z"
},
"validTo": {
"type": "Property",
"value": "2025-01-16T23:59:59Z"
},
"airQualityIndex": {
"type": "Property",
"value": 95
},
"airQualityLevel": {
"type": "Property",
"value": "moderate"
},
"pm25": {
"type": "Property",
"value": 42.5,
"unitCode": "GQ"
},
"pm10": {
"type": "Property",
"value": 78.2,
"unitCode": "GQ"
},
"no2": {
"type": "Property",
"value": 32.0,
"unitCode": "GQ"
},
"reliability": {
"type": "Property",
"value": 0.85
},
"source": {
"type": "Property",
"value": "OpenWeatherMap"
},
"@context": [
"https://raw.githubusercontent.com/smart-data-models/dataModel.Environment/master/context.jsonld"
]
}

WeatherForecast

Entity type cho dự báo thời tiết.

Schema

interface WeatherForecast {
id: string;
type: 'WeatherForecast';

// Time
dateIssued: DateTime;
validFrom: DateTime;
validTo: DateTime;

// Location
location: GeoProperty;

// Forecast
temperature: number;
feelsLikeTemperature?: number;
relativeHumidity: number;
precipitationProbability: number; // 0-100
precipitation?: number;

// Wind
windSpeed: number;
windDirection: number;

// Weather type
weatherType: string; // "clear", "cloudy", "rain", etc.

// Metadata
source: string;
dayMaximum?: { temperature: number };
dayMinimum?: { temperature: number };
}

PostgreSQL Schema

users

CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(255),
role VARCHAR(50) DEFAULT 'CITIZEN', -- ADMIN, MANAGER, CITIZEN
fcm_token VARCHAR(500),
avatar_url VARCHAR(500),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);

alerts

CREATE TABLE alerts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(500) NOT NULL,
description TEXT,
severity VARCHAR(50) NOT NULL, -- low, medium, high, critical
type VARCHAR(100) NOT NULL, -- weather, flood, fire, air_quality
status VARCHAR(50) DEFAULT 'active', -- active, resolved, expired
affected_areas JSONB,
start_time TIMESTAMP,
end_time TIMESTAMP,
created_by UUID REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_alerts_status ON alerts(status);
CREATE INDEX idx_alerts_type ON alerts(type);
CREATE INDEX idx_alerts_severity ON alerts(severity);

incidents

CREATE TABLE incidents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(500) NOT NULL,
description TEXT,
type VARCHAR(100) NOT NULL, -- flood, fire, pollution, other
status VARCHAR(50) DEFAULT 'pending', -- pending, processing, resolved, rejected
location GEOGRAPHY(POINT, 4326),
address VARCHAR(500),
images JSONB DEFAULT '[]',
reported_by UUID REFERENCES users(id),
processed_by UUID REFERENCES users(id),
process_note TEXT,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_incidents_status ON incidents(status);
CREATE INDEX idx_incidents_type ON incidents(type);
CREATE INDEX idx_incidents_location ON incidents USING GIST(location);

stations

CREATE TABLE stations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
external_id VARCHAR(255) UNIQUE NOT NULL, -- ID từ OpenWeatherMap
name VARCHAR(255) NOT NULL,
city VARCHAR(255),
country VARCHAR(10),
location GEOGRAPHY(POINT, 4326),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_stations_external_id ON stations(external_id);
CREATE INDEX idx_stations_city ON stations(city);

weather_history

CREATE TABLE weather_history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
station_id UUID REFERENCES stations(id),
date_observed TIMESTAMP NOT NULL,
temperature DECIMAL(5,2),
humidity DECIMAL(5,2),
pressure DECIMAL(7,2),
wind_speed DECIMAL(5,2),
wind_direction INTEGER,
precipitation DECIMAL(5,2),
weather_type VARCHAR(100),
raw_data JSONB,
created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_weather_history_station ON weather_history(station_id);
CREATE INDEX idx_weather_history_date ON weather_history(date_observed);
CREATE INDEX idx_weather_history_station_date ON weather_history(station_id, date_observed);

air_quality_history

CREATE TABLE air_quality_history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
station_id UUID REFERENCES stations(id),
date_observed TIMESTAMP NOT NULL,
aqi INTEGER,
aqi_category VARCHAR(50),
pm25 DECIMAL(6,2),
pm10 DECIMAL(6,2),
no2 DECIMAL(6,2),
so2 DECIMAL(6,2),
co DECIMAL(6,2),
o3 DECIMAL(6,2),
raw_data JSONB,
created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_air_quality_history_station ON air_quality_history(station_id);
CREATE INDEX idx_air_quality_history_date ON air_quality_history(date_observed);
CREATE INDEX idx_air_quality_history_station_date ON air_quality_history(station_id, date_observed);

Smart Data Models References

ModelDocumentation
WeatherObservedGitHub
WeatherForecastGitHub
AirQualityObservedGitHub
AirQualityForecastGitHub

Tiếp theo