mirror of
				https://github.com/node-red/node-red-nodes.git
				synced 2025-03-01 10:37:43 +00:00 
			
		
		
		
	Moved all nodes into one common .js file & .html file pair
This commit is contained in:
		@@ -1,184 +0,0 @@
 | 
			
		||||
<!--
 | 
			
		||||
  Copyright 2014 Maxwell R Hadley
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<!-- Edit dialog for analogue-in -->
 | 
			
		||||
<script type="text/x-red" data-template-name="analog-in">
 | 
			
		||||
   <div class="form-row">
 | 
			
		||||
       <label for="node-input-pin"><i class="icon-asterisk"></i>Input pin</label>
 | 
			
		||||
       <select type="text" id="node-input-pin" style="width: 150px;">
 | 
			
		||||
           <option value="">select pin</option>
 | 
			
		||||
           <option value="P9_39">AIN0 (P9 pin 39)</option>
 | 
			
		||||
           <option value="P9_40">AIN1 (P9 pin 40)</option>
 | 
			
		||||
           <option value="P9_37">AIN2 (P9 pin 37)</option>
 | 
			
		||||
           <option value="P9_38">AIN3 (P9 pin 38)</option>
 | 
			
		||||
           <option value="P9_33">AIN4 (P9 pin 33)</option>
 | 
			
		||||
           <option value="P9_36">AIN5 (P9 pin 36)</option>
 | 
			
		||||
           <option value="P9_35">AIN6 (P9 pin 35)</option>
 | 
			
		||||
       </select>
 | 
			
		||||
   </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
 | 
			
		||||
        <input type="text" id="node-input-topic" placeholder="Topic">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
    Input Scaling
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <div id="node-input-breakpoint-container-div" style="border-radius: 5px; height: 132px; padding: 5px; border: 1px solid #ccc; overflow-y:scroll;">
 | 
			
		||||
            <ol id="node-input-breakpoint-container" style=" list-style-type:none; margin: 0;">
 | 
			
		||||
            </ol>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <a href="#" class="btn btn-mini" id="node-input-add-breakpoint" style="margin-top: 4px;"><i class="icon-plus"></i> Add Breakpoint</a>
 | 
			
		||||
        <span style="float:right; margin-top:4px">
 | 
			
		||||
        	<input type="checkbox" id="node-input-averaging" style="display:inline-block; width:auto; vertical-align:top;"> Averaging 
 | 
			
		||||
    	</span>	
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="icon-tag"></i> Name</label>
 | 
			
		||||
        <input type="text" id="node-input-name" placeholder="Name">
 | 
			
		||||
    </div>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Help text for analogue-in -->
 | 
			
		||||
<script type="text/x-red" data-help-name="analog-in">
 | 
			
		||||
<p>
 | 
			
		||||
Analogue input for the Beaglebone Black. Reads an analogue pin when triggered by
 | 
			
		||||
a message.
 | 
			
		||||
</p>
 | 
			
		||||
<p>The output message topic is the node topic: the output message value is the
 | 
			
		||||
scaled analogue input or NaN if a read error occurs.
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
Simple linear scaling is defined by setting the output values required for input
 | 
			
		||||
values of 0 and 1. You can apply more complicated scaling, e.g. for sensor linearisation,
 | 
			
		||||
by defining breakpoints at intermediate input values, with the desired output for
 | 
			
		||||
each. Values between breakpoints are linearly interpolated.
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
To reduce the effect of noise, enable averaging. This will read the input pin
 | 
			
		||||
voltage ten times in rapid succession for each input message and output the mean value.
 | 
			
		||||
