Пользователь купил умный датчик температуры T200, а наклейка с QR-кодом стёрлась — знакомая ситуация. Без QR добавление устройства по серийному номеру становится основным способом, который выручает в таких случаях. Мы реализуем этот процесс с акцентом на UX и надёжность: ввод или сканирование, локальная валидация формата, поиск в облаке и двухэтапная привязка к аккаунту. Наш опыт в мобильной разработке — более 5 лет, 10+ IoT-проектов — позволяет предусмотреть все нюансы, от маски ввода до обработки ошибок API.
Серийный номер — уникальный идентификатор устройства, напечатанный на корпусе. В отличие от QR, он не портится со временем, но требует аккуратного ввода. Ошибка в одном символе — и устройство не найдётся. Поэтому мы уделяем особое внимание UX: маска ввода, сканирование камерой, inline-валидация. Сканирование камерой сокращает время ввода с 10 до 1 секунды — экономия до 90% времени пользователя. Локальная валидация снижает число некорректных запросов к серверу на 30%.
Форматы серийных номеров
У каждого производителя свой формат:
-
SN-XXXXXXXX— 8 hex-символов после префикса -
AAAA-BBBB-CCCC-DDDD— группы по 4 символа (аналог ключа активации) - MAC-адрес как серийный номер —
AA:BB:CC:DD:EE:FF - Числовой код —
12345678901
Формат нужно знать заранее — он определяет маску ввода и валидатор. Если серийный номер всегда 12 символов, пользователь не должен угадывать — поле ввода должно показывать маску и принимать только нужный формат.
Как реализовать маску ввода для серийного номера?
Ключевые требования к полю серийного номера:
-
Автокапс и автокоррекция — выключить.
inputType="textNoSuggestions|textCapCharacters"на Android. На iOS:autocorrectionType = .no,autocapitalizationType = .allCharacters. Автокоррекция превращаетABC123вAbc123— устройство не найдётся.
Маска ввода. Для формата XXXX-XXXX-XXXX — вставлять дефисы автоматически по мере ввода. На Android: TextWatcher с обработкой позиции курсора:
editText.addTextChangedListener(object : TextWatcher { private var isFormatting = false override fun afterTextChanged(s: Editable) { if (isFormatting) return isFormatting = true val digits = s.toString().filter { it.isLetterOrDigit() }.uppercase() val formatted = digits.chunked(4).joinToString("-").take(14) s.replace(0, s.length, formatted) isFormatting = false } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {} override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {} }) Сканирование камерой как альтернатива вводу. Серийный номер часто напечатан штрихкодом на задней панели устройства. Кнопка «Сканировать» рядом с полем ввода. Используем ML Kit или ZXing для Code 128 / Code 39.
| Критерий | Ручной ввод | Сканирование камерой |
|---|---|---|
| Скорость | ~10 секунд | ~1 секунда (в 10 раз быстрее) |
| Ошибки ввода | ~10% | менее 1% (точность 99%) |
| Затраты на разработку | Ниже | Выше, но окупается за счёт UX |
Почему важна локальная валидация?
Локальная валидация отсекает заведомо неверные вводы до обращения к серверу, снижая нагрузку на бэкенд на 30% и ускоряя обратную связь. Для пользователя это значит меньше ожидания.
fun validateSerialNumber(input: String): ValidationResult { val clean = input.filter { it.isLetterOrDigit() }.uppercase() return when { clean.length < 8 -> ValidationResult.TooShort clean.length > 16 -> ValidationResult.TooLong !clean.matches(Regex("[A-Z0-9]+")) -> ValidationResult.InvalidChars else -> ValidationResult.Valid(clean) } } Ошибку валидации показываем inline — под полем ввода, не в alert. Пользователь видит проблему сразу и исправляет, не теряя введённые данные.
Двухэтапная привязка через API
Шаг 1 — поиск устройства:
GET /api/devices/lookup?serial=ABC12345678 Ответ: тип устройства, модель, статус (свободно / уже привязано к другому аккаунту / не существует). Показываем пользователю что именно найдено — «Датчик температуры модель T200» — до подтверждения привязки.
Шаг 2 — привязка:
POST /api/devices/claim { "serial": "ABC12345678", "name": "Датчик на балконе" } Серийный номер не равен claim-токену — это разные вещи. Серийный номер публичный, по нему находят устройство. Привязка требует аутентификации пользователя (JWT в заголовке), иначе любой мог бы угнать устройство.
Обработка ошибок
| Статус | Что показать пользователю |
|---|---|
| 404 Not Found | «Устройство с таким серийным номером не найдено. Проверьте ввод» |
| 409 Conflict | «Это устройство уже привязано к другому аккаунту» |
| 422 Unprocessable | «Неверный формат серийного номера» |
| 503 Service Unavailable | «Сервис временно недоступен. Попробуйте позже» |
Для 409 — предложить «Это ваше устройство?» с кнопкой обращения в поддержку. Иначе пользователи с купленными б/у устройствами окажутся в тупике.
Что входит в работу и сроки
Мы реализуем добавление IoT-устройства по серийному номеру под ключ. В результате вы получаете:
- Исходный код на Kotlin (Android) или Swift (iOS) с комментариями
- Интеграцию с вашим REST API (спецификация, тестовые запросы)
- Документацию по форматам и обработке ошибок
- Тестирование на реальных устройствах (до 5 моделей)
- Поддержку в течение 30 дней после сдачи
Базовая реализация занимает от 1 до 2 недель. Стоимость рассчитывается индивидуально. Закажите реализацию этой функциональности под ключ — свяжитесь с нами для оценки вашего проекта. Мы гарантируем прозрачное сопровождение и качественный код, проверенный на 10+ IoT-проектах. Получите консультацию по вашему IoT-проекту.







