Monitoreo en tiempo real de pacientes con dispositivos Philips IntelliVue
Este es unMiscellaneous, Multimodal AIflujo de automatización del dominio deautomatización que contiene 8 nodos.Utiliza principalmente nodos como Code, Cron, Switch, EmailSend, HttpRequest. Monitoreo y alerta automatizados de signos vitales de pacientes usando Philips IntelliVue y Google Sheets
- •Pueden requerirse credenciales de autenticación para la API de destino
- •Credenciales de API de Google Sheets
Nodos utilizados (8)
Categoría
{
"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": "Consultar Datos del Dispositivo Cada 30s",
"type": "n8n-nodes-base.cron",
"position": [
-580,
80
],
"parameters": {
"triggerTimes": {
"item": [
{}
]
}
},
"typeVersion": 1
},
{
"id": "97fbcb09-0510-404e-b934-598c783a15d9",
"name": "Obtener desde IntelliVue Gateway",
"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": "Procesar Datos del Dispositivo",
"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": "Validar y Enriquecer Datos",
"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": "Guardar en Base de Datos del Paciente",
"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": "Enviar Alerta Clínica",
"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
}
]
]
}
}
}¿Cómo usar este flujo de trabajo?
Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.
¿En qué escenarios es adecuado este flujo de trabajo?
Intermedio - Varios, IA Multimodal
¿Es de pago?
Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.
Flujos de trabajo relacionados recomendados
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.
Compartir este flujo de trabajo