</p>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Register analogue-in node -->
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    RED.nodes.registerType('analog-in', {
 | 
			
		||||
        category: 'advanced-input', // the palette category
 | 
			
		||||
        color:"#c6dbef",
 | 
			
		||||
        defaults: {                 // defines the editable properties of the node
 | 
			
		||||
            name: { value:"" },     //  along with default values.
 | 
			
		||||
            topic: { value:"", required:true },
 | 
			
		||||
            pin: { value:"", required:true },
 | 
			
		||||
            breakpoints: { value:[{input:0.0, output:0.0, mutable:false},  {input:1.0, output:1.0, mutable:false}] },
 | 
			
		||||
            averaging: { value:false, required:true }
 | 
			
		||||
        },
 | 
			
		||||
        inputs:1,                   // set the number of inputs - only 0 or 1
 | 
			
		||||
        outputs:1,                  // set the number of outputs - 0 to n
 | 
			
		||||
        icon: "arrow-in.png",       // set the icon (held in public/icons)
 | 
			
		||||
        label: function() {         // sets the default label contents
 | 
			
		||||
                return this.name || "analog-in: " + this.pin;
 | 
			
		||||
            },
 | 
			
		||||
        labelStyle: function() {    // sets the class to apply to the label
 | 
			
		||||
                return this.name ? "node_label_italic" : "";
 | 
			
		||||
            },
 | 
			
		||||
        oneditprepare: function () {
 | 
			
		||||
                function generateBreakpoint(breakpoint, insert) {
 | 
			
		||||
                    var container = $('<li/>', {style:"margin:0; padding:4px; padding-left 10px;"});
 | 
			
		||||
                    var row = $('<div/>').appendTo(container);
 | 
			
		||||
                    var breakpointField = $('<span/>').appendTo(row);
 | 
			
		||||
					var inputValueField = $('<input/>',
 | 
			
		||||
						{disabled:"", class:"node-input-breakpoint-input-value", type:"text", style:"margin-left:5px; margin-right:2px; width:36%;"}).appendTo(breakpointField);
 | 
			
		||||
                    if (breakpoint.mutable) {
 | 
			
		||||
                    	inputValueField.removeAttr("disabled");
 | 
			
		||||
                    }
 | 
			
		||||
                    breakpointField.append(" => ");
 | 
			
		||||
                    var outputValueField = $('<input/>',
 | 
			
		||||
                        {class:"node-input-breakpoint-output-value", type:"text", style:"margin-left:0px; width:36%;"}).appendTo(breakpointField);
 | 
			
		||||
                    var finalSpan = $('<span/>', {style:"float:right; margin-top:3px; margin-right:10px;"}).appendTo(row);
 | 
			
		||||
                    var mutableFlag = $('<span/>', {class:"node-input-breakpoint-mutable", style:"display:hide;"}).appendTo(row);
 | 
			
		||||
                    if (breakpoint.mutable) {
 | 
			
		||||
                        mutableFlag.attr("mutable", "true");
 | 
			
		||||
                        var deleteButton = $('<a/>', {href:"#", class:"btn btn-mini", style:"margin-left: 5px;"}).appendTo(finalSpan);
 | 
			
		||||
                        $('<i/>', {class:"icon-remove"}).appendTo(deleteButton);
 | 
			
		||||
 | 
			
		||||
                        deleteButton.click(function() {
 | 
			
		||||
                                container.css({"background":"#fee"});
 | 
			
		||||
                                container.fadeOut(300, function() {
 | 
			
		||||
                                        $(this).remove();
 | 
			
		||||
                                    });
 | 
			
		||||
                            });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        mutableFlag.attr("mutable", "false");
 | 
			
		||||
                    }                   
 | 
			
		||||
                    if (insert === true) {
 | 
			
		||||
                    	var last = $("#node-input-breakpoint-container").children().last();
 | 
			
		||||
                    	var prev = last.prev();
 | 
			
		||||
                    	inputValueField.val((Number(last.find(".node-input-breakpoint-input-value").val()) + 
 | 
			
		||||
                    							Number(prev.find(".node-input-breakpoint-input-value").val()))/2);
 | 
			
		||||
                    	outputValueField.val((Number(last.find(".node-input-breakpoint-output-value").val()) +
 | 
			
		||||
                    							Number(prev.find(".node-input-breakpoint-output-value").val()))/2);
 | 
			
		||||
                    	last.before(container);
 | 
			
		||||
                    } else {
 | 
			
		||||
						inputValueField.val(breakpoint.input);
 | 
			
		||||
						outputValueField.val(breakpoint.output);
 | 
			
		||||
                    	$("#node-input-breakpoint-container").append(container);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                $("#node-input-add-breakpoint").click(function () {
 | 
			
		||||
                        generateBreakpoint({input:0, output:0, mutable:true}, true);
 | 
			
		||||
                        $("#node-input-breakpoint-container-div").scrollTop($("#node-input-breakpoint-container-div").get(0).scrollHeight);
 | 
			
		||||
                    });
 | 
			
		||||
                    
 | 
			
		||||
                for (var i = 0; i < this.breakpoints.length; i++) {
 | 
			
		||||
                    var breakpoint = this.breakpoints[i];
 | 
			
		||||
                    generateBreakpoint(breakpoint, false);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // Handle resizing the Input Scaling div when the dialog is resized - this isn't quite right!
 | 
			
		||||
                function switchDialogResize(ev, ui) {
 | 
			
		||||
                    $("#node-input-breakpoint-container-div").css("height", (ui.size.height - 299) + "px");
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                $("#dialog").on("dialogresize", switchDialogResize);
 | 
			
		||||
                $("#dialog").one("dialogopen", function (ev) {
 | 
			
		||||
                        var size = $("#dialog").dialog('option', 'sizeCache-switch');
 | 
			
		||||
                        if (size) {
 | 
			
		||||
                            switchDialogResize(null, { size:size });
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                $("#dialog").one("dialogclose", function(ev, ui) {
 | 
			
		||||
                        $("#dialog").off("dialogresize", switchDialogResize);
 | 
			
		||||
                    });
 | 
			
		||||
            },
 | 
			
		||||
        oneditsave: function() {
 | 
			
		||||
                var breakpoints = $("#node-input-breakpoint-container").children();
 | 
			
		||||
                var node = this;
 | 
			
		||||
                node.breakpoints = [];
 | 
			
		||||
                breakpoints.each(function (i) {
 | 
			
		||||
                        var breakpoint = $(this);
 | 
			
		||||
                        var r = {};
 | 
			
		||||
                        r.input = Number(breakpoint.find(".node-input-breakpoint-input-value").val());
 | 
			
		||||
                        r.output = Number(breakpoint.find(".node-input-breakpoint-output-value").val());
 | 
			
		||||
                        r.mutable = breakpoint.find(".node-input-breakpoint-mutable").attr("mutable") == "true";
 | 
			
		||||
                        node.breakpoints.push(r);
 | 
			
		||||
                    });
 | 
			
		||||
                node.breakpoints = node.breakpoints.sort(function (a, b) { return a.input - b.input; });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,84 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright 2014 Maxwell R Hadley
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
// Require main module
 | 
			
		||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
 | 
			
		||||
 | 
			
		||||
// Require bonescript
 | 
			
		||||
try {
 | 
			
		||||
    var bonescript = require("bonescript");
 | 
			
		||||
} catch (err) {
 | 
			
		||||
    require("util").log("[144-analog-in] Error: cannot find module 'bonescript'");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Node constructor for analogue-in
 | 
			
		||||
function AnalogInputNode(n) {
 | 
			
		||||
    // Create a RED node
 | 
			
		||||
    RED.nodes.createNode(this, n);
 | 
			
		||||
 | 
			
		||||
    // Store local copies of the node configuration (as defined in the .html)
 | 
			
		||||
    this.topic = n.topic;
 | 
			
		||||
    this.pin = n.pin;
 | 
			
		||||
    this.breakpoints = n.breakpoints;
 | 
			
		||||
    this.averaging = n.averaging;
 | 
			
		||||
    if (this.averaging) {
 | 
			
		||||
    	this.averages = 10;
 | 
			
		||||
    } else {
 | 
			
		||||
    	this.averages = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Define 'node' to allow us to access 'this' from within callbacks
 | 
			
		||||
    var node = this;
 | 
			
		||||
 | 
			
		||||
	// Variables used for input averaging
 | 
			
		||||
	var sum;	// accumulates the input readings to be averaged
 | 
			
		||||
	var count;	// keep track of the number of measurements made
 | 
			
		||||
	
 | 
			
		||||
    // The callback function for analogRead. Accumulates the required number of
 | 
			
		||||
    // measurements, then divides the total number, applies output scaling and
 | 
			
		||||
    // sends the result
 | 
			
		||||
    var analogReadCallback = function (x) {
 | 
			
		||||
    		sum = sum + x.value;
 | 
			
		||||
    		count = count - 1;
 | 
			
		||||
    		if (count > 0) {
 | 
			
		||||
    			bonescript.analogRead(node.pin, analogReadCallback);
 | 
			
		||||
    		} else {
 | 
			
		||||
				var msg = {};
 | 
			
		||||
				msg.topic = node.topic;
 | 
			
		||||
				sum = sum/node.averages;
 | 
			
		||||
				// i is the index of the first breakpoint where the 'input' value is strictly
 | 
			
		||||
				// greater than the measurement (note: a measurement can never be == 1)
 | 
			
		||||
				var i = node.breakpoints.map(function (breakpoint) { return sum >= breakpoint.input; }).indexOf(false);
 | 
			
		||||
				msg.payload = node.breakpoints[i-1].output + (node.breakpoints[i].output - node.breakpoints[i-1].output) *
 | 
			
		||||
								(sum - node.breakpoints[i-1].input)/(node.breakpoints[i].input - node.breakpoints[i-1].input);
 | 
			
		||||
				node.send(msg);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    // If we have a valid pin, set the input event handler to Bonescript's analogRead
 | 
			
		||||
    if (["P9_39", "P9_40", "P9_37", "P9_38", "P9_33", "P9_36", "P9_35"].indexOf(node.pin) >= 0) {
 | 
			
		||||
        node.on("input", function (msg) {
 | 
			
		||||
        		sum = 0;
 | 
			
		||||
        		count = node.averages;
 | 
			
		||||
        		bonescript.analogRead(node.pin, analogReadCallback);
 | 
			
		||||
        	});
 | 
			
		||||
    } else {
 | 
			
		||||
        node.error("Unconfigured input pin");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Register the node by name. This must be called before overriding any of the Node functions.
 | 
			
		||||
RED.nodes.registerType("analog-in", AnalogInputNode);
 | 
			
		||||
@@ -14,6 +14,175 @@
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<!-- Edit dialog for analogue-in -->
 | 
			
		||||
<script type="text/x-red" data-template-name="analog-in">
 | 
			
		||||
   <div class="form-row">
 | 
			
		||||
       <label for="node-input-pin"><i class="icon-asterisk"></i>Input pin</label>
 | 
			
		||||
       <select type="text" id="node-input-pin" style="width: 150px;">
 | 
			
		||||
           <option value="">select pin</option>
 | 
			
		||||
           <option value="P9_39">AIN0 (P9 pin 39)</option>
 | 
			
		||||
           <option value="P9_40">AIN1 (P9 pin 40)</option>
 | 
			
		||||
           <option value="P9_37">AIN2 (P9 pin 37)</option>
 | 
			
		||||
           <option value="P9_38">AIN3 (P9 pin 38)</option>
 | 
			
		||||
           <option value="P9_33">AIN4 (P9 pin 33)</option>
 | 
			
		||||
           <option value="P9_36">AIN5 (P9 pin 36)</option>
 | 
			
		||||
           <option value="P9_35">AIN6 (P9 pin 35)</option>
 | 
			
		||||
       </select>
 | 
			
		||||
   </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
 | 
			
		||||
        <input type="text" id="node-input-topic" placeholder="Topic">
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
    Input Scaling
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <div id="node-input-breakpoint-container-div" style="border-radius: 5px; height: 132px; padding: 5px; border: 1px solid #ccc; overflow-y:scroll;">
 | 
			
		||||
            <ol id="node-input-breakpoint-container" style=" list-style-type:none; margin: 0;">
 | 
			
		||||
            </ol>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <a href="#" class="btn btn-mini" id="node-input-add-breakpoint" style="margin-top: 4px;"><i class="icon-plus"></i> Add Breakpoint</a>
 | 
			
		||||
        <span style="float:right; margin-top:4px">
 | 
			
		||||
        	<input type="checkbox" id="node-input-averaging" style="display:inline-block; width:auto; vertical-align:top;"> Averaging 
 | 
			
		||||
    	</span>	
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="form-row">
 | 
			
		||||
        <label for="node-input-name"><i class="icon-tag"></i> Name</label>
 | 
			
		||||
        <input type="text" id="node-input-name" placeholder="Name">
 | 
			
		||||
    </div>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Help text for analogue-in -->
 | 
			
		||||
<script type="text/x-red" data-help-name="analog-in">
 | 
			
		||||
<p>
 | 
			
		||||
Analogue input for the Beaglebone Black. Reads an analogue pin when triggered by
 | 
			
		||||
a message.
 | 
			
		||||
</p>
 | 
			
		||||
<p>The output message topic is the node topic: the output message value is the
 | 
			
		||||
scaled analogue input or NaN if a read error occurs.
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
Simple linear scaling is defined by setting the output values required for input
 | 
			
		||||
values of 0 and 1. You can apply more complicated scaling, e.g. for sensor linearisation,
 | 
			
		||||
by defining breakpoints at intermediate input values, with the desired output for
 | 
			
		||||
each. Values between breakpoints are linearly interpolated.
 | 
			
		||||
</p>
 | 
			
		||||
<p>
 | 
			
		||||
To reduce the effect of noise, enable averaging. This will read the input pin
 | 
			
		||||
voltage ten times in rapid succession for each input message and output the mean value.
 | 
			
		||||
</p>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Register analogue-in node -->
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    RED.nodes.registerType('analog-in', {
 | 
			
		||||
        category: 'advanced-input', // the palette category
 | 
			
		||||
        color:"#c6dbef",
 | 
			
		||||
        defaults: {                 // defines the editable properties of the node
 | 
			
		||||
            name: { value:"" },     //  along with default values.
 | 
			
		||||
            topic: { value:"", required:true },
 | 
			
		||||
            pin: { value:"", required:true },
 | 
			
		||||
            breakpoints: { value:[{input:0.0, output:0.0, mutable:false},  {input:1.0, output:1.0, mutable:false}] },
 | 
			
		||||
            averaging: { value:false, required:true }
 | 
			
		||||
        },
 | 
			
		||||
        inputs:1,                   // set the number of inputs - only 0 or 1
 | 
			
		||||
        outputs:1,                  // set the number of outputs - 0 to n
 | 
			
		||||
        icon: "arrow-in.png",       // set the icon (held in public/icons)
 | 
			
		||||
        label: function() {         // sets the default label contents
 | 
			
		||||
                return this.name || "analog-in: " + this.pin;
 | 
			
		||||
            },
 | 
			
		||||
        labelStyle: function() {    // sets the class to apply to the label
 | 
			
		||||
                return this.name ? "node_label_italic" : "";
 | 
			
		||||
            },
 | 
			
		||||
        oneditprepare: function () {
 | 
			
		||||
                function generateBreakpoint(breakpoint, insert) {
 | 
			
		||||
                    var container = $('<li/>', {style:"margin:0; padding:4px; padding-left 10px;"});
 | 
			
		||||
                    var row = $('<div/>').appendTo(container);
 | 
			
		||||
                    var breakpointField = $('<span/>').appendTo(row);
 | 
			
		||||
					var inputValueField = $('<input/>',
 | 
			
		||||
						{disabled:"", class:"node-input-breakpoint-input-value", type:"text", style:"margin-left:5px; margin-right:2px; width:36%;"}).appendTo(breakpointField);
 | 
			
		||||
                    if (breakpoint.mutable) {
 | 
			
		||||
                    	inputValueField.removeAttr("disabled");
 | 
			
		||||
                    }
 | 
			
		||||
                    breakpointField.append(" => ");
 | 
			
		||||
                    var outputValueField = $('<input/>',
 | 
			
		||||
                        {class:"node-input-breakpoint-output-value", type:"text", style:"margin-left:0px; width:36%;"}).appendTo(breakpointField);
 | 
			
		||||
                    var finalSpan = $('<span/>', {style:"float:right; margin-top:3px; margin-right:10px;"}).appendTo(row);
 | 
			
		||||
                    var mutableFlag = $('<span/>', {class:"node-input-breakpoint-mutable", style:"display:hide;"}).appendTo(row);
 | 
			
		||||
                    if (breakpoint.mutable) {
 | 
			
		||||
                        mutableFlag.attr("mutable", "true");
 | 
			
		||||
                        var deleteButton = $('<a/>', {href:"#", class:"btn btn-mini", style:"margin-left: 5px;"}).appendTo(finalSpan);
 | 
			
		||||
                        $('<i/>', {class:"icon-remove"}).appendTo(deleteButton);
 | 
			
		||||
 | 
			
		||||
                        deleteButton.click(function() {
 | 
			
		||||
                                container.css({"background":"#fee"});
 | 
			
		||||
                                container.fadeOut(300, function() {
 | 
			
		||||
                                        $(this).remove();
 | 
			
		||||
                                    });
 | 
			
		||||
                            });
 | 
			
		||||
                    } else {
 | 
			
		||||
                        mutableFlag.attr("mutable", "false");
 | 
			
		||||
                    }                   
 | 
			
		||||
                    if (insert === true) {
 | 
			
		||||
                    	var last = $("#node-input-breakpoint-container").children().last();
 | 
			
		||||
                    	var prev = last.prev();
 | 
			
		||||
                    	inputValueField.val((Number(last.find(".node-input-breakpoint-input-value").val()) + 
 | 
			
		||||
                    							Number(prev.find(".node-input-breakpoint-input-value").val()))/2);
 | 
			
		||||
                    	outputValueField.val((Number(last.find(".node-input-breakpoint-output-value").val()) +
 | 
			
		||||
                    							Number(prev.find(".node-input-breakpoint-output-value").val()))/2);
 | 
			
		||||
                    	last.before(container);
 | 
			
		||||
                    } else {
 | 
			
		||||
						inputValueField.val(breakpoint.input);
 | 
			
		||||
						outputValueField.val(breakpoint.output);
 | 
			
		||||
                    	$("#node-input-breakpoint-container").append(container);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                $("#node-input-add-breakpoint").click(function () {
 | 
			
		||||
                        generateBreakpoint({input:0, output:0, mutable:true}, true);
 | 
			
		||||
                        $("#node-input-breakpoint-container-div").scrollTop($("#node-input-breakpoint-container-div").get(0).scrollHeight);
 | 
			
		||||
                    });
 | 
			
		||||
                    
 | 
			
		||||
                for (var i = 0; i < this.breakpoints.length; i++) {
 | 
			
		||||
                    var breakpoint = this.breakpoints[i];
 | 
			
		||||
                    generateBreakpoint(breakpoint, false);
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
                // Handle resizing the Input Scaling div when the dialog is resized - this isn't quite right!
 | 
			
		||||
                function switchDialogResize(ev, ui) {
 | 
			
		||||
                    $("#node-input-breakpoint-container-div").css("height", (ui.size.height - 299) + "px");
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                $("#dialog").on("dialogresize", switchDialogResize);
 | 
			
		||||
                $("#dialog").one("dialogopen", function (ev) {
 | 
			
		||||
                        var size = $("#dialog").dialog('option', 'sizeCache-switch');
 | 
			
		||||
                        if (size) {
 | 
			
		||||
                            switchDialogResize(null, { size:size });
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
                $("#dialog").one("dialogclose", function(ev, ui) {
 | 
			
		||||
                        $("#dialog").off("dialogresize", switchDialogResize);
 | 
			
		||||
                    });
 | 
			
		||||
            },
 | 
			
		||||
        oneditsave: function() {
 | 
			
		||||
                var breakpoints = $("#node-input-breakpoint-container").children();
 | 
			
		||||
                var node = this;
 | 
			
		||||
                node.breakpoints = [];
 | 
			
		||||
                breakpoints.each(function (i) {
 | 
			
		||||
                        var breakpoint = $(this);
 | 
			
		||||
                        var r = {};
 | 
			
		||||
                        r.input = Number(breakpoint.find(".node-input-breakpoint-input-value").val());
 | 
			
		||||
                        r.output = Number(breakpoint.find(".node-input-breakpoint-output-value").val());
 | 
			
		||||
                        r.mutable = breakpoint.find(".node-input-breakpoint-mutable").attr("mutable") == "true";
 | 
			
		||||
                        node.breakpoints.push(r);
 | 
			
		||||
                    });
 | 
			
		||||
                node.breakpoints = node.breakpoints.sort(function (a, b) { return a.input - b.input; });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Edit dialog for discrete-in -->
 | 
			
		||||
<script type="text/x-red" data-template-name="discrete-in">
 | 
			
		||||
   <div class="form-row">
 | 
			
		||||
@@ -107,7 +276,7 @@ press. When using buttons or switches, enable debouncing to improve reliability.
 | 
			
		||||
</p>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Register discrete-in -->
 | 
			
		||||
<!-- Register discrete-in node -->
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    RED.nodes.registerType('discrete-in', {
 | 
			
		||||
        category: 'advanced-input', // the palette category
 | 
			
		||||
@@ -218,7 +387,7 @@ any other input message will reset it to zero.
 | 
			
		||||
</p>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Register pulse-in -->
 | 
			
		||||
<!-- Register pulse-in node -->
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    RED.nodes.registerType('pulse-in', {
 | 
			
		||||
        category: 'advanced-input', // the palette category
 | 
			
		||||
@@ -329,7 +498,7 @@ the Inverting property is not applied to this value.
 | 
			
		||||
</p>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Register discrete-out -->
 | 
			
		||||
<!-- Register discrete-out node -->
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    RED.nodes.registerType('discrete-out', {
 | 
			
		||||
        category: 'advanced-input', // the palette category
 | 
			
		||||
@@ -441,7 +610,7 @@ the pin changes state: its payload is the new state (0 or 1).
 | 
			
		||||
</p>
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<!-- Register pulse-out -->
 | 
			
		||||
<!-- Register pulse-out node -->
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    RED.nodes.registerType('pulse-out', {
 | 
			
		||||
        category: 'advanced-input', // the palette category
 | 
			
		||||
@@ -24,6 +24,62 @@ try {
 | 
			
		||||
    require("util").log("[145-digital-in] Error: cannot find module 'bonescript'");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Node constructor for analogue-in
 | 
			
		||||
function AnalogInputNode(n) {
 | 
			
		||||
    // Create a RED node
 | 
			
		||||
    RED.nodes.createNode(this, n);
 | 
			
		||||
 | 
			
		||||
    // Store local copies of the node configuration (as defined in the .html)
 | 
			
		||||
    this.topic = n.topic;
 | 
			
		||||
    this.pin = n.pin;
 | 
			
		||||
    this.breakpoints = n.breakpoints;
 | 
			
		||||
    this.averaging = n.averaging;
 | 
			
		||||
    if (this.averaging) {
 | 
			
		||||
    	this.averages = 10;
 | 
			
		||||
    } else {
 | 
			
		||||
    	this.averages = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Define 'node' to allow us to access 'this' from within callbacks
 | 
			
		||||
    var node = this;
 | 
			
		||||
 | 
			
		||||
	// Variables used for input averaging
 | 
			
		||||
	var sum;	// accumulates the input readings to be averaged
 | 
			
		||||
	var count;	// keep track of the number of measurements made
 | 
			
		||||
	
 | 
			
		||||
    // The callback function for analogRead. Accumulates the required number of
 | 
			
		||||
    // measurements, then divides the total number, applies output scaling and
 | 
			
		||||
    // sends the result
 | 
			
		||||
    var analogReadCallback = function (x) {
 | 
			
		||||
    		sum = sum + x.value;
 | 
			
		||||
    		count = count - 1;
 | 
			
		||||
    		if (count > 0) {
 | 
			
		||||
    			bonescript.analogRead(node.pin, analogReadCallback);
 | 
			
		||||
    		} else {
 | 
			
		||||
				var msg = {};
 | 
			
		||||
				msg.topic = node.topic;
 | 
			
		||||
				sum = sum/node.averages;
 | 
			
		||||
				// i is the index of the first breakpoint where the 'input' value is strictly
 | 
			
		||||
				// greater than the measurement (note: a measurement can never be == 1)
 | 
			
		||||
				var i = node.breakpoints.map(function (breakpoint) { return sum >= breakpoint.input; }).indexOf(false);
 | 
			
		||||
				msg.payload = node.breakpoints[i-1].output + (node.breakpoints[i].output - node.breakpoints[i-1].output) *
 | 
			
		||||
								(sum - node.breakpoints[i-1].input)/(node.breakpoints[i].input - node.breakpoints[i-1].input);
 | 
			
		||||
				node.send(msg);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    // If we have a valid pin, set the input event handler to Bonescript's analogRead
 | 
			
		||||
    if (["P9_39", "P9_40", "P9_37", "P9_38", "P9_33", "P9_36", "P9_35"].indexOf(node.pin) >= 0) {
 | 
			
		||||
        node.on("input", function (msg) {
 | 
			
		||||
        		sum = 0;
 | 
			
		||||
        		count = node.averages;
 | 
			
		||||
        		bonescript.analogRead(node.pin, analogReadCallback);
 | 
			
		||||
        	});
 | 
			
		||||
    } else {
 | 
			
		||||
        node.error("Unconfigured input pin");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Node constructor for discrete-in
 | 
			
		||||
function DiscreteInputNode(n) {
 | 
			
		||||
    RED.nodes.createNode(this, n);
 | 
			
		||||
@@ -415,6 +471,7 @@ function PulseOutputNode(n) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Register the nodes by name. This must be called before overriding any of the Node functions.
 | 
			
		||||
RED.nodes.registerType("analog-in", AnalogInputNode);
 | 
			
		||||
RED.nodes.registerType("discrete-in", DiscreteInputNode);
 | 
			
		||||
RED.nodes.registerType("pulse-in", PulseInputNode);
 | 
			
		||||
RED.nodes.registerType("discrete-out", DiscreteOutputNode);
 | 
			
		||||
		Reference in New Issue
	
	Block a user