diff --git a/docs/cookbook/xfinity/index.md b/docs/cookbook/xfinity/index.md index ad51f388dc..c902b7c556 100644 --- a/docs/cookbook/xfinity/index.md +++ b/docs/cookbook/xfinity/index.md @@ -21,23 +21,6 @@ Here's an improved version of the requirements list with some additional context - **node-red-contrib-home-assistant-websocket** - [GitHub Repository](https://github.com/zachowj/node-red-contrib-home-assistant-websocket) - **Node-RED Companion Custom Component** - [GitHub Repository](https://github.com/zachowj/hass-node-red) -This flow requires Node-RED to be configured with a [context store](https://nodered.org/docs/user-guide/context#saving-context-data-to-the-file-system) named "file" to persist data to the file system. This is essential for storing the starting amount of the day’s usage. If desired, this functionality could be adapted to save the data as a sensor in Home Assistant instead. - -Add the following configuration to your `settings.js` file to enable file-based storage: - -```json title="settings.js" -contextStorage: { - default: { - module: "memory", // Volatile memory storage - }, - file: { - module: "localfilesystem" // Persistent storage in the file system - } -}, -``` - -This setup ensures that data, such as daily internet usage, is retained across Node-RED restarts. Alternatively, you can adjust the flow to save the daily starting value directly to a Home Assistant sensor, if desired. - ### Flow Overview ![screenshot of Node-RED flow](./flow.png) diff --git a/examples/cookbook/xfinity_usage.json b/examples/cookbook/xfinity_usage.json index 4d3d7b5435..c31601ef4d 100644 --- a/examples/cookbook/xfinity_usage.json +++ b/examples/cookbook/xfinity_usage.json @@ -1 +1 @@ -[{"id":"6615a5aad4b9ba51","type":"group","z":"1222406.8e2dfc","name":"Xfinity Usage","style":{"label":true},"nodes":["379b142b447e8ab7","4a33964bcdbd56d2","f85adedd5b32df85","68b863061ef4854f","d366fcc43a925970","9e55614bb42a6ef2","ab7a80d12efeaf5f","9d90f05012917222","b6ed587759967948","ee7d560c9248b5ed","08f4b8c0bfe2e999","d4897a6db2c8f634","da4171d93923d766","c6b4b9b22c1638c8","3a690e3333160edd","caf83470cf44375d","2111e9b06b258ddf"],"x":10,"y":1095,"w":956,"h":514},{"id":"379b142b447e8ab7","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"hours left","func":"const now = new Date();\nconst lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);\nconst hoursLeft = (lastDay.getDate() - now.getDate()) * 24 - now.getHours();\nconst hoursPassed = (now.getDate() - 1) * 24 + now.getHours();\nconst percent = hoursPassed / (hoursPassed + hoursLeft) * 100;\n\nmsg.payload = Math.round(percent);\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":1136,"wires":[["4a33964bcdbd56d2"]]},{"id":"4a33964bcdbd56d2","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Percent of hours passed","entityConfig":"fe831d83fa8a12c1","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":598,"y":1136,"wires":[[]]},{"id":"f85adedd5b32df85","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Usage Percent","entityConfig":"8c7d0c6eecee9819","version":0,"state":"$round(usagePercent)","stateType":"jsonata","attributes":[],"inputOverride":"block","outputProperties":[],"x":568,"y":1232,"wires":[[]]},{"id":"68b863061ef4854f","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Today's Usage","entityConfig":"cfe3bcc794d1f2c1","version":0,"state":"todaysUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":568,"y":1424,"wires":[[]]},{"id":"d366fcc43a925970","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Current Usage","entityConfig":"71242371557e25f3","version":0,"state":"currentUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":568,"y":1184,"wires":[[]]},{"id":"9e55614bb42a6ef2","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Remaining Daily Average","entityConfig":"12a17e3c3e3d36ed","version":0,"state":"$round(averageRemaining,1)","stateType":"jsonata","attributes":[],"inputOverride":"block","outputProperties":[],"x":598,"y":1328,"wires":[[]]},{"id":"ab7a80d12efeaf5f","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Used Daily Average","entityConfig":"3d5eaa4799914c8e","version":0,"state":"$round(averageUsed,1)","stateType":"jsonata","attributes":[],"inputOverride":"block","outputProperties":[],"x":588,"y":1376,"wires":[[]]},{"id":"9d90f05012917222","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"build sensors","func":"const usage = msg.usageMonths?.reverse();\n\nif (!usage) return;\n\nusage.forEach((month, index) => {\n // skip current month\n if (index === 0) return;\n\n const currentDate = new Date(month.startDate)\n const name = currentDate.toLocaleString(\"defualt\", { month: 'long', year: 'numeric' })\n const nodeId = `xfinity_month_usage_${index - 1}`; \n\n // in case sensor has been created yet use nodeId as the entity id\n msg.payload = { data: {\n type: \"nodered/discovery\",\n server_id: \"noderedserver\",\n node_id: nodeId,\n component: \"sensor\",\n config: {\n name: nodeId\n }\n }}; \n node.send(msg); \n \n // Update monthly usage to use friendly month name\n msg.payload = { data: {\n type: \"nodered/discovery\",\n server_id: \"noderedserver\",\n node_id: nodeId,\n component: \"sensor\",\n config: {\n name\n }\n }};\n \n node.send(msg); \n \n msg.payload = { data: {\n type: \"nodered/entity\",\n server_id: \"noderedserver\",\n node_id: nodeId,\n state: month.totalUsage,\n }};\n\n node.send(msg);\n});\n\nnode.done();","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":572,"y":1520,"wires":[["ee7d560c9248b5ed"]]},{"id":"b6ed587759967948","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Yesterday's Usage","entityConfig":"2c0a50b69a193618","version":0,"state":"yesterdaysUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":578,"y":1472,"wires":[[]]},{"id":"ee7d560c9248b5ed","type":"ha-api","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"create monthly usage sensors","server":"","version":1,"debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"","dataType":"jsonata","responseType":"json","outputProperties":[],"x":810,"y":1520,"wires":[[]]},{"id":"08f4b8c0bfe2e999","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"build message","func":"if(msg.payload === \"open\") {\n context.set(\"open\", true, \"file\");\n return;\n}\nif(context.get(\"open\", \"file\") !== true) return;\n\nconst today = new Date();\nconst monthlyReset = today.getDate() === 1;\nconst lastMonth = msg.payload.usageMonths.find(e => e.startDate.split(\"/\")[0] == getPreviousMonth(today.getMonth() + 1));\nconst currentUsage = monthlyReset ? lastMonth.totalUsage : msg.currentUsage;\nconst startOfYesterday = flow.get(\"xfinityStartedTodayAt\", \"file\") || 0;\nconst usedYesterday = currentUsage - startOfYesterday; \n\nmsg.payload = `${usedYesterday} GB used yesterday`;\nmsg.yesterdaysUsage = usedYesterday;\n\nif(monthlyReset) {\n const percent = currentUsage/lastMonth.allowableUsage * 100;\n msg.payload += `
Used ${currentUsage} of ${lastMonth.allowableUsage} GB (${percent.toFixed(1)}%) last month`;\n} else {\n msg.payload += ` ${msg.remainingUsage} GB remaining`;\n}\n\nflow.set(\"xfinityStartedTodayAt\", msg.currentUsage, \"file\");\ncontext.set(\"open\", false, \"file\");\n\nmsg.todaysUsage = 0;\n\nreturn msg;\n\nfunction getPreviousMonth(month) { \n return month === 1 ? 12 : month - 1;\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":312,"y":1520,"wires":[["68b863061ef4854f","b6ed587759967948","c6b4b9b22c1638c8"]]},{"id":"d4897a6db2c8f634","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"transform data","func":"const todayStartedAt = flow.get(\"xfinityStartedTodayAt\", \"file\") || 0;\nconst today = new Date();\nconst currentDay = today.getDate();\nconst daysInMonth = new Date(today.getFullYear(), today.getMonth()+1, 0).getDate();\nconst daysLeftInMonth = daysInMonth - currentDay + 1;\nconst currentMonth = msg.payload.usageMonths.find(e => e.startDate.split(\"/\")[0] == today.getMonth() + 1)\nconst allowableUsage = currentMonth.allowableUsage;\nconst currentUsage = currentMonth.totalUsage;\nconst remainingUsage = allowableUsage - currentUsage;\nconst averageUsed = currentUsage / currentDay;\nconst averageRemaining = remainingUsage / daysLeftInMonth;\nconst todaysUsage = currentUsage - todayStartedAt;\nconst usagePercent = currentUsage / allowableUsage * 100;\n\nreturn {\n usagePercent,\n currentUsage,\n allowableUsage,\n todaysUsage,\n averageUsed,\n averageRemaining,\n remainingUsage,\n usageMonths: msg.payload.usageMonths,\n};\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":264,"y":1328,"wires":[["f85adedd5b32df85","68b863061ef4854f","d366fcc43a925970","9e55614bb42a6ef2","ab7a80d12efeaf5f","9d90f05012917222","08f4b8c0bfe2e999","2111e9b06b258ddf"]]},{"id":"da4171d93923d766","type":"mqtt in","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"","topic":"xfinity","qos":"2","datatype":"auto-detect","broker":"644903cf.1e7dbc","nl":false,"rap":true,"rh":0,"inputs":0,"x":94,"y":1328,"wires":[["d4897a6db2c8f634"]]},{"id":"c6b4b9b22c1638c8","type":"api-call-service","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"send daily notification","server":"","version":7,"debugenabled":false,"action":"notify.person","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{\t \"title\": \"Data Usage\",\t \"message\": payload\t}","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":true,"domain":"notify","service":"person","x":588,"y":1568,"wires":[[]]},{"id":"3a690e3333160edd","type":"inject","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"12 am","props":[],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","x":116,"y":1520,"wires":[["08f4b8c0bfe2e999"]]},{"id":"caf83470cf44375d","type":"inject","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"every hour","props":[],"repeat":"","crontab":"0 0-23 * * *","once":true,"onceDelay":0.1,"topic":"","x":130,"y":1136,"wires":[["379b142b447e8ab7"]]},{"id":"2111e9b06b258ddf","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Remaining Usage","entityConfig":"edb2ab02c66aafda","version":0,"state":"remainingUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":578,"y":1280,"wires":[[]]},{"id":"fe831d83fa8a12c1","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Percent of hours passed","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Percent of hours passed"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"8c7d0c6eecee9819","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Usage Percent"},{"property":"icon","value":"mdi:percent"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"cfe3bcc794d1f2c1","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Today's Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Today's Usage"},{"property":"icon","value":"mdi:calendar-today"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"71242371557e25f3","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Current Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Current Usage"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"12a17e3c3e3d36ed","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Remaining Daily Average","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Average GB Remaining"},{"property":"icon","value":"mdi:chart-ppf"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB/day"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"3d5eaa4799914c8e","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Used Daily Average","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Average GB Used"},{"property":"icon","value":"mdi:chart-line"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB/day"},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"2c0a50b69a193618","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Yesterday's Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Yesterday's Usage"},{"property":"icon","value":"mdi:calendar-today"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"edb2ab02c66aafda","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Remaining Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Remaining Usage"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"157d6b39b3e283d5","type":"ha-device-config","name":"Xfinity Usage","hwVersion":"","manufacturer":"Node-RED","model":"","swVersion":""}] +[{"id":"6615a5aad4b9ba51","type":"group","z":"1222406.8e2dfc","name":"Xfinity Usage","style":{"label":true},"nodes":["379b142b447e8ab7","4a33964bcdbd56d2","f85adedd5b32df85","68b863061ef4854f","d366fcc43a925970","9e55614bb42a6ef2","ab7a80d12efeaf5f","9d90f05012917222","b6ed587759967948","ee7d560c9248b5ed","08f4b8c0bfe2e999","d4897a6db2c8f634","da4171d93923d766","c6b4b9b22c1638c8","3a690e3333160edd","caf83470cf44375d","2111e9b06b258ddf","82e81d1a2fed3a97","3e951e9bd9848f0a"],"x":14,"y":1095,"w":968,"h":562},{"id":"379b142b447e8ab7","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"hours left","func":"const now = new Date();\nconst lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);\nconst hoursLeft = (lastDay.getDate() - now.getDate()) * 24 - now.getHours();\nconst hoursPassed = (now.getDate() - 1) * 24 + now.getHours();\nconst percent = hoursPassed / (hoursPassed + hoursLeft) * 100;\n\nmsg.payload = Math.round(percent);\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":324,"y":1136,"wires":[["4a33964bcdbd56d2"]]},{"id":"4a33964bcdbd56d2","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Percent of hours passed","entityConfig":"fe831d83fa8a12c1","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":626,"y":1136,"wires":[[]]},{"id":"f85adedd5b32df85","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Usage Percent","entityConfig":"8c7d0c6eecee9819","version":0,"state":"$round(usagePercent)","stateType":"jsonata","attributes":[],"inputOverride":"block","outputProperties":[],"x":596,"y":1232,"wires":[[]]},{"id":"68b863061ef4854f","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Today's Usage","entityConfig":"cfe3bcc794d1f2c1","version":0,"state":"todaysUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":594,"y":1472,"wires":[[]]},{"id":"d366fcc43a925970","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Current Usage","entityConfig":"71242371557e25f3","version":0,"state":"currentUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":596,"y":1184,"wires":[[]]},{"id":"9e55614bb42a6ef2","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Remaining Daily Average","entityConfig":"12a17e3c3e3d36ed","version":0,"state":"$round(averageRemaining,1)","stateType":"jsonata","attributes":[],"inputOverride":"block","outputProperties":[],"x":626,"y":1328,"wires":[[]]},{"id":"ab7a80d12efeaf5f","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Used Daily Average","entityConfig":"3d5eaa4799914c8e","version":0,"state":"$round(averageUsed,1)","stateType":"jsonata","attributes":[],"inputOverride":"block","outputProperties":[],"x":616,"y":1376,"wires":[[]]},{"id":"9d90f05012917222","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"build sensors","func":"const usage = msg.usageMonths?.reverse();\n\nif (!usage) return;\n\nusage.forEach((month, index) => {\n // skip current month\n if (index === 0) return;\n\n const currentDate = new Date(month.startDate)\n const name = currentDate.toLocaleString(\"defualt\", { month: 'long', year: 'numeric' })\n const nodeId = `xfinity_month_usage_${index - 1}`; \n\n // in case sensor has been created yet use nodeId as the entity id\n msg.payload = { data: {\n type: \"nodered/discovery\",\n server_id: \"noderedserver\",\n node_id: nodeId,\n component: \"sensor\",\n config: {\n name: nodeId\n }\n }}; \n node.send(msg); \n \n // Update monthly usage to use friendly month name\n msg.payload = { data: {\n type: \"nodered/discovery\",\n server_id: \"noderedserver\",\n node_id: nodeId,\n component: \"sensor\",\n config: {\n name\n }\n }};\n \n node.send(msg); \n \n msg.payload = { data: {\n type: \"nodered/entity\",\n server_id: \"noderedserver\",\n node_id: nodeId,\n state: month.totalUsage,\n }};\n\n node.send(msg);\n});\n\nnode.done();","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":594,"y":1424,"wires":[["ee7d560c9248b5ed"]]},{"id":"b6ed587759967948","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Yesterday's Usage","entityConfig":"2c0a50b69a193618","version":0,"state":"yesterdaysUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":604,"y":1520,"wires":[[]]},{"id":"ee7d560c9248b5ed","type":"ha-api","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"create monthly usage sensors","server":"","version":1,"debugenabled":false,"protocol":"websocket","method":"get","path":"","data":"","dataType":"jsonata","responseType":"json","outputProperties":[],"x":826,"y":1424,"wires":[[]]},{"id":"08f4b8c0bfe2e999","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"build message","func":"if(msg.payload === \"open\") {\n context.set(\"open\", true);\n return;\n}\nif(context.get(\"open\") !== true) return;\n\nconst today = new Date();\nconst monthlyReset = today.getDate() === 1;\nconst lastMonth = msg.payload.usageMonths.find(e => e.startDate.split(\"/\")[0] == getPreviousMonth(today.getMonth() + 1));\nconst currentUsage = monthlyReset ? lastMonth.totalUsage : msg.currentUsage;\nconst startOfYesterday = !isNaN(msg.xfinityStartedTodayAt) ? msg.xfinityStartedTodayAt : 0;\nconst usedYesterday = currentUsage - startOfYesterday; \n\nmsg.payload = `${usedYesterday} GB used yesterday`;\nmsg.yesterdaysUsage = usedYesterday;\n\nif(monthlyReset) {\n const percent = currentUsage/lastMonth.allowableUsage * 100;\n msg.payload += `
Used ${currentUsage} of ${lastMonth.allowableUsage} GB (${percent.toFixed(1)}%) last month`;\n} else {\n msg.payload += ` ${msg.remainingUsage} GB remaining`;\n}\n\ncontext.set(\"open\", false);\n\nmsg.todaysUsage = 0;\nmsg.xfinityStartedTodayAt = msg.currentUsage;\n\nreturn msg;\n\nfunction getPreviousMonth(month) { \n return month === 1 ? 12 : month - 1;\n}","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":336,"y":1472,"wires":[["68b863061ef4854f","b6ed587759967948","c6b4b9b22c1638c8","82e81d1a2fed3a97"]]},{"id":"d4897a6db2c8f634","type":"function","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"transform data","func":"const todayStartedAt = flow.get(\"xfinityStartedTodayAt\", \"file\") || 0;\nconst today = new Date();\nconst currentDay = today.getDate();\nconst daysInMonth = new Date(today.getFullYear(), today.getMonth()+1, 0).getDate();\nconst daysLeftInMonth = daysInMonth - currentDay + 1;\nconst currentMonth = msg.payload.usageMonths.find(e => e.startDate.split(\"/\")[0] == today.getMonth() + 1)\nconst allowableUsage = currentMonth.allowableUsage;\nconst currentUsage = currentMonth.totalUsage;\nconst remainingUsage = allowableUsage - currentUsage;\nconst averageUsed = currentUsage / currentDay;\nconst averageRemaining = remainingUsage / daysLeftInMonth;\nconst todaysUsage = currentUsage - todayStartedAt;\nconst usagePercent = currentUsage / allowableUsage * 100;\n\nreturn {\n usagePercent,\n currentUsage,\n allowableUsage,\n todaysUsage,\n averageUsed,\n averageRemaining,\n remainingUsage,\n usageMonths: msg.payload.usageMonths,\n};\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":336,"y":1328,"wires":[["f85adedd5b32df85","68b863061ef4854f","d366fcc43a925970","9e55614bb42a6ef2","ab7a80d12efeaf5f","9d90f05012917222","2111e9b06b258ddf","3e951e9bd9848f0a"]]},{"id":"da4171d93923d766","type":"mqtt in","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"","topic":"xfinity","qos":"2","datatype":"auto-detect","broker":"644903cf.1e7dbc","nl":false,"rap":true,"rh":0,"inputs":0,"x":94,"y":1328,"wires":[["d4897a6db2c8f634"]]},{"id":"c6b4b9b22c1638c8","type":"api-call-service","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"send daily notification","server":"","version":7,"debugenabled":false,"action":"notify.jason","floorId":[],"areaId":[],"deviceId":[],"entityId":[],"labelId":[],"data":"{\t \"title\": \"Data Usage\",\t \"message\": payload\t}","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","blockInputOverrides":true,"domain":"notify","service":"jason","x":616,"y":1616,"wires":[[]]},{"id":"3a690e3333160edd","type":"inject","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"12 am","props":[{"p":"payload"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"open","payloadType":"str","x":164,"y":1520,"wires":[["08f4b8c0bfe2e999"]]},{"id":"caf83470cf44375d","type":"inject","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"every hour","props":[],"repeat":"","crontab":"0 0-23 * * *","once":true,"onceDelay":0.1,"topic":"","x":130,"y":1136,"wires":[["379b142b447e8ab7"]]},{"id":"2111e9b06b258ddf","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Remaining Usage","entityConfig":"edb2ab02c66aafda","version":0,"state":"remainingUsage","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":606,"y":1280,"wires":[[]]},{"id":"82e81d1a2fed3a97","type":"ha-sensor","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"Started Today At","entityConfig":"8e9f1b420bd7ac23","version":0,"state":"xfinityStartedTodayAt","stateType":"msg","attributes":[],"inputOverride":"block","outputProperties":[],"x":606,"y":1568,"wires":[[]]},{"id":"3e951e9bd9848f0a","type":"api-current-state","z":"1222406.8e2dfc","g":"6615a5aad4b9ba51","name":"startedTodayAt","server":"","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.xfinity_started_today_at","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"xfinityStartedTodayAt","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":144,"y":1472,"wires":[["08f4b8c0bfe2e999"]]},{"id":"fe831d83fa8a12c1","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Percent of hours passed","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Percent of hours passed"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"8c7d0c6eecee9819","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Usage Percent"},{"property":"icon","value":"mdi:percent"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"%"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"cfe3bcc794d1f2c1","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Today's Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Today's Usage"},{"property":"icon","value":"mdi:calendar-today"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"71242371557e25f3","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Current Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Current Usage"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"12a17e3c3e3d36ed","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Remaining Daily Average","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Average GB Remaining"},{"property":"icon","value":"mdi:chart-ppf"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB/day"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"3d5eaa4799914c8e","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Used Daily Average","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Average GB Used"},{"property":"icon","value":"mdi:chart-line"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB/day"},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"2c0a50b69a193618","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Yesterday's Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Yesterday's Usage"},{"property":"icon","value":"mdi:calendar-today"},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"edb2ab02c66aafda","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Remaining Usage","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Remaining Usage"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"8e9f1b420bd7ac23","type":"ha-entity-config","server":"","deviceConfig":"157d6b39b3e283d5","name":"Xfinity Started Today At","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"Xfinity Started Today At"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":"GB"},{"property":"state_class","value":""}],"resend":true,"debugEnabled":false},{"id":"157d6b39b3e283d5","type":"ha-device-config","name":"Xfinity Usage","hwVersion":"","manufacturer":"Node-RED","model":"","swVersion":""}]