Overview
The DevicesRepository provides CRUD operations for managing devices (sensors and actuators) within sectors, as well as catalog methods for device categories, types, and units. All methods are suspend functions that return Result<T> for consistent error handling.
Device CRUD Methods
getDevicesByTenantId()
Fetches all devices for a specific tenant.
suspend fun getDevicesByTenantId(tenantId: Long): Result<List<Device>>
Parameters
The tenant ID to filter devices by
Returns
Result containing a list of Device objects or an error
createDevice()
Creates a new device for a tenant.
suspend fun createDevice(
tenantId: Long,
sectorId: Long,
name: String?,
categoryId: Short?,
typeId: Short?,
unitId: Short?,
isActive: Boolean
): Result<Device>
Parameters
The tenant ID the device belongs to
The sector ID where the device is installed
Optional display name for the device
Device category (1=SENSOR, 2=ACTUATOR)
Device type ID from the catalog
Unit of measure ID from the catalog
Whether the device is active
Returns
Result containing the created Device object or an error
updateDevice()
Updates an existing device.
suspend fun updateDevice(
tenantId: Long,
deviceId: Long,
sectorId: Long?,
name: String?,
categoryId: Short?,
typeId: Short?,
unitId: Short?,
isActive: Boolean?
): Result<Device>
Parameters
The tenant ID the device belongs to
New display name (optional)
New category ID (optional)
New active status (optional)
Returns
Result containing the updated Device object or an error
deleteDevice()
Deletes a device by ID.
suspend fun deleteDevice(tenantId: Long, deviceId: Long): Result<Unit>
Parameters
The tenant ID the device belongs to
Returns
Result indicating success or error
Catalog Methods
getDeviceCategories()
Fetches all device categories from the catalog.
suspend fun getDeviceCategories(): Result<List<DeviceCatalogCategory>>
Returns
Result<List<DeviceCatalogCategory>>
Result containing a list of DeviceCatalogCategory objects or an error
getDeviceTypes()
Fetches device types from the catalog, optionally filtered by category.
suspend fun getDeviceTypes(categoryId: Short? = null): Result<List<DeviceCatalogType>>
Parameters
Optional category ID to filter types (1=SENSOR, 2=ACTUATOR)
Returns
Result<List<DeviceCatalogType>>
Result containing a list of DeviceCatalogType objects or an error
getUnits()
Fetches all units from the catalog.
suspend fun getUnits(): Result<List<DeviceCatalogUnit>>
Returns
Result<List<DeviceCatalogUnit>>
Result containing a list of DeviceCatalogUnit objects or an error
Usage Example
class DevicesViewModel(
private val devicesRepository: DevicesRepository
) : ViewModel() {
private val _devices = MutableStateFlow<List<Device>>(emptyList())
val devices: StateFlow<List<Device>> = _devices.asStateFlow()
private val _categories = MutableStateFlow<List<DeviceCatalogCategory>>(emptyList())
val categories: StateFlow<List<DeviceCatalogCategory>> = _categories.asStateFlow()
private val _types = MutableStateFlow<List<DeviceCatalogType>>(emptyList())
val types: StateFlow<List<DeviceCatalogType>> = _types.asStateFlow()
private val _units = MutableStateFlow<List<DeviceCatalogUnit>>(emptyList())
val units: StateFlow<List<DeviceCatalogUnit>> = _units.asStateFlow()
private val _error = MutableStateFlow<String?>(null)
val error: StateFlow<String?> = _error.asStateFlow()
fun loadDevices(tenantId: Long) {
viewModelScope.launch {
devicesRepository.getDevicesByTenantId(tenantId)
.onSuccess { _devices.value = it }
.onFailure { _error.value = it.message }
}
}
fun loadCatalogData() {
viewModelScope.launch {
// Load all catalog data in parallel
launch {
devicesRepository.getDeviceCategories()
.onSuccess { _categories.value = it }
.onFailure { _error.value = it.message }
}
launch {
devicesRepository.getDeviceTypes()
.onSuccess { _types.value = it }
.onFailure { _error.value = it.message }
}
launch {
devicesRepository.getUnits()
.onSuccess { _units.value = it }
.onFailure { _error.value = it.message }
}
}
}
fun createDevice(
tenantId: Long,
sectorId: Long,
name: String?,
categoryId: Short?,
typeId: Short?,
unitId: Short?
) {
viewModelScope.launch {
devicesRepository.createDevice(
tenantId = tenantId,
sectorId = sectorId,
name = name,
categoryId = categoryId,
typeId = typeId,
unitId = unitId,
isActive = true
)
.onSuccess { loadDevices(tenantId) }
.onFailure { _error.value = it.message }
}
}
}
Dependency Injection
Inject the repository using Koin in your Composables:
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun DevicesScreen(tenantId: Long) {
val viewModel: DevicesViewModel = koinViewModel()
val devices by viewModel.devices.collectAsState()
val categories by viewModel.categories.collectAsState()
LaunchedEffect(Unit) {
viewModel.loadCatalogData()
viewModel.loadDevices(tenantId)
}
// UI implementation
}