本文へスキップ
プロジェクトに戻る

Ward Stock

: 2023担当: Android application development閲覧なし

An automated medication dispensing system built in Kotlin with Jetpack Compose, talking to hardware through the NDK.

技術構成

What the system does#

Ward Stock is an automated medication dispensing system for hospital wards. It integrates with RESTful APIs to pull the medication list and post every dispense back to the central system. The app is written in Kotlin with the entire UI in Jetpack Compose, running on purpose-built hardware with the dispensing mechanism inside the unit.

Talking to hardware through the NDK#

  1. The vendor library that drives the mechanism is C, so it is called through the Android NDK over JNI.
  2. Every native call sits behind a single Kotlin interface, which keeps hardware details from leaking upward into the UI layer.
  3. All hardware commands run on an I/O dispatcher — opening a drawer takes seconds, and blocking the UI thread is never acceptable.
kotlin
external fun openDrawer(slot: Int): Int

private val _state = MutableStateFlow<DispenseState>(DispenseState.Idle)
val state: StateFlow<DispenseState> = _state.asStateFlow()

fun dispense(slot: Int) = viewModelScope.launch(Dispatchers.IO) {
    _state.value = DispenseState.Running(slot)
    val outcome = runCatching { openDrawer(slot) }
    _state.value = outcome.fold(
        onSuccess = { DispenseState.Done(slot) },
        onFailure = { DispenseState.Failed(it.message) },
    )
}
  • Model every machine state, including the ways a dispense can fail
  • Build the Compose UI so targets stay easy to hit with gloves on
  • Integrate the RESTful APIs for stock lists and dispense records
  • Keep working through short network drops on the ward

State and asynchronous work#

A machine that hands medication to a patient has to say clearly what it is doing, and whether it succeeded.
The rule the state design was built around
  • A stateful architecture keeps the screen reflecting one machine state — never two competing sources of truth.
  • Coroutines carry everything that has to wait: API calls and the dispensing mechanism alike.
  • Every state on screen traces back to a real event, so a single screenshot is usually enough to debug a report from the ward.