UPDATE: V1.2.1 node-red-contrib-cron-plus scheduler (incl solar events and Timezone support)

I was beginning to think that the recent discussion was about a totally different node....

3 Likes

At the risk of generating one "ask" too many, I've been looking at using solar events in cron-plus to replace node-red-node-suncalc, bigtimer and schedex, and I have run into three features I would miss.

  1. Enabling or disabling events on specific days of the week.
  2. An option to randomize offsets between zero and the value entered.
  3. Setting the location from environmental or global variables.

The first two might not be hard to implement or over-complicate the ui -- not sure about the last. What do you think?

Adding some randomisation would be a nice addition, for example to control lighting when away from home, and would make yet another node in my palette redundant...

Nah, all good. I guess I was reading into the meaning of 'solar' events? I fully understand the constant conflict between what to include and what to exclude in any given node scope... Having written several custom nodes I use in my own flows, I even debate with myself what and if I add or not during development.

1 Like

This is a far bigger task that the words it takes to describe it unfortunately - the only way i can see this being viable is at NODE level (i.e. affecting all schedules in the cron instance / NOT per item in the cron list).

Is that a suitable solution?

These 2 are easy quick wins

My proposal...
  1. change the offset to a typedInput permitting flow, global, env and jsaonata - from this you can set pretty much anything like (e.g. you can use a value stored in flow or global or a JSONata expression of $round($random()*10, 0) + 10 /* random number 10 ~ 20 */
  2. permit "lat lon" coordinates (as it is now) - OR - any valid JSONata expression (e.g. $env(MY_COORDS))

Are you also exposing 'offset' for cron schedules?

Wow, a lot more flexibility than I expected! A simple checkbox to randomize would do, but why not?

Also great, as long as you still can use your nice world map.

As for days of the week, I had just assumed that the solar events scheduler just generated cron items, which naturally know about days of the week. That's what I get for not looking at the code. Applying the same mask to all the schedules sort of defeats the idea of (for example) having one schedule for weekdays and another for weekends.

well, i did first think i would make that a typedInput with flow, global, JSONata and env options however I then have the issue of adding a button for the map popup. So, although I will permit JSONata expressions in the text box, you wont get the editor (at least in the 1st release)


No, the solar events are unique (change everyday) and are calculated datetime stamps. the issue isnt so much the logic but the efforts involved in presenting the options, per list item.



Assuming I added a date mask, you could of course have multiple instances of CRON node (one that fires on only weekends and another that fires on weekdays)

:thinking: I am going with "no" for now (sorry). I remember the pain of adding that seemingly simple option for solar events. Difficulties arise when you setup a CRON (or solar) item that occurs in the past BUT the offset causes it to execute AFTER current time. If I dont scan backwards through time, calculating all possibilities then scan forwards to see which events would occur AFTER now I miss firing events a user would expect to occur. This happens in many of the other nodes that do solar events. This also covers a few scenarios the other nodes dont (for example when the coordinates are every high north or south and you chose a date without a dusk or dawn - this library does because of the scanning) I'm rambling sorry.

No worries, you have to draw the line somewhere.:+1:
We can always add a 'delay' node in the flow with a random delay setting.

Add what happens when offsets cross midnight or there is a change to or away from summer time (Daylight Saving Time), and you can have a real mess. You have suffered enough.

Why not use (or pop up) a list of checkboxes like the one in schedex?

And yet another that fires every day, or duplicate schedules in the other two instances... I don't think there would be much benefit.

@Paul-Reed @drmibell & @anyone_else_too - I spoke too soon & I now have a dilemma

Suppose I do release a version with support for JSONata in the location and offset fields. That will permit you to do things like $random() for the offset or get location from $env() BUT if the user enters $flowContext("location") the value in the flow variable will likely not exist at startup AND I have no way of knowing the value has changed so cannot update the schedule.

My options are...

  1. prevent expressions including flowContext and globalContext
  2. provide a means for schedules to be re-calculated (by means of a command input)

Option 1 is easy (for me and the user) and avoids the confusion
Option 2 is much harder (for both myself and the user) as the user would need to know to send the recalculate command after flow/global value changes. There are likely a whole bunch of edge cases too.


for evaluation - this is what i have so far...

image

It really isn't your problem to deal with users entering (or not) incorrect data. That is an aspect of any general purpose compute platform. Your node provides the capability, it is the flow authors responsibility to make a flow that works and does something sensible. :smiley:

I would say that allowing JSONata and then excluding a feature is going to be more confusing and will likely be annoying for people. After all, if someone uses a variable that is retained, it WILL work or if the cron+ flow occurs after the variable as been initialised, it will work (I assume). This is normal since any flow using a variable has to take account of when it is initialised.

As for your second option, well that actually sounds like a useful feature if you are allowing variable inputs. But I wouldn't say that it is essential as long as it is clear that the node does not recalculate if the variable changes.

1 Like

Why do you need jsonata in the fields ? Do you support sending in the location and offset ? If so then it can be calculated and sent in. It not the job of every node to do everything.

1 Like

I dont need to Dave & ultimately, might not.

It was a quick win for ...

  • allowing the location field be supplied with ENV var
  • offset to be randomised (for reasons I personally dont understand).

At first it seemed adding JSONata support to the fields was a very simple and quick change & as a fantastic bonus, provided all the extra capability to boot. Arrrrggggghhhhh - so many edge cases.


I am mulling it over. Will give it a day or two.

Yes, I see where our greed has put you in a bit of a corner. I think the easiest way out, without asking for rescue by the user, is to require that all the information needed to generate all the schedules is available when the edit dialog closes. One way to go would be:

  1. location and offset cannot use flow variables.
  2. location and offset may use an environmental or global variable, but only if it has been defined in .bashrc or settings.js, so that it already exists.
  3. Random offsets are created by selecting a checkbox like the one in schedex ("Use random ... time within offset period"). Then, whenever a new event is created for that schedule, offset can be replaced by offset * Math.random().

I agree with @dceejay that JSONata is probably not really needed here. The reason for random offsets is to give lighting schedules in home automation systems some day-to-day variation in timing, so that your home might seem occupied when you are away. Both bigtimer and schedex do this, and a lot of folks find it useful.

I like the dashboard control a lot. Makes life easier. To make it (at least for me) even more easy, I added an edit button to the table. This has two advantages:

  1. You can edit the payload or the expression and then add it, the previous cron entry will be overwritten.
  2. You can change the name and add it, this way a duplicate entry will be created (as good as a copy feature)

This is the screenshot (grouped nodes have been added)

And this is the flow

[{"id":"952ffcf0.f84ac","type":"ui_text","z":"a93cea96.ad9938","group":"c3f194d9.93ecd8","order":1,"width":"16","height":"2","name":"CRON Description","label":"Expression Description (updates as you type)...","format":"{{msg.payload.result.description}}","layout":"col-center","x":890,"y":220,"wires":[]},{"id":"d657bcf5.0f961","type":"cronplus","z":"a93cea96.ad9938","name":"","outputField":"payload","timeZone":"","persistDynamic":true,"commandResponseMsgOutput":"output1","outputs":1,"options":[],"x":600,"y":220,"wires":[["952ffcf0.f84ac"]]},{"id":"8a3b6d25.2cc45","type":"function","z":"a93cea96.ad9938","name":"describe cmd","func":"msg.payload = {\n    \"command\": \"describe\",\n    \"expression\": msg.payload\n}\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":220,"wires":[["d657bcf5.0f961"]]},{"id":"7f182a47.6a92d4","type":"change","z":"a93cea96.ad9938","name":"","rules":[{"t":"set","p":"ui_add_schedule_name","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":100,"wires":[[]]},{"id":"178c29c6.469c26","type":"change","z":"a93cea96.ad9938","name":"","rules":[{"t":"set","p":"ui_add_schedule_payload","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":140,"wires":[[]]},{"id":"4e82804c.deec8","type":"change","z":"a93cea96.ad9938","name":"","rules":[{"t":"set","p":"ui_add_schedule_expression","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":180,"wires":[[]]},{"id":"b5b431d9.bfb55","type":"change","z":"a93cea96.ad9938","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{}","tot":"json"},{"t":"set","p":"payload.payload","pt":"msg","to":"ui_add_schedule_payload","tot":"flow"},{"t":"set","p":"payload.name","pt":"msg","to":"ui_add_schedule_name","tot":"flow"},{"t":"set","p":"payload.expression","pt":"msg","to":"ui_add_schedule_expression","tot":"flow"},{"t":"set","p":"payload.command","pt":"msg","to":"add","tot":"str"},{"t":"set","p":"payload.type","pt":"msg","to":"str","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":300,"wires":[["3f284188.fdf30e","f78bacd7.fd897"]]},{"id":"3f284188.fdf30e","type":"cronplus","z":"a93cea96.ad9938","name":"","outputField":"payload","timeZone":"","persistDynamic":true,"commandResponseMsgOutput":"output1","outputs":1,"options":[],"x":760,"y":300,"wires":[["abf40655.039a88"]]},{"id":"be8bc068.715f3","type":"ui_toast","z":"a93cea96.ad9938","position":"top right","displayTime":"3","highlight":"","sendall":true,"outputs":0,"ok":"OK","cancel":"","topic":"","name":"","x":710,"y":380,"wires":[]},{"id":"abf40655.039a88","type":"switch","z":"a93cea96.ad9938","name":"1=Cron Event   2=List Results ","property":"cronplus.triggerTimestamp","propertyType":"msg","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":440,"y":400,"wires":[["be8bc068.715f3"],["7ae8d780.88fc08"]]},{"id":"eba9438.7bf69c","type":"catch","z":"a93cea96.ad9938","name":"","scope":null,"uncaught":false,"x":220,"y":520,"wires":[["92cbfc6f.77ad5","d860d2d.5afc53"]]},{"id":"92cbfc6f.77ad5","type":"ui_toast","z":"a93cea96.ad9938","position":"top right","displayTime":"3","highlight":"red","outputs":0,"ok":"OK","cancel":"","topic":"Error...","name":"","x":430,"y":520,"wires":[]},{"id":"f78bacd7.fd897","type":"ui_button","z":"a93cea96.ad9938","name":"Refresh","group":"c3f194d9.93ecd8","order":6,"width":"1","height":"1","passthru":true,"label":"","tooltip":"Get status of jobs","color":"","bgcolor":"","icon":"fa-refresh","payload":"{\"command\":\"list-all\"}","payloadType":"json","topic":"","x":600,"y":320,"wires":[["3f284188.fdf30e"]]},{"id":"2e128d0.3fb4a74","type":"ui_text_input","z":"a93cea96.ad9938","name":"","label":"Expression","tooltip":"CRON expression or date/csv list of dates","group":"c3f194d9.93ecd8","order":3,"width":"4","height":"1","passthru":true,"mode":"text","delay":"100","topic":"","x":230,"y":180,"wires":[["8a3b6d25.2cc45","4e82804c.deec8"]]},{"id":"bda83091.c7f44","type":"ui_text_input","z":"a93cea96.ad9938","name":"","label":"Name","tooltip":"Schedule Name","group":"c3f194d9.93ecd8","order":2,"width":"4","height":"1","passthru":true,"mode":"text","delay":"100","topic":"","topicType":"str","x":210,"y":100,"wires":[["7f182a47.6a92d4"]]},{"id":"96463052.88a8d","type":"ui_button","z":"a93cea96.ad9938","name":"","group":"c3f194d9.93ecd8","order":5,"width":"3","height":"1","passthru":false,"label":"Add","tooltip":"Add or update named schedule","color":"","bgcolor":"","icon":"send","payload":"","payloadType":"str","topic":"","x":210,"y":300,"wires":[["b5b431d9.bfb55"]]},{"id":"5bb3aee1.5fc43","type":"ui_text_input","z":"a93cea96.ad9938","name":"","label":"Payload","tooltip":"Payload to send when schedule fires","group":"c3f194d9.93ecd8","order":4,"width":"4","height":"1","passthru":true,"mode":"text","delay":"100","topic":"","x":220,"y":140,"wires":[["178c29c6.469c26"]]},{"id":"e15ad659.7d0128","type":"ui_template","z":"a93cea96.ad9938","group":"c3f194d9.93ecd8","name":"","order":7,"width":"16","height":"5","format":"<style type=\"text/css\">\n.t1  {border-collapse:collapse;border-spacing:0;border-color:#ccc;}\n.t1 td{font-family:Arial, sans-serif;font-size:14px;padding:8px 3px;border-style:solid;border-width:0px;overflow:hidden;word-break:normal;border-top-width:1px;border-bottom-width:1px;border-color:#ccc;color:#333;background-color:#fff;}\n.t1 th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;}\n.t1 .t1-36r9{background-color:#000000;color:#ffffff;text-align:left;vertical-align:top}\n.t1 .t1-x2zo{background-color:#c0c0c0;font-size:small;text-align:left;vertical-align:top}\n.t1 .t1-o73e{background-color:#c0c0c0;font-size:small;text-align:center;vertical-align:top}\n.t1 .t1-5qt9{font-size:small;text-align:left;vertical-align:top}\n.t1 .t1-5qta{font-size:small;text-align:center;vertical-align:middle}\n</style>\n<table class=\"t1\">\n  <tr>\n    <th class=\"t1-36r9\" colspan=\"10\">CRON Schedules</th>\n  </tr>\n  <tr>\n    <td class=\"t1-x2zo\">Name</td>\n    <td class=\"t1-x2zo\">Expression</td>\n    <td class=\"t1-x2zo\">Payload</td>\n    <td class=\"t1-x2zo\">Description</td>\n    <td class=\"t1-x2zo\">Next run</td>\n    <td class=\"t1-x2zo\">State</td>\n    <td class=\"t1-o73e\">Delete</td>\n    <td class=\"t1-o73e\">Pause</td>\n    <td class=\"t1-o73e\">Resume</td>\n    <td class=\"t1-o73e\">Edit</td>\n  </tr>\n  <tr  ng-repeat=\"item in msg.payload\">\n    <td class=\"t1-5qt9\">{{item.config.name}}</td>\n    <td class=\"t1-5qt9\" style=\"white-space: nowrap\" nowrap>{{item.config.expression}}</td>\n    <td class=\"t1-5qt9\">{{item.config.payload}}</td>\n    <td class=\"t1-5qt9\">{{item.status.description}}</td>\n    <td class=\"t1-5qt9\">{{item.status.nextDescription}}</td>\n    <td class=\"t1-5qta\"><i class=\"fa fa-{{item.status.isRunning ? 'play' : 'pause'}}\"> </i></td>\n\n   <td class=\"t1-5qta\">\n       <md-button class=\"md-raised\"\n        ng-click=\"send([[{payload:{command:'remove', name: item.config.name}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-trash\"> </i></md-button>\n   </td>\n   <td class=\"t1-5qta\">\n       <md-button class=\"button\" \n       ng-click=\"send([[{payload:{command:'pause', name: item.config.name}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-pause\"> </i></md-button>\n   </td>\n   <td class=\"t1-5qta\">\n       <md-button class=\"button\" \n       ng-click=\"send([[{payload:{command:'start', name: item.config.name}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-play\"> </i></md-button>\n   </td>\n   <td class=\"t1-5qta\">\n       <md-button class=\"button\" \n       ng-click=\"send([[{payload:{command:'edit', name: item.config.name, expression: item.config.expression, payload: item.config.payload}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-pencil\"> </i></md-button>\n   </td>\n\n  </tr>\n\n </tbody>\n</table>\n\n<!--<table id=\"table\" class=\"table table-striped table-responsive-md btn-table\" >-->\n<!--     <tr>-->\n<!--        <th>Name</th> -->\n<!--        <th>Expression</th> -->\n<!--        <th>Payload</th> -->\n<!--        <th>Description</th>-->\n<!--        <th>Next run</th>-->\n<!--        <th>State</th>-->\n<!--        <th>Delete</th>-->\n<!--        <th>Pause</th>-->\n<!--        <th>Resume</th>-->\n<!-- </tr>-->\n<!-- <tbody>-->\n<!-- <tr ng-repeat=\"item in msg.payload\">-->\n<!--   <td >{{item.config.name}}</td>-->\n<!--   <td style=\"white-space: nowrap\" nowrap>{{item.config.expression}}</td>-->\n<!--   <td >{{item.config.payload}}</td>-->\n<!--   <td >{{item.status.description}}</td>-->\n<!--   <td >{{item.status.nextDescription}}</td>-->\n<!--   <td >{{item.status.isRunning ? 'Running' : 'Paused'}}</td>-->\n<!--   <td>-->\n<!--       <md-button class=\"md-raised\"-->\n<!--        ng-click=\"send([[{payload:{command:'remove', name: item.config.name}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-trash\"> </i></md-button>-->\n<!--   </td>-->\n<!--   <td>-->\n<!--       <md-button class=\"button\" -->\n<!--       ng-click=\"send([[{payload:{command:'pause', name: item.config.name}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-pause\"> </i></md-button>-->\n<!--   </td>-->\n<!--   <td>-->\n<!--       <md-button class=\"button\" -->\n<!--       ng-click=\"send([[{payload:{command:'start', name: item.config.name}}, {payload:{command:'list-all'}}]]);\"> <i class=\"fa fa-play\"> </i></md-button>-->\n<!--   </td>-->\n<!-- </tr>-->\n<!-- </tbody>-->\n<!--</table>-->\n\n","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"local","x":860,"y":420,"wires":[["2c08059f.e77d7a"]]},{"id":"7ae8d780.88fc08","type":"function","z":"a93cea96.ad9938","name":"Make table data","func":"if(!msg.payload || !msg.payload.result || !msg.payload.result.length){\n    msg.payload = [];\n    return msg;\n}\n\nmsg.payload = msg.payload.result;\nreturn msg;","outputs":1,"noerr":0,"x":700,"y":420,"wires":[["e15ad659.7d0128"]]},{"id":"d860d2d.5afc53","type":"debug","z":"a93cea96.ad9938","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":390,"y":560,"wires":[]},{"id":"e73772df.72258","type":"ui_template","z":"a93cea96.ad9938","group":"c3f194d9.93ecd8","name":"CRON Info","order":8,"width":"16","height":"12","format":"<div>\n<pre>CRON Format...\n\n    s  m  h  md m  wd y\n    |  |  |  |  |  |  |\n    *  *  *  *  *  *  *    Field              Allowed values    Special symbols\n    |  |  |  |  |  |  |    -----------------  ---------------   ---------------\n    `--|--|--|--|--|--|->  Second (optional)  0-59              * / , -\n       `--|--|--|--|--|->  Minute             0-59              * / , -\n          `--|--|--|--|->  Hour               0-23              * / , -\n             `--|--|--|->  Day of Month       1-31              * / , - L W\n                `--|--|->  Month              1-12 or JAN-DEC   * / , -\n                   `--|->  Day of Week        0-7 or SUN-SAT    * / , - L #\n                      `->  Year (optional)    1970-2099         * / , -\n                \n</pre>    \n</div>\n\n<style type=\"text/css\">\n.t2  {border-collapse:collapse;border-spacing:0;border-color:#ccc;}\n.t2 td{font-family:Arial, sans-serif;font-size:14px;padding:2px 2px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#fff;}\n.t2 th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;}\n.t2 .t2-dg6o{background-color:#000000;color:#ffffff;text-align:left;vertical-align:top}\n.t2 .t2-6e8n{font-weight:bold;background-color:#c0c0c0;border-color:inherit;text-align:left;vertical-align:top}\n.t2 .t2-0pky{border-color:inherit;text-align:left;vertical-align:top}\n</style>\n<table class=\"t2\">\n  <tr>\n    <th class=\"t2-dg6o\" colspan=\"2\">Example CRON Expressions</th>\n  </tr>\n  <tr>\n    <td class=\"t2-6e8n\">Expression</td>\n    <td class=\"t2-6e8n\">Description</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">* * * * * *</td>\n    <td class=\"t2-0pky\">Every Second</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 * * * * *</td>\n    <td class=\"t2-0pky\">Every minute</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 */10 * * * *</td>\n    <td class=\"t2-0pky\">Every 10 minutes</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 */20 1 * * *</td>\n    <td class=\"t2-0pky\">Every 20 minutes, between 01:00 AM and 01:59 AM</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 15,30,45 * * * *</td>\n    <td class=\"t2-0pky\">At 15, 30, and 45 minutes past the hour</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 0 12 * * *</td>\n    <td class=\"t2-0pky\">Every day at noon - 12pm</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 0 2 29 FEB * 2020-2040</td>\n    <td class=\"t2-0pky\">At 02:00 AM, on day 29 of the month, only in February, every 4 years, 2020 through 2040</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 0 7 * *</td>\n    <td class=\"t2-0pky\">MON#1 * At 07:00 AM, on the first Monday of the month</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 0 12 * JAN,FEB,MAR,APR *</td>\n    <td class=\"t2-0pky\">Every day at noon in January, February, March and April</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">* * 1W * *</td>\n    <td class=\"t2-0pky\">Every minute, on the first weekday of the month</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">* * * * Tue#3</td>\n    <td class=\"t2-0pky\">Every minute, on the third Tuesday of the month</td>\n  </tr>\n  <tr>\n    <td class=\"t2-0pky\">0 12 * * MONL</td>\n    <td class=\"t2-0pky\">At 12:00 PM, on the last Monday of the month</td>\n  </tr>\n</table>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":370,"y":640,"wires":[[]]},{"id":"e48ee70d.63d348","type":"link in","z":"a93cea96.ad9938","name":"","links":["851d95e5.61cc58","dde0b2cf.76d48"],"x":555,"y":280,"wires":[["3f284188.fdf30e"]]},{"id":"8ec7f0a1.59cd1","type":"group","z":"a93cea96.ad9938","name":"","style":{"fill":"#c8e7a7","label":true},"nodes":["851d95e5.61cc58","2c08059f.e77d7a","44ec11eb.82a12","94a56ac1.8ec318","8574e072.79c51","d5d60b9e.0048d8","af3482b3.56e92","95740169.9383a"],"x":594,"y":459,"w":322,"h":242},{"id":"851d95e5.61cc58","type":"link out","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"Delete / Pause / Resume","links":["e48ee70d.63d348"],"x":875,"y":500,"wires":[]},{"id":"2c08059f.e77d7a","type":"switch","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"Switch for Editing","property":"payload.command","propertyType":"msg","rules":[{"t":"else"},{"t":"eq","v":"edit","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":710,"y":520,"wires":[["851d95e5.61cc58"],["94a56ac1.8ec318","8574e072.79c51","d5d60b9e.0048d8"]]},{"id":"44ec11eb.82a12","type":"link out","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"","links":["b7135036.1ce2b"],"x":835,"y":580,"wires":[]},{"id":"94a56ac1.8ec318","type":"change","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"Extract Name","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.name","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":580,"wires":[["44ec11eb.82a12"]]},{"id":"8574e072.79c51","type":"change","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"Extract Expression","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.expression","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":710,"y":660,"wires":[["95740169.9383a"]]},{"id":"d5d60b9e.0048d8","type":"change","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"Extract Payload","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":620,"wires":[["af3482b3.56e92"]]},{"id":"af3482b3.56e92","type":"link out","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"","links":["78631fcf.a31fd"],"x":835,"y":620,"wires":[]},{"id":"95740169.9383a","type":"link out","z":"a93cea96.ad9938","g":"8ec7f0a1.59cd1","name":"","links":["8ed4e8d6.a740d8"],"x":835,"y":660,"wires":[]},{"id":"ce0bb01.7c3ec5","type":"group","z":"a93cea96.ad9938","name":"","style":{"fill":"#c8e7a7","label":true},"nodes":["b7135036.1ce2b","78631fcf.a31fd","8ed4e8d6.a740d8"],"x":74,"y":59,"w":82,"h":162},{"id":"b7135036.1ce2b","type":"link in","z":"a93cea96.ad9938","g":"ce0bb01.7c3ec5","name":"","links":["44ec11eb.82a12"],"x":115,"y":100,"wires":[["bda83091.c7f44"]]},{"id":"78631fcf.a31fd","type":"link in","z":"a93cea96.ad9938","g":"ce0bb01.7c3ec5","name":"","links":["af3482b3.56e92"],"x":115,"y":140,"wires":[["5bb3aee1.5fc43"]]},{"id":"8ed4e8d6.a740d8","type":"link in","z":"a93cea96.ad9938","g":"ce0bb01.7c3ec5","name":"","links":["95740169.9383a"],"x":115,"y":180,"wires":[["2e128d0.3fb4a74"]]},{"id":"c3f194d9.93ecd8","type":"ui_group","name":"Default","tab":"327ea06c.0a258","order":1,"disp":false,"width":"16","collapse":false},{"id":"327ea06c.0a258","type":"ui_tab","name":"CRON","icon":"dashboard","order":2,"disabled":false,"hidden":false}]

Maybe it is useful for someone...

1 Like