@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.
865 lines • 25.2 kB
JSON
[
{
"id": "d7a9aa05686055cd",
"type": "subflow",
"name": "Get Shifts from MIP",
"info": "",
"category": "",
"in": [
{
"x": 40,
"y": 80,
"wires": [
{
"id": "08422e45ec1e2ee7"
}
]
}
],
"out": [
{
"x": 1440,
"y": 80,
"wires": [
{
"id": "cf7a26fbe3e06c3c",
"port": 0
}
]
}
],
"env": [],
"meta": {},
"color": "#DDAA99"
},
{
"id": "73c73b822cd7b597",
"type": "change",
"z": "d7a9aa05686055cd",
"name": "Delete META data",
"rules": [
{
"t": "delete",
"p": "payload[0]",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 890,
"y": 80,
"wires": [
[
"cf7a26fbe3e06c3c"
]
]
},
{
"id": "1b236955d0a8025e",
"type": "change",
"z": "d7a9aa05686055cd",
"name": "Clean up for next requests",
"rules": [
{
"t": "delete",
"p": "headers",
"pt": "msg"
},
{
"t": "delete",
"p": "url",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 660,
"y": 80,
"wires": [
[
"73c73b822cd7b597"
]
]
},
{
"id": "85c894ddeb73fef4",
"type": "http request",
"z": "d7a9aa05686055cd",
"name": "service call to MIP",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 410,
"y": 80,
"wires": [
[
"1b236955d0a8025e",
"8569908875de067d"
]
]
},
{
"id": "08422e45ec1e2ee7",
"type": "function",
"z": "d7a9aa05686055cd",
"name": "build request",
"func": "msg.payload = { \n \"params\": [], \n \"columns\": [], \n \"returnAsObject\": true,\n \"languageKey\": msg.languageKey\n}\n\nmsg.url = msg.baseUrl + \"/data/MDMFDayModel/list?X-Access-Id=\" + msg.xAccessId\n\nlet basic_encrypted = \"Basic \" + new Buffer(msg.user + ':' + msg.password).toString('base64')\n\nmsg.headers = { \n \"Content-Type\": \"application/json\",\n \"Authorization\": basic_encrypted\n}\n\nreturn msg;",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 190,
"y": 80,
"wires": [
[
"85c894ddeb73fef4"
]
]
},
{
"id": "cf7a26fbe3e06c3c",
"type": "function",
"z": "d7a9aa05686055cd",
"name": "Create shifts and breaks for all DayModels",
"func": "function formatDateToRRule(date) {\n const year = date.getUTCFullYear();\n const month = (\"0\" + (date.getUTCMonth() + 1)).slice(-2);\n const day = (\"0\" + date.getUTCDate()).slice(-2);\n const hours = (\"0\" + date.getUTCHours()).slice(-2);\n const minutes = (\"0\" + date.getUTCMinutes()).slice(-2);\n const seconds = (\"0\" + date.getUTCSeconds()).slice(-2);\n return `${year}${month}${day}T${hours}${minutes}${seconds}Z`;\n}\n\nfunction calculateTimeDifference(startSeconds, endSeconds) {\n // calculate the difference in seconds\n let differenceInSeconds = endSeconds - startSeconds;\n \n // special case where the shift goes to the next day\n if (endSeconds < startSeconds){\n differenceInSeconds = 86400 - startSeconds + endSeconds;\n }\n // calculate hours and minutes\n let hours = Math.floor(differenceInSeconds / 3600);\n let minutes = Math.floor((differenceInSeconds % 3600) / 60);\n // return as string in the format HH:MM\n return `${(\"0\" + hours).slice(-2)}:${(\"0\" + minutes).slice(-2)}`;\n}\n\nfunction timeFromMidnight(seconds) {\n // Create a new Date object for the current date\n let date = new Date();\n // Set the time to 00:00:00\n date.setHours(0, 0, 0, 0);\n // Add the seconds to the date object\n date.setSeconds(seconds);\n // Return the date object\n return date;\n}\n\n\n// DTSTART:20230723T040000Z\\nRRULE:FREQ=DAILY;BYDAY=MO;INTERVAL=1;UNTIL=20230730T000000Z\n\n// freq\nconst freq = \"DAILY\"\n\n// interval\nconst interval = 1\n\n// byday\nconst byday = \"MO,TU,WE,TH,FR,SA,SU\"\n\n// shiftsData\n\n\n\n// iterate over dayModels\nmsg.payload.forEach(dayModel => {\n msg.shiftsData = [];\n dayModel = dayModel.obj;\n // possible shifts\n for(let i=1; i < 5;i++){\n let currShiftName = dayModel[`mf_daymodel.shift${i}.type`]\n let currShiftStart = dayModel[`mf_daymodel.shift${i}.start`];\n let currShiftEnd = dayModel[`mf_daymodel.shift${i}.end`];\n \n // filter unused shifts\n if (currShiftStart === 0 && currShiftEnd === 0){\n continue;\n }\n // dtstart calculate hour from seconds since 00:00\n let dtstartDate = timeFromMidnight(currShiftStart);\n let dtstart = formatDateToRRule(dtstartDate); \n \n\n let newShift = { \n \"shiftName\": `shift${i}`, \n \"rrule\": `DTSTART:${dtstart}\\nRRULE:FREQ=${freq};BYDAY=${byday};INTERVAL=${interval}`, \n \"duration\": calculateTimeDifference(currShiftStart, currShiftEnd), \n \"mode\": \"work\", \n \"color\": \"azure\" \n };\n \n msg.shiftsData.push(newShift);\n \n // possible breaks\n for(let j=1; j < 7;j++){\n let currBreakStart = dayModel[`mf_daymodel.shift${i}.break${j}.start`];\n let currBreakEnd = dayModel[`mf_daymodel.shift${i}.break${j}.end`];\n \n \n // filter unused breaks\n if (currBreakStart === 0 && currBreakEnd === 0){\n continue;\n }\n \n // dtstart calculate hour from seconds since 00:00\n dtstartDate = timeFromMidnight(currBreakStart);\n dtstart = formatDateToRRule(dtstartDate); \n \n let newBreak = { \n \"shiftName\": `break${j}`, \n \"rrule\": `DTSTART:${dtstart}\\nRRULE:FREQ=${freq};BYDAY=${byday};INTERVAL=${interval}`, \n \"duration\": calculateTimeDifference(currBreakStart, currBreakEnd), \n \"mode\": \"pause\", \n \"color\": \"indigo\" \n };\n \n msg.shiftsData.push(newBreak);\n }\n \n }\n msg.scheduleName = dayModel[\"mf_daymodel.designation\"] ?? \"No Name in MIP\";\n node.send(msg);\n})",
"outputs": 1,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1190,
"y": 80,
"wires": [
[]
]
},
{
"id": "8569908875de067d",
"type": "debug",
"z": "d7a9aa05686055cd",
"name": "service call MIP",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "statusCode",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 620,
"y": 120,
"wires": []
},
{
"id": "e4de7c01e09a776f",
"type": "subflow",
"name": "Post shift",
"info": "",
"category": "",
"in": [
{
"x": 200,
"y": 400,
"wires": [
{
"id": "a49b15b920a72364"
}
]
}
],
"out": [],
"env": [],
"meta": {},
"color": "#DDAA99"
},
{
"id": "a49b15b920a72364",
"type": "function",
"z": "e4de7c01e09a776f",
"name": "Formatting json payload",
"func": "msg.headers = {\n \"Authorization\": \"Bearer \" + msg.bearerToken,\n \"Content-Type\": \"application/vnd.api+json\"\n};\n\nmsg.payload = {\n \"data\": {\n \"type\": \"shifts\",\n \"attributes\": {\n \"name\": msg.shiftName,\n \"rrule\": msg.rrule,\n \"duration\": msg.duration,\n \"mode\": msg.mode,\n \"color\": msg.color\n },\n \"relationships\": {\n \"schedule\": {\n \"data\": {\n \"type\": \"schedules\",\n \"id\": msg.schedule\n }\n }\n }\n }\n};\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 410,
"y": 400,
"wires": [
[
"90b0febb18e8d827"
]
]
},
{
"id": "90b0febb18e8d827",
"type": "http request",
"z": "e4de7c01e09a776f",
"name": "POST shift",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.oee.ai/shifts",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"senderr": false,
"x": 610,
"y": 400,
"wires": [
[
"e3a52c265232f222",
"96753bc5dfa1ce82"
]
]
},
{
"id": "e3a52c265232f222",
"type": "change",
"z": "e4de7c01e09a776f",
"name": "Delete response header",
"rules": [
{
"t": "delete",
"p": "headers",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 830,
"y": 400,
"wires": [
[
"41debf62367c281b"
]
]
},
{
"id": "41debf62367c281b",
"type": "debug",
"z": "e4de7c01e09a776f",
"name": "Response from oee.ai",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 1080,
"y": 400,
"wires": []
},
{
"id": "96753bc5dfa1ce82",
"type": "debug",
"z": "e4de7c01e09a776f",
"name": "Post Shift",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "statusCode",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 780,
"y": 440,
"wires": []
},
{
"id": "fd9e8ae80b46227a",
"type": "subflow",
"name": "Send shifts to oee.ai",
"info": "",
"category": "",
"in": [
{
"x": 0,
"y": 80,
"wires": [
{
"id": "7e6da3c796a23dc8"
}
]
}
],
"out": [],
"env": [],
"meta": {},
"color": "#DDAA99"
},
{
"id": "8632f17598829578",
"type": "subflow:e4de7c01e09a776f",
"z": "fd9e8ae80b46227a",
"name": "",
"x": 840,
"y": 80,
"wires": []
},
{
"id": "0e5877e09b93e4ad",
"type": "change",
"z": "fd9e8ae80b46227a",
"name": "Mapping shift attributes",
"rules": [
{
"t": "set",
"p": "shiftName",
"pt": "msg",
"to": "payload.shiftName",
"tot": "msg"
},
{
"t": "set",
"p": "rrule",
"pt": "msg",
"to": "payload.rrule",
"tot": "msg"
},
{
"t": "set",
"p": "duration",
"pt": "msg",
"to": "payload.duration",
"tot": "msg"
},
{
"t": "set",
"p": "mode",
"pt": "msg",
"to": "payload.mode",
"tot": "msg"
},
{
"t": "set",
"p": "color",
"pt": "msg",
"to": "msg.payload.color",
"tot": "msg"
},
{
"t": "set",
"p": "schedule",
"pt": "msg",
"to": "scheduleId",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 630,
"y": 80,
"wires": [
[
"8632f17598829578"
]
]
},
{
"id": "fc7521805a23e0f7",
"type": "split",
"z": "fd9e8ae80b46227a",
"name": "Split shifts",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "",
"x": 410,
"y": 80,
"wires": [
[
"0e5877e09b93e4ad"
]
]
},
{
"id": "7e6da3c796a23dc8",
"type": "change",
"z": "fd9e8ae80b46227a",
"name": "Set payload to shiftsData",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "shiftsData",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 190,
"y": 80,
"wires": [
[
"fc7521805a23e0f7"
]
]
},
{
"id": "3ef6e3cb08fd4645",
"type": "subflow",
"name": "Post schedule",
"info": "",
"category": "",
"in": [
{
"x": 360,
"y": 280,
"wires": [
{
"id": "16f20561eeb96ab6"
}
]
}
],
"out": [
{
"x": 1180,
"y": 280,
"wires": [
{
"id": "db876e05e8954483",
"port": 0
}
]
}
],
"env": [],
"meta": {},
"color": "#DDAA99"
},
{
"id": "16f20561eeb96ab6",
"type": "function",
"z": "3ef6e3cb08fd4645",
"name": "Formatting json payload",
"func": "msg.headers = {\n \"Authorization\": \"Bearer \" + msg.bearerToken,\n \"Content-Type\": \"application/vnd.api+json\"\n};\n\nmsg.payload = {\n \"data\": {\n \"type\": \"schedules\",\n \"attributes\": {\n \"name\": msg.scheduleName,\n \"end-based\": msg[\"end-based\"]\n },\n \"relationships\": {\n \"location\": {\n \"data\": {\n \"type\": \"locations\",\n \"id\": msg.location\n }\n }\n }\n }\n};\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 550,
"y": 280,
"wires": [
[
"8b789b3c687e3db2"
]
]
},
{
"id": "8b789b3c687e3db2",
"type": "http request",
"z": "3ef6e3cb08fd4645",
"name": "POST schedule",
"method": "POST",
"ret": "obj",
"paytoqs": "ignore",
"url": "https://api.oee.ai/schedules",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"senderr": false,
"x": 780,
"y": 280,
"wires": [
[
"db876e05e8954483"
]
]
},
{
"id": "db876e05e8954483",
"type": "change",
"z": "3ef6e3cb08fd4645",
"name": "Delete response header",
"rules": [
{
"t": "delete",
"p": "headers",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1010,
"y": 280,
"wires": [
[]
]
},
{
"id": "96e5bd1b60b318b2",
"type": "subflow",
"name": "Send schedules to oee.ai",
"info": "",
"category": "",
"in": [
{
"x": 480,
"y": 340,
"wires": [
{
"id": "15ad974df513bfef"
}
]
}
],
"out": [
{
"x": 1320,
"y": 340,
"wires": [
{
"id": "9ce0601df1e13c43",
"port": 0
}
]
}
],
"env": [],
"meta": {},
"color": "#DDAA99"
},
{
"id": "daf88fda59f965b3",
"type": "switch",
"z": "96e5bd1b60b318b2",
"name": "Check if schedule already exists",
"property": "statusCode",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "422",
"vt": "num"
},
{
"t": "else"
}
],
"checkall": "false",
"repair": false,
"outputs": 2,
"x": 870,
"y": 340,
"wires": [
[],
[
"9ce0601df1e13c43"
]
]
},
{
"id": "15ad974df513bfef",
"type": "subflow:3ef6e3cb08fd4645",
"z": "96e5bd1b60b318b2",
"name": "",
"x": 610,
"y": 340,
"wires": [
[
"daf88fda59f965b3",
"24c71de118817ecb"
]
]
},
{
"id": "9ce0601df1e13c43",
"type": "change",
"z": "96e5bd1b60b318b2",
"name": "Save schedule id",
"rules": [
{
"t": "set",
"p": "scheduleId",
"pt": "msg",
"to": "payload.data.id",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1150,
"y": 340,
"wires": [
[]
]
},
{
"id": "24c71de118817ecb",
"type": "debug",
"z": "96e5bd1b60b318b2",
"name": "Post schedules",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "statusCode",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 820,
"y": 400,
"wires": []
},
{
"id": "9e66472980aab6f0",
"type": "tab",
"label": "MIP Synchronizing shifts",
"disabled": false,
"info": "",
"env": []
},
{
"id": "167466639d86460a",
"type": "change",
"z": "9e66472980aab6f0",
"name": "Mapping schedule attributes",
"rules": [
{
"t": "set",
"p": "end-based",
"pt": "msg",
"to": "false",
"tot": "bool"
},
{
"t": "set",
"p": "location",
"pt": "msg",
"to": "",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1020,
"y": 140,
"wires": [
[
"5c8f83a28d8986f3"
]
]
},
{
"id": "7fae43045599e197",
"type": "comment",
"z": "9e66472980aab6f0",
"name": "^^ set schedule attributes",
"info": "Format your message to the data model of oee.ai\nThen map your message values to the predefined\nmessage values in the change node",
"x": 1010,
"y": 180,
"wires": []
},
{
"id": "6ab2cecafd2430ea",
"type": "comment",
"z": "9e66472980aab6f0",
"name": "^^ enter your oee.ai API token",
"info": "You can find your API Token on oee.ai",
"x": 760,
"y": 180,
"wires": []
},
{
"id": "aa7a250d8a9016fa",
"type": "change",
"z": "9e66472980aab6f0",
"name": "Set API Token",
"rules": [
{
"t": "set",
"p": "bearerToken",
"pt": "msg",
"to": "",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 720,
"y": 140,
"wires": [
[
"167466639d86460a"
]
]
},
{
"id": "5c8f83a28d8986f3",
"type": "subflow:96e5bd1b60b318b2",
"z": "9e66472980aab6f0",
"name": "",
"x": 1290,
"y": 140,
"wires": [
[
"9f59e0e470ee9951"
]
]
},
{
"id": "9f59e0e470ee9951",
"type": "subflow:fd9e8ae80b46227a",
"z": "9e66472980aab6f0",
"name": "",
"x": 1540,
"y": 140,
"wires": []
},
{
"id": "a01afc49bb617478",
"type": "change",
"z": "9e66472980aab6f0",
"name": "set settings",
"rules": [
{
"t": "set",
"p": "baseUrl",
"pt": "msg",
"to": "",
"tot": "str"
},
{
"t": "set",
"p": "user",
"pt": "msg",
"to": "",
"tot": "str"
},
{
"t": "set",
"p": "password",
"pt": "msg",
"to": "",
"tot": "str"
},
{
"t": "set",
"p": "xAccessId",
"pt": "msg",
"to": "",
"tot": "str"
},
{
"t": "set",
"p": "languageKey",
"pt": "msg",
"to": "en",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 290,
"y": 140,
"wires": [
[
"4ac3005169152875"
]
]
},
{
"id": "e3eeeb78c36d0d76",
"type": "inject",
"z": "9e66472980aab6f0",
"name": "Once",
"props": [],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 110,
"y": 140,
"wires": [
[
"a01afc49bb617478"
]
]
},
{
"id": "4ac3005169152875",
"type": "subflow:d7a9aa05686055cd",
"z": "9e66472980aab6f0",
"name": "Get Shifts from MIP",
"x": 490,
"y": 140,
"wires": [
[
"aa7a250d8a9016fa"
]
]
},
{
"id": "c9acf0f4fa89423e",
"type": "comment",
"z": "9e66472980aab6f0",
"name": "^^ configure your settings",
"info": "",
"x": 330,
"y": 180,
"wires": []
},
{
"id": "fae09fa111f0b325",
"type": "comment",
"z": "9e66472980aab6f0",
"name": "^^Click me",
"info": "",
"x": 110,
"y": 180,
"wires": []
}
]