Search on webpage and retrieve data

Hi all.

I'm looking to draw out information from my local council page, specifically bin collection data. Unfortunately to get that data requires a postcode to be entered before any of the data shows up.

I've got a basic flow set up which would be able to retrieve the data, using Inject ---> http request to the URL--->html parser to get the right element from the page--->debug

My issue is getting the flow to automatically insert a postcode, search it and then grab that info.

This is the council page - Check my collection dates if you want to test it with a postcode, CF5 1QR (not mine) will work.

Any help on the above would be massively appreciated. If I haven't explained myself correctly, let me know - I have no idea what I'm doing truth be told! :laughing:

Thank you

If you go to that page, and open the browser's Inspect (or dev console) panel, you can see this URL is being called with your query inputs: https://api.cardiff.gov.uk/Location/api/AddressSearch

If you put that into an http request node, and figure out what data you need to send to it, you should get the next page of information back. Unfortunately, it looks like an intermediate page that requires you to enter an actual house address -- but you can use the same technique to find the next page's URL + inputs, and so on... at some point you should be able to just skip all of those intermediate pages and push your info straight into the final page and get your schedule info.

Parsing the target information out of an html page is usually not trivial, so hopefully the data you need will be returned in application/json format -- perfect for passing to the rest of your flows.

1 Like

If you check your browsers developer tools network tab, you'll see that the browser first makes some sort of authentication request to get a JWT access token.
then it makes the actual request to get the json data.

You can emulate the whole request process with a flow like the example below :

[{"id":"1c44140cb8acf2cb","type":"inject","z":"5847b7aa62131d37","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":160,"y":640,"wires":[["6da13aa2886382d1"]]},{"id":"b7762aa66de6a566","type":"http request","z":"5847b7aa62131d37","name":"auth req","method":"POST","ret":"txt","paytoqs":"body","url":"https://authwebservice.cardiff.gov.uk/AuthenticationWebService.asmx?op=GetJW","tls":"","persist":true,"proxy":"","authType":"","senderr":false,"x":400,"y":700,"wires":[["682b5c419c834422"]]},{"id":"33fc229af1bd9858","type":"debug","z":"5847b7aa62131d37","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":630,"y":780,"wires":[]},{"id":"6da13aa2886382d1","type":"function","z":"5847b7aa62131d37","name":"","func":"msg.headers = {\n    \"Content-Length\": \"284\",\n    \"Accept-Encoding\": \"gzip, deflate, br\",\n    \"Referer\": \"https://www.cardiff.gov.uk/\",\n    \"Origin\": \"https://www.cardiff.gov.uk\",\n    \"Content-Type\": `text/xml; charset=\"utf-8\"`,\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"no-cors\",\n    \"Sec-Fetch-Site\": \"same-site\",\n    \"Pragma\": \"no-cache\",\n    \"Cache-Control\": \"no-cache\"\n}\n\nmsg.payload = `<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><GetJWT xmlns='http://tempuri.org/' /></soap:Body></soap:Envelope>`\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":700,"wires":[["b7762aa66de6a566"]]},{"id":"682b5c419c834422","type":"xml","z":"5847b7aa62131d37","name":"","property":"payload","attr":"","chr":"","x":530,"y":700,"wires":[["24b162b725bfb0a2"]]},{"id":"24b162b725bfb0a2","type":"function","z":"5847b7aa62131d37","name":"","func":"let access_token = JSON.parse(msg.payload[\"soap:Envelope\"][\"soap:Body\"][0].GetJWTResponse[0].GetJWTResult).access_token\n\nmsg.payload = {\n    \"systemReference\": \"web\",\n    \"language\": \"eng\",\n    \"uprn\": 100100073989  // code for address ?? you need to find it from browser\n}\n\nmsg.headers = {\n    \"Authorization\": `Bearer ${access_token}`\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":780,"wires":[["b091cd6df0893112"]]},{"id":"b091cd6df0893112","type":"http request","z":"5847b7aa62131d37","name":"WasteCollection req","method":"POST","ret":"obj","paytoqs":"body","url":"https://api.cardiff.gov.uk/WasteManagement/api/WasteCollection","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":440,"y":780,"wires":[["33fc229af1bd9858"]]}]

