@mschaeffler/node-red-bthome 1.4.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,6 +12,9 @@ At the moment these sensors are implemented and tested:
12
12
  - Shelly BLU RC Button 4
13
13
  - Shelly BLU Wall Switch 4
14
14
  - Shelly BLU Motion
15
+ - Shelly BLU Distance
16
+ - Shelly BLU Remote
17
+ - Ecowitt WS90
15
18
 
16
19
  ## Capture of Raw Frames
17
20
 
@@ -29,14 +32,18 @@ This node can decrypt [encrypted messages](https://bthome.io/encryption/), if th
29
32
  $ npm install @mschaeffler/node-red-bthome
30
33
  ```
31
34
 
32
- ## Input
35
+ ## bthome Node
36
+
37
+ This node decodes the raw frames.
38
+
39
+ ### Input
33
40
 
34
41
  |msg. | type | description |
35
42
  |:-------|:-------|:----------------------------------|
36
43
  |payload | object | data from Shelly script|
37
44
  |resync | boolean| if set to yes, allow all packed ids; to resync after some issue|
38
45
 
39
- ### msg.payload
46
+ #### msg.payload
40
47
 
41
48
  Only the first two values are needed, the others are optional.
42
49
 
@@ -59,27 +66,27 @@ This is an example of such a message payload:
59
66
  }
60
67
  ```
61
68
 
62
- ## Outputs
69
+ ### Outputs
63
70
 
64
71
  There are two output ports:
65
72
  1. one for meassurement values (states)
66
73
  2. one for actions done with the devices (events)
67
74
 
68
- ### State
75
+ #### State
69
76
 
70
77
  |msg. | type | description |
71
78
  |:-------|:-------|:----------------------------------|
72
79
  |topic | string | `State-Prefix` + name of the device|
73
80
  |payload | object | decoded state data|
74
81
 
75
- ### Events
82
+ #### Events
76
83
 
77
84
  |msg. | type | description |
78
85
  |:-------|:-------|:----------------------------------|
79
86
  |topic | string | `Event-Prefix` + name of the device|
80
87
  |payload | object | data of the decoded event|
81
88
 
82
- ## Parameters
89
+ ### Parameters
83
90
 
84
91
  |config | type | description |
85
92
  |:------------|:-------|:----------------------------------|
@@ -90,7 +97,7 @@ There are two output ports:
90
97
  |Context-Variable| string | name of the variable in flow context storage |
91
98
  |Contextstore | string | context store to be used |
92
99
 
93
- ### Device-Configuration
100
+ #### Device-Configuration
94
101
 
95
102
  With this JSON string the installed [BT-Home](https://bthome.io) devices are configured:
96
103
  ```
@@ -109,7 +116,7 @@ An example for such a config from the unit tests:
109
116
  }
110
117
  ```
111
118
 
112
- ### Context storage
119
+ #### Context storage
113
120
 
114
121
  All recorded data can be stored in a flow context variable for
115
122
  - initialisation
@@ -136,10 +143,73 @@ If content storage is active, statistical data is also stored in a variable with
136
143
  { ok:0, err:0, old:0, dup:0 }
137
144
  ```
138
145
 
146
+ ## ws90 Node
147
+
148
+ This node does some additional calculations to get more usefull data from the WS90 weather station.
149
+
150
+ Similar calculations are done by the Ecowitt base stations.
151
+
152
+ ### Input
153
+
154
+ |msg. | type | description |
155
+ |:-------|:-------|:----------------------------------|
156
+ |payload |object |data from `bthome` node. |
157
+
158
+ This is an example of such a message payload:
159
+ ```
160
+ {
161
+ "lux": 3630,
162
+ "moisture": false,
163
+ "wind": [1.5,1.5],
164
+ "uv": 0,
165
+ "direction": 174,
166
+ "pressure": 948.2,
167
+ "dewpoint": -0.43,
168
+ "humidity": 99,
169
+ "temperature": -0.3,
170
+ "precipitation": 121.5
171
+ }
172
+ ```
173
+
174
+ ### Outputs
175
+
176
+ There are 12 output ports:
177
+ - temperature
178
+ - dew point
179
+ - humidity
180
+ - raining²
181
+ - rain yesterday
182
+ - rain today
183
+ - uv²
184
+ - air pressure
185
+ - direction
186
+ - wind²
187
+ - wind max
188
+ - illumination
189
+
190
+ ²: this values have style classes for the `dashboard 2` attached.
191
+
192
+ #### style classes
193
+ This classes should be defined (for an example check the `ui-template` in the
194
+ [examples](https://github.com/m-schaeffler/node-red-my-nodes/raw/main/node-red-bthome/examples/CSS.json)):
195
+ - greenValue
196
+ - yellowValue
197
+ - redValue
198
+ - blueValue
199
+
200
+ ### Parameters
201
+
202
+ |config | type | description |
203
+ |:------------|:-------|:----------------------------------|
204
+ |Contextstore | string | context store to be used. |
205
+ |reference height|number| height of the installation over the sea level, to caculate the absolute air pressure. |
206
+
139
207
  ## Example Flow
140
208
 
141
209
  [example flow](https://github.com/m-schaeffler/node-red-my-nodes/raw/main/node-red-bthome/examples/bthome.json)
142
210
 
211
+ [CSS template](https://github.com/m-schaeffler/node-red-my-nodes/raw/main/node-red-bthome/examples/CSS.json)
212
+
143
213
  ## Author
144
214
 
145
215
  [Mathias Schäffler](https://github.com/m-schaeffler)
package/bthome.js CHANGED
@@ -189,7 +189,7 @@ module.exports = function(RED) {
189
189
  setData( "lux", rawdata.getUInt24() / 100 );
190
190
  break;
191
191
  case 0x08:
192
- setData( "dewpoint", rawdata.getInt16() /100 );
192
+ setData( "dewpoint", rawdata.getInt16() / 100 );
193
193
  break;
194
194
  case 0x0C:
195
195
  if( node.batteryState )
@@ -203,6 +203,9 @@ module.exports = function(RED) {
203
203
  delete item.data?.voltage;
204
204
  }
205
205
  break;
206
+ case 0x1E:
207
+ setData( "light", rawdata.getUInt8() );
208
+ break;
206
209
  case 0x20:
207
210
  setData( "moisture", Boolean( rawdata.getUInt8() ) );
208
211
  break;
@@ -0,0 +1,54 @@
1
+ [
2
+ {
3
+ "id": "fb58dd887406a7d3",
4
+ "type": "ui-template",
5
+ "z": "bf934c281a6f35c0",
6
+ "group": "",
7
+ "page": "",
8
+ "ui": "fd06eabec55c4e5d",
9
+ "name": "CSS classes 2.0",
10
+ "order": 0,
11
+ "width": 0,
12
+ "height": 0,
13
+ "head": "",
14
+ "format": ".red label.nrdb-ui-text-label, .red span, .redValue span.nrdb-ui-text-value, span.red {\n color: red !important;\n}\n.green label.nrdb-ui-text-label, .green span, .greenValue span.nrdb-ui-text-value, span.green {\n color: LimeGreen !important;\n}\n.darkgreen label.nrdb-ui-text-label, .darkgreen span, span.darkgreen {\n color: green !important;\n}\n.blue label.nrdb-ui-text-label, .blue span, .blueValue span.nrdb-ui-text-value, span.blue {\n color: aqua !important;\n}\n.yellow label.nrdb-ui-text-label, .yellow span, .yellowValue span.nrdb-ui-text-value, span.yellow {\n color: yellow !important;\n}\n.gray label.nrdb-ui-text-label, .gray span, .grayValue span.nrdb-ui-text-value, span.gray {\n color: gray !important;\n}\n.silver label.nrdb-ui-text-label, .silver span, .silverValue span.nrdb-ui-text-value, span.silver {\n color: #b0b0b0 !important;\n}",
15
+ "storeOutMessages": true,
16
+ "passthru": false,
17
+ "resendOnRefresh": true,
18
+ "templateScope": "site:style",
19
+ "className": "",
20
+ "x": 440,
21
+ "y": 640,
22
+ "wires": [
23
+ []
24
+ ]
25
+ },
26
+ {
27
+ "id": "fd06eabec55c4e5d",
28
+ "type": "ui-base",
29
+ "name": "Dashboard 2.0",
30
+ "path": "/dashboard",
31
+ "appIcon": "",
32
+ "includeClientData": false,
33
+ "acceptsClientConfig": [
34
+ "ui-notification",
35
+ "ui-control"
36
+ ],
37
+ "showPathInSidebar": false,
38
+ "headerContent": "page",
39
+ "navigationStyle": "default",
40
+ "titleBarStyle": "fixed",
41
+ "showReconnectNotification": false,
42
+ "notificationDisplayTime": "5",
43
+ "showDisconnectNotification": false,
44
+ "allowInstall": true
45
+ },
46
+ {
47
+ "id": "7d327676499cd8a2",
48
+ "type": "global-config",
49
+ "env": [],
50
+ "modules": {
51
+ "@flowfuse/node-red-dashboard": "1.29.0"
52
+ }
53
+ }
54
+ ]
@@ -1,8 +1,8 @@
1
1
  [
2
2
  {
3
- "id": "3a9fcdbd98993dbc",
3
+ "id": "da2333b077f13c53",
4
4
  "type": "mqtt in",
5
- "z": "8e0e9a167c607864",
5
+ "z": "1607080a6a66359a",
6
6
  "name": "",
7
7
  "topic": "node-red/bleraw",
8
8
  "qos": "0",
@@ -12,39 +12,42 @@
12
12
  "rap": true,
13
13
  "rh": 0,
14
14
  "inputs": 0,
15
- "x": 140,
16
- "y": 1460,
15
+ "x": 260,
16
+ "y": 560,
17
17
  "wires": [
18
18
  [
19
- "c4df490573c18fc4"
19
+ "da23792a27f30483"
20
20
  ]
21
21
  ]
22
22
  },
23
23
  {
24
- "id": "c4df490573c18fc4",
24
+ "id": "da23792a27f30483",
25
25
  "type": "bthome",
26
- "z": "8e0e9a167c607864",
26
+ "z": "1607080a6a66359a",
27
27
  "name": "",
28
28
  "devices": "{\"11:22:33:44:55:66\":{\"topic\":\"dev_unencrypted_1\"},\"00:01:02:03:04:05\":{\"topic\":\"dev_unencrypted_2\"},\"00:10:20:30:40:50\":{\"topic\":\"dev_encrypted_1\",\"key\":\"00112233445566778899AABBCCDDEEFF\"},\"00:00:00:00:00:00\":{\"topic\":\"dev_encrypted_2\",\"key\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]}}",
29
+ "counterMode": "none",
29
30
  "statusPrefix": "Status",
30
31
  "eventPrefix": "Event",
31
32
  "contextVar": "bt-home",
32
33
  "contextStore": "memoryOnly",
33
- "x": 340,
34
- "y": 1440,
34
+ "batteryState": false,
35
+ "x": 460,
36
+ "y": 540,
35
37
  "wires": [
36
38
  [
37
- "3c9fee837ed43fc0"
39
+ "45cc12931b5a0b52",
40
+ "02887e37eebfaae5"
38
41
  ],
39
42
  [
40
- "26ebe1833f97c4d4"
43
+ "347a2db3d0351824"
41
44
  ]
42
45
  ]
43
46
  },
44
47
  {
45
- "id": "3c9fee837ed43fc0",
48
+ "id": "45cc12931b5a0b52",
46
49
  "type": "debug",
47
- "z": "8e0e9a167c607864",
50
+ "z": "1607080a6a66359a",
48
51
  "name": "debug 9",
49
52
  "active": true,
50
53
  "tosidebar": true,
@@ -53,14 +56,14 @@
53
56
  "complete": "false",
54
57
  "statusVal": "",
55
58
  "statusType": "auto",
56
- "x": 520,
57
- "y": 1420,
59
+ "x": 640,
60
+ "y": 520,
58
61
  "wires": []
59
62
  },
60
63
  {
61
- "id": "26ebe1833f97c4d4",
64
+ "id": "347a2db3d0351824",
62
65
  "type": "debug",
63
- "z": "8e0e9a167c607864",
66
+ "z": "1607080a6a66359a",
64
67
  "name": "debug 10",
65
68
  "active": true,
66
69
  "tosidebar": true,
@@ -69,14 +72,14 @@
69
72
  "complete": "false",
70
73
  "statusVal": "",
71
74
  "statusType": "auto",
72
- "x": 520,
73
- "y": 1460,
75
+ "x": 640,
76
+ "y": 560,
74
77
  "wires": []
75
78
  },
76
79
  {
77
- "id": "e3ad83be53fa3fe3",
80
+ "id": "5ba4c641b627284d",
78
81
  "type": "inject",
79
- "z": "8e0e9a167c607864",
82
+ "z": "1607080a6a66359a",
80
83
  "name": "",
81
84
  "props": [
82
85
  {
@@ -94,14 +97,63 @@
94
97
  "topic": "",
95
98
  "payload": "{\"addr\":\"11:22:33:44:55:66\",\"rssi\":-85,\"time\":1745395033113,\"gateway\":\"Shelly Gateway\",\"data\":[68,0,164,1,100,46,56,69,43,255]}",
96
99
  "payloadType": "json",
97
- "x": 170,
98
- "y": 1420,
100
+ "x": 290,
101
+ "y": 520,
99
102
  "wires": [
100
103
  [
101
- "c4df490573c18fc4"
104
+ "da23792a27f30483"
102
105
  ]
103
106
  ]
104
107
  },
108
+ {
109
+ "id": "02887e37eebfaae5",
110
+ "type": "switch",
111
+ "z": "1607080a6a66359a",
112
+ "name": "is WS90",
113
+ "property": "payload",
114
+ "propertyType": "msg",
115
+ "rules": [
116
+ {
117
+ "t": "hask",
118
+ "v": "dewpoint",
119
+ "vt": "str"
120
+ }
121
+ ],
122
+ "checkall": "false",
123
+ "repair": false,
124
+ "outputs": 1,
125
+ "x": 480,
126
+ "y": 360,
127
+ "wires": [
128
+ [
129
+ "57b7cd4b7d2e6f25"
130
+ ]
131
+ ]
132
+ },
133
+ {
134
+ "id": "57b7cd4b7d2e6f25",
135
+ "type": "ws90",
136
+ "z": "1607080a6a66359a",
137
+ "name": "",
138
+ "contextStore": "memoryOnly",
139
+ "refheight": "500",
140
+ "x": 630,
141
+ "y": 360,
142
+ "wires": [
143
+ [],
144
+ [],
145
+ [],
146
+ [],
147
+ [],
148
+ [],
149
+ [],
150
+ [],
151
+ [],
152
+ [],
153
+ [],
154
+ []
155
+ ]
156
+ },
105
157
  {
106
158
  "id": "66b8b47e.0f87bc",
107
159
  "type": "mqtt-broker",
@@ -133,5 +185,13 @@
133
185
  "willMsg": {},
134
186
  "userProps": "",
135
187
  "sessionExpiry": ""
188
+ },
189
+ {
190
+ "id": "888386dbbbc56d84",
191
+ "type": "global-config",
192
+ "env": [],
193
+ "modules": {
194
+ "@mschaeffler/node-red-bthome": "1.6.0"
195
+ }
136
196
  }
137
197
  ]
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mschaeffler/node-red-bthome",
3
- "version": "1.4.3",
3
+ "version": "1.6.0",
4
4
  "description": "A Node Red node to decrypt and decode BT-Home frames",
5
5
  "author": {
6
6
  "name": "Mathias Schäffler",
@@ -12,7 +12,8 @@
12
12
  "BT-Home",
13
13
  "bthome",
14
14
  "Shelly BLU",
15
- "BLE"
15
+ "BLE",
16
+ "WS90"
16
17
  ],
17
18
  "bugs": {
18
19
  "url": "https://github.com/m-schaeffler/node-red-my-nodes/tree/main/node-red-bthome/issues"
@@ -25,7 +26,8 @@
25
26
  "node-red": {
26
27
  "version": ">=4.0.0",
27
28
  "nodes": {
28
- "bthome": "bthome.js"
29
+ "bthome": "bthome.js",
30
+ "ws90": "ws90.js"
29
31
  }
30
32
  },
31
33
  "engines": {
package/ws90.html ADDED
@@ -0,0 +1,115 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('ws90',{
3
+ category: 'input',
4
+ color: '#DEB887',
5
+ defaults: {
6
+ name: {value:""},
7
+ contextStore:{value:"none",required:true},
8
+ refheight:{value:0,validate:RED.validators.number(),required:true}
9
+ },
10
+ inputs:1,
11
+ outputs:12,
12
+ icon: "font-awesome/fa-sun-o",
13
+ label: function() {
14
+ return this.name||"WS 90";
15
+ },
16
+ labelStyle: function() {
17
+ return this.name?"node_label_italic":"";
18
+ },
19
+ paletteLabel: "ws 90",
20
+ inputLabels: 'decoded bthome frame from ws90',
21
+ outputLabels: ['temperature','dew point','humidity','raining','rain yesterday','rain today','uv','air pressure','direction','wind','wind max','illumination'],
22
+ oneditprepare: function() {
23
+ const node = this;
24
+ // populate store names
25
+ $("#node-input-contextStore").empty();
26
+ $("#node-input-contextStore").append(`<option value="none">None</option>`);
27
+ const defaultStore = RED.settings.hasOwnProperty('context') ? RED.settings.context.default : '';
28
+ RED.settings.context.stores.forEach(function(item){
29
+ if( item ) {
30
+ const opt = $(`<option value="${item}">${item}${item===defaultStore?" (default)":""}</option>`);
31
+ $("#node-input-contextStore").append(opt);
32
+ }
33
+ });
34
+ const currentStore = node.contextStore || '';
35
+ // select the current option
36
+ $("#node-input-contextStore").val(currentStore);
37
+ }
38
+ });
39
+ </script>
40
+
41
+ <script type="text/x-red" data-template-name="ws90">
42
+ <div class="form-row">
43
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
44
+ <input type="text" id="node-input-name" placeholder="Name">
45
+ </div>
46
+ <div class="form-row">
47
+ <label for="node-input-contextStore"><i class="fa fa-database"></i> Contextstore</label>
48
+ <select type="text" id="node-input-contextStore"></select>
49
+ </div>
50
+ <div class="form-row">
51
+ <label for="node-input-refheight"><i class="fa fa-"></i> reference height</label>
52
+ <input type="text" id="node-input-refheight">
53
+ </div>
54
+ </script>
55
+
56
+ <script type="text/x-red" data-help-name="ws90">
57
+
58
+ <p>A Node Red node to work with data from the WS90 weather station.</p>
59
+
60
+ <h3>Input</h3>
61
+ <dl class="message-properties">
62
+ <dt>payload <span class="property-type">object</span></dt>
63
+ <dd> data from <code>bthome</code> node.</dd>
64
+ </dl>
65
+
66
+ <p>This is an example of such a message payload:</p>
67
+ <code>{<br>
68
+ "lux": 3630,<br>
69
+ "moisture": false,<br>
70
+ "wind": [1.5,1.5],<br>
71
+ "uv": 0,<br>
72
+ "direction": 174,<br>
73
+ "pressure": 948.2,<br>
74
+ "dewpoint": -0.43,<br>
75
+ "humidity": 99,<br>
76
+ "temperature": -0.3,<br>
77
+ "precipitation": 121.5<br>
78
+ }</code>
79
+
80
+ <h3>Outputs</h3>
81
+ <p>There are 12 output ports:</p>
82
+ <ol>
83
+ <li>temperature</li>
84
+ <li>dew point</li>
85
+ <li>humidity</li>
86
+ <li>raining²</li>
87
+ <li>rain yesterday</li>
88
+ <li>rain today</li>
89
+ <li>uv²</li>
90
+ <li>air pressure</li>
91
+ <li>direction</li>
92
+ <li>wind²</li>
93
+ <li>wind max</li>
94
+ <li>illumination</li>
95
+ </ol>
96
+ <p>²: this values have style classes for the <code>dashboard 2</code> attached.</p>
97
+
98
+ <h4>style classes</h4>
99
+ <p>This classes should be defined (for an example check the <code>ui-template</code> in the <a href="https://github.com/m-schaeffler/node-red-my-nodes/raw/main/node-red-bthome/examples/CSS.json">examples</a>):<p>
100
+ <ul>
101
+ <li>greenValue</li>
102
+ <li>yellowValue</li>
103
+ <li>redValue</li>
104
+ <li>blueValue</li>
105
+ </ul>
106
+
107
+ <h3>Parameters</h3>
108
+ <dl class="message-properties">
109
+ <dt>Contextstore <span class="property-type">string</span></dt>
110
+ <dd> context store to be used.</dd>
111
+ <dt>reference height <span class="property-type">number</span></dt>
112
+ <dd> height of the installation over the sea level, to caculate the absolute air pressure.</dt>
113
+ </dl>
114
+
115
+ </script>
package/ws90.js ADDED
@@ -0,0 +1,154 @@
1
+ module.exports = function(RED) {
2
+
3
+ function Ws90Node(config) {
4
+ RED.nodes.createNode(this,config);
5
+ var node = this;
6
+ var context = this.context();
7
+ this.contextStore = config.contextStore ?? "none";
8
+ this.refheight = Number( config.refheight ?? 0 );
9
+ this.timebase = Number( config.timebase ?? 60 ) * 1000;
10
+ this.last = {};
11
+ this.storage = {Raining:false,RegenHeute:0,RegenGestern:0,WindMax:0};
12
+ node.status( "" );
13
+ if( node.contextStore !== "none" )
14
+ {
15
+ context.get( "storage", node.contextStore, function(err,value)
16
+ {
17
+ if( err )
18
+ {
19
+ node.error( err );
20
+ }
21
+ else
22
+ {
23
+ //console.log( "context read", value );
24
+ if( value !== undefined )
25
+ {
26
+ node.storage = value;
27
+ }
28
+ }
29
+ } );
30
+ }
31
+
32
+ function ampel(value,v1,v2,s1="")
33
+ {
34
+ return value <= v1 ? s1 : ( value <= v2 ? "yellowValue" : "redValue" );
35
+ }
36
+
37
+ function setStorage(topic,value)
38
+ {
39
+ node.storage[topic] = value;
40
+ if( node.contextStore !== "none" )
41
+ {
42
+ context.set( "storage", node.storage, node.contextStore );
43
+ }
44
+ }
45
+
46
+ function genMessage(name,value,style=null)
47
+ {
48
+ if( node.last[name]?.value !== value || node.last[name]?.style !== style )
49
+ {
50
+ node.last[name] = { value:value, style:style };
51
+ let result = { topic: name, payload: value };
52
+ if( style !== null )
53
+ {
54
+ result.ui_update = { class: style };
55
+ }
56
+ return result;
57
+ }
58
+ else
59
+ {
60
+ return null;
61
+ }
62
+ }
63
+
64
+ node.on('input', function(msg,send,done) {
65
+ if( msg.invalid )
66
+ {
67
+ }
68
+ else if( msg.reset || msg.topic==="init" )
69
+ {
70
+ node.last = {};
71
+ }
72
+ else if( msg.newday || msg.topic==="newday" )
73
+ {
74
+ setStorage( "RegenGestern", node.storage.RegenHeute );
75
+ setStorage( "RegenHeute", 0 );
76
+ setStorage( "WindMax", 0 );
77
+ }
78
+ else if( typeof msg.payload !== "object" || msg.payload.temperature === undefined )
79
+ {
80
+ node.error( "invalid payload "+msg.payload );
81
+ }
82
+ else
83
+ {
84
+ const now = Date.now();
85
+
86
+ // Luftdruck https://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel
87
+ //const E = temperature >= 9.1 ? 18.219 * ( 1.0463 - Math.exp( -0.0666 * temperature ) ) : 5.6402 * ( Math.exp( 0.06 * temperature ) - 0.0916 );
88
+ const p_H2O = ( 6.112 * Math.exp((17.62 * msg.payload.temperature) / ( msg.payload.temperature + 243.12)) * msg.payload.humidity) / 100; // Partialdruck Wasserdampf https://www.schweizer-fn.de/lueftung/feuchte/feuchte.php
89
+ const h = node.refheight; // Ortshöhe
90
+ const normdruck = msg.payload.pressure * Math.exp( 9.80665 / ( 287.05 * ( 273.15 + msg.payload.temperature + 0.12 * p_H2O + 0.0065 * h / 2 ) ) * h );
91
+
92
+ // Regen
93
+ let raining = node.storage.Raining;
94
+ function setRaining(value,timeout)
95
+ {
96
+ raining = value;
97
+ setStorage( "rainingDate", value ? now + timeout*node.timebase : 8640000000000000 );
98
+ if( node.storage.Raining !== value )
99
+ {
100
+ setStorage( "Raining", value );
101
+ }
102
+ }
103
+ if( msg.payload.moisture && ! node.storage.moisture )
104
+ {
105
+ setRaining( true, 15 );
106
+ }
107
+ else if( now >= node.storage.rainingDate )
108
+ {
109
+ setRaining( false, 0 );
110
+ }
111
+ setStorage( "moisture", msg.payload.moisture );
112
+
113
+ // Regenmenge
114
+ if( msg.payload.precipitation > node.storage.Regen )
115
+ {
116
+ setStorage( "RegenHeute", node.storage.RegenHeute + msg.payload.precipitation - node.storage.Regen );
117
+ setRaining( true, 20 );
118
+ }
119
+ else if( msg.payload.precipitation < node.storage.Regen && msg.payload.precipitation <= 10 )
120
+ {
121
+ setStorage( "RegenHeute", node.storage.RegenHeute + msg.payload.precipitation );
122
+ setRaining( true, 20 );
123
+ }
124
+ setStorage( "Regen", msg.payload.precipitation );
125
+
126
+ // Wind
127
+ const wind = msg.payload.wind[1] * 3.6;
128
+ if( wind > node.storage.WindMax )
129
+ {
130
+ setStorage( "WindMax", wind );
131
+ }
132
+
133
+ node.status( Math.round( normdruck ) );
134
+ send( [
135
+ genMessage( "outside temperature", msg.payload.temperature ),
136
+ genMessage( "dew point", msg.payload.dewpoint ),
137
+ genMessage( "humidity", msg.payload.humidity ),
138
+ genMessage( "raining", raining ),
139
+ genMessage( "rain yesterday", node.storage.RegenGestern ),
140
+ genMessage( "rain today", node.storage.RegenHeute, msg.payload.moisture ? "blueValue" : "" ),
141
+ genMessage( "uv index", msg.payload.uv, ampel( msg.payload.uv, 2, 5, "greenValue" ) ),
142
+ genMessage( "air pressure", normdruck ),
143
+ genMessage( "wind direction", msg.payload.direction ),
144
+ genMessage( "wind", wind, ampel( wind, 25, 50 ) ),
145
+ genMessage( "wind_max", node.storage.WindMax ),
146
+ genMessage( "illumination", msg.payload.lux )
147
+ ] );
148
+ }
149
+ done();
150
+ });
151
+ }
152
+
153
+ RED.nodes.registerType( "ws90", Ws90Node );
154
+ }