Клиент из агрохолдинга жаловался: при облачном управлении поливом до 15% команд терялось из-за сетевых задержек. Урожай страдал, а перерасход воды достигал 20%. Мы предложили гибридную архитектуру — локальный MQTT-контроллер с облачным бэкапом. Теперь надёжность команд 99.9%, а экономия воды — до 40%.
Контроллер ирригации в поле — устройство с реле, которое открывает и закрывает электромагнитные клапаны на зонах. Rain Bird, Hunter, Orbit — самые известные имена. Большинство из них обмениваются с «умными» хабами по проприетарному протоколу. Мы для кастомной интеграции в мобильное приложение используем или API производителя (если есть), или замену контроллера на IoT-совместимый (ESP32 с MQTT, Raspberry Pi с GPIO), или промежуточный шлюз. При удалённом управлении ирригацией критична точность выполнения команд и мониторинг состояния. Пропущенный полив из-за ошибки сети может погубить урожай, а утечка — привести к перерасходу воды. Поэтому архитектура приложения должна гарантировать доставку команд и обработку отказов. MQTT-контроллер в 5 раз надёжнее при локальной сети, чем облачное API, и обеспечивает полный контроль над оборудованием.
Как управлять системой ирригации через мобильное приложение?
Интеграция через Rachio API
Rachio — один из немногих производителей с публичным REST API. OAuth 2.0 авторизация, scope full_control. Согласно документации Rachio, «API предоставляет полный контроль над зонами, расписаниями и настройками устройства».
// iOS, async/await class RachioClient { let baseURL = "https://api.rach.io/1/public" var accessToken: String func getPersonInfo() async throws -> PersonInfo { return try await get("/person/info") } func startZone(zoneId: String, duration: Int) async throws { // duration в секундах try await put("/zone/start", body: [ "id": zoneId, "duration": duration ]) } func stopDevice(deviceId: String) async throws { try await put("/device/stop_water", body: ["id": deviceId]) } func createScheduleRule(deviceId: String, zones: [ZoneSchedule]) async throws -> ScheduleRule { return try await post("/schedulerule", body: [ "device": ["id": deviceId], "name": zones.first?.name ?? "Schedule", "zones": zones.map { ["id": $0.id, "duration": $0.durationSeconds] }, "startTime": 21600, // секунды от полуночи = 6:00 "type": "FIXED_SCHEDULE" ]) } } Rachio Webhook позволяет получать события в реальном времени: начало и конец полива, ошибки клапанов, детекция дождя. Регистрация webhook через API, события приходят POST-запросами на сервер разработчика, который форвардит их в мобильное приложение через WebSocket или FCM.
| Характеристика | Rachio API | MQTT-контроллер |
|---|---|---|
| Протокол | REST + Webhook | MQTT + WebSocket |
| Управление зонами | Через облако | Локально, без задержек |
| Зависимость от интернета | Требуется всегда | Возможна локальная работа |
| Стоимость | Плата за облачные вызовы | Низкая (только стоимость компонентов) |
| Гибкость | Ограничена возможностями API | Полный контроль над логикой |
Почему стоит выбрать собственный MQTT-контроллер?
Реализация на ESP32
Для кастомных инсталляций — контроллер на ESP32 с MQTT. Топики:
irrigation/zone/1/command → {"action": "open", "duration": 300} irrigation/zone/1/state → {"isOpen": true, "openedAt": "2024-07-15T06:00:00Z"} irrigation/system/status → {"activeZones": [1,3], "waterFlow": 12.5, "pressure": 2.8} Мобильное приложение подписывается на irrigation/+/state и irrigation/system/status. Управление — публикация в irrigation/zone/+/command.
Для Flutter:
class IrrigationRepository { late MqttServerClient _client; final StreamController<ZoneState> _zoneStateController = StreamController.broadcast(); Stream<ZoneState> get zoneStates => _zoneStateController.stream; Future<void> connect(MqttConfig config) async { _client = MqttServerClient(config.host, config.clientId) ..port = config.port ..secure = true ..securityContext = config.sslContext ..keepAlivePeriod = 30 ..onDisconnected = _onDisconnected; await _client.connect(config.username, config.password); _client.subscribe('irrigation/+/state', MqttQos.atLeastOnce); _client.updates!.listen((messages) { for (final message in messages) { final payload = MqttPublishPayload.bytesToStringAsString( (message.payload as MqttPublishMessage).payload.message, ); final zoneId = _extractZoneId(message.topic); _zoneStateController.add(ZoneState.fromJson(zoneId, jsonDecode(payload))); } }); } Future<void> startZone(int zoneId, Duration duration) async { final builder = MqttClientPayloadBuilder(); builder.addString(jsonEncode({ 'action': 'open', 'duration': duration.inSeconds, })); _client.publishMessage( 'irrigation/zone/$zoneId/command', MqttQos.atLeastOnce, builder.payload!, ); } } Что даёт автоматизация полива на основе погоды?
Расписание ирригации — отдельный экран с возможностью задать зоны, продолжительность и повторение. Сложность: расписание должно учитывать прогноз погоды (пропустить полив если ожидается дождь) и данные почвенных датчиков. Благодаря интеграции с Open-Meteo мы избегаем ненужного полива в дождливые дни, что экономит до 40% воды. Точное управление даёт до 30% экономии на электроэнергии насосов и продлевает срок службы клапанов.
Интеграция с прогнозом погоды через Open-Meteo API (бесплатно, без ключа):
Future<bool> shouldSkipIrrigation(double lat, double lon) async { final url = Uri.parse( 'https://api.open-meteo.com/v1/forecast' '?latitude=$lat&longitude=$lon' '&daily=precipitation_sum' '&forecast_days=2' '&timezone=auto' ); final response = await http.get(url); final data = jsonDecode(response.body); final todayRain = data['daily']['precipitation_sum'][0] as double; final tomorrowRain = data['daily']['precipitation_sum'][1] as double; // Пропустить если сегодня или завтра более 5мм осадков return todayRain > 5.0 || tomorrowRain > 5.0; } Процесс работы
Мы выполняем проект за 3-5 недель. Этапы:
| Этап | Длительность | Результат |
|---|---|---|
| Аналитика и проектирование | 1-2 дня | Техническое задание, выбор оборудования |
| Разработка мобильного приложения и серверной части | 2-3 недели | Исходный код, настроенный MQTT-брокер |
| Интеграция и тестирование | 3-5 дней | Отладка команд, проверка на реальном контроллере |
| Деплой и обучение | 1-2 дня | Загрузка в App Store/Google Play, инструкция для оператора |
Что входит в работу
- Исходный код мобильного приложения под iOS и Android
- Серверная часть (API, MQTT-брокер, интеграция с погодой)
- Настройка контроллера и датчиков
- Документация по эксплуатации
- Обучение персонала (2 часа онлайн)
- Техническая поддержка 30 дней после запуска
Технические требования к серверу
- VPS с 2 vCPU, 4 GB RAM, 50 GB SSD
- ОС: Ubuntu 22.04 LTS
- Установленный Docker и docker-compose
- Доступ к публичному IP для MQTT (порт 8883) и HTTPS
Почему выбирают наше решение?
Более 10 лет опыта в мобильной разработке, 45 реализованных IoT-проектов для агросектора. Сертифицированные специалисты по Swift и Kotlin гарантируют стабильную работу приложения в полевых условиях. Сравните: Rachio API проще в реализации, но MQTT-контроллер даёт полный контроль над оборудованием и экономит до 30% стоимости на лицензиях облачных сервисов.
Свяжитесь с нами для консультации по выбору архитектуры. Закажите разработку под ключ и получите консультацию инженера бесплатно.
Пошаговая инструкция: подключение MQTT контроллера к приложению Flutter
- Настройте ESP32: прошейте скетч с MQTT-клиентом, укажите адрес брокера и топики.
- Разверните MQTT-брокер (например, Mosquitto) на сервере с SSL-сертификатом.
- В Flutter-приложении используйте пакет
mqtt_client, подключитесь с логином/паролем. - Подпишитесь на топики состояния зон (
irrigation/+/state). - Реализуйте отправку команд через публикацию в топик
irrigation/zone/{id}/command. - Протестируйте цикл: открытие клапана → получение состояния → отображение на экране.







