Socket
Socket
Sign inDemoInstall

node-red-contrib-sun-position

Package Overview
Dependencies
Maintainers
1
Versions
136
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-contrib-sun-position - npm Package Compare versions

Comparing version 1.2.4 to 2.0.3

.github/workflows/codeql-analysis.yml

228

CHANGELOG.md
# node-red-contrib-sun-position
# Installation
## Installation
Install of a specific Version in Node-Red:
- change to the installation directory of Node-Red
- enter the command `npm install node-red-contrib-sun-position@1.2.3`
- enter the command `npm install node-red-contrib-sun-position@2.0.0`

@@ -14,8 +14,124 @@ Install of a specific Version in Redmatic (on a Homematic):

- `cd /usr/local/addons/redmatic/var`
- `npm install --save --no-package-lock --global-style --save-prefix="~" --production node-red-contrib-sun-position@1.2.3`
- `npm install --save --no-package-lock --global-style --save-prefix="~" --production node-red-contrib-sun-position@2.0.0`
This can be also used to go back to an older Version.
#### 1.2.4: maintenance + critical bugfix
### 2.0.3: small fix + enhancement
- general
- allow to set context store in configuration node #351
- fixed randomNumber cached again #302 + #353
- selectable range for random number #352
- blind-control + clock-time
- allow to set context store, if not defined using settings from configuration node, otherwise default #351
- readjusted rules UI, edit buttons only visible on mouse over
- allows to enable/disable rules #349
### 2.0.1: small fix + enhancement
- general
- implemented partly #338 + #308
- fixed randomNumber cached #302
- implemented randomNumber cached weekly
- blind-control
- allow to setup a rule which will only overwrite slat #345 or topic
- enhanced overwrite possibilities for slat. Additional `msg.blindSlat` as message property allowed or if the topic contains __slatOverwrite __ the payload as slat position will be used - partly #346
- for slat value make a deep clone as this could be any object and an object comparison
- clock-time
- implement `resetOnSameAsLastValue` and `ignoreSameValue` #341
- for payload value make a deep clone as this could be any object and perform an an object comparison
- time-comp
- added next occurrence #339
### 2.0.0: enhancement
⚠ Warning: This Version could break existing flows. Please check your configuration!
🛑 Nodes (especially blind, time-control nodes) that were created or saved with this version do not work in older versions of the package. This affects the export / import of flows and when switching to an older version. It is therefore **essential** to create a **backup** before upgrading to this version!
- general
- added only even and only odd weeks
- added css property to moonPhases object an using css from [here](https://github.com/Paul-Reed/weather-icons-lite/blob/master/css_mappings.md)
- for offset values of a random number a cached value will be used which will be only generated once per day. #302
- selection of random number is available in more places
- allow negative altitudePercent #259
- time-inject
- fixed error if only flow/global context is set #252
- fixed missing interval multiplier
- added possibility for inject special values from config menu like default inject node
- reworked simple interval (only simple interval)
- added start timestamp
- added selection for interval of days and weeks #313
- added possibility to setup interval greater than 24.9 days (2147483647 - 32bit integer limit of NodeJs)
- within-time-switch
- configurable `msg.payload` of the outgoing message #292
- moon-position
- moon times will now be has additional property `timesNext` with the values for the times of the next day #307
- added next moon phase date time #296
- blind-control + clock-time
- added possibility to copy rules to clipboard and paste rules from clipboard
- nodes have now always 2 outputs - may breaks existing flows!
- First output is configurable.
- redesigned rule conditions, now unlimited conditions could be defined
- additional nodeID which will be also in the output (if set will override nodeId)
- added as rule condition operator - usable in subFlows
- No more messages are sent at the first output if the rule has changed but the payload (level/slat) has remained the same.
- A message will be sent if the topic has changed.
- overwrite will be written to node context and restored on recreation - allows overwrite be stable on deploy #300
- No longer configuration of number of outputs. Node will always have two outputs
- The message send to the first output will no longer be send on rule change, only on level/payload changes.
- The message on the first output is fully configurable.
- A property can be setup to be a string with placeholders. (The same placeholders can be used for the topic.):
- blind-control
- `%name%` - name of the node
- `%id%` - ID of the node
- `%level%` - level
- `%levelInverse%` - level, but inverse
- `%slat%` slat position
- `%code%` - node.reason.code,
- `%state%` - node.reason.state,
- `%description%` - node.reason.description,
- `%rule%` - ID of the active rule (if rule was active)
- `%mode%` - current mode
- `%topic%` - `msg.topic` of the incoming (trigger) message (if available)
- `%payload%` - `msg.payload` of the incoming (trigger) message (if available)
- clock-timer
- `%name%` - name of the node
- `%id%` - ID of the node
- `%code%` - node.reason.code
- `%state%` - node.reason.state
- `%description%` - node.reason.description
- `%rule%` - ID of the active rule (if rule was active)
- `%topic%` - `msg.topic` of the incoming (trigger) message (if available)
- `%payload%` - `msg.payload` of the incoming (trigger) message (if available)
- The name of the node (or the id if no name is given in the config) can be configured in the output message - #238
- this information will be send as `msg.payload.name` to the second output
- ID of the node can be send
- this information will be send as `msg.payload.id` to the second output if two outputs are configured
- blind-control only changes
- redesigned oversteer, now unlimited oversteer can defined
- oversteer can be defined only valid for special mode
- removed minimum altitude settings
- for functionality the downward compatibility is given by automatic adoption of the setting as new first oversteer, which has the same effect.
- no longer specific output of the reason (instead of "below the minimum elevation angle" will output "oversteer 1")
- window settings as typedInput, which allow to use from flow, global context or environment - node can better used in a subFlow
- per message set mode will be written to node context and to thus this will be stable on deploy
- needs to delete values of context on change
- current mode will no longer part of the node label/name, it will be displayed in the node state #321
- added option to setup a rule which prevents the node to send anything out #280
- *time compare and change* + *time span*
- fixed parsing of ECMA-262 (simplified ISO8601) Format times (e.g. 2021-05-17T08:45:00.000Z) #250
- added parsing of full ISO8601 Format (e.g 2019-01-18T00:00:00.000Z, 2019-01-17T17:00:00.000-07:00, 2019-01-18T07:00:00.000+07:00)
### 1.2.4: maintenance + critical bugfix
- time-span

@@ -33,8 +149,10 @@ - fixed bug that second operand displayed wrong in config!

- `msg.blindCtrl.id` / `msg.timeCtrl.id` which is the id of the node
- this information will be send as `msg.payload.id` to the second output if two outputs are configured
- this information will be send as `msg.payload.id` to the second output if two outputs are configured
- blind-control only
- renamed `msg.resetOnSameValue` to `msg.resetOnSameAsLastValue` parameter to reset existing overwrite if `msg.payload` equals to position (`node.previousData.level`) (#223)
- added slat position #250
- in opposite to the mode `maximize sunlight (⛄ Winter)` added the `minimize sunlight (🕶️)` mode #284
#### 1.2.3: BugFix
### 1.2.3: BugFix

@@ -44,3 +162,3 @@ - within-time-switch

#### 1.2.2: BugFix
### 1.2.2: BugFix

@@ -54,3 +172,3 @@ - general

#### 1.2.1: rework
### 1.2.1: rework

@@ -85,3 +203,3 @@ - general

#### 1.1.8: small enhancement
### 1.1.8: small enhancement

@@ -95,3 +213,3 @@ - time inject

#### 1.1.7: BugFix
### 1.1.7: BugFix

@@ -112,3 +230,3 @@ - general

#### 1.1.6: BugFix
### 1.1.6: BugFix

@@ -118,3 +236,3 @@ - general

#### 1.1.5: BugFix
### 1.1.5: BugFix

@@ -124,3 +242,3 @@ - general

#### 1.1.4: BugFix
### 1.1.4: BugFix

@@ -152,3 +270,3 @@ - general

#### 1.1.3: maintenance
### 1.1.3: maintenance

@@ -159,3 +277,3 @@ only documentation changes

#### 1.1.2: BugFix
### 1.1.2: BugFix

@@ -165,3 +283,3 @@ - blind-control + clock-time

#### 1.1.1: BugFix + maintenance
### 1.1.1: BugFix + maintenance

@@ -177,3 +295,3 @@ - blind-control + clock-time

#### 1.1.0: mayor release
### 1.1.0: mayor release

@@ -201,3 +319,3 @@ - time-inject

#### 1.0.17: small enhancement
### 1.0.17: small enhancement

@@ -212,3 +330,3 @@ - inspired by #132 added for a property the possibility to control by

#### 1.0.16: BugFix
### 1.0.16: BugFix

@@ -225,3 +343,3 @@ - general

#### 1.0.15: BugFix + maintenance
### 1.0.15: BugFix + maintenance

@@ -234,3 +352,3 @@ - blind-control + clock-time

#### 1.0.14: BugFix
### 1.0.14: BugFix

@@ -240,3 +358,3 @@ - blind-control + clock-time

#### 1.0.13: BugFix
### 1.0.13: BugFix

@@ -256,5 +374,5 @@ - time-inject

#### 1.0.12: BugFix + enhancement
### 1.0.12: BugFix + enhancement
##### fixes
#### fixes

@@ -267,3 +385,3 @@ - general

##### enhancements
#### enhancements

@@ -273,3 +391,3 @@ - Blind-control allows now granular settings of topic

#### 1.0.11: enhancement
### 1.0.11: enhancement

@@ -279,3 +397,3 @@ - blind-control + clock-time + time-inject + within-time

#### 1.0.10: bug fix
### 1.0.10: bug fix

@@ -288,3 +406,3 @@ - general

#### 1.0.9: bug fix
### 1.0.9: bug fix

@@ -306,3 +424,3 @@ - general

#### 1.0.8: bug fix
### 1.0.8: bug fix

@@ -316,3 +434,3 @@ - time-inject

#### 1.0.7: bug fix
### 1.0.7: bug fix

@@ -326,3 +444,3 @@ - general

#### 1.0.6: bug fix
### 1.0.6: bug fix

@@ -338,3 +456,3 @@ - general

#### 1.0.5: bug fix
### 1.0.5: bug fix

@@ -344,3 +462,3 @@ - blind-control + clock-time

#### 1.0.4: bug fix
### 1.0.4: bug fix

@@ -355,3 +473,3 @@ - within-time-switch

#### 1.0.3: bug fix
### 1.0.3: bug fix

@@ -361,3 +479,3 @@ - blind-control

#### 1.0.2: bug fix
### 1.0.2: bug fix

@@ -371,3 +489,3 @@ - time-comp

#### 1.0.1: bug fix
### 1.0.1: bug fix

@@ -377,3 +495,3 @@ - time-inject

#### 1.0.0: mayor release
### 1.0.0: mayor release

@@ -405,3 +523,3 @@ - new Node: clock-time

#### 0.5.3 + 0.5.4: BugFix
### 0.5.3 + 0.5.4: BugFix

@@ -411,3 +529,3 @@ - general

#### 0.5.2: BugFix
### 0.5.2: BugFix

@@ -417,3 +535,3 @@ - general

#### 0.5.1: BugFix and Maintenance Release
### 0.5.1: BugFix and Maintenance Release

@@ -434,3 +552,3 @@ - general

#### 0.5.0: mayor release for blind control
### 0.5.0: mayor release for blind control

@@ -467,7 +585,7 @@ - configuration

#### 0.4.10: critical bug fix
### 0.4.10: critical bug fix
- fixed bug #57 with the code prepared for Node-Red 1.0. The recommend way for be backward compatible doesn't work. This is [also](https://discourse.nodered.org/t/knowing-when-a-node-is-done-new-node-api/15737/9) confirmed by @knolleary.
#### 0.4.9: small enhancement
### 0.4.9: small enhancement

@@ -480,7 +598,7 @@ - implemented #52 as height of the sun in the sky in percent (0~100 with 100% being at solarnoon and 0% being completely down) - altithudePercent

#### 0.4.8: Maintenance Release
### 0.4.8: Maintenance Release
- update dependencies
#### 0.4.7: BugFix Release
### 0.4.7: BugFix Release

@@ -492,3 +610,3 @@ - fix problems

#### 0.4.6: Maintenance Release
### 0.4.6: Maintenance Release

@@ -502,3 +620,3 @@ - time-comp

#### 0.4.5: Maintenance Release
### 0.4.5: Maintenance Release

@@ -514,3 +632,3 @@ - time-compare

#### 0.4.4: Maintenance Release
### 0.4.4: Maintenance Release

@@ -521,3 +639,3 @@ - all previous changes

#### 0.4.4-beta: Maintenance Release
### 0.4.4-beta: Maintenance Release

@@ -553,11 +671,11 @@ - fixed critical problem in sun - calculating Julian cycle which leads into wrong sun times if it is calculated at certain times

#### 0.4.3: Maintenance Release
### 0.4.3: Maintenance Release
- Version was unpublished due to critical Bugs
#### 0.4.1 / 0.4.2: Maintenance Release
### 0.4.1 / 0.4.2: Maintenance Release
- Version was unpublished due to critical Bugs
#### 0.4.0: Maintenance Release
### 0.4.0: Maintenance Release

@@ -574,3 +692,3 @@ - i18N for type-input options

#### 0.3.4: Maintenance Release
### 0.3.4: Maintenance Release

@@ -582,3 +700,3 @@ - blind control

#### 0.3.3: Maintenance Release
### 0.3.3: Maintenance Release

@@ -589,3 +707,3 @@ - preparations for node-red 1.0

#### 0.3.2: Maintenance Release
### 0.3.2: Maintenance Release

@@ -592,0 +710,0 @@ - prepared for own timezone settings

[
{
"id": "7f811af1.a975a4",
"id": "cc607a948d6ec2c6",
"type": "group",
"z": "9e1a7786.dff708",
"z": "c224c971b366d1da",
"name": "Example 1:",

@@ -11,22 +11,49 @@ "style": {

"nodes": [
"173ba173.59900f",
"f5863244.81b21"
"667a4fc206b12f63",
"5ed995c0d3056630"
],
"x": 314,
"y": 2879,
"w": 437,
"x": 264,
"y": 119,
"w": 447,
"h": 82
},
{
"id": "173ba173.59900f",
"id": "667a4fc206b12f63",
"type": "blind-control",
"z": "9e1a7786.dff708",
"g": "7f811af1.a975a4",
"z": "c224c971b366d1da",
"g": "cc607a948d6ec2c6",
"name": "",
"topic": "",
"addIdType": "none",
"addId": "",
"positionConfig": "",
"outputs": "1",
"autoTrigger": true,
"autoTriggerTime": "600000",
"startDelayTime": "0",
"results": [
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "topic"
},
{
"p": "",
"pt": "msgPayload",
"v": "",
"vt": "level"
},
{
"p": "slat",
"pt": "msg",
"v": "",
"vt": "slat"
},
{
"p": "blindCtrl",
"pt": "msg",
"v": "",
"vt": "ctrlObj"
}
],
"blindIncrement": 0.01,

@@ -38,2 +65,4 @@ "blindOpenPos": 1,

"blindPosDefaultType": "levelFixed",
"slatPosDefault": "",
"slatPosDefaultType": "none",
"overwriteExpire": "7200000",

@@ -44,54 +73,37 @@ "rules": [

"name": "open on civilDawn, but not before 6",
"timeValue": "6:00",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeBValue": "civilDawn",
"timeBType": "pdsTime",
"timeBOp": 1,
"timeBOpText": "latest (max)",
"offsetBValue": "",
"offsetBType": "none",
"multiplierB": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "num",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until latest (max)<div class=\"indent-time-text\"> 6:00 <b>or</b> civilDawn</div></div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinType": "none",
"timeMinValue": "",
"timeMinOp": 0,
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxType": "none",
"timeMaxValue": "",
"timeMaxOp": 0,
"offsetMaxType": "none",
"multiplierMax": 60000
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 1,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "6:00",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>6:00</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -101,59 +113,42 @@ {

"name": "close civilDusk, but not later than 23:00",
"timeValue": "civilDusk",
"timeType": "pdsTime",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeBValue": "23:00",
"timeBType": "entered",
"timeBOp": 0,
"timeBOpText": "earliest (min)",
"offsetBValue": "",
"offsetBType": "none",
"multiplierB": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "num",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from earliest (min)<div class=\"indent-time-text\"> civilDusk <b>or</b> 23:00</div></div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinType": "none",
"timeMinValue": "",
"timeMinOp": 0,
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxType": "none",
"timeMaxValue": "",
"timeMaxOp": 0,
"offsetMaxType": "none",
"multiplierMax": 60000
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 1,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "23:00",
"offsetType": "none",
"offset": "",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>23:00</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
}
],
"sunControlMode": "0",
"sunFloorLengthType": "num",
"sunFloorLength": "",
"sunMinAltitude": "",
"sunMinDelta": "",

@@ -164,43 +159,30 @@ "blindPosMin": "closed (min)",

"blindPosMaxType": "levelFixed",
"sunSlat": "",
"sunSlatType": "none",
"smoothTime": "",
"sunTopic": "",
"windowTopType": "num",
"windowTop": "",
"windowBottomType": "num",
"windowBottom": "",
"windowAzimuthStartType": "numAzimuth",
"windowAzimuthStart": "",
"windowAzimuthEndType": "numAzimuth",
"windowAzimuthEnd": "",
"oversteerValue": "",
"oversteerValueType": "none",
"oversteerCompare": "gte",
"oversteerThreshold": "",
"oversteerThresholdType": "num",
"oversteerBlindPos": "open (max)",
"oversteerBlindPosType": "levelFixed",
"oversteer2Value": "",
"oversteer2ValueType": "none",
"oversteer2Compare": "gte",
"oversteer2Threshold": "",
"oversteer2ThresholdType": "num",
"oversteer2BlindPos": "open (max)",
"oversteer2BlindPosType": "levelFixed",
"oversteer3Value": "",
"oversteer3ValueType": "none",
"oversteer3Compare": "gte",
"oversteer3Threshold": "",
"oversteer3ThresholdType": "num",
"oversteer3BlindPos": "open (max)",
"oversteer3BlindPosType": "levelFixed",
"oversteers": [],
"oversteerTopic": "",
"x": 420,
"y": 2920,
"x": 380,
"y": 160,
"wires": [
[
"f5863244.81b21"
]
"5ed995c0d3056630"
],
[]
]
},
{
"id": "f5863244.81b21",
"id": "5ed995c0d3056630",
"type": "debug",
"z": "9e1a7786.dff708",
"g": "7f811af1.a975a4",
"z": "c224c971b366d1da",
"g": "cc607a948d6ec2c6",
"name": "",

@@ -212,6 +194,6 @@ "active": true,

"complete": "false",
"x": 635,
"y": 2920,
"x": 595,
"y": 160,
"wires": []
}
]
[
{
"id": "926ad7eb.e545b8",
"id": "6e01a45fcbd51a8c",
"type": "group",
"z": "9e1a7786.dff708",
"z": "c224c971b366d1da",
"name": "Example 2:",

@@ -11,13 +11,13 @@ "style": {

"nodes": [
"9f0b0d69.1ef08",
"fd9184cc.03be78",
"276df570.12c3da",
"5f6c302b.62169",
"4d67f26b.7eae7c",
"64892aed.a13a44",
"c39f19d5.200c58",
"3e105732.ce5f08"
"d195485526ad453e",
"eb392274d76a0414",
"aeda8f25a9820661",
"48348f9d010c1fde",
"2cb4ea2aba0c5c11",
"2913211db6773ad0",
"3b271cc23ececaf8",
"6a69e7605bb1ab83"
],
"x": 344,
"y": 3059,
"x": 304,
"y": 299,
"w": 552,

@@ -27,13 +27,40 @@ "h": 277

{
"id": "9f0b0d69.1ef08",
"id": "d195485526ad453e",
"type": "blind-control",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "",
"topic": "",
"addIdType": "none",
"addId": "",
"positionConfig": "",
"outputs": 1,
"autoTrigger": true,
"autoTriggerTime": "600000",
"startDelayTime": "0",
"results": [
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "topic"
},
{
"p": "",
"pt": "msgPayload",
"v": "",
"vt": "level"
},
{
"p": "slat",
"pt": "msg",
"v": "",
"vt": "slat"
},
{
"p": "blindCtrl",
"pt": "msg",
"v": "",
"vt": "ctrlObj"
}
],
"blindIncrement": "0.01",

@@ -44,2 +71,4 @@ "blindOpenPos": "1",

"blindPosDefaultType": "levelFixed",
"slatPosDefault": "",
"slatPosDefaultType": "none",
"overwriteExpire": "14400000",

@@ -50,49 +79,37 @@ "rules": [

"name": "",
"timeValue": "6:30",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until 6:30</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "6:30",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>6:30</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -102,49 +119,46 @@ {

"name": "",
"timeValue": "7:25",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "dayInfo.today.isWeekendOrHoliday",
"validOperandAType": "flow",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> flow....fo.today.isWeekendOrHoliday is true</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until 7:25</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "flow",
"value": "dayInfo.today.isWeekendOrHoliday",
"operator": "true",
"operatorText": "ist true",
"thresholdType": "str",
"threshold": ""
}
],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "7:25",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>flow....fo.today.isWeekendOrHoliday</var> ist true</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>7:25</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -154,49 +168,46 @@ {

"name": "",
"timeValue": "civilDawn",
"timeType": "pdsTime",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until civilDawn</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "flow",
"value": "dayInfo.tomorrow.isWeekendOrHoliday",
"operator": "false",
"operatorText": "ist false",
"thresholdType": "str",
"threshold": ""
}
],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "22:35",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>flow....tomorrow.isWeekendOrHoliday</var> ist false</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>22:35</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -206,156 +217,42 @@ {

"name": "",
"timeValue": "civilDusk",
"timeType": "pdsTime",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from civilDusk</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 4,
"name": "",
"timeValue": "22:35",
"timeType": "entered",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "dayInfo.tomorrow.isWeekendOrHoliday",
"validOperandAType": "flow",
"validOperator": "false",
"validOperatorText": "is false",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> flow....tomorrow.isWeekendOrHoliday is false</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from 22:35</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 5,
"name": "",
"timeValue": "23:15",
"timeType": "entered",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from 23:15</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "23:15",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>23:15</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
}
],
"sunControlMode": "0",
"sunFloorLengthType": "num",
"sunFloorLength": "",
"sunMinAltitude": "",
"sunMinDelta": "",

@@ -366,43 +263,30 @@ "blindPosMin": "closed (min)",

"blindPosMaxType": "levelFixed",
"sunSlat": "",
"sunSlatType": "none",
"smoothTime": "",
"sunTopic": "",
"windowTopType": "num",
"windowTop": "",
"windowBottomType": "num",
"windowBottom": "",
"windowAzimuthStartType": "numAzimuth",
"windowAzimuthStart": "",
"windowAzimuthEndType": "numAzimuth",
"windowAzimuthEnd": "",
"oversteerValue": "",
"oversteerValueType": "none",
"oversteerCompare": "gte",
"oversteerThreshold": "50",
"oversteerThresholdType": "num",
"oversteerBlindPos": "open (max)",
"oversteerBlindPosType": "levelFixed",
"oversteer2Value": "",
"oversteer2ValueType": "none",
"oversteer2Compare": "gte",
"oversteer2Threshold": "",
"oversteer2ThresholdType": "num",
"oversteer2BlindPos": "open (max)",
"oversteer2BlindPosType": "levelFixed",
"oversteer3Value": "",
"oversteer3ValueType": "none",
"oversteer3Compare": "gte",
"oversteer3Threshold": "",
"oversteer3ThresholdType": "num",
"oversteer3BlindPos": "open (max)",
"oversteer3BlindPosType": "levelFixed",
"oversteers": [],
"oversteerTopic": "",
"x": 520,
"y": 3100,
"x": 480,
"y": 340,
"wires": [
[
"fd9184cc.03be78"
]
"eb392274d76a0414"
],
[]
]
},
{
"id": "fd9184cc.03be78",
"id": "eb392274d76a0414",
"type": "debug",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "",

@@ -414,11 +298,11 @@ "active": true,

"complete": "false",
"x": 735,
"y": 3100,
"x": 695,
"y": 340,
"wires": []
},
{
"id": "276df570.12c3da",
"id": "aeda8f25a9820661",
"type": "change",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "dayInfo.today.isWeekendOrHoliday",

@@ -439,4 +323,4 @@ "rules": [

"reg": false,
"x": 710,
"y": 3160,
"x": 670,
"y": 400,
"wires": [

@@ -447,6 +331,6 @@ []

{
"id": "5f6c302b.62169",
"id": "48348f9d010c1fde",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "",

@@ -460,7 +344,7 @@ "repeat": "",

"payloadType": "bool",
"x": 440,
"y": 3160,
"x": 400,
"y": 400,
"wires": [
[
"276df570.12c3da"
"aeda8f25a9820661"
]

@@ -470,6 +354,6 @@ ]

{
"id": "4d67f26b.7eae7c",
"id": "2cb4ea2aba0c5c11",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "",

@@ -483,7 +367,7 @@ "repeat": "",

"payloadType": "bool",
"x": 440,
"y": 3205,
"x": 400,
"y": 445,
"wires": [
[
"276df570.12c3da"
"aeda8f25a9820661"
]

@@ -493,6 +377,6 @@ ]

{
"id": "64892aed.a13a44",
"id": "2913211db6773ad0",
"type": "change",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "dayInfo.tomorrow.isWeekendOrHoliday",

@@ -513,4 +397,4 @@ "rules": [

"reg": false,
"x": 720,
"y": 3250,
"x": 680,
"y": 490,
"wires": [

@@ -521,6 +405,6 @@ []

{
"id": "c39f19d5.200c58",
"id": "3b271cc23ececaf8",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "",

@@ -534,7 +418,7 @@ "repeat": "",

"payloadType": "bool",
"x": 440,
"y": 3250,
"x": 400,
"y": 490,
"wires": [
[
"64892aed.a13a44"
"2913211db6773ad0"
]

@@ -544,6 +428,6 @@ ]

{
"id": "3e105732.ce5f08",
"id": "6a69e7605bb1ab83",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "926ad7eb.e545b8",
"z": "c224c971b366d1da",
"g": "6e01a45fcbd51a8c",
"name": "",

@@ -557,7 +441,7 @@ "repeat": "",

"payloadType": "bool",
"x": 440,
"y": 3295,
"x": 400,
"y": 535,
"wires": [
[
"64892aed.a13a44"
"2913211db6773ad0"
]

@@ -564,0 +448,0 @@ ]

[
{
"id": "aae4e74b.890ad8",
"id": "f154222105f64635",
"type": "group",
"z": "9e1a7786.dff708",
"z": "c224c971b366d1da",
"name": "Example 3:",

@@ -11,22 +11,22 @@ "style": {

"nodes": [
"e9dd0842.1af178",
"45036313.db7dcc",
"a8cfd4d.9af3c28",
"75914074.c8629",
"8ce279e8.731418",
"99a18ac2.0bfe08",
"127a140f.61613c",
"bf647269.bfee2",
"61e24b9a.971464",
"4088273c.dc5af8",
"292af211.57f12e",
"8456fddc.63e15",
"4ef781c7.c8b9a",
"df6bfa2b.b65ae8",
"e22bf2e7.8d57f",
"f5439f90.11cfe",
"4b25a2b9.5062dc"
"63677e342a2b4852",
"50ece54c266a208c",
"476de16a1fed3df5",
"5b9d9975b243bd29",
"f00cd7fd0c194cc9",
"9336e0b901db3e22",
"3aa7f018fb3f61cc",
"84fd3f1ff36ef62b",
"d51582816e0b4932",
"6f988ad16fa7500e",
"735d3627bdb581e7",
"9b6ad2e5a5d7eeea",
"1de03741c7881227",
"4b858878346ebe2a",
"fe6920ed64b8cf0c",
"e96f0f06de5514d8",
"26931e3fb054bf5f"
],
"x": 204,
"y": 3494,
"x": 84,
"y": 494,
"w": 1027,

@@ -36,6 +36,6 @@ "h": 397

{
"id": "e9dd0842.1af178",
"id": "63677e342a2b4852",
"type": "function",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "30min 1sec",

@@ -47,7 +47,7 @@ "func": "\nconst minutesEachLoop = 30; // minutes to add\nconst loopCycle = 1; // seconds delay\nlet timeObj = context.get(\"timeObj\");\n\nif (timeObj && msg.topic.includes('stop')) {\n clearInterval(timeObj);\n context.set(\"timeObj\", null);\n context.set(\"orgtopic\", null);\n let d = new Date(context.get(\"date\"));\n node.log(\"STOP \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\n node.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ' + d.toISOString());\n node.status({fill:\"red\",shape:\"ring\",text:\"stopped - \" + d.toLocaleTimeString()});\n return null;\n} else if (!timeObj && msg.topic.includes('start')) {\n context.set(\"message\", msg);\n context.set(\"orgtopic\", msg.topic);\n let d = new Date();\n let num = Number(msg.payload);\n if (isNaN(num) && num < 24) {\n d.setHours(num);\n d.setMinutes(0);\n } else {\n let dt = new Date(msg.payload);\n if (dt instanceof Date && !isNaN(dt)) {\n d = dt;\n } else {\n d.setHours(0);\n d.setMinutes(0);\n }\n }\n context.set(\"date\", d.getTime());\n msg.tsISO = d.toISOString();\n msg.ts = d.getTime();\n msg.topic += ' ' + d.toLocaleTimeString();\n node.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');\n node.log(\"START \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\n node.send(msg);\n\n let timeObj = setInterval(function(){\n let msg = context.get(\"message\");\n let topic = context.get(\"orgtopic\");\n let d = new Date(context.get(\"date\"));\n //d.setHours(d.getHours()+1);\n let dt = d.getDate();\n let dm = d.getMonth();\n d.setMinutes(d.getMinutes() + minutesEachLoop)\n d.setDate(dt);\n d.getMonth(dm);\n context.set(\"date\", d.getTime());\n msg.tsISO = d.toISOString();\n msg.ts = d.getTime();\n msg.topic = topic + ' ' + d.toLocaleTimeString();\n node.status({fill:\"green\",shape:\"dot\",text:\"run - \" + d.toLocaleTimeString()});\n node.log(\"sending \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\n node.send(msg);\n\t}, (1000 * loopCycle));\n context.set(\"timeObj\", timeObj);\n node.status({fill:\"green\",shape:\"ring\",text:\"start - \" + d.toLocaleTimeString()});\n return null;\n}\n\nlet d = new Date(context.get(\"date\"));\nif (!(d instanceof Date) || isNaN(d)) {\n d = new Date();\n}\nd.setMinutes(d.getMinutes() + 1)\n//d.setHours(d.getHours()+1);\nmsg.tsISO = d.toISOString();\nmsg.ts = d.getTime();\nmsg.topic += ' ' + d.toLocaleTimeString();\nnode.status({fill:\"yellow\",shape:\"dot\",text:\"interposed - \" + d.toLocaleTimeString() + ' - ' + msg.payload});\nnode.log(\"sending interposed msg \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\nnode.send(msg);\nreturn null;\n",

"finalize": "",
"x": 650,
"y": 3580,
"x": 530,
"y": 580,
"wires": [
[
"4088273c.dc5af8"
"6f988ad16fa7500e"
]

@@ -57,6 +57,6 @@ ]

{
"id": "45036313.db7dcc",
"id": "50ece54c266a208c",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "",

@@ -70,7 +70,7 @@ "repeat": "",

"payloadType": "num",
"x": 355,
"y": 3535,
"x": 235,
"y": 535,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -80,6 +80,6 @@ ]

{
"id": "a8cfd4d.9af3c28",
"id": "476de16a1fed3df5",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "reset",

@@ -93,7 +93,7 @@ "repeat": "",

"payloadType": "bool",
"x": 330,
"y": 3625,
"x": 210,
"y": 625,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -103,6 +103,6 @@ ]

{
"id": "75914074.c8629",
"id": "5b9d9975b243bd29",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "0%",

@@ -116,7 +116,7 @@ "repeat": "",

"payloadType": "num",
"x": 330,
"y": 3665,
"x": 210,
"y": 665,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -126,6 +126,6 @@ ]

{
"id": "8ce279e8.731418",
"id": "f00cd7fd0c194cc9",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "60%",

@@ -139,7 +139,7 @@ "repeat": "",

"payloadType": "num",
"x": 330,
"y": 3710,
"x": 210,
"y": 710,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -149,17 +149,17 @@ ]

{
"id": "99a18ac2.0bfe08",
"id": "9336e0b901db3e22",
"type": "comment",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "manual overrides:",
"info": "",
"x": 325,
"y": 3580,
"x": 205,
"y": 580,
"wires": []
},
{
"id": "127a140f.61613c",
"id": "3aa7f018fb3f61cc",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "90%, expire 2,5s",

@@ -173,7 +173,7 @@ "repeat": "",

"payloadType": "json",
"x": 360,
"y": 3760,
"x": 240,
"y": 760,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -183,6 +183,6 @@ ]

{
"id": "bf647269.bfee2",
"id": "84fd3f1ff36ef62b",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "30% importance 1",

@@ -196,7 +196,7 @@ "repeat": "",

"payloadType": "json",
"x": 340,
"y": 3805,
"x": 220,
"y": 805,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -206,6 +206,6 @@ ]

{
"id": "61e24b9a.971464",
"id": "d51582816e0b4932",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "100% importance 1",

@@ -219,7 +219,7 @@ "repeat": "",

"payloadType": "json",
"x": 350,
"y": 3850,
"x": 230,
"y": 850,
"wires": [
[
"e9dd0842.1af178"
"63677e342a2b4852"
]

@@ -229,13 +229,40 @@ ]

{
"id": "4088273c.dc5af8",
"id": "6f988ad16fa7500e",
"type": "blind-control",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "",
"topic": "",
"addIdType": "none",
"addId": "",
"positionConfig": "",
"outputs": 1,
"autoTrigger": false,
"autoTriggerTime": "1200000",
"startDelayTime": "0",
"results": [
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "topic"
},
{
"p": "",
"pt": "msgPayload",
"v": "",
"vt": "level"
},
{
"p": "slat",
"pt": "msg",
"v": "",
"vt": "slat"
},
{
"p": "blindCtrl",
"pt": "msg",
"v": "",
"vt": "ctrlObj"
}
],
"blindIncrement": "0.01",

@@ -246,2 +273,4 @@ "blindOpenPos": "1",

"blindPosDefaultType": "levelFixed",
"slatPosDefault": "",
"slatPosDefaultType": "none",
"overwriteExpire": "7200000",

@@ -252,49 +281,37 @@ "rules": [

"name": "",
"timeValue": "5:30",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until 5:30</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 1,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "5:30",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>5:30</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -304,49 +321,46 @@ {

"name": "",
"timeValue": "7:25",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "dayInfo.today.isWeekendOrHoliday",
"validOperandAType": "flow",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> flow....fo.today.isWeekendOrHoliday is true</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until 7:25</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "flow",
"value": "dayInfo.today.isWeekendOrHoliday",
"operator": "true",
"operatorText": "ist true",
"thresholdType": "str",
"threshold": ""
}
],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 1,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "7:25",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>flow....fo.today.isWeekendOrHoliday</var> ist true</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>7:25</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -356,49 +370,46 @@ {

"name": "",
"timeValue": "civilDawn",
"timeType": "pdsTime",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until civilDawn</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "flow",
"value": "dayInfo.tomorrow.isWeekendOrHoliday",
"operator": "false",
"operatorText": "ist false",
"thresholdType": "str",
"threshold": ""
}
],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 1,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "21:25",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>flow....tomorrow.isWeekendOrHoliday</var> ist false</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>21:25</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -408,156 +419,42 @@ {

"name": "",
"timeValue": "civilDusk",
"timeType": "pdsTime",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from civilDusk</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 4,
"name": "",
"timeValue": "21:25",
"timeType": "entered",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "dayInfo.tomorrow.isWeekendOrHoliday",
"validOperandAType": "flow",
"validOperator": "false",
"validOperatorText": "is false",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> flow....tomorrow.isWeekendOrHoliday is false</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from 21:25</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 5,
"name": "",
"timeValue": "23:15",
"timeType": "entered",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 1,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from 23:15</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 1,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "23:15",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>23:15</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
}
],
"sunControlMode": "2",
"sunControlMode": 16,
"sunFloorLengthType": "num",
"sunFloorLength": "0.6",
"sunMinAltitude": "",
"sunMinDelta": "",

@@ -568,43 +465,30 @@ "blindPosMin": "closed (min)",

"blindPosMaxType": "levelFixed",
"sunSlat": "",
"sunSlatType": "none",
"smoothTime": "",
"sunTopic": "",
"windowTopType": "num",
"windowTop": "1.28",
"windowBottomType": "num",
"windowBottom": "0",
"windowAzimuthStartType": "numAzimuth",
"windowAzimuthStart": "70",
"windowAzimuthEndType": "numAzimuth",
"windowAzimuthEnd": "150",
"oversteerValue": "",
"oversteerValueType": "none",
"oversteerCompare": "gte",
"oversteerThreshold": "50",
"oversteerThresholdType": "num",
"oversteerBlindPos": "open (max)",
"oversteerBlindPosType": "levelFixed",
"oversteer2Value": "",
"oversteer2ValueType": "none",
"oversteer2Compare": "gte",
"oversteer2Threshold": "",
"oversteer2ThresholdType": "num",
"oversteer2BlindPos": "open (max)",
"oversteer2BlindPosType": "levelFixed",
"oversteer3Value": "",
"oversteer3ValueType": "none",
"oversteer3Compare": "gte",
"oversteer3Threshold": "",
"oversteer3ThresholdType": "num",
"oversteer3BlindPos": "open (max)",
"oversteer3BlindPosType": "levelFixed",
"oversteers": [],
"oversteerTopic": "",
"x": 870,
"y": 3580,
"x": 750,
"y": 580,
"wires": [
[
"292af211.57f12e"
]
"735d3627bdb581e7"
],
[]
]
},
{
"id": "292af211.57f12e",
"id": "735d3627bdb581e7",
"type": "debug",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "Blind position",

@@ -617,11 +501,11 @@ "active": true,

"targetType": "msg",
"x": 1115,
"y": 3580,
"x": 995,
"y": 580,
"wires": []
},
{
"id": "8456fddc.63e15",
"id": "9b6ad2e5a5d7eeea",
"type": "change",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "dayInfo.today.isWeekendOrHoliday",

@@ -642,4 +526,4 @@ "rules": [

"reg": false,
"x": 915,
"y": 3715,
"x": 795,
"y": 715,
"wires": [

@@ -650,6 +534,6 @@ []

{
"id": "4ef781c7.c8b9a",
"id": "1de03741c7881227",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "",

@@ -663,7 +547,7 @@ "repeat": "",

"payloadType": "bool",
"x": 645,
"y": 3715,
"x": 525,
"y": 715,
"wires": [
[
"8456fddc.63e15"
"9b6ad2e5a5d7eeea"
]

@@ -673,6 +557,6 @@ ]

{
"id": "df6bfa2b.b65ae8",
"id": "4b858878346ebe2a",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "",

@@ -686,7 +570,7 @@ "repeat": "",

"payloadType": "bool",
"x": 645,
"y": 3760,
"x": 525,
"y": 760,
"wires": [
[
"8456fddc.63e15"
"9b6ad2e5a5d7eeea"
]

@@ -696,6 +580,6 @@ ]

{
"id": "e22bf2e7.8d57f",
"id": "fe6920ed64b8cf0c",
"type": "change",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "dayInfo.tomorrow.isWeekendOrHoliday",

@@ -716,4 +600,4 @@ "rules": [

"reg": false,
"x": 925,
"y": 3805,
"x": 805,
"y": 805,
"wires": [

@@ -724,6 +608,6 @@ []

{
"id": "f5439f90.11cfe",
"id": "e96f0f06de5514d8",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "",

@@ -737,7 +621,7 @@ "repeat": "",

"payloadType": "bool",
"x": 645,
"y": 3805,
"x": 525,
"y": 805,
"wires": [
[
"e22bf2e7.8d57f"
"fe6920ed64b8cf0c"
]

@@ -747,6 +631,6 @@ ]

{
"id": "4b25a2b9.5062dc",
"id": "26931e3fb054bf5f",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "aae4e74b.890ad8",
"z": "c224c971b366d1da",
"g": "f154222105f64635",
"name": "",

@@ -760,7 +644,7 @@ "repeat": "",

"payloadType": "bool",
"x": 645,
"y": 3850,
"x": 525,
"y": 850,
"wires": [
[
"e22bf2e7.8d57f"
"fe6920ed64b8cf0c"
]

@@ -767,0 +651,0 @@ ]

[
{
"id": "36a278a8.1d1df8",
"id": "c76466a96ba836b1",
"type": "group",
"z": "9e1a7786.dff708",
"z": "c224c971b366d1da",
"name": "Example 4:",

@@ -11,30 +11,30 @@ "style": {

"nodes": [
"b1a35885.089b38",
"931b71c6.31c18",
"8cc8295d.535a98",
"d90bf98d.d851b8",
"ce1bfb37.e1e668",
"e367d9e9.0c39f8",
"40aac8dc.6d4e38",
"c02c44c8.01dbb8",
"5b3ce7b8.191ac8",
"bb9ca641.5cf4a8",
"e92d6413.317dc8",
"60ed6aa.786c594",
"512d7d7c.cc4324",
"5274fe0b.5c87b",
"5f5128b8.b203b8",
"7b462ced.4cb384",
"ad40d513.0245c8",
"b1237bf5.0feeb8",
"3d75aed5.6e8442",
"9ded5223.d994f",
"bf7f9c40.0ee1a",
"df4683fb.c9728",
"5d4d287b.8ac1f8",
"bab47071.c4815",
"8268cecb.a1615"
"ae28974eb66d7e01",
"2997c81e7b2225c1",
"55b37b3d630fcba4",
"961b294957d3a191",
"c496262a3e6fe741",
"2c7bb11cbc989bd0",
"13b8c1499694447c",
"d418e260b6b136cd",
"96d5f4a031ca61f5",
"fb6e7667db75ddfe",
"6c876fb5569b72c1",
"4e86bf5fa7ce9eb4",
"4bda9eccdbfdb495",
"bfa382b93bd597ad",
"c2682807c38e7984",
"d2ee545cee421e7d",
"f1cff356b43f2361",
"950ddb2bda38827c",
"5945cf207c1f9d75",
"bc0b1a95c3c96bba",
"540c58172e24984e",
"12fc3eb929f5fa03",
"77af066a2c94381b",
"147b4386c49ec7cc",
"41297f15f6a5173b"
],
"x": 204,
"y": 4024,
"x": 84,
"y": 944,
"w": 1032,

@@ -44,6 +44,6 @@ "h": 547

{
"id": "b1a35885.089b38",
"id": "ae28974eb66d7e01",
"type": "function",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "30min 0.5sec",

@@ -55,7 +55,7 @@ "func": "\nconst minutesEachLoop = 30; // minutes to add\nconst loopCycle = 0.5; // seconds delay\nlet timeObj = context.get(\"timeObj\");\n\nif (timeObj && msg.topic.includes('stop')) {\n clearInterval(timeObj);\n context.set(\"timeObj\", null);\n context.set(\"orgtopic\", null);\n let d = new Date(context.get(\"date\"));\n node.log(\"STOP \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\n node.log('<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ' + d.toISOString());\n node.status({fill:\"red\",shape:\"ring\",text:\"stopped - \" + d.toLocaleTimeString()});\n return null;\n} else if (!timeObj && msg.topic.includes('start')) {\n context.set(\"message\", msg);\n context.set(\"orgtopic\", msg.topic);\n let d = new Date();\n let num = Number(msg.payload);\n if (isNaN(num) && num < 24) {\n d.setHours(num);\n d.setMinutes(0);\n } else {\n let dt = new Date(msg.payload);\n if (dt instanceof Date && !isNaN(dt)) {\n d = dt;\n } else {\n d.setHours(0);\n d.setMinutes(0);\n }\n }\n context.set(\"date\", d.getTime());\n msg.tsISO = d.toISOString();\n msg.ts = d.getTime();\n msg.topic += ' ' + d.toLocaleTimeString();\n node.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>');\n node.log(\"START \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\n node.send(msg);\n\n let timeObj = setInterval(function(){\n let msg = context.get(\"message\");\n let topic = context.get(\"orgtopic\");\n let d = new Date(context.get(\"date\"));\n //d.setHours(d.getHours()+1);\n let dt = d.getDate();\n let dm = d.getMonth();\n d.setMinutes(d.getMinutes() + minutesEachLoop)\n d.setDate(dt);\n d.getMonth(dm);\n context.set(\"date\", d.getTime());\n msg.tsISO = d.toISOString();\n msg.ts = d.getTime();\n msg.topic = topic + ' ' + d.toLocaleTimeString();\n node.status({fill:\"green\",shape:\"dot\",text:\"run - \" + d.toLocaleTimeString()});\n node.log(\"sending \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\n node.send(msg);\n\t}, (1000 * loopCycle));\n context.set(\"timeObj\", timeObj);\n node.status({fill:\"green\",shape:\"ring\",text:\"start - \" + d.toLocaleTimeString()});\n return null;\n}\n\nlet d = new Date(context.get(\"date\"));\nif (!(d instanceof Date) || isNaN(d)) {\n d = new Date();\n}\nd.setMinutes(d.getMinutes() + 1)\n//d.setHours(d.getHours()+1);\nmsg.tsISO = d.toISOString();\nmsg.ts = d.getTime();\nmsg.topic += ' ' + d.toLocaleTimeString();\nnode.status({fill:\"yellow\",shape:\"dot\",text:\"interposed - \" + d.toLocaleTimeString() + ' - ' + msg.payload});\nnode.log(\"sending interposed msg \" + d.toLocaleTimeString() + ' ####################################### payload='+msg.payload+' topic='+msg.topic);\nnode.send(msg);\nreturn null;\n",

"finalize": "",
"x": 650,
"y": 4140,
"x": 530,
"y": 1060,
"wires": [
[
"bb9ca641.5cf4a8"
"fb6e7667db75ddfe"
]

@@ -65,6 +65,6 @@ ]

{
"id": "931b71c6.31c18",
"id": "2997c81e7b2225c1",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -78,7 +78,7 @@ "repeat": "",

"payloadType": "num",
"x": 355,
"y": 4095,
"x": 235,
"y": 1015,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -88,6 +88,6 @@ ]

{
"id": "8cc8295d.535a98",
"id": "55b37b3d630fcba4",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "reset",

@@ -101,7 +101,7 @@ "repeat": "",

"payloadType": "bool",
"x": 330,
"y": 4185,
"x": 210,
"y": 1105,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -111,6 +111,6 @@ ]

{
"id": "d90bf98d.d851b8",
"id": "961b294957d3a191",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "0%",

@@ -124,7 +124,7 @@ "repeat": "",

"payloadType": "num",
"x": 330,
"y": 4225,
"x": 210,
"y": 1145,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -134,6 +134,6 @@ ]

{
"id": "ce1bfb37.e1e668",
"id": "c496262a3e6fe741",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "60%",

@@ -147,7 +147,7 @@ "repeat": "",

"payloadType": "num",
"x": 330,
"y": 4270,
"x": 210,
"y": 1190,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -157,17 +157,17 @@ ]

{
"id": "e367d9e9.0c39f8",
"id": "2c7bb11cbc989bd0",
"type": "comment",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "manual overrides:",
"info": "",
"x": 325,
"y": 4140,
"x": 205,
"y": 1060,
"wires": []
},
{
"id": "40aac8dc.6d4e38",
"id": "13b8c1499694447c",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "90%, expire 2,5s",

@@ -181,7 +181,7 @@ "repeat": "",

"payloadType": "json",
"x": 360,
"y": 4320,
"x": 240,
"y": 1240,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -191,6 +191,6 @@ ]

{
"id": "c02c44c8.01dbb8",
"id": "d418e260b6b136cd",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "30% importance 1",

@@ -204,7 +204,7 @@ "repeat": "",

"payloadType": "json",
"x": 340,
"y": 4365,
"x": 220,
"y": 1285,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -214,6 +214,6 @@ ]

{
"id": "5b3ce7b8.191ac8",
"id": "96d5f4a031ca61f5",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "100% importance 1",

@@ -227,7 +227,7 @@ "repeat": "",

"payloadType": "json",
"x": 350,
"y": 4410,
"x": 230,
"y": 1330,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -237,13 +237,40 @@ ]

{
"id": "bb9ca641.5cf4a8",
"id": "fb6e7667db75ddfe",
"type": "blind-control",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",
"topic": "",
"addIdType": "none",
"addId": "",
"positionConfig": "",
"outputs": 1,
"autoTrigger": false,
"autoTriggerTime": "1200000",
"startDelayTime": "0",
"results": [
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "topic"
},
{
"p": "",
"pt": "msgPayload",
"v": "",
"vt": "level"
},
{
"p": "slat",
"pt": "msg",
"v": "",
"vt": "slat"
},
{
"p": "blindCtrl",
"pt": "msg",
"v": "",
"vt": "ctrlObj"
}
],
"blindIncrement": "0.01",

@@ -254,2 +281,4 @@ "blindOpenPos": "1",

"blindPosDefaultType": "levelFixed",
"slatPosDefault": "",
"slatPosDefaultType": "none",
"overwriteExpire": "7200000",

@@ -260,49 +289,26 @@ "rules": [

"name": "",
"timeValue": "",
"timeType": "none",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "10%",
"levelType": "levelFixed",
"levelOp": 1,
"levelOpText": "⭳❗ minimum (oversteer)",
"validOperandAValue": "windowOpen",
"validOperandAType": "msg",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "windowOpen",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> msg.windowOpen is true</div><div>⭳❗ minimum (oversteer) 10%</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "msg",
"value": "windowOpen",
"operator": "true",
"operatorText": "ist true",
"thresholdType": "str",
"threshold": "windowOpen"
}
],
"level": {
"type": "levelFixed",
"value": "10%",
"operator": 1,
"operatorText": "⭳❗ Minimum (übersteuernd)"
},
"slat": {
"type": "none",
"value": ""
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>msg.windowOpen</var> ist true</div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ⭳❗ Minimum (übersteuernd) <var>10%</var></div></div>",
"importance": 0
},

@@ -312,49 +318,37 @@ {

"name": "",
"timeValue": "5:30",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until 5:30</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "5:30",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>5:30</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -364,49 +358,46 @@ {

"name": "",
"timeValue": "7:25",
"timeType": "entered",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "dayInfo.today.isWeekendOrHoliday",
"validOperandAType": "flow",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> flow....fo.today.isWeekendOrHoliday is true</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until 7:25</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "flow",
"value": "dayInfo.today.isWeekendOrHoliday",
"operator": "true",
"operatorText": "ist true",
"thresholdType": "str",
"threshold": ""
}
],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDawn",
"operator": 0,
"operatorText": "↥ bis",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMin": {
"type": "entered",
"value": "7:25",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>flow....fo.today.isWeekendOrHoliday</var> ist true</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ bis <var>bürgerliche Morgendämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-backward\" aria-hidden=\"true\"></i> <span>frühestens (min)</span> <var>7:25</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -416,49 +407,26 @@ {

"name": "",
"timeValue": "civilDawn",
"timeType": "pdsTime",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↥ until civilDawn</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "msg",
"value": "raining",
"operator": "true",
"operatorText": "ist true",
"thresholdType": "num",
"threshold": 0
}
],
"level": {
"type": "levelFixed",
"value": "50%",
"operator": 2,
"operatorText": "⭱️❗ Maximum (übersteuernd)"
},
"slat": {
"type": "none",
"value": ""
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>msg.raining</var> ist true</div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ⭱️❗ Maximum (übersteuernd) <var>50%</var></div></div>",
"importance": 0
},

@@ -468,49 +436,46 @@ {

"name": "",
"timeValue": "",
"timeType": "none",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelND",
"levelOp": 1,
"levelOpText": "⭳❗ minimum (oversteer)",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "num",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div>⭳✋ reset minimum</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [
{
"valueType": "flow",
"value": "dayInfo.tomorrow.isWeekendOrHoliday",
"operator": "false",
"operatorText": "ist false",
"thresholdType": "str",
"threshold": ""
}
],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "21:25",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> <var>flow....tomorrow.isWeekendOrHoliday</var> ist false</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>21:25</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
},

@@ -520,207 +485,42 @@ {

"name": "",
"timeValue": "",
"timeType": "none",
"timeOp": 0,
"timeOpText": "↥ until",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "50%",
"levelType": "levelFixed",
"levelOp": 2,
"levelOpText": "⭱️❗ maximum (oversteer)",
"validOperandAValue": "raining",
"validOperandAType": "msg",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "num",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> msg.raining is true</div><div>⭱️❗ maximum (oversteer) 50%</div>",
"valid": {},
"isValid": false,
"version": 3,
"isValid": true,
"conditions": [],
"level": {
"type": "levelFixed",
"value": "closed (min)",
"operator": 0,
"operatorText": "↕ Absolut"
},
"slat": {
"type": "none",
"value": ""
},
"topic": "",
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 6,
"name": "",
"timeValue": "civilDusk",
"timeType": "pdsTime",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from civilDusk</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 7,
"name": "",
"timeValue": "21:25",
"timeType": "entered",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "dayInfo.tomorrow.isWeekendOrHoliday",
"validOperandAType": "flow",
"validOperator": "false",
"validOperatorText": "is false",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-code-fork\" aria-hidden=\"true\"></i> flow....tomorrow.isWeekendOrHoliday is false</div><div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from 21:25</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
},
{
"index": 8,
"name": "",
"timeValue": "23:15",
"timeType": "entered",
"timeOp": 1,
"timeOpText": "↧ from",
"offsetValue": "",
"offsetType": "none",
"multiplier": 60000,
"timeMinValue": "",
"timeMinType": "none",
"offsetMinValue": "",
"offsetMinType": "none",
"multiplierMin": 60000,
"timeMaxValue": "",
"timeMaxType": "none",
"offsetMaxValue": "",
"offsetMaxType": "none",
"multiplierMax": 60000,
"levelValue": "closed (min)",
"levelType": "levelFixed",
"levelOp": 0,
"levelOpText": "↕ absolute",
"validOperandAValue": "",
"validOperandAType": "none",
"validOperator": "true",
"validOperatorText": "is true",
"validOperandBValue": "",
"validOperandBType": "str",
"valid2LogOperator": 0,
"valid2LogOperatorText": "N/A",
"valid2OperandAValue": "",
"valid2OperandAType": "msg",
"valid2Operator": "true",
"valid2OperatorText": "is true",
"valid2OperandBValue": "",
"valid2OperandBType": "num",
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ from 23:15</div><div>↕ absolute closed (min)</div>",
"valid": {},
"isValid": false,
"importance": 0,
"timeDays": "*",
"timeMonths": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeDateStart": "",
"timeDateEnd": "",
"timeMinOp": 0,
"timeMaxOp": 0
"resetOverwrite": false,
"time": {
"type": "pdsTime",
"value": "civilDusk",
"operator": 1,
"operatorText": "↧ von",
"offsetType": "none",
"offset": "1",
"multiplier": 60000,
"days": "*",
"months": "*"
},
"timeMax": {
"type": "entered",
"value": "23:15",
"offsetType": "none",
"offset": "1",
"multiplier": 60000
},
"description": "<div><i class=\"fa fa-clock-o\" aria-hidden=\"true\"></i> ↧ von <var>bürgerliche Abenddämmerung</var><div class=\"indent-time-text\"><i class=\"fa fa-step-forward\" aria-hidden=\"true\"></i> <span>spätestens (max)</span> <var>23:15</var></div></div><div><div class=\"indent-level-text\"> <i class=\"fa fa-angle-down\" aria-hidden=\"true\"></i><span>Rollladenposition: </span> ↕ Absolut <var>geschlossen (min)</var></div></div>"
}
],
"sunControlMode": "2",
"sunControlMode": 16,
"sunFloorLengthType": "num",
"sunFloorLength": "0.6",
"sunMinAltitude": "",
"sunMinDelta": "0.1",

@@ -731,43 +531,30 @@ "blindPosMin": "closed (min)",

"blindPosMaxType": "levelFixed",
"sunSlat": "",
"sunSlatType": "none",
"smoothTime": "",
"sunTopic": "",
"windowTopType": "num",
"windowTop": "1.28",
"windowBottomType": "num",
"windowBottom": "0",
"windowAzimuthStartType": "numAzimuth",
"windowAzimuthStart": "70",
"windowAzimuthEndType": "numAzimuth",
"windowAzimuthEnd": "150",
"oversteerValue": "",
"oversteerValueType": "none",
"oversteerCompare": "gte",
"oversteerThreshold": "50",
"oversteerThresholdType": "num",
"oversteerBlindPos": "open (max)",
"oversteerBlindPosType": "levelFixed",
"oversteer2Value": "",
"oversteer2ValueType": "none",
"oversteer2Compare": "gte",
"oversteer2Threshold": "",
"oversteer2ThresholdType": "num",
"oversteer2BlindPos": "open (max)",
"oversteer2BlindPosType": "levelFixed",
"oversteer3Value": "",
"oversteer3ValueType": "none",
"oversteer3Compare": "gte",
"oversteer3Threshold": "",
"oversteer3ThresholdType": "num",
"oversteer3BlindPos": "open (max)",
"oversteer3BlindPosType": "levelFixed",
"oversteers": [],
"oversteerTopic": "",
"x": 870,
"y": 4140,
"x": 750,
"y": 1060,
"wires": [
[
"e92d6413.317dc8"
]
"6c876fb5569b72c1"
],
[]
]
},
{
"id": "e92d6413.317dc8",
"id": "6c876fb5569b72c1",
"type": "debug",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "Blind position",

@@ -780,11 +567,11 @@ "active": true,

"targetType": "full",
"x": 1115,
"y": 4140,
"x": 995,
"y": 1060,
"wires": []
},
{
"id": "60ed6aa.786c594",
"id": "4e86bf5fa7ce9eb4",
"type": "change",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "dayInfo.today.isWeekendOrHoliday",

@@ -805,4 +592,4 @@ "rules": [

"reg": false,
"x": 945,
"y": 4215,
"x": 825,
"y": 1135,
"wires": [

@@ -813,6 +600,6 @@ []

{
"id": "512d7d7c.cc4324",
"id": "4bda9eccdbfdb495",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -826,7 +613,7 @@ "repeat": "",

"payloadType": "bool",
"x": 675,
"y": 4215,
"x": 555,
"y": 1135,
"wires": [
[
"60ed6aa.786c594"
"4e86bf5fa7ce9eb4"
]

@@ -836,6 +623,6 @@ ]

{
"id": "5274fe0b.5c87b",
"id": "bfa382b93bd597ad",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -849,7 +636,7 @@ "repeat": "",

"payloadType": "bool",
"x": 675,
"y": 4260,
"x": 555,
"y": 1180,
"wires": [
[
"60ed6aa.786c594"
"4e86bf5fa7ce9eb4"
]

@@ -859,6 +646,6 @@ ]

{
"id": "5f5128b8.b203b8",
"id": "c2682807c38e7984",
"type": "change",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "dayInfo.tomorrow.isWeekendOrHoliday",

@@ -879,4 +666,4 @@ "rules": [

"reg": false,
"x": 955,
"y": 4305,
"x": 835,
"y": 1225,
"wires": [

@@ -887,6 +674,6 @@ []

{
"id": "7b462ced.4cb384",
"id": "d2ee545cee421e7d",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -900,7 +687,7 @@ "repeat": "",

"payloadType": "bool",
"x": 675,
"y": 4305,
"x": 555,
"y": 1225,
"wires": [
[
"5f5128b8.b203b8"
"c2682807c38e7984"
]

@@ -910,6 +697,6 @@ ]

{
"id": "ad40d513.0245c8",
"id": "f1cff356b43f2361",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -923,7 +710,7 @@ "repeat": "",

"payloadType": "bool",
"x": 675,
"y": 4350,
"x": 555,
"y": 1270,
"wires": [
[
"5f5128b8.b203b8"
"c2682807c38e7984"
]

@@ -933,6 +720,6 @@ ]

{
"id": "b1237bf5.0feeb8",
"id": "950ddb2bda38827c",
"type": "change",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -953,7 +740,7 @@ "rules": [

"reg": false,
"x": 990,
"y": 4395,
"x": 870,
"y": 1315,
"wires": [
[
"df4683fb.c9728"
"12fc3eb929f5fa03"
]

@@ -963,6 +750,6 @@ ]

{
"id": "3d75aed5.6e8442",
"id": "5945cf207c1f9d75",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -976,7 +763,7 @@ "repeat": "",

"payloadType": "bool",
"x": 705,
"y": 4395,
"x": 585,
"y": 1315,
"wires": [
[
"b1237bf5.0feeb8"
"950ddb2bda38827c"
]

@@ -986,6 +773,6 @@ ]

{
"id": "9ded5223.d994f",
"id": "bc0b1a95c3c96bba",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -999,7 +786,7 @@ "repeat": "",

"payloadType": "bool",
"x": 725,
"y": 4440,
"x": 605,
"y": 1360,
"wires": [
[
"b1237bf5.0feeb8"
"950ddb2bda38827c"
]

@@ -1009,16 +796,16 @@ ]

{
"id": "bf7f9c40.0ee1a",
"id": "540c58172e24984e",
"type": "link in",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "do_refreshBlind_state",
"links": [
"df4683fb.c9728",
"12fc3eb929f5fa03",
"dba49bc7.8be158"
],
"x": 550,
"y": 4065,
"x": 430,
"y": 985,
"wires": [
[
"b1a35885.089b38"
"ae28974eb66d7e01"
]

@@ -1028,19 +815,19 @@ ]

{
"id": "df4683fb.c9728",
"id": "12fc3eb929f5fa03",
"type": "link out",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "trigger_refreshBlind_state",
"links": [
"bf7f9c40.0ee1a"
"540c58172e24984e"
],
"x": 1195,
"y": 4395,
"x": 1075,
"y": 1315,
"wires": []
},
{
"id": "5d4d287b.8ac1f8",
"id": "77af066a2c94381b",
"type": "change",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -1061,7 +848,7 @@ "rules": [

"reg": false,
"x": 970,
"y": 4485,
"x": 850,
"y": 1405,
"wires": [
[
"df4683fb.c9728"
"12fc3eb929f5fa03"
]

@@ -1071,6 +858,6 @@ ]

{
"id": "bab47071.c4815",
"id": "147b4386c49ec7cc",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -1084,7 +871,7 @@ "repeat": "",

"payloadType": "bool",
"x": 695,
"y": 4485,
"x": 575,
"y": 1405,
"wires": [
[
"5d4d287b.8ac1f8"
"77af066a2c94381b"
]

@@ -1094,6 +881,6 @@ ]

{
"id": "8268cecb.a1615",
"id": "41297f15f6a5173b",
"type": "inject",
"z": "9e1a7786.dff708",
"g": "36a278a8.1d1df8",
"z": "c224c971b366d1da",
"g": "c76466a96ba836b1",
"name": "",

@@ -1107,7 +894,7 @@ "repeat": "",

"payloadType": "bool",
"x": 705,
"y": 4530,
"x": 585,
"y": 1450,
"wires": [
[
"5d4d287b.8ac1f8"
"77af066a2c94381b"
]

@@ -1114,0 +901,0 @@ ]

@@ -1,1 +0,341 @@

[{"id":"d3c04d4e.ce3e3","type":"debug","z":"de4e9c38.0d942","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":2100,"wires":[]},{"id":"586e4ae2.5b4f14","type":"debug","z":"de4e9c38.0d942","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":2160,"wires":[]},{"id":"1b71d0e5.35b02f","type":"debug","z":"de4e9c38.0d942","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":570,"y":2220,"wires":[]},{"id":"3e4d36c0.620e7a","type":"time-inject","z":"de4e9c38.0d942","name":"","positionConfig":"bdf7c4a.9ca6c38","time":"nadir","timeType":"pdsTime","timeDays":"*","offset":0,"offsetMultiplier":60,"payload":"","payloadType":"date","topic":"","x":320,"y":2100,"wires":[["d3c04d4e.ce3e3"]]},{"id":"c11713e.db07ef","type":"time-inject","z":"de4e9c38.0d942","name":"","positionConfig":"bdf7c4a.9ca6c38","time":"dawn","timeType":"pdsTime","timeDays":"*","offset":0,"offsetMultiplier":60,"payload":"","payloadType":"date","topic":"","x":320,"y":2160,"wires":[["586e4ae2.5b4f14"]]},{"id":"b227cadc.dcf8c8","type":"time-inject","z":"de4e9c38.0d942","name":"","positionConfig":"bdf7c4a.9ca6c38","time":"rise","timeType":"pdmTime","timeDays":"1,4,0","offset":0,"offsetMultiplier":60,"payload":"{\"bool\":true}","payloadType":"json","topic":"","x":340,"y":2220,"wires":[["1b71d0e5.35b02f"]]},{"id":"bdf7c4a.9ca6c38","type":"position-config","z":"","name":"","longitude":"13.71587","latitude":"51.01732","angleType":"deg"}]
[
{
"id": "d3c04d4e.ce3e3",
"type": "debug",
"z": "c224c971b366d1da",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"x": 710,
"y": 2140,
"wires": []
},
{
"id": "586e4ae2.5b4f14",
"type": "debug",
"z": "c224c971b366d1da",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"x": 710,
"y": 2200,
"wires": []
},
{
"id": "1b71d0e5.35b02f",
"type": "debug",
"z": "c224c971b366d1da",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"x": 710,
"y": 2260,
"wires": []
},
{
"id": "3e4d36c0.620e7a",
"type": "time-inject",
"z": "c224c971b366d1da",
"name": "",
"nameInt": "⏲ nadir = timestamp↷",
"positionConfig": "",
"props": [
{
"p": "",
"pt": "msgPayload",
"v": "",
"vt": "date",
"o": "1",
"oT": "num",
"oM": "60000",
"f": 0,
"fS": 0,
"fT": "UNIX timestamp (ms)",
"fI": "0",
"next": true,
"days": "*",
"months": "*",
"onlyOddDays": false,
"onlyEvenDays": false,
"onlyOddWeeks": false,
"onlyEvenWeeks": false
},
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "str",
"o": "1",
"oT": "none",
"oM": "60000",
"f": 0,
"fS": 0,
"fT": "UNIX timestamp (ms)",
"fI": "0",
"next": false,
"days": "*",
"months": "*",
"onlyOddDays": false,
"onlyEvenDays": false,
"onlyOddWeeks": false,
"onlyEvenWeeks": false
}
],
"injectTypeSelect": "time",
"intervalCount": 1,
"intervalCountType": "num",
"intervalCountMultiplier": 60000,
"intervalStart": "2021-09-19T17:04:00.000Z",
"time": "nadir",
"timeType": "pdsTime",
"offset": 0,
"offsetType": "none",
"offsetMultiplier": 60000,
"timeEnd": "",
"timeEndType": "entered",
"timeEndOffset": 0,
"timeEndOffsetType": "num",
"timeEndOffsetMultiplier": 60000,
"timeDays": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeOnlyOddWeeks": false,
"timeOnlyEvenWeeks": false,
"timeMonths": "*",
"timedatestart": "",
"timedateend": "",
"property": "",
"propertyType": "none",
"propertyCompare": "true",
"propertyThreshold": "",
"propertyThresholdType": "num",
"timeAlt": "",
"timeAltType": "entered",
"timeAltDays": "*",
"timeAltOnlyOddDays": false,
"timeAltOnlyEvenDays": false,
"timeAltOnlyOddWeeks": false,
"timeAltOnlyEvenWeeks": false,
"timeAltMonths": "*",
"timeAltOffset": 0,
"timeAltOffsetType": "num",
"timeAltOffsetMultiplier": 60000,
"once": false,
"onceDelay": "",
"recalcTime": "",
"x": 370,
"y": 2140,
"wires": [
[
"d3c04d4e.ce3e3"
]
]
},
{
"id": "c11713e.db07ef",
"type": "time-inject",
"z": "c224c971b366d1da",
"name": "",
"nameInt": "⏲ civil dawn = timestamp↷",
"positionConfig": "",
"props": [
{
"p": "",
"pt": "msgPayload",
"v": "",
"vt": "date",
"o": "1",
"oT": "num",
"oM": "60000",
"f": 0,
"fS": 0,
"fT": "UNIX timestamp (ms)",
"fI": "0",
"next": true,
"days": "*",
"months": "*",
"onlyOddDays": false,
"onlyEvenDays": false,
"onlyOddWeeks": false,
"onlyEvenWeeks": false
},
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "str",
"o": "1",
"oT": "none",
"oM": "60000",
"f": 0,
"fS": 0,
"fT": "UNIX timestamp (ms)",
"fI": "0",
"next": false,
"days": "*",
"months": "*",
"onlyOddDays": false,
"onlyEvenDays": false,
"onlyOddWeeks": false,
"onlyEvenWeeks": false
}
],
"injectTypeSelect": "time",
"intervalCount": 1,
"intervalCountType": "num",
"intervalCountMultiplier": 60000,
"intervalStart": "2021-09-19T17:05:00.000Z",
"time": "civilDawn",
"timeType": "pdsTime",
"offset": 0,
"offsetType": "none",
"offsetMultiplier": 60000,
"timeEnd": "",
"timeEndType": "entered",
"timeEndOffset": 0,
"timeEndOffsetType": "num",
"timeEndOffsetMultiplier": 60000,
"timeDays": "*",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeOnlyOddWeeks": false,
"timeOnlyEvenWeeks": false,
"timeMonths": "*",
"timedatestart": "",
"timedateend": "",
"property": "",
"propertyType": "none",
"propertyCompare": "true",
"propertyThreshold": "",
"propertyThresholdType": "num",
"timeAlt": "",
"timeAltType": "entered",
"timeAltDays": "*",
"timeAltOnlyOddDays": false,
"timeAltOnlyEvenDays": false,
"timeAltOnlyOddWeeks": false,
"timeAltOnlyEvenWeeks": false,
"timeAltMonths": "*",
"timeAltOffset": 0,
"timeAltOffsetType": "num",
"timeAltOffsetMultiplier": 60000,
"once": false,
"onceDelay": "",
"recalcTime": "",
"x": 380,
"y": 2200,
"wires": [
[
"586e4ae2.5b4f14"
]
]
},
{
"id": "b227cadc.dcf8c8",
"type": "time-inject",
"z": "c224c971b366d1da",
"name": "",
"nameInt": "⏲ moon rise[Sun,Mon,Thu] = {\"bool\":true}↷↷",
"positionConfig": "",
"props": [
{
"p": "",
"pt": "msgPayload",
"v": "{\"bool\":true}",
"vt": "json",
"o": "1",
"oT": "num",
"oM": "60000",
"f": 0,
"fS": 0,
"fT": "UNIX timestamp (ms)",
"fI": "0",
"next": true,
"days": "*",
"months": "*",
"onlyOddDays": false,
"onlyEvenDays": false,
"onlyOddWeeks": false,
"onlyEvenWeeks": false
},
{
"p": "",
"pt": "msgTopic",
"v": "",
"vt": "str",
"o": "1",
"oT": "none",
"oM": "60000",
"f": 0,
"fS": 0,
"fT": "UNIX timestamp (ms)",
"fI": "0",
"next": false,
"days": "*",
"months": "*",
"onlyOddDays": false,
"onlyEvenDays": false,
"onlyOddWeeks": false,
"onlyEvenWeeks": false
}
],
"injectTypeSelect": "time",
"intervalCount": 1,
"intervalCountType": "num",
"intervalCountMultiplier": 60000,
"intervalStart": "2021-09-19T17:05:00.000Z",
"time": "rise",
"timeType": "pdmTime",
"offset": 0,
"offsetType": "none",
"offsetMultiplier": 60000,
"timeEnd": "",
"timeEndType": "entered",
"timeEndOffset": 0,
"timeEndOffsetType": "num",
"timeEndOffsetMultiplier": 60000,
"timeDays": "1,4,0",
"timeOnlyOddDays": false,
"timeOnlyEvenDays": false,
"timeOnlyOddWeeks": false,
"timeOnlyEvenWeeks": false,
"timeMonths": "*",
"timedatestart": "",
"timedateend": "",
"property": "",
"propertyType": "none",
"propertyCompare": "true",
"propertyThreshold": "",
"propertyThresholdType": "num",
"timeAlt": "",
"timeAltType": "entered",
"timeAltDays": "*",
"timeAltOnlyOddDays": false,
"timeAltOnlyEvenDays": false,
"timeAltOnlyOddWeeks": false,
"timeAltOnlyEvenWeeks": false,
"timeAltMonths": "*",
"timeAltOffset": 0,
"timeAltOffsetType": "num",
"timeAltOffsetMultiplier": 60000,
"once": false,
"onceDelay": "",
"recalcTime": "",
"x": 440,
"y": 2260,
"wires": [
[
"1b71d0e5.35b02f"
]
]
}
]

@@ -9,6 +9,8 @@ /********************************************

const util = require('util');
const clonedeep = require('lodash.clonedeep');
const isEqual = require('lodash.isequal');
const cRuleUntil = 0;
const cRuleFrom = 1;
// const cRuleAbsolute = 0;
const cRuleDefault = -1;

@@ -20,11 +22,9 @@ /******************************************************************************************/

/**
/**
* check if a manual overwrite should be set
* @param {*} node node data
* @param {*} msg message object
* @param {ITimeObject} oNow the *current* date Object
* @returns {boolean} true if override is active, otherwise false
*/
function checkPosOverwrite(node, msg, dNow) {
function checkPosOverwrite(node, msg, oNow) {
// node.debug(`checkPosOverwrite act=${node.nodeData.overwrite.active} `);

@@ -39,6 +39,6 @@ let isSignificant = false;

}
ctrlLib.checkOverrideReset(node, msg, dNow, isSignificant);
ctrlLib.checkOverrideReset(node, msg, oNow, isSignificant);
return p;
}, () => {
ctrlLib.checkOverrideReset(node, msg, dNow, true);
ctrlLib.checkOverrideReset(node, msg, oNow, true);
return 0;

@@ -62,6 +62,12 @@ });

if (msg.topic && (msg.topic.includes('manual') ||
msg.topic.includes('overwrite'))) {
msg.topic.includes('overwrite') ||
(msg.topic.includes('Overwrite') && !msg.topic.includes('resetOverwrite')))) {
overrideData = msg.payload;
overrideTopic = msg.topic;
} else if (typeof msg.payload === 'object' && (msg.payload.value && (msg.payload.expires || msg.payload.importance || msg.payload.importance))) {
} else if (typeof msg.payload === 'object' &&
(msg.payload.value && (msg.payload.expire ||
msg.payload.importance ||
msg.payload.resetOnSameAsLastValue ||
msg.payload.ignoreSameValue ||
msg.payload.overwrite === true))) {
overrideData = msg.payload.value;

@@ -77,13 +83,22 @@ overrideTopic = msg.topic;

if (typeof overrideData !== 'undefined') {
node.debug(`needOverwrite importance=${nImportance} expire=${nExpire}`);
if (typeof overrideData !== 'undefined') {
node.debug(`overwrite overrideData=${overrideData}`);
node.payload.current = overrideData;
node.payload.topic = overrideTopic;
const rosalv = hlp.getMsgBoolValue(msg, 'resetOnSameAsLastValue');
const isv = hlp.getMsgBoolValue(msg, 'ignoreSameValue');
node.debug(`needOverwrite importance=${nImportance} expire=${nExpire} resetOnSameAsLastValue=${rosalv} ignoreSameValue=${isv}`);
if (rosalv && isEqual(node.previousData.payloadValue, overrideData)) {
node.debug(`resetOnSameAsLastValue active, reset overwrite and exit overrideData=${overrideData}`);
ctrlLib.posOverwriteReset(node);
return ctrlLib.setOverwriteReason(node);
} else if (isv && isEqual(node.previousData.payloadValue, overrideData)) {
node.debug(`overwrite exit true (ignoreSameValue), overrideData=${overrideData}`);
return ctrlLib.setOverwriteReason(node);
}
node.debug(`overwrite overrideData=${overrideData}`);
node.payload.current = overrideData;
node.payload.topic = overrideTopic;
if (Number.isFinite(nExpire) || (nImportance <= 0)) {
// will set expiring if importance is 0 or if expire is explizit defined
node.debug(`set expiring - expire is explizit defined "${nExpire}"`);
ctrlLib.setExpiringOverwrite(node, dNow, nExpire, 'set expiring time by message');
node.debug(`set expiring - expire is explicit defined "${nExpire}"`);
ctrlLib.setExpiringOverwrite(node, oNow, nExpire, 'set expiring time by message');
} else if ((!exactImportance && (node.nodeData.overwrite.importance < nImportance)) || (!node.nodeData.overwrite.expireTs)) {

@@ -93,3 +108,3 @@ // isSignificant

node.debug(`no expire defined, using default or will not expire`);
ctrlLib.setExpiringOverwrite(node, dNow, NaN, 'no special expire defined');
ctrlLib.setExpiringOverwrite(node, oNow, NaN, 'no special expire defined');
}

@@ -100,2 +115,3 @@ if (nImportance > 0) {

node.nodeData.overwrite.active = true;
node.context().set('overwrite', node.nodeData.overwrite, node.contextStore);
} else if (node.nodeData.overwrite.active) {

@@ -106,3 +122,3 @@ node.debug(`overwrite active, check of nImportance=${nImportance} or nExpire=${nExpire}`);

// set to new expiring time
ctrlLib.setExpiringOverwrite(node, dNow, nExpire, 'set new expiring time by message');
ctrlLib.setExpiringOverwrite(node, oNow, nExpire, 'set new expiring time by message');
}

@@ -113,2 +129,3 @@ if (nImportance > 0) {

}
node.context().set('overwrite', node.nodeData.overwrite, node.contextStore);
}

@@ -120,87 +137,34 @@ // node.debug(`overwrite exit node.nodeData.overwrite.active=${node.nodeData.overwrite.active}; expire=${nExpire}`);

/******************************************************************************************/
/**
* changes the rule settings
* @param {Object} node node data
* @param {number} [rulePos] the position of the rule which should be changed
* @param {string} [ruleName] the name of the rule which should be changed
* @param {Object} ruleData the properties of the rule which should be changed
*/
function changeRules(node, rulePos, ruleName, ruleData) {
node.debug(`changeRules: ${ node.rules.count } ruleData:' ${util.inspect(ruleData, {colors:true, compact:10})}`);
for (let i = 0; i <= node.rules.count; ++i) {
const rule = node.rules[i];
if (((typeof rulePos !== 'undefined') && rule.pos === rulePos) ||
((typeof ruleName !== 'undefined') && rule.name === ruleName)) {
node.rules[i] = Object.assign(node.rules[i], ruleData);
}
}
}
/******************************************************************************************/
/**
* check all rules and determinate the active rule
* @param {Object} node node data
* @param {Object} msg the message object
* @param {Date} dNow the *current* date Object
* @param {ITimeObject} oNow the *current* date Object
* @param {Object} tempData the object storing the temporary caching data
* @returns the active rule or null
*/
function checkRules(node, msg, dNow, tempData) {
function checkRules(node, msg, oNow, tempData) {
// node.debug('checkRules --------------------');
const livingRuleData = {};
const nowNr = dNow.getTime();
const dayNr = dNow.getDay();
const dateNr = dNow.getDate();
const monthNr = dNow.getMonth();
const dayId = hlp.getDayId(dNow);
ctrlLib.prepareRules(node, msg, tempData);
// node.debug(`checkRules dNow=${dNow.toISOString()}, nowNr=${nowNr}, dayNr=${dayNr}, dateNr=${dateNr}, monthNr=${monthNr}, dayId=${dayId}, rules.count=${node.rules.count}, rules.lastUntil=${node.rules.lastUntil}`);
ctrlLib.prepareRules(node, msg, tempData, oNow.dNow);
// node.debug(`checkRules rules.count=${node.rules.count}, rules.lastUntil=${node.rules.lastUntil}, oNow=${util.inspect(oNow, {colors:true, compact:10})}`);
/**
* Timestamp compare function
* @name ICompareTimeStamp
* @function
* @param {number} timeStamp The timestamp which should be compared
* @returns {Boolean} return true if if the timestamp is valid, otherwise false
*/
/**
* function to check a rule
* @param {object} rule a rule object to test
* @param {ICompareTimeStamp} cmp a function to compare two timestamps.
* @returns {Object|null} returns the rule if rule is valid, otherwhise null
*/
const fktCheck = (rule, cmp) => {
// node.debug('fktCheck rule ' + util.inspect(rule, {colors:true, compact:10}));
if (rule.conditional) {
try {
if (!rule.conditon.result) {
return null;
}
} catch (err) {
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.getPropertyData', err));
node.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
return null;
}
}
if (!rule.timeLimited) {
return rule;
}
if (rule.timeDays && rule.timeDays !== '*' && !rule.timeDays.includes(dayNr)) {
return null;
}
if (rule.timeMonths && rule.timeMonths !== '*' && !rule.timeMonths.includes(monthNr)) {
return null;
}
if (rule.timeOnlyOddDays && (dateNr % 2 === 0)) { // even
return null;
}
if (rule.timeOnlyEvenDays && (dateNr % 2 !== 0)) { // odd
return null;
}
if (rule.timeDateStart || rule.timeDateEnd) {
rule.timeDateStart.setFullYear(dNow.getFullYear());
rule.timeDateEnd.setFullYear(dNow.getFullYear());
if (rule.timeDateEnd > rule.timeDateStart) {
// in the current year
if (dNow < rule.timeDateStart || dNow > rule.timeDateEnd) {
return null;
}
} else {
// switch between year from end to start
if (dNow < rule.timeDateStart && dNow > rule.timeDateEnd) {
return null;
}
}
}
const num = ctrlLib.getRuleTimeData(node, msg, rule, dNow);
// node.debug(`pos=${rule.pos} type=${rule.timeOpText} - ${rule.timeValue} - num=${num} - rule.timeData = ${ util.inspect(rule.timeData, { colors: true, compact: 40, breakLength: Infinity }) }`);
if (dayId === rule.timeData.dayId && num >=0 && (cmp(num) === true)) {
return rule;
}
return null;
};
let ruleSel = null;

@@ -211,10 +175,11 @@ let ruleindex = -1;

const rule = node.rules.data[i];
// node.debug('rule ' + rule.timeOp + ' - ' + (rule.timeOp !== cRuleFrom) + ' - ' + util.inspect(rule, {colors:true, compact:10, breakLength: Infinity }));
if (rule.timeOp === cRuleFrom) { continue; }
// node.debug('rule ' + rule.time.operator + ' - ' + (rule.time.operator !== cRuleFrom) + ' - ' + util.inspect(rule, {colors:true, compact:10, breakLength: Infinity }));
if (!rule.enabled) { continue; }
if (rule.time && rule.time.operator === cRuleFrom) { continue; }
// const res = fktCheck(rule, r => (r >= nowNr));
let res = null;
if (rule.timeOp === cRuleFrom) {
res = fktCheck(rule, r => (r <= nowNr));
if (!rule.time || rule.time.operator === cRuleFrom) {
res = ctrlLib.compareRules(node, msg, rule, r => (r <= oNow.nowNr), oNow);
} else {
res = fktCheck(rule, r => (r >= nowNr));
res = ctrlLib.compareRules(node, msg, rule, r => (r >= oNow.nowNr), oNow);
}

@@ -225,3 +190,3 @@ if (res) {

ruleindex = i;
if (rule.timeOp !== cRuleFrom) {
if (rule.time && rule.time.operator !== cRuleFrom) {
break;

@@ -232,9 +197,10 @@ }

if (!ruleSel || (ruleSel.timeOp === cRuleFrom) ) {
if (!ruleSel || (ruleSel.time && ruleSel.time.operator === cRuleFrom) ) {
// node.debug('--------- starting second loop ' + node.rules.count);
for (let i = (node.rules.count - 1); i >= 0; --i) {
const rule = node.rules.data[i];
// node.debug('rule ' + rule.timeOp + ' - ' + (rule.timeOp !== cRuleUntil) + ' - ' + util.inspect(rule, {colors:true, compact:10, breakLength: Infinity }));
if (rule.timeOp === cRuleUntil) { continue; } // - From: timeOp === cRuleFrom
const res = fktCheck(rule, r => (r <= nowNr));
// node.debug('rule ' + rule.time.operator + ' - ' + (rule.time.operator !== cRuleUntil) + ' - ' + util.inspect(rule, {colors:true, compact:10, breakLength: Infinity }));
if (!rule.enabled) { continue; }
if (rule.time && rule.time.operator === cRuleUntil) { continue; } // - From: timeOp === cRuleFrom
const res = ctrlLib.compareRules(node, msg, rule, r => (r <= oNow.nowNr), oNow);
if (res) {

@@ -249,9 +215,9 @@ // node.debug('2. ruleSel ' + util.inspect(res, { colors: true, compact: 10, breakLength: Infinity }));

const checkRuleForAT = rule => {
if (!rule.timeLimited) {
if (!rule.time) {
return;
}
const num = ctrlLib.getRuleTimeData(node, msg, rule, dNow);
if (num > nowNr) {
const num = ctrlLib.getRuleTimeData(node, msg, rule, oNow);
if (num > oNow.nowNr) {
node.debug('autoTrigger set to rule ' + rule.pos);
const diff = num - nowNr;
const diff = num - oNow.nowNr;
node.autoTrigger.time = Math.min(node.autoTrigger.time, diff);

@@ -263,5 +229,5 @@ node.autoTrigger.type = 2; // next rule

if (node.autoTrigger) {
if (ruleSel.timeLimited && ruleSel.timeData.ts > nowNr) {
if (ruleSel.time && ruleSel.timeData.ts > oNow.nowNr) {
node.debug('autoTrigger set to rule ' + ruleSel.pos + ' (current)');
const diff = ruleSel.timeData.ts - nowNr;
const diff = ruleSel.timeData.ts - oNow.nowNr;
node.autoTrigger.time = Math.min(node.autoTrigger.time, diff);

@@ -272,3 +238,3 @@ node.autoTrigger.type = 1; // current rule end

const rule = node.rules.data[i];
if (!rule.timeLimited) {
if (!rule.time) {
continue;

@@ -298,12 +264,4 @@ }

livingRuleData.conditional = ruleSel.conditional;
livingRuleData.timeLimited = ruleSel.timeLimited;
livingRuleData.payloadData = {
type: ruleSel.payloadType,
value: ruleSel.payloadValue,
format: ruleSel.payloadFormat,
offsetType: ruleSel.payloadOffsetType,
offset: ruleSel.payloadOffsetValue,
multiplier: ruleSel.payloadOffsetMultiplier,
next: true
};
livingRuleData.timeLimited = (!!ruleSel.time);
livingRuleData.payloadData = ruleSel.payload;
const data = { number: ruleSel.pos, name: ruleSel.name };

@@ -317,3 +275,3 @@ let name = 'rule';

}
if (ruleSel.timeLimited) {
if (ruleSel.time) {
livingRuleData.time = ruleSel.timeData;

@@ -324,3 +282,3 @@ livingRuleData.time.timeLocal = node.positionConfig.toTimeString(ruleSel.timeData.value);

livingRuleData.time.dateUTC= ruleSel.timeData.value.toUTCString();
data.timeOp = ruleSel.timeOpText;
data.timeOp = ruleSel.time.operatorText;
data.timeLocal = livingRuleData.time.timeLocal;

@@ -336,3 +294,3 @@ data.time = livingRuleData.time.dateISO;

livingRuleData.active = false;
livingRuleData.id = -1;
livingRuleData.id = cRuleDefault;
livingRuleData.importance = 0;

@@ -377,13 +335,30 @@ livingRuleData.resetOverwrite = false;

const node = this;
// node.myNamename = config.name;
this.debug(`starting ${config.name}, name = ${node.name}`);
if (!Array.isArray(config.results)) {
config.results = [{
p: '',
pt: 'msgPayload',
v: '',
vt: 'payload'
},
{
p: '',
pt: 'msgTopic',
v: '',
vt: 'topic'
},
{
p: 'timeCtrl',
pt: 'msg',
v: 'full',
vt: 'ctrlObj'
}];
}
if (config.autoTrigger) {
node.autoTrigger = {
defaultTime : config.autoTriggerTime || 20 * 60000 // 20min
defaultTime : parseInt(config.autoTriggerTime) || 20 * 60000 // 20min
};
node.autoTriggerObj = null;
}
node.nowarn = {};

@@ -396,3 +371,3 @@ node.reason = {

// temporary node Data
node.storeName = config.storeName || '';
node.contextStore = config.contextStore || this.positionConfig.contextStore;
node.nodeData = {

@@ -406,10 +381,12 @@ /** The Level of the window */

payloadDefaultOffsetMultiplier: config.payloadDefaultOffsetMultiplier,
topic:config.topic,
topic: config.topic,
addId: config.addId,
addIdType: config.addIdType||'none',
/** The override settings */
overwrite: {
overwrite: node.context().get('overwrite', node.contextStore) || {
active: false,
expireDuration: parseFloat(hlp.chkValueFilled(config.overwriteExpire, NaN)),
importance: 0
}
};
node.nodeData.overwrite.expireDuration = parseFloat(hlp.chkValueFilled(config.overwriteExpire, NaN));

@@ -490,7 +467,19 @@ node.rules = {

case 'setAutoTriggerTime':
node.autoTrigger.defaultTime = parseFloat(msg.payload) || node.autoTrigger.defaultTime;
node.autoTrigger.defaultTime = parseInt(msg.payload) || node.autoTrigger.defaultTime;
break;
case 'setStoreName':
node.storeName = msg.payload || node.storeName;
case 'setCntextStore':
node.contextStore = msg.payload || node.contextStore;
break;
case 'disableRule':
changeRules(node, undefined, msg.payload, { enabled: false });
break;
case 'enableRule':
changeRules(node, undefined, msg.payload, { enabled: true });
break;
case 'disableRuleByPos':
changeRules(node, parseInt(msg.payload), undefined, { enabled: false });
break;
case 'enableRuleByPos':
changeRules(node, parseInt(msg.payload), undefined, { enabled: true });
break;
default:

@@ -503,15 +492,10 @@ break;

node.nowarn = {};
const tempData = node.context().get('cacheData',node.storeName) || {};
node.previousData.payloadType = (typeof node.payload.current);
const tempData = node.context().get('cacheData',node.contextStore) || {};
node.previousData.reasonCode = node.reason.code;
node.previousData.reasonState = node.reason.state;
node.previousData.reasonDescription = node.reason.description;
if (node.previousData.payloadType === 'string' ||
node.previousData.payloadType === 'boolean' ||
node.previousData.payloadType === 'number') {
node.previousData.payloadValue = node.payload.current;
node.previousData.payloadSimple = true;
}
node.previousData.payloadValue = clonedeep(node.payload.current);
node.reason.code = NaN;
const dNow = hlp.getNowTimeStamp(node, msg);
const oNow = hlp.getNowObject(node, msg);
if (node.autoTrigger) {

@@ -522,16 +506,29 @@ node.autoTrigger.time = node.autoTrigger.defaultTime;

// check if the message contains any oversteering data
if (node.nodeData.addIdType !== 'none') {
node.addId = node.positionConfig.getPropValue(node, msg, {
type: node.nodeData.addIdType,
value: node.nodeData.addId,
callback: (result, _obj) => {
if (result !== null && typeof result !== 'undefined') {
tempData[_obj.type + '.' + _obj.value] = result;
}
}
}, true, oNow.dNow);
}
const timeCtrl = {
reason : node.reason,
timeClock : node.nodeData,
autoTrigger : node.autoTrigger,
lastEvaluated: node.previousData.last,
name: node.name || node.id,
id: node.id
id: node.addId || node.id
};
let ruleId = -2;
// check for manual overwrite
let overwrite = checkPosOverwrite(node, msg, dNow);
let overwrite = checkPosOverwrite(node, msg, oNow);
if (!overwrite || node.rules.canResetOverwrite || (node.rules.maxImportance > 0 && node.rules.maxImportance > node.nodeData.overwrite.importance)) {
// calc times:
timeCtrl.rule = checkRules(node, msg, dNow, tempData);
timeCtrl.rule = checkRules(node, msg, oNow, tempData);
node.previousData.last.ruleId = timeCtrl.rule.id;

@@ -548,3 +545,5 @@ node.previousData.last.ruleTopic = timeCtrl.rule.topic;

ruleId = timeCtrl.rule.id;
node.payload.current = node.positionConfig.getOutDataProp(node, msg, timeCtrl.rule.payloadData, dNow);
if (timeCtrl.rule.payloadData) {
node.payload.current = node.positionConfig.getOutDataProp(node, msg, timeCtrl.rule.payloadData, oNow.dNow);
}
node.payload.topic = timeCtrl.rule.topic;

@@ -559,6 +558,2 @@ node.reason.code = timeCtrl.rule.code;

// node.debug(`result manual=${node.nodeData.overwrite.active} reasoncode=${node.reason.code} description=${node.reason.description}`);
timeCtrl.reason = node.reason;
timeCtrl.timeClock = node.nodeData;
if (node.startDelayTimeOut) {

@@ -571,14 +566,14 @@ node.reason.code = NaN;

let topic = node.payload.topic || msg.topic;
const replaceAttrs = {
name: timeCtrl.name,
id: timeCtrl.id,
code: node.reason.code,
state: node.reason.state,
description: node.reason.description,
rule: ruleId,
topic: msg.topic,
payload: msg.payload
};
if (topic) {
const topicAttrs = {
name: timeCtrl.name,
id: timeCtrl.id,
code: node.reason.code,
state: node.reason.state,
rule: ruleId,
newtopic: topic,
topic: msg.topic,
payload: msg.payload
};
topic = hlp.topicReplace(topic, topicAttrs);
topic = hlp.topicReplace(topic, replaceAttrs);
}

@@ -589,28 +584,42 @@

(node.payload.current !== null) &&
!isNaN(node.reason.code) &&
((node.reason.code !== node.previousData.reasonCode) ||
(ruleId !== node.previousData.usedRule) ||
(typeof node.payload.current !== node.previousData.payloadType) ||
((typeof node.previousData.payloadValue !== 'undefined') && (node.previousData.payloadValue !== node.payload.current))) ) {
msg.payload = node.payload.current;
msg.topic = topic;
msg.timeCtrl = timeCtrl;
if (node.outputs > 1) {
send([msg, { topic, payload: timeCtrl, payloadOut: node.payload.current }]);
} else {
send([msg, null]);
((node.payload.topic !== node.previousData.topic) ||
((typeof node.previousData.payloadValue !== 'undefined') && (!isEqual(node.previousData.payloadValue, node.payload.current)))) ) {
const msgOut = {};
for (let i = 0; i < node.results.length; i++) {
const prop = node.results[i];
let resultObj = null;
if (prop.type === 'topic') {
resultObj = topic;
} else if (prop.type === 'payload') {
resultObj = node.payload.current;
} else if (prop.type === 'ctrlObj') {
resultObj = timeCtrl;
} else if (prop.type === 'strPlaceholder') {
resultObj = hlp.topicReplace(''+prop.value, replaceAttrs);
} else {
resultObj = node.positionConfig.getPropValue(this, msg, prop, false, oNow.dNow);
}
if (typeof resultObj !== 'undefined') {
if (resultObj.error) {
this.error('error on getting result: "' + resultObj.error + '"');
} else {
node.positionConfig.setMessageProp(this, msgOut, prop.outType, prop.outValue, resultObj);
}
}
}
} else if (node.outputs > 1) {
send([msgOut, { topic, payload: timeCtrl, payloadOut: node.payload.current }]);
} else {
send([null, { topic, payload: timeCtrl }]);
}
node.previousData.usedRule = ruleId;
node.context().set('cacheData', tempData, node.storeName);
node.context().set('cacheData', tempData, node.contextStore);
if (node.autoTrigger) {
node.debug('------------- autoTrigger ---------------- ' + node.autoTrigger.time + ' - ' + node.autoTrigger.type);
node.debug('next autoTrigger will set to ' + node.autoTrigger.time + ' - ' + node.autoTrigger.type);
if (node.autoTriggerObj) {
clearTimeout(node.autoTriggerObj);
node.autoTriggerObj = null;
delete node.autoTriggerObj;
}
node.autoTriggerObj = setTimeout(() => {
clearTimeout(node.autoTriggerObj);
delete node.autoTriggerObj;
node.emit('input', {

@@ -640,3 +649,3 @@ topic: 'autoTrigger/triggerOnly',

clearTimeout(node.autoTriggerObj);
node.autoTriggerObj = null;
delete node.autoTriggerObj;
}

@@ -660,2 +669,22 @@ // tidy up any state

RED.nodes.registerType('clock-timer', clockTimerNode);
RED.httpAdmin.post('/clock-timer/:id', RED.auth.needsPermission('clock-timer.write'), (req, res) => {
const node = RED.nodes.getNode(req.params.id);
if (node !== null && typeof node !== 'undefined') {
try {
if (req.body && req.body.ruleData) {
changeRules(node, req.body.rulePos, req.body.ruleName, req.body.ruleData);
}
res.sendStatus(200);
} catch(err) {
res.sendStatus(500);
node.error(RED._('node-red:inject.failed',{error:err.toString()}));
}
} else {
res.status(404).send(JSON.stringify({
error: 'can not find node "' +req.params.id+'" '+String(node)
}));
return;
}
});
};

@@ -21,2 +21,3 @@ /*

const rad = Math.PI / 180;
const degr = 180 / Math.PI;

@@ -28,2 +29,96 @@ // date/time constants and conversions

const lunarDaysMs = 2551442778; // The duration in days of a lunar cycle is 29.53058770576
const firstNewMoon2000 = 947178840000; // first newMoon in the year 2000 2000-01-06 18:14
const fractionOfTheMoonCycle = [{
from: 0,
to: 0.033863193308711,
id: 'newMoon',
emoji: '🌚',
code: ':new_moon_with_face:',
name: 'New Moon',
weight: 1,
css: 'wi-moon-new'
},
{
from: 0.033863193308711,
to: 0.216136806691289,
id: 'waxingCrescentMoon',
emoji: '🌒',
code: ':waxing_crescent_moon:',
name: 'Waxing Crescent',
weight: 6.3825,
css: 'wi-moon-wax-cres'
},
{
from: 0.216136806691289,
to: 0.283863193308711,
id: 'firstQuarterMoon',
emoji: '🌓',
code: ':first_quarter_moon:',
name: 'First Quarter',
weight: 1,
css: 'wi-moon-first-quart'
},
{
from: 0.283863193308711,
to: 0.466136806691289,
id: 'waxingGibbousMoon',
emoji: '🌔',
code: ':waxing_gibbous_moon:',
name: 'Waxing Gibbous',
weight: 6.3825,
css: 'wi-moon-wax-gibb'
},
{
from: 0.466136806691289,
to: 0.533863193308711,
id: 'fullMoon',
emoji: '🌝',
code: ':full_moon_with_face:',
name: 'Full Moon',
weight: 1,
css: 'wi-moon-full'
},
{
from: 0.533863193308711,
to: 0.716136806691289,
id: 'waningGibbousMoon',
emoji: '🌖',
code: ':waning_gibbous_moon:',
name: 'Waning Gibbous',
weight: 6.3825,
css: 'wi-moon-wan-gibb'
},
{
from: 0.716136806691289,
to: 0.783863193308711,
id: 'thirdQuarterMoon',
emoji: '🌗',
code: ':last_quarter_moon:',
name: 'third Quarter',
weight: 1,
css: 'wi-moon-third-quart'
},
{
from: 0.783863193308711,
to: 0.966136806691289,
id: 'waningCrescentMoon',
emoji: '🌘',
code: ':waning_crescent_moon:',
name: 'Waning Crescent',
weight: 6.3825,
css: 'wi-moon-wan-cres'
},
{
from: 0.966136806691289,
to: 1,
id: 'newMoon',
emoji: '🌚',
code: ':new_moon_with_face:',
name: 'New Moon',
weight: 1,
css: 'wi-moon-new'
}];
/**

@@ -76,6 +171,6 @@ * convert date from Julian calendar

* @param {number} dec - The declination of the sun
* @returns {number}
* @returns {number} azimuth in rad
*/
function azimuth(H, phi, dec) {
return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi));
function azimuthCalc(H, phi, dec) {
return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)) + Math.PI;
}

@@ -90,3 +185,3 @@

*/
function altitude(H, phi, dec) {
function altitudeCalc(H, phi, dec) {
return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H));

@@ -195,13 +290,13 @@ }

const H = siderealTime(d, lw) - c.ra;
const azimuthr = azimuth(H, phi, c.dec);
const altituder = altitude(H, phi, c.dec);
const azimuth = azimuthCalc(H, phi, c.dec);
const altitude = altitudeCalc(H, phi, c.dec);
// console.log(`getPosition date=${date}, M=${H}, L=${H}, c=${JSON.stringify(c)}, d=${d}, lw=${lw}, phi=${phi}`);
return {
azimuth: azimuthr,
altitude: altituder,
zenith: (90*Math.PI/180) - altituder,
azimuthDegrees: 180 + 180 / Math.PI * azimuthr,
altitudeDegrees: 180 / Math.PI * altituder,
zenithDegrees: 90 - (180 / Math.PI * altituder),
azimuth,
altitude,
zenith: (90*Math.PI/180) - altitude,
azimuthDegrees: degr * azimuth,
altitudeDegrees: degr * altitude,
zenithDegrees: 90 - (degr * altitude),
declination: c.dec

@@ -553,3 +648,3 @@ };

let dateValue = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0).valueOf();
let addval = (dayMs / 2);
let addval = dayMs; // / 2);
dateValue += addval;

@@ -562,3 +657,3 @@

const H = siderealTime(d, lw) - c.ra;
const nazim = azimuth(H, phi, c.dec);
const nazim = azimuthCalc(H, phi, c.dec);

@@ -575,39 +670,2 @@ addval /= 2;

/* SunCalc.getSunDate2 = function (year, month, day, nazimuth, lat, lng) {
if (isNaN(nazimuth)) {
throw new Error('azimuth missing');
}
if (isNaN(lat)) {
throw new Error('latitude missing');
}
if (isNaN(lng)) {
throw new Error('longitude missing');
}
const lw = rad * -lng;
const phi = rad * lat;
let dateValue = new Date(year, month, day, 0, 0, 0).valueOf();
let d = ((dateValue / dayMs) + J1970) - J2000;
console.log(new Date(d));
let addval = (dayMs / 2);
d += addval;
while (addval > 200) {
const c = sunCoords(d);
const H = siderealTime(d, lw) - c.ra;
const nazi = azimuth(H, phi, c.dec);
console.log(d, addval, nazi, nazimuth);
addval /= 2;
if (nazi < nazimuth) {
d += addval;
} else {
d -= addval;
}
}
dateValue = (((d + J2000) - J1970) * dateValue);
return new Date(Math.floor(dateValue));
}; */
// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas

@@ -663,18 +721,18 @@

const H = siderealTime(d, lw) - c.ra;
let h = altitude(H, phi, c.dec);
let altitude = altitudeCalc(H, phi, c.dec);
altitude += astroRefraction(altitude); // altitude correction for refraction
// formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998.
const pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H));
h += astroRefraction(h); // altitude correction for refraction
const azimuth = azimuthCalc(H, phi, c.dec);
const azimuthr = azimuth(H, phi, c.dec);
return {
azimuth: azimuthr,
altitude: h,
azimuthDegrees: 180 + 180 / Math.PI * azimuthr,
altitudeDegrees: 180 / Math.PI * h,
azimuth,
altitude,
azimuthDegrees: degr * azimuth,
altitudeDegrees: degr * altitude,
distance: c.dist,
parallacticAngle: pa,
parallacticAngleDegrees: 180 / Math.PI * pa
parallacticAngleDegrees: degr * pa
};

@@ -684,6 +742,37 @@ };

/**
* @typedef {Object} dateData
* @property {string} date - The Date as a ISO String YYYY-MM-TTTHH:MM:SS.mmmmZ
* @property {number} value - The Date as the milliseconds since 1.1.1970 0:00 UTC
*/
/**
* @typedef {Object} phaseObj
* @property {number} from - The phase start
* @property {number} to - The phase end
* @property {string} id - id of the phase
* @property {string} emoji - unicode symbol of the phase
* @property {string} name - name of the phase
* @property {string} id - phase name
* @property {number} weight - weight of the phase
* @property {string} css - a css value of the phase
*/
/**
* @typedef {Object} nextmoonillum
* @property {number} fraction - The fraction of the moon
* @property {string} date - The Date as a ISO String YYYY-MM-TTTHH:MM:SS.mmmmZ of the next phase
* @property {number} value - The Date as the milliseconds since 1.1.1970 0:00 UTC of the next phase
* @property {string} type - The name of the next phase [newMoon, fullMoon, firstQuarter, thirdQuarter]
* @property {dateData} newMoon - Date of the next new moon
* @property {dateData} fullMoon - Date of the next full moon
* @property {dateData} firstQuarter - Date of the next first quater of the moon
* @property {dateData} thirdQuarter - Date of the next third/last quater of the moon
*/
/**
* @typedef {Object} moonillumination
* @property {number} fraction - The fraction of the moon
* @property {number} phase - The phase of the moon
* @property {number} angle - The angle of the moon
* @property {phaseObj} phase - The phase of the moon
* @property {number} phaseValue - The phase of the moon in the current cycle
* @property {nextmoonillum} next - object containing information about the next phases of the moon
*/

@@ -708,7 +797,57 @@

cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra));
const phaseValue = 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI;
// calculates the difference in ms between the sirst fullMoon 2000 and given Date
const diffBase = dateValue - firstNewMoon2000;
// Calculate modulus to drop completed cycles
let cycleModMs = diffBase % lunarDaysMs;
// If negative number (date before new moon 2000) add lunarDaysMs
if ( cycleModMs < 0 ) { cycleModMs += lunarDaysMs; }
const nextNewMoon = (lunarDaysMs - cycleModMs) + dateValue;
let nextFullMoon = ((lunarDaysMs/2) - cycleModMs) + dateValue;
if (nextFullMoon < dateValue) { nextFullMoon += lunarDaysMs; }
const quater = (lunarDaysMs/4);
let nextFirstQuarter = (quater - cycleModMs) + dateValue;
if (nextFirstQuarter < dateValue) { nextFirstQuarter += lunarDaysMs; }
let nextThirdQuarter = (lunarDaysMs - quater - cycleModMs) + dateValue;
if (nextThirdQuarter < dateValue) { nextThirdQuarter += lunarDaysMs; }
// Calculate the fraction of the moon cycle
// const currentfrac = cycleModMs / lunarDaysMs;
const next = Math.min(nextNewMoon, nextFirstQuarter, nextFullMoon, nextThirdQuarter);
let phase = '';
for (let index = 0; index < fractionOfTheMoonCycle.length; index++) {
const element = fractionOfTheMoonCycle[index];
if ( (phaseValue >= element.from) && (phaseValue <= element.to) ) {
phase = element;
break;
}
}
return {
fraction: (1 + cos(inc)) / 2,
phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI,
angle
// fraction2: cycleModMs / lunarDaysMs,
phase,
phaseValue,
next : {
value: next,
date: (new Date(next)).toISOString(),
type: (next === nextNewMoon) ? 'newMoon' : ((next === nextFirstQuarter) ? 'firstQuarter' : ((next === nextFullMoon) ? 'fullMoon' : 'thirdQuarter')),
newMoon: {
value: nextNewMoon,
date: (new Date(nextNewMoon)).toISOString()
},
fullMoon: {
value: nextFullMoon,
date: (new Date(nextFullMoon)).toISOString()
},
firstQuarter: {
value: nextFirstQuarter,
date: (new Date(nextFirstQuarter)).toISOString()
},
thirdQuarter: {
value: nextThirdQuarter,
date: (new Date(nextThirdQuarter)).toISOString()
}
}
};

@@ -831,2 +970,6 @@ };

}
} else if (rise && set) {
result.alwaysUp = false;
result.alwaysDown = false;
result.highest = new Date(hoursLater(dateValue, Math.min(rise, set) + (Math.abs(set - rise) / 2)));
} else {

@@ -833,0 +976,0 @@ result.alwaysUp = false;

@@ -19,12 +19,12 @@ /********************************************

validPosition,
compareRules,
initializeCtrl
};
const cRuleNoTime = -1;
const cRuleUntil = 0;
const cRuleFrom = 1;
const cRuleAbsolute = 0;
const cRuleNone = 0;
const cRuleMinOversteer = 1; // ⭳❗ minimum (oversteer)
const cRuleMaxOversteer = 2; // ⭱️❗ maximum (oversteer)
// const cRuleNone = 0;
// const cRuleMinOversteer = 1; // ⭳❗ minimum (oversteer)
// const cRuleMaxOversteer = 2; // ⭱️❗ maximum (oversteer)
const cRuleLogOperatorAnd = 2;

@@ -92,2 +92,3 @@ const cRuleLogOperatorOr = 1;

}
node.context().set('overwrite', node.nodeData.overwrite, node.contextStore);
}

@@ -98,7 +99,7 @@

* @param {*} node node data
* @param {Date} dNow the current timestamp
* @param {ITimeObject} oNow the *current* date Object
* @param {number} dExpire the expiring time, (if it is NaN, default time will be tried to use) if it is not used, nor a Number or less than 1 no expiring activated
*/
function setExpiringOverwrite(node, dNow, dExpire, reason) {
node.debug(`setExpiringOverwrite dNow=${dNow}, dExpire=${dExpire}, reason=${reason}`);
function setExpiringOverwrite(node, oNow, dExpire, reason) {
node.debug(`setExpiringOverwrite dExpire=${dExpire}, reason=${reason}`);
if (node.timeOutObj) {

@@ -119,5 +120,6 @@ clearTimeout(node.timeOutObj);

deleteExpireProp(node);
node.context().set('overwrite', node.nodeData.overwrite, node.contextStore);
return;
}
node.nodeData.overwrite.expireTs = (dNow.getTime() + dExpire);
node.nodeData.overwrite.expireTs = (oNow.nowNr + dExpire);
node.nodeData.overwrite.expireDate = new Date(node.nodeData.overwrite.expireTs);

@@ -135,2 +137,3 @@ node.nodeData.overwrite.expireDateISO = node.nodeData.overwrite.expireDate.toISOString();

}, dExpire);
node.context().set('overwrite', node.nodeData.overwrite, node.contextStore);
}

@@ -142,8 +145,8 @@

* @param {*} msg message object
* @param {*} dNow current timestamp
* @param {ITimeObject} oNow the *current* date Object
*/
function checkOverrideReset(node, msg, dNow, isSignificant) {
function checkOverrideReset(node, msg, oNow, isSignificant) {
if (node.nodeData.overwrite &&
node.nodeData.overwrite.expires &&
(node.nodeData.overwrite.expireTs < dNow.getTime())) {
(node.nodeData.overwrite.expireTs < oNow.nowNr)) {
node.log(`Overwrite is expired (trigger)`);

@@ -200,3 +203,3 @@ posOverwriteReset(node);

*/
function prepareRules(node, msg, tempData) {
function prepareRules(node, msg, tempData, dNow) {
for (let i = 0; i < node.rules.count; ++i) {

@@ -208,32 +211,33 @@ const rule = node.rules.data[i];

};
for (let i = 0; i < rule.conditonData.length; i++) {
const el = rule.conditonData[i];
if (rule.conditon.result === true && el.condition.value === cRuleLogOperatorOr) {
for (let i = 0; i < rule.conditions.length; i++) {
const el = rule.conditions[i];
if (rule.conditon.result === true && el.condition === cRuleLogOperatorOr) {
break; // not nessesary, becaue already tue
} else if (rule.conditon.result === false && el.condition.value === cRuleLogOperatorAnd) {
} else if (rule.conditon.result === false && el.condition === cRuleLogOperatorAnd) {
break; // should never bekome true
}
delete el.operandValue;
delete el.thresholdValue;
if (el.operand.type === 'sunControlMode') {
el.result = (node.sunData && (node.sunData.mode === el.operand.value));
delete el.valueWorth;
delete el.thresholdWorth;
if (el.valueType === 'sunControlMode') {
el.result = (node.sunData && (node.sunData.mode === el.value));
} else {
el.result = node.positionConfig.comparePropValue(node, msg,
{
value: el.operand.value,
type: el.operand.type,
value: el.value,
type: el.valueType,
expr: el.valueExpr,
callback: (result, _obj) => { // opCallback
el.operandValue = _obj.value;
el.valueWorth = _obj.value;
return evalTempData(node, _obj.type, _obj.value, result, tempData);
}
},
el.operator.value,
el.operator,
{
value: el.threshold.value,
type: el.threshold.type,
value: el.threshold,
type: el.thresholdType,
callback: (result, _obj) => { // opCallback
el.thresholdValue = _obj.value;
el.thresholdWorth = _obj.value;
return evalTempData(node, _obj.type, _obj.value, result, tempData);
}
}
}, false, dNow
);

@@ -247,5 +251,5 @@ }

};
if (typeof el.thresholdValue !== 'undefined') {
rule.conditon.text += ' ' + el.thresholdValue;
rule.conditon.textShort += ' ' + hlp.clipStrLength(el.thresholdValue, 10);
if (typeof el.thresholdWorth !== 'undefined') {
rule.conditon.text += ' ' + el.thresholdWorth;
rule.conditon.textShort += ' ' + hlp.clipStrLength(el.thresholdWorth, 10);
}

@@ -265,11 +269,4 @@ }

function getRuleTimeData(node, msg, rule, dNow) {
rule.timeData = node.positionConfig.getTimeProp(node, msg, {
type: rule.timeType,
value : rule.timeValue,
offsetType : rule.offsetType,
offset : rule.offsetValue,
multiplier : rule.multiplier,
next : false,
dNow
});
rule.time.dNow = dNow;
rule.timeData = node.positionConfig.getTimeProp(node, msg, rule.time);
if (rule.timeData.error) {

@@ -284,12 +281,5 @@ hlp.handleError(node, RED._('node-red-contrib-sun-position/position-config:errors.error-time', { message: rule.timeData.error }), undefined, rule.timeData.error);

rule.timeData.dayId = hlp.getDayId(rule.timeData.value);
if (rule.timeMinType !== 'none') {
rule.timeDataMin = node.positionConfig.getTimeProp(node, msg, {
type: rule.timeMinType,
value: rule.timeMinValue,
offsetType: rule.offsetMinType,
offset: rule.offsetMinValue,
multiplier: rule.multiplierMin,
next: false,
dNow
});
if (rule.timeMin) {
rule.timeMin.dNow = dNow;
rule.timeDataMin = node.positionConfig.getTimeProp(node, msg, rule.timeMin);
const numMin = rule.timeDataMin.value.getTime();

@@ -311,12 +301,5 @@ rule.timeDataMin.source = 'Min';

}
if (rule.timeMaxType !== 'none') {
rule.timeDataMax = node.positionConfig.getTimeProp(node, msg, {
type: rule.timeMaxType,
value: rule.timeMaxValue,
offsetType: rule.offsetMaxType,
offset: rule.offsetMaxValue,
multiplier: rule.multiplierMax,
next: false,
dNow
});
if (rule.timeMax) {
rule.timeMax.dNow = dNow;
rule.timeDataMax = node.positionConfig.getTimeProp(node, msg, rule.timeMax);
const numMax = rule.timeDataMax.value.getTime();

@@ -343,2 +326,88 @@ rule.timeDataMax.source = 'Max';

/**
* Timestamp compare function
* @name ICompareTimeStamp
* @function
* @param {number} timeStamp The timestamp which should be compared
* @returns {Boolean} return true if if the timestamp is valid, otherwise false
*/
/**
* support timeData
* @name ITimeObject Data
* @param {Date} dNow
* @param {number} nowNr
* @param {number} dayNr
* @param {number} monthNr
* @param {number} dateNr
* @param {number} yearNr
* @param {number} dayId
*/
/**
* function to check a rule
* @param {Object} node the node object
* @param {Object} msg the message object
* @param {Object} rule a rule object to test
* @param {ICompareTimeStamp} cmp a function to compare two timestamps.
* @param {ITimeObject} data Now time object
* @returns {Object|null} returns the rule if rule is valid, otherwhise null
*/
function compareRules(node, msg, rule, cmp, data) {
// node.debug('fktCheck rule ' + util.inspect(rule, {colors:true, compact:10}));
if (rule.conditional) {
try {
if (!rule.conditon.result) {
return null;
}
} catch (err) {
node.warn(RED._('node-red-contrib-sun-position/position-config:errors.getPropertyData', err));
node.debug(util.inspect(err, Object.getOwnPropertyNames(err)));
return null;
}
}
if (!rule.time) {
return rule;
}
if (rule.time.days && !rule.time.days.includes(data.dayNr)) {
return null;
}
if (rule.time.months && !rule.time.months.includes(data.monthNr)) {
return null;
}
if (rule.time.onlyOddDays && (data.dateNr % 2 === 0)) { // even
return null;
}
if (rule.time.onlyEvenDays && (data.dateNr % 2 !== 0)) { // odd
return null;
}
if (rule.time.onlyOddWeeks && (data.weekNr % 2 === 0)) { // even
return null;
}
if (rule.time.onlyEvenWeeks && (data.weekNr % 2 !== 0)) { // odd
return null;
}
if (rule.time.dateStart || rule.time.dateEnd) {
rule.time.dateStart.setFullYear(data.yearNr);
rule.time.dateEnd.setFullYear(data.yearNr);
if (rule.time.dateEnd > rule.time.dateStart) {
// in the current year
if (data.dNow < rule.time.dateStart || data.dNow > rule.time.dateEnd) {
return null;
}
} else {
// switch between year from end to start
if (data.dNow < rule.time.dateStart && data.dNow > rule.time.dateEnd) {
return null;
}
}
}
const num = getRuleTimeData(node, msg, rule, data.dNow);
// node.debug(`pos=${rule.pos} type=${rule.time.operatorText} - ${rule.time.value} - num=${num} - rule.timeData = ${ util.inspect(rule.timeData, { colors: true, compact: 40, breakLength: Infinity }) }`);
if (data.dayId === rule.timeData.dayId && num >=0 && (cmp(num) === true)) {
return rule;
}
return null;
}
/*************************************************************************************************************************/
/**
* check if a level has a valid value

@@ -394,3 +463,3 @@ * @param {*} node the node data

function initializeCtrl(REDLib, node, config) {
node.debug('initialize ' + node.name + ' [' + node.id + ']');
node.debug(`initialize ${ node.name || node.id}`);
RED = REDLib;

@@ -434,2 +503,22 @@

node.results = [];
config.results.forEach(prop => {
const propNew = {
outType : prop.pt,
outValue : prop.p,
type : prop.vt,
value : prop.v
};
if (this.positionConfig && propNew.type === 'jsonata') {
try {
propNew.expr = this.positionConfig.getJSONataExpression(this, propNew.value);
} catch (err) {
this.error(RED._('node-red-contrib-sun-position/position-config:errors.invalid-expr', { error: err.message }));
propNew.expr = null;
}
}
node.results.push(propNew);
});
// Prepare Rules

@@ -446,163 +535,246 @@ node.rules.count = node.rules.data.length;

rule.pos = i + 1;
rule.name = rule.name || 'rule ' + rule.pos;
rule.resetOverwrite = (rule.resetOverwrite === true || rule.resetOverwrite === 'true') ? true : false;
rule.importance = Number(rule.importance) || 0;
node.rules.maxImportance = Math.max(node.rules.maxImportance, rule.importance);
node.rules.canResetOverwrite = node.rules.canResetOverwrite || rule.resetOverwrite;
rule.timeOp = Number(rule.timeOp) || cRuleUntil;
rule.levelOp = Number(rule.levelOp) || cRuleAbsolute;
if (rule.levelOp === 3) { // cRuleMinReset = 3; // ⭳✋ reset minimum
rule.levelOp = cRuleMinOversteer;
rule.levelType = 'levelND';
rule.levelValue = '';
} else if (rule.levelOp === 4) { // cRuleMaxReset = 4; // ⭱️✋ reset maximum
rule.levelOp = cRuleMaxOversteer;
rule.levelType = 'levelND';
rule.levelValue = '';
// Backward compatibility
if (!rule.conditions) {
rule.conditions = [];
if (rule.validOperandAType && rule.validOperandAType !== 'none') {
rule.conditions.push({
condition : cRuleLogOperatorOr,
conditionText : '',
value : rule.validOperandAValue,
valueType : rule.validOperandAType,
operator : rule.validOperator,
operatorText : rule.validOperatorText,
threshold : rule.validOperandBValue,
thresholdType : (rule.validOperandBType || 'num')
});
const conditionValue = parseInt(rule.valid2LogOperator);
if (conditionValue > 0 && rule.valid2OperandAType) {
rule.conditions.push({
condition : conditionValue,
conditionText : rule.valid2LogOperatorText,
value : rule.valid2OperandAValue,
valueType : (rule.valid2OperandAType || 'msg'),
operator : rule.valid2Operator,
operatorText : rule.valid2OperatorText,
threshold : rule.valid2OperandBValue,
thresholdType : (rule.valid2OperandBType || 'num')
});
}
}
delete rule.validOperandAValue;
delete rule.validOperandAType;
delete rule.validOperator;
delete rule.validOperatorText;
delete rule.validOperandBValue;
delete rule.validOperandBType;
delete rule.valid2LogOperator;
delete rule.valid2LogOperatorText;
delete rule.valid2OperandAValue;
delete rule.valid2OperandAType;
delete rule.valid2Operator;
delete rule.valid2OperatorText;
delete rule.valid2OperandBValue;
delete rule.valid2OperandBType;
}
rule.timeLimited = (rule.timeType && (rule.timeType !== 'none'));
if (!rule.timeLimited) {
rule.timeOp = cRuleNoTime;
if(rule.timeType) {
if (!rule.time && rule.timeType !== 'none') {
rule.time = {
type : rule.timeType,
value : (rule.timeValue || ''),
operator : (parseInt(rule.timeOp) || cRuleUntil),
offsetType : (rule.offsetType || 'none'),
offset : (rule.offsetValue || 1),
multiplier : (parseInt(rule.multiplier) || 60000),
days : (rule.timeDays || '*'),
months : (rule.timeMonths || '*')
};
if (rule.timeOnlyOddDays) rule.time.onlyOddDays = rule.timeOnlyOddDays;
if (rule.timeOnlyEvenDays) rule.time.onlyEvenDays = rule.timeOnlyEvenDays;
if (rule.timeDateStart) rule.time.dateStart = rule.timeDateStart;
if (rule.timeDateEnd) rule.time.dateEnd = rule.timeDateEnd;
if (rule.timeOpText) rule.time.operatorText = rule.timeOpText;
if (rule.timeMinType) {
if (!rule.timeMin && rule.timeMinType !== 'none') {
rule.timeMin = {
type : rule.timeMinType,
value : (rule.timeMinValue || ''),
offsetType : (rule.offsetMinType || 'none'),
offset : (rule.offsetMinValue || 1),
multiplier : (parseInt(rule.multiplierMin) || 60000)
};
}
}
if (rule.timeMaxType) {
if (!rule.timeMax && rule.timeMaxType !== 'none') {
rule.timeMax = {
type : rule.timeMaxType,
value : (rule.timeMaxValue || ''),
offsetType : (rule.offsetMaxType || 'none'),
offset : (rule.offsetMaxValue || 1),
multiplier : (parseInt(rule.multiplierMax) || 60000)
};
}
}
}
delete rule.timeType;
delete rule.timeValue;
delete rule.timeOp;
delete rule.offsetType;
delete rule.offsetValue;
delete rule.multiplier;
delete rule.timeDays;
delete rule.timeMonths;
delete rule.timeOnlyOddDays;
delete rule.timeOnlyEvenDays;
delete rule.timeDateStart;
delete rule.timeDateEnd;
delete rule.timeOpText;
delete rule.timeMinType;
delete rule.timeMinValue;
delete rule.offsetMinType;
delete rule.offsetMinValue;
delete rule.multiplierMin;
delete rule.timeMinOp;
delete rule.timeMaxType;
delete rule.timeMaxValue;
delete rule.offsetMaxType;
delete rule.offsetMaxValue;
delete rule.multiplierMax;
delete rule.timeDays;
delete rule.timeMonths;
delete rule.timeOnlyOddDays;
delete rule.timeOnlyEvenDays;
delete rule.timeDateStart;
delete rule.timeDateEnd;
} else {
rule.offsetType = rule.offsetType || 'none';
rule.multiplier = rule.multiplier || 60000;
rule.timeMinType = rule.timeMinType || 'none';
rule.timeMinValue = (rule.timeMinValue || '');
rule.offsetMinType = rule.offsetMinType || 'none';
rule.multiplierMin = rule.multiplierMin || 60000;
rule.timeMaxType = rule.timeMaxType || 'none';
rule.timeMaxValue = (rule.timeMaxValue || '');
rule.offsetMaxType = rule.offsetMaxType || 'none';
rule.multiplierMax = rule.multiplierMax || 60000;
node.rules.firstTimeLimited = Math.min(i,node.rules.firstTimeLimited);
if (rule.timeOp === cRuleUntil) {
delete rule.timeMaxOp;
}
if (rule.levelType) {
if (!rule.level) {
rule.level = {
type : (rule.levelType || 'levelFixed'),
value : (rule.levelValue || 'closed (min)'),
operator : (parseInt(rule.levelOp) || cRuleAbsolute),
operatorText : rule.levelOpText || RED._('node-red-contrib-sun-position/position-config:ruleCtrl.label.ruleLevelAbs')
};
}
if (!rule.slat) {
rule.slat = {
type : 'str',
value : ''
};
}
if ((rule.level.operator === 3) || (rule.level.operator === 4)) { // 3 -> ⭳✋ reset minimum; 4 -> ⭱️✋ reset maximum
rule.level.operator.type = 'levelND';
rule.level.operator.value = '';
rule.level.operator = rule.level.operator - 2;
}
delete rule.levelType;
delete rule.levelValue;
delete rule.levelOp;
delete rule.levelOpText;
}
if (rule.payloadType) {
if (!rule.payload && rule.payloadType !== 'none') {
rule.payload = {
type : rule.payloadType,
value : (rule.payloadValue || ''),
offsetType : (rule.payloadOffsetType || 'none'),
offset : (rule.payloadOffsetValue || '1'),
multiplier : (parseInt(rule.payloadOffsetMultiplier) || 60000),
format : (parseInt(rule.payloadFormat) || 99)
};
}
delete rule.payloadType;
delete rule.payloadValue;
delete rule.payloadOffsetType;
delete rule.payloadOffsetValue;
delete rule.payloadOffsetMultiplier;
delete rule.payloadFormat;
}
if (rule.payload && !('next' in rule)) {
rule.payload.next = true;
}
/// check generic rule settings
rule.name = rule.name || 'rule ' + rule.pos;
rule.enabled = !(rule.enabled === false || rule.enabled === 'false');
rule.resetOverwrite = hlp.isTrue(rule.resetOverwrite === true) ? true : false;
if (rule.payload || (rule.level && (rule.level.operator === cRuleAbsolute))) {
rule.importance = Number(rule.importance) || 0;
node.rules.maxImportance = Math.max(node.rules.maxImportance, rule.importance);
node.rules.canResetOverwrite = node.rules.canResetOverwrite || rule.resetOverwrite;
}
/// readout timesettings
if (rule.time) {
rule.time.next = false;
if (rule.timeMax) { rule.timeMax.next = false; }
if (rule.timeMin) { rule.timeMin.next = false; }
node.rules.firstTimeLimited = Math.min(i, node.rules.firstTimeLimited);
if (rule.time.operator === cRuleUntil) {
node.rules.lastUntil = i;
}
if (rule.timeOp === cRuleFrom) {
if (rule.time.operator === cRuleFrom) {
node.rules.firstFrom = Math.min(i,node.rules.firstFrom);
}
if (!rule.timeDays || rule.timeDays === '*') {
rule.timeDays = null;
if (!rule.time.days || rule.time.days === '*') {
delete rule.time.days;
} else {
rule.timeDays = rule.timeDays.split(',');
rule.timeDays = rule.timeDays.map( e => parseInt(e) );
rule.time.days = rule.time.days.split(',');
rule.time.days = rule.time.days.map( e => parseInt(e) );
}
if (!rule.timeMonths || rule.timeMonths === '*') {
rule.timeMonths = null;
if (!rule.time.months || rule.time.months === '*') {
delete rule.time.months;
} else {
rule.timeMonths = rule.timeMonths.split(',');
rule.timeMonths = rule.timeMonths.map( e => parseInt(e) );
rule.time.months = rule.time.months.split(',');
rule.time.months = rule.time.months.map( e => parseInt(e) );
}
if (rule.timeOnlyOddDays && rule.timeOnlyEvenDays) {
rule.timeOnlyOddDays = false;
rule.timeOnlyEvenDays = false;
if (rule.time.onlyOddDays && rule.time.onlyEvenDays) {
delete rule.time.onlyOddDays;
delete rule.time.onlyEvenDays;
}
rule.timeDateStart = rule.timeDateStart || '';
rule.timeDateEnd = rule.timeDateEnd || '';
if (rule.timeDateStart || rule.timeDateEnd) {
if (rule.timeDateStart) {
rule.timeDateStart = new Date(rule.timeDateStart);
rule.timeDateStart.setHours(0, 0, 0, 1);
if (rule.time.onlyOddWeeks && rule.time.onlyEvenWeeks) {
delete rule.time.onlyOddWeeks;
delete rule.time.onlyEvenWeeks;
}
if (rule.time.dateStart || rule.time.dateEnd) {
if (rule.time.dateStart) {
rule.time.dateStart = new Date(rule.time.dateStart);
rule.time.dateStart.setHours(0, 0, 0, 1);
} else {
rule.timeDateStart = new Date(2000,0,1,0, 0, 0, 1);
rule.time.dateStart = new Date(2000,0,1,0, 0, 0, 1);
}
if (rule.timeDateEnd) {
rule.timeDateEnd = new Date(rule.timeDateEnd);
rule.timeDateEnd.setHours(23, 59, 59, 999);
if (rule.time.dateEnd) {
rule.time.dateEnd = new Date(rule.time.dateEnd);
rule.time.dateEnd.setHours(23, 59, 59, 999);
} else {
rule.timeDateEnd = new Date(2000,11,31, 23, 59, 59, 999);
rule.time.dateEnd = new Date(2000,11,31, 23, 59, 59, 999);
}
}
}
rule.conditonData = [];
const setCondObj = (pretext, defLgOp) => {
const operandAType = rule[pretext+'OperandAType'];
const conditionValue = Number(rule[pretext+'LogOperator']) || defLgOp;
if (operandAType !== 'none' && conditionValue !== cRuleNone) {
const operandAValue = rule[pretext+'OperandAValue'];
const operandBType = rule[pretext+'OperandBType'];
const operandBValue = rule[pretext+'OperandBValue'];
const el = {
result: false,
operandName: getName(operandAType, operandAValue),
thresholdName: getName(operandBType, operandBValue),
operand: {
type:operandAType,
value:operandAValue
},
threshold: {
type:operandBType,
value:operandBValue
},
operator: {
value : rule[pretext+'Operator'],
text : rule[pretext+'OperatorText'],
description: RED._('node-red-contrib-sun-position/position-config:common.comparatorDescription.' + rule[pretext+'Operator'])
},
condition: {
value : conditionValue,
text : rule[pretext+'LogOperatorText']
}
};
if (operandAType === 'sunControlMode') {
if (operandAValue === 'off' || operandAValue.charAt(0) === '0') {
el.operand.value = 0;
} else if (operandAValue === 'maximize' || operandAValue.charAt(0) === '1') {
el.operand.value = 1;
} else {
el.operand.value = 2;
}
rule.conditions.forEach(cond => {
cond.operatorDescription = RED._('node-red-contrib-sun-position/position-config:common.comparatorDescription.' + rule[cond.operator]);
if (cond.valueType === 'sunControlMode') {
if (cond.value === 'off' || cond.value.charAt(0) === '0') {
cond.value = 0;
} else if (cond.value === 'maximize' || cond.value.charAt(0) === '1') {
cond.value = 1;
} else {
cond.value = 2;
}
if (el.operandName.length > 25) {
el.operandNameShort = getNameShort(operandAType, operandAValue);
} else if (node.positionConfig && cond.valueType === 'jsonata') {
try {
cond.valueExpr = node.positionConfig.getJSONataExpression(node, cond.value);
} catch (err) {
node.error(RED._('node-red-contrib-sun-position/position-config:errors.invalid-expr', { error:err.message }));
cond.valueExpr = null;
}
if (el.thresholdName.length > 25) {
el.thresholdNameShort = getNameShort(operandBType, operandBValue);
}
el.text = el.operandName + ' ' + el.operator.text;
el.textShort = (el.operandNameShort || el.operandName) + ' ' + el.operator.text;
rule.conditonData.push(el);
}
delete rule[pretext+'OperandAType'];
delete rule[pretext+'OperandAValue'];
delete rule[pretext+'OperandBType'];
delete rule[pretext+'OperandBValue'];
delete rule[pretext+'Operator'];
delete rule[pretext+'OperatorText'];
delete rule[pretext+'LogOperator'];
delete rule[pretext+'LogOperatorText'];
};
setCondObj('valid', cRuleLogOperatorOr);
setCondObj('valid2', cRuleNone);
rule.conditional = rule.conditonData.length > 0;
cond.valueName = getName(cond.valueType, cond.value);
if (cond.valueName.length > 25) {
cond.valueNameShort = getNameShort(cond.valueType, cond.value);
}
cond.thresholdName = getName(cond.thresholdType, cond.threshold);
if (cond.thresholdName.length > 25) {
cond.thresholdNameShort = getNameShort(cond.thresholdType, cond.threshold);
}
cond.text = cond.valueName + ' ' + cond.operatorText;
cond.textShort = (cond.valueNameShort || cond.valueName) + ' ' + cond.operatorText;
cond.result = false;
});
rule.conditional = rule.conditions.length > 0;
}

@@ -609,0 +781,0 @@

@@ -6,3 +6,2 @@ {

"blind-control-palette": "Rollladen",
"output1": "neue Rollladen position",
"output2": "status Objekt",

@@ -17,32 +16,6 @@ "windowTop": "Fenster Oberseite",

"blindLevelDefault": "Standard Rollladenposition",
"slatPosDefault": "Standard Lamellenposition",
"blindLevelMin": "minimale Rollladenposition",
"blindLevelMax": "maximale Rollladenposition",
"overwriteExpire": "verfällt",
"ruleCondition": "nur wenn",
"ruleConditionThreshold": "Schwelle",
"ruleAndOr": "und/oder",
"ruleCondNone": "N/A",
"ruleCondAnd": "und",
"ruleCondOr": "oder",
"ruleTimeFrom": "↧ von",
"ruleTimeUntil": "↥ bis",
"ruleTimeNone": "N/A",
"ruleTimeMax": "spätestens (max)",
"ruleTimeMin": "frühestens (min)",
"ruleTimeDays": "nur an bestimmten Wochentagen",
"ruleTimeMonths": "nur an bestimmten Monaten",
"ruleDescription": "Beschreibung",
"ruleBlindLevel": "Rollladenposition",
"ruleResetOverwrite": "manuelle Überschreibung verfällt wenn die Regel aktiv wird",
"ruleTopic": "Topic:",
"ruleImportance":"Wichtung der Regel",
"ruleTimeLimitStart": "nur von",
"ruleTimeLimitEnd": "bis",
"ruleLevelAbs": "↕ Absolut",
"ruleLevelMin": "⭳❗ Minimum (übersteuernd)",
"ruleLevelMax": "⭱️❗ Maximum (übersteuernd)",
"ruleLevelResetMin": "⭳✋ Minimum zurücksetzen",
"ruleLevelResetMax": "⭱️✋ Maximum zurücksetzen",
"ruleLevelND": "standard level (e.g. sun control)",
"sunControlMode": "Modus",

@@ -52,4 +25,8 @@ "sunControlOff": "keine Beschränkung, Sonnenstands unabhängig",

"sunControlMaximize": "Sonnenlicht maximieren (⛄ Winter)",
"sunControlMinimize": "Sonnenlicht minimieren (🕶️)",
"sunFloorLength": "Länge auf dem Boden",
"sunMinAltitude": "Minimale Sonnenhöhenwinkel",
"sunControlNoMatter": "∞ egal welcher modus",
"sunControlRestrictOnly": "🌞 nur im Modus Sonnenlicht beschränken",
"sunControlMaximizeOnly": "⛄ nur im Modus Sonnenlicht maximieren",
"sunControlMinimizeOnly": "🕶️ nur im Modus Sonnenlicht minimieren",
"sunMinDelta": "Mindeständerung",

@@ -62,36 +39,17 @@ "sunTopic": "Topic 🌞/⛄",

"oversteerBlindPos": "Rollladenposition",
"oversteer2Value": "Übersteuerung zus.",
"oversteer2Threshold": "Schwelle",
"oversteer2BlindPos": "Rollladenposition",
"oversteer3Value": "Übersteuerung zus.",
"oversteer3Threshold": "Schwelle",
"oversteer3BlindPos": "Rollladenposition",
"oversteerSlatPos": "Lamellenposition",
"oversteerTopic":"Übersteuerungs topic",
"smoothTime": "glätten",
"showEnhSettings": "Erweiterte Einstellungen",
"outputs": "Ausgänge",
"offset": "Zeit offset",
"offset-timeMin": "früheste (min) offset",
"offset-timeMax": "späteste (max) offset",
"singleOutput": "einzeln (1)",
"splitOutput": "doppelt (2)",
"btnAdd": "hinzufügen",
"btnSort": "sortieren",
"btnClear": "leeren",
"dialogtitle": "Regel bearbeiten",
"autoTrigger": "automatisch triggern",
"autoTrigger2": "dynamisch aber max aller",
"autoTrigger2": "dynamisch aber mind. aller",
"startDelay": "Ausgabe bei Start verzögern",
"timeconstraintshow": "zeige zusätzliche Zeitbeschränkungen",
"timeconstrainthide": "verberge zusätzliche Zeitbeschränkungen",
"validForDays": "gültige Tage",
"validForMonths": "gültige Monate",
"validForDates":"Gültigkeitsdauer (Jahr wird ignoriert)",
"specialDays": "spezielle tage",
"onlyEven": "nur gerade",
"onlyOdd": "nur ungerade",
"onlyEvenDays": "nur gerade Tage",
"onlyOddDays": "nur ungerade Tage",
"editRule": "Regel editieren",
"duplicateRule": "Regel duplizieren"
"addId": "zus. ID",
"resultContainer": "Ausgang 1 msg Objekt Definition"
},

@@ -107,8 +65,9 @@ "placeholder": {

"blindLevelDefault": "Rollladenposition, wenn keine andere zutrifft",
"slatPosDefault": "Lamellenposition, wenn keine andere zutrifft",
"blindLevelMin": "maximale Rollladenposition Sonnenstands abhängig",
"blindLevelMax": "minimale Rollladenposition Sonnenstands abhängig",
"blindSlatSun": "Lamellenposition, wenn Sonnensteuerung aktiv",
"sunControlMode": "wähle wie die Sonnensteuerung arbeiten soll",
"overwriteExpire": "(opt) Dauer nasch der eine manuelle Einstellung (überschreiben) verfällt",
"sunFloorLength": "das Ausmaß, in dem direktes Sonnenlicht durch das Fenster in den Raum gelangen darf, definiert als Länge am Boden",
"sunMinAltitude": "(opt) minimaler Höhenwinkel der Sonne",
"sunMinDelta": "(opt) mindest Änderung der Behanghöhe",

@@ -125,6 +84,8 @@ "oversteerValue": "Wert zum Vergleich",

"btnClear": "alle Regeln entfernen",
"condoperand": "operand",
"btnExport": "Alle Regeln in die Zwischenablage kopieren.",
"btnImport": "Regeln aus der Zwischenablage einfügen (anfügen an vorhandene).",
"time": "Zeit",
"offset": "Zeit offset",
"level": "Behanghöhe",
"slat": "Lamellenposition",
"ruleImportance": "definiert eine wichtung der Regel gegenüber manueller Einstellung (überschreiben). Nur Überschreibungen mit gleicher oder höherer Wichtung können diese Regel übersteuern.",

@@ -141,18 +102,11 @@ "ruleTopic":"Erlaubt es die topic der ausgesendeten Nachricht speziell für die Regel angepasst werden. Wenn diese leer ist, wird die Standard topic verwendet.",

"start":"tt.mm",
"end":"tt.mm"
"end":"tt.mm",
"addId": "zusätzliche ID"
},
"text": {
"blind": "Rollladen Einstellungen",
"time": "Zeitsteuerung: Es werden nur Zeilen ausgewertet, bei denen die Eigenschaft <b>nicht verwendet</b> oder <em>true</em> ist. <br> <b>bis</b>: Die erste übereinstimmende Zeile wird verwendet, wobei die definierte Zeit <b>nicht verwendet</b> oder größer als <b>now</b> ist. <br> <b>von</b>: Die letzte übereinstimmende Zeile wird verwendet, wo die angegebene Zeit <b>nicht verwendet</b> oder weniger als <b>der aktuelle Zeitpunkt</b> ist. <br>",
"blindLevelDefault": "Wenn keine Regel zutrifft, wird die aktuelle Rollladenposition genutzt. Bei beschränkender Sonnen-Steuerung ist die die Rollladenposition, wenn die Sonne nicht in das Fenster scheint.",
"overwrite": "manuelles Überschreiben der Rollladenposition",
"sunControlNotActive": "Nur Regelbasiert",
"sunControlMode": "Anstelle der standard Rollladenposition kann das Ausmaß in dem direktes Sonnenlicht in den Raum scheint eingeschränkt werden.",
"windowAzimuth": "Darstellung der Ausrichtung des Fensters zum geografischen Norden (in Grad), wenn die Sonne in das Fenster fällt (Sonnenrichtung/Azimuth).",
"windowPos": "Fenster Eigenschaften, Messung vom Boden bis zum unter und Oberseite des Fensters",
"oversteer": "erlaubt das Übersteuern der Position in Abhängigkeit von der Sonne unter definierten Bedingungen wie Wetter (z. B. Wolkenhimmel, Beleuchtung, etc.)",
"sunControlMaximization": "<ul><li>Wenn keine Regel oder Überschreiben (Override) zutrifft,<ul><li>Wenn die Sonne <em>nicht</ em> in das Fenster scheint, wird die Rollladenhöhe die definierte <strong>Minimalposition</ strong> gesetzt. (Übersteuern wird ignoriert)</ li><li>Wenn sich die Sonne im Fenster befindet</ li><li>Wenn eine Übersteueruzng aufgesetzt ist und die bedingung zutrifft, wird der Behang auf die Höhe des Übersteuerns gesetzt.< / li><li>Andernfalls wird die Behanghöhe auf die definierte <strong>Maximalposition</ strong> gesetzt.</ li></ ul></ li></ ul>",
"sunControlRestriction": "Wenn keine Regel oder Überschreiben (Override) zutrifft, berechnet der Knoten die entsprechende Blindposition, um die Menge des direkten Sonnenlichts, das in den Raum fällt, zu begrenzen.",
"sunCtrlLoF": "Definition inwieweit direktes Sonnenlicht durch das Fenster in den Raum gelangen darf (als Länge auf dem Boden).",
"sunCtrlRestrict": "Begrenzen Sie die Häufigkeit von Änderungen nach Zeit und / oder Änderungsgröße (Delta). Minimaler Höhenwinkel (Sonnenhöhenwinkel/Altitude in Grad) der Sonne."
"tabs-label": {
"general":"Name und Konfiguration",
"default":"Default Einstellungen",
"time":"Zeit/Regelsteuerung",
"sun-control":"Sonnensteuerung",
"output":"Ausgabe und anderes"
},

@@ -169,62 +123,16 @@ "typeOptions": {

},
"ctrlObj": {
"full": "komplettes Objekt",
"rule": "Regel Objekt (wenn eine Regel aktiv wurde)"
},
"tips": {
"documentation": "<a href=\"https://github.com/rdmtc/node-red-contrib-sun-position/wiki/blind-control\">Dokumentation und Beispiele</a>"
},
"reasons": {
"overwriteNoExpire": "manuell überschrieben (Wichtigkeit __importance__), kein Verfall",
"overwriteExpire": "manuell überschrieben (Wichtigkeit __importance__), verfällt __dateISO__",
"default": "Position ist auf Standard gesetzt, weil keine Regel zutrifft",
"ruleTime": "Position durch Zeitregel - rule __timeOp__ __timeLocal__ [rule __number__]",
"ruleCond": "Position durch bedingte Regel __text__ [rule __number__]",
"ruleTimeCond": "Position durch Zeit Regel __timeOp__ __timeLocal__ und Bedingung __text__ [rule __number__]",
"rule": "Position durch feste Regel __number__",
"sunMinAltitude": "Sonne ist niedriger als der minimale Höhenwinkel",
"sunMinDelta": "Änderung ist geringer als die minimale Behanghöhenänderung",
"sunNotInWin": "Sonne scheint nicht in das Fenster",
"sunCtrl": "Rollladenposition wird durch den Sonnenstand bestimmt",
"sunCtrlMin": "__org__ (__level__ ist unter dem minimum)",
"sunCtrlMax": "__org__ (__level__ ist über dem maximum)",
"oversteer": "Sonder Bedingung erfüllt",
"smooth": "Rollladenposition wird nicht geändert zu __pos__ weil die letzte Änderung nicht lang genug her ist",
"sunInWinMax": "Die Sonne scheint ins Fenster und die maximale Rollladenposition ist gesetzt",
"sunNotInWinMin": "Die Sonne scheint nicht ins Fenster und die minimale Rollladenposition ist gesetzt",
"ruleMin": "__org__ (__level__ ist unter minimum) [__number__] __name__",
"ruleMax": "__org__ (__level__ ist über maximum) [__number__] __name__",
"startDelay": "verzögerter Start bis __dateISO__"
},
"states": {
"overwriteNoExpire": "überschrieben [Prio=__importance__]",
"overwriteExpire": "überschrieben [Prio=__importance__], bis __timeLocal__",
"default": "Standard",
"ruleTime": "__timeOp__ __timeLocal__ [rule __number__]",
"ruleCond": "__textShort__ [rule __number__]",
"ruleTimeCond": "__timeOp__ __timeLocal__ + cond __operatorText__ [rule __number__]",
"rule": "durch feste Regel __number__",
"sunMinAltitude": "minimaler Höhenwinkel",
"sunMinDelta": "Änderung zu gering",
"sunNotInWin": "Sonne scheint nicht ins Fenster",
"sunCtrl": "durch Sonnenstand",
"sunCtrlMin": "__org__ (min)",
"sunCtrlMax": "__org__ (max)",
"oversteer": "Übersteuert",
"smooth": "Änderung zu __pos__ verhindert",
"sunInWinMax": "Sonne scheint ins Fenster (max)",
"sunNotInWinMin": "Sonne scheint nicht ins Fenster (min)",
"ruleMin": "__org__ [min rule __number__]",
"ruleMax": "__org__ [max rule __number__]",
"startDelay": "verzögerter Start"
},
"errors": {
"warning": "Warnung: __message__",
"internal": "Fehler: __message__",
"error-time": "Fehler bei Ermittlung der Zeit: __message__",
"invalid-blind-level": "Rollladenposition __pos__ ist keine gültige Position!",
"getOversteerData": "Fehler bei der Ermittlung der Daten: __message__",
"getBlindPosData": "Fehler bei der Ermittlung der Rollladenposition: __message__",
"getPropertyData": "Fehler bei der Ermittlung der Bedingung: \"__message__\" skipping time",
"smoothTimeToolong": "Die gewählte zeit ist zu groß!!",
"usingTempValue": "Wert von __type__.__value__ kann nicht ermitteln werden und es wird der gespeicherte Wert \"__usedValue__\" verwendet!",
"notEvaluableProperty": "kann den Wert von __type__.__value__ nicht ermitteln, verwende \"__usedValue__\"!"
"smoothTimeToolong": "Die gewählte zeit ist zu groß!!"
}
}
}

@@ -6,3 +6,2 @@ {

"clock-timer-palette": "Zeitschaltuhr",
"output1": "payload basierend auf Regel",
"output2": "status Objekt",

@@ -13,51 +12,16 @@ "payloadDefault": "payload",

"overwriteExpire": "verfällt",
"ruleCondition": "nur wenn",
"ruleConditionThreshold": "Schwelle",
"ruleAndOr": "und/oder",
"ruleCondNone": "N/A",
"ruleCondAnd": "und",
"ruleCondOr": "oder",
"ruleTimeFrom": "↧ von",
"ruleTimeUntil": "↥ bis",
"ruleTimeNone": "N/A",
"ruleTimeMax": "spätestens (max)",
"ruleTimeMin": "frühestens (min)",
"ruleTimeDays": "nur an folgenden Tagen",
"ruleTimeMonths": "nur an folgenden Monaten",
"ruleDescription": "Beschreibung",
"rulePayload": "Payload:",
"rulePayloadND": "Kein Payload",
"ruleResetOverwrite": "manuelle Überschreibung verfällt wenn die Regel aktiv wird",
"ruleTopic": "Topic:",
"ruleImportance":"Wichtung der Regel",
"ruleTimeLimitStart": "only from",
"ruleTimeLimitEnd": "to",
"time": "Zeit",
"name": "name",
"showEnhSettings": "Erweiterte Einstellungen",
"outputs": "Ausgänge",
"offset": "Zeit offset",
"offset-timeMin": "früheste (min) offset",
"offset-timeMax": "späteste (max) offset",
"singleOutput": "einzeln (1)",
"splitOutput": "doppelt (2)",
"btnAdd": "hinzufügen",
"btnSort": "sortieren",
"btnClear": "leeren",
"dialogtitle": "Regel bearbeiten",
"autoTrigger": "automatisch triggern",
"autoTrigger2": "dynamisch aber max aller",
"autoTrigger2": "dynamisch aber mind. aller",
"startDelay": "Ausgabe bei Start verzögern",
"timeconstraintshow": "zeige zusätzliche Zeitbeschränkungen",
"timeconstrainthide": "verberge zusätzliche Zeitbeschränkungen",
"validForDays": "gültige Tage",
"validForMonths": "gültige Monate",
"validForDates":"Gültigkeitsdauer (Jahr wird ignoriert)",
"specialDays": "spezielle tage",
"onlyEven": "nur gerade",
"onlyOdd": "nur ungerade",
"onlyEvenDays": "nur gerade Tage",
"onlyOddDays": "nur ungerade Tage",
"editRule": "Regel editieren",
"duplicateRule": "Regel duplizieren"
"addId": "zus. ID",
"resultContainer": "Ausgang 1 msg Objekt Definition"
},

@@ -71,10 +35,9 @@ "placeholder": {

"expiryperiod": "120",
"outputs": "Anzahl der Ausgänge",
"btnAdd": "neue leere Regel hinzufügen",
"btnSort": "alle Regeln sortieren, Achtung dies kann das Verhalten ändern!",
"btnClear": "alle Regeln entfernen",
"condoperand": "operand",
"btnExport": "Alle Regeln in die Zwischenablage kopieren.",
"btnImport": "Regeln aus der Zwischenablage einfügen (anfügen an vorhandene).",
"time": "Zeit",
"offset": "Zeit offset",
"level": "Behanghöhe",
"ruleImportance": "definiert eine wichtung der Regel gegenüber manueller Einstellung (überschreiben). Nur Überschreibungen mit gleicher oder höherer Wichtung können diese Regel übersteuern.",

@@ -89,45 +52,15 @@ "ruleTopic":"Erlaubt es die topic der ausgesendeten Nachricht speziell für die Regel angepasst werden. Wenn diese leer ist, wird die Standard topic verwendet.",

"start":"tt.mm",
"end":"tt.mm"
"end":"tt.mm",
"addId": "zusätzliche ID"
},
"text": {
"time": "Zeitsteuerung: Es werden nur Zeilen ausgewertet, bei denen die Eigenschaft <b>nicht verwendet</b> oder <em>true</em> ist. <br> <b>bis</b>: Die erste übereinstimmende Zeile wird verwendet, wobei die definierte Zeit <b>nicht verwendet</b> oder größer als <b>now</b> ist. <br> <b>von</b>: Die letzte übereinstimmende Zeile wird verwendet, wo die angegebene Zeit <b>nicht verwendet</b> oder weniger als <b>der aktuelle Zeitpunkt</b> ist. <br>",
"payloadDefault":"Wenn keine Regel zutrifft, wird der folgende payload gesendet.",
"overwrite": "manuelles Überschreiben der Rollladenposition"
"tabs-label": {
"general":"Name und Konfiguration",
"default":"default und Überschreiben",
"time":"Zeitsteuerung",
"output":"Ausgabe und anderes"
},
"tips": {
"documentation": "<a href=\"https://github.com/rdmtc/node-red-contrib-sun-position/wiki/clock-timer\">Dokumentation und Beispiele</a>"
},
"reasons": {
"overwriteNoExpire": "manuell überschrieben (Wichtigkeit __importance__), kein Verfall",
"overwriteExpire": "manuell überschrieben (Wichtigkeit __importance__), verfällt __dateISO__",
"default": "Position ist auf Standard gesetzt, weil keine Regel zutrifft",
"ruleTime": "Position durch Zeitregel - rule __timeOp__ __timeLocal__ [rule __number__]",
"ruleCond": "Position durch bedingte Regel __text__ [rule __number__]",
"ruleTimeCond": "Position durch Zeit Regel __timeOp__ __timeLocal__ und Bedingung __text__ [rule __number__]",
"rule": "Position durch feste Regel __number__",
"ruleMin": "__org__ (__level__ ist unter minimum) [__number__] __name__",
"ruleMax": "__org__ (__level__ ist über maximum) [__number__] __name__",
"startDelay": "verzögerter Start bis __dateISO__"
},
"states": {
"overwriteNoExpire": "überschrieben [Prio=__importance__]",
"overwriteExpire": "überschrieben [Prio=__importance__], bis __timeLocal__",
"default": "Standard",
"ruleTime": "__timeOp__ __timeLocal__ [rule __number__]",
"ruleCond": "__textShort__ [rule __number__]",
"ruleTimeCond": "__timeOp__ __timeLocal__ + cond __operatorText__ [rule __number__]",
"rule": "durch feste Regel __number__",
"ruleMin": "__org__ [min rule __number__]",
"ruleMax": "__org__ [max rule __number__]",
"startDelay": "verzögerter Start"
},
"errors": {
"warning": "Warnung: __message__",
"internal": "Fehler: __message__",
"error-time": "Fehler bei Ermittlung der Zeit: __message__",
"getPropertyData": "Fehler bei der Ermittlung der Bedingung: \"__message__\" skipping time",
"usingTempValue": "Wert von __type__.__value__ kann nicht ermitteln werden und es wird der gespeicherte Wert \"__usedValue__\" verwendet!",
"notEvaluableProperty": "kann den Wert von __type__.__value__ nicht ermitteln, verwende \"__usedValue__\"!"
}
}
}
{
"moon-position": {
"label": {
"azimuthpos":"Moondrichtung",
"between":"zwischen",
"and":"und"
"azimuthpos":"Moondrichtung"
},

@@ -8,0 +6,0 @@ "tips": {

@@ -15,3 +15,21 @@ {

"nextOccurrence": "next occurrence",
"on": "nur"
"on": "nur",
"validForDays": "gültige Tage",
"validForMonths": "gültige Monate",
"validForDates": "Gültigkeitsdauer (Jahr wird ignoriert)",
"specialLimits": "spezielles",
"onlyEvenDays":"nur gerade Tage",
"onlyOddDays":"nur ungerade Tage",
"onlyEvenWeeks":"nur gerade Wochen",
"onlyOddWeeks":"nur ungerade Wochen",
"between":"zwischen",
"and": "und",
"or": "oder",
"enabled": "aktiviert",
"disabled": "deaktiviert",
"cancel":"Abbrechen",
"ok":"Ok",
"randNum":"zufällig bis",
"randNumCachedDay":"zufällig (täglich) bis",
"randNumCachedWeek":"zufällig (wöchentlich) bis"
},

@@ -22,2 +40,4 @@ "types": {

"datespecific": "Zeitpunkt (erweitert)",
"nodeId":"Node Name",
"nodeName":"Node ID",
"timeentered": "Uhrzeit (nächste)",

@@ -31,3 +51,5 @@ "dateentered": "Datum (spezieller Zeitpunkt)",

"timemoon": "Uhrzeit Mond Auf/Untergang",
"randomNumber":"zufällig",
"randomNumber":"zufällige Zahl (immer neu)",
"randmNumCachedDay":"zufällig Zahl (täglich neu)",
"randmNumCachedWeek":"zufällig Zahl (wöchentlich neu)",
"numPercent":"Nummer in Prozent %",

@@ -37,5 +59,13 @@ "suncalc":"Sonnenstand berechnet",

"sunAzimuth":"Sonnenrichtung",
"sunElevation":"Sonnenhöhe",
"sunElevation":"Sonnenhöhenwinkel",
"sunAzimuthRad":"Sonnenrichtung (rad)",
"sunElevationRad":"Sonnenhöhe (rad)",
"sunElevationRad":"Sonnenhöhenwinkel (rad)",
"numAzimuth":"Sonnenrichtung",
"numAltitude":"Sonnenhöhenwinkel",
"numAzimuthRad":"Sonnenrichtung (rad)",
"numAltitudeRad":"Sonnenhöhenwinkel (rad)",
"sunTimeByElevation":"Zeit durch Sonnenhöhenwinkel",
"sunTimeByAzimuth":"Zeit durch Sonnenrichtung",
"sunTimeByElevationRad":"Zeit durch Sonnenhöhenwinkel (rad)",
"sunTimeByAzimuthRad":"Zeit durch Sonnenrichtung (rad)",
"suntime":"Sonnenzeit",

@@ -48,3 +78,3 @@ "suntimes":"Sonnenzeiten",

"levelfree": "Position eingeben",
"levelND": "N/D - benutze standard, sonnensteuerung oder reset",
"levelND": "N/D - benutze standard oder sonnensteuerung",
"PlTRes":"msg.payload wenn msg.topic enthält",

@@ -59,3 +89,11 @@ "isDST":"ist Sommerzeit (true/false)",

"sunControlRestrict": "Sonnenlicht beschränken (🌞 Sommer)",
"sunControlMaximize": "Sonnenlicht maximieren (⛄ Winter)"
"sunControlMaximize": "Sonnenlicht maximieren (⛄ Winter)",
"sunControlMinimize": "Sonnenlicht minimieren (🕶️)",
"payload":"payload",
"level":"Rollladenposition",
"levelInverse":"Rollladenposition invers",
"slat":"Lamellenposition",
"topic":"topic",
"ctrlObj":"Status object",
"strPlaceholder": "string mit Platzhatern"
},

@@ -68,15 +106,15 @@ "typeOptions": {

"nauticalDawn": "nautische Morgendämmerung",
"blueHourDawnStart": "Blaue Morgenstunde Begin",
"blueHourDawnStart": "Blaue Morgenstunde Beginn",
"civilDawn": "bürgerliche Morgendämmerung",
"blueHourDawnEnd": "Blaue Morgenstunde Ende",
"goldenHourDawnStart": "Goldene Morgenstunde Begin",
"sunriseStart": "Sonnenaufgang Begin",
"goldenHourDawnStart": "Goldene Morgenstunde Beginn",
"sunriseStart": "Sonnenaufgang Beginn",
"sunriseEnd": "Sonnenaufgang Ende",
"goldenHourDawnEnd": "Goldene Morgenstunde Ende",
"solarNoon": "Sonnenmittag",
"goldenHourDuskStart": "Goldene Abendstunde Begin",
"sunsetStart": "Sonnenuntergang Begin",
"goldenHourDuskStart": "Goldene Abendstunde Beginn",
"sunsetStart": "Sonnenuntergang Beginn",
"sunsetEnd": "Sonnenuntergang Ende",
"goldenHourDuskEnd": "Goldene Abendstunde Ende",
"blueHourDuskStart": "Blaue Abendstunde Begin",
"blueHourDuskStart": "Blaue Abendstunde Beginn",
"civilDusk": "bürgerliche Abenddämmerung",

@@ -204,3 +242,4 @@ "blueHourDuskEnd": "Blaue Abendstunde Ende",

"Millisekunden UNIX-Zeit",
"ECMA-262 - JSON Date",
"ECMA-262 - simple JSON Date",
"ISO8601",
"try different text Formats, prefer day first like d/M/y",

@@ -297,5 +336,125 @@ "try different text Formats, prefer month first like M/d/y",

"containEvery": "enthält alle"
},
"units": {
"ms": "ms",
"sec": "s",
"min": "min",
"hour": "h",
"day": "Tag",
"days": "Tage",
"week": "Woche",
"weeks": "Wochen"
}
},
"ruleCtrl": {
"label": {
"outDated": "✎ Bitte editieren Sie diese Regel.",
"isInValid": "⚠️ Diese Regel ist ungültig und muss geändert werden!!",
"ruleIsOutdated": "⚠️ Diese Regel ist ungültig und muss angepasst werden, da sie nicht mehr funktioniert!",
"ruleTimeMax": "spätestens (max)",
"ruleTimeMin": "frühestens (min)",
"ruleTimeLimit": "limitiert",
"ruleTimeLimitStart": "nur von",
"ruleTimeLimitEnd": "bis",
"ruleTimeDays": "nur an folgenden Tagen",
"ruleTimeMonths": "nur an folgenden Monaten",
"ruleTopic": "Topic",
"ruleSlat": "Lamellenposition",
"rulePayload": "Payload:",
"rulePayloadND": "Kein Payload",
"ruleResetOverwrite": "manuelle Überschreibung verfällt wenn die Regel aktiv wird",
"ruleDescription": "Beschreibung",
"ruleBlindLevel": "Rollladenposition",
"ruleBlindLevelMinimum": "⭳ minimale Rollladen Position",
"ruleBlindLevelMaximum": "⭱️ maximale Rollladen Position",
"ruleOverwrite": "überschreiben",
"ruleImportance":"Wichtung der Regel",
"ruleLevelAbs": "↕ Absolut",
"ruleLevelMin": "⭳❗ Minimum (übersteuernd)",
"ruleLevelMax": "⭱️❗ Maximum (übersteuernd)",
"ruleSlatOversteer": "Lamellenposition (übersteuernd)",
"ruleTopicOversteer": "Topic (übersteuernd)",
"ruleOff": "✋ nichts senden",
"ruleLevelND": "standard level (e.g. sun control)",
"editRule": "Regel editieren",
"duplicateRule": "Regel duplizieren",
"ruleState": "aktiviert oder deaktiviert die Regel",
"ruleTimeFrom": "↧ von",
"ruleTimeUntil": "↥ bis",
"btnAdd": "hinzufügen",
"btnSort": "sortieren",
"btnClear": "leeren",
"btnExport": "",
"btnImport": ""
},
"reasons": {
"overwriteNoExpire": "manuell überschrieben (Wichtigkeit __importance__), kein Verfall",
"overwriteExpire": "manuell überschrieben (Wichtigkeit __importance__), verfällt __dateISO__",
"default": "Position ist auf Standard gesetzt, weil keine Regel zutrifft",
"ruleTime": "Position durch Zeitregel - rule __timeOp__ __timeLocal__ [rule __number__]",
"ruleCond": "Position durch bedingte Regel __text__ [rule __number__]",
"ruleTimeCond": "Position durch Zeit Regel __timeOp__ __timeLocal__ und Bedingung __text__ [rule __number__]",
"rule": "Position durch feste Regel __number__",
"sunMinDelta": "Änderung ist geringer als die minimale Behanghöhenänderung",
"sunNotInWin": "Sonne scheint nicht in das Fenster",
"sunCtrl": "Rollladenposition wird durch den Sonnenstand bestimmt",
"sunCtrlMin": "__org__ (__level__ ist unter dem minimum)",
"sunCtrlMax": "__org__ (__level__ ist über dem maximum)",
"oversteer": "Sonder Bedingung __pos__ erfüllt",
"smooth": "Rollladenposition wird nicht geändert zu __pos__ weil die letzte Änderung nicht lang genug her ist",
"sunInWinMin": "Die Sonne scheint ins Fenster und die minimale Rollladenposition ist gesetzt",
"sunInWinMax": "Die Sonne scheint ins Fenster und die maximale Rollladenposition ist gesetzt",
"sunNotInWinMin": "Die Sonne scheint nicht ins Fenster und die minimale Rollladenposition ist gesetzt",
"sunNotInWinMax": "Die Sonne scheint nicht ins Fenster und die maximale Rollladenposition ist gesetzt",
"ruleMin": "__org__ (__level__ ist unter minimum) [__number__] __name__",
"ruleMax": "__org__ (__level__ ist über maximum) [__number__] __name__",
"startDelay": "verzögerter Start bis __dateISO__"
},
"states": {
"overwriteNoExpire": "überschrieben [Prio=__importance__]",
"overwriteExpire": "überschrieben [Prio=__importance__], bis __timeLocal__",
"default": "Standard",
"ruleTime": "__timeOp__ __timeLocal__ [rule __number__] __name__",
"ruleCond": "__textShort__ [rule __number__] __name__",
"ruleTimeCond": "__timeOp__ __timeLocal__ + cond __operatorText__ [rule __number__] __name__",
"rule": "durch feste Regel[__number__] __name__",
"sunMinDelta": "Änderung zu gering",
"sunNotInWin": "Sonne scheint nicht ins Fenster",
"sunCtrl": "durch Sonnenstand",
"sunCtrlMin": "__org__ (min)",
"sunCtrlMax": "__org__ (max)",
"oversteer": "Übersteuert durch Regel __pos__",
"smooth": "Änderung zu __pos__ verhindert",
"sunInWinMin": "Sonne scheint ins Fenster (min)",
"sunInWinMax": "Sonne scheint ins Fenster (max)",
"sunNotInWinMin": "Sonne scheint nicht ins Fenster (min)",
"sunNotInWinMax": "Sonne scheint nicht ins Fenster (max)",
"ruleMin": "__org__ [min rule __number__]",
"ruleMax": "__org__ [max rule __number__]",
"startDelay": "verzögerter Start [__date__]"
},
"text": {
"blind": "Rollladen Einstellungen",
"time": "Es werden nur Zeilen ausgewertet, bei denen die Eigenschaft <b>nicht verwendet</b> oder <em>true</em> ist. <br> <b>bis</b>: Die erste übereinstimmende Zeile wird verwendet, wobei die definierte Zeit <b>nicht verwendet</b> oder größer als <b>now</b> ist. <br> <b>von</b>: Die letzte übereinstimmende Zeile wird verwendet, wo die angegebene Zeit <b>nicht verwendet</b> oder weniger als <b>der aktuelle Zeitpunkt</b> ist. <br>",
"blindLevelDefault": "Wenn keine andere Vorgabe (Zeitregel, Regel, Sonnensteuerung) zutrifft, wird diese Rollladenposition, Lamelleneinstellung und Topic genutzt. Bei beschränkender Sonnen-Steuerung ist die die Rollladenposition, wenn die Sonne nicht in das Fenster scheint.",
"payloadDefault":"Wenn keine Regel zutrifft, wird der folgende payload gesendet.",
"overwriteBlind": "manuelles Überschreiben der Rollladenposition",
"overwriteTimer": "manuelles Überschreiben der Regel",
"sunControlNotActive": "Nur Regelbasiert",
"sunControlMode": "Anstelle der standard Rollladenposition kann das Ausmaß in dem direktes Sonnenlicht in den Raum scheint eingeschränkt werden. <br><br>Der Modus kann über die eingehende Nachricht verändert werden. In diesem Falle ist der heir eingestellte Modus der maximal wählbare Modus. Der über eine nachricht eingestellte Modus wird im Node-Context persistiert und bleibt bei einem deploy erhalten.",
"windowAzimuth": "Darstellung der Ausrichtung des Fensters zum geografischen Norden (in Grad), wenn die Sonne in das Fenster fällt (Sonnenrichtung/Azimuth).",
"windowPos": "Fenster Eigenschaften, Messung vom Boden bis zum unter und Oberseite des Fensters",
"oversteer": "erlaubt das Übersteuern der Position in Abhängigkeit von der Sonne unter definierten Bedingungen wie Sonnenwinkel oder Wetter (z. B. Wolkenhimmel, Beleuchtung, etc.). Hiermit kann auch eine minimale oder maximaler Höhenwinkel definiert werden, wenn Berge/Gebäude, etc das Fenster verdecken.",
"sunControlMaximization": "<ul><li>Wenn keine Regel oder Überschreiben (Override) zutrifft,<ul><li>Wenn die Sonne <em>nicht</ em> in das Fenster scheint, wird die Rollladenhöhe die definierte <strong>Minimalposition</ strong> gesetzt. (Übersteuern wird ignoriert)</ li><li>Wenn sich die Sonne im Fenster befindet</ li><li>Wenn eine Übersteueruzng aufgesetzt ist und die bedingung zutrifft, wird der Behang auf die Höhe des Übersteuerns gesetzt.< / li><li>Andernfalls wird die Behanghöhe auf die definierte <strong>Maximalposition</ strong> gesetzt.</ li></ ul></ li></ ul>",
"sunControlMinimization": "<ul><li>Wenn keine Regel oder Überschreiben (Override) zutrifft,<ul><li>Wenn die Sonne <em>nicht</ em> in das Fenster scheint, wird die Rollladenhöhe die definierte <strong>Maximalposition</ strong> gesetzt. (Übersteuern wird ignoriert)</ li><li>Wenn sich die Sonne im Fenster befindet</ li><li>Wenn eine Übersteueruzng aufgesetzt ist und die bedingung zutrifft, wird der Behang auf die Höhe des Übersteuerns gesetzt.< / li><li>Andernfalls wird die Behanghöhe auf die definierte <strong>Minimalposition</ strong> gesetzt.</ li></ ul></ li></ ul>",
"sunControlRestriction": "Wenn keine Regel oder Überschreiben (Override) zutrifft, berechnet der Knoten die entsprechende Blindposition, um die Menge des direkten Sonnenlichts, das in den Raum fällt, zu begrenzen.",
"sunCtrlLoF": "Definition inwieweit direktes Sonnenlicht durch das Fenster in den Raum gelangen darf (als Länge auf dem Boden).",
"sunCtrlRestrict": "Begrenzen Sie die Häufigkeit von Änderungen nach Zeit und / oder Änderungsgröße (Delta).",
"ruleCondition": "Bedingung unter welcher diese Regel beachtet wird.<br/><small>Es gibt keine Operatorrangfolge! Die Verknüpfung von mehreren Bedingungen mit <kbd>UND</kbd> bzw. <kbd>ODER</kbd> bedeutet nur die jeweilige Bedingung zu den vorhergehenden. Die Auswertung wird abgebrochen sobald der Ausdruck true ergibt.</small>",
"enhanced":"erweiterte Einstellungen",
"startDelayTime":"Bei einem Wert von 0 wird die node nach einem Deploy oder Node-Red Start erst mit der nächsten eingehenden nachricht aktiviert und bis dahin auf keine Ereignise reagieren!"
}
},
"errors": {
"warning": "Warnung: __message__",
"error": "Fehler: __message__",

@@ -308,5 +467,11 @@ "error-title": "interner Fehler",

"unknownPropertyOperator": "Fehler, der verwendete Operator __propertyOp__=\"__propertyOpText__\" ist unbekannt!",
"unknownCompareOperator": "Fehler, der verwendete vergleichs-Operator \"__operator__\" ist unbekannt!",
"unknownCompareOperator": "Fehler, der verwendete vergleichs-Operator \"__operator__\" ist unbekannt! (Vergleich \"__opTypeA__.__opValueA__\" mit \"__opTypeB__.__opValueB__\")",
"notEvaluableProperty":"Kann den Wert von __type__.__value__ nicht ermitteln",
"notEvaluablePropertyAdd":"\"__err__\", kann den Wert von __type__.__value__ nicht ermitteln!"
"notEvaluablePropertyAdd":"\"__err__\", kann den Wert von __type__.__value__ nicht ermitteln!",
"notEvaluablePropertyUsedValue": "kann den Wert von __type__.__value__ nicht ermitteln, verwende \"__usedValue__\"!",
"invalidParameter":"Der Parameter \"__param__\" hat ist ungültig \"__type__\" (nutze __newValue__)",
"invalid-expr": "Ungültiger JSONata Austruck: __error__",
"getPropertyData": "Fehler bei der Ermittlung der Bedingung: \"__message__\" Zeit wird nicht verwendet",
"error-time": "Fehler bei der Ermittlung der Zeit: __message__",
"usingTempValue": "Wert von __type__.__value__ kann nicht ermitteln werden und es wird der gespeicherte Wert \"__usedValue__\" verwendet!"
},

@@ -313,0 +478,0 @@ "position-config": {

@@ -5,4 +5,2 @@ {

"azimuthpos":"Sonnenrichtung",
"between":"zwischen",
"and":"und",
"start": "Start",

@@ -9,0 +7,0 @@ "startOffset":"Start Offset",

@@ -19,14 +19,7 @@ {

"onceDelay": "Sekunden",
"validForDays":"gültig für Tage",
"validForMonths":"gültig für Monate",
"validForDates":"Gültigkeitsdauer (Jahr wird ignoriert)",
"specialDays":"spezielle Tage",
"onlyEvenDays":"nur gerade",
"onlyOddDays":"nur ungerade",
"fewDays": "ein paar Tage",
"fewMonths": "ein paar Monate",
"between":"zwischen",
"and":"und",
"interval-amount":"feste Anzahl zwischen den Zeitpunkten",
"count":"Anzahl"
"count":"Anzahl",
"intervalStart":"beginnend von"
},

@@ -40,2 +33,3 @@ "placeholder": {

"payload": "payload der gesendeten Nachricht",
"intervalCount":"Anzahl",
"time": "Zeitpunkt für das Senden der Nachricht",

@@ -42,0 +36,0 @@ "timeOffset": "offset der Zeit",

@@ -29,7 +29,2 @@ {

"showEnhSettings":"Erweiterte Einstellungen",
"validForDays":"gültig für Tage",
"validForMonths":"gültig für Monate",
"specialDays":"spezielle Tage",
"onlyEvenDays":"nur gerade",
"onlyOddDays":"nur ungerade",
"timeRestrictions":"Zeit begrenzen",

@@ -66,5 +61,7 @@ "internally":"👇 ist hier definiert"

"only-odd-day": "Kein ungerader Tag!",
"only-even-day": "Kein gerader Tag"
"only-even-day": "Kein gerader Tag!",
"only-odd-week": "Keine ungerade Woche!",
"only-even-week": "Keine gerade Woche!"
}
}
}

@@ -6,3 +6,2 @@ {

"blind-control-palette": "blind",
"output1": "new blind level",
"output2": "state object",

@@ -17,32 +16,6 @@ "windowTop": "window top",

"blindLevelDefault": "default position",
"slatPosDefault": "default slat",
"blindLevelMin": "min position",
"blindLevelMax": "max position",
"overwriteExpire": "expire",
"ruleCondition": "only if",
"ruleConditionThreshold": "threshold",
"ruleAndOr": "and/or",
"ruleCondNone": "N/A",
"ruleCondAnd": "and",
"ruleCondOr": "or",
"ruleTimeFrom": "↧ from",
"ruleTimeUntil": "↥ until",
"ruleTimeNone": "N/A",
"ruleTimeMax": "no later than (max)",
"ruleTimeMin": "at the earliest (min)",
"ruleTimeDays": "only on day",
"ruleTimeMonths": "only on month",
"ruleDescription": "Description",
"ruleBlindLevel": "blind position",
"ruleTopic": "Topic: ",
"ruleResetOverwrite": "overwrite expire when rule gets active",
"ruleOverwrite": "overwrite",
"ruleImportance":"Override Importance",
"ruleTimeLimitStart": "only from",
"ruleTimeLimitEnd": "to",
"ruleLevelAbs": "↕ absolute",
"ruleLevelMin": "⭳❗ minimum (oversteer)",
"ruleLevelMax": "⭱️❗ maximum (oversteer)",
"ruleLevelResetMin": "⭳✋ reset minimum",
"ruleLevelResetMax": "⭱️✋ reset maximum",
"ruleLevelND": "use default level (e.g. sun control)",
"sunControlMode": "mode",

@@ -52,4 +25,8 @@ "sunControlOff": "no restriction, no sun control",

"sunControlMaximize": "maximize sunlight (⛄ Winter)",
"sunControlMinimize": "minimize sunlight (🕶️)",
"sunControlNoMatter": "∞ no matter what mode",
"sunControlRestrictOnly": "🌞 only in Mode restrict sunlight",
"sunControlMaximizeOnly": "⛄ only in Mode maximize sunlight",
"sunControlMinimizeOnly": "🕶️ only in Mode minimize sunlight",
"sunFloorLength": "length on the floor",
"sunMinAltitude": "min altitude threshold",
"sunMinDelta": "min delta",

@@ -62,36 +39,17 @@ "sunTopic": "Topic 🌞/⛄",

"oversteerBlindPos": "blind position",
"oversteer2Value": "oversteer add",
"oversteer2Threshold": "Threshold",
"oversteer2BlindPos": "blind position",
"oversteer3Value": "oversteer add",
"oversteer3Threshold": "Threshold",
"oversteer3BlindPos": "blind position",
"oversteerSlatPos": "slat position",
"oversteerTopic":"oversteer topic",
"smoothTime": "smoothTime",
"showEnhSettings": "Enhanced settings",
"outputs": "Outputs",
"offset": "time offset",
"offset-timeMin": "earliest (min) offset",
"offset-timeMax": "latest (max) offset",
"singleOutput": "single (1)",
"splitOutput": "dual (2)",
"btnAdd": "add",
"btnSort": "sort",
"btnClear": "clear",
"dialogtitle": "Edit Rule",
"autoTrigger": "auto trigger",
"autoTrigger2": "dynamic, but max every",
"autoTrigger2": "dynamic, but at least every",
"startDelay": "delay output on start",
"timeconstraintshow": "show additional time constraints",
"timeconstrainthide": "hide additional time constraints",
"validForDays": "valid days",
"validForMonths": "valid months",
"validForDates":"valid period (year is ignored)",
"specialDays": "special days",
"onlyEven": "only even",
"onlyOdd": "only odd",
"onlyEvenDays": "only even days",
"onlyOddDays": "only odd days",
"editRule": "edit the rule",
"duplicateRule": "duplicate the rule"
"addId": "add. ID",
"resultContainer": "Output 1 msg object definition"
},

@@ -106,9 +64,10 @@ "placeholder": {

"blindClosedPos": "0",
"blindLevelDefault": "position if no other used",
"blindLevelDefault": "blind position if no other used",
"slatPosDefault": "slat position if no other used",
"blindLevelMin": "minimum position if sun calculated position",
"blindLevelMax": "maximum position if sun calculated position",
"blindSlatSun": "slat position if sun coltrolled",
"sunControlMode": "select if sun control is active and how it should working",
"overwriteExpire": "(opt) the duration a manual setting will remain",
"sunFloorLength": "(opt) the extent to which direct sunlight is to be allowed into the room through the window, defined as a length on the floor",
"sunMinAltitude": "(opt) minimum altitude of the sun for determination of blind position",
"sunMinDelta": "(opt) define the minimum change of the blind position",

@@ -121,10 +80,11 @@ "oversteerValue": "value to compare",

"expiryperiod": "120",
"outputs": "number of outputs",
"btnAdd": "add new empty rule",
"btnSort": "sort all rules, Attention this can change the behavior!",
"btnClear": "removes all rules from list",
"condoperand": "operand",
"btnExport": "Copy all rules to clipboard.",
"btnImport": "Past rules from Clipboard to the list (append).",
"time": "time",
"offset": "time offset",
"level": "level",
"slat": "slat",
"ruleImportance": "defined a importance how the rule should be work to overrides. Only Overrides with a higher or same importance can override the rule.",

@@ -142,18 +102,11 @@ "ruleTopic": "allows to define a seperate topic for outgoing message per rule, if not defined default topic will be used",

"start":"tt.mm",
"end":"tt.mm"
"end":"tt.mm",
"addId": "additional ID"
},
"text": {
"blind": "blind settings",
"time": "Time control:Only rows will be evaluated, where property is <b>not used</b> or matches the selected value. <br><b>until</b>:The first matching line will used, where defined time is <b>not used</b> or greater than <b>now</b>.<br><b>from</b>:The last matching line will used, where defined time is <b>not used</b> or less than <b>now</b>.<br>",
"blindLevelDefault": "if no rule matches the following position will be used, On sun light restriction this is the blind level wenn sun is not in the window.",
"overwrite": "manual overwrite of the blind position",
"sunControlNotActive": "Only rule control",
"sunControlMode": "Instead of the default blind position there can be restricted the extent to which direct sunlight may shine into the room.",
"windowAzimuth": "representing the orientation of the window to geographical north (in degrees) when the sun falls into the window (sun azimuth).",
"windowPos": "window settings, measurement from the floor to bottom and top of the window covered by the blind",
"oversteer": "allows to oversteer the position depending on the sun under defined condition such as weather (for example sky covered by clouds, lighting, ...)",
"sunControlMaximization": "<ul><li>If no rule or override matches<ul><li>If the sun is <em>not</em> in the window the blind will set to defined <strong>min position</strong>. (oversteer will be ignored)</li><li>If the sun is in the window</li><li>If any oversteer data are setup and oversteer conditions are fulfilled the blind will set to the defined oversteer blind position.</li><li>otherwise the blind level is set to defined <strong>max position</strong>.</li></ul></li></ul>",
"sunControlRestriction": "If no rule or override matches, the node calculates the appropriate blind position to restrict the amount of direct sunlight entering the room.",
"sunCtrlLoF": "The limit to what extent direct sunlight is to be allowed into the room through the window, defined as a length on the floor.",
"sunCtrlRestrict": "Limit the frequency of changes by time and/or delta; set the minimum altitude (in degree) of the sun"
"tabs-label": {
"general":"Name and config",
"default":"Default settings",
"time":"Time/Rule control",
"sun-control":"sun control",
"output":"Output and other"
},

@@ -170,4 +123,8 @@ "typeOptions": {

},
"ctrlObj": {
"full": "complete object",
"rule": "rule object (if rule is active)"
},
"tips": {
"documentation": "<a href=\"https://github.com/rdmtc/node-red-contrib-sun-position/wiki/blind-control\">Documentation and examples</a>"
"documentation": "<a href=\"https://github.com/rdmtc/node-red-contrib-sun-position/wiki/blind-control\" target=\"_blank\">Documentation and examples</a>"
},

@@ -178,7 +135,5 @@ "errors": {

"getBlindPosData": "error getting blind level: __message__",
"smoothTimeToolong": "The selected smooth is too long!!",
"usingTempValue": "Could not evaluate __type__.__value__ and using stored value \"__usedValue__\"!",
"notEvaluableProperty": "could not evaluate __type__.__value__, using \"__usedValue__\"!"
"smoothTimeToolong": "The selected smooth is too long!!"
}
}
}

@@ -6,3 +6,2 @@ {

"clock-timer-palette": "clock timer",
"output1": "payload based on rule",
"output2": "state object",

@@ -13,52 +12,16 @@ "payloadDefault": "payload",

"overwriteExpire": "expire",
"ruleCondition": "only if",
"ruleConditionThreshold": "threshold",
"ruleAndOr": "and/or",
"ruleCondNone": "N/A",
"ruleCondAnd": "and",
"ruleCondOr": "or",
"ruleTimeFrom": "↧ from",
"ruleTimeUntil": "↥ until",
"ruleTimeNone": "N/A",
"ruleTimeMax": "no later than (max)",
"ruleTimeMin": "at the earliest (min)",
"ruleTimeDays": "only on day",
"ruleTimeMonths": "only on month",
"ruleDescription": "Description",
"rulePayload": "Payload: ",
"rulePayloadND": "No Payload",
"ruleTopic": "Topic: ",
"ruleResetOverwrite": "overwrite expire when rule gets active",
"ruleOverwrite": "overwrite",
"ruleImportance":"Override Importance",
"ruleTimeLimitStart": "only from",
"ruleTimeLimitEnd": "to",
"time": "time",
"name": "name",
"showEnhSettings": "Enhanced settings",
"outputs": "Outputs",
"offset": "time offset",
"offset-timeMin": "earliest (min) offset",
"offset-timeMax": "latest (max) offset",
"singleOutput": "single (1)",
"splitOutput": "dual (2)",
"btnAdd": "add",
"btnSort": "sort",
"btnClear": "clear",
"dialogtitle": "Edit Rule",
"autoTrigger": "auto trigger",
"autoTrigger2": "dynamic, but max every",
"autoTrigger2": "dynamic, but at least every",
"startDelay": "delay output on start",
"timeconstraintshow": "show additional time constraints",
"timeconstrainthide": "hide additional time constraints",
"validForDays": "valid days",
"validForMonths": "valid months",
"validForDates":"valid period (year is ignored)",
"specialDays": "special days",
"onlyEven": "only even",
"onlyOdd": "only odd",
"onlyEvenDays": "only even days",
"onlyOddDays": "only odd days",
"editRule": "edit the rule",
"duplicateRule": "duplicate the rule"
"addId": "add. ID",
"resultContainer": "Output 1 msg object definition"
},

@@ -72,7 +35,7 @@ "placeholder": {

"expiryperiod": "120",
"outputs": "number of outputs",
"btnAdd": "add new empty rule",
"btnSort": "sort all rules, Attention this can change the behavior!",
"btnClear": "removes all rules from list",
"condoperand": "operand",
"btnExport": "Copy all rules to clipboard.",
"btnImport": "Past rules from Clipboard to the list (append).",
"time": "time",

@@ -86,11 +49,14 @@ "offset": "time offset",

"autoTrigger": "automatic triggers new calculation of the rule in a dynamic changing time interval",
"autoTriggerTime": "10",
"startDelay": "0 - off",
"startDelay2": "delay any output to the first (or only) output on start (Node-Red start, Deplay, ...). Set to 0 to deactivate.",
"start":"tt.mm",
"end":"tt.mm"
"end":"tt.mm",
"addId": "additional ID"
},
"text": {
"time": "Time control:Only rows will be evaluated, where property is <b>not used</b> or matches the selected value. <br><b>until</b>:The first matching line will used, where defined time is <b>not used</b> or greater than <b>now</b>.<br><b>from</b>:The last matching line will used, where defined time is <b>not used</b> or less than <b>now</b>.<br>",
"payloadDefault": "if no rule matches the following payload will be used.",
"overwrite": "manual overwrite of the rule payload"
"tabs-label": {
"general":"Name and config",
"default":"Default and Ooverwrite",
"time":"Time control",
"output":"Output and other"
},

@@ -97,0 +63,0 @@ "tips": {

{
"moon-position": {
"label": {
"azimuthpos":"azimuth Position",
"between":"between",
"and":"and"
"azimuthpos":"azimuth Position"
},

@@ -8,0 +6,0 @@ "tips": {

@@ -6,2 +6,3 @@ {

"infoText":"The configuration must be created and deployed for the settings page to work properly.",
"loadingInfo":"loading data...",
"binary": "binary",

@@ -20,6 +21,18 @@ "json": "json",

"validForMonths": "valid months",
"validForDates": "Gültigkeitsdauer (Jahr wird ignoriert)",
"specialDays": "special days",
"onlyEvenDays":"only even",
"onlyOddDays":"only odd"
"validForDates": "validForDates (year will be ignored)",
"specialLimits": "limit",
"onlyEvenDays":"only even days",
"onlyOddDays":"only odd days",
"onlyEvenWeeks":"only even weeks",
"onlyOddWeeks":"only odd weeks",
"between":"between",
"and": "and",
"or": "or",
"enabled": "enabled",
"disabled": "disabled",
"cancel":"Cancel",
"ok":"Ok",
"randNum":"random till",
"randNumCachedDay":"random (daily) till",
"randNumCachedWeek":"random (weekly) till"
},

@@ -30,2 +43,4 @@ "types": {

"datespecific":"timestamp enhanced",
"nodeId":"node name",
"nodeName":"node ID",
"timeentered":"time (next)",

@@ -39,3 +54,5 @@ "dateentered":"date",

"timemoon":"moon time",
"randomNumber":"random number",
"randomNumber":"random number (continuously new)",
"randmNumCachedDay":"random number (once a day)",
"randmNumCachedWeek":"random number (once a week)",
"numPercent":"number in percent %",

@@ -48,2 +65,6 @@ "suncalc":"sun calculation",

"sunElevationRad":"Elevation of sun (rad)",
"numAzimuth":"Azimuth angle",
"numAltitude":"Elevation angle",
"numAzimuthRad":"Azimuth angle (rad)",
"numAltitudeRad":"Elevation angle (rad)",
"sunTimeByElevation":"time by elevation",

@@ -60,3 +81,3 @@ "sunTimeByAzimuth":"time by azimuth",

"levelfree": "Level entered",
"levelND": "N/D - use default, sun control or reset",
"levelND": "N/D - use default or sun control",
"PlTRes":"msg.payload if msg.topic contains",

@@ -71,3 +92,11 @@ "isDST":"is DST (true/false)",

"sunControlRestrict": "restrict sunlight (🌞 Summer)",
"sunControlMaximize": "maximize sunlight (⛄ Winter)"
"sunControlMaximize": "maximize sunlight (⛄ Winter)",
"sunControlMinimize": "minimize sunlight (🕶️)",
"payload":"payload",
"level":"blind level",
"levelInverse":"blind level inverse",
"slat":"blind slat",
"topic":"topic",
"ctrlObj":"status object",
"strPlaceholder": "string with placeholder"
},

@@ -119,3 +148,3 @@ "typeOptions": {

"waningGibbousMoon": "Waning Gibbous 🌖",
"lastQuarterMoon": "Last Quarter 🌗",
"thirdQuarterMoon": "Third Quarter 🌗",
"waningCrescentMoon": "Waning Crescent 🌘",

@@ -216,3 +245,4 @@ "PlTRes":"msg.payload if msg.topic contains \"__topic__\""

"milliseconds - UNIX timestamp",
"ECMA-262 - JSON Date representation",
"ECMA-262 - simple JSON Date representation",
"ISO8601",
"try different text Formats, prefer day first like d/M/y",

@@ -324,5 +354,55 @@ "try different text Formats, prefer month first like M/d/y",

"containEvery": "containEvery"
},
"units": {
"ms": "ms",
"sec": "s",
"min": "min",
"hour": "h",
"day": "day",
"days": "days",
"week": "week",
"weeks": "weeks"
}
},
"ruleCtrl": {
"label": {
"outDated": "✎ Please edit this rule.",
"isInValid": "⚠️ Rule is invalid and needs to be changed!!",
"ruleIsOutdated": "⚠️ This rule is invalid and has to be adjusted because it no longer works!",
"ruleTimeMin": "at the earliest (min)",
"ruleTimeMax": "no later than (max)",
"ruleTimeLimit": "limited",
"ruleTimeLimitStart": "only from",
"ruleTimeLimitEnd": "to",
"ruleTimeMonths": "only on month",
"ruleTimeDays": "only on day",
"ruleTopic": "Topic",
"ruleSlat": "Slat",
"rulePayload": "Payload: ",
"rulePayloadND": "No Payload",
"ruleResetOverwrite": "overwrite should expire when rule gets active",
"ruleDescription": "Description",
"ruleBlindLevel": "blind position",
"ruleBlindLevelMinimum": "⭳ minimum blind position",
"ruleBlindLevelMaximum": "⭱️ maximum blind position",
"ruleOverwrite": "overwrite",
"ruleImportance":"Importance",
"ruleLevelAbs": "↕ absolute",
"ruleLevelMin": "⭳❗ minimum (oversteer)",
"ruleLevelMax": "⭱️❗ maximum (oversteer)",
"ruleSlatOversteer": "Slat (oversteer)",
"ruleTopicOversteer": "Topic (oversteer)",
"ruleOff": "✋ send nothing",
"ruleLevelND": "use default level (e.g. sun control)",
"editRule": "edit the rule",
"duplicateRule": "duplicate the rule",
"ruleState": "enables or disables the rule",
"ruleTimeFrom": "↧ from",
"ruleTimeUntil": "↥ until",
"btnAdd": "add",
"btnSort": "sort",
"btnClear": "clear",
"btnExport": "",
"btnImport": ""
},
"reasons": {

@@ -336,3 +416,2 @@ "overwriteNoExpire": "position is overwritten with importance __importance__",

"rule": "position by fixed rule [__number__] __name__",
"sunMinAltitude": "sun below minimum altitude",
"sunMinDelta": "change is less ad min delta",

@@ -343,6 +422,8 @@ "sunNotInWin": "Sun not in window",

"sunCtrlMax": "__org__ (__level__ is above maximum)",
"oversteer": "sun position oversteers",
"oversteer": "sun position oversteer __pos__",
"smooth": "Position is not changed to __pos__ because not enough time has passed since the last change (time smooth)",
"sunInWinMin": "Sun in window (Level is minimum)",
"sunInWinMax": "Sun in window (Level is maximum)",
"sunNotInWinMin": "Sun not in window (Level is minimum)",
"sunNotInWinMax": "Sun not in window (Level is maximum)",
"ruleMin": "__org__ (__level__ is below minimum) [__number__] __name__",

@@ -360,3 +441,2 @@ "ruleMax": "__org__ (__level__ is above maximum) [__number__] __name__",

"rule": "by fixed rule [__number__] __name__",
"sunMinAltitude": "min altitude",
"sunMinDelta": "min delta",

@@ -367,9 +447,32 @@ "sunNotInWin": "no sun in window",

"sunCtrlMax": "__org__ (max)",
"oversteer": "oversteer",
"oversteer": "oversteer rule __pos__",
"smooth": "block change to __pos__",
"sunInWinMin": "Sun in window (min)",
"sunInWinMax": "Sun in window (max)",
"sunNotInWinMin": "Sun not in window (min)",
"sunNotInWinMax": "Sun not in window (max)",
"ruleMin": "__org__ [min rule __number__]",
"ruleMax": "__org__ [max rule __number__]",
"startDelay": "startup [__date__]"
},
"text": {
"blind": "blind settings",
"time": "Time control:Only rows will be evaluated, where property is <b>not used</b> or matches the selected value. <br><b>until</b>:The first matching line will used, where defined time is <b>not used</b> or greater than <b>now</b>.<br><b>from</b>:The last matching line will used, where defined time is <b>not used</b> or less than <b>now</b>.<br>",
"blindLevelDefault": "if no other settings matches (timerule, rule or sun-control) the following default settings for level, slat and the topic will be used. On sun light restriction this is the blind level wenn sun is not in the window.",
"payloadDefault": "if no rule matches the following payload will be used.",
"overwriteBlind": "manual overwrite of the blind position",
"overwriteTimer": "manual overwrite of the rule payload",
"sunControlNotActive": "Only rule control",
"sunControlMode": "Instead of the default blind position there can be restricted the extent to which direct sunlight may shine into the room.<br><br>The mode can be changed with an incomming message. Then this is the maximum possible mode which can selected. The value of the incomming message will be stored in the node's context and will persists a deploy.",
"windowAzimuth": "representing the orientation of the window to geographical north (in degrees) when the sun falls into the window (sun azimuth).",
"windowPos": "window settings, measurement from the floor to bottom and top of the window covered by the blind",
"oversteer": "allows to oversteer the position depending on the sun under defined condition such as elevation, weather (for example sky covered by clouds, lighting, ...) This can also be used to define a minimum or maximum elevation angle if mountains / buildings, etc. cover the window.",
"sunControlMaximization": "<ul><li>If no rule or override matches<ul><li>If the sun is <em>not</em> in the window the blind will set to defined <strong>minimum position</strong>. (oversteer will be ignored)</li><li>If the sun is in the window</li><li>If any oversteer data are setup and oversteer conditions are fulfilled the blind will set to the defined oversteer blind position.</li><li>otherwise the blind level is set to defined <strong>maximum position</strong>.</li></ul></li></ul>",
"sunControlMinimization": "<ul><li>If no rule or override matches<ul><li>If the sun is <em>not</em> in the window the blind will set to defined <strong>maximum position</strong>. (oversteer will be ignored)</li><li>If the sun is in the window</li><li>If any oversteer data are setup and oversteer conditions are fulfilled the blind will set to the defined oversteer blind position.</li><li>otherwise the blind level is set to defined <strong>minimum position</strong>.</li></ul></li></ul>",
"sunControlRestriction": "If no rule or override matches, the node calculates the appropriate blind position to restrict the amount of direct sunlight entering the room.",
"sunCtrlLoF": "The limit to what extent direct sunlight is to be allowed into the room through the window, defined as a length on the floor.",
"sunCtrlRestrict": "Limit the frequency of changes by time and/or delta",
"ruleCondition": "Condition under which this rule is observed.<br/><small>There is no operator precedence! The combination of several conditions with <kbd>AND</kbd> or <kbd>OR</kbd> only means the respective condition to the preceding ones. The evaluation is canceled as soon as the expression results in true.</small>",
"enhanced":"advanced settings",
"startDelayTime":"With a value of 0, the node will only be activated with the next incoming message after a deploy or node red start and will not react to any events until then!"
}

@@ -393,3 +496,4 @@ },

"getPropertyData": "error getting condition data: \"__message__\" skipping time",
"error-time": "Error get time: __message__"
"error-time": "Error get time: __message__",
"usingTempValue": "Could not evaluate __type__.__value__ and using stored value \"__usedValue__\"!"
},

@@ -396,0 +500,0 @@ "position-config": {

@@ -5,4 +5,2 @@ {

"azimuthpos":"azimuth Position",
"between":"between",
"and":"and",
"start": "Start",

@@ -9,0 +7,0 @@ "startOffset":"Start Offset",

@@ -17,2 +17,5 @@ {

},
"typeLabel":{
"input": "Input value"
},
"placeholder": {

@@ -23,2 +26,3 @@ "property": "Property",

"inputOffset": "Offset",
"nextOccurrence":"defines if the next occurrence or the date for the current day (which can be in the past)",
"result": "result",

@@ -25,0 +29,0 @@ "resultValue": "value",

@@ -22,6 +22,5 @@ {

"fewMonths": "few months",
"between":"between",
"and":"and",
"interval-amount":"fixed number between time",
"count":"Count"
"count":"Count",
"intervalStart":"start from"
},

@@ -35,2 +34,4 @@ "placeholder": {

"payload": "payload data of the send message",
"intervalCount":"count",
"intervalStart":"YYYY-MM-DDTHH:mm:ss",
"time": "time for inject",

@@ -37,0 +38,0 @@ "timeOffset": "offset of time",

@@ -20,2 +20,7 @@ {

},
"typeLabel":{
"timespan": "timespan between Inputs",
"operand1": "Input 1 value",
"operand2": "Input 2 value"
},
"placeholder": {

@@ -22,0 +27,0 @@ "operand": "Input",

@@ -34,10 +34,10 @@ {

"showEnhSettings":"Enhanced settings",
"validForDays":"valid days",
"validForMonths":"valid months",
"specialDays":"special days",
"onlyEvenDays":"only even",
"onlyOddDays":"only odd",
"timeRestrictions":"limit time",
"internally":"👇 is defined here"
"internally":"👇 is defined here",
"withinTimeValue": "in time payload",
"outOfTimeValue": "out of time payload"
},
"typeLabel":{
"input": "msg.payload of the input message"
},
"placeholder": {

@@ -60,3 +60,4 @@ "propertyStart": "Property for alternate start time",

"addTimes": "Here can be defined alternate times for start/end. If the given property is true the alternate start/end times will be used instead the normal ones. This can be used to have different start/end times for holidays or other special days.",
"documentation": "<a href=\"https://github.com/rdmtc/node-red-contrib-sun-position/wiki/within-time\">Documentation and examples</a>"
"documentation": "<a href=\"https://github.com/rdmtc/node-red-contrib-sun-position/wiki/within-time\">Documentation and examples</a>",
"outputValue":"Here can be defined the payload of the output 1 if the input message arrived within time or the payload of the message of output 2 if the message arrives out of the time."
},

@@ -72,5 +73,7 @@ "errors": {

"only-odd-day": "Not an odd Day!",
"only-even-day": "Not an even Day!"
"only-even-day": "Not an even Day!",
"only-odd-week": "Not an odd Week!",
"only-even-week": "Not an even Week!"
}
}
}

@@ -47,2 +47,3 @@ /********************************************

ports[0].payload = this.positionConfig.getMoonCalc(dNow, true, true, msg.latitude || msg.lat, msg.longitude || msg.lon);
ports[0].topic = this.topic;

@@ -49,0 +50,0 @@ if (!ports[0].payload.azimuth) {

@@ -9,125 +9,126 @@ /************************************************************************/

operatorsGroups: [
{id: 'default', label: 'compare Timestamp'},
{ id: 'other', label: 'always'}
{ id: 'default', label: 'compare Timestamp', i18n: 'common.operatorsGroups.0'},
{ id: 'other', label: 'always', i18n: 'common.operatorsGroups.1'}
],
operators: [
{id: 1, group: 'default', label: '==', text: 'equal'},
{id: 2, group: 'default', label: '!=', text: 'unequal'},
{id: 3, group: 'default', label: '>', text: 'greater'},
{id: 4, group: 'default', label: '>=', text: 'greater or equal'},
{id: 5, group: 'default', label: '<', text: 'lesser'},
{id: 6, group: 'default', label: '<=', text: 'lesser or equal'},
{id: 99, group: 'other', label: 'otherwise', text: 'otherwise'}
{id: 1, group: 'default', label: '==', text: 'equal', i18n: 'common.operators.0'},
{id: 2, group: 'default', label: '!=', text: 'unequal', i18n: 'common.operators.1'},
{id: 3, group: 'default', label: '>', text: 'greater', i18n: 'common.operators.2'},
{id: 4, group: 'default', label: '>=', text: 'greater or equal', i18n: 'common.operators.3'},
{id: 5, group: 'default', label: '<', text: 'lesser', i18n: 'common.operators.4'},
{id: 6, group: 'default', label: '<=', text: 'lesser or equal', i18n: 'common.operators.5'},
{id: 99, group: 'other', label: 'otherwise', text: 'otherwise', i18n: 'common.operators.6'}
], operatorTypesGroups: [
{id: 'default', label: 'include into compare'},
{id: 'spec', label: 'special'}
{id: 'default', label: 'include into compare', i18n: 'common.operatorTypesGroups.0'},
{id: 'spec', label: 'special', i18n: 'common.operatorTypesGroups.1'}
], operatorTypes: [
{id: 11, group: 'default', label: 'Milliseconds'},
{id: 12, group: 'default', label: 'Seconds'},
{id: 13, group: 'default', label: 'Minutes'},
{id: 14, group: 'default', label: 'Hours'},
{id: 15, group: 'default', label: 'Day of Month'},
{id: 16, group: 'default', label: 'Month'},
{id: 17, group: 'default', label: 'Year'},
{id: 18, group: 'spec', label: 'Day of Week'}
{id: 11, group: 'default', label: 'Milliseconds', i18n: 'common.operatorTypes.0'},
{id: 12, group: 'default', label: 'Seconds', i18n: 'common.operatorTypes.1'},
{id: 13, group: 'default', label: 'Minutes', i18n: 'common.operatorTypes.2'},
{id: 14, group: 'default', label: 'Hours', i18n: 'common.operatorTypes.3'},
{id: 15, group: 'default', label: 'Day of Month', i18n: 'common.operatorTypes.4'},
{id: 16, group: 'default', label: 'Month', i18n: 'common.operatorTypes.5'},
{id: 17, group: 'default', label: 'Year', i18n: 'common.operatorTypes.6'},
{id: 18, group: 'spec', label: 'Day of Week', i18n: 'common.operatorTypes.7'}
], outputTSFormatsGroups: [
{id: 'time', label: 'timestamp (number)'},
{id: 'timeRounded', label: 'timestamp rounded (number)'},
{id: 'string', label: 'Text'}
{id: 'time', label: 'timestamp (number)', i18n: 'common.outputTSFormatsGroups.0'},
{id: 'timeRounded', label: 'timestamp rounded (number)', i18n: 'common.outputTSFormatsGroups.1'},
{id: 'string', label: 'Text', i18n: 'common.outputTSFormatsGroups.2'}
], outputTSFormats: [
{id: 0, group: 'time', name: 'ms', label: 'milliseconds'},
{id: 1, group: 'time', name: 'sec', label: 'seconds'},
{id: 2, group: 'time', name: 'min', label: 'minutes'},
{id: 3, group: 'time', name: 'hour', label: 'hours'},
{id: 4, group: 'time', name: 'days', label: 'days'},
{id: 5, group: 'time', name: 'weeks', label: 'weeks'},
{id: 6, group: 'time', name: 'month', label: 'month'},
{id: 7, group: 'time', name: 'years', label: 'years'},
{id: 11, group: 'timeRounded', name: 'sec', label: 'seconds'},
{id: 12, group: 'timeRounded', name: 'min', label: 'minutes'},
{id: 13, group: 'timeRounded', name: 'hour', label: 'hours'},
{id: 14, group: 'timeRounded', name: 'days', label: 'days'},
{id: 15, group: 'timeRounded', name: 'weeks', label: 'weeks'},
{id: 16, group: 'timeRounded', name: 'month', label: 'month'},
{id: 17, group: 'timeRounded', name: 'years', label: 'years'},
{id: 99, group: 'string', name: 'Other', label: 'Other'}
{id: 0, group: 'time', name: 'ms', label: 'milliseconds', i18n: 'common.outputTSFormats.0'},
{id: 1, group: 'time', name: 'sec', label: 'seconds', i18n: 'common.outputTSFormats.1'},
{id: 2, group: 'time', name: 'min', label: 'minutes', i18n: 'common.outputTSFormats.2'},
{id: 3, group: 'time', name: 'hour', label: 'hours', i18n: 'common.outputTSFormats.3'},
{id: 4, group: 'time', name: 'days', label: 'days', i18n: 'common.outputTSFormats.4'},
{id: 5, group: 'time', name: 'weeks', label: 'weeks', i18n: 'common.outputTSFormats.5'},
{id: 6, group: 'time', name: 'month', label: 'month', i18n: 'common.outputTSFormats.6'},
{id: 7, group: 'time', name: 'years', label: 'years', i18n: 'common.outputTSFormats.7'},
{id: 11, group: 'timeRounded', name: 'sec', label: 'seconds', i18n: 'common.outputTSFormats.8'},
{id: 12, group: 'timeRounded', name: 'min', label: 'minutes', i18n: 'common.outputTSFormats.9'},
{id: 13, group: 'timeRounded', name: 'hour', label: 'hours', i18n: 'common.outputTSFormats.10'},
{id: 14, group: 'timeRounded', name: 'days', label: 'days', i18n: 'common.outputTSFormats.11'},
{id: 15, group: 'timeRounded', name: 'weeks', label: 'weeks', i18n: 'common.outputTSFormats.12'},
{id: 16, group: 'timeRounded', name: 'month', label: 'month', i18n: 'common.outputTSFormats.13'},
{id: 17, group: 'timeRounded', name: 'years', label: 'years', i18n: 'common.outputTSFormats.14'},
{id: 99, group: 'string', name: 'Other', label: 'Other', i18n: 'common.outputTSFormats.15'}
], outputFormatsGroups: [
{id: 'number', label: 'Number'},
{id: 'string', label: 'Text (string)'},
{id: 'time', label: 'time (number) since emit'},
{id: 'dayOfWeek', label: 'day of week'},
{id: 'dayOfYear', label: 'day of year'},
{id: 'WeekOfYear', label: 'week of year'},
{id: 'other', label: 'Other'}
{id: 'number', label: 'Number', i18n: 'common.outputFormatsGroups.0'},
{id: 'string', label: 'Text (string)', i18n: 'common.outputFormatsGroups.1'},
{id: 'time', label: 'time (number) since emit', i18n: 'common.outputFormatsGroups.2'},
{id: 'dayOfWeek', label: 'day of week', i18n: 'common.outputFormatsGroups.3'},
{id: 'dayOfYear', label: 'day of year', i18n: 'common.outputFormatsGroups.4'},
{id: 'WeekOfYear', label: 'week of year', i18n: 'common.outputFormatsGroups.5'},
{id: 'other', label: 'Other', i18n: 'common.outputFormatsGroups.6'}
], outputFormats: [
{id: 0, group: 'number', name: 'UNIX', label: 'milliseconds UNIX timestamp'},
{id: 10, group: 'number', name: 'YYYYMMDDHHMMSS', label: 'YYYYMMDDHHMMSS'},
{id: 11, group: 'number', name: 'YYYYMMDD_HHMMSS', label: 'YYYYMMDD.HHMMSS'},
{id: 1, group: 'string', name: 'UTC', label: 'UTC date and time' },
{id: 2, group: 'string', name: 'local', label: 'local date and time'},
{id: 3, group: 'string', name: 'localTime', label: 'local time'},
{id: 12, group: 'string', name: 'localDate', label: 'local date'},
{id: 5, group: 'string', name: 'ISO', label: 'ISO date and time'},
{id: 18, group: 'string', name: 'ISO-2', label: 'ISO date and time of local timezone' },
{id: 6, group: 'time', name: 'ms', label: 'milliseconds'},
{id: 7, group: 'time', name: 'sec', label: 'seconds'},
{id: 8, group: 'time', name: 'min', label: 'minutes'},
{id: 9, group: 'time', name: 'hour', label: 'hours'},
{id: 16, group: 'dayOfWeek', name: 'Day Name', label: 'Day Name, e.g. Monday, 22.12.'},
{id: 17, group: 'dayOfWeek', name: 'Day', label: 'Day in relative, e.g. Today, 22.12.'},
{id: 19, group: 'WeekOfYear', name: 'week number', label: 'Number of week e.g. 22'},
{id: 20, group: 'WeekOfYear', name: 'is week even', label: 'Boolean if week is even'},
{id: 21, group: 'dayOfYear', name: 'day number', label: 'Number of day e.g. 365'},
{id: 22, group: 'dayOfYear', name: 'is day even', label: 'Boolean if day is even'},
{id: -1, group: 'other', name: 'object', label: 'as object'},
{id: 99, group: 'other', name: 'free definition', label: 'Other'}
{id: 0, group: 'number', name: 'UNIX', label: 'milliseconds UNIX timestamp', i18n: 'common.outputFormats.0'},
{id: 10, group: 'number', name: 'YYYYMMDDHHMMSS', label: 'YYYYMMDDHHMMSS', i18n: 'common.outputFormats.1'},
{id: 11, group: 'number', name: 'YYYYMMDD_HHMMSS', label: 'YYYYMMDD.HHMMSS', i18n: 'common.outputFormats.2'},
{id: 1, group: 'string', name: 'UTC', label: 'UTC date and time', i18n: 'common.outputFormats.3'},
{id: 2, group: 'string', name: 'local', label: 'local date and time', i18n: 'common.outputFormats.4'},
{id: 3, group: 'string', name: 'localTime', label: 'local time', i18n: 'common.outputFormats.5'},
{id: 12, group: 'string', name: 'localDate', label: 'local date', i18n: 'common.outputFormats.6'},
{id: 5, group: 'string', name: 'ISO', label: 'ISO date and time', i18n: 'common.outputFormats.7'},
{id: 18, group: 'string', name: 'ISO-2', label: 'ISO date and time of local timezone', i18n: 'common.outputFormats.8'},
{id: 6, group: 'time', name: 'ms', label: 'milliseconds', i18n: 'common.outputFormats.9'},
{id: 7, group: 'time', name: 'sec', label: 'seconds', i18n: 'common.outputFormats.10'},
{id: 8, group: 'time', name: 'min', label: 'minutes', i18n: 'common.outputFormats.11'},
{id: 9, group: 'time', name: 'hour', label: 'hours', i18n: 'common.outputFormats.12'},
{id: 16, group: 'dayOfWeek', name: 'Day Name', label: 'Day Name, e.g. Monday, 22.12.', i18n: 'common.outputFormats.13'},
{id: 17, group: 'dayOfWeek', name: 'Day', label: 'Day in relative, e.g. Today, 22.12.', i18n: 'common.outputFormats.14'},
{id: 19, group: 'WeekOfYear', name: 'week number', label: 'Number of week e.g. 22', i18n: 'common.outputFormats.15'},
{id: 20, group: 'WeekOfYear', name: 'is week even', label: 'Boolean if week is even', i18n: 'common.outputFormats.16'},
{id: 21, group: 'dayOfYear', name: 'day number', label: 'Number of day e.g. 365', i18n: 'common.outputFormats.17'},
{id: 22, group: 'dayOfYear', name: 'is day even', label: 'Boolean if day is even', i18n: 'common.outputFormats.18'},
{id: -1, group: 'other', name: 'object', label: 'as object', i18n: 'common.outputFormats.19'},
{id: 99, group: 'other', name: 'free definition', label: 'Other', i18n: 'common.outputFormats.20'}
], parseFormatsGroups: [
{id: 'number', label: 'Number'},
{id: 'string', label: 'Text (string)'},
{id: 'other', label: 'Other'}
{id: 'number', label: 'Number', i18n: 'common.parseFormatsGroups.0'},
{id: 'string', label: 'Text (string)', i18n: 'common.parseFormatsGroups.1'},
{id: 'other', label: 'Other', i18n: 'common.parseFormatsGroups.2'}
], parseFormats: [
{id: 0, group: 'number', label: 'milliseconds UNIX timestamp', add: 'xxx'},
{id: 1, group: 'string', label: 'ECMA-262', add: 'standard JSON Date representation'},
{id: 2, group: 'string', label: 'try different text Formats, prefer day first like d/M/y (e.g. European format)', add: 'will try different formats, prefer European formats'},
{id: 3, group: 'string', label: 'try different text Formats, prefer month first like M/d/y (e.g. American format)', add: 'will try different formats, prefer American formats'},
{id: 4, group: 'number', label: 'YYYYMMDDHHMMSS', add: 'xxx'},
{id: 5, group: 'number', label: 'YYYYMMDD.HHMMSS', add: 'xxx'},
{id: 98, group: 'other', label: 'various - try different Formats (object, number, text)', add: 'xxx'},
{id: 99, group: 'other', label: 'text - free definition', add: 'xxx'}
{id: 0, group: 'number', label: 'milliseconds UNIX timestamp', add: 'xxx', i18n: 'common.parseFormats.0'},
{id: 1, group: 'string', label: 'ECMA-262', add: 'standard JS Date representation', i18n: 'common.parseFormats.1'},
{id: 6, group: 'string', label: 'ISO 8601', add: 'YYYY-MM-TTTHH:MM:SS.sssZ , YYYY-MM-TTTHH:MM:SS+HH:MM or YYYY-MM-TTTHH:MM:SS-HH:MM', i18n: 'common.parseFormats.2'},
{id: 2, group: 'string', label: 'try different text Formats, prefer day first like d/M/y (e.g. European format)', add: 'will try different formats, prefer European formats', i18n: 'common.parseFormats.3'},
{id: 3, group: 'string', label: 'try different text Formats, prefer month first like M/d/y (e.g. American format)', add: 'will try different formats, prefer American formats', i18n: 'common.parseFormats.4'},
{id: 4, group: 'number', label: 'YYYYMMDDHHMMSS', add: 'xxx', i18n: 'common.parseFormats.5'},
{id: 5, group: 'number', label: 'YYYYMMDD.HHMMSS', add: 'xxx', i18n: 'common.parseFormats.6'},
{id: 98, group: 'other', label: 'various - try different Formats (object, number, text)', add: 'xxx', i18n: 'common.parseFormats.7'},
{id: 99, group: 'other', label: 'text - free definition', add: 'xxx', i18n: 'common.parseFormats.8'}
], multiplierGroups: [
{id: 'default', label: 'Standard'},
{id: 'other', label: 'Special'}
{id: 'default', label: 'Standard', i18n: 'common.multiplierGroups.0'},
{id: 'other', label: 'Special', i18n: 'common.multiplierGroups.1'}
], multiplier: [
{id: 1, group: 'default', label: 'milliseconds'},
{id: 1000, group: 'default', label: 'seconds'},
{id: 60000, group: 'default', label: 'minutes'},
{id: 3600000, group: 'default', label: 'hours'},
{id: 86400000, group: 'default', label: 'days'},
// {id: 604800000, group: 'other', label: 'weeks'}, //maximum is 2147483647
{id: -1, group: 'other', label: 'month'},
{id: -2, group: 'other', label: 'year'}
{id: 1, group: 'default', label: 'milliseconds', i18n: 'common.multiplier.0'},
{id: 1000, group: 'default', label: 'seconds', i18n: 'common.multiplier.1'},
{id: 60000, group: 'default', label: 'minutes', i18n: 'common.multiplier.2'},
{id: 3600000, group: 'default', label: 'hours', i18n: 'common.multiplier.3'},
{id: 86400000, group: 'default', label: 'days', i18n: 'common.multiplier.4'},
{id: 604800000, group: 'other', label: 'weeks', i18n: 'common.multiplier.5'}, // maximum is 2147483647 - 24 Tage!
{id: -1, group: 'other', label: 'month', i18n: 'common.multiplier.6'},
{id: -2, group: 'other', label: 'year', i18n: 'common.multiplier.7'}
], comparatorGroups: [
{ id: 'simple', label: 'simple' },
{ id: 'compare', label: 'compare' },
{ id: 'enhanced', label: 'enhanced' }
{ id: 'simple', label: 'simple', i18n: 'common.comparatorGroups.0' },
{ id: 'compare', label: 'compare', i18n: 'common.comparatorGroups.1' },
{ id: 'enhanced', label: 'enhanced', i18n: 'common.comparatorGroups.2' }
], comparator: [
{ id: 'true', group: 'simple', label: 'true', operatorCount: 1 },
{ id: 'false', group: 'simple', label: 'false', operatorCount: 1 },
{ id: 'null', group: 'simple', label: 'null', operatorCount: 1 },
{ id: 'nnull', group: 'simple', label: 'not null', operatorCount: 1 },
{ id: 'empty', group: 'simple', label: 'empty', operatorCount: 1 },
{ id: 'nempty', group: 'simple', label: 'not empty', operatorCount: 1 },
{ id: 'true_expr', group: 'enhanced', label: 'true_expr', operatorCount: 1 },
{ id: 'false_expr', group: 'enhanced', label: 'false_expr', operatorCount: 1 },
{ id: 'ntrue_expr', group: 'enhanced', label: 'not true_expr', operatorCount: 1 },
{ id: 'nfalse_expr', group: 'enhanced', label: 'not false_expr', operatorCount: 1 },
{ id: 'equal', group: 'compare', label: 'equal', operatorCount: 2 },
{ id: 'nequal', group: 'compare', label: 'not equal', operatorCount: 2 },
{ id: 'lt', group: 'compare', label: 'less than', operatorCount: 2 },
{ id: 'lte', group: 'compare', label: 'less than or equal', operatorCount: 2 },
{ id: 'gt', group: 'compare', label: 'greater than', operatorCount: 2 },
{ id: 'gte', group: 'compare', label: 'greater than or equal', operatorCount: 2 },
{ id: 'contain', group: 'enhanced', label: 'contain', operatorCount: 2 },
{ id: 'containSome', group: 'enhanced', label: 'containSome', operatorCount: 2 },
{ id: 'containEvery', group: 'enhanced', label: 'containEvery', operatorCount: 2 }
{ id: 'true', group: 'simple', label: 'true', operandCount: 1, i18n: 'common.comparator.0' },
{ id: 'false', group: 'simple', label: 'false', operandCount: 1, i18n: 'common.comparator.1' },
{ id: 'null', group: 'simple', label: 'null', operandCount: 1, i18n: 'common.comparator.2' },
{ id: 'nnull', group: 'simple', label: 'not null', operandCount: 1, i18n: 'common.comparator.3' },
{ id: 'empty', group: 'simple', label: 'empty', operandCount: 1, i18n: 'common.comparator.4' },
{ id: 'nempty', group: 'simple', label: 'not empty', operandCount: 1, i18n: 'common.comparator.5' },
{ id: 'true_expr', group: 'enhanced', label: 'true_expr', operandCount: 1, i18n: 'common.comparator.6' },
{ id: 'false_expr', group: 'enhanced', label: 'false_expr', operandCount: 1, i18n: 'common.comparator.7' },
{ id: 'ntrue_expr', group: 'enhanced', label: 'not true_expr', operandCount: 1, i18n: 'common.comparator.8'},
{ id: 'nfalse_expr', group: 'enhanced', label: 'not false_expr', operandCount: 1, i18n: 'common.comparator.9' },
{ id: 'equal', group: 'compare', label: 'equal', operandCount: 2, i18n: 'common.comparator.10' },
{ id: 'nequal', group: 'compare', label: 'not equal', operandCount: 2, i18n: 'common.comparator.11' },
{ id: 'lt', group: 'compare', label: 'less than', operandCount: 2, i18n: 'common.comparator.12' },
{ id: 'lte', group: 'compare', label: 'less than or equal', operandCount: 2, i18n: 'common.comparator.13' },
{ id: 'gt', group: 'compare', label: 'greater than', operandCount: 2, i18n: 'common.comparator.14' },
{ id: 'gte', group: 'compare', label: 'greater than or equal', operandCount: 2, i18n: 'common.comparator.15' },
{ id: 'contain', group: 'enhanced', label: 'contain', operandCount: 2, i18n: 'common.comparator.16' },
{ id: 'containSome', group: 'enhanced', label: 'containSome', operandCount: 2, i18n: 'common.comparator.17' },
{ id: 'containEvery', group: 'enhanced', label: 'containEvery', operandCount: 2, i18n: 'common.comparator.18' }
]

@@ -220,2 +221,7 @@ };

},
strPlaceholder: {
value: 'strPlaceholder',
label: node._('node-red-contrib-sun-position/position-config:common.types.strPlaceholder'),
hasValue: false
},
numPercent: {

@@ -228,2 +234,12 @@ value: 'numPct',

},
nodeId: {
value: 'nodeId',
label: node._('node-red-contrib-sun-position/position-config:common.types.nodeId','node ID'),
hasValue: false
},
nodeName: {
value: 'nodeName',
label: node._('node-red-contrib-sun-position/position-config:common.types.nodeName','node name'),
hasValue: false
},
TimeEntered: {

@@ -295,4 +311,18 @@ value: 'entered',

hasValue: true,
validate: RED.validators.number()
validate: RED.validators.regex(/^(?:[1-9]|-0\.|0\.|-)\d*(?:\.\d+)?([\/|](?:[1-9]|-0\.|0\.|-)\d*(?:\.\d+)?)?$/)()
},
randmNumCachedDay: {
value: 'randmNumCachedDay',
label: node._('node-red-contrib-sun-position/position-config:common.types.randmNumCachedDay','randmNumCachedDay'),
icon: 'icons/node-red-contrib-sun-position/inputTypeRandomNumber.svg',
hasValue: true,
validate: RED.validators.regex(/^(?:[1-9]|-0\.|0\.|-)\d*(?:\.\d+)?([\/|](?:[1-9]|-0\.|0\.|-)\d*(?:\.\d+)?)?$/)()
},
randmNumCachedWeek: {
value: 'randmNumCachedWeek',
label: node._('node-red-contrib-sun-position/position-config:common.types.randmNumCachedWeek','randmNumCachedWeek'),
icon: 'icons/node-red-contrib-sun-position/inputTypeRandomNumber.svg',
hasValue: true,
validate: RED.validators.regex(/^(?:[1-9]|-0\.|0\.|-)\d*(?:\.\d+)?([\/|](?:[1-9]|-0\.|0\.|-)\d*(?:\.\d+)?)?$/)()
},
TimeSun: {

@@ -406,8 +436,38 @@ value: 'pdsTime',

},
numAzimuth: {
value: 'numAzimuth',
label: node._('node-red-contrib-sun-position/position-config:common.types.numAzimuth'),
icon: 'icons/node-red-contrib-sun-position/inputTypeSunAzimuth.svg',
hasValue: true,
validate(v) {
const n = parseFloat(v);
return (RED.validators.number()(v) && (n >= -360) && (n <= 720));
}
},
numAzimuthRad: {
value: 'numAzimuth',
label: node._('node-red-contrib-sun-position/position-config:common.types.numAzimuthRad'),
icon: 'icons/node-red-contrib-sun-position/inputTypeSunAzimuth.svg',
hasValue: true,
validate(v) {
const n = parseFloat(v);
return (RED.validators.number()(v) && (n > -6.3) && (n < 12.6));
}
},
SunElevation: {
value: 'pdsCalcElevation',
label: node._('node-red-contrib-sun-position/position-config:common.types.sunElevation','Elevation'),
label: node._('node-red-contrib-sun-position/position-config:common.types.sunElevation'),
icon: 'icons/node-red-contrib-sun-position/inputTypeSunElevation.svg',
hasValue: false
},
numAltitude: {
value: 'numAltitude',
label: node._('node-red-contrib-sun-position/position-config:common.types.numAltitude'),
icon: 'icons/node-red-contrib-sun-position/inputTypeSunElevation.svg',
hasValue: true,
validate(v) {
const n = parseFloat(v);
return (RED.validators.number()(v) && (n >= -90) && (n <= 90));
}
},
SunAzimuthRad: {

@@ -419,5 +479,15 @@ value: 'pdsCalcAzimuthRad',

},
numAltitudeRad: {
value: 'numAltitudeRad',
label: node._('node-red-contrib-sun-position/position-config:common.types.numAltitudeRad'),
icon: 'icons/node-red-contrib-sun-position/inputTypeSunElevation.svg',
hasValue: true,
validate(v) {
const n = parseFloat(v);
return (RED.validators.number()(v) && (n > -1.56) && (n < 1.56));
}
},
SunElevationRad: {
value: 'pdsCalcElevationRad',
label: node._('node-red-contrib-sun-position/position-config:common.types.sunElevationRad','Elevation'),
label: node._('node-red-contrib-sun-position/position-config:common.types.sunElevationRad'),
icon: 'icons/node-red-contrib-sun-position/inputTypeSunElevation.svg',

@@ -752,3 +822,3 @@ hasValue: false

for (let gIndex = 0; gIndex < groupLength; gIndex++) {
const group = $('<optgroup/>', {label: node._('node-red-contrib-sun-position/position-config:common.' + elementName + 'Groups.' + gIndex)}).appendTo(parent);
const group = $('<optgroup/>', {label: node._('node-red-contrib-sun-position/position-config:' + groups[gIndex].i18n)}).appendTo(parent);
for (let eIndex = 0; eIndex < elementsLength; eIndex++) {

@@ -758,6 +828,6 @@ if (groups[gIndex].id === elements[eIndex].group) {

if (filter(elements[eIndex])) {
group.append($('<option></option>').val(elements[eIndex].id).text(node._('node-red-contrib-sun-position/position-config:common.' + elementName + '.' + eIndex)).attr('addText', elements[eIndex].add));
group.append($('<option></option>').val(elements[eIndex].id).text(node._('node-red-contrib-sun-position/position-config:' + elements[eIndex].i18n)).attr('addText', elements[eIndex].add));
}
} else {
group.append($('<option></option>').val(elements[eIndex].id).text(node._('node-red-contrib-sun-position/position-config:common.' + elementName + '.' + eIndex)).attr('addText', elements[eIndex].add));
group.append($('<option></option>').val(elements[eIndex].id).text(node._('node-red-contrib-sun-position/position-config:' + elements[eIndex].i18n)).attr('addText', elements[eIndex].add));
}

@@ -791,4 +861,3 @@ }

let type='';
if (typeof node[data.typeProp] === 'undefined' ||
node[data.typeProp] === null) {
if (typeof node[data.typeProp] === 'undefined' || node[data.typeProp] === null) {
if (typeof data.defaultType !== 'undefined') {

@@ -803,4 +872,3 @@ type = data.defaultType;

}
if (typeof node[data.valueProp] === 'undefined' ||
node[data.valueProp] === null) {
if (typeof node[data.valueProp] === 'undefined' || node[data.valueProp] === null) {
if (typeof data.defaultValue !== 'undefined') {

@@ -840,9 +908,13 @@ node[data.valueProp] = data.defaultValue;

function setTInputValue($field, value, type) { // eslint-disable-line no-unused-vars
if (type === 'flow' || type === 'global') {
$field.typedInput('type', 'env'); // env haben alle, bug fix
$field.typedInput('value', checkDeprecatedValues(type, value));
$field.typedInput('type', type);
} else {
$field.typedInput('type', type);
$field.typedInput('value', checkDeprecatedValues(type, value));
try {
if (type === 'flow' || type === 'global') {
$field.typedInput('type', 'env'); // env haben alle, bug fix
$field.typedInput('value', checkDeprecatedValues(type, value));
$field.typedInput('type', type);
} else {
$field.typedInput('type', type);
$field.typedInput('value', checkDeprecatedValues(type, value));
}
} catch (err) {
console.log('error setting type input', value, type, err); // eslint-disable-line no-console
}

@@ -921,5 +993,6 @@ }

* @param {string} [text] - text of the label
* @param {string} [width] - width of the label
* @returns {jQuery} jQuery selector of the new label
*/
function addLabel(parent, forEl, symb, text) { // eslint-disable-line no-unused-vars
function addLabel(parent, forEl, symb, text, width) { // eslint-disable-line no-unused-vars
const lbl = $('<label class="' + forEl + '-lbl" style="width:auto"/>').attr('for', forEl).appendTo(parent);

@@ -933,5 +1006,7 @@ if (symb) {

// lbl.attr('style', 'margin-left: 5px; width:' + 20 + span.width() + 'px;');
lbl.attr('style', 'margin-left: 5px; width:auto;');
width = width || 'auto';
lbl.attr('style', 'margin-left: 5px; width:' + width + ';');
} else {
lbl.attr('style', 'margin-left: 5px; margin-right: 2px; width:20px');
width = width || '20px';
lbl.attr('style', 'margin-left: 5px; margin-right: 2px; width:' + width + ';');
}

@@ -1082,37 +1157,51 @@ return lbl;

function getBackendData(result, data) { // eslint-disable-line no-unused-vars
// console.log('[IN getBackendData] ',data); // eslint-disable-line
let res = '';
if (!data || data.type === 'none' || data.type === '' || data.type === 'json' || data.type === 'bin') {
res = data.type;
} else if ( data.type === 'bool') {
res = data.value;
} else if (data.type === 'msg' || data.type === 'env') {
res = data.type + '.' + data.value;
} else if (data.type === 'msgPayload') {
res = 'msg.payload';
} else if (data.type === 'msgTopic') {
res = 'msg.topic';
} else if (data.type === 'PlT') {
res = 'msg.payload if msg.topic contains "' + data.value + '"';
} else if (data.type === 'msgTs') {
res = 'msg.ts';
} else if (data.type === 'msgLC') {
res = 'msg.lc';
} else if (data.type === 'msgValue') {
res = 'msg.value';
} else if (data.timeDays === '') {
res = 'No valid days given! Please check settings!';
} else if (data.timeMonths === '') {
res = 'No valid month given! Please check settings!';
} else {
const url = 'sun-position/data?' + jQuery.param( data );
$.getJSON(url, result);
return;
// console.log('[IN getBackendData]',data);
try {
const res = {
value:'',
useful: false
};
if (!data || data.type === 'none' || data.type === '' || data.type === 'json' || data.type === 'bin') {
res.value = data.type;
} else if ( data.type === 'bool' || data.type === 'num' || data.type === 'str' || data.type === 'numAzimuth' || data.type === 'numAltitude') {
res.value = String(data.value);
res.useful = true;
} else if (data.type === 'msg' || data.type === 'env') {
res.value = data.type + '.' + data.value;
} else if (data.type === 'msgPayload') {
res.value = 'msg.payload';
} else if (data.type === 'msgTopic') {
res.value = 'msg.topic';
} else if (data.type === 'PlT') {
res.value = 'msg.payload if msg.topic contains "' + data.value + '"';
} else if (data.type === 'msgTs') {
res.value = 'msg.ts';
} else if (data.type === 'msgLC') {
res.value = 'msg.lc';
} else if (data.type === 'msgValue') {
res.value = 'msg.value';
} else if (data.timeDays === '') {
res.value = 'No valid days given! Please check settings!';
} else if (data.timeMonths === '') {
res.value = 'No valid month given! Please check settings!';
} else {
const url = 'sun-position/data?' + jQuery.param( data );
$.getJSON(url, result);
return;
}
result(res);
} catch (err) {
console.log('can not get data from Server',err); // eslint-disable-line no-console
}
if (data.kind === 'getTimeData') {
result({ value: res});
}
result(res);
}
/**
* returns **true** if the parameter value is a valid boolean value for **true**
* @param {*} val a parameter which should be checked if it is a valid true boolean
* @returns {boolean} true if the parameter value is a valid boolean value for **true**
*/
function isTrue(val) { // eslint-disable-line no-unused-vars
val = (val+'').toLowerCase();
return (['true', 'yes', 'on', 'ja'].includes(val) || (!isNaN(val) && (Number(val) > 0)));
}

@@ -1153,3 +1242,2 @@ /**

/**

@@ -1156,0 +1244,0 @@ * get the value for the day checkbox array

@@ -23,2 +23,3 @@ /********************************************

value: config.input,
next: hlp.isTrue(config.inputNext),
format: config.inputFormat,

@@ -71,7 +72,9 @@ offsetType: config.inputOffsetType,

multiplier : prop.oM,
next : (typeof prop.next === 'undefined' || prop.next === null || prop.next === true || prop.next === 'true') ? true : false,
next : (typeof prop.next === 'undefined' || prop.next === null || hlp.isTrue(prop.next)) ? true : false,
days : prop.days,
months : prop.months,
onlyEvenDays: prop.onlyEvenDays,
onlyOddDays : prop.onlyOddDays
onlyOddDays : prop.onlyOddDays,
onlyEvenWeeks: prop.onlyEvenWeeks,
onlyOddWeeks : prop.onlyOddWeeks
};

@@ -187,2 +190,3 @@

format: rule.format,
next: rule.next,
offsetType: 'num',

@@ -189,0 +193,0 @@ offset: rule.offsetValue,

@@ -19,2 +19,42 @@ /********************************************

function timeInjectNode(config) {
/**
* get the output properies
* @param {object} props - the property array
* @returns {object} the nw property object
*/
function prepareProps(node, props) {
// node.debug('prepareProps ' + util.inspect(props, { colors: true, compact: 10, breakLength: Infinity }));
const outProps = [];
props.forEach( prop => {
const propNew = {
outType : prop.pt,
outValue : prop.p,
type : prop.vt,
value : prop.v,
format : prop.f,
offsetType : prop.oT,
offset : prop.o,
multiplier : prop.oM,
next : (typeof prop.next === 'undefined' || prop.next === null || hlp.isTrue(prop.next === true)) ? true : false,
days : prop.days,
months : prop.months,
onlyEvenDays: prop.onlyEvenDays,
onlyOddDays : prop.onlyOddDays,
onlyEvenWeeks: prop.onlyEvenWeeks,
onlyOddWeeks : prop.onlyOddWeeks
};
if (node.positionConfig && propNew.type === 'jsonata') {
try {
propNew.expr = node.positionConfig.getJSONataExpression(node, propNew.value);
} catch (err) {
node.error(RED._('node-red-contrib-sun-position/position-config:errors.invalid-expr', { error:err.message }));
propNew.expr = null;
}
}
outProps.push(propNew);
});
return outProps;
}
const tInj = {

@@ -24,5 +64,6 @@ none : 0,

interval : 2,
intervalTime : 4,
intervalBtwStartEnd : 4,
intervalAmount : 5
};
const intervalMax = 24*60*60*1000 * 3; // 3 Tage
RED.nodes.createNode(this, config);

@@ -33,3 +74,3 @@ // Retrieve the config node

if (config.injectTypeSelect === 'interval-time') {
this.injType = tInj.intervalTime;
this.injType = tInj.intervalBtwStartEnd;
} else if (config.injectTypeSelect === 'interval') {

@@ -47,3 +88,3 @@ this.injType = tInj.interval;

if (this.injType === tInj.interval ||
this.injType === tInj.intervalTime ||
this.injType === tInj.intervalBtwStartEnd ||
this.injType === tInj.intervalAmount) {

@@ -56,3 +97,11 @@ this.intervalCountType = (config.intervalCountType || 'num');

if (this.injType === tInj.intervalTime ||
if (this.injType === tInj.interval) {
if (config.intervalStart) {
this.intervalStart = hlp.isoStringToDate(config.intervalStart);
} else {
this.intervalStart = new Date();
}
}
if (this.injType === tInj.intervalBtwStartEnd ||
this.injType === tInj.intervalAmount ||

@@ -65,8 +114,10 @@ this.injType === tInj.timer) {

offset : config.offset || config.timeOffset || 0,
multiplier : config.offsetMultiplier ? config.offsetMultiplier : (config.timeOffsetMultiplier ? config.timeOffsetMultiplier : 60),
multiplier : config.offsetMultiplier ? parseInt(config.offsetMultiplier) : (config.timeOffsetMultiplier ? parseInt(config.timeOffsetMultiplier) : 60),
next : true,
days : config.timeDays,
months : config.timeMonths,
onlyOddDays: config.timeOnlyOddDays,
onlyEvenDays: config.timeOnlyEvenDays
onlyOddDays: hlp.isTrue(config.timeOnlyOddDays),
onlyEvenDays: hlp.isTrue(config.timeOnlyEvenDays),
onlyEvenWeeks: hlp.isTrue(config.timeOnlyEvenWeeks),
onlyOddWeeks : hlp.isTrue(config.timeOnlyOddWeeks)
};

@@ -87,2 +138,6 @@

}
if (this.timeStartData.onlyEvenWeeks && this.timeStartData.onlyOddWeeks) {
this.timeStartData.onlyEvenWeeks = false;
this.timeStartData.onlyOddWeeks = false;
}
if (config.propertyType && config.propertyType !== 'none' && config.timeAltType && config.timeAltType !== 'none') {

@@ -118,8 +173,10 @@ this.property = {

offset : config.timeAltOffset ? config.timeAltOffset : 0,
multiplier : config.timeAltOffsetMultiplier ? config.timeAltOffsetMultiplier : 60,
multiplier : config.timeAltOffsetMultiplier ? parseInt(config.timeAltOffsetMultiplier) : 60,
next : true,
days : config.timeAltDays,
months : config.timeAltMonths,
onlyOddDays: config.timeAltOnlyOddDays,
onlyEvenDays: config.timeAltOnlyEvenDays
onlyOddDays: hlp.isTrue(config.timeAltOnlyOddDays),
onlyEvenDays: hlp.isTrue(config.timeAltOnlyEvenDays),
onlyEvenWeeks: hlp.isTrue(config.timeAltOnlyEvenWeeks),
onlyOddWeeks : hlp.isTrue(config.timeAltOnlyOddWeeks)
};

@@ -138,6 +195,10 @@ if (!this.timeStartAltData.offsetType) { this.timeStartAltData.offsetType = ((this.timeStartAltData.offset === 0) ? 'none' : 'num'); }

}
if (this.timeStartAltData.onlyEvenWeeks && this.timeStartAltData.onlyOddWeeks) {
this.timeStartAltData.onlyEvenWeeks = false;
this.timeStartAltData.onlyOddWeeks = false;
}
} // timeAlt
} // timeStartData
if (this.injType === tInj.intervalTime ||this.injType === tInj.intervalAmount ) {
if (this.injType === tInj.intervalBtwStartEnd ||this.injType === tInj.intervalAmount ) {
this.timeEndData = {

@@ -148,8 +209,10 @@ type: config.timeEndType,

offset : config.timeEndOffset ? config.timeEndOffset : 0,
multiplier : config.timeEndOffsetMultiplier ? config.timeEndOffsetMultiplier : 60,
multiplier : config.timeEndOffsetMultiplier ? parseInt(config.timeEndOffsetMultiplier) : 60,
next : true,
days : config.timeDays,
months : config.timeMonths,
onlyOddDays: config.timeOnlyOddDays,
onlyEvenDays: config.timeOnlyEvenDays
onlyOddDays: hlp.isTrue(config.timeOnlyOddDays),
onlyEvenDays: hlp.isTrue(config.timeOnlyEvenDays),
onlyEvenWeeks: hlp.isTrue(config.timeOnlyEvenWeeks),
onlyOddWeeks : hlp.isTrue(config.timeOnlyOddWeeks)
};

@@ -169,2 +232,6 @@ if (!this.timeEndData.offsetType) {

}
if (this.timeEndData.onlyEvenWeeks && this.timeEndData.onlyOddWeeks) {
this.timeEndData.onlyEvenWeeks = false;
this.timeEndData.onlyOddWeeks = false;
}
} // timeEndData

@@ -307,31 +374,4 @@

this.props = [];
config.props.forEach( prop => {
const propNew = {
outType : prop.pt,
outValue : prop.p,
type : prop.vt,
value : prop.v,
format : prop.f,
offsetType : prop.oT,
offset : prop.o,
multiplier : prop.oM,
next : (typeof prop.next === 'undefined' || prop.next === null || prop.next === true || prop.next === 'true') ? true : false,
days : prop.days,
months : prop.months,
onlyEvenDays: prop.onlyEvenDays,
onlyOddDays : prop.onlyOddDays
};
this.props = prepareProps(this, config.props);
if (this.positionConfig && propNew.type === 'jsonata') {
try {
propNew.expr = this.positionConfig.getJSONataExpression(this, propNew.value);
} catch (err) {
this.error(RED._('node-red-contrib-sun-position/position-config:errors.invalid-expr', { error:err.message }));
propNew.expr = null;
}
}
this.props.push(propNew);
});
this.recalcTime = (config.recalcTime || 2) * 3600000;

@@ -346,2 +386,16 @@

this.nextEndTime = null;
if (config.once) {
if (config.onceDelay > 2147483) {
this.onceDelay = 2147483;
} else {
this.onceDelay = config.onceDelay || 0.1;
}
}
if (config.timedatestart) {
this.timedatestart = new Date(config.timedatestart);
}
if (config.timedateend) {
this.timedateend = new Date(config.timedateend);
}
const node = this;

@@ -363,3 +417,2 @@

}
return millisec;

@@ -376,8 +429,8 @@ };

};
if (config.timedatestart || config.timedateend) {
if (node.timedatestart || node.timedateend) {
const year = dNow.getFullYear();
if (node.cacheYear !== year) {
node.cacheYear = year;
if (config.timedatestart) {
node.cacheStart = new Date(config.timedatestart);
if (node.timedatestart) {
node.cacheStart = new Date(node.timedatestart);
node.cacheStart.setFullYear(year);

@@ -388,4 +441,4 @@ node.cacheStart.setHours(0, 0, 0, 0);

}
if (config.timedateend) {
node.cacheEnd = new Date(config.timedateend);
if (node.timedateend) {
node.cacheEnd = new Date(node.timedateend);
node.cacheEnd.setFullYear(year);

@@ -420,5 +473,5 @@ node.cacheEnd.setHours(23, 59, 59, 999);

node.initializeStartTimer = node => {
node.debug(`initializeStartTimer`);
// node.debug(`initializeStartTimer`);
if (!node.timeStartData) {
node.debug('initializeStartTimer - no start time data');
// node.debug('initializeStartTimer - no start time data');
return false;

@@ -431,3 +484,3 @@ }

if (!startLimit.valid) {
node.debug('initializeStartTimer - start limited');
// node.debug('initializeStartTimer - start limited');
return false;

@@ -439,6 +492,6 @@ }

if (nextStartTimeData.error || !hlp.isValidDate(nextStartTimeData.value)) {
node.debug(`initializeStartTimer - start time wrong ${ nextStartTimeData.error}`);
// node.debug(`initializeStartTimer - start time wrong ${ nextStartTimeData.error}`);
return false;
}
let millisec = nextStartTimeData.value.valueOf() - nowTs;
let millisecStart = nextStartTimeData.value.valueOf() - nowTs;

@@ -452,9 +505,9 @@ if (node.timeStartAltData) {

const millisecAlt = nextTimeAltData.value.valueOf() - nowTs;
if (millisecAlt < millisec) {
millisec = millisecAlt;
if (millisecAlt < millisecStart) {
millisecStart = millisecAlt;
}
}
}
if (millisec > 0 || !node.timeEndData) {
node.debug(`initializeStartTimer - start ${ millisec } in future or no end time`);
if (millisecStart > 0 || !node.timeEndData) {
// node.debug(`initializeStartTimer - start ${ millisecStart } in future or no end time`);
return false;

@@ -466,3 +519,3 @@ }

if (nextEndTimeData.error || !hlp.isValidDate(nextEndTimeData.value)) {
node.debug(`initializeStartTimer - end time error ${ nextEndTimeData.error }`);
// node.debug(`initializeStartTimer - end time error ${ nextEndTimeData.error }`);
return false;

@@ -472,8 +525,8 @@ }

if (millisecEnd < 0) {
node.debug(`initializeStartTimer - end time ${ millisecEnd } in past`);
// node.debug(`initializeStartTimer - end time ${ millisecEnd } in past`);
return false;
}
node.debug(`initializeStartTimer - starting interval!!`);
// node.debug(`initializeStartTimer - starting interval!!`);
if (this.injType === tInj.intervalTime) {
if (this.injType === tInj.intervalBtwStartEnd) {
node.getIntervalTime();

@@ -483,3 +536,3 @@ node.doStartInterval(); // starte Interval

node.IntervalCountMax = node.positionConfig.getFloatProp(node, null, node.intervalCountType, node.intervalCount, 0);
node.intervalTime = Math.floor((millisecEnd - millisec) / node.IntervalCountMax);
node.intervalTime = Math.floor((millisecEnd - millisecStart) / node.IntervalCountMax);
node.IntervalCountCurrent = 0;

@@ -492,3 +545,2 @@ node.doStartInterval(); // starte Interval

node.initialize = (node, doEmit) => {
node.debug(`initialize`);
switch (node.injType) {

@@ -501,15 +553,8 @@ case tInj.interval:

}
node.debug('initialize - absolute Intervall');
node.getIntervalTime();
clearInterval(node.intervalObj);
node.status({
text: '↻' + Math.round(((node.intervalTime / 1000) + Number.EPSILON) * 10) / 10 + 's'
});
// node.debug('initialize - absolute Intervall');
node.send(node.prepOutMsg({ type: 'interval-start' }));
node.intervalObj = setInterval(() => {
node.send(node.prepOutMsg({ type: 'interval' }));
}, node.intervalTime);
node.createNextInterval();
break;
case tInj.timer:
node.debug('initialize - timer');
// node.debug('initialize - timer');
if (doEmit) {

@@ -523,9 +568,9 @@ node.emit('input', {

break;
case tInj.intervalTime:
case tInj.intervalBtwStartEnd:
case tInj.intervalAmount:
node.debug('initialize - Intervall timer/amount');
// node.debug('initialize - Intervall timer/amount/fromStart');
if (doEmit) {
node.emit('input', {
type: 'once/startup'
});
}); // will create timeout
}

@@ -537,3 +582,3 @@ if (!node.initializeStartTimer(node)) {

default:
node.debug('initialize - default');
// node.debug('initialize - default');
node.doSetStatus(node, 'green');

@@ -556,3 +601,3 @@ if (doEmit) {

}
node.debug(`doCreateEndTimeout node.timeEndData=${util.inspect(node.timeEndData, { colors: true, compact: 10, breakLength: Infinity })}`);
// node.debug(`doCreateEndTimeout node.timeEndData=${util.inspect(node.timeEndData, { colors: true, compact: 10, breakLength: Infinity })}`);
if (node.timeOutEndObj) {

@@ -623,17 +668,101 @@ clearTimeout(node.timeOutEndObj);

node.getIntervalText = (mstime, val) => {
if (mstime === 604800000) {
if (val === 1) {
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.week');
}
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.weeks');
} else if (mstime === 86400000) {
if (val === 1) {
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.day');
}
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.days');
} else if (mstime === 3600000) {
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.hour');
} else if (mstime === 60000) {
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.min');
} else if (mstime === 1000) {
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.sec');
}
return String(val) + RED._('node-red-contrib-sun-position/position-config:common.units.ms');
};
/**
* Prepaes a message object for sending
* Recalculate the Interval
*/
node.createNextInterval = () => {
node.getIntervalTime();
clearInterval(node.intervalObj);
const dNow = (new Date()).valueOf();
const diff = Math.abs(dNow - node.intervalStart.valueOf());
const ivCount = Math.trunc(diff / node.intervalTime) + 1;
const tsStart = node.intervalStart.valueOf() + (node.intervalTime * ivCount); // Start Timestamp
const millisec = tsStart - dNow;
// node.debug(`createNextInterval start=${node.intervalStart}; interval=${node.intervalTime}; diff=${diff}; ivCount=${ivCount}; tsStart=${tsStart}; millisec=${millisec}`);
if (millisec > 2147483647) {
// there is a limitation of nodejs that the maximum setTimeout time
// should not more then 2147483647 ms (24.8 days).
node.timeOutStartObj = setTimeout(() => {
node.createNextInterval();
}, 2147483647);
return;
}
node.timeOutStartObj = setTimeout(() => {
node.timeOutStartObj = null;
if (node.intervalTime < intervalMax) {
node.debug(`interval is less than max=${intervalMax}ms, create absolute interval of ${node.intervalTime}ms`);
node.intervalObj = setInterval(() => {
node.send(node.prepOutMsg({ type: 'interval' }));
}, node.intervalTime);
if (node.intervalTime > 43200000) { // 12h
node.status({
text: '↻' + (node.intervalTime / 3600000).toFixed(1) + 'h'
});
} else if (node.intervalTime > 3600000) { // 1h
node.status({
text: '↻' + (node.intervalTime / 60000).toFixed(2) + 'min'
});
} else {
node.status({
text: ' ↻' + node.intervalText
});
/*
node.status({
text: '↻' + Math.round(((node.intervalTime / 1000) + Number.EPSILON) * 10) / 10 + 's'
}); */
}
} else {
node.createNextInterval();
}
node.send(node.prepOutMsg({ type: 'interval' }));
}, millisec);
node.status({
text: node.positionConfig.toTimeString(new Date(tsStart)) + ' ↻' + node.intervalText
});
};
/**
* Prepares a message object for sending
*/
node.prepOutMsg = msg => {
// node.debug(`prepOutMsg node.msg=${util.inspect(msg, { colors: true, compact: 10, breakLength: Infinity })}`);
const dNow = new Date();
for (let i = 0; i < node.props.length; i++) {
// node.debug(`prepOutMsg-${i} node.props[${i}]=${util.inspect(node.props[i], { colors: true, compact: 10, breakLength: Infinity })}`);
const res = node.positionConfig.getOutDataProp(this, msg, node.props[i], dNow);
let props = node.props;
if (msg.__user_inject_props__ && msg.__user_inject_props__.props && Array.isArray(msg.__user_inject_props__.props)) {
props = prepareProps(node, msg.__user_inject_props__.props);
}
delete msg.__user_inject_props__;
// node.debug(`prepOutMsg props=${util.inspect(props, { colors: true, compact: 10, breakLength: Infinity })}`);
for (let i = 0; i < props.length; i++) {
// node.debug(`prepOutMsg-${i} props[${i}]=${util.inspect(props[i], { colors: true, compact: 10, breakLength: Infinity })}`);
const res = node.positionConfig.getOutDataProp(this, msg, props[i], dNow);
if (res === null || (typeof res === 'undefined')) {
this.error('Could not evaluate ' + node.props[i].type + '.' + node.props[i].value + '. - Maybe settings outdated (open and save again)!');
this.error('Could not evaluate ' + props[i].type + '.' + props[i].value + '. - Maybe settings outdated (open and save again)!');
} else if (res.error) {
this.error('Error on getting additional payload: "' + res.error + '"');
} else {
node.positionConfig.setMessageProp(this, msg, node.props[i].outType, node.props[i].outValue, res);
node.positionConfig.setMessageProp(this, msg, props[i].outType, props[i].outValue, res);
}

@@ -655,2 +784,3 @@ // node.debug(`prepOutMsg-${i} msg=${util.inspect(msg, { colors: true, compact: 10, breakLength: Infinity })}`);

} else {
node.intervalText = node.getIntervalText(node.intervalCountMultiplier, node.intervalTime);
if (node.intervalCountMultiplier > 0) {

@@ -673,3 +803,3 @@ node.intervalTime = Math.floor(node.intervalTime * node.intervalCountMultiplier);

node.IntervalCountCurrent++;
if (node.IntervalCountMax < 1) {
if (node.injType !== node.intervalAmount) {
node.send(node.prepOutMsg({ type: 'interval-time' }));

@@ -689,3 +819,3 @@ } else if (node.IntervalCountCurrent < node.IntervalCountMax) {

node.doCreateStartTimeout = node => {
node.debug(`doCreateStartTimeout node.timeStartData=${util.inspect(node.timeStartData, { colors: true, compact: 10, breakLength: Infinity })}`);
// node.debug(`doCreateStartTimeout node.timeStartData=${util.inspect(node.timeStartData, { colors: true, compact: 10, breakLength: Infinity })}`);
if (node.injType === tInj.none ||

@@ -705,3 +835,3 @@ node.injType === tInj.interval) {

if (node.injType === tInj.intervalTime) {
if (node.injType === tInj.intervalBtwStartEnd) {
node.IntervalCountMax = 0;

@@ -726,3 +856,3 @@ node.getIntervalTime();

if (startLimit.valid) {
node.debug(`node.timeStartData=${util.inspect(node.timeStartData, { colors: true, compact: 10, breakLength: Infinity })}`);
// node.debug(`node.timeStartData=${util.inspect(node.timeStartData, { colors: true, compact: 10, breakLength: Infinity })}`);
const nextStartTimeData = node.positionConfig.getTimeProp(node, {}, node.timeStartData);

@@ -740,3 +870,3 @@ if (nextStartTimeData.error) {

node.timeStartAltData.now = node.timeStartData.now;
node.debug(`node.timeStartAltData=${util.inspect(node.timeStartAltData, { colors: true, compact: 10, breakLength: Infinity })}`);
// node.debug(`node.timeStartAltData=${util.inspect(node.timeStartAltData, { colors: true, compact: 10, breakLength: Infinity })}`);
const nextTimeAltData = node.positionConfig.getTimeProp(node, {}, node.timeStartAltData);

@@ -746,3 +876,3 @@

isFixedTime = false;
node.debug('nextTimeAltData=' + util.inspect(nextTimeAltData, { colors: true, compact: 10, breakLength: Infinity }));
// node.debug('nextTimeAltData=' + util.inspect(nextTimeAltData, { colors: true, compact: 10, breakLength: Infinity }));
hlp.handleError(node, nextTimeAltData.error, null, 'could not evaluate alternate time');

@@ -760,3 +890,8 @@ return;

} else {
hlp.handleError(this, startLimit.errorStatus);
this.debug(startLimit.errorStatus);
node.status({
fill: 'red',
shape: 'ring',
text: startLimit.errorStatus
});
return;

@@ -790,3 +925,3 @@ }

millisec = Math.min((millisec - 129600000), 2147483646);
node.debug('next inject is far far away, plan a inject time recalc in ' + millisec + ' ms');
// node.debug('next inject is far far away, plan a inject time recalc in ' + millisec + ' ms');
node.timeOutStartObj = setTimeout(() => {

@@ -796,8 +931,8 @@ node.doRecalcStartTimeOut();

fill = 'blue';
} else if (this.injType === tInj.intervalTime) {
node.debug('intervalTime - timeout ' + node.nextStartTime + ' is in ' + millisec + 'ms (isAlt=' + node.timeStartData.isAltAvailable + ' isAltFirst=' + node.timeStartData.isAltFirst + ')');
} else if (this.injType === tInj.intervalBtwStartEnd) {
// node.debug('intervalTime - timeout ' + node.nextStartTime + ' is in ' + millisec + 'ms (isAlt=' + node.timeStartData.isAltAvailable + ' isAltFirst=' + node.timeStartData.isAltFirst + ')');
node.timeOutStartObj = setTimeout(node.doStartInterval, millisec);
fill = 'grey';
} else if (this.injType === tInj.intervalAmount) {
node.debug('intervalAmount - timeout ' + node.nextStartTime + ' is in ' + millisec + 'ms (isAlt=' + node.timeStartData.isAltAvailable + ' isAltFirst=' + node.timeStartData.isAltFirst + ')');
// node.debug('intervalAmount - timeout ' + node.nextStartTime + ' is in ' + millisec + 'ms (isAlt=' + node.timeStartData.isAltAvailable + ' isAltFirst=' + node.timeStartData.isAltFirst + ')');
const millisecEnd = node.getMillisecEnd(node);

@@ -809,3 +944,3 @@ node.intervalTime = Math.floor((millisecEnd - millisec) / node.IntervalCountMax);

} else { // this.injType === tInj.timer
node.debug('timeout ' + node.nextStartTime + ' is in ' + millisec + 'ms (isAlt=' + node.timeStartData.isAltAvailable + ' isAltFirst=' + node.timeStartData.isAltFirst + ')');
// node.debug('timeout ' + node.nextStartTime + ' is in ' + millisec + 'ms (isAlt=' + node.timeStartData.isAltAvailable + ' isAltFirst=' + node.timeStartData.isAltFirst + ')');
node.timeOutStartObj = setTimeout(() => {

@@ -913,3 +1048,3 @@ // node.debug(`timeOutStartObj isAlt=${isAlt} isAltFirst=${node.timeStartData.isAltFirst}`);

try {
node.debug('--------- time-inject - input (type=' + msg.type + ')');
node.debug('--------- time-inject - input msg='+ util.inspect(msg, { colors: true, compact: 10, breakLength: Infinity }));
if (!node.positionConfig) {

@@ -922,5 +1057,3 @@ throw new Error('configuration missing!');

send(node.prepOutMsg(msg));
if (msg.payload === null || (typeof msg.payload === 'undefined')) {
done('could not evaluate ' + config.payloadType + '.' + config.payload);
} else if (msg.payload.error) {
if (msg.payload && msg.payload.error) {
done('could not getting payload: ' + msg.payload.error);

@@ -954,10 +1087,7 @@ } else {

}
if (config.once) {
if (config.onceDelay > 2147483) {
config.onceDelay = 2147483;
}
if (node.onceDelay) {
node.status({
fill: 'yellow',
shape: 'ring',
text: RED._('time-inject.message.onceDelay', { seconds: (config.onceDelay || 0.1)})
text: RED._('time-inject.message.onceDelay', { seconds: (node.onceDelay)})
});

@@ -976,3 +1106,3 @@ node.onceTimeout = setTimeout(() => {

}
}, (config.onceDelay || 0.1) * 1000);
}, node.onceDelay * 1000);
return;

@@ -1034,7 +1164,11 @@ }

RED.httpAdmin.post('/time-inject/:id', RED.auth.needsPermission('time-inject.write'), (req,res) => {
RED.httpAdmin.post('/time-inject/:id', RED.auth.needsPermission('time-inject.write'), (req, res) => {
const node = RED.nodes.getNode(req.params.id);
if (node !== null && typeof node !== 'undefined') {
try {
node.receive();
if (req.body && req.body.__user_inject_props__) {
node.receive(req.body);
} else {
node.receive();
}
res.sendStatus(200);

@@ -1041,0 +1175,0 @@ } catch(err) {

@@ -6,3 +6,6 @@ /********************************************

const util = require('util');
const path = require('path');
const hlp = require(path.join(__dirname, '/lib/dateTimeHelper.js'));
const perSecond = 1000;

@@ -329,7 +332,9 @@ const perMinute = 60000;

outTSFormat : prop.fTs,
next : (typeof prop.next === 'undefined' || prop.next === null || prop.next === true || prop.next === 'true') ? true : false,
next : (typeof prop.next === 'undefined' || prop.next === null || hlp.isTrue(prop.next)) ? true : false,
days : prop.days,
months : prop.months,
onlyEvenDays : prop.onlyEvenDays,
onlyOddDays : prop.onlyOddDays
onlyOddDays : prop.onlyOddDays,
onlyEvenWeeks : prop.onlyEvenWeeks,
onlyOddWeeks : prop.onlyOddWeeks
};

@@ -336,0 +341,0 @@

@@ -44,3 +44,3 @@ /********************************************

node.debug('compare time to ' + id + ' = "' + value + '"');
const dto = new Date(msg.ts);
const dto = new Date(value);
if (hlp.isValidDate(dto)) {

@@ -152,2 +152,12 @@ return dto;

}
if (Object.prototype.hasOwnProperty.call(node.timeRestrictions.data,'onlyOddWeeks')) {
node.timeOnlyOddWeeks = node.timeRestrictions.data.onlyOddWeeks;
} else {
delete node.timeOnlyOddWeeks;
}
if (Object.prototype.hasOwnProperty.call(node.timeRestrictions.data,'onlyEvenWeeks')) {
node.timeOnlyEvenWeeks = node.timeRestrictions.data.onlyEvenWeeks;
} else {
delete node.timeOnlyEvenWeeks;
}
}

@@ -208,2 +218,16 @@ } catch (err) {

}
if (node.timeOnlyOddWeeks) {
const weekNr = hlp.getWeekOfYear(dNow)[1];
if (weekNr % 2 === 0) { // even
result.warn = RED._('within-time-switch.errors.only-odd-week');
return result;
}
}
if (node.timeOnlyEvenWeeks) {
const weekNr = hlp.getWeekOfYear(dNow[1]);
if (weekNr % 2 !== 0) { // odd
result.warn = RED._('within-time-switch.errors.only-even-week');
return result;
}
}
result.valid = true;

@@ -215,3 +239,3 @@

result.altStartTime = node.positionConfig.comparePropValue(node, msg, node.propertyStart,
node.propertyStartOperator, node.propertyStartThreshold);
node.propertyStartOperator, node.propertyStartThreshold, false, dNow);
} catch (err) {

@@ -238,3 +262,3 @@ result.altStartTime = false;

result.altEndTime = node.positionConfig.comparePropValue(node, msg, node.propertyEnd,
node.propertyEndOperator, node.propertyEndThreshold);
node.propertyEndOperator, node.propertyEndThreshold, false, dNow);
} catch (err) {

@@ -359,4 +383,16 @@ result.altEndTime = false;

if (this.timeRestrictions.type === 'none') { // none means limitations would defined internal!
this.timeOnlyEvenDays = config.timeOnlyEvenDays;
this.timeOnlyOddDays = config.timeOnlyOddDays;
this.timeOnlyEvenDays = hlp.isTrue(config.timeOnlyEvenDays);
this.timeOnlyOddDays = hlp.isTrue(config.timeOnlyOddDays);
this.timeOnlyEvenWeeks = hlp.isTrue(config.timeOnlyEvenWeeks);
this.timeOnlyOddWeeks = hlp.isTrue(config.timeOnlyOddWeeks);
if (this.timeOnlyEvenDays && this.timeOnlyOddDays) {
this.timeOnlyEvenDays = false;
this.timeOnlyOddDays = false;
}
if (this.timeOnlyEvenWeeks && this.timeOnlyOddWeeks) {
this.timeOnlyEvenWeeks = false;
this.timeOnlyOddWeeks = false;
}
if (typeof config.timedatestart !== undefined && config.timedatestart !== '') {

@@ -388,8 +424,11 @@ this.timeStartDate = new Date(config.timedatestart);

}
if (this.timeOnlyEvenDays && this.timeOnlyOddDays) {
this.timeOnlyEvenDays = false;
this.timeOnlyOddDays = false;
}
}
this.withinTimeValue = {
value : config.withinTimeValue ? config.withinTimeValue : 'true',
type : config.withinTimeValueType ? config.withinTimeValueType : 'input'
};
this.outOfTimeValue = {
value : config.outOfTimeValue ? config.outOfTimeValue : 'false',
type : config.outOfTimeValueType ? config.outOfTimeValueType : 'input'
};

@@ -414,4 +453,4 @@ this.timeOutObj = null;

// this.debug('self ' + util.inspect(this, { colors: true, compact: 10, breakLength: Infinity }));
const now = getIntDate(config.tsCompare, msg, node);
const result = calcWithinTimes(this, msg, now);
const dNow = getIntDate(config.tsCompare, msg, node);
const result = calcWithinTimes(this, msg, dNow);

@@ -423,3 +462,3 @@ if (result.valid && result.start.value && result.end.value) {

msg.withinTimeEnd.id = hlp.getTimeNumberUTC(result.end.value);
const cmpNow = hlp.getTimeNumberUTC(now);
const cmpNow = hlp.getTimeNumberUTC(dNow);
setstate(node, result);

@@ -430,4 +469,10 @@ if (msg.withinTimeStart.id < msg.withinTimeEnd.id) {

this.debug('in time [1] - send msg to first output ' + result.startSuffix +
node.positionConfig.toDateTimeString(now) + result.endSuffix + ' (' + msg.withinTimeStart.id + ' - ' + cmpNow + ' - ' + msg.withinTimeEnd.id + ')');
send([msg, null]); // this.send([msg, null]);
node.positionConfig.toDateTimeString(dNow) + result.endSuffix + ' (' + msg.withinTimeStart.id + ' - ' + cmpNow + ' - ' + msg.withinTimeEnd.id + ')');
if (node.withinTimeValue.type === 'input') {
send([msg, null]); // within time
} else {
const resultMsg = RED.util.cloneMessage(msg);
resultMsg.payload = node.positionConfig.getOutDataProp(node, msg, node.withinTimeValue, dNow);
send([resultMsg, null]); // within time
}
done();

@@ -439,4 +484,10 @@ return null;

this.debug('in time [2] - send msg to first output ' + result.startSuffix +
node.positionConfig.toDateTimeString(now) + result.endSuffix + ' (' + msg.withinTimeStart.id + ' - ' + cmpNow + ' - ' + msg.withinTimeEnd.id + ')');
send([msg, null]); // this.send([msg, null]);
node.positionConfig.toDateTimeString(dNow) + result.endSuffix + ' (' + msg.withinTimeStart.id + ' - ' + cmpNow + ' - ' + msg.withinTimeEnd.id + ')');
if (node.withinTimeValue.type === 'input') {
send([msg, null]); // within time
} else {
const resultMsg = RED.util.cloneMessage(msg);
resultMsg.payload = node.positionConfig.getOutDataProp(node, msg, node.withinTimeValue, dNow);
send([resultMsg, null]); // within time
}
done();

@@ -449,4 +500,10 @@ return null;

msg.withinTime = false;
this.debug('out of time - send msg to second output ' + result.startSuffix + node.positionConfig.toDateTimeString(now) + result.endSuffix);
send([null, msg]); // this.send([null, msg]);
this.debug('out of time - send msg to second output ' + result.startSuffix + node.positionConfig.toDateTimeString(dNow) + result.endSuffix);
if (node.outOfTimeValue.type === 'input') {
send([null, msg]); // out of time
} else {
const resultMsg = RED.util.cloneMessage(msg);
resultMsg.payload = node.positionConfig.getOutDataProp(node, msg, node.outOfTimeValue, dNow);
send([null, resultMsg]); // out of time
}
done();

@@ -453,0 +510,0 @@ return null;

{
"name": "node-red-contrib-sun-position",
"version": "1.2.4",
"version": "2.0.3",
"description": "NodeRED nodes to get sun and moon position",

@@ -45,3 +45,7 @@ "keywords": [

"blind",
"blind-control"
"blind-control",
"home+automation",
"cover",
"roller",
"shutter"
],

@@ -106,7 +110,11 @@ "main": "none",

},
"dependencies": {
"lodash.clonedeep": "^4.5.0",
"lodash.isequal": "^4.5.0"
},
"devDependencies": {
"eslint": "^7.20.0",
"eslint-plugin-html": "^6.1.1",
"eslint-plugin-jsdoc": "^32.0.2",
"eslint-plugin-json": "^2.1.2",
"eslint": "^8.2.0",
"eslint-plugin-html": "^6.2.0",
"eslint-plugin-jsdoc": "^37.0.3",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-node": "^11.1.0"

@@ -113,0 +121,0 @@ },

@@ -25,2 +25,4 @@ # node-red-contrib-sun-position for NodeRED

⚠ Nodes that were created or saved with a version 2.0.0 or later do not work in versions prior 2.0.0 of the package.
## Table of contents

@@ -27,0 +29,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc