Клієнт з агрохолдингу скаржився: при хмарному керуванні поливом до 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. - Протестуйте цикл: відкриття клапана → отримання стану → відображення на екрані.







