Echtzeit-Überwachung von Patienten mit Philips IntelliVue-Geräten
Dies ist ein Miscellaneous, Multimodal AI-Bereich Automatisierungsworkflow mit 8 Nodes. Hauptsächlich werden Code, Cron, Switch, EmailSend, HttpRequest und andere Nodes verwendet. Automatisierte Überwachung und Alarmierung von Patienten-Vitalzeichen mit Philips IntelliVue und Google Sheets
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
- •Google Sheets API-Anmeldedaten
Verwendete Nodes (8)
Kategorie
{
"id": "ZglHLOi9fxEH6oKT",
"meta": {
"instanceId": "dd69efaf8212c74ad206700d104739d3329588a6f3f8381a46a481f34c9cc281",
"templateCredsSetupCompleted": true
},
"name": "Real-Time Patient Monitoring with Philips IntelliVue Devices",
"tags": [],
"nodes": [
{
"id": "6b8ff0c7-6c35-4141-a0c8-030dcab3fe7b",
"name": "Gerätedaten alle 30s abfragen",
"type": "n8n-nodes-base.cron",
"position": [
-580,
80
],
"parameters": {
"triggerTimes": {
"item": [
{}
]
}
},
"typeVersion": 1
},
{
"id": "97fbcb09-0510-404e-b934-598c783a15d9",
"name": "Von IntelliVue Gateway abrufen",
"type": "n8n-nodes-base.httpRequest",
"position": [
-360,
80
],
"parameters": {
"url": "http://{{ $env.INTELLIVUE_GATEWAY_IP }}:8080/api/patients/current",
"options": {
"timeout": 5000
},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "httpBasicAuth"
},
"credentials": {
"httpBasicAuth": {
"id": "in1EZeEnhkmqnkds",
"name": "test - auth"
}
},
"typeVersion": 4.2
},
{
"id": "4d33d657-9b37-426d-a5e9-674bc91ce054",
"name": "Gerätedaten verarbeiten",
"type": "n8n-nodes-base.code",
"position": [
-140,
80
],
"parameters": {
"jsCode": "// Process different data sources from Philips IntelliVue\nconst inputData = $input.all();\nlet processedVitals = [];\n\n// Process each input source\nfor (const input of inputData) {\n const data = input.json;\n let vitals = null;\n\n // Detect data source and process accordingly\n if (data.MSH && data.MSH.includes('HL7')) {\n // HL7 Message Processing\n vitals = processHL7Message(data);\n } else if (data.filename && data.filename.endsWith('.csv')) {\n // CSV Export File Processing\n vitals = processCSVExport(data);\n } else if (data.patients || data.deviceId) {\n // Gateway API Response Processing\n vitals = processGatewayResponse(data);\n }\n\n if (vitals) {\n processedVitals.push(vitals);\n }\n}\n\n// HL7 Message Parser\nfunction processHL7Message(hl7Data) {\n try {\n const segments = hl7Data.message.split('\\r');\n let patientInfo = {};\n let vitalSigns = {};\n\n segments.forEach(segment => {\n const fields = segment.split('|');\n \n // Patient Identification (PID segment)\n if (segment.startsWith('PID')) {\n patientInfo = {\n patient_id: fields[3] || 'UNKNOWN',\n patient_name: fields[5] || 'Unknown Patient',\n room_number: fields[11] || 'N/A'\n };\n }\n \n // Observation Results (OBX segment for vitals)\n if (segment.startsWith('OBX')) {\n const valueType = fields[2];\n const observationId = fields[3];\n const value = parseFloat(fields[5]) || 0;\n const unit = fields[6] || '';\n \n // Map Philips observation codes to vital signs\n switch(observationId) {\n case 'MDC_ECG_HEART_RATE':\n vitalSigns.heart_rate = value;\n break;\n case 'MDC_PULS_OXIM_SAT_O2':\n vitalSigns.spo2 = value;\n break;\n case 'MDC_PRESS_BLD_NONINV_SYS':\n vitalSigns.bp_systolic = value;\n break;\n case 'MDC_PRESS_BLD_NONINV_DIA':\n vitalSigns.bp_diastolic = value;\n break;\n case 'MDC_TEMP_BODY':\n vitalSigns.temperature = value;\n break;\n case 'MDC_RESP_RATE':\n vitalSigns.respiration_rate = value;\n break;\n case 'MDC_CO2_AWAY':\n vitalSigns.etco2 = value;\n break;\n }\n }\n });\n\n return {\n ...patientInfo,\n ...vitalSigns,\n data_source: 'HL7',\n timestamp: new Date().toISOString(),\n device_type: 'Philips_IntelliVue'\n };\n } catch (error) {\n console.error('HL7 parsing error:', error);\n return null;\n }\n}\n\n// CSV Export File Parser\nfunction processCSVExport(csvData) {\n try {\n const lines = csvData.data.split('\\n');\n const headers = lines[0].split(',');\n const latestRecord = lines[lines.length - 2].split(','); // Skip empty last line\n\n const vitals = {};\n headers.forEach((header, index) => {\n const cleanHeader = header.trim().replace(/\"/g, '');\n const value = latestRecord[index] ? latestRecord[index].trim().replace(/\"/g, '') : '';\n \n // Map CSV columns to standard format\n switch(cleanHeader.toLowerCase()) {\n case 'patient_id':\n case 'patientid':\n vitals.patient_id = value;\n break;\n case 'heart_rate':\n case 'hr':\n case 'ecg':\n vitals.heart_rate = parseFloat(value) || 0;\n break;\n case 'spo2':\n case 'oxygen_saturation':\n vitals.spo2 = parseFloat(value) || 0;\n break;\n case 'bp_sys':\n case 'systolic':\n vitals.bp_systolic = parseFloat(value) || 0;\n break;\n case 'bp_dia':\n case 'diastolic':\n vitals.bp_diastolic = parseFloat(value) || 0;\n break;\n case 'temp':\n case 'temperature':\n vitals.temperature = parseFloat(value) || 0;\n break;\n case 'resp_rate':\n case 'rr':\n vitals.respiration_rate = parseFloat(value) || 0;\n break;\n case 'etco2':\n case 'co2':\n vitals.etco2 = parseFloat(value) || 0;\n break;\n case 'room':\n case 'location':\n vitals.room_number = value;\n break;\n }\n });\n\n return {\n ...vitals,\n patient_name: vitals.patient_id || 'Unknown',\n data_source: 'CSV_Export',\n timestamp: new Date().toISOString(),\n device_type: 'Philips_IntelliVue'\n };\n } catch (error) {\n console.error('CSV parsing error:', error);\n return null;\n }\n}\n\n// Gateway API Response Parser\nfunction processGatewayResponse(apiData) {\n try {\n // Handle different API response formats\n const patients = apiData.patients || [apiData];\n const patient = patients[0] || apiData;\n\n return {\n patient_id: patient.patientId || patient.id || 'UNKNOWN',\n patient_name: patient.name || patient.patientName || 'Unknown',\n room_number: patient.room || patient.location || 'N/A',\n heart_rate: patient.heartRate || patient.hr || 0,\n spo2: patient.spo2 || patient.oxygenSaturation || 0,\n bp_systolic: patient.systolicBP || patient.bpSys || 0,\n bp_diastolic: patient.diastolicBP || patient.bpDia || 0,\n temperature: patient.temperature || patient.temp || 0,\n respiration_rate: patient.respirationRate || patient.rr || 0,\n etco2: patient.etco2 || patient.co2 || 0,\n data_source: 'Gateway_API',\n timestamp: patient.timestamp || new Date().toISOString(),\n device_type: 'Philips_IntelliVue',\n device_id: patient.deviceId || apiData.deviceId || 'UNKNOWN'\n };\n } catch (error) {\n console.error('Gateway API parsing error:', error);\n return null;\n }\n}\n\n// Return all processed vitals\nreturn processedVitals.filter(v => v !== null).map(vital => ({ json: vital }));"
},
"typeVersion": 2
},
{
"id": "26fde5b7-0e12-426b-aa01-c267b332a79c",
"name": "Daten validieren und anreichern",
"type": "n8n-nodes-base.code",
"position": [
80,
80
],
"parameters": {
"jsCode": "// Validate and enrich vital signs data\nconst vitals = $json;\n\n// Data validation\nif (!vitals.patient_id || vitals.patient_id === 'UNKNOWN') {\n console.warn('Missing or invalid patient ID');\n return null;\n}\n\n// Calculate derived values\nif (vitals.bp_systolic && vitals.bp_diastolic) {\n vitals.pulse_pressure = vitals.bp_systolic - vitals.bp_diastolic;\n vitals.mean_arterial_pressure = Math.round(vitals.bp_diastolic + (vitals.pulse_pressure / 3));\n}\n\n// Convert temperature if needed (assume Celsius input)\nif (vitals.temperature) {\n vitals.temperature_celsius = vitals.temperature;\n vitals.temperature_fahrenheit = Math.round((vitals.temperature * 9/5 + 32) * 10) / 10;\n}\n\n// Determine clinical status\nvitals.clinical_status = determineClinicalStatus(vitals);\nvitals.alert_level = determineAlertLevel(vitals);\nvitals.clinical_alerts = generateClinicalAlerts(vitals);\n\n// Add metadata\nvitals.processed_at = new Date().toISOString();\nvitals.system_status = 'PROCESSED';\n\nfunction determineClinicalStatus(v) {\n const abnormalConditions = [\n v.heart_rate && (v.heart_rate < 60 || v.heart_rate > 100),\n v.spo2 && v.spo2 < 95,\n v.bp_systolic && (v.bp_systolic > 140 || v.bp_systolic < 90),\n v.temperature && (v.temperature > 38.0 || v.temperature < 36.0),\n v.respiration_rate && (v.respiration_rate < 12 || v.respiration_rate > 20)\n ];\n \n return abnormalConditions.some(condition => condition) ? 'ABNORMAL' : 'NORMAL';\n}\n\nfunction determineAlertLevel(v) {\n // Critical conditions\n const critical = [\n v.heart_rate && (v.heart_rate < 50 || v.heart_rate > 120),\n v.spo2 && v.spo2 < 90,\n v.bp_systolic && (v.bp_systolic > 180 || v.bp_systolic < 80),\n v.temperature && (v.temperature > 39.0 || v.temperature < 35.0),\n v.respiration_rate && (v.respiration_rate < 8 || v.respiration_rate > 30)\n ];\n \n if (critical.some(c => c)) return 'CRITICAL';\n if (v.clinical_status === 'ABNORMAL') return 'WARNING';\n return 'NORMAL';\n}\n\nfunction generateClinicalAlerts(v) {\n const alerts = [];\n \n if (v.heart_rate) {\n if (v.heart_rate < 50) alerts.push('Severe Bradycardia');\n else if (v.heart_rate > 120) alerts.push('Severe Tachycardia');\n else if (v.heart_rate < 60) alerts.push('Bradycardia');\n else if (v.heart_rate > 100) alerts.push('Tachycardia');\n }\n \n if (v.spo2) {\n if (v.spo2 < 90) alerts.push('Severe Hypoxemia');\n else if (v.spo2 < 95) alerts.push('Hypoxemia');\n }\n \n if (v.bp_systolic) {\n if (v.bp_systolic > 180) alerts.push('Hypertensive Crisis');\n else if (v.bp_systolic < 80) alerts.push('Severe Hypotension');\n else if (v.bp_systolic > 140) alerts.push('Hypertension');\n else if (v.bp_systolic < 90) alerts.push('Hypotension');\n }\n \n if (v.temperature) {\n if (v.temperature > 39.0) alerts.push('High Fever');\n else if (v.temperature < 35.0) alerts.push('Hypothermia');\n else if (v.temperature > 38.0) alerts.push('Fever');\n }\n \n return alerts;\n}\n\nreturn { json: vitals };"
},
"typeVersion": 2
},
{
"id": "4a6d57fc-ef8c-480c-946e-afdb6dd307ce",
"name": "In Patientendatenbank speichern",
"type": "n8n-nodes-base.googleSheets",
"position": [
300,
80
],
"parameters": {
"range": "PatientVitals!A:Z",
"options": {},
"sheetId": "{{your_patient_vitals_sheet_id}}",
"operation": "append",
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"id": "ScSS2KxGQULuPtdy",
"name": "Google Sheets- test"
}
},
"typeVersion": 2
},
{
"id": "de7e2320-85ac-4754-949b-4660a1a1f990",
"name": "Klinischen Alarm senden",
"type": "n8n-nodes-base.emailSend",
"position": [
740,
80
],
"webhookId": "d38d9c8d-66ba-4d86-840d-660249bfdb3d",
"parameters": {
"text": "=Patient: {{ $json.patient_name }} (ID: {{ $json.patient_id }}), Room: {{ $json.room_number }}\nHR: {{ $json.heart_rate || 'N/A' }} bpm | SpO₂: {{ $json.spo2 || 'N/A' }}% | BP: {{ $json.bp_systolic || 'N/A' }}/{{ $json.bp_diastolic || 'N/A' }} mmHg | Temp: {{ $json.temperature_celsius || 'N/A' }}°C | Resp: {{ $json.respiration_rate || 'N/A' }}/min | EtCO₂: {{ $json.etco2 || 'N/A' }} mmHg\nAlerts: {{ ($json.clinical_alerts || []).join(', ') || 'None' }}\nMAP: {{ $json.mean_arterial_pressure || 'N/A' }} mmHg | Status: {{ $json.clinical_status || 'Unknown' }}\nAction: Assess patient, confirm vitals, check devices, notify physician, document actions.\n\n",
"options": {},
"subject": "🏥 PHILIPS INTELLIVUE ALERT – {{ $json.alert_level }}",
"toEmail": "nursing-{{ $json.room_number }}@hospital.com, oncall-physician@hospital.com",
"fromEmail": "intellivue-alerts@hospital.com",
"emailFormat": "text"
},
"credentials": {
"smtp": {
"id": "G1kyF8cSWTZ4vouN",
"name": "SMTP -test"
}
},
"typeVersion": 2.1
},
{
"id": "1560e40e-b92a-413c-95ef-4a5100977104",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
520,
80
],
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "7c1c5be0-12e1-4730-99ac-802c20a00601",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.alert_level }}",
"rightValue": "CRITICAL"
}
]
}
},
{
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "52051cac-6a10-4537-ba91-93bafea7a847",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.alert_level }}",
"rightValue": "Normal"
}
]
}
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "7b2c77b6-470c-42b9-8f28-67ca546aabb7",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-260,
-220
],
"parameters": {
"width": 560,
"height": 180,
"content": "## 📊 Google Sheet Structure:\n### Columns: patient_id, patient_name, room_number, timestamp, ecg_heart_rate, spo2_oxygen_saturation, nibp_systolic, nibp_diastolic, temperature_celsius, respiration_rate, etco2_end_tidal, cardiac_output, alert_level, alerts, device_status"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "d381294b-d1ca-4f13-8581-c724961f23c5",
"connections": {
"1560e40e-b92a-413c-95ef-4a5100977104": {
"main": [
[
{
"node": "de7e2320-85ac-4754-949b-4660a1a1f990",
"type": "main",
"index": 0
}
],
[]
]
},
"4d33d657-9b37-426d-a5e9-674bc91ce054": {
"main": [
[
{
"node": "26fde5b7-0e12-426b-aa01-c267b332a79c",
"type": "main",
"index": 0
}
]
]
},
"26fde5b7-0e12-426b-aa01-c267b332a79c": {
"main": [
[
{
"node": "4a6d57fc-ef8c-480c-946e-afdb6dd307ce",
"type": "main",
"index": 0
}
]
]
},
"4a6d57fc-ef8c-480c-946e-afdb6dd307ce": {
"main": [
[
{
"node": "1560e40e-b92a-413c-95ef-4a5100977104",
"type": "main",
"index": 0
}
]
]
},
"6b8ff0c7-6c35-4141-a0c8-030dcab3fe7b": {
"main": [
[
{
"node": "97fbcb09-0510-404e-b934-598c783a15d9",
"type": "main",
"index": 0
}
]
]
},
"97fbcb09-0510-404e-b934-598c783a15d9": {
"main": [
[
{
"node": "4d33d657-9b37-426d-a5e9-674bc91ce054",
"type": "main",
"index": 0
}
]
]
}
}
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Fortgeschritten - Verschiedenes, Multimodales KI
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Oneclick AI Squad
@oneclick-aiThe AI Squad Initiative is a pioneering effort to build, automate and scale AI-powered workflows using n8n.io. Our mission is to help individuals and businesses integrate AI agents seamlessly into their daily operations from automating tasks and enhancing productivity to creating innovative, intelligent solutions. We design modular, reusable AI workflow templates that empower creators, developers and teams to supercharge their automation with minimal effort and maximum impact.
Diesen Workflow teilen