|
[ |
|
{ |
|
"id": "7823c4cbf9ad1cb7", |
|
"type": "tab", |
|
"label": "NFC Chores", |
|
"disabled": false, |
|
"info": "", |
|
"env": [] |
|
}, |
|
{ |
|
"id": "47e41aab3a2c5d1b", |
|
"type": "inject", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Daily Trigger", |
|
"props": [{ "p": "payload" }, { "p": "topic", "vt": "str" }], |
|
"repeat": "", |
|
"crontab": "*/1 6-22 * * *", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"payload": "[\t \"todo.chores_daily_morning\",\t \"todo.chores_daily_evening\"\t]", |
|
"payloadType": "jsonata", |
|
"x": 140, |
|
"y": 100, |
|
"wires": [["09820fbcdda6d672"]] |
|
}, |
|
{ |
|
"id": "09820fbcdda6d672", |
|
"type": "ha-api", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Daily Todo List", |
|
"server": "5021ce22.33335", |
|
"version": 1, |
|
"debugenabled": false, |
|
"protocol": "websocket", |
|
"method": "get", |
|
"path": "", |
|
"data": "{\t \"type\": \"call_service\",\t \"domain\": \"todo\",\t \"service\": \"get_items\",\t \"target\": { \t \"entity_id\": \"todo.chores_daily\"\t },\t \"id\": 1,\t \"return_response\": true\t }", |
|
"dataType": "jsonata", |
|
"responseType": "json", |
|
"outputProperties": [ |
|
{ |
|
"property": "payload", |
|
"propertyType": "msg", |
|
"value": "", |
|
"valueType": "results" |
|
} |
|
], |
|
"x": 340, |
|
"y": 100, |
|
"wires": [["ba983682a8709d45"]] |
|
}, |
|
{ |
|
"id": "ba983682a8709d45", |
|
"type": "function", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Transform Chores", |
|
"func": "// Deep copy the raw response\nmsg.raw_response = JSON.parse(JSON.stringify(msg.payload));\n\n// Formats a date for updating todo items in home assistant\nfunction getCurrentDate() {\n const today = new Date();\n const year = today.getFullYear();\n const month = String(today.getMonth() + 1).padStart(2, '0');\n const day = String(today.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\n// Filters out for chores that are scheduled to be added\nfunction transformAllChores(apiResponse) {\n const currentHour = new Date().getHours();\n msg.current_hour = currentHour;\n const items = [];\n\n for (const key in apiResponse) {\n const listItems = apiResponse[key]?.items || [];\n\n const transformedItems = listItems\n .map(item => {\n const dueDate = new Date(item.due);\n const hour = dueDate.getHours();\n const minutes = dueDate.getMinutes();\n const seconds = dueDate.getSeconds();\n const formattedTime = `${String(hour).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;\n\n return {\n ...item,\n dueHour: hour,\n status: \"needs_action\",\n tag: item.description,\n todo_list: key,\n complete: false,\n due_datetime: `${getCurrentDate()} ${formattedTime}`\n };\n })\n .filter(item => item.dueHour <= currentHour)\n .map(({ description, dueHour, ...rest }) => rest);\n\n items.push(...transformedItems);\n }\n\n return items;\n}\n\n// Adds chores if they're not in the global chore list\nfunction syncUpcomingChores(apiResponse) {\n const currentChores = global.get('chores', 'file') || [];\n const upcomingChores = transformAllChores(apiResponse);\n const existingSummaries = new Set(currentChores.map(chore => chore.summary));\n\n const newChores = upcomingChores.filter(chore => !existingSummaries.has(chore.summary));\n const updatedChores = [...currentChores, ...newChores];\n\n global.set('chores', updatedChores, 'file');\n return updatedChores;\n}\n\n// Grabs the current chores and sends them out asynchronously\nconst updatedChores = syncUpcomingChores(msg.payload.response);\nupdatedChores.forEach(chore => {\n node.send({ payload: chore });\n});\n", |
|
"outputs": 1, |
|
"timeout": 0, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"libs": [], |
|
"x": 610, |
|
"y": 100, |
|
"wires": [["61073a4d6ef2d0ee"]] |
|
}, |
|
{ |
|
"id": "ad727d0a918726fa", |
|
"type": "inject", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Reset Chores", |
|
"props": [{ "p": "payload" }, { "p": "topic", "vt": "str" }], |
|
"repeat": "", |
|
"crontab": "00 05 * * *", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"payload": "", |
|
"payloadType": "date", |
|
"x": 140, |
|
"y": 360, |
|
"wires": [["4a69482a43321501"]] |
|
}, |
|
{ |
|
"id": "4a69482a43321501", |
|
"type": "change", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Clear Chores List", |
|
"rules": [ |
|
{ |
|
"t": "set", |
|
"p": "#:(file)::chores", |
|
"pt": "global", |
|
"to": "[]", |
|
"tot": "jsonata" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 330, |
|
"y": 360, |
|
"wires": [[]] |
|
}, |
|
{ |
|
"id": "bcc03a66c9718547", |
|
"type": "inject", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Get Chores", |
|
"props": [{ "p": "payload" }, { "p": "topic", "vt": "str" }], |
|
"repeat": "", |
|
"crontab": "", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"payload": "", |
|
"payloadType": "date", |
|
"x": 130, |
|
"y": 440, |
|
"wires": [["099c55965980d15e"]] |
|
}, |
|
{ |
|
"id": "099c55965980d15e", |
|
"type": "change", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Get global.chores", |
|
"rules": [ |
|
{ |
|
"t": "set", |
|
"p": "payload", |
|
"pt": "msg", |
|
"to": "#:(file)::chores", |
|
"tot": "global" |
|
} |
|
], |
|
"action": "", |
|
"property": "", |
|
"from": "", |
|
"to": "", |
|
"reg": false, |
|
"x": 330, |
|
"y": 440, |
|
"wires": [["eb3f9e221ae85d25"]] |
|
}, |
|
{ |
|
"id": "9f0a25079af5273b", |
|
"type": "ha-tag", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "", |
|
"server": "5021ce22.33335", |
|
"version": 2, |
|
"exposeAsEntityConfig": "", |
|
"tags": ["__ALL_TAGS__"], |
|
"devices": [], |
|
"outputProperties": [ |
|
{ |
|
"property": "payload", |
|
"propertyType": "msg", |
|
"value": "", |
|
"valueType": "eventData" |
|
}, |
|
{ |
|
"property": "topic", |
|
"propertyType": "msg", |
|
"value": "", |
|
"valueType": "triggerId" |
|
} |
|
], |
|
"x": 110, |
|
"y": 260, |
|
"wires": [["baaec6d9a0e23c9f"]] |
|
}, |
|
{ |
|
"id": "baaec6d9a0e23c9f", |
|
"type": "function", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Update Chores", |
|
"func": "// Get existing chores and count incomplete ones\nconst chores = global.get('chores', 'file') || [];\nconst previousChoreCount = chores.filter(chore => !chore.complete).length;\n\n// Mark chores as complete based on matching tag\nconst updatedChores = chores.map(chore => {\n if (chore.tag === msg.payload.name) {\n return { ...chore, complete: true, status: \"completed\" };\n }\n return chore;\n});\n\n// Save updated chore list\nglobal.set('chores', updatedChores, 'file');\n\n// Compute remaining chores\nconst remainingChores = updatedChores.filter(chore => !chore.complete);\n\n// Set message payload and metadata\nmsg.payload = updatedChores;\nmsg.previous_chore_count = previousChoreCount;\nmsg.remaining_chore_count = remainingChores.length;\n\nreturn msg;\n", |
|
"outputs": 1, |
|
"timeout": 0, |
|
"noerr": 0, |
|
"initialize": "", |
|
"finalize": "", |
|
"libs": [], |
|
"x": 280, |
|
"y": 260, |
|
"wires": [["9b9d42cdd758029e"]] |
|
}, |
|
{ |
|
"id": "4892caf26b3627b3", |
|
"type": "inject", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Weekend Trigger", |
|
"props": [{ "p": "payload" }, { "p": "topic", "vt": "str" }], |
|
"repeat": "", |
|
"crontab": "*/1 6-22 * * 6", |
|
"once": false, |
|
"onceDelay": 0.1, |
|
"topic": "", |
|
"payload": "[\t \"todo.chores_daily_morning\",\t \"todo.chores_daily_evening\"\t]", |
|
"payloadType": "jsonata", |
|
"x": 150, |
|
"y": 160, |
|
"wires": [["ca0cda6f48b85966"]] |
|
}, |
|
{ |
|
"id": "ca0cda6f48b85966", |
|
"type": "ha-api", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Weekend Todo List", |
|
"server": "5021ce22.33335", |
|
"version": 1, |
|
"debugenabled": false, |
|
"protocol": "websocket", |
|
"method": "get", |
|
"path": "", |
|
"data": "{\t \"type\": \"call_service\",\t \"domain\": \"todo\",\t \"service\": \"get_items\",\t \"target\": { \t \"entity_id\": \"todo.chores_weekend\"\t },\t \"id\": 1,\t \"return_response\": true\t }", |
|
"dataType": "jsonata", |
|
"responseType": "json", |
|
"outputProperties": [ |
|
{ |
|
"property": "payload", |
|
"propertyType": "msg", |
|
"value": "", |
|
"valueType": "results" |
|
} |
|
], |
|
"x": 350, |
|
"y": 160, |
|
"wires": [["ba983682a8709d45"]] |
|
}, |
|
{ |
|
"id": "61073a4d6ef2d0ee", |
|
"type": "ha-api", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Update Checklist", |
|
"server": "5021ce22.33335", |
|
"version": 1, |
|
"debugenabled": false, |
|
"protocol": "websocket", |
|
"method": "get", |
|
"path": "", |
|
"data": "{\t \"type\": \"execute_script\",\t \"sequence\": [\t {\t \"service\" : \"todo.update_item\",\t \"target\" : {\t \"entity_id\" : payload.todo_list\t },\t \"data\" : {\t \"status\" : payload.status,\t \"item\": payload.summary,\t \"due_datetime\": payload.due_datetime\t }\t },\t {\t \"stop\" : \"done\",\t \"response_variable\": \"service_result\"\t }\t ]\t}", |
|
"dataType": "jsonata", |
|
"responseType": "json", |
|
"outputProperties": [ |
|
{ |
|
"property": "payload", |
|
"propertyType": "msg", |
|
"value": "", |
|
"valueType": "results" |
|
} |
|
], |
|
"x": 610, |
|
"y": 140, |
|
"wires": [[]] |
|
}, |
|
{ |
|
"id": "9b9d42cdd758029e", |
|
"type": "link out", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Updated Chores", |
|
"mode": "link", |
|
"links": [], |
|
"x": 395, |
|
"y": 260, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "eb3f9e221ae85d25", |
|
"type": "debug", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Get Chores Debug Output", |
|
"active": true, |
|
"tosidebar": true, |
|
"console": false, |
|
"tostatus": false, |
|
"complete": "payload", |
|
"targetType": "msg", |
|
"statusVal": "", |
|
"statusType": "auto", |
|
"x": 550, |
|
"y": 440, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "4174d3798d930140", |
|
"type": "comment", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Logic to Update HA Chore Lists", |
|
"info": "", |
|
"x": 190, |
|
"y": 60, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "06694b6363513540", |
|
"type": "comment", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Logic to Mark Chores Complete", |
|
"info": "", |
|
"x": 190, |
|
"y": 220, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "7bf5b12db4869094", |
|
"type": "comment", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Nightly Chore List Reset", |
|
"info": "", |
|
"x": 170, |
|
"y": 320, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "17353b6e4bcd5b55", |
|
"type": "comment", |
|
"z": "7823c4cbf9ad1cb7", |
|
"name": "Debug", |
|
"info": "", |
|
"x": 110, |
|
"y": 400, |
|
"wires": [] |
|
}, |
|
{ |
|
"id": "5021ce22.33335", |
|
"type": "server", |
|
"name": "Home Assistant", |
|
"addon": true |
|
} |
|
] |