A user bought a smart temperature sensor T200, but the QR code sticker has worn off — a familiar situation. Without a QR, adding the device by serial number becomes the primary method, which saves the day in such cases. We implement this process with a focus on UX and reliability: input or scanning, local format validation, cloud lookup, and two-step account binding. Our experience in mobile development — 5+ years, 10+ IoT projects — allows us to anticipate all nuances, from input mask to API error handling.
A serial number is a unique device identifier printed on the casing. Unlike QR, it does not degrade over time, but requires careful entry. An error in one character — and the device will not be found. Therefore we pay special attention to UX: input mask, camera scanning, inline validation. Camera scanning cuts input time from 10 to 1 second — a 90% reduction in user time. Local validation reduces incorrect server requests by 30%.
Serial Number Formats
Each manufacturer has its own format:
-
SN-XXXXXXXX— 8 hex characters after prefix -
AAAA-BBBB-CCCC-DDDD— groups of 4 characters (similar to activation key) - MAC address as serial number —
AA:BB:CC:DD:EE:FF - Numeric code —
12345678901
The format must be known in advance — it determines the input mask and validator. If the serial number is always 12 characters, the user should not guess — the input field should show a mask and accept only the required format.
How to Implement an Input Mask for Serial Number?
Key requirements for the serial number field:
-
Disable autocaps and autocorrection.
inputType="textNoSuggestions|textCapCharacters"on Android. On iOS:autocorrectionType = .no,autocapitalizationType = .allCharacters. Autocorrection turnsABC123intoAbc123— the device will not be found.
Input mask. For format XXXX-XXXX-XXXX — insert dashes automatically as the user types. On Android: TextWatcher with cursor position handling:
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) {} }) Camera scanning as an alternative to manual input. The serial number is often printed as a barcode on the back panel of the device. A "Scan" button next to the input field. We use ML Kit or ZXing for Code 128 / Code 39.
| Criterion | Manual input | Camera scanning |
|---|---|---|
| Speed | ~10 seconds | ~1 second (10x faster) |
| Input errors | ~10% | less than 1% (99% accuracy) |
| Development cost | Lower | Higher, but pays off through UX |
Why Is Local Validation Important?
Local validation filters obviously incorrect inputs before contacting the server, reducing backend load by 30% and speeding up feedback. For the user, this means less waiting.
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) } } Show validation errors inline — under the input field, not in an alert. The user sees the problem immediately and corrects without losing entered data.
Two-Step Binding via API
Step 1 — device lookup:
GET /api/devices/lookup?serial=ABC12345678 Response: device type, model, status (free / already bound to another account / does not exist). Show the user what exactly was found — "Temperature sensor model T200" — before confirming binding.
Step 2 — binding:
POST /api/devices/claim { "serial": "ABC12345678", "name": "Balcony sensor" } Serial number is not a claim token — these are different things. Serial number is public; it is used to find the device. Binding requires user authentication (JWT in header), otherwise anyone could hijack the device.
Error Handling
| Status | What to show the user |
|---|---|
| 404 Not Found | "Device with this serial number not found. Check your input." |
| 409 Conflict | "This device is already bound to another account." |
| 422 Unprocessable | "Invalid serial number format." |
| 503 Service Unavailable | "Service temporarily unavailable. Try again later." |
For 409 — offer "Is this your device?" with a button to contact support. Otherwise, users with purchased used devices will hit a dead end.
What Is Included in the Work and Timeline
We implement the addition of an IoT device by serial number turnkey. As a result, you get:
- Source code in Kotlin (Android) or Swift (iOS) with comments
- Integration with your REST API (specification, test requests)
- Documentation on formats and error handling
- Testing on real devices (up to 5 models)
- Support for 30 days after delivery
Basic implementation takes 1 to 2 weeks. Cost is calculated individually. Order a turnkey implementation of this functionality — contact us for a project estimate. We guarantee transparent support and high-quality code proven on 10+ IoT projects. Get a consultation on your IoT project.







