Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
FHIR Device Workflows

Medical Device Workflows in FHIR

Medical device workflow are rich and complex. This design attempts to factor the domain into a minimal set of components that can be combined to produce useful systems. It's self-consciously naïve, but it should serve as a seed for discussion.

A few assumptions and a sketch

  • Any device can be online all the time, and can act as a FHIR server -- possible all on its own, or possibly with the help of a proxy/manager/facade component that "fronts for" the device. (Communication between the device and its manager occurs using any mechanism necessary; but the components below be useful for such internal communication, too.)

  • A device generates snapshot (i.e. point-in-time) reports -- which can consist of observations or alerts.

  • A device exposes a collection of individual "settings" that can be directly manipulated by authorized clients.

Basic Components

Device

Device: as-is in FHIR, describes a specific instance of a device. For example:

{
  resourceType: 'Device',
  type: {
    code: [{
      system: 'http://carefusion.com/',
      code: 'alaris-pulse-ox'
    }]
  },
  identifier: {
    system: 'http://carefusion.com/serial-number/',
    value: '75023658923523'
  },
  location: 'Location/medical_ward_5'
}

Device System (Layout)

DeviceSystem resource: provides a detailed layout of the components of a device system. Specifically in IHE PCD terms, this describes a tree structure of device, virtualdevices, channels, and metrics. Within this tree, every node has a unique identifier (which can, if desired, be expressed as a PCD-like path). For example:

{
  resourceType: 'DeviceSystem',
  device: 'Device/pulse_ox_unit_8273513',
  virtualDevice: [{
    identifier: 'vd1',
    channel: [{
      identifier: 'vd1/ch1',
      metric: [{
        identifier: 'vd1/ch1/metric183'
      }]
    }]
  }, {
    identifier: 'vd2',
    channel: [{
      identifier: 'vd2/ch1',
      metric: [{
        identifier: 'vd2/ch1/metric387'
      }]
    }]
  }]
}

Device Settings

Any given device has a collection of associated DeviceSetting resources that describe the current state of configurable settings. Each DeviceSetting represent a single state for a device configuration setting. For example, "the SpO2 alarm threshold" for a specific pulse oximeter. These settings are fully qualified by device and (as needed) path within the virtual device system:

{
  resourceType: 'DeviceSetting',
  device: 'Device/pulse_ox_unit_8273513',
  component: 'vd1/ch1/metric138',  # <-- virtualdevice, channel or message id in Device/123
  name: {
    system: 'http://carefusion.com/alaris-pulse-ox', 
    code: 'spo2_alarm_threshold'
  },
  allowedValueRange: {
    low: {value: 20, unit '%'},
    high:{value: 99, unit'%'}
  },
  valueQuantity: {  # <-- This is the only part a client can change
    value: 64,
    unit: '%'
  }
}

In general, an authorized user can update a DeviceSetting via HTTP PUT -- but only the value portion is allowed to change.

Device Observation Report

A DeviceObservationReport captures the complete details of a point-in-time observation report. It contains a set of observations, each associated with a specific component metric. Would consider flattening the structure so the entire hierarchy isn't recapitulated from DeviceSystem:

{
  resource: 'DeviceObservationReport',
  device: 'Device/pulse_ox_unit_8273513',
  observation: [{
    component: 'vd1/ch1/metric138', # <-- virtualdevice, channel or message id in Device/123
    observation: 'Observation/123' # <-- e.g. about Patient: "has SpO2 = 82%"
  }]
}

Device Alert Report

A DeviceAlertReport captures the complete details of a point-in-time device alert. This includes details about what alerts are active and why. A report is explicitly generated, and multiple reports can be generated by the same device in sequence. So a report is not a "singleton"; a whole stream, or feed, of alerts would emerge from a device. It's possible that the leaf-level alert details should be Observation (Which is how IHE does it in v2) -- I'm not sure.

Importantly: when possible, if an alert is

  • triggered by a DeviceSetting (e.g. SpO2 threshold underrun), or
  • can be disabled by a `DeviceSetting (e.g. "Alarm is buzzing --> false")

then these links should be conveyed here. So right next to the fact that "the alarm is beeping" there's a reference to the settings that allow a client to change that state -- e.g. to change the threshold or simply silence the alarm.

{
  resource: 'DeviceAlertReport',
  device: 'Device/pulse_ox_unit_8273513',
  alert: [{
    component: 'vd1/ch1/metric138',# <-- virtualdevice, channel or message id in Device/123
    observation: 'Observation/456', # <-- e.g. about device: "is currently beeping"
    wasTriggeredBy: 'DeviceSetting/3897535', # <-- the "SpO2 threshold = 82%" setting 
    canDisableWith: 'DeviceSetting/9385372' # <-- the "alarm status" setting
  }]
}

So a client could GET /DeviceSetting/3897535, discover the valid settings, and turn the alarm off via HTTP PUT.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment