Skip to content

spvoronin/future-AZS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

159 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

⛽ SAF — Smart AZS Future

Цифровая экосистема автономной модульной АЗС: FastAPI-бэкенд на чистом SQL, веб-интерфейс клиента, мониторинг состояния АЗС с системами безопасности с помощью датчиков и контроллера на базе esp32, дистанционное управление, вывод логов и телеметрии по MQTT.

Python FastAPI PostgreSQL React ESP32 MQTT License


📖 Содержание

📝 О проекте

SAF (Smart AZS Future) — контейнерная автономная АЗС (40-футовый морской контейнер + солнечные панели + дизель-генератор) с цифровым ядром, которое связывает:

  • клиентское веб-приложение;
  • интерфейс мониторинга для работников: бэкенд-платформу учёта станций, ТРК, резервуаров, цен и транзакций;
  • физический ESP32-контроллер на самой станции, который считывает показания датчиков, управляет работой АЗС (системы безопасности, ТРК, помещение КАЗС, генерация энергии);
  • MQTT-канал телеметрии между железом и сервером.

Бэкенд написан на асинхронном FastAPI с чистым SQL через psycopg2 (без ORM) — это даёт полный контроль над транзакциями и SQL-запросами, что критично для сценариев вроде одновременной блокировки колонки несколькими клиентами.


🗂 Структура репозитория

future-AZS/
├── Arduino/
│   ├── main/
│       ├── main.ino            # точка входа прошивки ESP32
│       ├── func.ino            # опрос датчиков, отрисовка на дисплее
│       ├── func_wifi.ino       # Wi-Fi/MQTT: подключение, телеметрия, приём команд
│       ├── config.h            # пины, таймеры, структура SensorData
│       ├── Cl_timestamp.h      # хелпер для NTP-времени
│       ├── foto.h              # растровая заставка для TFT-дисплея
│       └── demo_secrets.h      # шаблон для secrets.h (Wi-Fi/MQTT-доступы)
│    └── led/
│       └── led.ino             #прошивка на контроллер ленты (arduino nano)
├── WEB/
│   ├── backend/
│   │   ├── main.py             # точка входа FastAPI, подключение роутеров
│   │   ├── worker_mqtt.py      # подписчик MQTT → запись показаний в БД
│   │   ├── init.sql            # схема PostgreSQL
│   │   ├── routers/            # users, stations, pumps, prices, tanks, transactions, sensors
│   │   ├── schemas/schem.py    # Pydantic-модели запросов
│   │   └── analiz_num/         # прототип распознавания гос. номеров
│   └── frontend/                # HTML/CSS/JS клиент
├── requirements.txt
└── LICENCE

📐 Архитектура системы

┌────────────┐      HTTP/JSON       ┌────────────────────┐
│  Frontend  │ ───────────────────► │    FastAPI Core    │
│ (JS/HTML)  │ ◄─────────────────── │       API          │
└────────────┘                      └──────────┬─────────┘
                                               │ psycopg2 (raw SQL)
                                               ▼
                                      ┌──────────────────┐
                                      │    PostgreSQL    │
                                      │   (init.sql)     │
                                      └────────▲─────────┘
                                               │ INSERT телеметрии
                                      ┌────────┴─────────┐
                                      │  worker_mqtt.py  │◄──── MQTT broker
                                      └────────▲─────────┘        ▲
                                               │ подписка         │ публикация
                                               │ BV/SAF/sensors   │ телеметрии /
                                      ┌────────┴─────────┐        │ команды АЗС
                                      │  ESP32 (Arduino) │────────┘
                                      │ датчики + дисплей│
                                      └──────────────────┘

Данные о станциях, пользователях и колонках хранятся в PostgreSQL и отдаются через REST API. Показания датчиков со станции идут отдельным потоком через MQTT: прошивка публикует JSON-телеметрию, worker_mqtt.py слушает топик и пишет её в таблицу sensors; обратная команда ((например) включить/выключить ТРК) публикуется бэкендом в топик конкретной колонки и обрабатывается контроллером как переключение реле.

🖥 Backend (WEB/backend)

Backend на FastAPI разбит на роутеры по сущностям:

Файл Префикс Назначение
routers/users.py /users Регистрация, логин, профиль клиента (телефон, email, госномер number_of_car)
routers/stations.py /stations CRUD станций, привязка к региону, список ТРК на станции
routers/pumps.py /pumps CRUD ТРК: статус (idle / dispensing / error), доступность is_active
routers/prices.py /prices Цены на топливо по регионам, UPSERT через ON CONFLICT
routers/tanks.py /tanks Резервуары/отсеки станции: остатки, температура, пополнение (refill)
routers/transactions.py /transactions Оформление заказа на заправку
routers/sensors.py /sensors Последние показания датчиков станции, отправка MQTT-команды на ТРК

