Scratch 3 and NodeRED working together

#1

Scratch 3 translate requests re-directed to NodeRED HTTP nodes using a chrome extension

Then parsed by Blockly node and result of eval returned back to Scratch

Brings power of javascript to Scratch :slight_smile:

image

[{"id":"5e6b6b53.d78c04","type":"http in","z":"c8a7da0b.8ad438","name":"","url":"/translate","method":"get","upload":false,"swaggerDoc":"","x":90,"y":100,"wires":[["8b7c4be.55fcbb8"]]},{"id":"de319892.1c93d8","type":"http response","z":"c8a7da0b.8ad438","name":"","statusCode":"","headers":{"Access-Control-Allow-Origin":"*"},"x":390,"y":100,"wires":[]},{"id":"605a7fc1.3e2e9","type":"inject","z":"c8a7da0b.8ad438","name":"","topic":"","payload":"{\"text\":\"[1+2]\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":200,"wires":[["8b7c4be.55fcbb8"]]},{"id":"a6cea089.6eee9","type":"debug","z":"c8a7da0b.8ad438","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":370,"y":220,"wires":[]},{"id":"8b7c4be.55fcbb8","type":"Blockly","z":"c8a7da0b.8ad438","language":"en","func":"var message;\n\n\nmessage = (msg['payload']['text']);\n// Remove [ and/or ]\nif (message.charAt(0) == '[') {\n  message = message.slice(1, message.length);\n}\nif (message.slice(-1) == ']') {\n  message = message.slice(0, message.length - 1);\n}\n// Use eval to process the message\nmessage = String(eval(message));\n// Re-package result to pass back to Scratch 3\nmessage = ['{\"result\":\"',message,'\"}'].join('');\nmsg['payload'] = message;\nreturn msg;\n","workspaceXml":"<xml xmlns=\"http://www.w3.org/1999/xhtml\"><variables><variable type=\"\" id=\"tRt)J6ju,#c{x[U1pP.I\">message</variable></variables><block type=\"variables_set\" id=\"1#8[z=8c+=_~=Q0ULr#K\" x=\"-462\" y=\"-212\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"node_object_get\" id=\"}Lha(ev5jipd*2wwf|9t\"><mutation action=\"GET\"></mutation><field name=\"action\">GET</field><value name=\"object\"><shadow type=\"node_msg\" id=\"?5)PeuSYW/w|6npl8soI\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"+?KfAUp_a6($,t/G+LYe\"><field name=\"TEXT\">payload.text</field></shadow></value></block></value><next><block type=\"misc_comment\" id=\"WIRVzXH+hmlI*+.9d@KW\"><value name=\"TEXT\"><shadow type=\"text\" id=\"G-BR-,XLXr{67lem9w#q\"><field name=\"TEXT\">Remove [ and/or ]</field></shadow></value><next><block type=\"controls_if\" id=\"KUOuZO+imQGNU3(xJB[!\"><value name=\"IF0\"><block type=\"logic_compare\" id=\"@$Ud+/EKOZn9QqlZ%5Ak\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"text_charAt\" id=\"EiPm~/*k27j{Sc|M{^FJ\"><mutation at=\"false\"></mutation><field name=\"WHERE\">FIRST</field><value name=\"VALUE\"><block type=\"variables_get\" id=\".uh:5ru_m0//-%tNx!,O\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value></block></value><value name=\"B\"><block type=\"text\" id=\"qq]Q`wDc5-~cIFGEKL-c\"><field name=\"TEXT\">[</field></block></value></block></value><statement name=\"DO0\"><block type=\"variables_set\" id=\"CQVibNOb9ME$!PIRvzb;\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_getSubstring\" id=\"x}/1BSlZSQNp~79,NQXJ\"><mutation at1=\"true\" at2=\"false\"></mutation><field name=\"WHERE1\">FROM_START</field><field name=\"WHERE2\">LAST</field><value name=\"STRING\"><block type=\"variables_get\" id=\"@S?i8O{S=;P7b$4J::sp\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"AT1\"><block type=\"math_number\" id=\"@)t-J;cEnYs_-$9CLP!c\"><field name=\"NUM\">2</field></block></value></block></value></block></statement><next><block type=\"controls_if\" id=\"|!@53E@~Z~5Prk)S^$JJ\"><value name=\"IF0\"><block type=\"logic_compare\" id=\"*t/tA0Mfw?ddyac*0Fv5\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"text_charAt\" id=\"KQ?:{LT2aPn-rbd?uS-h\"><mutation at=\"false\"></mutation><field name=\"WHERE\">LAST</field><value name=\"VALUE\"><block type=\"variables_get\" id=\"Chy1ta2u|LVv`Amvc{@l\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value></block></value><value name=\"B\"><block type=\"text\" id=\"0kMv[heEgcW}`Z.5j+lr\"><field name=\"TEXT\">]</field></block></value></block></value><statement name=\"DO0\"><block type=\"variables_set\" id=\"?fhsb}acBq%{Zf1rQtfp\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_getSubstring\" id=\"^z%Dflr1)K1=HJF7**3X\"><mutation at1=\"false\" at2=\"true\"></mutation><field name=\"WHERE1\">FIRST</field><field name=\"WHERE2\">FROM_END</field><value name=\"STRING\"><block type=\"variables_get\" id=\"g,wc2-M{/!4ZCUM.~C`|\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"AT2\"><block type=\"math_number\" id=\"Y/bQQ.a*EM!h@~m~DKtD\"><field name=\"NUM\">2</field></block></value></block></value></block></statement><next><block type=\"misc_comment\" id=\"pL$%3)!S*F*h/uyFFWfL\"><value name=\"TEXT\"><shadow type=\"text\" id=\"KbV6=2]L9vIQ$,?|K(OU\"><field name=\"TEXT\">Use eval to process the message</field></shadow></value><next><block type=\"misc_javascript\" id=\"[:eX51yxUnbyhl7-cz$m\"><value name=\"STATEMENT\"><shadow type=\"text\" id=\"1t?Vp%SuQ@bN2~$M3J]L\"><field name=\"TEXT\">message = String(eval(message))</field></shadow></value><next><block type=\"misc_comment\" id=\"(]5Y3@2N/E%w#4UqgDI}\"><value name=\"TEXT\"><shadow type=\"text\" id=\"c|R*SbW396,l}$_7g9,~\"><field name=\"TEXT\">Re-package result to pass back to Scratch 3</field></shadow></value><next><block type=\"variables_set\" id=\"nRdt[H56mc#x$jb_m6tH\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_join\" id=\"{5aa^yGeaA}e#+mHhiEw\" inline=\"true\"><mutation items=\"3\"></mutation><value name=\"ADD0\"><block type=\"text\" id=\"g9y^B`=d6]Fq^D+n.{ts\"><field name=\"TEXT\">{\"result\":\"</field></block></value><value name=\"ADD1\"><block type=\"variables_get\" id=\"@7lQ*N}w.49T,9~Zbu*5\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"ADD2\"><block type=\"text\" id=\";XB3H60nOwE:#%=pC%@M\"><field name=\"TEXT\">\"}</field></block></value></block></value><next><block type=\"node_object_set\" id=\"TtY/%g}HQ.thV[!)[)+?\" inline=\"true\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"M).kpUd-=P`$-@}AiR47\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"$8B#TMu?Jk,_S~VWy{2L\"><field name=\"TEXT\">payload</field></shadow></value><value name=\"value_field\"><shadow type=\"text\" id=\"l%C_@co}{eglIH!)%.D[\"><field name=\"TEXT\"></field></shadow><block type=\"variables_get\" id=\"`(1IxXS^hiy;uAiLtNRT\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><next><block type=\"node_return_message\" id=\"*bbcmWYcM1SuE^[3$)+_\"><field name=\"OUTPUT_NR\">1</field><value name=\"MESSAGE_INPUT\"><shadow type=\"node_msg\" id=\"SYNR|[0}wO3nN5A(,1yq\"></shadow></value></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></xml>","outputs":1,"name":"","x":260,"y":100,"wires":[["de319892.1c93d8","a6cea089.6eee9"]]}]
3 Likes
#2

Hi Simon,
That looks really interesting - thanks for sharing.
One question - where did you find the NodeRED HTTP Server extension for Scratch 3.0 ???

Cheers from David.

#3

There's nothing running on/within Scratch 3 other than the translate extension

Last year, i noticed that Scratch 3 uses calls to https://translate-service.scratch.mit.edu/language=xxx&text=yyyy to do the translations

originally, I used computer hosts file to re-direct these calls to my own python webserver which processed them and returned results back to Scratch. I'm using this for a Scratch3 -> Pi GPIO effort

A friend said he could write a Chrome extension to do the redirection instead and then recently I found this Redirector chrome store extension to do the job instead (my friends original one needed to be loaded manually)

So the extension re-directs and translation requests surrounded by (actually any non alphanumeric char but I stick with using ) :slight_smile:

#4

Hi Simon,
Just been trying to get "Translate" to work.
Will it work with the Desktop offline version of Scratch-3 ???

I might have misunderstood "Translate".

I thought I could send/receive text strings to/from Scratch (and Node-RED) that I could then decode in Scratch to perform things like... move the cat, utter words, etc..

#5

It doesn't work on Scratch Desktop because its a rolled up webapp so no-way of getting chrome extension running inside it (but the hosts file workaground may work but its a real bodge doing it that way)

I'll be doing a blog on this but 1st thing is to install Scratch Translate extension

Then install the Chrome browser extension called Redirector - you can upload these settings to it to set it up

{
    "createdBy": "Redirector v3.2",
    "createdAt": "2019-02-28T20:20:19.675Z",
    "redirects": [
        {
            "description": "Scratch3 Translate",
            "exampleUrl": "https://translate-service.scratch.mit.edu/translate?language=en&text=%",
            "exampleResult": "http://localhost:1880/translate?language=en&text=%",
            "error": null,
            "includePattern": "https://translate-service.scratch.mit.edu/translate?language=en&text=%*",
            "excludePattern": "",
            "patternDesc": "",
            "redirectUrl": "http://localhost:1880/translate?language=en&text=%$1",
            "patternType": "W",
            "processMatches": "noProcessing",
            "disabled": false,
            "appliesTo": [
                "main_frame",
                "xmlhttprequest"
            ]
        }
    ]
}

or type in from this pic but one mistook and it won't work :slight_smile:

That will redirect any translate extension requests that have a [ at the start of them to NodeRED webserver running on same machine

e.g
image

will get sent to localhost

image
will go as normal to translate-service.scratch.mit.edu

(timer needed on language to randomise language to prevent Scratch translate extension caching sequential requests)

Then use this flow (blockly translated into javascript function) to respond to requests and return a JSON string formatted like this

{"result":"foobar"}

where foobar is the value that the translate block will report

[{"id":"90d1c275.a2499","type":"http in","z":"95e451ab.36f1","name":"","url":"/translate","method":"get","upload":false,"swaggerDoc":"","x":90,"y":80,"wires":[["2df4aae3.985c16"]]},{"id":"31cf166a.c33efa","type":"http response","z":"95e451ab.36f1","name":"","statusCode":"","headers":{"Access-Control-Allow-Origin":"*"},"x":390,"y":80,"wires":[]},{"id":"24da8b0c.634494","type":"inject","z":"95e451ab.36f1","name":"","topic":"","payload":"{\"text\":\"[1+2]\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":180,"wires":[["2df4aae3.985c16"]]},{"id":"2b21b67d.3d217a","type":"debug","z":"95e451ab.36f1","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":370,"y":200,"wires":[]},{"id":"2df4aae3.985c16","type":"function","z":"95e451ab.36f1","name":"","func":"var message;\n\n\nmessage = (msg['payload']['text']);\n// Remove [ and/or ]\nif (message.charAt(0) == '[') {\n  message = message.slice(1, message.length);\n}\nif (message.slice(-1) == ']') {\n  message = message.slice(0, message.length - 1);\n}\n// Use eval to process the message\nmessage = String(eval(message));\n// Re-package result to pass back to Scratch 3\nmessage = ['{\"result\":\"',message,'\"}'].join('');\nmsg['payload'] = message;\nreturn msg;","outputs":1,"noerr":0,"x":250,"y":80,"wires":[["31cf166a.c33efa","2b21b67d.3d217a"]]}]

My code does a javascript eval of whatever is inside the but you can make it do what you want :slight_smile:

Come back if it doesn't work for you :slight_smile:

#6

I've split the main Blockly node into two to demonstrate how easy to add in functionality

[{"id":"e37ea0ce.0a02f","type":"http in","z":"5394ff3.760ca","name":"","url":"/translate","method":"get","upload":false,"swaggerDoc":"","x":90,"y":120,"wires":[["b2ec3054.cdfdc"]]},{"id":"55a1e66d.8692e8","type":"http response","z":"5394ff3.760ca","name":"","statusCode":"","headers":{"Access-Control-Allow-Origin":"*"},"x":730,"y":160,"wires":[]},{"id":"15d00d47.085123","type":"inject","z":"5394ff3.760ca","name":"","topic":"","payload":"{\"text\":\"[1+2]\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":220,"wires":[["b2ec3054.cdfdc"]]},{"id":"8d7c059a.8e2108","type":"debug","z":"5394ff3.760ca","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":750,"y":220,"wires":[]},{"id":"b2ec3054.cdfdc","type":"Blockly","z":"5394ff3.760ca","language":"en","func":"var message;\n\n\nmessage = (msg['payload']['text']);\n// Remove [ and/or ]\nif (message.charAt(0) == '[') {\n  message = message.slice(1, message.length);\n}\nif (message.slice(-1) == ']') {\n  message = message.slice(0, message.length - 1);\n}\nmsg['payload'] = message;\nreturn msg;\n","workspaceXml":"<xml xmlns=\"http://www.w3.org/1999/xhtml\"><variables><variable type=\"\" id=\"tRt)J6ju,#c{x[U1pP.I\">message</variable></variables><block type=\"variables_set\" id=\"1#8[z=8c+=_~=Q0ULr#K\" x=\"-612\" y=\"-212\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"node_object_get\" id=\"}Lha(ev5jipd*2wwf|9t\"><mutation action=\"GET\"></mutation><field name=\"action\">GET</field><value name=\"object\"><shadow type=\"node_msg\" id=\"?5)PeuSYW/w|6npl8soI\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"+?KfAUp_a6($,t/G+LYe\"><field name=\"TEXT\">payload.text</field></shadow></value></block></value><next><block type=\"misc_comment\" id=\"WIRVzXH+hmlI*+.9d@KW\"><value name=\"TEXT\"><shadow type=\"text\" id=\"G-BR-,XLXr{67lem9w#q\"><field name=\"TEXT\">Remove [ and/or ]</field></shadow></value><next><block type=\"controls_if\" id=\"KUOuZO+imQGNU3(xJB[!\"><value name=\"IF0\"><block type=\"logic_compare\" id=\"@$Ud+/EKOZn9QqlZ%5Ak\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"text_charAt\" id=\"EiPm~/*k27j{Sc|M{^FJ\"><mutation at=\"false\"></mutation><field name=\"WHERE\">FIRST</field><value name=\"VALUE\"><block type=\"variables_get\" id=\".uh:5ru_m0//-%tNx!,O\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value></block></value><value name=\"B\"><block type=\"text\" id=\"qq]Q`wDc5-~cIFGEKL-c\"><field name=\"TEXT\">[</field></block></value></block></value><statement name=\"DO0\"><block type=\"variables_set\" id=\"CQVibNOb9ME$!PIRvzb;\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_getSubstring\" id=\"x}/1BSlZSQNp~79,NQXJ\"><mutation at1=\"true\" at2=\"false\"></mutation><field name=\"WHERE1\">FROM_START</field><field name=\"WHERE2\">LAST</field><value name=\"STRING\"><block type=\"variables_get\" id=\"@S?i8O{S=;P7b$4J::sp\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"AT1\"><block type=\"math_number\" id=\"@)t-J;cEnYs_-$9CLP!c\"><field name=\"NUM\">2</field></block></value></block></value></block></statement><next><block type=\"controls_if\" id=\"|!@53E@~Z~5Prk)S^$JJ\"><value name=\"IF0\"><block type=\"logic_compare\" id=\"*t/tA0Mfw?ddyac*0Fv5\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"text_charAt\" id=\"KQ?:{LT2aPn-rbd?uS-h\"><mutation at=\"false\"></mutation><field name=\"WHERE\">LAST</field><value name=\"VALUE\"><block type=\"variables_get\" id=\"Chy1ta2u|LVv`Amvc{@l\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value></block></value><value name=\"B\"><block type=\"text\" id=\"0kMv[heEgcW}`Z.5j+lr\"><field name=\"TEXT\">]</field></block></value></block></value><statement name=\"DO0\"><block type=\"variables_set\" id=\"?fhsb}acBq%{Zf1rQtfp\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_getSubstring\" id=\"^z%Dflr1)K1=HJF7**3X\"><mutation at1=\"false\" at2=\"true\"></mutation><field name=\"WHERE1\">FIRST</field><field name=\"WHERE2\">FROM_END</field><value name=\"STRING\"><block type=\"variables_get\" id=\"g,wc2-M{/!4ZCUM.~C`|\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"AT2\"><block type=\"math_number\" id=\"Y/bQQ.a*EM!h@~m~DKtD\"><field name=\"NUM\">2</field></block></value></block></value></block></statement><next><block type=\"node_object_set\" id=\"TtY/%g}HQ.thV[!)[)+?\" inline=\"true\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"M).kpUd-=P`$-@}AiR47\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"$8B#TMu?Jk,_S~VWy{2L\"><field name=\"TEXT\">payload</field></shadow></value><value name=\"value_field\"><shadow type=\"text\" id=\"l%C_@co}{eglIH!)%.D[\"><field name=\"TEXT\"></field></shadow><block type=\"variables_get\" id=\"`(1IxXS^hiy;uAiLtNRT\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><next><block type=\"node_return_message\" id=\"*bbcmWYcM1SuE^[3$)+_\"><field name=\"OUTPUT_NR\">1</field><value name=\"MESSAGE_INPUT\"><shadow type=\"node_msg\" id=\"SYNR|[0}wO3nN5A(,1yq\"></shadow></value></block></next></block></next></block></next></block></next></block></next></block></xml>","outputs":1,"name":"Remove []","x":270,"y":120,"wires":[["a5e69ff.edd716"]]},{"id":"51371cdd.fd36c4","type":"Blockly","z":"5394ff3.760ca","language":"en","func":"var message;\n\n\nmessage = (msg['payload']);\n// Use eval to process the message\nmessage = String(eval(message));\n// Re-package result to pass back to Scratch 3\nmessage = ['{\"result\":\"',message,'\"}'].join('');\nmsg['payload'] = message;\nreturn msg;\n","workspaceXml":"<xml xmlns=\"http://www.w3.org/1999/xhtml\"><variables><variable type=\"\" id=\"tRt)J6ju,#c{x[U1pP.I\">message</variable></variables><block type=\"variables_set\" id=\"1#8[z=8c+=_~=Q0ULr#K\" x=\"-712\" y=\"-262\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"node_object_get\" id=\"}Lha(ev5jipd*2wwf|9t\"><mutation action=\"GET\"></mutation><field name=\"action\">GET</field><value name=\"object\"><shadow type=\"node_msg\" id=\"?5)PeuSYW/w|6npl8soI\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"+?KfAUp_a6($,t/G+LYe\"><field name=\"TEXT\">payload</field></shadow></value></block></value><next><block type=\"misc_comment\" id=\"pL$%3)!S*F*h/uyFFWfL\"><value name=\"TEXT\"><shadow type=\"text\" id=\"KbV6=2]L9vIQ$,?|K(OU\"><field name=\"TEXT\">Use eval to process the message</field></shadow></value><next><block type=\"misc_javascript\" id=\"[:eX51yxUnbyhl7-cz$m\"><value name=\"STATEMENT\"><shadow type=\"text\" id=\"1t?Vp%SuQ@bN2~$M3J]L\"><field name=\"TEXT\">message = String(eval(message))</field></shadow></value><next><block type=\"misc_comment\" id=\"(]5Y3@2N/E%w#4UqgDI}\"><value name=\"TEXT\"><shadow type=\"text\" id=\"c|R*SbW396,l}$_7g9,~\"><field name=\"TEXT\">Re-package result to pass back to Scratch 3</field></shadow></value><next><block type=\"variables_set\" id=\"nRdt[H56mc#x$jb_m6tH\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_join\" id=\"{5aa^yGeaA}e#+mHhiEw\" inline=\"true\"><mutation items=\"3\"></mutation><value name=\"ADD0\"><block type=\"text\" id=\"g9y^B`=d6]Fq^D+n.{ts\"><field name=\"TEXT\">{\"result\":\"</field></block></value><value name=\"ADD1\"><block type=\"variables_get\" id=\"@7lQ*N}w.49T,9~Zbu*5\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"ADD2\"><block type=\"text\" id=\";XB3H60nOwE:#%=pC%@M\"><field name=\"TEXT\">\"}</field></block></value></block></value><next><block type=\"node_object_set\" id=\"TtY/%g}HQ.thV[!)[)+?\" inline=\"true\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"M).kpUd-=P`$-@}AiR47\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"$8B#TMu?Jk,_S~VWy{2L\"><field name=\"TEXT\">payload</field></shadow></value><value name=\"value_field\"><shadow type=\"text\" id=\"l%C_@co}{eglIH!)%.D[\"><field name=\"TEXT\"></field></shadow><block type=\"variables_get\" id=\"`(1IxXS^hiy;uAiLtNRT\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><next><block type=\"node_return_message\" id=\"*bbcmWYcM1SuE^[3$)+_\"><field name=\"OUTPUT_NR\">1</field><value name=\"MESSAGE_INPUT\"><shadow type=\"node_msg\" id=\"SYNR|[0}wO3nN5A(,1yq\"></shadow></value></block></next></block></next></block></next></block></next></block></next></block></next></block></xml>","outputs":1,"name":"eval","x":550,"y":220,"wires":[["55a1e66d.8692e8","8d7c059a.8e2108"]]},{"id":"a5e69ff.edd716","type":"switch","z":"5394ff3.760ca","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"cheerlights","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":410,"y":120,"wires":[["3ea65dbf.4db052"],["51371cdd.fd36c4"]]},{"id":"eef565ff.5f2468","type":"mqtt in","z":"5394ff3.760ca","name":"","topic":"cheerlights","qos":"2","broker":"bd8bd50e.f63368","x":80,"y":40,"wires":[["8b7bc4c.99aea38"]]},{"id":"8b7bc4c.99aea38","type":"change","z":"5394ff3.760ca","name":"","rules":[{"t":"set","p":"cheerlights","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":250,"y":40,"wires":[["ad2dd968.e28138"]]},{"id":"3ea65dbf.4db052","type":"Blockly","z":"5394ff3.760ca","language":"en","func":"var message;\n\n\nmessage = (flow.get('cheerlights'));\n// Re-package result to pass back to Scratch 3\nmessage = ['{\"result\":\"',message,'\"}'].join('');\nmsg['payload'] = message;\nreturn msg;\n","workspaceXml":"<xml xmlns=\"http://www.w3.org/1999/xhtml\"><variables><variable type=\"\" id=\"tRt)J6ju,#c{x[U1pP.I\">message</variable></variables><block type=\"variables_set\" id=\"1#8[z=8c+=_~=Q0ULr#K\" x=\"-837\" y=\"-287\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"node_object_get\" id=\"}Lha(ev5jipd*2wwf|9t\"><mutation action=\"GET\"></mutation><field name=\"action\">GET</field><value name=\"object\"><shadow type=\"node_msg\" id=\"?5)PeuSYW/w|6npl8soI\"></shadow><block type=\"node_flow_memory\" id=\"lp%_vwiG*]8hQFgITd)M\"></block></value><value name=\"field_name\"><shadow type=\"text\" id=\"+?KfAUp_a6($,t/G+LYe\"><field name=\"TEXT\">cheerlights</field></shadow></value></block></value><next><block type=\"misc_comment\" id=\"(]5Y3@2N/E%w#4UqgDI}\"><value name=\"TEXT\"><shadow type=\"text\" id=\"c|R*SbW396,l}$_7g9,~\"><field name=\"TEXT\">Re-package result to pass back to Scratch 3</field></shadow></value><next><block type=\"variables_set\" id=\"nRdt[H56mc#x$jb_m6tH\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_join\" id=\"{5aa^yGeaA}e#+mHhiEw\" inline=\"true\"><mutation items=\"3\"></mutation><value name=\"ADD0\"><block type=\"text\" id=\"g9y^B`=d6]Fq^D+n.{ts\"><field name=\"TEXT\">{\"result\":\"</field></block></value><value name=\"ADD1\"><block type=\"variables_get\" id=\"@7lQ*N}w.49T,9~Zbu*5\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><value name=\"ADD2\"><block type=\"text\" id=\";XB3H60nOwE:#%=pC%@M\"><field name=\"TEXT\">\"}</field></block></value></block></value><next><block type=\"node_object_set\" id=\"TtY/%g}HQ.thV[!)[)+?\" inline=\"true\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"M).kpUd-=P`$-@}AiR47\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"$8B#TMu?Jk,_S~VWy{2L\"><field name=\"TEXT\">payload</field></shadow></value><value name=\"value_field\"><shadow type=\"text\" id=\"l%C_@co}{eglIH!)%.D[\"><field name=\"TEXT\"></field></shadow><block type=\"variables_get\" id=\"`(1IxXS^hiy;uAiLtNRT\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><next><block type=\"node_return_message\" id=\"*bbcmWYcM1SuE^[3$)+_\"><field name=\"OUTPUT_NR\">1</field><value name=\"MESSAGE_INPUT\"><shadow type=\"node_msg\" id=\"SYNR|[0}wO3nN5A(,1yq\"></shadow></value></block></next></block></next></block></next></block></next></block></xml>","outputs":1,"name":"Cheerlights","x":570,"y":120,"wires":[["55a1e66d.8692e8","8d7c059a.8e2108"]]},{"id":"ad2dd968.e28138","type":"debug","z":"5394ff3.760ca","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","x":430,"y":40,"wires":[]},{"id":"bd8bd50e.f63368","type":"mqtt-broker","z":"","name":"simplesi.cloud","broker":"simplesi.cloud","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""}]
#7

Hi Simon,
I've not had any success with this.
My setup is...
Scratch-3 Offline editor running on Chrome on a PC.
Your NR flow running on a Raspberry Pi 3+ (running on the same wired network).
I've changed the settings in Redirector to http://192.168.1.140:1880/translate?language=en&text=%$1
I hope I should have a bit more time to devote to this today.
Cheers from David.

#8

aah - won't work :frowning:
The redirector won't re-direct the translate calls as they are not going thru the chrome browser - they are going straight out to T'internet from the encapsulated Scratch Desktop electron app

You need to be running Scratch 3 in the chrome browser

#9

If you REALLY need to use Scratch Desktop then your going to have to alter the Windows hosts file to re-direct ALL calls to translate-service.scratch.mit.edu to go to your Pi but that's a bit hard core :slight_smile:

(its what I did originally until I discovered the benefits of redirecting in the browser itself)

#10

Hi Simon,

Your enthousiasm is really contagiously. Just love it ...

FOR ALL OTHERS READING THIS: I had promised Simon to work together on the Blockly node this month. However I so much other stuff to do. So I would appreciate if you could post here that you love his new project, and ask him to add new functionality to it. Doesn't matter if it is ridiculous functionality, just keep him busy as long as possible!!
:rofl: :joy:

1 Like
#11

I thought I'd better check if this worked - and I can't get it to redirect from Scratch running in browser on Win 10 to my Pi - its works for manual requests typed into browser bar but the Scratch ones don't seems to be

looking at browser console - I't seems that not using at https endpoint issue has returned - investigating more

#12

I'm running Scratch 3 on the MIT website on Chrome on my Windows 7 PC.
It doesn't seem to work.

I'll wait to hear the results of your investigation.

Cheers from David.

#13

Getting this at moment

I originally had these sort of issues (been playing around using python webservers up until this projects) so I made my python webserver https and all worked - then started playing with NodeRED as server and it all worked without any https/ssl

So maybe its a "feature/bug" that if the webserver is on localhost - the browser decides not to block it if its not https

And down the rabbit hole we go again...............

#14

OK -managed to setup NodeRED as https server


So if you do those changes (don't forget to stick ca.key and ca.pem in /home/pi/.node-red) then it works again

You do have to accept my certs in a webbrowser session 1st so you need to kick the session into life by doing some like
https://192.168.0.189:1880/translate?test
(replace my address with your Pi one)

No where near as smooth and easy as doing it on one machine :slight_smile:

#15

BTW That also might be an issue - don't know as don't have access to any Win7 machines any more

#16

Alternative Approach:Double hop :slight_smile:

So if we run a NodeRED http server on main PC - it can forward the requests to/from the Pi NodeRED http server :slight_smile:

Adds a bit of extra delay in of course but maybe easier to use YMMV :slight_smile:

Flow to do the hop on main PC - just use orig flow on Pi

[{"id":"1836d5e.05e912a","type":"http in","z":"b6ca4ac3.e99258","name":"","url":"/translate","method":"get","upload":false,"swaggerDoc":"","x":130,"y":80,"wires":[["ef634694.e7dcd8","2a2d6511.96aaaa"]]},{"id":"3b414718.d534f8","type":"http response","z":"b6ca4ac3.e99258","name":"","statusCode":"","headers":{"Access-Control-Allow-Origin":"*"},"x":930,"y":80,"wires":[]},{"id":"9ffc4ddc.74373","type":"http request","z":"b6ca4ac3.e99258","name":"","method":"GET","ret":"txt","url":"","tls":"","x":590,"y":80,"wires":[["3f83ba0d.070c36","3b414718.d534f8","e129c3db.d30b9"]]},{"id":"ef634694.e7dcd8","type":"Blockly","z":"b6ca4ac3.e99258","language":"en","func":"var message;\n\n\nnode.status({fill:\"blue\", shape:\"ring\", text:(msg['req']['url'])});\nmessage = String('http://192.168.0.189:1880') + String(msg['req']['url']);\nmsg['url'] = message;\nreturn msg;\n","workspaceXml":"<xml xmlns=\"http://www.w3.org/1999/xhtml\"><variables><variable type=\"\" id=\"tRt)J6ju,#c{x[U1pP.I\">message</variable></variables><block type=\"node_status\" id=\"qsi}ds]f`Nk2GKp4]3hn\" x=\"-1412\" y=\"-13\"><field name=\"COLOUR\">#0000FF</field><field name=\"SHAPE\">RING</field><value name=\"TEXT_INPUT\"><shadow type=\"text\" id=\"12lwme0K)`2%?rKFoGgh\"><field name=\"TEXT\"></field></shadow><block type=\"node_object_get\" id=\"b;YZ0w4oG4jm{9*EAc;s\"><mutation action=\"GET\"></mutation><field name=\"action\">GET</field><value name=\"object\"><shadow type=\"node_msg\" id=\"Tx14`n)^-L(g9]f;hSt*\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"~gY/Q:px/}g=cn+Q7HC;\"><field name=\"TEXT\">req.url</field></shadow></value></block></value><next><block type=\"variables_set\" id=\"1#8[z=8c+=_~=Q0ULr#K\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field><value name=\"VALUE\"><block type=\"text_join\" id=\"`LKof`F[j`{xS.[HcEO#\"><mutation items=\"2\"></mutation><value name=\"ADD0\"><block type=\"text\" id=\"sBu/m+!*,,-(bxwF2o!s\"><field name=\"TEXT\">http://192.168.0.189:1880</field></block></value><value name=\"ADD1\"><block type=\"node_object_get\" id=\"}Lha(ev5jipd*2wwf|9t\"><mutation action=\"GET\"></mutation><field name=\"action\">GET</field><value name=\"object\"><shadow type=\"node_msg\" id=\"?5)PeuSYW/w|6npl8soI\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"+?KfAUp_a6($,t/G+LYe\"><field name=\"TEXT\">req.url</field></shadow></value></block></value></block></value><next><block type=\"node_object_set\" id=\"TtY/%g}HQ.thV[!)[)+?\" inline=\"true\"><value name=\"object_field\"><shadow type=\"node_msg\" id=\"M).kpUd-=P`$-@}AiR47\"></shadow></value><value name=\"field_name\"><shadow type=\"text\" id=\"$8B#TMu?Jk,_S~VWy{2L\"><field name=\"TEXT\">url</field></shadow></value><value name=\"value_field\"><shadow type=\"text\" id=\"l%C_@co}{eglIH!)%.D[\"><field name=\"TEXT\"></field></shadow><block type=\"variables_get\" id=\"`(1IxXS^hiy;uAiLtNRT\"><field name=\"VAR\" id=\"tRt)J6ju,#c{x[U1pP.I\" variabletype=\"\">message</field></block></value><next><block type=\"node_return_message\" id=\"*bbcmWYcM1SuE^[3$)+_\"><field name=\"OUTPUT_NR\">1</field><value name=\"MESSAGE_INPUT\"><shadow type=\"node_msg\" id=\"SYNR|[0}wO3nN5A(,1yq\"></shadow></value></block></next></block></next></block></next></block></xml>","outputs":1,"name":"","x":340,"y":80,"wires":[["9ffc4ddc.74373"]]}]

If you don't want/can#t run NodeRED on main PC it wouldn't be too hard to make a standalone python version I wouldn't have thought :slight_smile:

#17

That's a very nice hack !! Thanks for sharing.

1 Like