mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
Add out node
This commit is contained in:
parent
20f14a698c
commit
0cc33db58f
@ -28,7 +28,8 @@ Run the following command in your Node-RED user directory (typically `~/.node-re
|
|||||||
|
|
||||||
### Input Node
|
### Input Node
|
||||||
|
|
||||||
This node sends readings from the various sensors on the Sense HAT, grouped into three sets; motion events, environment events and joystick events.
|
This node sends readings from the various sensors on the Sense HAT, grouped into
|
||||||
|
three sets; motion events, environment events and joystick events.
|
||||||
|
|
||||||
#### Motion events
|
#### Motion events
|
||||||
|
|
||||||
@ -38,9 +39,9 @@ per second. The `topic` is set to `motion` and the `payload` is an object with t
|
|||||||
following values:
|
following values:
|
||||||
|
|
||||||
- `acceleration.x/y/z` : the acceleration intensity in Gs
|
- `acceleration.x/y/z` : the acceleration intensity in Gs
|
||||||
- `gyroscope.x/y/z` : the rotational intensity in radians/s
|
-`gyroscope.x/y/z` : the rotational intensity in radians/s
|
||||||
- `orientation.roll/pitch/yaw` : the angle of the axis in degrees
|
-`orientation.roll/pitch/yaw` : the angle of the axis in degrees
|
||||||
- `compass` : the direction of North in degrees
|
-`compass` : the direction of North in degrees
|
||||||
|
|
||||||
#### Environment events
|
#### Environment events
|
||||||
|
|
||||||
@ -49,17 +50,69 @@ sensors. They are sent at a rate of approximately 1 per second. The `topic`
|
|||||||
is set to `environment` and the `payload` is an object
|
is set to `environment` and the `payload` is an object
|
||||||
with the following values:
|
with the following values:
|
||||||
|
|
||||||
- `temperature` : degrees Celsius
|
-`temperature` : degrees Celsius
|
||||||
- `humidity` : percentage of relative humidity
|
-`humidity` : percentage of relative humidity
|
||||||
- `pressure` : Millibars
|
-`pressure` : Millibars
|
||||||
|
|
||||||
#### Joystick events
|
#### Joystick events
|
||||||
|
|
||||||
Joystick events are sent when the Sense HAT joystick is interacted with. The
|
Joystick events are sent when the Sense HAT joystick is interacted with. The
|
||||||
`topic` is set to `joystick` and the `payload` is an object with the following values:
|
`topic` is set to `joystick` and the `payload` is an object with the following values:
|
||||||
|
|
||||||
- `key` : one of `UP`, `DOWN`, `LEFT`, `RIGHT`, `ENTER`
|
-`key` : one of `UP`, `DOWN`, `LEFT`, `RIGHT`, `ENTER`
|
||||||
- `state` : the state of the key:
|
-`state` : the state of the key:
|
||||||
- `0` : the key has been released
|
-`0` : the key has been released
|
||||||
- `1` : the key has been pressed
|
-`1` : the key has been pressed
|
||||||
- `2` : the key is being held down
|
-`2` : the key is being held down
|
||||||
|
|
||||||
|
|
||||||
|
### Output Node
|
||||||
|
|
||||||
|
This node sends commands to the 8x8 LED display on the Sense HAT.
|
||||||
|
|
||||||
|
Commands are sent to the node in `msg.payload`. Multiple commands can
|
||||||
|
be sent in a single message by separating them with newline (\n) characters.
|
||||||
|
|
||||||
|
#### Set the colour of individual pixels
|
||||||
|
|
||||||
|
Format: `<x>,<y>,<colour>`
|
||||||
|
|
||||||
|
`x` and `y` must either be a value in the range 0-7, or `*` to indicate the entire row or column.
|
||||||
|
|
||||||
|
`colour` must be one of:
|
||||||
|
|
||||||
|
- the well-known <a href="https://en.wikipedia.org/wiki/Web_colors" target="_new">HTML colour names</a>
|
||||||
|
- eg `red` or `aquamarine`,
|
||||||
|
- the <a href="http://cheerlights.com/cheerlights-api/">CheerLights colour names</a>,
|
||||||
|
- a HEX colour value - eg `#aa9900`
|
||||||
|
- an RGB triple - `190,255,0`
|
||||||
|
- or simply `off`
|
||||||
|
|
||||||
|
To set the entire screen to red: `*,*,red`
|
||||||
|
|
||||||
|
To set the four corners of the display to red, green (#00ff00), yellow and blue (0,0,255):
|
||||||
|
|
||||||
|
`0,0,red,0,7,#00ff00,7,7,yellow,7,0,0,0,255`
|
||||||
|
|
||||||
|
#### Rotate the screen
|
||||||
|
|
||||||
|
Format: `R<angle>`
|
||||||
|
|
||||||
|
`angle` must be 0, 90, 180 or 270.
|
||||||
|
|
||||||
|
#### Flip the screen
|
||||||
|
|
||||||
|
Format: `R<axis>`
|
||||||
|
|
||||||
|
`axis` must be either `H` or `V` to flip on the horizontal or vertical axis respectively.
|
||||||
|
|
||||||
|
#### Scroll a message
|
||||||
|
|
||||||
|
If `msg.payload` is not recognised as any of the above commands, it is treated
|
||||||
|
as a text message to be scrolled across the screen.
|
||||||
|
|
||||||
|
The following message properties can be used to customise the appearance:
|
||||||
|
|
||||||
|
- `msg.colour` - the colour of the text, default: `white`
|
||||||
|
- `msg.background` - the colour of the background, default: `off`
|
||||||
|
- `msg.speed` - the scroll speed. A value in the range 1 (slower) to 5 (faster), default: `3`
|
||||||
|
220
hardware/sensehat/colours.js
Normal file
220
hardware/sensehat/colours.js
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 IBM Corp.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var colours = {
|
||||||
|
'aqua':'#00FFFF',
|
||||||
|
'aliceblue':'#F0F8FF',
|
||||||
|
'antiquewhite':'#FAEBD7',
|
||||||
|
'black':'#000000',
|
||||||
|
'off':'#000000',
|
||||||
|
'blue':'#0000FF',
|
||||||
|
'cyan':'#00FFFF',
|
||||||
|
'darkblue':'#00008B',
|
||||||
|
'darkcyan':'#008B8B',
|
||||||
|
'darkgreen':'#006400',
|
||||||
|
'darkturquoise':'#00CED1',
|
||||||
|
'deepskyblue':'#00BFFF',
|
||||||
|
'green':'#008000',
|
||||||
|
'lime':'#00FF00',
|
||||||
|
'mediumblue':'#0000CD',
|
||||||
|
'mediumspringgreen':'#00FA9A',
|
||||||
|
'navy':'#000080',
|
||||||
|
'springgreen':'#00FF7F',
|
||||||
|
'teal':'#008080',
|
||||||
|
'midnightblue':'#191970',
|
||||||
|
'dodgerblue':'#1E90FF',
|
||||||
|
'lightseagreen':'#20B2AA',
|
||||||
|
'forestgreen':'#228B22',
|
||||||
|
'seagreen':'#2E8B57',
|
||||||
|
'darkslategray':'#2F4F4F',
|
||||||
|
'darkslategrey':'#2F4F4F',
|
||||||
|
'limegreen':'#32CD32',
|
||||||
|
'mediumseagreen':'#3CB371',
|
||||||
|
'turquoise':'#40E0D0',
|
||||||
|
'royalblue':'#4169E1',
|
||||||
|
'steelblue':'#4682B4',
|
||||||
|
'darkslateblue':'#483D8B',
|
||||||
|
'mediumturquoise':'#48D1CC',
|
||||||
|
'indigo':'#4B0082',
|
||||||
|
'darkolivegreen':'#556B2F',
|
||||||
|
'cadetblue':'#5F9EA0',
|
||||||
|
'cornflowerblue':'#6495ED',
|
||||||
|
'mediumaquamarine':'#66CDAA',
|
||||||
|
'dimgray':'#696969',
|
||||||
|
'dimgrey':'#696969',
|
||||||
|
'slateblue':'#6A5ACD',
|
||||||
|
'olivedrab':'#6B8E23',
|
||||||
|
'slategray':'#708090',
|
||||||
|
'slategrey':'#708090',
|
||||||
|
'lightslategray':'#778899',
|
||||||
|
'lightslategrey':'#778899',
|
||||||
|
'mediumslateblue':'#7B68EE',
|
||||||
|
'lawngreen':'#7CFC00',
|
||||||
|
'aquamarine':'#7FFFD4',
|
||||||
|
'chartreuse':'#7FFF00',
|
||||||
|
'gray':'#808080',
|
||||||
|
'grey':'#808080',
|
||||||
|
'maroon':'#800000',
|
||||||
|
'olive':'#808000',
|
||||||
|
'purple':'#800080',
|
||||||
|
'lightskyblue':'#87CEFA',
|
||||||
|
'skyblue':'#87CEEB',
|
||||||
|
'blueviolet':'#8A2BE2',
|
||||||
|
'darkmagenta':'#8B008B',
|
||||||
|
'darkred':'#8B0000',
|
||||||
|
'saddlebrown':'#8B4513',
|
||||||
|
'darkseagreen':'#8FBC8F',
|
||||||
|
'lightgreen':'#90EE90',
|
||||||
|
'mediumpurple':'#9370DB',
|
||||||
|
'darkviolet':'#9400D3',
|
||||||
|
'palegreen':'#98FB98',
|
||||||
|
'darkorchid':'#9932CC',
|
||||||
|
'yellowgreen':'#9ACD32',
|
||||||
|
'sienna':'#A0522D',
|
||||||
|
'brown':'#A52A2A',
|
||||||
|
'darkgray':'#A9A9A9',
|
||||||
|
'darkgrey':'#A9A9A9',
|
||||||
|
'greenyellow':'#ADFF2F',
|
||||||
|
'lightblue':'#ADD8E6',
|
||||||
|
'paleturquoise':'#AFEEEE',
|
||||||
|
'lightsteelblue':'#B0C4DE',
|
||||||
|
'powderblue':'#B0E0E6',
|
||||||
|
'firebrick':'#B22222',
|
||||||
|
'darkgoldenrod':'#B8860B',
|
||||||
|
'mediumorchid':'#BA55D3',
|
||||||
|
'rosybrown':'#BC8F8F',
|
||||||
|
'darkkhaki':'#BDB76B',
|
||||||
|
'silver':'#C0C0C0',
|
||||||
|
'mediumvioletred':'#C71585',
|
||||||
|
'indianred':'#CD5C5C',
|
||||||
|
'peru':'#CD853F',
|
||||||
|
'chocolate':'#D2691E',
|
||||||
|
'tan':'#D2B48C',
|
||||||
|
'lightgray':'#D3D3D3',
|
||||||
|
'lightgrey':'#D3D3D3',
|
||||||
|
'thistle':'#D8BFD8',
|
||||||
|
'goldenrod':'#DAA520',
|
||||||
|
'orchid':'#DA70D6',
|
||||||
|
'palevioletred':'#DB7093',
|
||||||
|
'crimson':'#DC143C',
|
||||||
|
'gainsboro':'#DCDCDC',
|
||||||
|
'plum':'#DDA0DD',
|
||||||
|
'burlywood':'#DEB887',
|
||||||
|
'lightcyan':'#E0FFFF',
|
||||||
|
'lavender':'#E6E6FA',
|
||||||
|
'darksalmon':'#E9967A',
|
||||||
|
'palegoldenrod':'#EEE8AA',
|
||||||
|
'violet':'#EE82EE',
|
||||||
|
'azure':'#F0FFFF',
|
||||||
|
'honeydew':'#F0FFF0',
|
||||||
|
'khaki':'#F0E68C',
|
||||||
|
'lightcoral':'#F08080',
|
||||||
|
'sandybrown':'#F4A460',
|
||||||
|
'beige':'#F5F5DC',
|
||||||
|
'mintcream':'#F5FFFA',
|
||||||
|
'wheat':'#F5DEB3',
|
||||||
|
'whitesmoke':'#F5F5F5',
|
||||||
|
'ghostwhite':'#F8F8FF',
|
||||||
|
'lightgoldenrodyellow':'#FAFAD2',
|
||||||
|
'linen':'#FAF0E6',
|
||||||
|
'salmon':'#FA8072',
|
||||||
|
'oldlace':'#FDF5E6',
|
||||||
|
'warmwhite':'#FDF5E6',
|
||||||
|
'bisque':'#FFE4C4',
|
||||||
|
'blanchedalmond':'#FFEBCD',
|
||||||
|
'coral':'#FF7F50',
|
||||||
|
'cornsilk':'#FFF8DC',
|
||||||
|
'darkorange':'#FF8C00',
|
||||||
|
'deeppink':'#FF1493',
|
||||||
|
'floralwhite':'#FFFAF0',
|
||||||
|
'fuchsia':'#FF00FF',
|
||||||
|
'gold':'#FFD700',
|
||||||
|
'hotpink':'#FF69B4',
|
||||||
|
'ivory':'#FFFFF0',
|
||||||
|
'lavenderblush':'#FFF0F5',
|
||||||
|
'lemonchiffon':'#FFFACD',
|
||||||
|
'lightpink':'#FFB6C1',
|
||||||
|
'lightsalmon':'#FFA07A',
|
||||||
|
'lightyellow':'#FFFFE0',
|
||||||
|
'magenta':'#FF00FF',
|
||||||
|
'mistyrose':'#FFE4E1',
|
||||||
|
'moccasin':'#FFE4B5',
|
||||||
|
'navajowhite':'#FFDEAD',
|
||||||
|
'orange':'#FFA500',
|
||||||
|
'orangered':'#FF4500',
|
||||||
|
'papayawhip':'#FFEFD5',
|
||||||
|
'peachpuff':'#FFDAB9',
|
||||||
|
'pink':'#FFC0CB',
|
||||||
|
'red':'#FF0000',
|
||||||
|
'seashell':'#FFF5EE',
|
||||||
|
'snow':'#FFFAFA',
|
||||||
|
'tomato':'#FF6347',
|
||||||
|
'white':'#FFFFFF',
|
||||||
|
'yellow':'#FFFF00',
|
||||||
|
'amber':'#FFD200'
|
||||||
|
};
|
||||||
|
|
||||||
|
var hexColour = /^#([0-9A-F][0-9A-F][0-9A-F]){1,2}$/i;
|
||||||
|
|
||||||
|
module.exports.getRGB = function(col,rgb) {
|
||||||
|
if (!col) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (/^\d{1,3},\d{1,3},\d{1,3}$/.test(col)) {
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
col = col.toString().toLowerCase();
|
||||||
|
if (col in colours) {
|
||||||
|
col = colours[col];
|
||||||
|
}
|
||||||
|
if (hexColour.test(col)) {
|
||||||
|
if (col.length === 4) {
|
||||||
|
col = "#"+col[1]+col[1]+col[2]+col[2]+col[3]+col[3];
|
||||||
|
}
|
||||||
|
if (rgb === "grb") {
|
||||||
|
g = parseInt(col.slice(1,3),16);
|
||||||
|
r = parseInt(col.slice(3,5),16);
|
||||||
|
b = parseInt(col.slice(5),16);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = parseInt(col.slice(1,3),16);
|
||||||
|
g = parseInt(col.slice(3,5),16);
|
||||||
|
b = parseInt(col.slice(5),16);
|
||||||
|
}
|
||||||
|
return r+","+g+","+b;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.getHex = function(col) {
|
||||||
|
col = col.toString().toLowerCase();
|
||||||
|
if (col in colours) {
|
||||||
|
return colours[col];
|
||||||
|
}
|
||||||
|
else { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.HexRGB = function(hex) {
|
||||||
|
try {
|
||||||
|
r = parseInt(hex.slice(1,3),16);
|
||||||
|
g = parseInt(hex.slice(3,5),16);
|
||||||
|
b = parseInt(hex.slice(5),16);
|
||||||
|
return r+","+g+","+b;
|
||||||
|
}
|
||||||
|
catch(e) { return null; }
|
||||||
|
}
|
@ -36,6 +36,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="rpi-sensehat out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="rpi-sensehat in">
|
<script type="text/x-red" data-help-name="rpi-sensehat in">
|
||||||
<p>Raspberry Pi Sense HAT input node.</p>
|
<p>Raspberry Pi Sense HAT input node.</p>
|
||||||
<p>This node sends readings from the various sensors on the Sense HAT,
|
<p>This node sends readings from the various sensors on the Sense HAT,
|
||||||
@ -75,10 +82,53 @@ is an object with the following values:</p>
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-sensehat out">
|
||||||
|
<p>Raspberry Pi Sense HAT output node.</p>
|
||||||
|
<p>This node sends commands to the 8x8 LED display on the Sense HAT.</p>
|
||||||
|
<p>Commands are sent to the node in <code>msg.payload</code>. Multiple commands can
|
||||||
|
be sent in a single message by separating them with newline (\n) characters.<p>
|
||||||
|
|
||||||
|
<p><b>Set the colour of individual pixels</b></p>
|
||||||
|
<p>Format: <code><x>,<y>,<colour></code>
|
||||||
|
<p><code>x</code> and <code>y</code> must either be a value in the range 0-7, or
|
||||||
|
<code>*</code> to indicate the entire row or column.</p>
|
||||||
|
<p><code>colour</code> must be one of:
|
||||||
|
<ul>
|
||||||
|
<li>the well-known <a href="https://en.wikipedia.org/wiki/Web_colors" target="_new">HTML colour names</a>
|
||||||
|
- eg <code>red</code> or <code>aquamarine</code>,</li>
|
||||||
|
<li>the <a href="http://cheerlights.com/cheerlights-api/">CheerLights colour names</a>,</li>
|
||||||
|
<li>a HEX colour value - eg <code>#aa9900</code></li>
|
||||||
|
<li>an RGB triple - <code>190,255,0</code></li>
|
||||||
|
<li>or simply <code>off</code></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p><i>Examples</i></p>
|
||||||
|
<p>To set the entire screen to red:</p>
|
||||||
|
<p><code>*,*,red</code></p>
|
||||||
|
<p>To set the four corners of the display to red, green (#00ff00), yellow and blue (0,0,255):</p>
|
||||||
|
<p><code>0,0,red,0,7,#00ff00,7,7,yellow,7,0,0,0,255</code></p>
|
||||||
|
|
||||||
|
<p><b>Rotate the screen</b></p>
|
||||||
|
<p>Format: <code>R<angle></code></p>
|
||||||
|
<p><code>angle</code> must be 0, 90, 180 or 270.</p>
|
||||||
|
|
||||||
|
<p><b>Flip the screen</b></p>
|
||||||
|
<p>Format: <code>R<axis></code></p>
|
||||||
|
<p><code>axis</code> must be either <code>H</code> or <code>V</code> to flip on
|
||||||
|
the horizontal or vertical axis respectively.</p>
|
||||||
|
|
||||||
|
<p><b>Scroll a message</b></p>
|
||||||
|
<p>If <code>msg.payload</code> is not recognised as any of the above commands,
|
||||||
|
it is treated as a text message to be scrolled across the screen.</p>
|
||||||
|
<p>The following message properties can be used to customise the appearance:</p>
|
||||||
|
<ul>
|
||||||
|
<li><code>msg.colour</code> - the colour of the text, default: <code>white</code></li>
|
||||||
|
<li><code>msg.background</code> - the colour of the background, default: <code>off</code></li>
|
||||||
|
<li><code>msg.speed</code> - the scroll speed. A value in the range 1 (slower) to 5 (faster), default: <code>3</code></li>
|
||||||
|
</ul>
|
||||||
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType('rpi-sensehat in',{
|
RED.nodes.registerType('rpi-sensehat in',{
|
||||||
category: 'Raspberry Pi',
|
category: 'Raspberry Pi',
|
||||||
@ -100,4 +150,23 @@ is an object with the following values:</p>
|
|||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
RED.nodes.registerType('rpi-sensehat out',{
|
||||||
|
category: 'Raspberry Pi',
|
||||||
|
paletteLabel: "Sense HAT",
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" },
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "rpi.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"Sense HAT";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -18,6 +18,7 @@ module.exports = function(RED) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var spawn = require('child_process').spawn;
|
var spawn = require('child_process').spawn;
|
||||||
|
var colours = require('./colours');
|
||||||
|
|
||||||
var hatCommand = __dirname+'/sensehat';
|
var hatCommand = __dirname+'/sensehat';
|
||||||
|
|
||||||
@ -198,10 +199,16 @@ module.exports = function(RED) {
|
|||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
send: function(msg) {
|
||||||
|
if (hat) {
|
||||||
|
hat.stdin.write(msg+'\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
||||||
function SenseHatInNode(n) {
|
function SenseHatInNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.motion = n.motion;
|
this.motion = n.motion;
|
||||||
@ -215,4 +222,115 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("rpi-sensehat in",SenseHatInNode);
|
RED.nodes.registerType("rpi-sensehat in",SenseHatInNode);
|
||||||
|
|
||||||
|
function SenseHatOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
var node = this;
|
||||||
|
HAT.open(this);
|
||||||
|
|
||||||
|
node.on("close", function(done) {
|
||||||
|
HAT.close(this,done);
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("input",function(msg) {
|
||||||
|
var command;
|
||||||
|
var parts;
|
||||||
|
var col;
|
||||||
|
if (typeof msg.payload === 'string') {
|
||||||
|
var lines = msg.payload.split("\n");
|
||||||
|
lines.forEach(function(line) {
|
||||||
|
command = null;
|
||||||
|
col = colours.getRGB(line);
|
||||||
|
if ( /^(([0-7]|\*),([0-7]|\*),(\d{1,3},\d{1,3},\d{1,3}|#[a-f0-9]{3,6}|[a-z]+))(,([0-7]|\*),([0-7]|\*),(\d{1,3},\d{1,3},\d{1,3}|#[a-f0-9]{3,6}|[a-z]+))*$/i.test(line)) {
|
||||||
|
parts = line.split(",");
|
||||||
|
var expanded = [];
|
||||||
|
var i=0;
|
||||||
|
var j=0;
|
||||||
|
while (i<parts.length) {
|
||||||
|
var x = parts[i++];
|
||||||
|
var y = parts[i++];
|
||||||
|
col = parts[i++];
|
||||||
|
if (/#[a-f0-9]{3,6}|[a-z]/i.test(col)) {
|
||||||
|
col = colours.getRGB(col);
|
||||||
|
if (col === null) {
|
||||||
|
// invalid colour, go no further
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
col += ","+parts[i++]+","+parts[i++];
|
||||||
|
}
|
||||||
|
if (x!=='*' && y!=='*') {
|
||||||
|
expanded.push([x,y,col]);
|
||||||
|
} else if (x == '*' && y == '*') {
|
||||||
|
for (j=0;j<8;j++) {
|
||||||
|
for (var k=0;k<8;k++) {
|
||||||
|
expanded.push([j,k,col]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (x == '*') {
|
||||||
|
for (j=0;j<8;j++) {
|
||||||
|
expanded.push([j,y,col]);
|
||||||
|
}
|
||||||
|
} else if (y == '*') {
|
||||||
|
for (j=0;j<8;j++) {
|
||||||
|
expanded.push([x,j,col]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (expanded.length > 0) {
|
||||||
|
var pixels = {};
|
||||||
|
var rules = [];
|
||||||
|
for (i=expanded.length-1;i>=0;i--) {
|
||||||
|
var rule = expanded[i];
|
||||||
|
if (!pixels[rule[0]+","+rule[1]]) {
|
||||||
|
rules.unshift(rule.join(","));
|
||||||
|
pixels[rule[0]+","+rule[1]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rules.length > 0) {
|
||||||
|
command = "P"+rules.join(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!command) {
|
||||||
|
if (/^R(0|90|180|270)$/i.test(line)) {
|
||||||
|
command = line.toUpperCase();
|
||||||
|
} else if (/^F(H|V)$/i.test(line)) {
|
||||||
|
command = line.toUpperCase();
|
||||||
|
} else {
|
||||||
|
var textCol = colours.getRGB(msg.color);
|
||||||
|
var backCol = colours.getRGB(msg.background);
|
||||||
|
var speed = null;
|
||||||
|
if (!isNaN(msg.speed)) {
|
||||||
|
speed = msg.speed;
|
||||||
|
}
|
||||||
|
command = "T";
|
||||||
|
if (textCol) {
|
||||||
|
command += textCol;
|
||||||
|
if (backCol) {
|
||||||
|
command += ","+backCol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (speed) {
|
||||||
|
var s = parseInt(speed);
|
||||||
|
if (s >= 1 && s <= 5) {
|
||||||
|
s = 0.1 + (3-s)*0.03;
|
||||||
|
}
|
||||||
|
command = command + ((command.length === 1)?"":",") + s;
|
||||||
|
}
|
||||||
|
command += ":" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (command) {
|
||||||
|
//console.log(command);
|
||||||
|
HAT.send(command);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("rpi-sensehat out",SenseHatOutNode);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
# C[R,G,B] - clear to colour (or off if no RGB provided)
|
# C[R,G,B] - clear to colour (or off if no RGB provided)
|
||||||
# R[rot] - rotate by rot (0,90,180,270)
|
# R[rot] - rotate by rot (0,90,180,270)
|
||||||
# P[x,y,R,G,B]+ - set individual pixel(s) to a colour
|
# P[x,y,R,G,B]+ - set individual pixel(s) to a colour
|
||||||
# T[R,G,B:]Message - scroll a message (nb: if message contains ':' it must be prefixed with ':')
|
# T[R,G,B[,R,G,B][,S]:]Message - scroll a message (nb: if message contains ':' it must be prefixed with ':')
|
||||||
# F[H|V] - flip horizontal|vertical
|
# F[H|V] - flip horizontal|vertical
|
||||||
# X[0|1] - high frequency reporting (accel/gyro/orientation/compass) off|on
|
# X[0|1] - high frequency reporting (accel/gyro/orientation/compass) off|on
|
||||||
# Y[0|1] - low frequency reporting (temperature/humidity/pressure) off|on
|
# Y[0|1] - low frequency reporting (temperature/humidity/pressure) off|on
|
||||||
@ -32,8 +32,11 @@ import sys
|
|||||||
import glob
|
import glob
|
||||||
import time
|
import time
|
||||||
import errno
|
import errno
|
||||||
|
import ctypes
|
||||||
import select
|
import select
|
||||||
import struct
|
import struct
|
||||||
|
import inspect
|
||||||
|
import threading
|
||||||
|
|
||||||
from sense_hat import SenseHat
|
from sense_hat import SenseHat
|
||||||
|
|
||||||
@ -69,40 +72,48 @@ lf_interval = 1
|
|||||||
hf_enabled = False
|
hf_enabled = False
|
||||||
lf_enabled = False
|
lf_enabled = False
|
||||||
|
|
||||||
|
scroll = None
|
||||||
|
|
||||||
|
class ScrollThread(threading.Thread):
|
||||||
|
def __init__(self,fcol,bcol,speed,message):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.fcol = fcol
|
||||||
|
self.bcol = bcol
|
||||||
|
self.message = message
|
||||||
|
self.speed = speed
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
global SH
|
||||||
|
old_rotation = SH.rotation
|
||||||
|
|
||||||
|
try:
|
||||||
|
SH.show_message(self.message,text_colour=self.fcol,back_colour=self.bcol,scroll_speed=self.speed)
|
||||||
|
except:
|
||||||
|
SH.set_rotation(old_rotation,False)
|
||||||
|
SH.clear(self.bcol);
|
||||||
|
pass
|
||||||
|
|
||||||
|
def interrupt(self):
|
||||||
|
if not self.isAlive():
|
||||||
|
raise threading.ThreadError()
|
||||||
|
for thread_id, thread_object in threading._active.items():
|
||||||
|
if thread_object == self:
|
||||||
|
r = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,ctypes.py_object(StandardError))
|
||||||
|
if r == 1:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if r > 1:
|
||||||
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
|
||||||
|
raise SystemError()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_command(data):
|
def process_command(data):
|
||||||
global hf_enabled, lf_enabled
|
global hf_enabled, lf_enabled,scroll
|
||||||
if data[0] == "R":
|
|
||||||
SH.set_rotation(float(data[1:]))
|
if data[0] == "X":
|
||||||
elif data[0] == "C":
|
|
||||||
data = data[1:].strip()
|
|
||||||
if len(data) > 0:
|
|
||||||
s = data.split(",")
|
|
||||||
col = (int(s[0]),int(s[1]),int(s[2]))
|
|
||||||
else:
|
|
||||||
col = (0,0,0)
|
|
||||||
SH.clear(col)
|
|
||||||
elif data[0] == "P":
|
|
||||||
data = data[1:].strip()
|
|
||||||
s = data.split(',')
|
|
||||||
for p in range(0,len(s),5):
|
|
||||||
SH.set_pixel(int(s[p]),int(s[p+1]),int(s[p+2]),int(s[p+3]),int(s[p+4]))
|
|
||||||
elif data[0] == "T":
|
|
||||||
data = data[1:].strip()
|
|
||||||
col = (255,255,255)
|
|
||||||
s = data.split(':',1)
|
|
||||||
if len(s) == 2:
|
|
||||||
data = s[1]
|
|
||||||
if len(s[0]) > 0:
|
|
||||||
c = s[0].split(",")
|
|
||||||
col = (int(c[0]),int(c[1]),int(c[2]))
|
|
||||||
SH.show_message(data,text_colour=col)
|
|
||||||
elif data[0] == "F":
|
|
||||||
if data[1] == "H":
|
|
||||||
SH.flip_h()
|
|
||||||
elif data[1] == "V":
|
|
||||||
SH.flip_v()
|
|
||||||
elif data[0] == "X":
|
|
||||||
if data[1] == '0':
|
if data[1] == '0':
|
||||||
hf_enabled = False
|
hf_enabled = False
|
||||||
else:
|
else:
|
||||||
@ -112,6 +123,61 @@ def process_command(data):
|
|||||||
lf_enabled = False
|
lf_enabled = False
|
||||||
else:
|
else:
|
||||||
lf_enabled = True
|
lf_enabled = True
|
||||||
|
else:
|
||||||
|
if threading.activeCount() == 2:
|
||||||
|
scroll.interrupt()
|
||||||
|
while scroll.isAlive():
|
||||||
|
time.sleep(0.01)
|
||||||
|
try:
|
||||||
|
scroll.interrupt()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if data[0] == "R":
|
||||||
|
SH.set_rotation(float(data[1:]))
|
||||||
|
elif data[0] == "C":
|
||||||
|
data = data[1:].strip()
|
||||||
|
if len(data) > 0:
|
||||||
|
s = data.split(",")
|
||||||
|
col = (int(s[0]),int(s[1]),int(s[2]))
|
||||||
|
else:
|
||||||
|
col = (0,0,0)
|
||||||
|
SH.clear(col)
|
||||||
|
elif data[0] == "P":
|
||||||
|
data = data[1:].strip()
|
||||||
|
s = data.split(',')
|
||||||
|
for p in range(0,len(s),5):
|
||||||
|
SH.set_pixel(int(s[p]),int(s[p+1]),int(s[p+2]),int(s[p+3]),int(s[p+4]))
|
||||||
|
elif data[0] == "T":
|
||||||
|
data = data[1:].strip()
|
||||||
|
tcol = (255,255,255)
|
||||||
|
bcol = (0,0,0)
|
||||||
|
speed = 0.1
|
||||||
|
s = data.split(':',1)
|
||||||
|
if len(s) == 2:
|
||||||
|
data = s[1]
|
||||||
|
if len(s[0]) > 0:
|
||||||
|
c = s[0].split(",")
|
||||||
|
if len(c) == 1:
|
||||||
|
speed = float(c[0])
|
||||||
|
elif len(c) == 3:
|
||||||
|
tcol = (int(c[0]),int(c[1]),int(c[2]))
|
||||||
|
if len(c) == 4:
|
||||||
|
tcol = (int(c[0]),int(c[1]),int(c[2]))
|
||||||
|
speed = float(c[3])
|
||||||
|
elif len(c) == 6:
|
||||||
|
tcol = (int(c[0]),int(c[1]),int(c[2]))
|
||||||
|
bcol = (int(c[3]),int(c[4]),int(c[5]))
|
||||||
|
elif len(c) == 7:
|
||||||
|
tcol = (int(c[0]),int(c[1]),int(c[2]))
|
||||||
|
bcol = (int(c[3]),int(c[4]),int(c[5]))
|
||||||
|
speed = float(c[6])
|
||||||
|
scroll = ScrollThread(tcol,bcol,speed,data);
|
||||||
|
scroll.start()
|
||||||
|
elif data[0] == "F":
|
||||||
|
if data[1] == "H":
|
||||||
|
SH.flip_h()
|
||||||
|
elif data[1] == "V":
|
||||||
|
SH.flip_v()
|
||||||
|
|
||||||
def idle_work():
|
def idle_work():
|
||||||
global last_hf_time, last_lf_time
|
global last_hf_time, last_lf_time
|
||||||
|
Loading…
x
Reference in New Issue
Block a user