Reputation: 65
to control my robot via Node-Red dashboard, I need some kind of joystick control for UI (not a hardware joystick).
Luckily I found nippleJS which does exactly what I was looking for. Also I was able to get it running with ui_template node.
Now I get stuck. How can I send the coordinates back to node-red node? I know that I can't reach any context and I only get a msg object. But I'm unable to change it (msg undefined).
Here is my current flow. To run it you must load nipplejs and set the path accordingly. I hope someone out there can show me a way how to send data back to node-red
[{"id":"ff5f827f.796e","type":"ui_template","z":"9738c4ac.01e748","group":"9550e4e.ea6f618","name":"","order":0,"width":"6","height":"6","format":"\n<script src=\"/myjs/nippleJS/nipplejs.min.js\" ></script>\n\n<div data-type=\"semi\" id=\"zone_joystick\" style=\"position:absolute; width:200px; height:200px; background-color:grey;\"></div>\n\n<script>\n\n\n (function(scope){ \n\n scope.$watch('msg', function(msg) {\n createJoystick();\n \n });\n })(scope);\n\n\nfunction createJoystick(){\n var semi = nipplejs.create({\n zone: document.getElementById('zone_joystick'),\n mode: 'semi',\n catchDistance: 150,\n color: 'white'\n });\n\t\n\n\tsemi.on('move', function(evt, nipple_obj) {\n\t debug(nipple_obj);\n\t});\n\t\n\t}\n\nfunction debug(obj) {\n setTimeout(function() {\n var test = obj.position.x;\n console.log(test);\n }, 0);\n}\t\n\t\n\t\t\n\n</script>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":286,"y":708,"wires":[["17f18c51.494204","3e99bf46.a8532"]]},{"id":"b2219879.075b28","type":"inject","z":"9738c4ac.01e748","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":117,"y":675,"wires":[["ff5f827f.796e"]]},{"id":"17f18c51.494204","type":"ui_text","z":"9738c4ac.01e748","group":"9550e4e.ea6f618","order":0,"width":"3","height":"2","name":"","label":"text","format":"{{msg.payload}}","layout":"row-spread","x":468,"y":736,"wires":[]},{"id":"3e99bf46.a8532","type":"debug","z":"9738c4ac.01e748","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":314,"y":769,"wires":[]},{"id":"9550e4e.ea6f618","type":"ui_group","z":"","name":"Joystick","tab":"ccfc45fa.de7cb8","order":1,"disp":true,"width":"6","collapse":false},{"id":"ccfc45fa.de7cb8","type":"ui_tab","z":"","name":"Bubbles","icon":"dashboard"}]
For those who don't want to import the flow, here is the Script I use. As you see in function debug, I can print the values to console. I need this value back.
<script src="/myjs/nippleJS/nipplejs.min.js" ></script>
<div data-type="semi" id="zone_joystick" style="position:absolute; width:200px; height:200px; background-color:grey;"></div>
<script>
(function(scope){
scope.$watch('msg', function(msg) {
createJoystick();
});
})(scope);
function createJoystick(){
var semi = nipplejs.create({
zone: document.getElementById('zone_joystick'),
mode: 'semi',
catchDistance: 150,
color: 'white'
});
semi.on('move', function(evt, nipple_obj) {
debug(nipple_obj);
});
}
function debug(obj) {
setTimeout(function() {
var test = obj.position.x;
console.log(test);
}, 0);
}
</script>
Thank you for your support, Patrick.
Upvotes: 1
Views: 3871
Reputation: 65
Just in case someone else wants to use nippleJS, here is my workling code
[{"id":"d1cb92a5.0e9b2","type":"inject","z":"cf477024.84de6","name":"Trigger UI Templates","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":163,"y":209,"wires":[["93a7c595.e3b868","8b092d1b.0e2ed"]]},{"id":"8b092d1b.0e2ed","type":"ui_template","z":"cf477024.84de6","group":"52892a0c.d9c5b4","name":"Joystick","order":0,"width":"6","height":"6","format":"<script src=\"/myjs/nippleJS/nipplejs.min.js\" ></script>\n\n<div data-type=\"dynamic\" id=\"zone_joystick\" style=\"position:absolute; width:200px; height:200px; background-color:grey;\"></div>\n\n<script>\n\n\n(function(scope){ \n\n function createJoystick(){\n var dynamic = nipplejs.create({\n zone: document.getElementById('zone_joystick'),\n mode: 'dynamic',\n catchDistance: 150,\n color: 'white'\n });\n dynamic.on('move', function(evt, nipple_obj) {\n setTimeout(function() {\n var posx = nipple_obj.position.x;\n var posy = nipple_obj.position.y;\n var centerx = nipple_obj.instance.position.x;\n var centery = nipple_obj.instance.position.y;\n // use scope.send to trigger a message in the runtime flow\n scope.send({payload:{x: posx, y:posy, centerx:centerx, centery:centery}});\n }, 0);\n\n });\n }\n\n\n scope.$watch('msg', function(msg) {\n createJoystick();\n\n });\n})(scope);\n\n</script>","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":434,"y":212,"wires":[["65da6852.c65ac8","fbdf3963.9c2858"]]},{"id":"fbdf3963.9c2858","type":"function","z":"cf477024.84de6","name":"","func":"\nvar x = {payload:msg.payload.centerx - msg.payload.x};\nvar y = {payload:msg.payload.centery - msg.payload.y};\n\nreturn [x, y];","outputs":2,"noerr":0,"x":578,"y":216,"wires":[["26f05e22.8d3a12"],["2d78681b.d82be8"]]},{"id":"26f05e22.8d3a12","type":"ui_text","z":"cf477024.84de6","group":"52892a0c.d9c5b4","order":0,"width":"3","height":"1","name":"","label":"X","format":"{{msg.payload}}","layout":"row-spread","x":710,"y":227,"wires":[]},{"id":"2d78681b.d82be8","type":"ui_text","z":"cf477024.84de6","group":"52892a0c.d9c5b4","order":0,"width":"3","height":"2","name":"","label":"Y","format":"{{msg.payload}}","layout":"row-spread","x":719,"y":275,"wires":[]},{"id":"65da6852.c65ac8","type":"debug","z":"cf477024.84de6","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":571,"y":257,"wires":[]},{"id":"52892a0c.d9c5b4","type":"ui_group","z":"","name":"Default","tab":"56c2703a.7a819","disp":true,"width":"6","collapse":false},{"id":"56c2703a.7a819","type":"ui_tab","z":"","name":"Manual","icon":"dashboard"}]
Thanks again knolleary
Upvotes: 0
Reputation: 10117
The scope
object has a send
function that can be used to send a message from the ui_template
node within the runtime.
You need to structure your code so the callback for the move
event is in scope of the scope
variable. For example, replace your code inside the <script>
block with:
(function(scope){
function createJoystick(){
var semi = nipplejs.create({
zone: document.getElementById('zone_joystick'),
mode: 'semi',
catchDistance: 150,
color: 'white'
});
semi.on('move', function(evt, nipple_obj) {
setTimeout(function() {
var test = obj.position.x;
// use scope.send to trigger a message in the runtime flow
scope.send({payload:test});
}, 0);
});
}
scope.$watch('msg', function(msg) {
createJoystick();
});
})(scope);
Upvotes: 2