Interpretation of a QR Code

Hi all !

I'm starting with Node RED and discovering this amazing world !
I work in the industry and will use node red for data acquisition in a product tracability subject.

My subject today is the following :

I will install a camera made to scan QR Codes. This camera is connected to a device running Node RED.
I need some help to create the flow to interpret the message that will be send by the camera.

Here is the structure of the message in my QR Code :
ProductName_ProductFormat_ProductDimension_Component_BatchNumber_SubBatchNumber-ProductNumber1_ProductNumber2_..._ProductNumberN

Example :
HARDCOVER_LANDSCAPE_H21_INNER_074_241UCNE9- A0000012492554_A0000012492555_..._A0000012492565

Another one :
SOFTCOVER_PORTRAIT_H28_COVER_085_852NNE5-A0000013492896_A0000013492875_...

The number of products is not fixed (that's why I putted N products).

What I would like to get in output is :
First message :
ProductName = HARDCOVER
ProductFormat = LANDSCAPE
ProductDimension = H21
Component = INNER
BatchNumber = 074
SubBatchNumber = 241UCNE9
ProductNumber = A0000012492554

N message :
ProductName = HARDCOVER
ProductFormat = LANDSCAPE
ProductDimension = H21
Component = INNER
BatchNumber = 074
SubBatchNumber = 241UCNE9
ProductNumber = A0000012492565

I would like to get a message every 0.5 secondes.

My final goal is to transfer these messages via the API of my software and store the datas in a Table :

ProductName ProductFormat ProductDimension Component BatchNumber SubBatchNumber ProductNumber
HARDCOVER LANDSCAPE H21 INNER 74 241UCNE9 A0000012492554
HARDCOVER LANDSCAPE H21 INNER 74 241UCNE9 A0000012492555
… … … … … … …
HARDCOVER LANDSCAPE H21 INNER 74 241UCNE9 A0000012492565

My goal is to use as less code as possible and to try to use the Low Code force of Node RED.

I hope everything I said is clear...
Thanks a lot for your tips !

Apologies, I did not notice you said a QR code may have more than one ProductNumber

The split command in a function node should do the job

let qrtext = "HARDCOVER_LANDSCAPE_H21_INNER_074_241UCNE9- A0000012492554_A0000012492555_..._A0000012492565";
msg.payload = qrtext.split("_");

assuming msg.payload to be something like
HARDCOVER_LANDSCAPE_H21_INNER_074_241UCNE9A0000012492554_A0000012492555_..._A0000012492565

You could use a csv node, set the separator to other: _

Specify the column names; ProductName,ProductFormat,ProductDimension,Component,BatchNumber,SubBatchNumber,ProductNumber

and you get an object that you can sent to an api (depending on what it is expecting ofcourse).

Passing the string through a change node with the JSONata expression

(
    $parts := $split($$.payload, "-");
    $temp := $split($parts[0], "_");
    $split($parts[1], "_").{
        "ProductName": $temp[0],
        "ProductFormat": $temp[1],
        "ProductDimension": $temp[2],
        "Component": $temp[3],
        "_BatchNumber": $temp[4],
        "SubBatchNumber": $temp[5],
        "ProductNumber": $
    }
)

will produce an array of objects
e.g.

[
    {
        "ProductName": "HARDCOVER",
        "ProductFormat": "LANDSCAPE",
        "ProductDimension": "H21",
        "Component": "INNER",
        "BatchNumber": "074",
        "SubBatchNumber": "241UCNE9",
        "ProductNumber": " A0000012492554"
    },
    {
        "ProductName": "HARDCOVER",
        "ProductFormat": "LANDSCAPE",
        "ProductDimension": "H21",
        "Component": "INNER",
        "BatchNumber": "074",
        "SubBatchNumber": "241UCNE9",
        "ProductNumber": "A0000012492555"
    },
    {
        "ProductName": "HARDCOVER",
        "ProductFormat": "LANDSCAPE",
        "ProductDimension": "H21",
        "Component": "INNER",
        "BatchNumber": "074",
        "SubBatchNumber": "241UCNE9",
        "ProductNumber": "A0000012492565"
    }
]

which you can the split and rate limit.

example flow

[{"id":"19ead9e2436a8834","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"HARDCOVER_LANDSCAPE_H21_INNER_074_241UCNE9- A0000012492554_A0000012492555_A0000012492565","payloadType":"str","x":130,"y":4780,"wires":[["989b3b0e0caa2c69"]]},{"id":"0875332341da5d2b","type":"debug","z":"d1395164b4eec73e","name":"debug 2557","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":510,"y":4720,"wires":[]},{"id":"989b3b0e0caa2c69","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"(\t    $parts := $split($$.payload, \"-\");\t    $temp := $split($parts[0], \"_\");\t    $split($parts[1], \"_\").{\t        \"ProductName\": $temp[0],\t        \"ProductFormat\": $temp[1],\t        \"ProductDimension\": $temp[2],\t        \"Component\": $temp[3],\t        \"_BatchNumber\": $temp[4],\t        \"SubBatchNumber\": $temp[5],\t        \"ProductNumber\": $\t    }\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":4780,"wires":[["0875332341da5d2b","217d3c59d0dc6922"]]},{"id":"217d3c59d0dc6922","type":"split","z":"d1395164b4eec73e","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":490,"y":4780,"wires":[["474273521cec5219"]]},{"id":"ac0de4b31034ea31","type":"debug","z":"d1395164b4eec73e","name":"debug 2558","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":530,"y":4840,"wires":[]},{"id":"474273521cec5219","type":"delay","z":"d1395164b4eec73e","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"2","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":630,"y":4780,"wires":[["ac0de4b31034ea31"]]}]

Sometimes, a function with code is the right answer. In this case, you have a highly proprietary format of data that you need to reuse portion of to generate table rows.

Had this data been stored in an easily parse-able format (like JSON or XML) then it might have been different.

Dont get me wrong, it IS possible in low code but it will not be pretty nor super readable.

Look maa, no-code, no JS, no JSONata

[{"id":"5aa40c0210472df1","type":"template","z":"c37c71daed7c269d","name":"data","field":"payload","fieldType":"msg","format":"text","syntax":"plain","template":"HARDCOVER_LANDSCAPE_H21_INNER_074_241UCNE9-A0000012492554_A0000012492555_A0000012492565","output":"str","x":510,"y":1900,"wires":[["c38e9e43b6852505"]]},{"id":"240693f2c4adc3f0","type":"inject","z":"c37c71daed7c269d","name":"","repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":360,"y":1900,"wires":[["5aa40c0210472df1"]]},{"id":"c38e9e43b6852505","type":"split","z":"c37c71daed7c269d","name":"split fixed data / part nos","splt":"-","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":710,"y":1900,"wires":[["8eafcd416ea7e4bb"]]},{"id":"8eafcd416ea7e4bb","type":"join","z":"c37c71daed7c269d","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":",","joinerType":"str","accumulate":false,"timeout":"","count":"2","reduceRight":false,"reduceExp":"$append($A,[{\t  \"name\": payload,\t  \"index\": $I\t}])","reduceInit":"[]","reduceInitType":"json","reduceFixup":"","x":910,"y":1900,"wires":[["aee5de86886bd5d6","e1e6b10dbdd03484"]]},{"id":"aee5de86886bd5d6","type":"debug","z":"c37c71daed7c269d","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1090,"y":1900,"wires":[]},{"id":"e1e6b10dbdd03484","type":"change","z":"c37c71daed7c269d","name":"","rules":[{"t":"set","p":"fixed","pt":"msg","to":"payload[0]","tot":"msg"},{"t":"set","p":"partNos","pt":"msg","to":"payload[1]","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"fixed","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":1980,"wires":[["31e92a43546e5ff1"]]},{"id":"31e92a43546e5ff1","type":"csv","z":"c37c71daed7c269d","name":"parse fixed part","sep":"_","hdrin":"","hdrout":"none","multi":"one","ret":"\\n","temp":"ProductName,ProductFormat,ProductDimension,Component,BatchNumber,SubBatchNumber,ProductNumber","skip":"0","strings":true,"include_empty_strings":"","include_null_values":"","x":590,"y":1980,"wires":[["0daee601b38ce9aa"]]},{"id":"0daee601b38ce9aa","type":"change","z":"c37c71daed7c269d","name":"move fixed part to fixedValues","rules":[{"t":"set","p":"fixedValues","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"partNos","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":830,"y":1980,"wires":[["4df33c1bf7d858f2","59e18245f3a6b23a"]]},{"id":"4df33c1bf7d858f2","type":"debug","z":"c37c71daed7c269d","name":"debug 7","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1080,"y":1980,"wires":[]},{"id":"59e18245f3a6b23a","type":"split","z":"c37c71daed7c269d","name":"split fixed data / part nos","splt":"_","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":430,"y":2060,"wires":[["6adb6e4ad2cd9846"]]},{"id":"e4599ef1c3157c4f","type":"debug","z":"c37c71daed7c269d","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1080,"y":2060,"wires":[]},{"id":"6adb6e4ad2cd9846","type":"change","z":"c37c71daed7c269d","name":"make final object","rules":[{"t":"set","p":"thisRow","pt":"msg","to":"fixedValues","tot":"msg","dc":true},{"t":"set","p":"thisRow.ProductNumber","pt":"msg","to":"payload","tot":"msg"},{"t":"move","p":"thisRow","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":2060,"wires":[["e4599ef1c3157c4f"]]}]
1 Like

Hi everyone !

Thanks a lot for all your help ! I managed to do what I wanted.

I know that coding is sometime the right answer but Low Code is easier to understand when you don't know (yet) JavaScript.

Would you care to share your solution?

I used the solution given by @Steve-Mcl and it works perfectly !

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.