{
  "id": "oxRwykQoiLwpbFdf",
  "name": "Real-Time IoT Incident Management with Jira & Slack Technician Alerts",
  "tags": [],
  "nodes": [
    {
      "id": "d238dbb2-3754-41c4-b711-372b9abdd5d7",
      "name": "Receive IoT Machine Alert",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1360,
        816
      ],
      "parameters": {
        "path": "0afced43-4cba-45b5-bd48-3baa67716e99",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "3db39226-36ee-411f-824c-cd6258cc578b",
      "name": "Check Failure Threshold",
      "type": "n8n-nodes-base.if",
      "position": [
        -1088,
        816
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "3e909d51-1ae5-42af-9a21-30764877216a",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.body.temperature }}",
              "rightValue": 90
            },
            {
              "id": "98fe38a8-4eba-46a8-b74e-684bcdff3ace",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.body.vibration }}",
              "rightValue": 5
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5ebeda68-69cb-4dda-9c23-d372316731b9",
      "name": "Create Jira Maintenance Ticket",
      "type": "n8n-nodes-base.jira",
      "position": [
        -848,
        800
      ],
      "parameters": {
        "project": {
          "__rl": true,
          "mode": "list",
          "value": "10000",
          "cachedResultName": "n8n sample project"
        },
        "summary": "=Predictive Failure Alert: {{ $json.body.machineId }}",
        "issueType": {
          "__rl": true,
          "mode": "list",
          "value": "10003",
          "cachedResultName": "Task"
        },
        "additionalFields": {
          "priority": {
            "__rl": true,
            "mode": "list",
            "value": "2",
            "cachedResultName": "High"
          },
          "description": "=Machine {{ $json.body.machineId }} triggered alert at {{ $json.body.timestamp }}. Temperature: {{ $json.body.temperature }}\u00b0C Vibration: {{ $json.body.vibration }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8cd54d87-4542-45fa-8bcc-5134d773662b",
      "name": "Fetch Technician Channel Members",
      "type": "n8n-nodes-base.slack",
      "position": [
        -496,
        800
      ],
      "parameters": {
        "resource": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "operation": "member"
      },
      "typeVersion": 2.3
    },
    {
      "id": "e2e9f3e0-21f4-49f7-9865-4aa14d94b14d",
      "name": "Prepare Technician Iteration Data",
      "type": "n8n-nodes-base.set",
      "position": [
        -304,
        800
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1fc348f5-fc2c-4f9e-9bb3-3cfb18eb2611",
              "name": "technicianAvailable",
              "type": "string",
              "value": "false"
            },
            {
              "id": "5ff48458-01ec-4d8f-bcaf-6a99f960341a",
              "name": "technician member id",
              "type": "string",
              "value": "={{ $json.member }}"
            },
            {
              "id": "75be3361-b47f-48af-9532-03f34dcc8587",
              "name": "machin id",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.machineId }}"
            },
            {
              "id": "227617ee-bac3-40cd-b2e2-15428b64ea0a",
              "name": "temperature",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.temperature }}"
            },
            {
              "id": "54731b5d-32fe-4e6d-80e7-98ff54bf3ab6",
              "name": "vibration",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.vibration }}"
            },
            {
              "id": "caddf028-994b-4781-a6e0-468c9b2a9be2",
              "name": "timestamp",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.timestamp }}"
            },
            {
              "id": "7868333a-e688-444d-b986-62ff58effd03",
              "name": "jira ticket",
              "type": "string",
              "value": "={{ $('Create Jira Maintenance Ticket').item.json.key }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "014820bc-1c2e-4def-a55d-d8f72fe222e2",
      "name": "Loop Through Technicians",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -64,
        800
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "4a949864-5d43-4a00-903f-8605222d5e93",
      "name": "Get Technician Presence Status",
      "type": "n8n-nodes-base.slack",
      "position": [
        160,
        816
      ],
      "parameters": {
        "user": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json[\"technician member id\"] }}"
        },
        "resource": "user",
        "operation": "getPresence"
      },
      "typeVersion": 2.3
    },
    {
      "id": "029a11f5-4483-4154-aec3-79bb944822c7",
      "name": "Check If Technician Active",
      "type": "n8n-nodes-base.if",
      "position": [
        368,
        816
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "d4433f2f-f479-4b0b-a9b9-0f29b0534fb2",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.presence }}",
              "rightValue": "={{ $json.presence }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ad488dae-56a9-4fba-9a77-3bd07b714f3c",
      "name": "Format Technician Availability Result",
      "type": "n8n-nodes-base.set",
      "position": [
        624,
        800
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1fc348f5-fc2c-4f9e-9bb3-3cfb18eb2611",
              "name": "technicianAvailable",
              "type": "string",
              "value": "={{ $json.presence }}"
            },
            {
              "id": "5ff48458-01ec-4d8f-bcaf-6a99f960341a",
              "name": "technician member id",
              "type": "string",
              "value": "={{ $('Loop Through Technicians').item.json[\"technician member id\"] }}"
            },
            {
              "id": "f1f80b31-812a-4778-9184-e15959281e3c",
              "name": "machine id",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.machineId }}"
            },
            {
              "id": "afaae717-6a3a-4fa6-bb7a-643bdf6936ce",
              "name": "temperature",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.temperature }}"
            },
            {
              "id": "d9672348-6c8c-48a6-9ed0-8742bc6a5718",
              "name": "vibration",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.vibration }}"
            },
            {
              "id": "1753659a-b563-4d36-9aa2-1f8850f5bf03",
              "name": "timestamp",
              "type": "string",
              "value": "={{ $('Check Failure Threshold').item.json.body.timestamp }}"
            },
            {
              "id": "bc70e0c8-6d5e-4597-b18a-db525ad408ab",
              "name": "jira ticket",
              "type": "string",
              "value": "={{ $('Create Jira Maintenance Ticket').item.json.key }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "0cfaa458-11ab-49b7-8a70-1bedcd30a49f",
      "name": "Select Final Available Technician",
      "type": "n8n-nodes-base.code",
      "position": [
        176,
        240
      ],
      "parameters": {
        "jsCode": "// Get all inputs\nconst itemsList = items.map(i => i.json);\n\n// Pick machine data from ANY item (same for all items)\nconst baseData = {\n  machine_id: itemsList[0][\"machine id\"],\n  temperature: itemsList[0].temperature,\n  vibration: itemsList[0].vibration,\n  timestamp: itemsList[0].timestamp,\n  jira_ticket: itemsList[0][\"jira ticket\"]\n};\n\n// Find first active technician\nconst activeTech = itemsList.find(i => i.technicianAvailable === \"active\");\n\nif (activeTech) {\n  // Technician available\n  return [\n    {\n      json: {\n        finalTechnicianAvailable: true,\n        technicianId: activeTech[\"technician member id\"],\n        ...baseData\n      }\n    }\n  ];\n} else {\n  // No technician available\n  return [\n    {\n      json: {\n        finalTechnicianAvailable: false,\n        technicianId: null,\n        ...baseData\n      }\n    }\n  ];\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "992b5731-f04f-4bb7-a734-b621a96fe586",
      "name": "Check If Any Technician Available",
      "type": "n8n-nodes-base.if",
      "position": [
        384,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "623be4df-0ddd-4096-8b82-b56d57b809a6",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.finalTechnicianAvailable }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7f9eba04-e250-4949-b81a-3eae8813b516",
      "name": "Send Technicians Alert (Active Tech)",
      "type": "n8n-nodes-base.slack",
      "position": [
        656,
        128
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f Predictive Failure Alert:\nMachine: {{ $json.machine_id }}\nTemperature: {{ $json.temperature }} degree calcius\nVibration: {{ $json.vibration }}\nJira Ticket : {{ $json.jira_ticket }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c3971d9b-3271-4634-a2ae-c2d4c575bf70",
      "name": "Escalate to Ops Emergency Channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        656,
        320
      ],
      "parameters": {
        "text": "=\ud83d\udea8 URGENT MACHINE FAILURE ESCALATION : Machine: {{ $json.machine_id }} Temperature: {{ $json.temperature }} degree calcius Vibration: {{ $json.vibration }} Jira Ticket : {{ $json.jira_ticket }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "2d2eb6dc-a130-4c6a-a5a7-bfa98dc690c8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1952,
        80
      ],
      "parameters": {
        "width": 400,
        "height": 768,
        "content": "## How it Works \nThis workflow automates predictive maintenance by linking IoT devices, Jira, and Slack. When a machine sends a webhook with data like temperature or vibration, the workflow checks if values exceed safety thresholds. If a potential failure is detected, it automatically creates a Jira maintenance ticket with all machine details.\n\nNext, the workflow fetches Slack channel members, checks each technician\u2019s real-time presence, and determines the first available technician. If someone is active, an alert is sent to the technician channel; if no one is available, it escalates to the emergency channel, ensuring no downtime goes unnoticed.\n\n## Setup Steps\n Import Workflow: Go to n8n \u2192 Workflows \u2192 Import from File and select the JSON.\n\nConfigure Slack: Add required scopes (users:read, users:read.presence, channels:read, chat:write) and reconnect credentials.\n\nUpdate Channels: Use your preferred Slack channels for technicians and emergency alerts.\n\nConfigure Jira: Add credentials, select project and issue type, and set priority mapping if needed.\n\nDeploy Webhook: Copy the n8n webhook URL and configure your IoT device to POST machine data.\n\nTest System: Send a test payload to ensure Jira tickets are created and Slack notifications route correctly based on technician availability."
      },
      "typeVersion": 1
    },
    {
      "id": "e9e516d9-e3bc-416a-af0d-d34d0d0ec482",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1440,
        608
      ],
      "parameters": {
        "color": 7,
        "width": 800,
        "height": 416,
        "content": "## Data Intake & Failure Detection\n### Receives real-time machine data from IoT devices and evaluates it against defined safety thresholds (temperature, vibration, etc.). If a failure is detected, automatically creates a Jira maintenance ticket with machine details, summary, labels, priority, and optional technician assignment."
      },
      "typeVersion": 1
    },
    {
      "id": "f4e9f5c4-37b7-4b01-babd-e80e694ede61",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -576,
        624
      ],
      "parameters": {
        "color": 7,
        "width": 1408,
        "height": 400,
        "content": "## Technician Identification & Presence Check\n### Fetches members from a selected Slack channel and processes them in batches to check real-time presence. Ensures scalable, efficient monitoring, providing a list of active technicians and supporting flexible configuration for any chosen technician channel."
      },
      "typeVersion": 1
    },
    {
      "id": "ae161b2b-e9b8-4749-9074-9755907cc428",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 528,
        "content": "## Technician Selection & Escalation Logic \n### Determines the first available technician using custom logic. If a technician is online, alerts are routed to the designated channel; if none are available, the workflow triggers fallback escalation to the emergency channel, ensuring no downtime goes unnoticed."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "adfa0047-bf2a-40d1-be62-7210841b8258",
  "connections": {
    "Check Failure Threshold": {
      "main": [
        [
          {
            "node": "Create Jira Maintenance Ticket",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Through Technicians": {
      "main": [
        [
          {
            "node": "Select Final Available Technician",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Technician Presence Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive IoT Machine Alert": {
      "main": [
        [
          {
            "node": "Check Failure Threshold",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Technician Active": {
      "main": [
        [
          {
            "node": "Format Technician Availability Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Jira Maintenance Ticket": {
      "main": [
        [
          {
            "node": "Fetch Technician Channel Members",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Technician Presence Status": {
      "main": [
        [
          {
            "node": "Check If Technician Active",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Technician Channel Members": {
      "main": [
        [
          {
            "node": "Prepare Technician Iteration Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check If Any Technician Available": {
      "main": [
        [
          {
            "node": "Send Technicians Alert (Active Tech)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Escalate to Ops Emergency Channel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Technician Iteration Data": {
      "main": [
        [
          {
            "node": "Loop Through Technicians",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select Final Available Technician": {
      "main": [
        [
          {
            "node": "Check If Any Technician Available",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Technician Availability Result": {
      "main": [
        [
          {
            "node": "Loop Through Technicians",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}