@ifp-software/node-red-contrib-oee-ai-connector
Version:
Easily connect your production machines to oee.ai – The Industry 4.0 solution for OEE optimization.
506 lines • 15.2 kB
JSON
[
{
"id": "901c8e8f8d43cbb7",
"type": "tab",
"label": "Connecting a SQL DB",
"disabled": false,
"info": "",
"env": []
},
{
"id": "e4df151a7bc1c137",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Build SQL Query",
"func": "// create array of machine keys\nconst machineKeys = Object.keys(msg.locationMapping)\n\n// Format machine keys to a comma seperated string\nlet listifiedKeys = `${machineKeys.map(key => `${key}`).join(', ')}`;\n\nmsg.query = `SELECT * FROM table_name WHERE machine_id IN (${listifiedKeys})`;\n\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 350,
"y": 220,
"wires": [
[]
]
},
{
"id": "f63c018b4ea9f73f",
"type": "inject",
"z": "901c8e8f8d43cbb7",
"name": "Configuration",
"props": [
{
"p": "locationMapping",
"v": "{\"MCH2001\":\"883ba0a6-f6d1-4814-bcda-b8518fb12423\",\"MCH2002\":\"a92023f5-0371-47ca-9ff8-7272756e68e3\",\"MCH2003\":\"655efb1e-90c7-41d7-987b-837a337240f1\"}",
"vt": "json"
},
{
"p": "timestamp",
"v": "",
"vt": "date"
}
],
"repeat": "",
"crontab": "*/1 0 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 140,
"y": 220,
"wires": [
[
"e4df151a7bc1c137"
]
]
},
{
"id": "c7529de85ac16b2e",
"type": "split",
"z": "901c8e8f8d43cbb7",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "",
"property": "payload",
"x": 670,
"y": 220,
"wires": [
[
"c90dd0d53d225625",
"7144c51ebf3a07d9",
"5c46a03c48378bc4"
]
]
},
{
"id": "0ab7229eaa0c8b1d",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "SQL Node",
"info": "",
"x": 520,
"y": 220,
"wires": []
},
{
"id": "72b8a4bf0e26d004",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Is entry new?",
"func": "const machineId = msg.payload.machine_id;\nconst timestamp = msg.payload.timestamp;\nconst oldTimestamp = flow.get(`${machineId}oldTimestamp`);\n\nif (timestamp !== oldTimestamp) {\n flow.set(`${machineId}oldTimestamp`, timestamp);\n return msg;\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 690,
"y": 280,
"wires": [
[]
]
},
{
"id": "5f3b159ca5543a98",
"type": "switch",
"z": "901c8e8f8d43cbb7",
"name": "Switch on Machine Identifier",
"property": "payload.machine_id",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "MCH2001",
"vt": "str"
},
{
"t": "eq",
"v": "MCH2002",
"vt": "str"
},
{
"t": "eq",
"v": "MCH2003",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 3,
"x": 1300,
"y": 120,
"wires": [
[
"44b76704ca27625a"
],
[
"66c36876da27c237"
],
[
"c5fe935eafb3f4fc"
]
]
},
{
"id": "c90dd0d53d225625",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Build measurements",
"func": "const INTERVALL_IN_SECONDS = 60\nmsg.from = msg.payload.timestamp\nmsg.to = msg.payload.timestamp // Use this if your count is <1 or you dont want automatic distribution\nmsg.to = msg.payload.timestamp - (INTERVALL_IN_SECONDS * 1000) // Use this if you query in a set intervall or have an accumulating counter and want it to be distributed\n\nreturn msg;\n\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1040,
"y": 120,
"wires": [
[
"5f3b159ca5543a98"
]
]
},
{
"id": "44b76704ca27625a",
"type": "oee-ai-connector",
"z": "901c8e8f8d43cbb7",
"name": "MCH2001",
"server": "production",
"protocol": "wss-443",
"x": 1610,
"y": 40,
"wires": []
},
{
"id": "66c36876da27c237",
"type": "oee-ai-connector",
"z": "901c8e8f8d43cbb7",
"name": "MCH2002",
"server": "production",
"protocol": "wss-443",
"x": 1610,
"y": 100,
"wires": []
},
{
"id": "c5fe935eafb3f4fc",
"type": "oee-ai-connector",
"z": "901c8e8f8d43cbb7",
"name": "MCH2003",
"server": "production",
"protocol": "wss-443",
"x": 1610,
"y": 160,
"wires": []
},
{
"id": "7144c51ebf3a07d9",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Product changed",
"func": "const machineId = msg.payload.machine_id;\nconst productId = msg.payload.product_id;\nconst oldProductId = flow.get(`${machineId}oldProductId`);\n\nif (productId !== oldProductId){\n flow.set(`${machineId}oldProductId`, productId);\n msg.productId = productId;\n msg.machineId = machineId;\n return msg;\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1030,
"y": 320,
"wires": [
[
"137f502157697867"
]
]
},
{
"id": "26f2af41978494b7",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Create changeover payload",
"func": "if (msg.payload.data.length > 0){\n const productId = msg.payload.data[0].id;\n const locationId = msg.locationMapping[msg.machineId].locationId;\n const time = new Date(msg.timestamp).toISOString();\n\n msg.payload = {\n \"data\": {\n \"attributes\": {\n \"time\": time,\n },\n \"relationships\": {\n \"product\": {\n \"data\": {\n \"id\": productId,\n }\n },\n \"location\": {\n \"data\": {\n \"id\": locationId,\n }\n }\n }\n }\n };\n\n return msg;\n}else{\n node.error(`Product with productId \"${msg.productId}\" not found in oee.ai`);\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1660,
"y": 320,
"wires": [
[
"e0c243a0daa0c10f"
]
]
},
{
"id": "137f502157697867",
"type": "http request",
"z": "901c8e8f8d43cbb7",
"name": "GET Product for Article ID",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.oee.ai/products?filter[code-or-description]={{{productId}}}",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "bearer",
"senderr": false,
"headers": [],
"x": 1290,
"y": 320,
"wires": [
[
"26f2af41978494b7"
]
]
},
{
"id": "e0c243a0daa0c10f",
"type": "mqtt out",
"z": "901c8e8f8d43cbb7",
"name": "Send Changeover",
"topic": "",
"qos": "2",
"retain": "true",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "",
"x": 1930,
"y": 320,
"wires": []
},
{
"id": "e363d841ceef487b",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^ Replace with oee.ai sensor information",
"info": "",
"x": 1700,
"y": 220,
"wires": []
},
{
"id": "af515eb18929c95a",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^ Add MQTT Details",
"info": "",
"x": 1940,
"y": 380,
"wires": []
},
{
"id": "e76053f379176fab",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^ Add API-Token",
"info": "",
"x": 1270,
"y": 360,
"wires": []
},
{
"id": "5c46a03c48378bc4",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Loss Reason detected",
"func": "const machineId = msg.payload.machine_id;\nconst machineState = msg.payload.machine_state;\nconst oldMachineState = flow.get(`${machineId}oldMachineState`);\n\n\nif (machineState !== oldMachineState){\n msg.machineState = machineState;\n msg.locationId = msg.locationMapping[machineId].locationId;\n msg.machineId = machineId;\n flow.set(`${machineId}machineState`, machineState);\n\n return msg;\n}\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1040,
"y": 500,
"wires": [
[
"84b4f6668f75c205"
]
]
},
{
"id": "84b4f6668f75c205",
"type": "http request",
"z": "901c8e8f8d43cbb7",
"name": "GET Loss Reasons",
"method": "GET",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.oee.ai/loss-reasons?filter[locations]={{{locationId}}}",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "bearer",
"senderr": false,
"headers": [],
"x": 1270,
"y": 500,
"wires": [
[
"f641ac63c0667b9e"
]
]
},
{
"id": "f641ac63c0667b9e",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Save Loss Reason ID ",
"func": "const lossReasonId = msg.payload.data.find(item => item.attributes.details?.machineState === msg.machineState)?.id || null;\n\n// we save it with the location ID so its easier to match on the incoming loss alerts\nflow.set(`${msg.locationId}lossReasonId`, lossReasonId);\n\nif(msg.machineState && lossReasonId === null){\n node.error(`Loss Reason with machineState \"${msg.machineState}\" not found in oee.ai`);\n}",
"outputs": 0,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1640,
"y": 500,
"wires": []
},
{
"id": "21b7325c1f731f54",
"type": "mqtt in",
"z": "901c8e8f8d43cbb7",
"name": "Listen for Loss Alerts",
"topic": " ",
"qos": "2",
"datatype": "auto-detect",
"broker": "",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 1030,
"y": 640,
"wires": [
[
"4ccc3c62c54fbbcf"
]
]
},
{
"id": "4ccc3c62c54fbbcf",
"type": "function",
"z": "901c8e8f8d43cbb7",
"name": "Create payload",
"func": "const locationId = msg.payload.data.relationships.location.data.id;\nconst lossAlertHasLossReason = msg.payload.data.relationships[\"loss-reason\"]?.data?.id;\nconst lossReasonId = flow.get(`${locationId}lossReasonId`);\nconst lossAlertId = msg.payload.data.id;\n\nif (!lossAlertHasLossReason && lossReasonId){\n msg.payload = {\n \"data\": {\n \"id\": lossAlertId,\n \"relationships\": {\n \"loss-reason\": {\n \"data\": {\n \"id\": lossReasonId\n }\n }\n }\n }\n };\n\n return msg;\n}\n\nif (!lossAlertHasLossReason && lossReasonId === null ){\n node.warn(`No UserState for loss alert \"${lossAlertId}\"`);\n}",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1260,
"y": 640,
"wires": [
[
"2172febdd78e2f57"
]
]
},
{
"id": "2172febdd78e2f57",
"type": "mqtt out",
"z": "901c8e8f8d43cbb7",
"name": "Send Alert Reason",
"topic": "",
"qos": "2",
"retain": "true",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "",
"x": 1630,
"y": 640,
"wires": []
},
{
"id": "13e741079e2f04c0",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^ Add API-Token",
"info": "",
"x": 1270,
"y": 540,
"wires": []
},
{
"id": "196ce0f652f62656",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^Optional validity check",
"info": "",
"x": 730,
"y": 360,
"wires": []
},
{
"id": "8b97ac3dd6983c00",
"type": "switch",
"z": "901c8e8f8d43cbb7",
"name": "Data up to date?",
"property": "payload.data_up_to_date",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "1",
"vt": "num"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 710,
"y": 320,
"wires": [
[]
]
},
{
"id": "14749a70ee842810",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^ Add MQTT Details",
"info": "",
"x": 1640,
"y": 700,
"wires": []
},
{
"id": "e043f1ef64fb06a4",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^ Add MQTT Details",
"info": "",
"x": 1040,
"y": 700,
"wires": []
},
{
"id": "cd42aacb94ae34ae",
"type": "comment",
"z": "901c8e8f8d43cbb7",
"name": "^^Optional validity check",
"info": "",
"x": 150,
"y": 260,
"wires": []
}
]