The data is in msg.payload.collectionWeeks

One small problem is that you have to make a request of your real postcode and address (from the browser) and see in its dev tools the uprn code. Use that in the Function node to get the correct data relating to your address.

image

1 Like

UnborN, you are an absolute hero. It works!

Thank you! :grinning:

1 Like

Thanks Shrickus! Big big help! Should be able to get this up and running now with this.

The flow returns the data perfectly, however in the next step I'm trying to draw out the information to just show a single line variable with a colour. The initial function provides an array in the following format:

msg : Object
object
payload: object
lanugage: "eng"
collectionWeeks: array[4]
0: object
week: 1
date: "2021-10-19T00:00:00"
day: "Tuesday"
bins: array[1]
0: object
binId: "25 Food Caddy"
imageUrl: "https://www.cardiff.gov.uk/ENG/resident/Rubbish-and-recycling/When-are-my-bins-collected/PublishingImages/20.png"
type: "Food"
collectionType: "Standard"
1: object
2: object
3: object
hasGlassBin: false

and its the 'Type' value that I'm trying to modify and use. I've copied the path for it and used it in the function below.


for(var i = 0; i < msg.payload.collectionWeeks.bins.type.length; i++) {
    
    var binName1 = msg.payload.collectionWeeks[0].bins[0].type[i];
    
    if(binName1 === 'General'){
        binName1 = 'white';
    } else if(binName1 === 'Food'){
        binName1 = 'blue' ;
    } else if(binName1 === 'Garden'){
        binName1 = 'green';
    }
    
    msg.payload[i] = binName1;
}

return msg;



The debug returns the following error - "TypeError: Cannot read property 'type' of undefined"

I'm assuming I've tried to call on the Type value incorrectly in the msg.payload lines?

Thanks

Hello Mike ..

This additional Function ("add bin Colors") will add for each collectionWeek and for each bin for that week a color property based on the type of the bin.

Is this a suitable format for the data ?

image

Flow :

[{"id":"1c44140cb8acf2cb","type":"inject","z":"5847b7aa62131d37","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":200,"y":500,"wires":[["6da13aa2886382d1"]]},{"id":"b7762aa66de6a566","type":"http request","z":"5847b7aa62131d37","name":"auth req","method":"POST","ret":"txt","paytoqs":"body","url":"https://authwebservice.cardiff.gov.uk/AuthenticationWebService.asmx?op=GetJW","tls":"","persist":true,"proxy":"","authType":"","senderr":false,"x":440,"y":560,"wires":[["682b5c419c834422"]]},{"id":"33fc229af1bd9858","type":"debug","z":"5847b7aa62131d37","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":890,"y":640,"wires":[]},{"id":"6da13aa2886382d1","type":"function","z":"5847b7aa62131d37","name":"","func":"msg.headers = {\n    \"Content-Length\": \"284\",\n    \"Accept-Encoding\": \"gzip, deflate, br\",\n    \"Referer\": \"https://www.cardiff.gov.uk/\",\n    \"Origin\": \"https://www.cardiff.gov.uk\",\n    \"Content-Type\": `text/xml; charset=\"utf-8\"`,\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"no-cors\",\n    \"Sec-Fetch-Site\": \"same-site\",\n    \"Pragma\": \"no-cache\",\n    \"Cache-Control\": \"no-cache\"\n}\n\nmsg.payload = `<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><GetJWT xmlns='http://tempuri.org/' /></soap:Body></soap:Envelope>`\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":560,"wires":[["b7762aa66de6a566"]]},{"id":"682b5c419c834422","type":"xml","z":"5847b7aa62131d37","name":"","property":"payload","attr":"","chr":"","x":570,"y":560,"wires":[["24b162b725bfb0a2"]]},{"id":"24b162b725bfb0a2","type":"function","z":"5847b7aa62131d37","name":"","func":"let access_token = JSON.parse(msg.payload[\"soap:Envelope\"][\"soap:Body\"][0].GetJWTResponse[0].GetJWTResult).access_token\n\nmsg.payload = {\n    \"systemReference\": \"web\",\n    \"language\": \"eng\",\n    \"uprn\": 100100073989  // code for address ?? you need to find it from browser\n}\n\nmsg.headers = {\n    \"Authorization\": `Bearer ${access_token}`\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":640,"wires":[["b091cd6df0893112"]]},{"id":"b091cd6df0893112","type":"http request","z":"5847b7aa62131d37","name":"WasteCollection req","method":"POST","ret":"obj","paytoqs":"body","url":"https://api.cardiff.gov.uk/WasteManagement/api/WasteCollection","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":480,"y":640,"wires":[["13bedea79c85a923"]]},{"id":"13bedea79c85a923","type":"function","z":"5847b7aa62131d37","name":"add bin Colors","func":"let weeks = msg.payload.collectionWeeks;\n\n\nweeks.forEach(week => {\n    week.bins.forEach(bin => {\n        if (bin.type === \"General\") { bin.color = \"white\" }\n        else if (bin.type === \"Food\") { bin.color = \"blue\" }\n        else if (bin.type === \"Garden\") { bin.color = \"green\" }\n        else { bin.color = \"none\" }\n    })\n});\n\nmsg.payload = weeks;\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":720,"y":640,"wires":[["33fc229af1bd9858"]]}]