Модуль транзакций уже реализован: POST /transactions

  1. проверяет, что ТРК существует, активна (is_active) и свободна (status = 'idle');
  2. находит цену топлива для региона станции;
  3. блокирует подходящий резервуар с помощью SELECT ... FOR UPDATE, чтобы исключить гонку при параллельных заказах;
  4. списывает литры из резервуара, переводит ТРК в статус dispensing;
  5. создаёт запись в transactions со статусом progress и считает итоговую стоимость;
  6. фиксирует всё одной транзакцией (connection.commit() / rollback() при ошибке — autocommit=False).

Схема базы данных (init.sql)

region → station → pumps, station → tanks, region → prices, pumps/users → transactions, users → loyalty_cards, station → uuid → sensors. Отдельного внимания заслуживают:

  • uuid — таблица привязки физического устройства (ESP32) к конкретной станции;
  • sensors — сырые показания с контроллера: ток (electric_current), пламя, газ, влажность и температура воздуха, температура цистерны, уровень воды;
  • loyalty_cards — карты лояльности с бонусным балансом и персональной скидкой (в API пока не задействованы — задел на будущее).

🔧 Embedded / ESP32 (Arduino/main)

Прошивка контроллера станции — сердце физического слоя SAF. Устройство: ESP32, дисплей ST7735 (SPI), набор датчиков и одно силовое реле (в макете, далее выбранное оснащение).

Датчики и периферия (config.h):

Пин Датчик/модуль Что измеряет
DHT_PIN (14) DHT11 температура и влажность воздуха
DS18B20_PIN (26) DS18B20 (1-Wire) температура топлива в цистерне
FUEL_PIN (34) аналоговый уровнемер уровень топлива (0–100 %)
CURRENT_PIN (35) ACS712 ток потребления (мА)
FLAME_PIN (32) датчик пламени пожарная безопасность
GAZ_PIN (33) MQ-2 загазованность
RELAY_PIN (27) реле включение/выключение ТРК
TFT_CS/DC/RST/LED ST7735 TFT локальный дисплей с показаниями в реальном времени

Логика работы (main.ino, func.ino, func_wifi.ino):

  • при старте контроллер подключается к Wi-Fi, синхронизирует время по NTP (Cl_timestamp.h) и рисует стартовый экран с логотипом SAF;
  • каждую секунду (DISPLAY_INTERVAL) опрашивает все датчики и обновляет значения на экране;
  • каждые 5 секунд (MQTT_INTERVAL) собирает данные в JSON и публикует их в MQTT-топик (sendTelemetryMQTT) — именно этот пакет забирает worker_mqtt.py на бэкенде;
  • подписан на топик BV/SAF/{id} конкретной ТРК: получив сообщение "change", переключает состояние реле (callback в func_wifi.ino) — это и есть физическое включение/выключение колонки по команде из API (POST /sensors/pumps/{pumps_id});
  • отправляет командуphoto на BV/SAF/cam/request, при получении этой команды esp32cam делает снимок с номером, который улетает на сервер;
  • получает, декодирует и выводит на экран номер с топика BV/SAF/cam/response;
  • обрабатывает и переводит в нужный формат показания с датчиков с помощью фильтров и формул (напрмер для газа см. func.ino (getGasPPM())).

Реальные Wi-Fi/MQTT-данные и UUID устройства не хранятся в репозитории — используется secrets.h.gitignore), а шаблон для заполнения лежит в demo_secrets.h. Перед прошивкой контроллера скопируйте его в secrets.h и подставьте свои значения.

🌐 Frontend (WEB/frontend)

Лёгкий клиент на чистых HTML/CSS/JS, без сборщиков и фреймворков:

  • config.js — задаёт API_BASE (адрес бэкенда) и текущую станцию по умолчанию;
  • api.js — тонкая обёртка над fetch (Api.get/post/put/del) с готовыми методами под все нужные эндпоинты (логин, список станций, ТРК станции, цены, оформление заказа);
  • index.html / main.js — главный экран заправки;
  • profile.html / profile.js — профиль пользователя;
  • session.js — работа с сессией пользователя на клиенте.

здесь будут мокапы сайта

🔍 Распознавание номеров (analiz_num)

