Привет, Хабр! Слышали о землетрясениях, которые происходят каждый день по всему миру? Как правило, если вы не сейсмолог или не живёте рядом с тектоническим разломом, то вам всё равно. Но информировать людей о реальных катастрофах в их регионе очень важно, покажем пример такой системы оповещения через 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: стильные рюкзаки, лонгсливы и мощные беспроводные зарядки. Победители прошлых розыгрышей и правила.
ссылка на оригинал статьи https://habr.com/ru/articles/875216/
Добавить комментарий