Is it possible to then draw out that colour or type value to then use it in other functions?

Copying the path for the type of the first bin gives payload.collectionWeeks[0].bins[0].type, which I'm guessing identifies where it sits in the resultant array. However it gives an error when using this path when trying to essentially say:

new variable = payload.collectionWeeks[0].bins[0].type

If new variable = food then new variable = blue

The end goal is that I want to be able to post the colour to a webpage to be able to view by other devices.

[{"id":"27f0628ce2b73c52","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"38b3fec2fa415e98","type":"debug","z":"27f0628ce2b73c52","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":970,"y":260,"wires":[]},{"id":"b07ee27e4184ed20","type":"function","z":"27f0628ce2b73c52","name":"add bin Colors","func":"let weeks = msg.payload.collectionWeeks;\n\n\nweeks.forEach(week => {\n    week.bins.forEach(bin => {\n        if (bin.type === \"General\") { bin.colour = \"white\" }\n        if (bin.type === \"Food\") { bin.colour = \"blue\" }\n        if (bin.type === \"Garden\") { bin.colour = \"green\" }\n    })\n});\n\nmsg.payload = weeks;\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":320,"wires":[["38b3fec2fa415e98","8a3373dc55e9a981"]]},{"id":"1c44140cb8acf2cb","type":"inject","z":"27f0628ce2b73c52","name":"","props":[{"p":"payload"}],"repeat":"72000","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":170,"y":120,"wires":[["6da13aa2886382d1"]]},{"id":"b7762aa66de6a566","type":"http request","z":"27f0628ce2b73c52","name":"auth req","method":"POST","ret":"txt","paytoqs":"body","url":"https://authwebservice.cardiff.gov.uk/AuthenticationWebService.asmx?op=GetJW","tls":"","persist":true,"proxy":"","authType":"","x":400,"y":180,"wires":[["682b5c419c834422"]]},{"id":"6da13aa2886382d1","type":"function","z":"27f0628ce2b73c52","name":"","func":"msg.headers = {\n    \"Content-Length\": \"284\",\n    \"Accept-Encoding\": \"gzip, deflate, br\",\n    \"Referer\": \"https://www.cardiff.gov.uk/\",\n    \"Origin\": \"https://www.cardiff.gov.uk\",\n    \"Content-Type\": `text/xml; charset=\"utf-8\"`,\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"no-cors\",\n    \"Sec-Fetch-Site\": \"same-site\",\n    \"Pragma\": \"no-cache\",\n    \"Cache-Control\": \"no-cache\"\n}\n\nmsg.payload = `<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><GetJWT xmlns='http://tempuri.org/' /></soap:Body></soap:Envelope>`\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":180,"wires":[["b7762aa66de6a566"]]},{"id":"682b5c419c834422","type":"xml","z":"27f0628ce2b73c52","name":"","property":"payload","attr":"","chr":"","x":530,"y":180,"wires":[["24b162b725bfb0a2"]]},{"id":"24b162b725bfb0a2","type":"function","z":"27f0628ce2b73c52","name":"","func":"let access_token = JSON.parse(msg.payload[\"soap:Envelope\"][\"soap:Body\"][0].GetJWTResponse[0].GetJWTResult).access_token\n\nmsg.payload = {\n    \"systemReference\": \"web\",\n    \"language\": \"eng\",\n    \"uprn\": 10094241834  // code for address ?? you need to find it from browser\n}\n\nmsg.headers = {\n    \"Authorization\": `Bearer ${access_token}`\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":260,"wires":[["b091cd6df0893112"]]},{"id":"b091cd6df0893112","type":"http request","z":"27f0628ce2b73c52","name":"WasteCollection req","method":"POST","ret":"obj","paytoqs":"body","url":"https://api.cardiff.gov.uk/WasteManagement/api/WasteCollection","tls":"","persist":false,"proxy":"","authType":"","x":440,"y":260,"wires":[["b07ee27e4184ed20","2c5279c597838494"]]},{"id":"2c5279c597838494","type":"debug","z":"27f0628ce2b73c52","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":140,"wires":[]},{"id":"8a3373dc55e9a981","type":"function","z":"27f0628ce2b73c52","name":"SaveToGlobal","func":"global.set('bincolour',msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":960,"y":400,"wires":[[]]},{"id":"8980c46f8934c893","type":"http in","z":"27f0628ce2b73c52","name":"mybin","url":"/mybin","method":"get","upload":false,"swaggerDoc":"","x":160,"y":440,"wires":[["2ff426b235e5a3f3"]]},{"id":"2ff426b235e5a3f3","type":"function","z":"27f0628ce2b73c52","name":"getFromGlobal","func":"var newMsg = RED.util.clonemessage(msg);\nnewMsg.payload = JSON.stringify(global.get('bincolour')).replace(/\\\"/g\", \"\");\nreturn msg;","outputs":1,"noerr":6,"initialize":"","finalize":"","libs":[],"x":370,"y":440,"wires":[["6fec5ac8175e8819"]]},{"id":"6fec5ac8175e8819","type":"template","z":"27f0628ce2b73c52","name":"DisplayOnPage","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{payload}}","output":"str","x":590,"y":440,"wires":[["5e9586894bbb69e5"]]},{"id":"5e9586894bbb69e5","type":"http response","z":"27f0628ce2b73c52","name":"success","statusCode":"200","headers":{},"x":830,"y":480,"wires":[]}]

This is where I'm at, I just need to be able to take that colour variable and then post to that page.

Any thoughts?

it needs to be msg.payload.collectionWeeks[0].bins[0].type

First you need to clarify what data you want to send to the other devices.
When you say "post the colour" ... which colour ? every week (array of 4) has nested bins arrays each with a seperate colour.

or you want to send the whole data as JSON and let the device read it as it needs

[{"id":"c0af06dc356ef4d9","type":"debug","z":"670e449e482aa4bb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":970,"y":260,"wires":[]},{"id":"5dbec895b23ecad5","type":"function","z":"670e449e482aa4bb","name":"add bin Colors","func":"let weeks = msg.payload.collectionWeeks;\n\n\nweeks.forEach(week => {\n    week.bins.forEach(bin => {\n        if (bin.type === \"General\") { bin.colour = \"white\" }\n        if (bin.type === \"Food\") { bin.colour = \"blue\" }\n        if (bin.type === \"Garden\") { bin.colour = \"green\" }\n    })\n});\n\nmsg.payload = weeks;\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":320,"wires":[["c0af06dc356ef4d9","8711e985586cb9d8"]]},{"id":"5101f305bc459755","type":"inject","z":"670e449e482aa4bb","name":"","props":[{"p":"payload"}],"repeat":"72000","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":170,"y":120,"wires":[["6adcf5b8d460ea03"]]},{"id":"a5c4a65e3a54b2f8","type":"http request","z":"670e449e482aa4bb","name":"auth req","method":"POST","ret":"txt","paytoqs":"body","url":"https://authwebservice.cardiff.gov.uk/AuthenticationWebService.asmx?op=GetJW","tls":"","persist":true,"proxy":"","authType":"","x":400,"y":180,"wires":[["8c1f12d8f1590f10"]]},{"id":"6adcf5b8d460ea03","type":"function","z":"670e449e482aa4bb","name":"","func":"msg.headers = {\n    \"Content-Length\": \"284\",\n    \"Accept-Encoding\": \"gzip, deflate, br\",\n    \"Referer\": \"https://www.cardiff.gov.uk/\",\n    \"Origin\": \"https://www.cardiff.gov.uk\",\n    \"Content-Type\": `text/xml; charset=\"utf-8\"`,\n    \"Sec-Fetch-Dest\": \"empty\",\n    \"Sec-Fetch-Mode\": \"no-cors\",\n    \"Sec-Fetch-Site\": \"same-site\",\n    \"Pragma\": \"no-cache\",\n    \"Cache-Control\": \"no-cache\"\n}\n\nmsg.payload = `<?xml version='1.0' encoding='utf-8'?><soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><GetJWT xmlns='http://tempuri.org/' /></soap:Body></soap:Envelope>`\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":180,"wires":[["a5c4a65e3a54b2f8"]]},{"id":"8c1f12d8f1590f10","type":"xml","z":"670e449e482aa4bb","name":"","property":"payload","attr":"","chr":"","x":530,"y":180,"wires":[["7078b53f47d7595b"]]},{"id":"7078b53f47d7595b","type":"function","z":"670e449e482aa4bb","name":"","func":"let access_token = JSON.parse(msg.payload[\"soap:Envelope\"][\"soap:Body\"][0].GetJWTResponse[0].GetJWTResult).access_token\n\nmsg.payload = {\n    \"systemReference\": \"web\",\n    \"language\": \"eng\",\n    \"uprn\": 10094241834  // code for address ?? you need to find it from browser\n}\n\nmsg.headers = {\n    \"Authorization\": `Bearer ${access_token}`\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":260,"wires":[["bace54a7a9461362"]]},{"id":"bace54a7a9461362","type":"http request","z":"670e449e482aa4bb","name":"WasteCollection req","method":"POST","ret":"obj","paytoqs":"body","url":"https://api.cardiff.gov.uk/WasteManagement/api/WasteCollection","tls":"","persist":false,"proxy":"","authType":"","x":440,"y":260,"wires":[["5dbec895b23ecad5","ffd502144bc637db"]]},{"id":"ffd502144bc637db","type":"debug","z":"670e449e482aa4bb","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":140,"wires":[]},{"id":"8711e985586cb9d8","type":"function","z":"670e449e482aa4bb","name":"SaveToGlobal","func":"global.set('bincolour', msg.payload);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":960,"y":400,"wires":[[]]},{"id":"eaf43c07ec9fb718","type":"http in","z":"670e449e482aa4bb","name":"mybin","url":"/mybin","method":"get","upload":false,"swaggerDoc":"","x":160,"y":440,"wires":[["b6ac3483fd5bae4e"]]},{"id":"b6ac3483fd5bae4e","type":"function","z":"670e449e482aa4bb","name":"getFromGlobal","func":"//var newMsg = RED.util.cloneMessage(msg);\n//msg.payload = JSON.stringify(global.get('bincolour')).replace(\"/\\\"/g\", \"\");\nmsg.payload = global.get(\"bincolour\")\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":370,"y":440,"wires":[["d36ea6de71435558"]]},{"id":"d36ea6de71435558","type":"http response","z":"670e449e482aa4bb","name":"success","statusCode":"200","headers":{},"x":560,"y":440,"wires":[]}]

[EDIT]
If you only want to sent with your /mybin endpoint, only the data that is closest to today's date
then in "getFromGlobal" function

msg.payload = global.get("bincolour")[0]
return msg;

The only bit of info I want to send is the colour of the next bin coming up, and if there is more than one bin, the colour of that one as well. In an ideal world, it would just say:

"Blue
Green"

or whatever colours it is for that week. So it would need to be object 0, bin 0, color + (if it exists that particular week) object 0, bin 1, color.

luckily the data has the closest collection in the first element [0] of the array.
so if we do another forEach loop on the bins array of the 1st week we can pick up the colours.

getFromGlobal Function

let data = global.get("bincolour")
let colours = []

// get colours for first week 
data[0].bins.forEach(bin => colours.push(bin.colour) )

msg.payload = colours  //or   msg.payload = colours.join(" ")

return msg;