analiz_num/analiz_num.py — прототип модуля компьютерного зрения для автоматического распознавания госномера автомобиля: каскад Хаара (haarcascade_russian_plate_number.xml) находит рамку номера на фото, EasyOCR распознаёт текст на найденном фрагменте. Это заготовка под идею из бизнес-логики модуля пользователей — узнавать клиента по камере на въезде и предлагать его предполагаемый заказ. Также это система безопасности. Пока модуль работает автономно (планируется приём изображений с камер видеонаблюдения) и не подключён к FastAPI как эндпоинт.

🚀 Запуск программы

Backend

cd WEB/backend

python -m venv venv
source venv/bin/activate        # Linux/macOS
venv\Scripts\activate           # Windows

pip install -r ../../requirements.txt

# создать .env (см. раздел ниже)

# поднять схему БД (PostgreSQL должен быть запущен и создана база)
psql -U <user> -d <database> -f init.sql

# запустить API
uvicorn main:app --reload

Документация API (Swagger) будет доступна на http://127.0.0.1:8000/docs.

Отдельным процессом (например, во втором терминале) запускается воркер телеметрии:

python worker_mqtt.py

Frontend

Статические файлы из WEB/frontend можно открыть напрямую в браузере или раздать любым простым HTTP-сервером — предварительно проверьте API_BASE в config.js.

Прошивка ESP32

  1. Переименуете demo_secrets.hsecrets.h и заполните реальными данными Wi-Fi/MQTT/UUID устройства.
  2. Откройте Arduino/main/main.ino в Arduino IDE / PlatformIO, установите библиотеки Adafruit_GFX, Adafruit_ST7735, DHT, ACS712, WiFi, PubSubClient, ArduinoJson, OneWire, DallasTemperature.
  3. Откройте Arduino/main/config.h и введите соответствующие пины ваших датчиков и нужные значения локальных переменных.
  4. Выберите плату ESP32 и залейте прошивку.

🔐 Переменные окружения

Создайте файл WEB/backend/.env.gitignore, создаётся локально) и заполните его таким образом:

HOST=localhost
NAME_USER=postgres
PASSWORD=your_password
DATABASE=azs_db

MQTT_LOGIN=your_mqtt_login
MQTT_PASSWORD=your_mqtt_password
MQTT_ADDRESS=your_mqtt_broker_address
MQTT_PORT=1883

UUID=uuid_станции_для_чтения_последних_показаний

🔗 API-эндпоинты

Модуль Метод Путь Описание
Users GET /users Список всех пользователей
Users GET /users/{user_id} Один пользователь
Users POST /users/register Регистрация (RETURNING id)
Users PUT /users/{user_id} Частичное обновление профиля
Users POST /users/login Аутентификация по email/паролю
Stations GET /stations Список станций (join с регионом)
Stations GET /stations/{id} Одна станция
Stations POST /stations Создать станцию (регион создаётся при необходимости)
Stations PUT /stations/{id} Обновить регион/адрес
Stations DELETE /stations/{id} Удалить станцию
Stations GET /stations/{id}/pumps Все ТРК станции
Pumps GET /pumps/{id} Одна ТРК
Pumps POST /pumps Создать ТРК
Pumps PUT /pumps/{id} Обновить статус/активность
Pumps DELETE /pumps/{id} Удалить ТРК
Prices GET /prices/{station_id} Цены на топливо на станции (опц. фильтр fuel_type)
Prices POST /prices Установить/обновить цену (UPSERT)
Prices DELETE /prices/{region_id} Удалить цену по региону и типу топлива
Tanks GET /tanks/station/{station_id} Резервуары станции с % заполнения
Tanks PUT /tanks/{tank_id}/refill Пополнить резервуар
Tanks POST /tanks Создать/обновить резервуар (UPSERT)
Transactions POST /transactions Оформить заказ на заправку (списание топлива, блокировка ТРК)
Sensors GET /sensors Последние показания датчиков станции
Sensors POST /sensors/pumps/{pumps_id} Отправить MQTT-команду на переключение ТРК

👥 Команда

Участники

Воронин Сергей — embedded-разработчик

Есенин Константин — fullstak-разработчик

Веселов Василий — 3D-инженер

Рожков Егор — схемотехник

Дектеренко Евгения — эколог

Арынова Малика — дизайнер

Савельева Арина — экономист

Преподаватели

Фадеев Дмитрий Владимирович

Косик Андрей Васильевич

Максимов Станислав Валерьевич

📄 Лицензия

Проект распространяется на условиях All Rights Reserved — см. файл LICENCE. Копирование, модификация и использование кода (включая учебные и некоммерческие цели) без письменного согласия правообладателей запрещены.

© 2026 Esenin Konstantin, Voronin Sergey / SAF — Smart AZS Future.

About

Smart AZS Future - Autonomous container-type gas station for remote regions without infrastructure

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors