Skip to content

Rivian on FHIR®

alt text

Good to know: Rivian is not an ISO-13485 compliant Medical Device

This is an example of the flexibility of Healthcare Standard, FHIR@ (Fast Healthcare Interoperability Resources) and how it could be used to onboard a Medical Device for something like a Patient Home Monitoring solution where the device emits metrics back to the hospital as observations for external care.

Now, for fun and little profit, lets augment the scenario above and use FHIR to Deliver a Rivian to a Driver, and have it send back metrics to the Plant after the vehicle has been entitled to its new owner.

  • FHIR® Resource Modeling

    Though it may not be perfect, I think we can get this done with 5 FHIR Resource types.

    Medical Device OnboardingRivian Onboarding
    OrganizationOrganization
    DeviceDevice
    DeviceMetricDeviceMetric
    PatientAccount
    ObservationObservation

    Using clinFHIR, lets visualize our FHIR Resources and the relationships between them to model our payloads for the workload. The model the left is a somewhat accurate way to onboard a device for Remote Monitoring in a hospital, on the right, is how we would onboard the Rivian. represented in FSH (FHIR Shorthand) and visualized by gb2.

    FHIR Resource Models

    Now that we got things modeled, we are going to execute the workflow in two different parts. On boarding and Post Delivery Observation as a stateful API. The on boarding is done exactly once, the Post Delivery Observation posts continuously utilizing values from the on boarding process.

  • Organization Setup

    Rivian Headquarters, where the whip rolled out of the plant.

    {
    "resourceType": "Organization",
    "id": "rivian_automotive",
    "name": "Rivian Automotive",
    "address": [
    {
    "line": [
    "100 N Rivian Motorway"
    ],
    "city": "Normal",
    "state": "IL",
    "postalCode": "61761",
    "country": "USA"
    }
    ],
    }
  • Device Registration

    The whip itself. R1S to be exact.

    {
    "resourceType": "Device",
    "id": "01-24926594",
    "manufacturer" : "Rivian Automotive",
    "identifier": [
    {
    "system": "http://deezwatts.com/devices/vin/id",
    "value": "7PDSGABA90000000"
    }
    ],
    "name" : [{
    "value" : "Deez Watts",
    "type" : "user-friendly-name"
    }],
    "modelNumber" : "r1s",
    }
  • Metric Definition

    These are the metric "thingers" the device is capturing and capable of publishing, think of these as an envelop to the metric, declaring the data type, labels, and all that stuff around the unit of measure.

    {
    "resourceType": "DeviceMetric",
    "id": "miles",
    "identifier": [
    {
    "system": "http://deezwatts.com/devicemetric/id",
    "value": "milesmetric"
    }
    ],
    "type": {
    "coding": [
    {
    "system": "urn:iso:std:iso:11073:10101",
    "code": "2000",
    "display": "MILES"
    }
    ]
    },
    "unit": {
    "coding": [
    {
    "system": "urn:iso:std:iso:11073:10101",
    "code": "262688",
    "display": "MILES_LEFT"
    }
    ]
    },
    "source": {
    "reference": "Device/01-24926594"
    },
    "parent": {
    "reference": "Device/01-24926594"
    },
    "operationalStatus": "on",
    "color": "blue",
    "category": "measurement",
    "measurementPeriod": {
    "repeat": {
    "frequency": 1,
    "period": 1,
    "periodUnit": "s"
    }
    }
    }
  • Account Association

    This is the owner of the vehicle, in this example myself.

    {
    "resourceType": "Account",
    "id": "02-f3939935-a667-4c22-9ddf-e84a5c2550ba-e48c09ce",
    "active": true,
    "name": [
    {
    "use": "official",
    "family": "Sweeney",
    "given": [
    "Ronald"
    ]
    }
    ],
    "gender": "male",
    "managingOrganization": {
    "reference": "Organization/rivian_automotive",
    "display": "Rivian Automotive"
    }
    }

    Now, lets post these to the server and have a look at the result. You can do this in a bundle, or individually as resources, but here we are going to do it as individual resources to drive home the order of events, and we'll use bundles for the next part of the workload.

  • Post Delivery Observation

    So the above all happened and the Device (R1S) is now rolling all over the State of Michigan collecting and spewing forth Observations for remote monitoring. We're going to poll the Rivian API for the data, and ship it to a FHIR Server.

    rivian_fhir_bundle.py
    import time
    import uuid
    import json
    # Bundle
    fhir = {}
    fhir["type"] = "transaction"
    fhir["resourceType"] = "Bundle"
    fhir["entry"] = []
    # For simplicity, these are the values of the associated resources we created in the previous step that associate the metrics in FHIR
    whip_device_id =
    rivian_org_id = "rivian_automotive"
    person_customer_id =
    metricone =
    # lets grab our metrics from the api
    # Lets add the observation resources to the bundle
    with open('affected_patients_missing_id_obs.csv') as f:
    # Observation
    obsentry = {}
    obsentry["request"] = {}
    obsentry["resource"] = {}
    obsentry["request"]["method"] = "POST"
    obsentry["request"]["url"] = "Observation"
    obsentry["resource"]["resourceType"] = "Observation"
    # Top Level
    obsentry["resource"]["status"] = "final"
    obsentry["resource"]["valueString"] = obsvaluestring
    # basedOn
    obsentry["resource"]["basedOn"] = [
    {
    'reference': 'ServiceRequest/' + referralId,
    'type': 'ServiceRequest'
    }
    ]
    # subject
    obsentry["resource"]["subject"] = {}
    obsentry["resource"]["subject"]["reference"] = "Patient/" + data["personId"]
    obsentry["resource"]["subject"]["display"] = getnamefrompersonid(data["personId"])
    # Add the Observation Resource Entries to the Bundle
    fhir["entry"].append(obsentry)
    payload = fhir.dumps(fhir)

    Post that Transaction Bundle!