# Day of Year Function To Control a Relay - Charging Device

**URL:** https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921
**Category:** General
**Created:** [8 October 2020 05:21 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921 "2020-10-08T05:21:38Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![TotoMu](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totomu/32/30065_2.png) [@TotoMu](https://discourse.nodered.org/u/TotoMu)
#### Post date: [8 October 2020 05:21 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/1 "2020-10-08T05:21:39Z")

</div>

Hello everybody. I am using NR to control chargers - to prevent overcharging. However, one charger - for toothbrush - cannot be controlled by (for example) a power-reading socket because the power consumed is too small to be recorded. (I have used this solution for washing machine alerts.) I have therefore resorted to a fixed 3 day charging cycle but this cannot be automated with Big Timer because the "BAN" options are only for "even" and "odd" days (ok for a 2 day charging cycle but not any other). So my first idea was to use a "get day of year" function so that the relay is only triggered when the day (counting from 1 January) is divisible by 3.

However, as I am not an IT specialist and have no programming background I have not been able to find Javascript code to do this - cide which can be cut and pasted into a NR function node. I also want to have code which allows me (in NR) to select whether I want 3, 4 or 5 etc. days as the period between charges. If the solution allows simplifies the process of choosing the actual charging period (in hours) that would be very handy. So my questions are:

1. Is a function node the best way to control a relay in this way?  
2, If so what would the code be - bearing in mind leap year complications.
2. If not what alternative NR solution could be used?

---

<div class="post-metadata">

### Author: ![Bobo](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bobo/32/8401_2.png) [@Bobo](https://discourse.nodered.org/u/Bobo)
#### Post date: [8 October 2020 06:44 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/2 "2020-10-08T06:44:09Z")

</div>

> [@TotoMu](#):
>
> If not what alternative NR solution could be used?

Have you looked at the other timing/scheduling nodes? There are quite a few.

---

<div class="post-metadata">

### Author: ![TotoMu](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totomu/32/30065_2.png) [@TotoMu](https://discourse.nodered.org/u/TotoMu)
#### Post date: [8 October 2020 07:23 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/3 "2020-10-08T07:23:00Z")

</div>

Tried simpletime last week to get day of ytear but did not work - "mymonth" and others were ok but not the one I wanted. So just checked again and realised that it had been updated last week. It now produces a string containing the number for current doy so now I have a good starting point.

I am new to NR so had assumed that nodes automatically updated if you had installed them. Bad assumption!

---

<div class="post-metadata">

### Author: ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)
#### Post date: [8 October 2020 09:18 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/4 "2020-10-08T09:18:52Z")

</div>

also worth checking out [https://flows.nodered.org/node/node-red-contrib-cron-plus](https://flows.nodered.org/node/node-red-contrib-cron-plus)  
as it is very flexible

---

<div class="post-metadata">

### Author: ![droberts](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/droberts/32/40295_2.png) [@droberts](https://discourse.nodered.org/u/droberts)
#### Post date: [8 October 2020 11:28 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/6 "2020-10-08T11:28:00Z")

</div>

I like using function nodes and built in nodes as it reduces your dependency on 3rd party nodes which may stop being supported.

This is a modification of a timer I built. It uses a flow variable `flow.chargeTime` (how long you want to charge the toothbrush for) and an inject node that will start the timer every 72 hours. The stop node can be removed for your purposes, it is used to stop the timer partway through and sends `'chargeDisable'`. The function sends a message `'chargeEnable'` when started, and `'chargeDisable'` when stopped.

The `'Start every 72 hours'` inject node could be modified to send a payload every day, and the function modified to increment a count when it receives a message. When this value reaches 3, it would start the timer and reset, otherwise it would do nothing. This would allow you to have better control of when the charger is turned on and off - at the moment the beginning of the 3 day cycle will be dependent on when you deploy the flow.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/4/34c4266953efcc7c1b96ed7a0e161df7e0eaa906.png)

```auto
[
    {
        "id": "72140aba.c30d64",
        "type": "inject",
        "z": "59fcda25.edd454",
        "name": "Start every 72 hours",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "00 22 * * *",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 520,
        "y": 120,
        "wires": [
            [
                "6e6703ab.87e13c"
            ]
        ]
    },
    {
        "id": "30b0c638.4abdfa",
        "type": "inject",
        "z": "59fcda25.edd454",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "stop",
        "payloadType": "str",
        "x": 470,
        "y": 180,
        "wires": [
            [
                "6e6703ab.87e13c"
            ]
        ]
    },
    {
        "id": "ff53b61c.471938",
        "type": "inject",
        "z": "59fcda25.edd454",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "5",
        "payloadType": "num",
        "x": 470,
        "y": 60,
        "wires": [
            [
                "4ec48c94.eaf824"
            ]
        ]
    },
    {
        "id": "4ec48c94.eaf824",
        "type": "change",
        "z": "59fcda25.edd454",
        "name": "chargeTime (s)",
        "rules": [
            {
                "t": "set",
                "p": "chargeTime",
                "pt": "flow",
                "to": "payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 660,
        "y": 60,
        "wires": [
            []
        ]
    },
    {
        "id": "6e6703ab.87e13c",
        "type": "function",
        "z": "59fcda25.edd454",
        "name": "",
        "func": "if(msg.payload !== true && msg.payload !== 'stop') {\n return;\n}\n\nvar timerEnable;\n\nfunction timer() {\n context.set(\"timerValue\", (context.get(\"timerValue\") - 1));\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Charge Time Remaining: \" +context.get(\"timerValue\")}); \n if (context.get(\"timerValue\") === 0) {\n msg.payload = \"chargeDisable\"\n node.status({fill:\"green\",shape:\"dot\",text:\"Charging finished\"}); \n node.send(msg);\n clearInterval(context.timer);\n context.set(\"timerRunning\", false)\n return;\n }\n}\n\nif (msg.payload === \"stop\") {\n timerEnable = false;\n}\nelse {\n timerEnable = true;\n}\n\nif (context.get(\"timerRunning\") === false && timerEnable === true) { //Start\n context.set(\"timerValue\", flow.get(\"timeout\"));\n node.status({fill:\"blue\",shape:\"dot\",text:\"Charge Time Remaining: \" + context.get(\"timerValue\")});\n context.timer = setInterval(timer,1000);\n context.set(\"timerRunning\", true);\n \n msg.payload = 'chargeEnable';\n node.send(msg);\n}\n\nelse if (context.get(\"timerRunning\") === true && timerEnable === true) { //Reset\n context.set(\"timerValue\", flow.get(\"timeout\"));\n //msg.payload = 'timer reset';\n node.status({fill:\"blue\",shape:\"ring\",text:\"Charge Time Remaining: \" + context.get(\"timerValue\")});\n context.set(\"timerRunning\", true);\n}\n\nelse if (timerEnable === false) { //Stop\n //msg.payload = 'timer stop';\n clearInterval(context.timer);\n node.status({fill:\"red\",shape:\"ring\",text:\"Stopped\"});\n context.set(\"timerRunning\", false);\n msg.payload = 'chargeDisable';\n node.send(msg);\n}\n\nreturn;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "context.set(\"timerRunning\", false);",
        "finalize": "",
        "x": 640,
        "y": 180,
        "wires": [
            [
                "3e2c38c1.05ad18"
            ]
        ]
    },
    {
        "id": "3e2c38c1.05ad18",
        "type": "debug",
        "z": "59fcda25.edd454",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 810,
        "y": 180,
        "wires": []
    }
]

```

---

<div class="post-metadata">

### Author: ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)
#### Post date: [8 October 2020 11:58 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/7 "2020-10-08T11:58:00Z")

</div>

You could put this code into a function node, and it will send `true` if the doy, when divided by 3 returns a whole number, otherwise does nothing;

```auto
// When divided by 3, is the result an integer?
if (Number.isInteger((msg.mydoy)/3)){
// If it is, then send the payload as true
node.send({payload:true});
// ...otherwise - do nothing
} else {return;}

```

```auto
[{"id":"22d2c7a5.e93958","type":"inject","z":"c53060.842a0fa","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"str","x":140,"y":1290,"wires":[["30069df9.a01282"]]},{"id":"82432f72.e126f","type":"debug","z":"c53060.842a0fa","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":640,"y":1290,"wires":[]},{"id":"5a92ee25.6c136","type":"function","z":"c53060.842a0fa","name":"","func":"// When divided by 3, is the result an integer?\nif (Number.isInteger((msg.mydoy)/3)){\n// If it is, then send the payload as true\nnode.send({payload:true});\n// ...otherwise - do nothing\n} else {return;}","outputs":1,"noerr":0,"initialize":"","finalize":"","x":470,"y":1290,"wires":[["82432f72.e126f"]]},{"id":"30069df9.a01282","type":"simpletime","z":"c53060.842a0fa","name":"","mydate":true,"myymd":true,"myyear":true,"mymonth":true,"mymonthn":true,"mydom":true,"mydoy":true,"myday":true,"myhourpm":true,"myhour":true,"mytime":true,"mytimes":true,"myminute":true,"myminutes":true,"mysecond":true,"mymillis":true,"myepoch":true,"myrawdate":true,"mypm":true,"x":300,"y":1290,"wires":[["5a92ee25.6c136"]]}]

```

 ![doy](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/0/50aa929967a463e6620f51d159660d70835dc137.jpeg)

---

<div class="post-metadata">

### Author: ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)
#### Post date: [8 October 2020 12:12 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/8 "2020-10-08T12:12:36Z")

</div>

Or  
This in a function will return true every 3 days from 1st of January.

```auto
msg.days3 = Math.round((new Date().setHours(23) - new Date(new Date().getFullYear(), 0, 1, 0, 0, 0))/1000/60/60/24) % 3 === 0 ? true : false;
return msg;

```

---

<div class="post-metadata">

### Author: ![TotoMu](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totomu/32/30065_2.png) [@TotoMu](https://discourse.nodered.org/u/TotoMu)
#### Post date: [9 October 2020 04:16 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/9 "2020-10-09T04:16:58Z")

</div>

Thanks for the replies everyone. I shall play around with the various suggestions - part of this process is, of course, just learning some useful approaches and having some more samples of coding that can be cut and pasted into other flows where this is going to be of help. The elegance of coding a function node is, of course, the way to go - but using existing nodes and piecing together a flow that is more aligned to the individual's IT skills (or lack thereor) has a certain educative value for the individual concerned.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [8 December 2020 04:17 UTC](https://discourse.nodered.org/t/day-of-year-function-to-control-a-relay-charging-device/33921/10 "2020-12-08T04:17:09Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
