UNPKG

@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
[ { "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": [] } ]