Device Model
The Device model represents Android devices registered with the FYI Automation Tool. It stores device information, capabilities, and connection details for automation execution.
Schema Definition
model Device {
id String @id @default(uuid())
deviceId String @unique
name String?
brand String?
model String?
androidVersion String?
screenWidth Int?
screenHeight Int?
isActive Boolean @default(true)
lastSeenAt DateTime @default(now())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
androidId String?
avdName String?
buildFingerprint String?
buildId String?
cpuAbi String?
deviceName String?
fingerprint String? @unique
hardwareSerial String?
isEmulator Boolean @default(false)
lastAdbId String?
marketingName String?
productName String?
}
Field Descriptions
Primary Identification
| Field | Type | Description |
|---|---|---|
id | String | UUID primary key |
deviceId | String | Unique device identifier (ADB serial) |
fingerprint | String? | Unique device fingerprint for deduplication |
Basic Information
| Field | Type | Description |
|---|---|---|
name | String? | Human-readable device name |
brand | String? | Device manufacturer (e.g., "Google", "Samsung") |
model | String? | Device model (e.g., "Pixel 6", "Galaxy S21") |
marketingName | String? | Marketing name of the device |
deviceName | String? | Device codename |
Android Information
| Field | Type | Description |
|---|---|---|
androidVersion | String? | Android OS version (e.g., "13", "14") |
androidId | String? | Android ID of the device |
buildFingerprint | String? | Complete build fingerprint |
buildId | String? | Build ID |
cpuAbi | String? | CPU ABI (e.g., "arm64-v8a", "x86_64") |
Hardware Information
| Field | Type | Description |
|---|---|---|
screenWidth | Int? | Screen width in pixels |
screenHeight | Int? | Screen height in pixels |
productName | String? | Product name |
hardwareSerial | String? | Hardware serial number |
Emulator Information
| Field | Type | Description |
|---|---|---|
isEmulator | Boolean | Whether this is an Android emulator (default: false) |
avdName | String? | Android Virtual Device name (for emulators) |
Status and Tracking
| Field | Type | Description |
|---|---|---|
isActive | Boolean | Whether the device is active and available (default: true) |
lastSeenAt | DateTime | Last time the device was seen/connected |
lastAdbId | String? | Last ADB identifier used |
createdAt | DateTime | Device registration timestamp |
updatedAt | DateTime | Last update timestamp |
Relationships
The Device model doesn't have direct foreign key relationships but is referenced by:
- Flow execution (via
targetDevicestring field) - Coordinate caching (via
deviceIdin FlowCoordinateCache) - Recordings (via
deviceIdin Recording)
Usage Examples
Registering a Physical Device
const device = await prisma.device.create({
data: {
deviceId: "HT1A12345678",
name: "Samsung Galaxy S21",
brand: "Samsung",
model: "SM-G991U",
androidVersion: "13",
screenWidth: 1080,
screenHeight: 2400,
androidId: "a1b2c3d4e5f6g7h8",
buildFingerprint: "samsung/beyond2lte/beyond2:13/TP1A.220624.014/G975FXXS7CUF1:user/release-keys",
cpuAbi: "arm64-v8a",
fingerprint: "unique-device-hash-123"
}
});
Registering an Emulator
const emulator = await prisma.device.create({
data: {
deviceId: "emulator-5554",
name: "Pixel 6 API 34",
brand: "Google",
model: "sdk_gphone64_arm64",
androidVersion: "14",
screenWidth: 1080,
screenHeight: 2400,
isEmulator: true,
avdName: "Pixel_6_API_34",
cpuAbi: "arm64-v8a",
fingerprint: "emulator-fingerprint-456"
}
});
Updating Device Status
await prisma.device.update({
where: { deviceId: "emulator-5554" },
data: {
lastSeenAt: new Date(),
isActive: true
}
});
Finding Active Devices
const activeDevices = await prisma.device.findMany({
where: {
isActive: true,
lastSeenAt: {
gte: new Date(Date.now() - 5 * 60 * 1000) // Active in last 5 minutes
}
},
orderBy: { lastSeenAt: "desc" }
});
Query Examples
Get Device by Serial
const device = await prisma.device.findUnique({
where: { deviceId: "emulator-5554" }
});
Get Devices by Brand
const googleDevices = await prisma.device.findMany({
where: {
brand: "Google",
isActive: true
}
});
Get Available Emulators
const emulators = await prisma.device.findMany({
where: {
isEmulator: true,
isActive: true
},
orderBy: { name: "asc" }
});
Get Devices by Android Version
const android14Devices = await prisma.device.findMany({
where: {
androidVersion: "14"
}
});
Update Device Fingerprint
await prisma.device.update({
where: { deviceId: "HT1A12345678" },
data: {
fingerprint: "new-unique-fingerprint"
}
});
Deactivate Offline Devices
await prisma.device.updateMany({
where: {
lastSeenAt: {
lt: new Date(Date.now() - 24 * 60 * 60 * 1000) // Not seen for 24 hours
}
},
data: {
isActive: false
}
});
Device Fingerprinting
Device fingerprints are used to uniquely identify devices and prevent duplicate registrations. The fingerprint is typically generated from:
- Android ID
- Build fingerprint
- Hardware serial
- Device properties
// Example fingerprint generation
const fingerprint = crypto
.createHash('sha256')
.update(`${androidId}-${buildFingerprint}-${hardwareSerial}`)
.digest('hex');
Device Discovery Process
- ADB Device Scan: System scans for connected devices via ADB
- Device Information: Retrieves device properties using ADB commands
- Fingerprint Check: Generates/checks device fingerprint for uniqueness
- Registration: Creates or updates device record
- Coordinate Calculation: Calculates screen coordinates for automation
Coordinate System
Device screen coordinates are crucial for UI automation:
interface DeviceCoordinates {
width: number;
height: number;
density: number;
normalizedWidth: number;
normalizedHeight: number;
}
Performance Considerations
Indexing
- Primary key on
id - Unique index on
deviceId - Unique index on
fingerprint - Index on
isActivefor active device queries - Index on
isEmulatorfor emulator filtering - Index on
lastSeenAtfor activity-based queries - Index on
brandandmodelfor device type queries
Query Optimization
- Use
selectto fetch only needed fields - Cache device information to reduce ADB calls
- Implement device health checks periodically
- Use connection pooling for database access
Data Management
- Regular cleanup of inactive devices
- Archive old device records for analytics
- Monitor device connection patterns
- Implement device usage statistics
Migration and Compatibility
ADB Integration
The device model is closely tied to ADB device information:
# ADB device properties
adb -s <deviceId> shell getprop | grep -E "(ro\.product\.|ro\.build\.)"
Emulator Detection
Emulators are identified by:
- Device ID format:
emulator-<port> - AVD name presence
- Emulator-specific properties
Device State Management
Devices can be in various states:
- Active: Currently connected and usable
- Inactive: Disconnected but registered
- Stale: Not seen for extended period
- Removed: Explicitly removed from system
Monitoring and Alerts
Consider monitoring:
- Device connection/disconnection events
- Device health and battery status
- Screen coordinate changes
- Device performance metrics
- ADB connection stability