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="orion/built-editor.min.js"></script> | ||||||
| <script src="d3.v3.min.js"></script> | <script src="d3.v3.min.js"></script> | ||||||
| <script src="red/main.js"></script> | <script src="red/main.js"></script> | ||||||
|  | <script src="red/comms.js"></script> | ||||||
| <script src="red/ui/state.js"></script> | <script src="red/ui/state.js"></script> | ||||||
| <script src="red/nodes.js"></script> | <script src="red/nodes.js"></script> | ||||||
| <script src="red/history.js"></script> | <script src="red/history.js"></script> | ||||||
| @@ -317,6 +318,5 @@ | |||||||
| <script src="red/ui/editor.js"></script> | <script src="red/ui/editor.js"></script> | ||||||
| <script src="red/ui/library.js"></script> | <script src="red/ui/library.js"></script> | ||||||
| <script src="red/ui/notifications.js"></script> | <script src="red/ui/notifications.js"></script> | ||||||
| <script src="red/comms.js"></script> |  | ||||||
| </body> | </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -18,26 +18,36 @@ RED.comms = function() { | |||||||
|      |      | ||||||
|     var errornotification = null; |     var errornotification = null; | ||||||
|     var subscriptions = {}; |     var subscriptions = {}; | ||||||
|      |     var ws; | ||||||
|     function connectWS() { |     function connectWS() { | ||||||
|         var path = location.hostname+":"+location.port+document.location.pathname; |         var path = location.hostname+":"+location.port+document.location.pathname; | ||||||
|         path = path+(path.slice(-1) == "/"?"":"/")+"comms"; |         path = path+(path.slice(-1) == "/"?"":"/")+"comms"; | ||||||
|         path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path; |         path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path; | ||||||
|         var ws = new WebSocket(path); |         ws = new WebSocket(path); | ||||||
|         ws.onopen = function() { |         ws.onopen = function() { | ||||||
|             if (errornotification) { |             if (errornotification) { | ||||||
|                 errornotification.close(); |                 errornotification.close(); | ||||||
|                 errornotification = null; |                 errornotification = null; | ||||||
|             } |             } | ||||||
|  |             for (var t in subscriptions) { | ||||||
|  |                 ws.send(JSON.stringify({subscribe:t})); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         ws.onmessage = function(event) { |         ws.onmessage = function(event) { | ||||||
|             var msg = JSON.parse(event.data); |             var msg = JSON.parse(event.data); | ||||||
|             var subscribers = subscriptions[msg.topic]; |             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) { |                         if (subscribers) { | ||||||
|                             for (var i=0;i<subscribers.length;i++) { |                             for (var i=0;i<subscribers.length;i++) { | ||||||
|                                 subscribers[i](msg.topic,msg.data); |                                 subscribers[i](msg.topic,msg.data); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         }; |         }; | ||||||
|         ws.onclose = function() { |         ws.onclose = function() { | ||||||
|             if (errornotification == null) { |             if (errornotification == null) { | ||||||
| @@ -46,16 +56,20 @@ RED.comms = function() { | |||||||
|             setTimeout(connectWS,1000); |             setTimeout(connectWS,1000); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     connectWS(); |  | ||||||
|      |      | ||||||
|     function subscribe(topic,callback) { |     function subscribe(topic,callback) { | ||||||
|         if (subscriptions[topic] == null) { |         if (subscriptions[topic] == null) { | ||||||
|             subscriptions[topic] = []; |             subscriptions[topic] = []; | ||||||
|         } |         } | ||||||
|         subscriptions[topic].push(callback); |         subscriptions[topic].push(callback); | ||||||
|  |         if (ws && ws.readyState == 1) { | ||||||
|  |             ws.send(JSON.stringify({subscribe:topic})); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |      | ||||||
|     return { |     return { | ||||||
|  |         connect: connectWS, | ||||||
|         subscribe: subscribe |         subscribe: subscribe | ||||||
|     } |     } | ||||||
| }(); | }(); | ||||||
|   | |||||||
| @@ -156,6 +156,15 @@ var RED = function() { | |||||||
|             RED.nodes.import(nodes); |             RED.nodes.import(nodes); | ||||||
|             RED.view.dirty(false); |             RED.view.dirty(false); | ||||||
|             RED.view.redraw(); |             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(); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -180,6 +189,7 @@ var RED = function() { | |||||||
|     $(function() { |     $(function() { | ||||||
|         RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); |         RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); | ||||||
|         loadSettings(); |         loadSettings(); | ||||||
|  |         RED.comms.connect(); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     return { |     return { | ||||||
|   | |||||||
| @@ -44,6 +44,12 @@ RED.view = function() { | |||||||
|  |  | ||||||
|     var clipboard = ""; |     var clipboard = ""; | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     var status_colours = { | ||||||
|  |         "red"  : "#00c", | ||||||
|  |         "green": "#5a8" | ||||||
|  |     } | ||||||
|  |      | ||||||
|     var outer = d3.select("#chart") |     var outer = d3.select("#chart") | ||||||
|         .append("svg:svg") |         .append("svg:svg") | ||||||
|         .attr("width", space_width) |         .attr("width", space_width) | ||||||
| @@ -893,6 +899,21 @@ RED.view = function() { | |||||||
|                         text.attr('text-anchor','end'); |                         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}); |                     //node.append("circle").attr({"class":"centerDot","cx":0,"cy":0,"r":5}); | ||||||
|  |  | ||||||
|                     if (d._def.inputs > 0) { |                     if (d._def.inputs > 0) { | ||||||
| @@ -1017,6 +1038,36 @@ RED.view = function() { | |||||||
|                             } |                             } | ||||||
|                             return ""; |                             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; |                         d.dirty = false; | ||||||
|                     } |                     } | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								red/comms.js
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								red/comms.js
									
									
									
									
									
								
							| @@ -23,6 +23,8 @@ var settings; | |||||||
| var wsServer; | var wsServer; | ||||||
| var activeConnections = []; | var activeConnections = []; | ||||||
|  |  | ||||||
|  | var retained = {}; | ||||||
|  |  | ||||||
| var heartbeatTimer; | var heartbeatTimer; | ||||||
| var lastSentTime; | 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) { |         ws.on('error', function(err) { | ||||||
|             util.log("[red:comms] error : "+err.toString()); |             util.log("[red:comms] error : "+err.toString()); | ||||||
|         }); |         }); | ||||||
| @@ -67,15 +75,32 @@ function start() { | |||||||
|     }, 15000); |     }, 15000); | ||||||
| } | } | ||||||
|  |  | ||||||
| function publish(topic,data) { | function publish(topic,data,retain) { | ||||||
|     var msg = JSON.stringify({topic:topic,data:data}); |     if (retain) { | ||||||
|  |         retained[topic] = data; | ||||||
|  |     } | ||||||
|  |     lastSentTime = Date.now(); | ||||||
|     activeConnections.forEach(function(conn) { |     activeConnections.forEach(function(conn) { | ||||||
|  |         publishTo(conn,topic,data); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function publishTo(ws,topic,data) { | ||||||
|  |     var msg = JSON.stringify({topic:topic,data:data}); | ||||||
|     try { |     try { | ||||||
|             conn.send(msg); |         ws.send(msg); | ||||||
|     } catch(err) { |     } catch(err) { | ||||||
|         util.log("[red:comms] send error : "+err.toString()); |         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]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ var clone = require("clone"); | |||||||
|  |  | ||||||
| var flows = require("./flows"); | var flows = require("./flows"); | ||||||
|  |  | ||||||
|  | var comms = require("../comms"); | ||||||
|  |  | ||||||
| function Node(n) { | function Node(n) { | ||||||
|     this.id = n.id; |     this.id = n.id; | ||||||
| @@ -114,6 +114,11 @@ Node.prototype.error = function(msg) { | |||||||
|     if (this.name) o.name = this.name; |     if (this.name) o.name = this.name; | ||||||
|     this.emit("log",o); |     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; | module.exports = Node; | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ var events = require("./events"); | |||||||
| var server = require("./server"); | var server = require("./server"); | ||||||
| var nodes = require("./nodes"); | var nodes = require("./nodes"); | ||||||
| var library = require("./library"); | var library = require("./library"); | ||||||
| var comms = require("./comms"); |  | ||||||
| var log = require("./log"); | var log = require("./log"); | ||||||
| var fs = require("fs"); | var fs = require("fs"); | ||||||
| var settings = null; | var settings = null; | ||||||
| @@ -51,7 +50,6 @@ var RED = { | |||||||
|     stop: server.stop, |     stop: server.stop, | ||||||
|     nodes: nodes, |     nodes: nodes, | ||||||
|     library: library, |     library: library, | ||||||
|     comms: comms, |  | ||||||
|     events: events, |     events: events, | ||||||
|     log: log |     log: log | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user