Flow Details
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.
[
{
"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"
}
]
-- Flow first published on May 25, 2025.