Привет, Хабр! Слышали о землетрясениях, которые происходят каждый день по всему миру? Как правило, если вы не сейсмолог или не живёте рядом с тектоническим разломом, то вам всё равно. Но информировать людей о реальных катастрофах в их регионе очень важно, покажем пример такой системы оповещения через SMS.
Сегодня мы построим небольшой центр уведомлений. За основу возьмем GeoJSON Earthquake API для получения данных о землетрясениях, подключим Exolve API, чтобы рассылать SMS, а для хранения данных используем PostgreSQL.
Что используем
GeoJSON Earthquake API — предоставляет данные о землетрясениях в формате GeoJSON. Включает координаты, магнитуду, время и другие параметры.
Exolve SMS API — позволяет отправлять SMS с динамическими шаблонами.
PostgreSQL — база данных для хранения землетрясений и логирования уведомлений.
RabbitMQ — очередь сообщений для асинхронной отправки SMS.
Python — связываем все компоненты в единую работающую систему.
Как всё будет работать
Получение данных: скрипт запрашивает данные о землетрясениях через GeoJSON API каждые 10 минут.
Фильтрация: геофильтры отбирают только события, которые относятся к нужному региону (например, России).
Обработка событий: новые события записываются в базу данных. Уведомления отправляются в RabbitMQ.
Асинхронная отправка SMS: RabbitMQ обрабатывает очередь, отправляя SMS через Exolve API.
Хранение истории: PostgreSQL сохраняет данные для аналитики.
Подготовка базы данных
Сначала создаём таблицы для хранения данных о землетрясениях и уведомлениях.
CREATE TABLE earthquakes (
id SERIAL PRIMARY KEY,
quake_id TEXT UNIQUE NOT NULL,
magnitude REAL NOT NULL,
place TEXT,
time TIMESTAMP NOT NULL,
longitude REAL NOT NULL,
latitude REAL NOT NULL
);
CREATE TABLE notifications (
id SERIAL PRIMARY KEY,
earthquake_id INTEGER REFERENCES earthquakes(id),
phone_number TEXT NOT NULL,
sent_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Таблица earthquakes хранит данные о землетрясениях. Поле quake_id уникальное, чтобы одно событие не записывалось дважды.
Таблица notifications логирует каждое отправленное SMS, связывая его с конкретным землетрясением.
Подключим RabbitMQ
RabbitMQ — это очередь сообщений, которая позволяет отправлять уведомления асинхронно. Установим RabbitMQ:
sudo apt install rabbitmq-server
sudo systemctl start rabbitmq-server
sudo systemctl enable rabbitmq-server
Теперь создадим очередь для уведомлений. Очереди делают обработку сообщений надёжной, даже если часть системы временно недоступна.
Подключимся к базе данных и RabbitMQ:
import psycopg2
import pika
# Подключение к PostgreSQL
def get_db_connection():
return psycopg2.connect(
dbname="earthquakes",
user="your_user",
password="your_password",
host="localhost"
)
# Инициализация RabbitMQ
def init_rabbitmq():
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='notifications')
return channel
get_db_connection() создаёт подключение к PostgreSQL, а init_rabbitmq() подключается к RabbitMQ и создаёт очередь notifications, если её ещё нет.
Работа с GeoJSON API и фильтрация событий
import requests
from datetime import datetime
from shapely.geometry import Point, Polygon
GEOJSON_API_URL = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson"
# Координаты границ региона (пример для России)
RUSSIA_BOUNDS = Polygon([
(19.0, 41.0), (19.0, 82.0), (169.0, 82.0), (169.0, 41.0), (19.0, 41.0)
])
def is_in_region(longitude, latitude):
point = Point(longitude, latitude)
return RUSSIA_BOUNDS.contains(point)
def fetch_earthquake_data():
response = requests.get(GEOJSON_API_URL)
if response.status_code != 200:
print(f"Ошибка API: {response.status_code}")
return []
data = response.json()
earthquakes = []
for feature in data["features"]:
props = feature["properties"]
coords = feature["geometry"]["coordinates"]
if props["mag"] >= 4.5 and is_in_region(coords[0], coords[1]):
earthquakes.append({
"id": feature["id"],
"magnitude": props["mag"],
"place": props["place"],
"time": datetime.fromtimestamp(props["time"] / 1000),
"longitude": coords[0],
"latitude": coords[1]
})
return earthquakes
fetch_earthquake_data() запрашивает данные с GeoJSON API и возвращает список землетрясений, которые соответствуют нашим фильтрам. is_in_region() проверяет, находится ли событие в пределах России.
Сохраним данные и отправим уведомления в RabbitMQ
def save_earthquake(conn, quake):
with conn.cursor() as cursor:
cursor.execute("""
INSERT INTO earthquakes (quake_id, magnitude, place, time, longitude, latitude)
VALUES (%s, %s, %s, %s, %s, %s)
ON CONFLICT (quake_id) DO NOTHING
""", (quake['id'], quake['magnitude'], quake['place'], quake['time'], quake['longitude'], quake['latitude']))
conn.commit()
def send_to_queue(channel, earthquake):
message = {
"place": earthquake["place"],
"magnitude": earthquake["magnitude"],
"time": earthquake["time"].strftime("%Y-%m-%d %H:%M:%S")
}
channel.basic_publish(exchange='', routing_key='notifications', body=json.dumps(message))
print(f"Сообщение отправлено в очередь: {message}")
save_earthquake() записывает событие в базу данных и send_to_queue() отправляет данные о землетрясении в очередь RabbitMQ для дальнейшей обработки.
Обработчик уведомлений
import requests
import json
EXOLVE_API_URL = "https://api.exolve.ru/messaging/v1/SendSMS"
EXOLVE_API_KEY = "Bearer your_api_key_here"
def process_notifications(ch, method, properties, body):
data = json.loads(body)
message = (
f"⚠ Землетрясение!\n"
f"Местоположение: {data['place']}\n"
f"Магнитуда: {data['magnitude']}\n"
f"Время: {data['time']}\n"
f"Рекомендация: Оставайтесь в безопасности."
)
payload = {
"number": "AlfaName",
"destination": "79991112233",
"text": message
}
headers = {
"Authorization": EXOLVE_API_KEY,
"Content-Type": "application/json"
}
response = requests.post(EXOLVE_API_URL, json=payload, headers=headers)
if response.status_code == 200:
print("SMS успешно отправлено")
else:
print(f"Ошибка SMS: {response.status_code}")
process_notifications() забирает данные из очереди и отправляет SMS через Exolve API.
Виды сообщений
Предупреждение: «⚠ Землетрясение! Магнитуда 5.4. Оставайтесь в безопасности!»
Рекомендация: «Следуйте к безопасной зоне. Проверьте перекрытие газа и воды.»
Статус: «Все системы работают. Угрозы нет.»
Заключение
Создали систему, которая:
Обрабатывает данные о землетрясениях.
Фильтрует события по географическим границам.
Отправляет уведомления с помощью RabbitMQ и Exolve API.
Хранит все данные в PostgreSQL.
Знайте, статья носит исключительно ознакомительный характер и не может использоваться как основа для построения системы раннего оповещения или критической инфраструктуры. Для реальных задач, связанных с чрезвычайными ситуациями, рекомендуется обращаться к специализированным службам и сертифицированным решениям.
Подписывайтесь на наш Хаб, следите за новыми гайдами и получайте приз
Каждый понедельник мы случайным образом выбираем победителей среди новых подписчиков нашего Хабр-канала и дарим крутые призы от МТС Exolve: стильные рюкзаки, лонгсливы и мощные беспроводные зарядки. Победители прошлых розыгрышей и правила.