Deez Watts
IntroductionWorkloadsAppsImplementationsResourcesData Exhaust
  • A Rivian Data Adventure
  • INTRODUCTION
    • Architecture
    • Data Access
    • Rivian Databricks
    • The Whip
  • Workloads
    • Rivian Falcon LogScale
    • Rivian NATS Comms
  • Apps
    • Rivian Prometheus Exporter
    • Rivian Configurator Rotator
  • Implementations
    • Rivian Geo via IRIS Document Database
    • Rivian on FHIR®
  • Data Exhaust
    • Fun with ffmpeg, Gear Guard at Iceman 2024
  • Resources
    • Repos
    • Miscellaneous
Powered by GitBook
On this page
  • FHIR® Resource Modeling
  • On boarding
  • Post Delivery Observation
  • Lets have a look through the
  1. Implementations

Rivian on FHIR®

Device On-boarding Example

PreviousRivian Geo via IRIS Document DatabaseNextFun with ffmpeg, Gear Guard at Iceman 2024

Last updated 1 year ago

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 Onboarding
Rivian Onboarding

Organization

Organization

Device

Device

DeviceMetric

DeviceMetric

Patient

Account

Observation

Observation

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.

On boarding

On boarding is quite simple, the Organization (Rivian) builds the Device (R1S), formulates the Metrics (telemetry) and associates it to its Account to take home.

Lets look at the payloads of the FHIR resources adapted to this Scenario.

Organization 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 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",
}

DeviceMeasurements 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 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.

Pay attention to the relationships built in the above payloads.... cause its awesome.

UNDER CONSTRUCTION HERE

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.

We have a trusty technique for scheduling the workload found in the Data Access section of the data adventure, Ill go over it again, but make it dismissable with one of those collapsble thingies, but show the script in its entirety that gets the job done.

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)

Lets run it, if you are curious on we run python as kubernetes jobs, have a look at our foundational section, Data Access or the github repo associated with this post for clues.

Transaction Bundles Posting!

Lets have a look through the

I wrote this up initially for participants of the MIT Hack in 2022 as a simple of example of how to do exactly the above using FHIR, and provided a postman collection of sorts to back it. It fits nicely for those wanting to understand how slick and powerful relationships between FHIR resources are, and t

Using , 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.

clinFHIR
Rivian on FHIR®
FHIR Resource Models