Work-Time-Tracker
Track your work day and get reminders to take a break.
About this flow
| System | Node-RED |
|---|---|
| AWTRIX version | AWTRIX 3 |
| Topic | Miscellaneous |
| Built by | Frifan |
| File | qMpQAgZE50Ky.json · 4.2 KB |
| Icons | — |
| Published | 25 May 2025 |
| Downloads | 19 |
Is this your flow?
If you created this flow, open your saved edit link to add it to your account. You can then manage it whenever you sign in. Adding it to your account replaces the edit link.
A 7.5 hour countdown that pauses every hour and switches to a 10 minute countdown to remind the user to take a break.
At the end of the countdown the message "STOP WORK" is displayed in red.
qMpQAgZE50Ky.json
[
{
"id":"mqtt_btn",
"type":"mqtt in",
"z":"flow",
"name":"AWTRIX Button",
"topic":"YOUR_MQTT_PREFIX/btn",
"qos":"0",
"datatype":"json",
"broker":"mqtt_broker"
},
{
"id":"handle_btn",
"type":"function",
"z":"flow",
"name":"Handle Middle Button",
"func":"// states: idle, work, break\nlet state = global.get('workState') || 'idle';\nif(msg.payload.button!=='middle') return null;\nswitch(state) {\n case 'idle':\n global.set('workState','work');\n return {topic:'work_start'};\n case 'work':\n global.set('workState','break');\n return {topic:'break_start'};\n case 'break':\n global.set('workState','work');\n return {topic:'break_resume'};\n}\nreturn null;","outputs":1,"noerr":0},
{
"id":"inject_tick",
"type":"inject",
"z":"flow",
"name":"Every second",
"props":[{"p":"payload"}],
"repeat":"1",
"once":false
},
{
"id":"publish_work",
"type":"function",
"z":"flow",
"name":"Work Timer Tick",
"func":"let state=global.get('workState');\nif(state!=='work') return null;\nlet start=global.get('workStart')||Date.now();\nlet elapsed=(Date.now()-start)/1000; // seconds\nlet total=7.5*3600;\nlet rem=Math.max(0, total-elapsed)|0;\nlet pct=((elapsed/total)*100)|0;\n// hourly break trigger\nglobal.set('lastHourTrig', global.get('lastHourTrig')||0);\nif(rem%3600===0 && rem!==total && rem/3600!==global.get('lastHourTrig')){\n global.set('lastHourTrig', rem/3600);\n global.set('workState','paused_for_break');\n return {topic:'hour_break'};\n}\nmsg.payload=JSON.stringify({icon:global.get('timerIcon'),text:rem,progress:pct,progressC:'#f00',progressBC:'#000'});\nmsg.topic=`${global.get('mqttPrefix')}/${global.get('customTopic')}`;\nreturn msg;","outputs":1,"noerr":0},
{
"id":"work_start",
"type":"function",
"z":"flow",
"name":"On Work Start",
"func":"global.set('workStart', Date.now());\nglobal.set('lastHourTrig',0);\nreturn null;","outputs":1
},
{
"id":"hour_break",
"type":"switch",
"z":"flow",
"name":"Hourly Break",
"property":"topic",
"rules":[{"t":"eq","v":"hour_break"}]
},
{
"id":"notify_break",
"type":"mqtt out",
"z":"flow",
"name":"Show 1 hr Break",
"topic":"${mqttPrefix}/${customTopic}",
"qos":"0",
"retain":false,
"broker":"mqtt_broker",
"x":750,"y":300
},
{
"id":"start_break_timer",
"type":"function",
"z":"flow",
"name":"Prepare Break",
"func":"// pause work tick\nglobal.set('workState','break_wait');\nmsg.payload=JSON.stringify({icon:global.get('breakIcon'),text:'1 hr break'});\nreturn msg;","outputs":1
},
{
"id":"break_start",
"type":"switch",
"z":"flow",
"name":"On Break Start",
"property":"topic",
"rules":[{"t":"eq","v":"break_start"}]
},
{
"id":"break_timer",
"type":"delay",
"z":"flow",
"name":"10 min Break Timer",
"pauseType":"delay",
"timeout":"10","timeoutUnits":"minutes"
},
{
"id":"break_finish",
"type":"function",
"z":"flow",
"name":"Break Complete",
"func":"// after break\nmsg.topic=`${global.get('mqttPrefix')}/${global.get('customTopic')}`;\nmsg.payload=JSON.stringify({icon:global.get('breakIcon'),text:0});\nglobal.set('workState','work');\nreturn msg;","outputs":1
},
{
"id":"publish_break",
"type":"function",
"z":"flow",
"name":"Break Tick",
"func":"let state=global.get('workState');\nif(state!=='break') return null;\nlet start=global.get('breakStart')||Date.now();\nlet elapsed=(Date.now()-start)/1000;\nlet total=10*60;\nlet rem=Math.max(0,total-elapsed)|0;\nmsg.topic=`${global.get('mqttPrefix')}/${global.get('customTopic')}`;\nmsg.payload=JSON.stringify({icon:global.get('breakIcon'),text:rem});\nreturn msg;","outputs":1
},
{
"id":"mqtt_out",
"type":"mqtt out",
"z":"flow",
"name":"AWTRIX Display",
"topic":"",
"qos":"0",
"retain":false,
"broker":"mqtt_broker"
}
]
More flows for Node-RED or Miscellaneous
Something wrong with this flow? Report it.