mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Add node status updates
This commit is contained in:
		| @@ -303,6 +303,7 @@ | ||||
| <script src="orion/built-editor.min.js"></script> | ||||
| <script src="d3.v3.min.js"></script> | ||||
| <script src="red/main.js"></script> | ||||
| <script src="red/comms.js"></script> | ||||
| <script src="red/ui/state.js"></script> | ||||
| <script src="red/nodes.js"></script> | ||||
| <script src="red/history.js"></script> | ||||
| @@ -317,6 +318,5 @@ | ||||
| <script src="red/ui/editor.js"></script> | ||||
| <script src="red/ui/library.js"></script> | ||||
| <script src="red/ui/notifications.js"></script> | ||||
| <script src="red/comms.js"></script> | ||||
| </body> | ||||
| </html> | ||||
|   | ||||
| @@ -18,24 +18,34 @@ RED.comms = function() { | ||||
|      | ||||
|     var errornotification = null; | ||||
|     var subscriptions = {}; | ||||
|      | ||||
|     var ws; | ||||
|     function connectWS() { | ||||
|         var path = location.hostname+":"+location.port+document.location.pathname; | ||||
|         path = path+(path.slice(-1) == "/"?"":"/")+"comms"; | ||||
|         path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path; | ||||
|         var ws = new WebSocket(path); | ||||
|         ws = new WebSocket(path); | ||||
|         ws.onopen = function() { | ||||
|             if (errornotification) { | ||||
|                 errornotification.close(); | ||||
|                 errornotification = null; | ||||
|             } | ||||
|             for (var t in subscriptions) { | ||||
|                 ws.send(JSON.stringify({subscribe:t})); | ||||
|             } | ||||
|         } | ||||
|         ws.onmessage = function(event) { | ||||
|             var msg = JSON.parse(event.data); | ||||
|             var subscribers = subscriptions[msg.topic]; | ||||
|             if (subscribers) { | ||||
|                 for (var i=0;i<subscribers.length;i++) { | ||||
|                     subscribers[i](msg.topic,msg.data); | ||||
|             if (msg.topic) { | ||||
|                 for (var t in subscriptions) { | ||||
|                     var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); | ||||
|                     if (re.test(msg.topic)) { | ||||
|                         var subscribers = subscriptions[t]; | ||||
|                         if (subscribers) { | ||||
|                             for (var i=0;i<subscribers.length;i++) { | ||||
|                                 subscribers[i](msg.topic,msg.data); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
| @@ -46,16 +56,20 @@ RED.comms = function() { | ||||
|             setTimeout(connectWS,1000); | ||||
|         } | ||||
|     } | ||||
|     connectWS(); | ||||
|  | ||||
|      | ||||
|     function subscribe(topic,callback) { | ||||
|         if (subscriptions[topic] == null) { | ||||
|             subscriptions[topic] = []; | ||||
|         } | ||||
|         subscriptions[topic].push(callback); | ||||
|         if (ws && ws.readyState == 1) { | ||||
|             ws.send(JSON.stringify({subscribe:topic})); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|      | ||||
|     return { | ||||
|         connect: connectWS, | ||||
|         subscribe: subscribe | ||||
|     } | ||||
| }(); | ||||
|   | ||||
| @@ -52,13 +52,13 @@ var RED = function() { | ||||
|                 var invalid = false; | ||||
|                 var unknownNodes = []; | ||||
|                 RED.nodes.eachNode(function(node) { | ||||
|                         invalid = invalid || !node.valid; | ||||
|                         if (node.type === "unknown") { | ||||
|                             if (unknownNodes.indexOf(node.name) == -1) { | ||||
|                                 unknownNodes.push(node.name); | ||||
|                             } | ||||
|                             invalid = true; | ||||
|                     invalid = invalid || !node.valid; | ||||
|                     if (node.type === "unknown") { | ||||
|                         if (unknownNodes.indexOf(node.name) == -1) { | ||||
|                             unknownNodes.push(node.name); | ||||
|                         } | ||||
|                         invalid = true; | ||||
|                     } | ||||
|                 }); | ||||
|                 if (invalid) { | ||||
|                     if (unknownNodes.length > 0) { | ||||
| @@ -137,25 +137,34 @@ var RED = function() { | ||||
|  | ||||
|     function loadSettings() { | ||||
|         $.get('settings', function(data) { | ||||
|                 RED.settings = data; | ||||
|                 loadNodes(); | ||||
|             RED.settings = data; | ||||
|             loadNodes(); | ||||
|         }); | ||||
|     } | ||||
|     function loadNodes() { | ||||
|         $.get('nodes', function(data) { | ||||
|                 $("body").append(data); | ||||
|                 $(".palette-spinner").hide(); | ||||
|                 $(".palette-scroll").show(); | ||||
|                 $("#palette-search").show(); | ||||
|                 loadFlows(); | ||||
|             $("body").append(data); | ||||
|             $(".palette-spinner").hide(); | ||||
|             $(".palette-scroll").show(); | ||||
|             $("#palette-search").show(); | ||||
|             loadFlows(); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     function loadFlows() { | ||||
|         $.getJSON("flows",function(nodes) { | ||||
|                 RED.nodes.import(nodes); | ||||
|                 RED.view.dirty(false); | ||||
|                 RED.view.redraw(); | ||||
|             RED.nodes.import(nodes); | ||||
|             RED.view.dirty(false); | ||||
|             RED.view.redraw(); | ||||
|             RED.comms.subscribe("status/#",function(topic,msg) { | ||||
|                 var parts = topic.split("/"); | ||||
|                 var node = RED.nodes.node(parts[1]); | ||||
|                 if (node) { | ||||
|                     node.status = msg; | ||||
|                     node.dirty = true; | ||||
|                     RED.view.redraw(); | ||||
|                 } | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @@ -168,18 +177,19 @@ var RED = function() { | ||||
|         //}); | ||||
|  | ||||
|         dialog.on('show',function() { | ||||
|                 RED.keyboard.disable(); | ||||
|             RED.keyboard.disable(); | ||||
|         }); | ||||
|         dialog.on('hidden',function() { | ||||
|                 RED.keyboard.enable(); | ||||
|             RED.keyboard.enable(); | ||||
|         }); | ||||
|  | ||||
|         dialog.modal(); | ||||
|     } | ||||
|  | ||||
|     $(function() { | ||||
|             RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); | ||||
|             loadSettings(); | ||||
|         RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); | ||||
|         loadSettings(); | ||||
|         RED.comms.connect(); | ||||
|     }); | ||||
|  | ||||
|     return { | ||||
|   | ||||
| @@ -44,6 +44,12 @@ RED.view = function() { | ||||
|  | ||||
|     var clipboard = ""; | ||||
|  | ||||
|      | ||||
|     var status_colours = { | ||||
|         "red"  : "#00c", | ||||
|         "green": "#5a8" | ||||
|     } | ||||
|      | ||||
|     var outer = d3.select("#chart") | ||||
|         .append("svg:svg") | ||||
|         .attr("width", space_width) | ||||
| @@ -811,7 +817,7 @@ RED.view = function() { | ||||
|                                 .on("click",function(d) { d._def.onbadgeclick.call(d);d3.event.preventDefault();}); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                      | ||||
|                     if (d._def.button) { | ||||
|                         var nodeButtonGroup = node.append('svg:g') | ||||
|                             .attr("transform",function(d) { return "translate("+((d._def.align == "right") ? 94 : -25)+",2)"; }) | ||||
| @@ -893,6 +899,21 @@ RED.view = function() { | ||||
|                         text.attr('text-anchor','end'); | ||||
|                     } | ||||
|  | ||||
|                     var status = node.append("svg:g").attr("class","node_status_group").style("display","none"); | ||||
|                      | ||||
|                     var statusRect = status.append("circle").attr("class","node_status") | ||||
|                                             .attr("cx",9).attr("cy",6).attr("r",5).attr("stroke-width","3"); | ||||
|                     var statusLabel = status.append("svg:text") | ||||
|                         .attr("class","node_status_label") | ||||
|                         .attr('x',20).attr('y',10) | ||||
|                         .style({ | ||||
|                                 'stroke-width': 0, | ||||
|                                 'fill': '#999', | ||||
|                                 'font-size':'9pt', | ||||
|                                 'stroke':'#000', | ||||
|                                 'text-anchor':'start' | ||||
|                         }); | ||||
|                          | ||||
|                     //node.append("circle").attr({"class":"centerDot","cx":0,"cy":0,"r":5}); | ||||
|  | ||||
|                     if (d._def.inputs > 0) { | ||||
| @@ -1017,7 +1038,37 @@ RED.view = function() { | ||||
|                             } | ||||
|                             return ""; | ||||
|                         }); | ||||
|  | ||||
|                         if (!d.status) { | ||||
|                             thisNode.selectAll('.node_status_group').style("display","none"); | ||||
|                         } else { | ||||
|                             thisNode.selectAll('.node_status_group').style("display","inline").attr("transform","translate(3,"+(d.h+3)+")"); | ||||
|                             var fill = status_colours[d.status.fill]; // Only allow our colours for now | ||||
|                             if (d.status.shape == null && fill == null) { | ||||
|                                 thisNode.selectAll('.node_status').style("display","none"); | ||||
|                             } else { | ||||
|                                 var style; | ||||
|                                 if (d.status.shape == null || d.status.shape == "dot") { | ||||
|                                     style = { | ||||
|                                         display: "inline", | ||||
|                                         fill: fill, | ||||
|                                         stroke: fill | ||||
|                                     }; | ||||
|                                 } else if (d.status.shape == "ring" ){ | ||||
|                                     style = { | ||||
|                                         display: "inline", | ||||
|                                         fill: '#fff', | ||||
|                                         stroke: fill | ||||
|                                     } | ||||
|                                 } | ||||
|                                 thisNode.selectAll('.node_status').style(style); | ||||
|                             } | ||||
|                             if (d.status.text) { | ||||
|                                 thisNode.selectAll('.node_status_label').text(d.status.text); | ||||
|                             } else { | ||||
|                                 thisNode.selectAll('.node_status_label').text(""); | ||||
|                             } | ||||
|                         } | ||||
|                          | ||||
|                         d.dirty = false; | ||||
|                     } | ||||
|             }); | ||||
|   | ||||
							
								
								
									
										39
									
								
								red/comms.js
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								red/comms.js
									
									
									
									
									
								
							| @@ -23,6 +23,8 @@ var settings; | ||||
| var wsServer; | ||||
| var activeConnections = []; | ||||
|  | ||||
| var retained = {}; | ||||
|  | ||||
| var heartbeatTimer; | ||||
| var lastSentTime; | ||||
|  | ||||
| @@ -47,6 +49,12 @@ function start() { | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|         ws.on('message', function(data,flags) { | ||||
|             var msg = JSON.parse(data); | ||||
|             if (msg.subscribe) { | ||||
|                 handleRemoteSubscription(ws,msg.subscribe); | ||||
|             } | ||||
|         }); | ||||
|         ws.on('error', function(err) { | ||||
|             util.log("[red:comms] error : "+err.toString()); | ||||
|         }); | ||||
| @@ -67,17 +75,34 @@ function start() { | ||||
|     }, 15000); | ||||
| } | ||||
|  | ||||
| function publish(topic,data) { | ||||
|     var msg = JSON.stringify({topic:topic,data:data}); | ||||
| function publish(topic,data,retain) { | ||||
|     if (retain) { | ||||
|         retained[topic] = data; | ||||
|     } | ||||
|     lastSentTime = Date.now(); | ||||
|     activeConnections.forEach(function(conn) { | ||||
|         try { | ||||
|             conn.send(msg); | ||||
|         } catch(err) { | ||||
|             util.log("[red:comms] send error : "+err.toString()); | ||||
|         } | ||||
|         publishTo(conn,topic,data); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function publishTo(ws,topic,data) { | ||||
|     var msg = JSON.stringify({topic:topic,data:data}); | ||||
|     try { | ||||
|         ws.send(msg); | ||||
|     } catch(err) { | ||||
|         util.log("[red:comms] send error : "+err.toString()); | ||||
|     } | ||||
| } | ||||
|  | ||||
| function handleRemoteSubscription(ws,topic) { | ||||
|     var re = new RegExp("^"+topic.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); | ||||
|     for (var t in retained) { | ||||
|         if (re.test(t)) { | ||||
|             publishTo(ws,t,retained[t]); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| module.exports = { | ||||
|     init:init, | ||||
|   | ||||
| @@ -20,7 +20,7 @@ var clone = require("clone"); | ||||
|  | ||||
| var flows = require("./flows"); | ||||
|  | ||||
|  | ||||
| var comms = require("../comms"); | ||||
|  | ||||
| function Node(n) { | ||||
|     this.id = n.id; | ||||
| @@ -114,6 +114,11 @@ Node.prototype.error = function(msg) { | ||||
|     if (this.name) o.name = this.name; | ||||
|     this.emit("log",o); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * status: { fill:"red|green", shape:"dot|ring", text:"blah" } | ||||
|  */ | ||||
| Node.prototype.status = function(status,retain) { | ||||
|     comms.publish("status/"+this.id,status,retain); | ||||
| } | ||||
|  | ||||
| module.exports = Node; | ||||
|   | ||||
| @@ -18,7 +18,6 @@ var events = require("./events"); | ||||
| var server = require("./server"); | ||||
| var nodes = require("./nodes"); | ||||
| var library = require("./library"); | ||||
| var comms = require("./comms"); | ||||
| var log = require("./log"); | ||||
| var fs = require("fs"); | ||||
| var settings = null; | ||||
| @@ -51,7 +50,6 @@ var RED = { | ||||
|     stop: server.stop, | ||||
|     nodes: nodes, | ||||
|     library: library, | ||||
|     comms: comms, | ||||
|     events: events, | ||||
|     log: log | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user