This repository is developed in Fish-IoT project
https://www.tequ.fi/en/project-bank/fish-iot/
This repository is developed with fresh Jetpack 5.0.2 and Jetson AGX Orin Developer Kit. Example flows should work with any Basler camera and can easily be modified to work with multiple cameras. Basic support for v4l2 video sources is also available. This is developed and tested with Logitech C920 USB camera.
Other tested machines:
- Neousys NRU-120S, Jetson AGX Xavier with Jetpack 4.6.1
- Dell Precision 7560, Windows 10
Please first configure your Jetson setup using following repositiories:
- Basic configuration for Jetson: https://github.com/Lapland-UAS-Tequ/tequ-jetson-setup
- Triton Inference Server configuration: https://github.com/Lapland-UAS-Tequ/tequ-setup-triton-inference-server
- Basler Camera configuration: https://github.com/Lapland-UAS-Tequ/tequ-jetson-basler
- Windows 10 configuration: https://github.com/Lapland-UAS-Tequ/win10-nodered-tensorflow
- Starts local RTSP-server to serve encoded camera stream
- Starts multiple GStreamer instances that connects to Basler cameras using its serial number and predefined configuration files
- Starts GStreamer instances that connects to Logitech USB camera using v4l2_device video source (/dev/video0)
- GStreamer reads camera video stream and publishes encoded H264/H265 video stream to RTSP server and JPEG stream to local TCP port
- Node-RED application is used to
- Manage GStreamer instances
- Manage Triton Inference Server Dockers
- Receive and process JPEG image streams from GStreamer
- Serve MJPEG streams in local network
- Convert image to tensor
- Send tensor to local or remote Triton Inference Server for object detection using "ssd-example-model" that detects common things
- Post-process Triton Inference Server response
- Annotate detected objects to images
- Formats and sends annotated images to Tequ-API based on object detection threshold
Real time video streams will be available in following addresses:
-
rtsp://IP:8554/CAMERA_SERIAL_NUMBER
You can disable functionality
- Disable "Inference" flow if you dont want to run inference
- Disable "Triton" flow if you dont need Triton docker on this machine
- Disable "Tequ-API" flow if you need to send images to Tequ-API
cd ~/.node-red
npm install node-red-contrib-image-info &&
npm install node-red-contrib-image-output &&
npm install node-red-contrib-moment &&
npm install node-red-contrib-multipart-stream-encoder &&
npm install node-red-contrib-multipart-stream-decoder &&
npm install node-red-node-daemon &&
npm install node-red-node-smooth &&
npm install node-red-node-exif &&
npm install node-red-contrib-msg-speed &&
npm install node-red-contrib-random-output &&
npm install canvas &&
npm install numjs &&
npm install sharp &&
npm install piscina &&
npm install uuid
Install tfjs-node-gpu on Jetson
Note: If you are using Jetpack 4.6.1 you have to install numjs and canvas more or less manually:
Copy and import this example flow to your Node-RED. Configure nodes to match your setup, this means that you should corrent paths to point right files in your system and set Basler camera serial numbers according to your setup etc..
This flow will add following subflows in your Node-RED:
- [IMG] Annotate
- gst - jetson
- Parse JPEG
- gst WD
- Triton request
- Pre-process
- Post-process
This example flow starts 5 Gstreamer pipelines and uses 5 different cameras:
- Basler daA3840-45uc
- Basler daA1920-160uc
- Basler a2A1920-51gcBAS
- Basler acA2500-14gc
- Logitech C920
[{"id":"04508fd4d91dd935","type":"tab","label":"RTSP","disabled":false,"info":"","env":[]},{"id":"332da02c8e396138","type":"tab","label":"GStreamer","disabled":false,"info":"","env":[]},{"id":"0d2c119e1f2d1adf","type":"tab","label":"Parse streams","disabled":false,"info":"","env":[]},{"id":"48bebe191b6a13b3","type":"tab","label":"MJPEG","disabled":false,"info":"","env":[]},{"id":"88f8f06219122b1d","type":"tab","label":"Inference","disabled":true,"info":"","env":[]},{"id":"9baae2baa8d6b1c7","type":"tab","label":"Triton","disabled":true,"info":"","env":[]},{"id":"7028b45bb7803169","type":"tab","label":"Tequ-API","disabled":true,"info":"","env":[]},{"id":"83a7a965.1808a8","type":"subflow","name":"[IMG] Annotate","info":"","category":"Tequ-API Client","in":[{"x":120,"y":140,"wires":[{"id":"d05bfd8e.a02e"}]}],"out":[{"x":1080,"y":140,"wires":[{"id":"4e5f5c6c.bcf214","port":0}]}],"env":[{"name":"box_colors","type":"json","value":"{\"fish\":\"#FFFFFF\",\"pike\":\"#006400\",\"perch\":\"#008000\",\"smolt\":\"#ADD8E6\",\"salmon\":\"#0000FF\",\"trout\":\"#0000FF\",\"cyprinidae\":\"#808080\",\"zander\":\"#009000\",\"bream\":\"#008800\"}","ui":{"type":"input","opts":{"types":["json"]}}},{"name":"image_settings","type":"json","value":"{\"quality\":0.8}","ui":{"type":"input","opts":{"types":["json"]}}},{"name":"image_type","type":"str","value":"image/jpeg","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"JPG"},"v":"image/jpeg"},{"l":{"en-US":"PNG"},"v":"image/png"}]}}},{"name":"bbox_lineWidth","type":"num","value":"5","ui":{"type":"spinner","opts":{"min":0,"max":10}}},{"name":"bbox_text_color","type":"str","value":"white","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"white"},"v":"white"},{"l":{"en-US":"black"},"v":"black"},{"l":{"en-US":"blue"},"v":"blue"},{"l":{"en-US":"green"},"v":"green"},{"l":{"en-US":"yellow"},"v":"yellow"},{"l":{"en-US":"red"},"v":"red"},{"l":{"en-US":"orange"},"v":"orange"}]}}},{"name":"bbox_font","type":"str","value":"30px Arial","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"5px Arial"},"v":"5 px Arial"},{"l":{"en-US":"10px Arial"},"v":"10px Arial"},{"l":{"en-US":"15px Arial"},"v":"15px Arial"},{"l":{"en-US":"20px Arial"},"v":"20px Arial"},{"l":{"en-US":"25px Arial"},"v":"25px Arial"},{"l":{"en-US":"30px Arial"},"v":"30px Arial"},{"l":{"en-US":"35px Arial"},"v":"35px Arial"},{"l":{"en-US":"40px Arial"},"v":"40px Arial"},{"l":{"en-US":"45px Arial"},"v":"45px Arial"},{"l":{"en-US":"50px Arial"},"v":"50px Arial"}]}}},{"name":"label_offset_x","type":"num","value":"0","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"label_offset_y","type":"num","value":"30","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"threshold","type":"num","value":"0.75","ui":{"type":"spinner","opts":{"min":0,"max":1}}}],"meta":{"module":"[IMG] Annotate","version":"0.0.1","author":"[email protected]","desc":"Annotates prediction results from [AI] Detect subflows.","license":"MIT"},"color":"#87A980","icon":"font-awesome/fa-pencil-square-o","status":{"x":1080,"y":340,"wires":[{"id":"7fd4f6bf24348b12","port":0}]}},{"id":"fa7f491898fed374","type":"subflow","name":"gst-jetson","info":"","category":"Tequ-API Client","in":[{"x":120,"y":200,"wires":[{"id":"54dc40fe44895f9a"}]}],"out":[{"x":1100,"y":120,"wires":[{"id":"ab1595a359c8a71b","port":0},{"id":"dd701ced077fb628","port":0},{"id":"361321e30bc9bba9","port":0},{"id":"d86014e70dadc4b2","port":0}]}],"env":[{"name":"video_source","type":"str","value":"pylonsrc","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"pylonsrc"},"v":"pylonsrc"},{"l":{"en-US":"v4l2src"},"v":"v4l2src"}]}}},{"name":"v4l2_device","type":"str","value":"/dev/video0","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"serial","type":"str","value":"40257292","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"model","type":"str","value":"daA3840-45uc","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"manufacturer","type":"str","value":"Basler","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"pfs_file","type":"str","value":"/home/tequ/40257292.pfs","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"enable_mjpeg","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool"]}}},{"name":"mjpeg_width","type":"num","value":"1920","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_height","type":"num","value":"1080","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_framerate","type":"num","value":"5","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_font_size","type":"num","value":"8","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"enable_rtsp","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool"]}}},{"name":"rtsp_width","type":"num","value":"3840","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_height","type":"num","value":"2160","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_font_size","type":"str","value":"4","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"rtsp_server","type":"str","value":"rtsp://localhost:8554/","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"rtsp_framerate","type":"num","value":"10","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_encoder","type":"str","value":"nvv4l2h265enc","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"nvv4l2h265enc"},"v":"nvv4l2h265enc"},{"l":{"en-US":"nvv4l2h264enc"},"v":"nvv4l2h264enc"}]}}},{"name":"tcp_host","type":"str","value":"localhost","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"tcp_port","type":"num","value":"50001","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"video_width","type":"num","value":"3840","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"video_height","type":"num","value":"2160","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"video_type","type":"str","value":"video/x-raw","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"video_format","type":"str","value":"YUY2","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"video_framerate","type":"num","value":"10","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-basler-gst-jetson","version":"0.0.1","author":"[email protected]","desc":"Launch and control GStreamer pipelines.","license":"MIT"},"color":"#3FADB5","inputLabels":["command in"],"outputLabels":["info out"],"icon":"node-red/bridge.svg","status":{"x":1060,"y":360,"wires":[{"id":"6abd0b160a7877dd","port":0}]}},{"id":"21dbb5f62f40368e","type":"subflow","name":"Parse JPEG","info":"Parses JPEG image from MJPEG stream and adds metadata to msg.\r\n\r\nReads or adds:\r\n - Basic image info (width,height,size) \r\n - Exif data\r\n - Local timestamp, UTC timestamp, Unix timestamp \r\n - Thumbnail of the original image\r\n - Coordinates (if given)\r\n\r\n Output message is formatted to Tequ-API compatible format.\r\n\r\n","category":"Tequ-API Client","in":[{"x":40,"y":60,"wires":[{"id":"2ab9331e24332f8a"}]}],"out":[{"x":960,"y":480,"wires":[{"id":"b2856c4181e5257e","port":1}]}],"env":[{"name":"is_stream","type":"bool","value":"true","ui":{"label":{"en-US":"is_stream?"},"type":"input","opts":{"types":["bool","env"]}}},{"name":"latitude","type":"num","value":"66.503059","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"longitude","type":"num","value":"25.726967","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"thumbnail","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}},{"name":"width","type":"num","value":"50","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-parse-mjpeg","version":"0.0.1","author":"[email protected]","desc":"Parse JPEG from stream and add metadata to image","license":"MIT"},"color":"#3FADB5","inputLabels":["MJPEG stream in"],"outputLabels":["image out"],"icon":"font-awesome/fa-image","status":{"x":780,"y":540,"wires":[{"id":"64555399f8f3f8de","port":0}]}},{"id":"d9dd49bd747346d4","type":"subflow","name":"gst WD","info":"","category":"Tequ-API Client","in":[{"x":80,"y":60,"wires":[{"id":"4676b6d77fb4c9fd"}]}],"out":[{"x":840,"y":220,"wires":[{"id":"67250f6441a6d8f2","port":0}]},{"x":780,"y":60,"wires":[{"id":"4676b6d77fb4c9fd","port":1}]}],"env":[],"meta":{},"color":"#3FADB5","inputLabels":["Stream data in"],"outputLabels":["Restart cmd out",""],"icon":"font-awesome/fa-search","status":{"x":780,"y":340,"wires":[{"id":"42e72deef2a5b5b1","port":0}]}},{"id":"fd51dfdc3367d25c","type":"subflow","name":"Triton request","info":"Sends request to NVIDIA Triton Inference Server.\r\n\r\nExpects \"msg.tensor\" to be present in input\r\n\r\n\r\n \"msg.tensor.data\" and \r\n\r\n\r\n\r\n","category":"Tequ-API Client","in":[{"x":100,"y":100,"wires":[{"id":"837af87e0b706d16"}]}],"out":[{"x":980,"y":100,"wires":[{"id":"7451b5b3b174fc54","port":0}]}],"env":[{"name":"server_url","type":"str","value":"localhost:8000","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"model_name","type":"str","value":"tequ-fish-species-detection","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"request_timeout","type":"num","value":"10000","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"rate_limit_ms","type":"num","value":"0","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-triton-request","version":"0.0.1","author":"[email protected]","desc":"Send request to Triton Inference server.","license":"MIT"},"color":"#3FADB5","icon":"font-awesome/fa-globe","status":{"x":980,"y":180,"wires":[{"id":"5368623e2deefd7e","port":0}]}},{"id":"fde3bd1da88bc03c","type":"subflow","name":"Pre-process","info":"Converts input image (msg.payload) to Tensor.\r\n\r\nOutputs results in \"msg.tensor\".","category":"Tequ-API Client","in":[{"x":60,"y":60,"wires":[{"id":"557647c8b195bdea"}]}],"out":[{"x":380,"y":60,"wires":[{"id":"557647c8b195bdea","port":0}]}],"env":[],"meta":{"module":"tequ-image-to-tensor","version":"0.0.1","author":"[email protected]","desc":"Converts image to tensor.","license":"MIT"},"color":"#3FADB5","icon":"node-red/swap.svg","status":{"x":380,"y":140,"wires":[{"id":"752a76d98d97af39","port":0}]}},{"id":"9215deec580c5391","type":"subflow","name":"Post-process","info":"Post process result from Triton request.\r\n","category":"Tequ-API Client","in":[{"x":100,"y":120,"wires":[{"id":"1e80d9526ad0c4ee"}]}],"out":[{"x":970,"y":120,"wires":[{"id":"1e80d9526ad0c4ee","port":0}]}],"env":[{"name":"model_name","type":"str","value":"ssd-example-model","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"server_url","type":"str","value":"localhost:8000","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"threshold","type":"num","value":"0.5","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-triton-post-process","version":"0.0.1","author":"[email protected]","desc":"Post-process Triton request.","license":"MIT"},"color":"#3FADB5","inputLabels":["Triton request result in"],"outputLabels":["Processed output"],"icon":"font-awesome/fa-compress","status":{"x":740,"y":360,"wires":[{"id":"b93022c83cb00303","port":0}]}},{"id":"fcd42407.59d1a8","type":"subflow","name":"[API] Send image","info":"This node sends single image to Tequ-API. \n\nEndpoint used is /image/add\n\nYou need to add Bearer token to msg.token.\n\nYou can configure maximum times to try sending by parameter \"times_to_try\" in node config.","category":"Tequ-API Client","in":[{"x":40,"y":40,"wires":[{"id":"80c6d087.30ca7"}]}],"out":[{"x":1220,"y":60,"wires":[{"id":"f6e7b71a.50b0f8","port":0}]}],"env":[{"name":"API_URL","type":"str","value":"https://api.tequ.fi"},{"name":"times_to_try","type":"num","value":"3","ui":{"type":"spinner","opts":{"min":1,"max":10}}},{"name":"save_failed","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}},{"name":"path","type":"str","value":"/home/nvidia/"}],"meta":{"license":"MIT"},"color":"#FFCC66","inputLabels":["Data in"],"outputLabels":["Data out"],"icon":"node-red/white-globe.svg","status":{"x":1180,"y":340,"wires":[{"id":"9363fb9a.c3f578","port":0}]}},{"id":"ffeafac1.b0db18","type":"subflow","name":"[API] Get Token","info":"Username and password for login are configured in settings-file.\n\nprocess.env.client_email = \"email\";\nprocess.env.client_password = \"password\";\n\nPlease contact Tequ-API administrator to get credentials.\n\n[https://api.tequ.fi]()","category":"Tequ-API Client","in":[{"x":80,"y":140,"wires":[{"id":"d7310f56.fb383"}]}],"out":[{"x":1220,"y":300,"wires":[{"id":"c4734d48.7f0ff","port":0}]},{"x":1220,"y":140,"wires":[{"id":"50252e9e.d28d4","port":0}]}],"env":[{"name":"username","type":"str","value":"client_email","ui":{"icon":"font-awesome/fa-user-o"}},{"name":"password","type":"str","value":"client_password","ui":{"icon":"font-awesome/fa-lock","type":"input","opts":{"types":["str","env","cred"]}}},{"name":"API_URL","type":"str","value":"https://api.tequ.fi"}],"meta":{"license":"MIT"},"color":"#FFCC66","icon":"node-red/envelope.svg","status":{"x":1220,"y":360,"wires":[{"id":"6096db38.546e94","port":0}]}},{"id":"75015de274d71273","type":"subflow","name":"Format for Tequ-API","info":"","category":"Tequ-API Client","in":[{"x":140,"y":200,"wires":[{"id":"77e4f7126f22a6a9"}]}],"out":[{"x":750,"y":200,"wires":[{"id":"eb06f89989a8028c","port":0}]}],"env":[{"name":"enable","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}}],"meta":{"version":"0.0.1","author":"[email protected]","desc":"Format payload from [AI]Annotate to Tequ-API compatible format. Enable / disable sending to API.","license":"MIT"},"color":"#FFCC66","inputLabels":["Connect to \"[IMG] Annotate\" output "],"outputLabels":["Connect to \"[API] Send image\" input"],"icon":"node-red/sort.svg","status":{"x":620,"y":280,"wires":[{"id":"40ba865bf8f26d27","port":0}]}},{"id":"c19ac6bd.2a9d08","type":"function","z":"83a7a965.1808a8","name":"Annotate with canvas","func":"const img = msg.payload;\nconst objects = msg.data.properties.computer_vision.result\nconst labels = msg.data.properties.computer_vision.labels\n\nconst image_type = env.get(\"image_type\");\nconst image_settings = env.get(\"image_settings\");\nconst bbox_lineWidth = env.get(\"bbox_lineWidth\");\nconst bbox_text_color = env.get(\"bbox_text_color\");\nconst label_offset_x = env.get(\"label_offset_x\");\nconst label_offset_y = env.get(\"label_offset_y\");\nconst bbox_font = env.get(\"bbox_font\");\nconst COLORS = env.get(\"box_colors\");\n\n\n//Define threshold\nlet threshold = 0;\n\nconst global_settings = global.get(\"settings\") || undefined\nlet thresholdType = \"\"\n\nif(global_settings !== undefined){\n if(\"threshold\" in global_settings){\n threshold = global_settings[\"threshold\"]\n thresholdType = \"global\";\n }\n}\n\nelse if(\"threshold\" in msg){\n threshold = msg.threshold;\n thresholdType = \"msg\";\n if(threshold < 0){\n threshold = 0\n }\n else if(threshold > 1){\n threshold = 1\n }\n}\n\nelse{\n threshold = env.get(\"threshold\");\n thresholdType = \"env\";\n}\n\nmsg.thresholdUsed = threshold;\nmsg.thresholdTypeUsed = thresholdType;\n\nasync function annotateImage(image) {\n const localImage = await canvas.loadImage(image); \n const cvs = canvas.createCanvas(localImage.width, localImage.height);\n const ctx = cvs.getContext('2d'); \n ctx.drawImage(localImage, 0, 0); \n \n objects.forEach((obj) => {\n if(labels.includes(obj.class) && obj.score >= threshold){\n let [x, y, w, h] = obj.bbox;\n ctx.lineWidth = bbox_lineWidth;\n ctx.strokeStyle = COLORS[obj.class];\n ctx.strokeRect(x, y, w, h);\n ctx.fillStyle = bbox_text_color;\n ctx.font = bbox_font;\n ctx.fillText(obj.class+\" \"+Math.round(obj.score*100)+\" %\",x+label_offset_x,y+label_offset_y);\n }\n });\n \n return cvs.toBuffer(image_type, image_settings);\n}\n\nif(objects.length > 0){\n msg.data.properties.object.data.annotated.image = await annotateImage(img) \n msg.objects_found = true\n}\nelse{\n msg.objects_found = false\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"canvas","module":"canvas"}],"x":440,"y":140,"wires":[["a801355d.9f7ac8"]]},{"id":"d05bfd8e.a02e","type":"change","z":"83a7a965.1808a8","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":140,"wires":[["c19ac6bd.2a9d08"]]},{"id":"a801355d.9f7ac8","type":"change","z":"83a7a965.1808a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.annotated.annotation_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"},{"t":"set","p":"payload.annotation.objects_found","pt":"msg","to":"objects_found","tot":"msg"},{"t":"delete","p":"annotated_image","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":140,"wires":[["c20a6448.e6f218"]]},{"id":"4e5f5c6c.bcf214","type":"change","z":"83a7a965.1808a8","name":"delete useless","rules":[{"t":"delete","p":"annotated_image","pt":"msg"},{"t":"delete","p":"start","pt":"msg"},{"t":"delete","p":"resize_start","pt":"msg"},{"t":"delete","p":"thresholdTypeUsed","pt":"msg"},{"t":"delete","p":"threshold","pt":"msg"},{"t":"delete","p":"thresholdUsed","pt":"msg"},{"t":"delete","p":"start","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":140,"wires":[[]]},{"id":"c20a6448.e6f218","type":"switch","z":"83a7a965.1808a8","name":"objects found?","property":"objects_found","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":260,"wires":[["5fae1e95eb3561e9"],["0ec56ca8f000a540"]]},{"id":"a9379cd1321a02da","type":"function","z":"83a7a965.1808a8","name":"","func":"node.status({ fill: \"green\", shape: \"dot\", text: msg.thresholdTypeUsed + \" \" + msg.thresholdUsed + \" in \" + msg.data.properties.object.data.annotated.total_ms+\" ms\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1040,"y":240,"wires":[]},{"id":"0ec56ca8f000a540","type":"function","z":"83a7a965.1808a8","name":"","func":"node.status({fill:\"green\",shape:\"dot\",text:msg.thresholdTypeUsed+\" \"+msg.thresholdUsed+\" No objects to annotate\"})\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":300,"wires":[["4e5f5c6c.bcf214"]]},{"id":"7fd4f6bf24348b12","type":"status","z":"83a7a965.1808a8","name":"","scope":null,"x":860,"y":340,"wires":[[]]},{"id":"5fae1e95eb3561e9","type":"change","z":"83a7a965.1808a8","name":"timer","rules":[{"t":"set","p":"resize_start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":240,"wires":[["f5809fcdc54a540e"]]},{"id":"f5809fcdc54a540e","type":"function","z":"83a7a965.1808a8","name":"resize","func":"let input = msg.data.properties.object.data.annotated.image;\n\nlet resized = await sharp(input)\n .metadata()\n .then(({ width }) => sharp(input)\n .resize({ width: 200 })\n .toBuffer()\n);\n\nmsg.data.properties.object.data.annotated.thumbnail = resized.toString('base64');\nmsg.data.properties.object.data.annotated.image = (msg.data.properties.object.data.annotated.image).toString('base64')\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"sharp","module":"sharp"}],"x":630,"y":240,"wires":[["e0f13103c7faabff"]]},{"id":"e0f13103c7faabff","type":"change","z":"83a7a965.1808a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.annotated.thumbnail_ms","pt":"msg","to":"$millis() - msg.resize_start","tot":"jsonata"},{"t":"set","p":"data.properties.object.data.annotated.total_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":240,"wires":[["4e5f5c6c.bcf214","a9379cd1321a02da"]]},{"id":"d9a2420055236c2b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"SIGTERM","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":120,"wires":[["99ac100731d2d825"]]},{"id":"be99e21d6ee788c1","type":"function","z":"fa7f491898fed374","name":"construct gst pipeline","func":"let serial = env.get(\"serial\");\nlet model = env.get(\"model\");\nlet pfs_file = env.get(\"pfs_file\");\nlet source = env.get(\"video_source\");\nlet v4l2_device = env.get(\"v4l2_device\");\nlet manufacturer = env.get(\"manufacturer\");\n\nlet enable_rtsp = env.get(\"enable_rtsp\")\nlet rtsp_width = env.get(\"rtsp_width\");\nlet rtsp_height = env.get(\"rtsp_height\");\nlet rtsp_framerate = env.get(\"rtsp_framerate\");\nlet rtsp_encoder = env.get(\"rtsp_encoder\");\nlet rtsp_font_size = env.get(\"rtsp_font_size\");\nlet rtsp_server = env.get(\"rtsp_server\");\n\nlet enable_mjpeg = env.get(\"enable_mjpeg\")\nlet mjpeg_width = env.get(\"mjpeg_width\");\nlet mjpeg_height = env.get(\"mjpeg_height\");\nlet mjpeg_framerate = env.get(\"mjpeg_framerate\");\nlet mjpeg_font_size = env.get(\"mjpeg_font_size\");\n\n\nlet video_width = env.get(\"video_width\");\nlet video_height = env.get(\"video_height\");\nlet video_format = env.get(\"video_format\");\nlet video_type = env.get(\"video_type\");\nlet video_framerate = env.get(\"video_framerate\");\nlet tcp_host = env.get(\"tcp_host\");\nlet tcp_port = env.get(\"tcp_port\");\nlet gst_pipeline;\n\n\n\n\nlet gst_msg = {}\n\nif (source == \"pylonsrc\"){\n gst_pipeline = \n source + ' capture-error=skip device-serial-number=\"' + serial + '\" pfs-location=' + pfs_file; \n \n gst_pipeline = gst_pipeline + ' ! \"' + video_type + ',width=' + video_width + ',height=' + video_height + ',framerate=' + video_framerate + '/1,format=' + video_format+ '\"'; \n gst_pipeline = gst_pipeline + ' ! tee name = video_out';\n\n\n if (enable_mjpeg){\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + mjpeg_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + mjpeg_width + ',height=' + mjpeg_height + ',framerate=' + mjpeg_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! nvjpegenc ! taginject tags = \"application-name=tequ-gst-1.0,copyright=Lapland_UAS,description=serialnumber_' + serial + ',artist=Tequ,device-manufacturer=' + manufacturer +',device-model='+model+'\" ! jifmux ! queue ! tcpclientsink host='+tcp_host+' port='+tcp_port;\n }\n if (enable_rtsp){\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + rtsp_font_size +'\" ! videoscale ! videorate ! \"' + video_type + ',width=' + rtsp_width + ',height=' + rtsp_height + ',framerate=' + rtsp_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! ' +rtsp_encoder+' ! queue ! rtspclientsink location = '+rtsp_server+serial+'';\n }\n}\nelse if (source == \"v4l2src\"){\n gst_pipeline =\n source + ' device=\"' + v4l2_device+'\"'; \n gst_pipeline = gst_pipeline + ' ! videoscale ! \"' + video_type + ',width=' + video_width + ',height=' + video_height + ',framerate=' + video_framerate + '/1,format=' + video_format + '\"';\n gst_pipeline = gst_pipeline + ' ! tee name = video_out';\n\n if (enable_mjpeg) {\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + mjpeg_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + mjpeg_width + ',height=' + mjpeg_height + ',framerate=' + mjpeg_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! nvjpegenc ! taginject tags = \"application-name=tequ-gst-1.0,copyright=Lapland_UAS,description=serialnumber_' + serial + ',artist=Tequ,device-manufacturer=' + manufacturer + ',device-model=' + model + '\" ! jifmux ! queue ! tcpclientsink host=' + tcp_host + ' port=' + tcp_port;\n }\n if (enable_rtsp) {\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + rtsp_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + rtsp_width + ',height=' + rtsp_height + ',framerate=' + rtsp_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! ' + rtsp_encoder + ' ! queue ! rtspclientsink location = ' + rtsp_server + serial + '';\n }\n}\nelse {\n node.status({ fill: \"red\", shape: \"ring\", text: \"src: \" + source +\" is not supported\" });\n return null;\n}\n\ngst_msg.payload = gst_pipeline;\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Launching...\"});\nreturn gst_msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":320,"wires":[["99ac100731d2d825","ab1595a359c8a71b"]]},{"id":"99ac100731d2d825","type":"exec","z":"fa7f491898fed374","command":"gst-launch-1.0","addpay":"payload","append":"","useSpawn":"true","timer":"","winHide":false,"oldrc":false,"name":"gst-launch","x":710,"y":120,"wires":[["361321e30bc9bba9"],["dd701ced077fb628"],["d86014e70dadc4b2"]]},{"id":"8ba82764fc44edf8","type":"delay","z":"fa7f491898fed374","name":"","pauseType":"random","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"6","randomLast":"22","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":480,"y":240,"wires":[["be99e21d6ee788c1"]]},{"id":"f6110566b977602b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"SIGTERM","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":180,"wires":[["8ba82764fc44edf8","99ac100731d2d825"]]},{"id":"6abd0b160a7877dd","type":"status","z":"fa7f491898fed374","name":"","scope":["be99e21d6ee788c1","99ac100731d2d825","54dc40fe44895f9a"],"x":760,"y":360,"wires":[[]]},{"id":"54dc40fe44895f9a","type":"function","z":"fa7f491898fed374","name":"cmd?","func":"let topic = msg.topic;\n\nif(topic == \"kill\"){\n node.status({fill:\"red\",shape:\"ring\",text:\"cmd: kill\"});\n return [msg,null,null]\n}\nelse if (topic == \"restart\") {\n node.status({ fill: \"yellow\", shape: \"ring\", text: \"cmd: restart\" });\n return [null, msg, null]\n}\nelse if (topic == \"start\") {\n node.status({ fill: \"blue\", shape: \"ring\", text: \"cmd: start\" });\n return [null, null, msg]\n}\n\nreturn msg;","outputs":3,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":200,"wires":[["d9a2420055236c2b"],["f6110566b977602b"],["be99e21d6ee788c1"]]},{"id":"ab1595a359c8a71b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"pipeline-info","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":320,"wires":[[]]},{"id":"dd701ced077fb628","type":"change","z":"fa7f491898fed374","name":"stderr","rules":[{"t":"set","p":"topic","pt":"msg","to":"stderr","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":120,"wires":[[]]},{"id":"361321e30bc9bba9","type":"change","z":"fa7f491898fed374","name":"stdout","rules":[{"t":"set","p":"topic","pt":"msg","to":"stdout","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":80,"wires":[[]]},{"id":"d86014e70dadc4b2","type":"change","z":"fa7f491898fed374","name":"return code","rules":[{"t":"set","p":"topic","pt":"msg","to":"return code","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":160,"wires":[[]]},{"id":"e0bb72dfae4ee3a3","type":"image-info","z":"21dbb5f62f40368e","name":"","x":170,"y":360,"wires":[["e4dd6a59044e7bfa"]]},{"id":"e4dd6a59044e7bfa","type":"exif","z":"21dbb5f62f40368e","name":"","mode":"normal","property":"payload","x":150,"y":420,"wires":[["8f854870.b60a68"]]},{"id":"f89675e462ce03bb","type":"moment","z":"21dbb5f62f40368e","name":"","topic":"","input":"","inputType":"date","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"en-US","output":"utc_timestamp","outputType":"msg","outTz":"Europe/Helsinki","x":200,"y":180,"wires":[["0aa0578efb06e6b3"]]},{"id":"0aa0578efb06e6b3","type":"moment","z":"21dbb5f62f40368e","name":"","topic":"","input":"utc_timestamp","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"YYYY-MM-DD HH:mm:ss","locale":"en-US","output":"local_timestamp","outputType":"msg","outTz":"Europe/Helsinki","x":200,"y":240,"wires":[["684d7d4f12541303"]]},{"id":"684d7d4f12541303","type":"moment","z":"21dbb5f62f40368e","name":"","topic":"","input":"utc_timestamp","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"x","locale":"en-US","output":"unix_timestamp","outputType":"msg","outTz":"ETC/UTC","x":200,"y":300,"wires":[["e0bb72dfae4ee3a3"]]},{"id":"64555399f8f3f8de","type":"status","z":"21dbb5f62f40368e","name":"","scope":["b2856c4181e5257e"],"x":600,"y":540,"wires":[[]]},{"id":"13ad0fba970dab22","type":"function","z":"21dbb5f62f40368e","name":"Reformat data","func":"let type;\nlet random_name = uuid.v4();\nlet image_type = msg.type;\nlet file_extension;\nlet latitude = Number(env.get(\"latitude\"))\nlet longitude = Number(env.get(\"longitude\"))\nlet unix_timestamp = parseInt(msg.unix_timestamp);\nlet serial;\ntry{\n serial = (msg.exif.image.ImageDescription).split(\"_\")[1];\n}\ncatch(e){\n serial = \"unknown\"\n}\n\nlet datasource = serial;\n\nif (image_type == \"jpg\") {\n image_type = \"image/jpeg\"\n file_extension = \".jpg\"\n}\nelse if (image_type == \"png\") {\n image_type = \"image/png\"\n file_extension = \".png\"\n}\n\nmsg.topic = serial;\nmsg.datasource = serial;\nmsg.random_name = random_name;\nmsg.file_extension = file_extension;\n\nlet parameters = {\n \"owner\": msg.exif.image.Copyright,\n \"version\": msg.exif.image.Software,\n \"model\": msg.exif.image.Model,\n \"serial\": serial,\n \"manufacturer\": msg.exif.image.Make\n}\n\nmsg.data = {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [longitude, latitude]\n },\n \"properties\": {\n \"datasource\": datasource,\n \"local_timestamp\": msg.local_timestamp,\n \"utc_timestamp\": msg.utc_timestamp,\n \"unix_timestamp\": unix_timestamp,\n \"cos\": {\n \"bucket\": \"\",\n \"region\": \"\",\n \"service_id\": \"\"\n },\n \"object\": {\n \"type\": image_type,\n \"data\": {\n \"width\": msg.width,\n \"height\": msg.height,\n \"size\": (msg.payload).length,\n \"exif\": msg.exif,\n \"parameters\": parameters,\n \"original\": {\n \"image\": (msg.payload).toString('base64'),\n \"objectname\": datasource + \"-\" + random_name + file_extension,\n \"thumbnail\": (msg.thumbnail).toString('base64'),\n \"thumbnail_ms\": msg.thumbnail_ms,\n \"mjpeg_process_ms\":0\n },\n \"annotated\": {\n \"image\": \"\",\n \"objectname\": datasource + \"-\" + random_name+ \"_annotated\"+file_extension,\n \"thumbnail\": \"\",\n \"thumbnail_ms\":0,\n \"annotation_ms\":0,\n \"total_ms\":0\n }\n }\n },\n \"computer_vision\": {\n \"type\": \"\",\n \"model\": \"\",\n \"inference_time\": \"\",\n \"result\": \"\"\n }\n }\n}\n\ndelete msg.settings;\ndelete msg.width;\ndelete msg.height;\ndelete msg.type;\ndelete msg.exif;\ndelete msg.thumbnail;\ndelete msg.utc_timestamp;\ndelete msg.local_timestamp;\ndelete msg.unix_timestamp;\ndelete msg.start;\ndelete msg.thumbnail_ms;\ndelete msg.datasource;\ndelete msg.random_name;\ndelete msg.file_extension;\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"uuid","module":"uuid"}],"x":620,"y":400,"wires":[["cfd1798c21f67f4b"]]},{"id":"8f854870.b60a68","type":"change","z":"21dbb5f62f40368e","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":420,"wires":[["7ebfd14d.6f0a2"]]},{"id":"11af73fe.677eac","type":"change","z":"21dbb5f62f40368e","name":"end timer","rules":[{"t":"set","p":"thumbnail_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":340,"wires":[["13ad0fba970dab22"]]},{"id":"24296ef596b98b25","type":"change","z":"21dbb5f62f40368e","name":"timer","rules":[{"t":"set","p":"process_start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["f89675e462ce03bb"]]},{"id":"7ebfd14d.6f0a2","type":"function","z":"21dbb5f62f40368e","name":"resize","func":"let input = msg.payload;\nlet width = env.get(\"thumbnail_width\")\nlet create_thumbnail = env.get(\"thumbnail\")\nlet thumbnail;\n\nif (create_thumbnail){\n thumbnail = await sharp(input)\n .metadata()\n .then(({ width }) => sharp(input)\n .resize({ width: width })\n .toBuffer()\n );\n\n \n}\nelse{\n thumbnail = []\n}\nmsg.thumbnail = thumbnail\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"sharp","module":"sharp"}],"x":450,"y":340,"wires":[["11af73fe.677eac"]]},{"id":"cfd1798c21f67f4b","type":"change","z":"21dbb5f62f40368e","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.original.mjpeg_process_ms","pt":"msg","to":"$millis() - msg.process_start","tot":"jsonata"},{"t":"delete","p":"process_start","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":460,"wires":[["b2856c4181e5257e"]]},{"id":"79f2e9e678938947","type":"split","z":"21dbb5f62f40368e","name":"","splt":"[255, 216, 255]","spltType":"bin","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":330,"y":40,"wires":[["ce93aab9fcf9afda"]]},{"id":"ce93aab9fcf9afda","type":"function","z":"21dbb5f62f40368e","name":"Join","func":"let header = Buffer.from(msg.parts.ch);\nlet image = Buffer.from(msg.payload);\nlet arr = [header,image]\nmsg.payload = Buffer.concat(arr)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":40,"wires":[["24296ef596b98b25"]]},{"id":"b2856c4181e5257e","type":"msg-speed","z":"21dbb5f62f40368e","name":"images","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":760,"y":460,"wires":[[],[]]},{"id":"2ab9331e24332f8a","type":"switch","z":"21dbb5f62f40368e","name":"is_stream?","property":"is_stream","propertyType":"env","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":170,"y":60,"wires":[["79f2e9e678938947"],["24296ef596b98b25"]]},{"id":"4676b6d77fb4c9fd","type":"msg-speed","z":"d9dd49bd747346d4","name":"","frequency":"sec","interval":"5","estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":210,"y":60,"wires":[["75a772553f72adc5"],[]]},{"id":"75a772553f72adc5","type":"switch","z":"d9dd49bd747346d4","name":"== 0","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":170,"y":160,"wires":[["48bd712e32556613"]]},{"id":"48bd712e32556613","type":"delay","z":"d9dd49bd747346d4","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":180,"y":220,"wires":[["10b1bb59b99fd89e"]]},{"id":"10b1bb59b99fd89e","type":"trigger","z":"d9dd49bd747346d4","name":"","op1":"{\"topic\":\"restart\",\"payload\":\"ok\"}","op2":"","op1type":"json","op2type":"nul","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":380,"y":220,"wires":[["860b8a639262a949"]]},{"id":"67250f6441a6d8f2","type":"change","z":"d9dd49bd747346d4","name":"restart","rules":[{"t":"set","p":"topic","pt":"msg","to":"restart","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":220,"wires":[["abcd5255fa959167"]]},{"id":"abcd5255fa959167","type":"function","z":"d9dd49bd747346d4","name":"Restart","func":"node.status({fill:\"red\",shape:\"ring\",text:\"no data, restart\"});\nreturn msg;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":180,"wires":[]},{"id":"42e72deef2a5b5b1","type":"status","z":"d9dd49bd747346d4","name":"","scope":["4676b6d77fb4c9fd","abcd5255fa959167"],"x":640,"y":340,"wires":[[]]},{"id":"883688b62b7bec6b","type":"inject","z":"d9dd49bd747346d4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":130,"y":20,"wires":[["4676b6d77fb4c9fd"]]},{"id":"860b8a639262a949","type":"delay","z":"d9dd49bd747346d4","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"5","randomLast":"25","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":520,"y":220,"wires":[["67250f6441a6d8f2"]]},{"id":"b63e9a83f3001f21","type":"function","z":"fd51dfdc3367d25c","name":"Triton request","func":"if(\"tensor\" in msg){\n const serverUrl = env.get(\"server_url\");\n const modelName = env.get(\"model_name\");\n const requestTimeout = env.get(\"request_timeout\");\n const tensor_data = msg.tensor.data;\n const inference_header_length = msg.tensor.inference_header_length;\n\n //Construct Triton Inference Server HTTP API message\n msg.request_start = Date.now();\n msg.payload = tensor_data\n msg.method = \"POST\";\n msg.requestTimeout = requestTimeout;\n msg.url = serverUrl + \"/v2/models/\" + modelName + \"/infer\";\n msg.headers = {\n \"Content-Type\": \"application/octet-stream\",\n \"Inference-Header-Content-Length\": inference_header_length,\n };\n\n return msg;\n}\nelse{\n node.status({ fill: \"red\", shape: \"dot\", text: \"No msg.tensor in input msg\" });\n node.error(\"No msg.tensor in input msg\", msg);\n return null;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"// Code added here will be run when the\n// node is being stopped or re-deployed.\ncontext.set(\"piscina\",{})","libs":[{"var":"pis","module":"piscina"},{"var":"fs","module":"fs"},{"var":"zlib","module":"zlib"},{"var":"os","module":"os"},{"var":"process","module":"process"},{"var":"path","module":"path"}],"x":520,"y":100,"wires":[["3937c53e6f34bf73"]]},{"id":"3937c53e6f34bf73","type":"http request","z":"fd51dfdc3367d25c","name":"req","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":true,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":690,"y":100,"wires":[["7451b5b3b174fc54"]]},{"id":"5368623e2deefd7e","type":"status","z":"fd51dfdc3367d25c","name":"","scope":["b63e9a83f3001f21","7451b5b3b174fc54","7276cd4d5b2ed247","c9d10c33a635199d"],"x":680,"y":180,"wires":[[]]},{"id":"7451b5b3b174fc54","type":"function","z":"fd51dfdc3367d25c","name":"Process req","func":"let statuscode = msg.statusCode;\nlet request_ms = Date.now() - msg.request_start;\nlet color = \"\"\nlet rate_limit_ms = 0\nmsg.request_ms = request_ms\n\ntry{\n rate_limit_ms = parseInt(env.get(\"rate_limit_ms\"))\n}\ncatch(e){\n //\n}\n\nif (statuscode == 200){\n color = \"blue\"\n delete msg.request_start;\n delete msg.headers;\n delete msg.statusCode;\n delete msg.method;\n delete msg.retry;\n delete msg.url;\n delete msg.responseUrl;\n delete msg.requestTimeout;\n delete msg.redirectList;\n \n if(rate_limit_ms === 0){\n color = \"blue\"\n node.status({\n fill: color, shape: \"dot\", text: statuscode + \" | \" + request_ms + \" ms\"\n }); \n }\n else{\n color = \"yellow\"\n const rate = Math.round(1000 / rate_limit_ms*100)/100\n node.status({\n fill: color, shape: \"dot\", text: statuscode + \" | \" + request_ms + \" ms | \" + rate+\" msg/s\"\n }); \n }\n \n \n return msg;\n}\n\nelse{\n color = \"red\"\n node.status({ fill: color, shape: \"dot\", text: statuscode + \" | \"+msg.payload.error});\n node.error(\"Processing request failed\", msg);\n return null;\n} ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":100,"wires":[[]]},{"id":"db3449811636781b","type":"http request","z":"fd51dfdc3367d25c","name":"status request","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":600,"y":420,"wires":[["c9d10c33a635199d"]]},{"id":"7276cd4d5b2ed247","type":"function","z":"fd51dfdc3367d25c","name":"request","func":"let modelName = env.get(\"model_name\")\nlet serverUrl = env.get(\"server_url\")\n\nmsg.requestTimeout = 1000;\nmsg.method = \"GET\";\nmsg.url = serverUrl+\"/v2/models/\"+modelName+\"/config\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":420,"wires":[["db3449811636781b"]]},{"id":"c9d10c33a635199d","type":"function","z":"fd51dfdc3367d25c","name":"status","func":"let statusCode = msg.statusCode;\nlet parsed_value;\nlet modelName = env.get(\"model_name\")\n\nif(statusCode == 200){\n flow.set(\"ready\",true) \n node.status({fill:\"green\",shape:\"dot\",text:\" Server ready.\"}); \n return msg;\n}\nelse{\n flow.set(\"ready\",false)\n node.status({fill:\"red\",shape:\"dot\",text:msg.statusCode+\": \"+\"Server is not ready or model not found.\"}); \n return null\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":420,"wires":[[]]},{"id":"861ee57d416b8b03","type":"inject","z":"fd51dfdc3367d25c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"ready","payloadType":"flow","x":210,"y":420,"wires":[["7276cd4d5b2ed247"]]},{"id":"837af87e0b706d16","type":"switch","z":"fd51dfdc3367d25c","name":"ready?","property":"ready","propertyType":"flow","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":210,"y":100,"wires":[["1abffcc5defb1aaa"],[]]},{"id":"8e4df5803e108905","type":"change","z":"fd51dfdc3367d25c","name":"","rules":[{"t":"set","p":"ready","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":480,"wires":[[]]},{"id":"b7e78ff17bb440b8","type":"inject","z":"fd51dfdc3367d25c","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":480,"wires":[["8e4df5803e108905"]]},{"id":"1abffcc5defb1aaa","type":"switch","z":"fd51dfdc3367d25c","name":"rate limit?","property":"rate_limit_ms","propertyType":"env","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":160,"wires":[["b63e9a83f3001f21"],["2cc1bd4e5a083146"]]},{"id":"8c7c992ba1c6145c","type":"delay","z":"fd51dfdc3367d25c","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":true,"outputs":1,"x":410,"y":220,"wires":[["b63e9a83f3001f21"]]},{"id":"2cc1bd4e5a083146","type":"change","z":"fd51dfdc3367d25c","name":"","rules":[{"t":"set","p":"rate","pt":"msg","to":"rate_limit_ms","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":220,"wires":[["8c7c992ba1c6145c"]]},{"id":"557647c8b195bdea","type":"function","z":"fde3bd1da88bc03c","name":"pre-process","func":"//Get a worker from the pool and execute the task\nconst start = Date.now();\nconst image = msg.payload;\nlet piscina = context.get(\"piscina\")\nlet pre_process_time;\n\ntry{\n let result = await piscina.run({jpeg:image,gzip:false});\n \n msg.tensor = {\n \"image\":image,\n \"data\":Buffer.from(result.tensorBuffer),\n \"tensor_shape\":result.tensorShape,\n \"inference_header_length\":result.inference_header_length,\n \"image_tensor_buffer_length\":result.image_tensor_buffer_length\n }\n \n pre_process_time = Date.now() - start;\n msg.data.properties.computer_vision.pre_process_ms = pre_process_time\n node.status({fill:\"green\",shape:\"dot\",text:pre_process_time+\" ms\"}); \n return msg;\n}\ncatch(e){\n node.status({fill:\"red\",shape:\"dot\",text:\"Convert failed...\"}); \n node.error(\"Image to tensor conversion failed. Probably input is not an image buffer.\", msg);\n}","outputs":1,"noerr":0,"initialize":"let nr_folder;\nconst scriptName = 'numjs_piscina_worker.js';\nvar worker_path = \"\"\nconst platform = os.platform()\nvar worker_script;\nlet sep;\nlet numberOfWorkers;\n\nnode.warn(\"Platform: \" + platform)\n\nif(platform == \"win32\"){\n sep = \"\\\\\"\n nr_folder = path.resolve()\n worker_path = path.resolve(scriptName)\n worker_script = \"console.log(\\\"Worker starting...\\\");\\r\\nlet nj;\\r\\nlet zlib;\\r\\n\\r\\n\\r\\ntry{\\r\\n\\tnj = require(\\\"./node_modules\\//numjs\\\")\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(\\\"Loading numjs failed\\\")\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\ntry{\\r\\n\\tzlib = require(\\'zlib\\');\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\nmodule.exports = async ({jpeg,gzip}) => {\\r\\n\\ttry{\\r\\n\\t\\tconst start = Date.now();\\t\\r\\n\\t\\tconst img = nj.images.read(jpeg);\\r\\n\\t\\tconst dataBuffer = Buffer.from(img.selection.data);\\r\\n\\t\\tconst shape = [1].concat(img.shape);\\r\\n\\t\\tconst image_tensor_buffer_length = dataBuffer.length\\r\\n\\t\\t\\r\\n\\t\\t\\r\\n\\t\\tconst inference_header = {\\r\\n\\t\\t \\\"model_name\\\" : \\\"test\\\",\\r\\n\\t\\t \\\"inputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"input_tensor\\\",\\r\\n\\t\\t\\t \\\"shape\\\" : shape,\\r\\n\\t\\t\\t \\\"datatype\\\" : \\\"UINT8\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t \\\"binary_data_size\\\":image_tensor_buffer_length\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ],\\r\\n\\t\\t \\\"outputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_scores\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_boxes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_classes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tconst inference_header_buffer = Buffer.from(JSON.stringify(inference_header))\\r\\n\\t\\tconst inference_header_length = inference_header_buffer.length\\r\\n\\t\\tlet payload = Buffer.concat([inference_header_buffer,dataBuffer])\\r\\n\\t\\ttime_ms = Date.now() - start;\\r\\n\\t\\t\\r\\n\\t\\tif(gzip){\\r\\n\\t\\t\\tpayload = zlib.gzipSync(payload)\\r\\n\\t\\t}\\r\\n\\t\\t\\r\\n\\t\\tresult = {\\r\\n\\t\\t\\t\\\"tensorBuffer\\\" : payload,\\r\\n\\t\\t\\t\\\"Content-Type\\\" : \\\"application\\/octet-stream\\\",\\r\\n\\t\\t\\t\\\"inference_header_length\\\": inference_header_length,\\r\\n\\t\\t\\t\\\"image_tensor_buffer_length\\\":image_tensor_buffer_length,\\r\\n\\t\\t\\t\\\"tensorShape\\\":shape,\\r\\n\\t\\t\\t\\\"processing_time\\\":time_ms,\\r\\n\\t\\t\\t\\\"payload\\\":jpeg\\r\\n\\t\\t}\\t\\t\\r\\n\\t\\treturn result\\t\\t\\r\\n\\t}\\r\\n\\tcatch(e){\\r\\n\\t\\tconsole.log(e)\\r\\n\\t}\\r\\n\\t\\t\\r\\n}\"\n}\nelse{\n nr_folder = path.resolve(\".node-red\")\n node.warn(nr_folder)\n worker_path = path.resolve(\".node-red\",scriptName)\n node.warn(worker_path)\n sep = \"/\" \n worker_script = \"console.log(\\\"Worker starting...\\\");\\r\\nlet nj;\\r\\nlet zlib;\\r\\n\\r\\n\\r\\ntry{\\r\\n\\tnj = require(\\\"./node_modules\\//numjs\\\")\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(\\\"Loading numjs failed\\\")\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\ntry{\\r\\n\\tzlib = require(\\'zlib\\');\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\nmodule.exports = async ({jpeg,gzip}) => {\\r\\n\\ttry{\\r\\n\\t\\tconst start = Date.now();\\t\\r\\n\\t\\tconst img = nj.images.read(jpeg);\\r\\n\\t\\tconst dataBuffer = Buffer.from(img.selection.data);\\r\\n\\t\\tconst shape = [1].concat(img.shape);\\r\\n\\t\\tconst image_tensor_buffer_length = dataBuffer.length\\r\\n\\t\\t\\r\\n\\t\\t\\r\\n\\t\\tconst inference_header = {\\r\\n\\t\\t \\\"model_name\\\" : \\\"test\\\",\\r\\n\\t\\t \\\"inputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"input_tensor\\\",\\r\\n\\t\\t\\t \\\"shape\\\" : shape,\\r\\n\\t\\t\\t \\\"datatype\\\" : \\\"UINT8\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t \\\"binary_data_size\\\":image_tensor_buffer_length\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ],\\r\\n\\t\\t \\\"outputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_scores\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_boxes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_classes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tconst inference_header_buffer = Buffer.from(JSON.stringify(inference_header))\\r\\n\\t\\tconst inference_header_length = inference_header_buffer.length\\r\\n\\t\\tlet payload = Buffer.concat([inference_header_buffer,dataBuffer])\\r\\n\\t\\ttime_ms = Date.now() - start;\\r\\n\\t\\t\\r\\n\\t\\tif(gzip){\\r\\n\\t\\t\\tpayload = zlib.gzipSync(payload)\\r\\n\\t\\t}\\r\\n\\t\\t\\r\\n\\t\\tresult = {\\r\\n\\t\\t\\t\\\"tensorBuffer\\\" : payload,\\r\\n\\t\\t\\t\\\"Content-Type\\\" : \\\"application\\/octet-stream\\\",\\r\\n\\t\\t\\t\\\"inference_header_length\\\": inference_header_length,\\r\\n\\t\\t\\t\\\"image_tensor_buffer_length\\\":image_tensor_buffer_length,\\r\\n\\t\\t\\t\\\"tensorShape\\\":shape,\\r\\n\\t\\t\\t\\\"processing_time\\\":time_ms,\\r\\n\\t\\t\\t\\\"payload\\\":jpeg\\r\\n\\t\\t}\\t\\t\\r\\n\\t\\treturn result\\t\\t\\r\\n\\t}\\r\\n\\tcatch(e){\\r\\n\\t\\tconsole.log(e)\\r\\n\\t}\\r\\n\\t\\t\\r\\n}\"\n}\n\ntry{\n numberOfWorkers = 2\n}\ncatch(e){\n node.warn(\"Loading numberOfWorkers from env variable failed... using default value = 1\")\n node.warn(e)\n numberOfWorkers = 1\n}\n\nfs.writeFile(worker_path, worker_script, function (err) {\n if (err) {\n node.error(\"Cannot create web_worker_test_script.js file: \" + err);\n }\n});\n\ntry{\n const piscina = new pis.Piscina({\n filename: worker_path,\n maxThreads: numberOfWorkers\n });\n \n context.set(\"piscina\",piscina)\n node.status({fill:\"green\", shape:\"dot\", text:\"Piscina initialized\"});\n}\ncatch(error){\n node.warn(error)\n node.status({fill:\"red\", shape:\"dot\", text:\"Initializing piscina failed...\"});\n}","finalize":"// Code added here will be run when the\n// node is being stopped or re-deployed.\ncontext.set(\"piscina\",{})","libs":[{"var":"pis","module":"piscina"},{"var":"fs","module":"fs"},{"var":"os","module":"os"},{"var":"process","module":"process"},{"var":"path","module":"path"}],"x":210,"y":60,"wires":[[]]},{"id":"752a76d98d97af39","type":"status","z":"fde3bd1da88bc03c","name":"","scope":null,"x":240,"y":140,"wires":[[]]},{"id":"1e80d9526ad0c4ee","type":"function","z":"9215deec580c5391","name":"Post-process","func":"function chunk(arr, chunkSize) {\n if (chunkSize <= 0) throw \"Invalid chunk size\";\n var R = [];\n for (var i = 0, len = arr.length; i < len; i += chunkSize)\n R.push(arr.slice(i, i + chunkSize));\n return R;\n}\n\ntry{\n let ready = flow.get(\"ready\") || false;\n\n if (ready){\n \n let start = Date.now()\n let inference_result = msg.payload;\n let results = [];\n const modelName = env.get(\"model_name\")\n const model = flow.get(modelName);\n const labels = model.parameters.labels;\n const metadata = model.parameters.metadata;\n const ts = msg.ts;\n let post_process_time = 0;\n const threshold = env.get(\"threshold\")\n msg.threshold = threshold;\n const image_width = msg.data.properties.object.data.width;\n const image_height = msg.data.properties.object.data.height;\n\n let scores;\n let boxes;\n let names;\n let newObject;\n\n for(let i=0;i<(inference_result.outputs).length;i++){ \n if(inference_result.outputs[i][\"name\"] == \"detection_scores\"){\n scores = inference_result.outputs[i].data\n }\n else if(inference_result.outputs[i][\"name\"] == \"detection_boxes\"){\n boxes = inference_result.outputs[i].data\n boxes = chunk(boxes,4) \n }\n else if(inference_result.outputs[i][\"name\"] == \"detection_classes\"){\n names = inference_result.outputs[i].data \n }\n } \n\n for (let i = 0; i < scores.length; i++) {\n if (scores[i] > threshold) {\n newObject = {\n \"bbox\":[\n boxes[i][1] * image_width,\n boxes[i][0] * image_height,\n (boxes[i][3] - boxes[i][1]) * image_width,\n (boxes[i][2] - boxes[i][0]) * image_height\n ],\n \"class\":labels[names[i]-1],\n \"label\":labels[names[i]-1],\n \"score\":scores[i],\n \"length_cm\":NaN\n }\n results.push(newObject)\n }\n }\n\n post_process_time = Date.now() - start; \n\n msg.data.properties.computer_vision.result = results;\n msg.data.properties.computer_vision.model = modelName;\n msg.data.properties.computer_vision.inference_time = msg.request_ms;\n msg.data.properties.computer_vision.type = \"object detection\";\n msg.data.properties.computer_vision.metadata = metadata;\n msg.data.properties.computer_vision.labels = labels;\n msg.data.properties.computer_vision.threshold = msg.threshold;\n msg.data.properties.computer_vision.validated = false;\n msg.data.properties.computer_vision.post_process_time = post_process_time;\n\n msg.payload = msg.tensor.image;\n delete msg.tensor;\n delete msg.request_ms;\n\n const objects_count = results.length\n\n if (objects_count > 0 ){ \n msg.objects_found = true \n node.status({ fill: \"blue\", shape: \"dot\", text: \"Objects found:\" + objects_count});\n return msg;\n }\n else{\n node.status({fill: \"red\", shape: \"dot\", text: \" No objects over threshold: \" +threshold});\n return msg;\n }\n \n }\n else{\n node.status({ fill: \"red\", shape: \"dot\", text: \"Modeldata is not loaded\"});\n return null;\n }\n}\ncatch(e){\n node.error(\"Post process failed.\", msg);\n return null;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":120,"wires":[[]]},{"id":"bc716e2cbc7c0995","type":"http request","z":"9215deec580c5391","name":"status request","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":500,"y":220,"wires":[["c42a4bd0916459d6"]]},{"id":"e070e6af761a0137","type":"function","z":"9215deec580c5391","name":"request","func":"let modelName = env.get(\"model_name\")\nlet serverUrl = env.get(\"server_url\")\n\nmsg.requestTimeout = 1000;\nmsg.method = \"GET\";\nmsg.url = serverUrl+\"/v2/models/\"+modelName+\"/config\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":220,"wires":[["bc716e2cbc7c0995"]]},{"id":"c42a4bd0916459d6","type":"function","z":"9215deec580c5391","name":"status","func":"let statusCode = msg.statusCode;\nlet parsed_value;\nlet modelName = env.get(\"model_name\")\n\nif(statusCode == 200){\n let model_data = msg.payload;\n parsed_value = JSON.parse(model_data.parameters.metadata.string_value)\n model_data.parameters.labels = parsed_value.labels\n model_data.parameters.metadata = parsed_value.metadata\n flow.set(\"ready\",true) \n node.status({fill:\"green\",shape:\"dot\",text:\" Model configuration loaded.\"}); \n flow.set(modelName,model_data) \n return null;\n}\nelse{\n flow.set(\"ready\",false)\n node.status({fill:\"red\",shape:\"dot\",text:msg.statusCode+\": \"+\"Server is not ready or model not found.\"}); \n return msg\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":220,"wires":[["7169ecadae48d625"]]},{"id":"973d9f1bf645853c","type":"inject","z":"9215deec580c5391","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"ready","payloadType":"flow","x":110,"y":220,"wires":[["e070e6af761a0137"]]},{"id":"b93022c83cb00303","type":"status","z":"9215deec580c5391","name":"","scope":["1e80d9526ad0c4ee","c42a4bd0916459d6"],"x":500,"y":360,"wires":[[]]},{"id":"7169ecadae48d625","type":"delay","z":"9215deec580c5391","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":120,"y":300,"wires":[["e070e6af761a0137"]]},{"id":"5b933476.fc386c","type":"http request","z":"fcd42407.59d1a8","name":"POST","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":true,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":450,"y":100,"wires":[["5b3e2fe4.4c3f9"]]},{"id":"f17ef03d.d18bf","type":"function","z":"fcd42407.59d1a8","name":"HTTP request","func":"let times_to_try;\nlet token;\n\nif('token' in msg){\n times_to_try = env.get(\"times_to_try\")\n token = msg.token;\n msg.data = msg.payload;\n msg.method = \"POST\";\n msg.url = env.get(\"API_URL\")+\"/api/v1/image/add\"\n msg.headers = {\n \"Content-Type\": \"application/json\",\n 'Authorization': \"Bearer \"+token \n };\n node.status({fill:\"blue\",shape:\"dot\",text:\"Sending image...\"})\n return [msg,null];\n}\nelse{\n times_to_try = env.get(\"times_to_try\")\n token = msg.token;\n msg.data = msg.payload;\n msg.method = \"POST\";\n msg.url = env.get(\"API_URL\")+\"/api/v1/image/add\"\n msg.headers = {\n \"Content-Type\": \"application/json\",\n 'Authorization': \"Bearer \"+token \n };\n msg.statusCode = 401;\n node.status({fill:\"red\",shape:\"dot\",text:\"msg.token is missing\"})\n return [null,msg];\n}","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":40,"wires":[["5b933476.fc386c"],["5b3e2fe4.4c3f9"]]},{"id":"5b3e2fe4.4c3f9","type":"switch","z":"fcd42407.59d1a8","name":"statusCode?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"eq","v":"201","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":630,"y":100,"wires":[["68394e6b.8b877"],["68394e6b.8b877"],["b6efc528.054bc8"]]},{"id":"f4f14ebd.6e975","type":"link out","z":"fcd42407.59d1a8","name":"","links":["d1c084fc.4da468"],"x":1175,"y":120,"wires":[]},{"id":"d1c084fc.4da468","type":"link in","z":"fcd42407.59d1a8","name":"Try again","links":["f4f14ebd.6e975"],"x":55,"y":100,"wires":[["a8257482.0d16e8"]]},{"id":"b6efc528.054bc8","type":"function","z":"fcd42407.59d1a8","name":"Format for resend","func":"let times_to_try = env.get(\"times_to_try\")\n\nif(msg.times_to_try >= times_to_try){\n node.status({fill:\"red\",shape:\"dot\",text:msg.statusCode+\": \"+msg.payload.message})\n msg.times_to_try = msg.times_to_try + 1\n return msg;\n}\nelse{\n msg.payload = msg.data\n msg.times_to_try = msg.times_to_try + 1\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Trying again... \"+msg.times_to_try+\"/\"+times_to_try})\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":830,"y":120,"wires":[["e8a7bd1f.28f73"]]},{"id":"e8a7bd1f.28f73","type":"delay","z":"fcd42407.59d1a8","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"5","randomLast":"10","randomUnits":"seconds","drop":false,"outputs":1,"x":1020,"y":120,"wires":[["f4f14ebd.6e975"]]},{"id":"9363fb9a.c3f578","type":"status","z":"fcd42407.59d1a8","name":"","scope":["f17ef03d.d18bf","b6efc528.054bc8","f6e7b71a.50b0f8","9fb35f6f.022b","ca8420ca.fbcfa"],"x":1040,"y":340,"wires":[[]]},{"id":"f6e7b71a.50b0f8","type":"function","z":"fcd42407.59d1a8","name":"Status","func":"node.status({fill:\"green\",shape:\"dot\",text:\"Image sent @\"+msg.sent_timestamp+\" in \"+msg.send_time+\" ms\"})\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1070,"y":60,"wires":[[]]},{"id":"aba7379c.9aec88","type":"change","z":"fcd42407.59d1a8","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":40,"wires":[["f17ef03d.d18bf"]]},{"id":"68394e6b.8b877","type":"change","z":"fcd42407.59d1a8","name":"end timer","rules":[{"t":"set","p":"send_time","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":60,"wires":[["8a74eebe.fdbc8"]]},{"id":"80c6d087.30ca7","type":"change","z":"fcd42407.59d1a8","name":"","rules":[{"t":"set","p":"times_to_try","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":200,"y":40,"wires":[["aba7379c.9aec88"]]},{"id":"a8257482.0d16e8","type":"switch","z":"fcd42407.59d1a8","name":"times_to_try?","property":"times_to_try","propertyType":"msg","rules":[{"t":"gt","v":"times_to_try","vt":"env"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":180,"y":100,"wires":[["2164bc8e0654a805"],["aba7379c.9aec88"]]},{"id":"9fb35f6f.022b","type":"file","z":"fcd42407.59d1a8","name":"","filename":"filename","filenameType":"msg","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":620,"y":220,"wires":[["ca8420ca.fbcfa"]]},{"id":"3faa6785.3e0888","type":"function","z":"fcd42407.59d1a8","name":"Format filename","func":"let name = (msg.data.properties.object.data.original.objectname).split(\".\")[0]\nconst platform = os.platform()\nlet base_path = env.get(\"path\")\n\nif (platform == \"win32\"){\n msg.filename = base_path + \"\\\\\" + \"tequ_api_images\" + \"\\\\\" +msg.ts_for_file + \"\\\\\" + name + \".json\";\n}\nelse{\n msg.filename = base_path + \"/\" + \"tequ_api_images\" + \"/\" + msg.ts_for_file + \"/\" + name + \".json\";\n}\nmsg.payload = msg.data;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"os","module":"os"}],"x":440,"y":220,"wires":[["9fb35f6f.022b"]]},{"id":"ca8420ca.fbcfa","type":"function","z":"fcd42407.59d1a8","name":"Update status","func":"node.status({fill:\"blue\",shape:\"dot\",text:\"Payload saved to file.\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":220,"wires":[]},{"id":"235873ad.c9440c","type":"moment","z":"fcd42407.59d1a8","name":"","topic":"","input":"","inputType":"date","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"YYYY-MM-DD","locale":"en-US","output":"ts_for_file","outputType":"msg","outTz":"ETC/UTC","x":200,"y":220,"wires":[["3faa6785.3e0888"]]},{"id":"8a74eebe.fdbc8","type":"moment","z":"fcd42407.59d1a8","name":"ts","topic":"","input":"","inputType":"date","inTz":"Europe/Kiev","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH:mm:ss","locale":"en-US","output":"sent_timestamp","outputType":"msg","outTz":"Europe/Kiev","x":950,"y":60,"wires":[["f6e7b71a.50b0f8"]]},{"id":"2164bc8e0654a805","type":"switch","z":"fcd42407.59d1a8","name":"Save failed","property":"save_failed","propertyType":"env","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":170,"y":160,"wires":[["235873ad.c9440c"]]},{"id":"dfacae6d.01672","type":"function","z":"ffeafac1.b0db18","name":"App-ID Token","func":"if(msg.topic == \"force_update\"){\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Forced update.\"})\n}\nelse{\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Updating token...\"})\n}\n\nlet username = env.get(\"username\");\nlet password = env.get(\"password\");\n\nmsg.url = env.get(\"API_URL\")+\"/api/v1/token\"\nmsg.method = 'POST';\n\nmsg.payload = {\n \"grant_type\":\"password\",\n \"username\":username,\n \"password\":password\n};\n\nmsg.headers = {\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":720,"y":280,"wires":[["bffe1286.5564"]]},{"id":"bffe1286.5564","type":"http request","z":"ffeafac1.b0db18","name":"req","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":890,"y":300,"wires":[["c4734d48.7f0ff"]]},{"id":"c4734d48.7f0ff","type":"function","z":"ffeafac1.b0db18","name":"Parse response","func":"var token = msg.payload.access_token;\nvar decoded = jwtDecode(token);\nmsg.payload = {\n \"decoded\":decoded,\n \"token\":token\n}\nnode.status({fill:\"green\",shape:\"dot\",text:\"Token updated.\"})\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"jwtDecode","module":"jwt-decode"}],"x":1060,"y":300,"wires":[[]]},{"id":"db473541.b967b8","type":"switch","z":"ffeafac1.b0db18","name":"check keys","property":"payload","propertyType":"msg","rules":[{"t":"hask","v":"exp","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":230,"y":200,"wires":[["50252e9e.d28d4"],["dfacae6d.01672"]]},{"id":"50252e9e.d28d4","type":"function","z":"ffeafac1.b0db18","name":"Check token","func":"let jwt = msg.payload;\nlet time_left = jwt.exp - Math.round(new Date().getTime()/1000);\n\nif(time_left > 120){\n node.status({fill:\"green\",shape:\"dot\",text:\"TOKEN OK. \"+time_left+\" s left.\"})\n msg.do_login = false;\n}\nelse{\n node.status({fill:\"red\",shape:\"dot\",text:\"Token expired. LOGIN again\"})\n msg.do_login = true;\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":140,"wires":[["2c7d2b4f.126d34"]]},{"id":"2c7d2b4f.126d34","type":"switch","z":"ffeafac1.b0db18","name":"LOGIN?","property":"do_login","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":700,"y":200,"wires":[["dfacae6d.01672"]]},{"id":"d7310f56.fb383","type":"switch","z":"ffeafac1.b0db18","name":"Force update","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"force_update","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":230,"y":140,"wires":[["dfacae6d.01672"],["db473541.b967b8"]]},{"id":"6096db38.546e94","type":"status","z":"ffeafac1.b0db18","name":"","scope":["dfacae6d.01672","c4734d48.7f0ff","50252e9e.d28d4","431c0f8ee889f44d"],"x":1080,"y":360,"wires":[[]]},{"id":"431c0f8ee889f44d","type":"function","z":"ffeafac1.b0db18","name":"Status","func":"node.status({fill:\"red\",shape:\"dot\",text:\"Please supply decoded token in msg.payload\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":340,"wires":[]},{"id":"eb06f89989a8028c","type":"function","z":"75015de274d71273","name":"Format payload","func":"const newMsg = {\n \"payload\":msg.data\n }\nreturn newMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":200,"wires":[[]]},{"id":"77e4f7126f22a6a9","type":"function","z":"75015de274d71273","name":"enabled?","func":"const enabled = env.get(\"enable\")\nconst objects_found = msg.objects_found;\n\nif(enabled){\n \n if (objects_found){\n node.status({ fill: \"green\", shape: \"dot\", text: \"Tequ-API enabled\" });\n return msg;\n }\n else{\n node.status({ fill: \"yellow\", shape: \"dot\", text: \"Tequ-API enabled, but no annotated objects\" });\n return null;\n } \n}\nelse{\n node.status({ fill: \"red\", shape: \"dot\", text: \"Tequ-API disabled\" });\n return null;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":280,"y":200,"wires":[["eb06f89989a8028c"]]},{"id":"40ba865bf8f26d27","type":"status","z":"75015de274d71273","name":"","scope":null,"x":480,"y":280,"wires":[[]]},{"id":"449388bafc5ced99","type":"inject","z":"04508fd4d91dd935","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":100,"wires":[["fe9c51b3673ce6ee"]]},{"id":"bb209580ff5b4836","type":"debug","z":"04508fd4d91dd935","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":470,"y":60,"wires":[]},{"id":"5d12eb90f740fdd6","type":"debug","z":"04508fd4d91dd935","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":470,"y":100,"wires":[]},{"id":"fe9c51b3673ce6ee","type":"daemon","z":"04508fd4d91dd935","name":"RTSP server","command":"/home/nvidia/rtsp-simple-server/rtsp-simple-server","args":"/home/nvidia/rtsp-simple-server/rtsp-simple-server.yml","autorun":true,"cr":true,"redo":true,"op":"string","closer":"SIGKILL","x":270,"y":100,"wires":[["bb209580ff5b4836"],["5d12eb90f740fdd6"],["03372fcec2f8d5be"]]},{"id":"f4e0dab8f6118c77","type":"comment","z":"04508fd4d91dd935","name":"Start local RTSP server ","info":"","x":160,"y":40,"wires":[]},{"id":"03372fcec2f8d5be","type":"debug","z":"04508fd4d91dd935","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":470,"y":140,"wires":[]},{"id":"b50216a2b31d801b","type":"inject","z":"332da02c8e396138","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"kill","x":130,"y":180,"wires":[["d22449da926eb9b1"]]},{"id":"d22449da926eb9b1","type":"subflow:fa7f491898fed374","z":"332da02c8e396138","name":"gst Basler 40198132","env":[{"name":"serial","value":"40198132","type":"str"},{"name":"pfs_file","value":"/home/nvidia/basler/40198132.pfs","type":"str"},{"name":"mjpeg_width","value":"854","type":"num"},{"name":"mjpeg_height","value":"480","type":"num"},{"name":"rtsp_width","value":"1920","type":"num"},{"name":"rtsp_height","value":"1080","type":"num"},{"name":"rtsp_encoder","value":"nvv4l2h264enc","type":"str"},{"name":"framerate","value":"5","type":"num"}],"x":360,"y":140,"wires":[["21f2142dbe030a40"]]},{"id":"9e2794684ea9e823","type":"link in","z":"332da02c8e396138","name":"40198132 in","links":["3b4445143b5d37b1"],"x":165,"y":140,"wires":[["d22449da926eb9b1"]]},{"id":"21f2142dbe030a40","type":"debug","z":"332da02c8e396138","name":"Log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":140,"wires":[]},{"id":"927817224e3149a0","type":"comment","z":"332da02c8e396138","name":"Start GStreamer and connect to Basler camera using camera Serial number","info":"","x":290,"y":20,"wires":[]},{"id":"9a51f17f7e58e6b4","type":"comment","z":"332da02c8e396138","name":"Encode camera video stream and publish to local RTSP server","info":"","x":240,"y":100,"wires":[]},{"id":"1eba6a95dbad0f45","type":"comment","z":"332da02c8e396138","name":"Encode camera video as JPEGs and stream to local TCP port","info":"","x":240,"y":60,"wires":[]},{"id":"d4ebf66b500dad1b","type":"inject","z":"332da02c8e396138","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"kill","x":130,"y":660,"wires":[["7dd7c5a7f5314cc1"]]},{"id":"7dd7c5a7f5314cc1","type":"subflow:fa7f491898fed374","z":"332da02c8e396138","name":"gst Logitech USB","env":[{"name":"video_source","value":"v4l2src","type":"str"},{"name":"serial","value":"7B5B8BEF","type":"str"},{"name":"model","value":"C920","type":"str"},{"name":"manufacturer","value":"Logitech","type":"str"},{"name":"pfs_file","value":"/home/nvidia/basler/40257292.pfs","type":"str"},{"name":"mjpeg_width","value":"854","type":"num"},{"name":"mjpeg_height","value":"480","type":"num"},{"name":"rtsp_width","value":"1920","type":"num"},{"name":"rtsp_height","value":"1080","type":"num"},{"name":"rtsp_encoder","value":"nvv4l2h264enc","type":"str"},{"name":"tcp_port","value":"50005","type":"num"},{"name":"video_width","value":"1920","type":"num"},{"name":"video_height","value":"1080","type":"num"},{"name":"source","value":"v4l2src","type":"str"},{"name":"framerate","value":"5","type":"num"}],"x":350,"y":620,"wires":[["4de2647b516d1319"]]},{"id":"62afd8f704123c20","type":"link in","z":"332da02c8e396138","name":"7B5B8BEF in","links":["a37348d8d7ae1f3f"],"x":165,"y":620,"wires":[["7dd7c5a7f5314cc1"]]},{"id":"4de2647b516d1319","type":"debug","z":"332da02c8e396138","name":"Log","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":620,"wires":[]},{"id":"ed93794d274d7aef","type":"inject","z":"332da02c8e396138","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"kill","x":130,"y":300,"wires":[["4e3b1a76597c53a5"]]},{"id":"4e3b1a76597c53a5","type":"subflow:fa7f491898fed374","z":"332da02c8e396138","name":"gst Basler 40204286","env":[{"name":"serial","value":"40204286","type":"str"},{"name":"model","value":"a2A1920-51gcBAS","type":"str"},{"name":"pfs_file","value":"/home/nvidia/basler/40204286.pfs","type":"str"},{"name":"mjpeg_width","value":"854","type":"num"},{"name":"mjpeg_height","value":"480","type":"num"},{"name":"rtsp_width","value":"1920","type":"num"},{"name":"rtsp_height","value":"1080","type":"num"},{"name":"rtsp_encoder","value":"nvv4l2h264enc","type":"str"},{"name":"tcp_port","value":"50002","type":"num"},{"name":"video_width","value":"1920","type":"num"},{"name":"video_height","value":"1080","type":"num"},{"name":"framerate","value":"5","type":"num"}],"x":360,"y":260,"wires":[["0688c070e94081dc"]]},{"id":"0a7e634d4d49d373","type":"link in","z":"332da02c8e396138","name":"40204286 in","links":["c0fff134ee4db2b1"],"x":165,"y":260,"wires":[["4e3b1a76597c53a5"]]},{"id":"0688c070e94081dc","type":"debug","z":"332da02c8e396138","name":"Log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":260,"wires":[]},{"id":"2bd46203d03cb145","type":"inject","z":"332da02c8e396138","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"kill","x":130,"y":420,"wires":[["c6a2768cb3417cf4"]]},{"id":"c6a2768cb3417cf4","type":"subflow:fa7f491898fed374","z":"332da02c8e396138","name":"gst Basler 23751808","env":[{"name":"serial","value":"23751808","type":"str"},{"name":"model","value":"acA2500-14gc","type":"str"},{"name":"pfs_file","value":"/home/nvidia/basler/23751808.pfs","type":"str"},{"name":"mjpeg_width","value":"854","type":"num"},{"name":"mjpeg_height","value":"480","type":"num"},{"name":"rtsp_width","value":"1920","type":"num"},{"name":"rtsp_height","value":"1080","type":"num"},{"name":"rtsp_encoder","value":"nvv4l2h264enc","type":"str"},{"name":"tcp_port","value":"50003","type":"num"},{"name":"video_width","value":"1920","type":"num"},{"name":"video_height","value":"1080","type":"num"},{"name":"framerate","value":"5","type":"num"}],"x":360,"y":380,"wires":[["31af4aa6052b9fba"]]},{"id":"92e8a7d66c8c071d","type":"link in","z":"332da02c8e396138","name":"23751808 in","links":["26b4ce0463d68d31"],"x":165,"y":380,"wires":[["c6a2768cb3417cf4"]]},{"id":"31af4aa6052b9fba","type":"debug","z":"332da02c8e396138","name":"Log","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":380,"wires":[]},{"id":"3bf6fb6ba30bb1e1","type":"inject","z":"332da02c8e396138","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"kill","x":130,"y":540,"wires":[["4a2cc9178b29a26a"]]},{"id":"4a2cc9178b29a26a","type":"subflow:fa7f491898fed374","z":"332da02c8e396138","name":"gst Basler 40165426","env":[{"name":"serial","value":"40165426","type":"str"},{"name":"model","value":"daA1920-160uc","type":"str"},{"name":"pfs_file","value":"/home/nvidia/basler/40165426.pfs","type":"str"},{"name":"mjpeg_width","value":"854","type":"num"},{"name":"mjpeg_height","value":"480","type":"num"},{"name":"rtsp_width","value":"1920","type":"num"},{"name":"rtsp_height","value":"1080","type":"num"},{"name":"rtsp_encoder","value":"nvv4l2h264enc","type":"str"},{"name":"tcp_port","value":"50004","type":"num"},{"name":"video_width","value":"1920","type":"num"},{"name":"video_height","value":"1080","type":"num"},{"name":"framerate","value":"5","type":"num"}],"x":360,"y":500,"wires":[["8fc342caccf8cf01"]]},{"id":"3452909bcf1104dc","type":"link in","z":"332da02c8e396138","name":"40165426 in","links":["4d8dd9bdeb149f4e"],"x":165,"y":500,"wires":[["4a2cc9178b29a26a"]]},{"id":"8fc342caccf8cf01","type":"debug","z":"332da02c8e396138","name":"Log","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":500,"wires":[]},{"id":"dfefe6ec0d823cdb","type":"inject","z":"332da02c8e396138","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"start","payload":"","payloadType":"date","x":130,"y":220,"wires":[["d22449da926eb9b1"]]},{"id":"7e1f54714e033b22","type":"inject","z":"332da02c8e396138","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"start","payload":"","payloadType":"date","x":130,"y":340,"wires":[["4e3b1a76597c53a5"]]},{"id":"e72b4e201d69a778","type":"inject","z":"332da02c8e396138","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"10","topic":"start","payload":"","payloadType":"date","x":130,"y":460,"wires":[["c6a2768cb3417cf4"]]},{"id":"d95ead55994a9bac","type":"inject","z":"332da02c8e396138","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"15","topic":"start","payload":"","payloadType":"date","x":130,"y":700,"wires":[["7dd7c5a7f5314cc1"]]},{"id":"66a41dc3b851b4c0","type":"inject","z":"332da02c8e396138","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"15","topic":"start","payload":"","payloadType":"date","x":130,"y":580,"wires":[["4a2cc9178b29a26a"]]},{"id":"3097982829e635f4","type":"tcp in","z":"0d2c119e1f2d1adf","name":"","server":"server","host":"localhost","port":"50001","datamode":"stream","datatype":"buffer","newline":"","topic":"","trim":false,"base64":false,"tls":"","x":110,"y":80,"wires":[["09f9c5151ea072ae"]]},{"id":"3b4445143b5d37b1","type":"link out","z":"0d2c119e1f2d1adf","name":"40198132 wd out","mode":"link","links":["9e2794684ea9e823"],"x":625,"y":60,"wires":[]},{"id":"09f9c5151ea072ae","type":"subflow:21dbb5f62f40368e","z":"0d2c119e1f2d1adf","name":"Parse JPEG","env":[{"name":"thumbnail_width","value":"50","type":"num"}],"x":310,"y":80,"wires":[["ecf6867daa7efe37"]]},{"id":"ecf6867daa7efe37","type":"subflow:d9dd49bd747346d4","z":"0d2c119e1f2d1adf","name":"","x":480,"y":80,"wires":[["3b4445143b5d37b1"],["105f5bee0e3a36ca"]]},{"id":"105f5bee0e3a36ca","type":"link out","z":"0d2c119e1f2d1adf","name":"JPEGs out","mode":"link","links":["70b287d622b1444c","d4207e520d8f51aa"],"x":625,"y":100,"wires":[]},{"id":"a2db749f57aed2eb","type":"catch","z":"0d2c119e1f2d1adf","name":"","scope":null,"uncaught":false,"x":320,"y":480,"wires":[["13cf22af4398336a"]]},{"id":"13cf22af4398336a","type":"debug","z":"0d2c119e1f2d1adf","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":480,"y":480,"wires":[]},{"id":"e881009b9922778f","type":"comment","z":"0d2c119e1f2d1adf","name":"Receive JPEG stream from GStreamer, parse JPEGs","info":"","x":220,"y":20,"wires":[]},{"id":"46ef424e1329d0e0","type":"tcp in","z":"0d2c119e1f2d1adf","name":"","server":"server","host":"localhost","port":"50002","datamode":"stream","datatype":"buffer","newline":"","topic":"","trim":false,"base64":false,"tls":"","x":110,"y":160,"wires":[["2b9a067d1d51300f"]]},{"id":"2b9a067d1d51300f","type":"subflow:21dbb5f62f40368e","z":"0d2c119e1f2d1adf","name":"Parse JPEG","env":[{"name":"thumbnail_width","value":"50","type":"num"}],"x":310,"y":160,"wires":[["f8c41698802555a4"]]},{"id":"f8c41698802555a4","type":"subflow:d9dd49bd747346d4","z":"0d2c119e1f2d1adf","name":"","x":480,"y":160,"wires":[["c0fff134ee4db2b1"],["4523844c7f21ed3e"]]},{"id":"c0fff134ee4db2b1","type":"link out","z":"0d2c119e1f2d1adf","name":"40204286 wd out","mode":"link","links":["0a7e634d4d49d373"],"x":625,"y":140,"wires":[]},{"id":"4523844c7f21ed3e","type":"link out","z":"0d2c119e1f2d1adf","name":"JPEGs out","mode":"link","links":["70b287d622b1444c","d4207e520d8f51aa"],"x":625,"y":180,"wires":[]},{"id":"44df495bd3c675eb","type":"tcp in","z":"0d2c119e1f2d1adf","name":"","server":"server","host":"localhost","port":"50003","datamode":"stream","datatype":"buffer","newline":"","topic":"","trim":false,"base64":false,"tls":"","x":110,"y":240,"wires":[["ef8072728c6e5dd8"]]},{"id":"ef8072728c6e5dd8","type":"subflow:21dbb5f62f40368e","z":"0d2c119e1f2d1adf","name":"Parse JPEG","env":[{"name":"thumbnail_width","value":"50","type":"num"}],"x":310,"y":240,"wires":[["660b3c7140b82c3f"]]},{"id":"660b3c7140b82c3f","type":"subflow:d9dd49bd747346d4","z":"0d2c119e1f2d1adf","name":"","x":480,"y":240,"wires":[["26b4ce0463d68d31"],["a0e008ef8a207cdc"]]},{"id":"26b4ce0463d68d31","type":"link out","z":"0d2c119e1f2d1adf","name":"link out 7","mode":"link","links":["92e8a7d66c8c071d"],"x":625,"y":220,"wires":[]},{"id":"518652e9183c5353","type":"tcp in","z":"0d2c119e1f2d1adf","name":"","server":"server","host":"localhost","port":"50004","datamode":"stream","datatype":"buffer","newline":"","topic":"","trim":false,"base64":false,"tls":"","x":110,"y":320,"wires":[["1e49447be12298ce"]]},{"id":"1e49447be12298ce","type":"subflow:21dbb5f62f40368e","z":"0d2c119e1f2d1adf","name":"Parse JPEG","env":[{"name":"thumbnail_width","value":"50","type":"num"}],"x":310,"y":320,"wires":[["7f073b7bfd59c9ef"]]},{"id":"7f073b7bfd59c9ef","type":"subflow:d9dd49bd747346d4","z":"0d2c119e1f2d1adf","name":"","x":480,"y":320,"wires":[["a37348d8d7ae1f3f"],["aad43f8362deb0db"]]},{"id":"a37348d8d7ae1f3f","type":"link out","z":"0d2c119e1f2d1adf","name":"link out 9","mode":"link","links":["62afd8f704123c20"],"x":625,"y":300,"wires":[]},{"id":"aad43f8362deb0db","type":"link out","z":"0d2c119e1f2d1adf","name":"JPEGs out","mode":"link","links":["70b287d622b1444c","d4207e520d8f51aa"],"x":625,"y":340,"wires":[]},{"id":"68c0af34d09c9788","type":"tcp in","z":"0d2c119e1f2d1adf","name":"","server":"server","host":"localhost","port":"50005","datamode":"stream","datatype":"buffer","newline":"","topic":"","trim":false,"base64":false,"tls":"","x":110,"y":400,"wires":[["08a0931fbd0ff07b"]]},{"id":"08a0931fbd0ff07b","type":"subflow:21dbb5f62f40368e","z":"0d2c119e1f2d1adf","name":"Parse JPEG","env":[{"name":"thumbnail_width","value":"50","type":"num"}],"x":310,"y":400,"wires":[["f1497197cff1631f"]]},{"id":"f1497197cff1631f","type":"subflow:d9dd49bd747346d4","z":"0d2c119e1f2d1adf","name":"","x":480,"y":400,"wires":[["4d8dd9bdeb149f4e"],["c1c1f56ebd3de480"]]},{"id":"4d8dd9bdeb149f4e","type":"link out","z":"0d2c119e1f2d1adf","name":"link out 11","mode":"link","links":["3452909bcf1104dc"],"x":625,"y":380,"wires":[]},{"id":"c1c1f56ebd3de480","type":"link out","z":"0d2c119e1f2d1adf","name":"JPEGs out","mode":"link","links":["70b287d622b1444c","d4207e520d8f51aa"],"x":625,"y":420,"wires":[]},{"id":"a0e008ef8a207cdc","type":"link out","z":"0d2c119e1f2d1adf","name":"JPEGs out","mode":"link","links":["70b287d622b1444c","d4207e520d8f51aa"],"x":625,"y":260,"wires":[]},{"id":"be61237047ae3829","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":40,"wires":[[]]},{"id":"0ac85f383fec55a1","type":"switch","z":"48bebe191b6a13b3","name":"Camera ID?","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"40198132","vt":"str"},{"t":"eq","v":"40204286","vt":"str"},{"t":"eq","v":"23751808","vt":"str"},{"t":"eq","v":"7B5B8BEF","vt":"str"},{"t":"eq","v":"40165426","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":490,"y":140,"wires":[["be61237047ae3829"],["7e75b156c672fd99"],["3d4df113393045f8"],["6badc516311bbc93"],["81bc80b9962f9719"]]},{"id":"a8b547526768ea32","type":"http in","z":"48bebe191b6a13b3","name":"","url":"/camera/id/:id/stream/:stream","method":"get","upload":false,"swaggerDoc":"","x":140,"y":180,"wires":[["4d5762753792d92c"]]},{"id":"d4207e520d8f51aa","type":"link in","z":"48bebe191b6a13b3","name":"JPEGs in","links":["105f5bee0e3a36ca","4523844c7f21ed3e","a0e008ef8a207cdc","aad43f8362deb0db","c1c1f56ebd3de480"],"x":265,"y":140,"wires":[["0ac85f383fec55a1"]]},{"id":"61c36ce572b971fc","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":340,"wires":[[]]},{"id":"d70ae79ef0a8cec0","type":"switch","z":"48bebe191b6a13b3","name":"Camera ID?","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"40198132","vt":"str"},{"t":"eq","v":"40204286","vt":"str"},{"t":"eq","v":"23751808","vt":"str"},{"t":"eq","v":"7B5B8BEF","vt":"str"},{"t":"eq","v":"40165426","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":490,"y":260,"wires":[["61c36ce572b971fc"],["aa6a016fdc3ec555"],["b4261f19d43368c0"],["f272d481759380d4"],["83896b1d90baa00e"]]},{"id":"bb3a8984bab22f98","type":"http in","z":"48bebe191b6a13b3","name":"","url":"/camera/id/:id/annotated/:stream","method":"get","upload":false,"swaggerDoc":"","x":170,"y":420,"wires":[["a5f76fa67e18419b"]]},{"id":"a7845144eea23474","type":"link in","z":"48bebe191b6a13b3","name":"Annoated JPEGs in","links":["4239127242a1d3f6","b5228a1b05f81a58"],"x":175,"y":260,"wires":[["7388910e1b0f790b"]]},{"id":"7388910e1b0f790b","type":"function","z":"48bebe191b6a13b3","name":"base64 -> buffer","func":"if (msg.data.properties.object.data.annotated.image !== \"\"){\n msg.payload = Buffer.from(msg.data.properties.object.data.annotated.image, 'base64');\n}\nelse{\n // do not change payload\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":260,"wires":[["d70ae79ef0a8cec0","bcd067bd40f1e579"]]},{"id":"cd9fd91e206fca37","type":"comment","z":"48bebe191b6a13b3","name":"http://localhost:1880/camera/id/40257292/annotated/1","info":"","x":200,"y":60,"wires":[]},{"id":"97a1c861f21d777e","type":"comment","z":"48bebe191b6a13b3","name":"http://localhost:1880/camera/id/40257292/stream/1","info":"","x":190,"y":100,"wires":[]},{"id":"6517a19f1fdd0eb0","type":"comment","z":"48bebe191b6a13b3","name":"Publish camera original video and annotated data as MJPEG","info":"","x":220,"y":20,"wires":[]},{"id":"7e75b156c672fd99","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":100,"wires":[[]]},{"id":"aa6a016fdc3ec555","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":400,"wires":[[]]},{"id":"3d4df113393045f8","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":160,"wires":[[]]},{"id":"b4261f19d43368c0","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":460,"wires":[[]]},{"id":"6badc516311bbc93","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":220,"wires":[[]]},{"id":"f272d481759380d4","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":520,"wires":[[]]},{"id":"81bc80b9962f9719","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":280,"wires":[[]]},{"id":"83896b1d90baa00e","type":"multipart-encoder","z":"48bebe191b6a13b3","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":810,"y":580,"wires":[[]]},{"id":"a5f76fa67e18419b","type":"change","z":"48bebe191b6a13b3","name":"set","rules":[{"t":"set","p":"topic","pt":"msg","to":"req.params.id","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":360,"wires":[["d70ae79ef0a8cec0"]]},{"id":"4d5762753792d92c","type":"change","z":"48bebe191b6a13b3","name":"set","rules":[{"t":"set","p":"topic","pt":"msg","to":"req.params.id","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":180,"wires":[["0ac85f383fec55a1"]]},{"id":"bcd067bd40f1e579","type":"debug","z":"48bebe191b6a13b3","name":"debug 43","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":500,"y":360,"wires":[]},{"id":"70b287d622b1444c","type":"link in","z":"88f8f06219122b1d","name":"Inference in","links":["1a1e99dab44074a2","71b7dd85b470b336","aad55414b42e6d99","de819fd13c6758ed","e382c1f02ee35cf6","4523844c7f21ed3e","105f5bee0e3a36ca","a0e008ef8a207cdc","aad43f8362deb0db","c1c1f56ebd3de480"],"x":165,"y":80,"wires":[["8d2c0d8b504f5e3c"]]},{"id":"9721d71a45af7eb5","type":"msg-speed","z":"88f8f06219122b1d","name":"Inferences","frequency":"sec","interval":"1","estimation":true,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":870,"y":200,"wires":[[],["b56dbf4649869c7f"]]},{"id":"370ef41edc3f7b8a","type":"subflow:83a7a965.1808a8","z":"88f8f06219122b1d","name":"","env":[{"name":"threshold","value":"0.80","type":"num"},{"name":"labels","value":"[\"fish\",\"perch\", \"pike\", \"rainbow trout\", \"salmon\", \"trout\", \"cyprinidae\", \"zander\", \"smolt\", \"bream\", \"teddy_bear\"]","type":"json"}],"x":940,"y":360,"wires":[["4239127242a1d3f6"]]},{"id":"4239127242a1d3f6","type":"link out","z":"88f8f06219122b1d","name":"Processed data out","mode":"link","links":["04594dde36b63fea","a7845144eea23474"],"x":1115,"y":360,"wires":[]},{"id":"e0d971f1bdb1c5d0","type":"catch","z":"88f8f06219122b1d","name":"","scope":null,"uncaught":false,"x":120,"y":500,"wires":[["c8ca5ddecdb7b754"]]},{"id":"c8ca5ddecdb7b754","type":"debug","z":"88f8f06219122b1d","name":"debug 10","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":280,"y":500,"wires":[]},{"id":"f250c0709c7a33e1","type":"comment","z":"88f8f06219122b1d","name":"Convert image to tensor and send Tensor to Triton Inference Server, process response and annotate it","info":"","x":390,"y":20,"wires":[]},{"id":"8d2c0d8b504f5e3c","type":"random-output","z":"88f8f06219122b1d","name":"rnd","outputs":4,"useWeights":false,"weights":["1","3","3","3","1"],"x":90,"y":280,"wires":[["0b5e87a85ae01a92","7338505a38a56291"],["0b5e87a85ae01a92","f7bf2150aa06ab9c"],["0b5e87a85ae01a92","2ab913e5d264f577"],["0b5e87a85ae01a92","fe270303ec501006"]]},{"id":"e15802e24fdc8a4d","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8010","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"},{"name":"rate_limit_ms","value":"1000","type":"num"}],"x":580,"y":200,"wires":[["9721d71a45af7eb5"]]},{"id":"b56dbf4649869c7f","type":"subflow:9215deec580c5391","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8010","type":"str"},{"name":"threshold","value":"0.60","type":"num"}],"x":890,"y":280,"wires":[["370ef41edc3f7b8a"]]},{"id":"8fc0e996bd18ec10","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8020","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"},{"name":"rate_limit_ms","value":"1000","type":"num"}],"x":580,"y":260,"wires":[["9721d71a45af7eb5"]]},{"id":"7338505a38a56291","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":290,"y":200,"wires":[["e15802e24fdc8a4d"]]},{"id":"f7bf2150aa06ab9c","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":290,"y":260,"wires":[["8fc0e996bd18ec10"]]},{"id":"0b5e87a85ae01a92","type":"msg-speed","z":"88f8f06219122b1d","name":"images","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":280,"y":140,"wires":[[],[]]},{"id":"94fb34abee55b6c2","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8030","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"},{"name":"rate_limit_ms","value":"1000","type":"num"}],"x":580,"y":320,"wires":[["9721d71a45af7eb5"]]},{"id":"093dc3d7014c8a1d","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8040","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"},{"name":"rate_limit_ms","value":"1000","type":"num"}],"x":580,"y":380,"wires":[["9721d71a45af7eb5"]]},{"id":"2ab913e5d264f577","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":290,"y":320,"wires":[["94fb34abee55b6c2"]]},{"id":"fe270303ec501006","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":290,"y":380,"wires":[["093dc3d7014c8a1d"]]},{"id":"cb08d5c4f7d028a4","type":"comment","z":"88f8f06219122b1d","name":"You can use local or remote Triton here","info":"","x":590,"y":140,"wires":[]},{"id":"082771590bd65966","type":"comment","z":"9baae2baa8d6b1c7","name":"Start Triton Inference Server in multiple Dockers","info":"","x":220,"y":20,"wires":[]},{"id":"50cc98aa6ef19343","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 17","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":180,"wires":[]},{"id":"9f176bad102d9916","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 18","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":220,"wires":[]},{"id":"dec57918c3fc39ef","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":260,"wires":[]},{"id":"a9b0e7e1026709ef","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":220,"wires":[["17727c001180e47a"]]},{"id":"b72eb0783ff35f2f","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":60,"wires":[]},{"id":"59646a804798ed3f","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 21","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":100,"wires":[]},{"id":"a131f967956dd191","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 22","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":140,"wires":[]},{"id":"4553da76f4261f77","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":100,"wires":[["ddfa1169c57b0442"]]},{"id":"17727c001180e47a","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8020","command":"docker","args":"run --rm -p8020:8000 -p8021:8001 -p8022:8002 -v /home/nvidia/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":220,"wires":[["50cc98aa6ef19343"],["9f176bad102d9916"],["dec57918c3fc39ef","977f7c2bef187e2e"]]},{"id":"ddfa1169c57b0442","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8010","command":"docker","args":"run --rm -p8010:8000 -p8011:8001 -p8012:8002 -v /home/nvidia/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":100,"wires":[["b72eb0783ff35f2f"],["59646a804798ed3f"],["a131f967956dd191","977f7c2bef187e2e"]]},{"id":"bc6e11416e47f742","type":"exec","z":"9baae2baa8d6b1c7","command":"docker ps","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":220,"y":660,"wires":[["cd58ae7a65883e9a"],["ced3ba1d9e1136b3"],["586eb208f10fb950"]]},{"id":"b12af62701f9eb2e","type":"inject","z":"9baae2baa8d6b1c7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":720,"wires":[["bc6e11416e47f742"]]},{"id":"20858d1d90159c41","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 27","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":860,"y":580,"wires":[]},{"id":"ced3ba1d9e1136b3","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 28","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":680,"wires":[]},{"id":"586eb208f10fb950","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 29","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":500,"y":720,"wires":[]},{"id":"cd58ae7a65883e9a","type":"split","z":"9baae2baa8d6b1c7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":370,"y":580,"wires":[["8eb8bc474d1db305"]]},{"id":"8eb8bc474d1db305","type":"join","z":"9baae2baa8d6b1c7","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":510,"y":620,"wires":[["5a9860316b7627f7"]]},{"id":"5a9860316b7627f7","type":"function","z":"9baae2baa8d6b1c7","name":"Get running docker ids","func":"let values = (msg.payload).slice(1);;\nnode.warn(values)\nlet params;\n\nfor(let value in values){\n let item = values[value]\n if(item.length > 5){\n node.send({\"payload\":item.split(\" \")[0]})\n }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":680,"y":620,"wires":[["20858d1d90159c41","4c8547a23123be74"]]},{"id":"4c8547a23123be74","type":"exec","z":"9baae2baa8d6b1c7","command":"docker stop ","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":870,"y":620,"wires":[["d1c0f1c5853f1f31"],["4cff2888777ec2dc"],["1108a8961e17efa5"]]},{"id":"d1c0f1c5853f1f31","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 30","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1040,"y":580,"wires":[]},{"id":"4cff2888777ec2dc","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 31","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1040,"y":620,"wires":[]},{"id":"1108a8961e17efa5","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 32","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1040,"y":660,"wires":[]},{"id":"977f7c2bef187e2e","type":"delay","z":"9baae2baa8d6b1c7","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":690,"y":260,"wires":[["1b6122abdafec689"]]},{"id":"1b6122abdafec689","type":"link out","z":"9baae2baa8d6b1c7","name":"link out 5","mode":"link","links":["d2ddf97bf235b212"],"x":825,"y":260,"wires":[]},{"id":"d2ddf97bf235b212","type":"link in","z":"9baae2baa8d6b1c7","name":"reset dockers","links":["1b6122abdafec689"],"x":125,"y":620,"wires":[["bc6e11416e47f742"]]},{"id":"0b9bece6c192d7e2","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 34","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":420,"wires":[]},{"id":"d4f4f331567780d1","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 35","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":460,"wires":[]},{"id":"8e616bfaa20e0f05","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 36","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":500,"wires":[]},{"id":"d6c50685526a1d33","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":460,"wires":[["cea536d5b0f1b2c8"]]},{"id":"621e15a090eac72a","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 37","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":300,"wires":[]},{"id":"e2cc8b25298fba9a","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 38","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":340,"wires":[]},{"id":"adc69e75ccaaff9e","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 39","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":380,"wires":[]},{"id":"df12917451cc824e","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":340,"wires":[["528e26e95bea2eb4"]]},{"id":"cea536d5b0f1b2c8","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8040","command":"docker","args":"run --rm -p8040:8000 -p8041:8001 -p8042:8002 -v /home/nvidia/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":460,"wires":[["0b9bece6c192d7e2"],["d4f4f331567780d1"],["8e616bfaa20e0f05","977f7c2bef187e2e"]]},{"id":"528e26e95bea2eb4","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8030","command":"docker","args":"run --rm -p8030:8000 -p8031:8001 -p8032:8002 -v /home/nvidia/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":340,"wires":[["621e15a090eac72a"],["e2cc8b25298fba9a"],["adc69e75ccaaff9e","977f7c2bef187e2e"]]},{"id":"52e35c5d.d8e104","type":"subflow:ffeafac1.b0db18","z":"7028b45bb7803169","name":"","env":[{"name":"username","value":"[email protected]","type":"str"},{"name":"password","type":"cred"}],"x":360,"y":300,"wires":[["db3f33c75e9f51fb"],[]]},{"id":"b0758ccf.21a41","type":"inject","z":"7028b45bb7803169","name":"Update token","props":[{"p":"payload"}],"repeat":"300","crontab":"","once":true,"onceDelay":"30","topic":"","payload":"token[\"decoded\"]","payloadType":"global","x":160,"y":300,"wires":[["52e35c5d.d8e104"]]},{"id":"8f4bf4f73e26688e","type":"debug","z":"7028b45bb7803169","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":300,"wires":[]},{"id":"db3f33c75e9f51fb","type":"change","z":"7028b45bb7803169","name":"Set token","rules":[{"t":"set","p":"token","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":300,"wires":[["8f4bf4f73e26688e"]]},{"id":"6bc9e7e2d59b278b","type":"debug","z":"7028b45bb7803169","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":710,"y":200,"wires":[]},{"id":"dbde31fc9471a462","type":"change","z":"7028b45bb7803169","name":"Get token","rules":[{"t":"set","p":"token","pt":"msg","to":"token[\"token\"]","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":180,"y":200,"wires":[["66e4f850.ae1f38"]]},{"id":"66e4f850.ae1f38","type":"subflow:fcd42407.59d1a8","z":"7028b45bb7803169","name":"","env":[{"name":"path","value":"/tmp/","type":"str"},{"name":"API_BASE_URL","value":"http://tequ-api-node-red-app","type":"str"}],"x":370,"y":200,"wires":[["6bc9e7e2d59b278b"]]},{"id":"b183c2acc2169c3e","type":"inject","z":"7028b45bb7803169","name":"Force update","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"force_update","x":170,"y":340,"wires":[["52e35c5d.d8e104"]]},{"id":"04594dde36b63fea","type":"link in","z":"7028b45bb7803169","name":"Images in","links":["4239127242a1d3f6"],"x":215,"y":100,"wires":[["665a5d3aba0311ec"]]},{"id":"2cd49072a5b2376b","type":"debug","z":"7028b45bb7803169","name":"debug 41","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":720,"y":100,"wires":[]},{"id":"046093f3b1f5fb48","type":"catch","z":"7028b45bb7803169","name":"","scope":null,"uncaught":false,"x":380,"y":400,"wires":[["b448b4d7d5b51c67"]]},{"id":"b448b4d7d5b51c67","type":"debug","z":"7028b45bb7803169","name":"debug 42","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":720,"y":400,"wires":[]},{"id":"665a5d3aba0311ec","type":"subflow:75015de274d71273","z":"7028b45bb7803169","name":"[API] Format data","env":[{"name":"enable","value":"false","type":"bool"}],"x":370,"y":100,"wires":[["2cd49072a5b2376b","dbde31fc9471a462"]]},{"id":"fccfbea89d6171eb","type":"comment","z":"7028b45bb7803169","name":"Images in","info":"","x":120,"y":100,"wires":[]}]
Example flow 2
- Connects to MJPEG streams
- Parses JPEG streams
- Converts Images to Tensor
- Makes inference using Triton Inference Server
- Post-process image files
- Annotates image files
- Formats and sends annotated images to Tequ-API
[{"id":"9356e3543f8bbd88","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"95ebe51baa66ead1","type":"tab","label":"Streams","disabled":false,"info":"","env":[]},{"id":"88f8f06219122b1d","type":"tab","label":"Inference","disabled":false,"info":"","env":[]},{"id":"9baae2baa8d6b1c7","type":"tab","label":"Triton","disabled":false,"info":"","env":[]},{"id":"3ec4ce3c762176f0","type":"tab","label":"Tequ-API","disabled":true,"info":"","env":[]},{"id":"83a7a965.1808a8","type":"subflow","name":"[IMG] Annotate","info":"","category":"Tequ-API Client","in":[{"x":120,"y":140,"wires":[{"id":"d05bfd8e.a02e"}]}],"out":[{"x":1080,"y":140,"wires":[{"id":"4e5f5c6c.bcf214","port":0}]}],"env":[{"name":"box_colors","type":"json","value":"{\"fish\":\"#FFFFFF\",\"pike\":\"#006400\",\"perch\":\"#008000\",\"smolt\":\"#ADD8E6\",\"salmon\":\"#0000FF\",\"trout\":\"#0000FF\",\"cyprinidae\":\"#808080\",\"zander\":\"#009000\",\"bream\":\"#008800\"}","ui":{"type":"input","opts":{"types":["json"]}}},{"name":"image_settings","type":"json","value":"{\"quality\":0.8}","ui":{"type":"input","opts":{"types":["json"]}}},{"name":"image_type","type":"str","value":"image/jpeg","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"JPG"},"v":"image/jpeg"},{"l":{"en-US":"PNG"},"v":"image/png"}]}}},{"name":"bbox_lineWidth","type":"num","value":"5","ui":{"type":"spinner","opts":{"min":0,"max":10}}},{"name":"bbox_text_color","type":"str","value":"white","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"white"},"v":"white"},{"l":{"en-US":"black"},"v":"black"},{"l":{"en-US":"blue"},"v":"blue"},{"l":{"en-US":"green"},"v":"green"},{"l":{"en-US":"yellow"},"v":"yellow"},{"l":{"en-US":"red"},"v":"red"},{"l":{"en-US":"orange"},"v":"orange"}]}}},{"name":"bbox_font","type":"str","value":"30px Arial","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"5px Arial"},"v":"5 px Arial"},{"l":{"en-US":"10px Arial"},"v":"10px Arial"},{"l":{"en-US":"15px Arial"},"v":"15px Arial"},{"l":{"en-US":"20px Arial"},"v":"20px Arial"},{"l":{"en-US":"25px Arial"},"v":"25px Arial"},{"l":{"en-US":"30px Arial"},"v":"30px Arial"},{"l":{"en-US":"35px Arial"},"v":"35px Arial"},{"l":{"en-US":"40px Arial"},"v":"40px Arial"},{"l":{"en-US":"45px Arial"},"v":"45px Arial"},{"l":{"en-US":"50px Arial"},"v":"50px Arial"}]}}},{"name":"label_offset_x","type":"num","value":"0","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"label_offset_y","type":"num","value":"30","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"threshold","type":"num","value":"0.75","ui":{"type":"spinner","opts":{"min":0,"max":1}}}],"meta":{"module":"[IMG] Annotate","version":"0.0.1","author":"[email protected]","desc":"Annotates prediction results from [AI] Detect subflows.","license":"MIT"},"color":"#87A980","icon":"font-awesome/fa-pencil-square-o","status":{"x":1080,"y":340,"wires":[{"id":"7fd4f6bf24348b12","port":0}]}},{"id":"fa7f491898fed374","type":"subflow","name":"gst-jetson","info":"","category":"Tequ-API Client","in":[{"x":120,"y":200,"wires":[{"id":"54dc40fe44895f9a"}]}],"out":[{"x":1100,"y":120,"wires":[{"id":"ab1595a359c8a71b","port":0},{"id":"dd701ced077fb628","port":0},{"id":"361321e30bc9bba9","port":0},{"id":"d86014e70dadc4b2","port":0}]}],"env":[{"name":"video_source","type":"str","value":"pylonsrc","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"pylonsrc"},"v":"pylonsrc"},{"l":{"en-US":"v4l2src"},"v":"v4l2src"}]}}},{"name":"v4l2_device","type":"str","value":"/dev/video0","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"serial","type":"str","value":"40257292","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"model","type":"str","value":"daA3840-45uc","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"manufacturer","type":"str","value":"Basler","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"pfs_file","type":"str","value":"/home/tequ/40257292.pfs","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"enable_mjpeg","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool"]}}},{"name":"mjpeg_width","type":"num","value":"1920","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_height","type":"num","value":"1080","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_framerate","type":"num","value":"5","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_font_size","type":"num","value":"8","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"enable_rtsp","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool"]}}},{"name":"rtsp_width","type":"num","value":"3840","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_height","type":"num","value":"2160","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_font_size","type":"str","value":"4","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"rtsp_server","type":"str","value":"rtsp://localhost:8554/","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"rtsp_framerate","type":"num","value":"10","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_encoder","type":"str","value":"nvv4l2h265enc","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"nvv4l2h265enc"},"v":"nvv4l2h265enc"},{"l":{"en-US":"nvv4l2h264enc"},"v":"nvv4l2h264enc"}]}}},{"name":"tcp_host","type":"str","value":"localhost","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"tcp_port","type":"num","value":"50001","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"video_width","type":"num","value":"3840","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"video_height","type":"num","value":"2160","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"video_type","type":"str","value":"video/x-raw","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"video_format","type":"str","value":"YUY2","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"video_framerate","type":"num","value":"10","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-basler-gst-jetson","version":"0.0.1","author":"[email protected]","desc":"Launch and control GStreamer pipelines.","license":"MIT"},"color":"#3FADB5","inputLabels":["command in"],"outputLabels":["info out"],"icon":"node-red/bridge.svg","status":{"x":1060,"y":360,"wires":[{"id":"6abd0b160a7877dd","port":0}]}},{"id":"d9dd49bd747346d4","type":"subflow","name":"gst WD","info":"","category":"Tequ-API Client","in":[{"x":80,"y":60,"wires":[{"id":"4676b6d77fb4c9fd"}]}],"out":[{"x":840,"y":220,"wires":[{"id":"67250f6441a6d8f2","port":0}]},{"x":780,"y":60,"wires":[{"id":"4676b6d77fb4c9fd","port":1}]}],"env":[],"meta":{},"color":"#3FADB5","inputLabels":["Stream data in"],"outputLabels":["Restart cmd out",""],"icon":"font-awesome/fa-search","status":{"x":780,"y":340,"wires":[{"id":"42e72deef2a5b5b1","port":0}]}},{"id":"fd51dfdc3367d25c","type":"subflow","name":"Triton request","info":"Sends request to NVIDIA Triton Inference Server.\r\n\r\nExpects \"msg.tensor\" to be present in input\r\n\r\n\r\n \"msg.tensor.data\" and \r\n\r\n\r\n\r\n","category":"Tequ-API Client","in":[{"x":100,"y":100,"wires":[{"id":"837af87e0b706d16"}]}],"out":[{"x":980,"y":100,"wires":[{"id":"7451b5b3b174fc54","port":0}]}],"env":[{"name":"server_url","type":"str","value":"localhost:8000","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"model_name","type":"str","value":"tequ-fish-species-detection","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"request_timeout","type":"num","value":"10000","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"rate_limit_ms","type":"num","value":"0","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-triton-request","version":"0.0.1","author":"[email protected]","desc":"Send request to Triton Inference server.","license":"MIT"},"color":"#3FADB5","icon":"font-awesome/fa-globe","status":{"x":980,"y":180,"wires":[{"id":"5368623e2deefd7e","port":0}]}},{"id":"fde3bd1da88bc03c","type":"subflow","name":"Image to Tensor","info":"Converts input image (msg.payload) to Tensor.\r\n\r\nOutputs results in \"msg.tensor\".","category":"Tequ-API Client","in":[{"x":60,"y":60,"wires":[{"id":"557647c8b195bdea"}]}],"out":[{"x":380,"y":60,"wires":[{"id":"557647c8b195bdea","port":0}]}],"env":[],"meta":{"module":"tequ-image-to-tensor","version":"0.0.1","author":"[email protected]","desc":"Converts image to tensor.","license":"MIT"},"color":"#3FADB5","icon":"node-red/swap.svg","status":{"x":380,"y":140,"wires":[{"id":"752a76d98d97af39","port":0}]}},{"id":"9215deec580c5391","type":"subflow","name":"Post-process","info":"Post process result from Triton request.\r\n","category":"Tequ-API Client","in":[{"x":100,"y":120,"wires":[{"id":"1e80d9526ad0c4ee"}]}],"out":[{"x":970,"y":120,"wires":[{"id":"1e80d9526ad0c4ee","port":0}]}],"env":[{"name":"model_name","type":"str","value":"ssd-example-model","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"server_url","type":"str","value":"localhost:8000","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"threshold","type":"num","value":"0.5","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-triton-post-process","version":"0.0.1","author":"[email protected]","desc":"Post-process Triton request.","license":"MIT"},"color":"#3FADB5","inputLabels":["Triton request result in"],"outputLabels":["Processed output"],"icon":"font-awesome/fa-compress","status":{"x":740,"y":360,"wires":[{"id":"b93022c83cb00303","port":0}]}},{"id":"fcd42407.59d1a8","type":"subflow","name":"[API] Send image","info":"This node sends single image to Tequ-API. \n\nEndpoint used is /image/add\n\nYou need to add Bearer token to msg.token.\n\nYou can configure maximum times to try sending by parameter \"times_to_try\" in node config.","category":"Tequ-API Client","in":[{"x":40,"y":40,"wires":[{"id":"80c6d087.30ca7"}]}],"out":[{"x":1220,"y":60,"wires":[{"id":"f6e7b71a.50b0f8","port":0}]}],"env":[{"name":"API_URL","type":"str","value":"https://api.tequ.fi"},{"name":"times_to_try","type":"num","value":"3","ui":{"type":"spinner","opts":{"min":1,"max":10}}},{"name":"save_failed","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}},{"name":"path","type":"str","value":"/home/nvidia/"}],"meta":{"license":"MIT"},"color":"#FFCC66","inputLabels":["Data in"],"outputLabels":["Data out"],"icon":"node-red/white-globe.svg","status":{"x":1180,"y":340,"wires":[{"id":"9363fb9a.c3f578","port":0}]}},{"id":"ffeafac1.b0db18","type":"subflow","name":"[API] Get Token","info":"Username and password for login are configured in settings-file.\n\nprocess.env.client_email = \"email\";\nprocess.env.client_password = \"password\";\n\nPlease contact Tequ-API administrator to get credentials.\n\n[https://api.tequ.fi]()","category":"Tequ-API Client","in":[{"x":80,"y":140,"wires":[{"id":"d7310f56.fb383"}]}],"out":[{"x":1220,"y":300,"wires":[{"id":"c4734d48.7f0ff","port":0}]},{"x":1220,"y":140,"wires":[{"id":"50252e9e.d28d4","port":0}]}],"env":[{"name":"username","type":"str","value":"client_email","ui":{"icon":"font-awesome/fa-user-o"}},{"name":"password","type":"str","value":"client_password","ui":{"icon":"font-awesome/fa-lock","type":"input","opts":{"types":["str","env","cred"]}}},{"name":"API_URL","type":"str","value":"https://api.tequ.fi"}],"meta":{"license":"MIT"},"color":"#FFCC66","icon":"node-red/envelope.svg","status":{"x":1220,"y":360,"wires":[{"id":"6096db38.546e94","port":0}]}},{"id":"75015de274d71273","type":"subflow","name":"Format for Tequ-API","info":"","category":"Tequ-API Client","in":[{"x":140,"y":200,"wires":[{"id":"77e4f7126f22a6a9"}]}],"out":[{"x":750,"y":200,"wires":[{"id":"eb06f89989a8028c","port":0}]}],"env":[{"name":"enable","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}}],"meta":{"version":"0.0.1","author":"[email protected]","desc":"Format payload from [AI]Annotate to Tequ-API compatible format. Enable / disable sending to API.","license":"MIT"},"color":"#FFCC66","inputLabels":["Connect to \"[IMG] Annotate\" output "],"outputLabels":["Connect to \"[API] Send image\" input"],"icon":"node-red/sort.svg","status":{"x":620,"y":280,"wires":[{"id":"40ba865bf8f26d27","port":0}]}},{"id":"1810b5ccd40a609b","type":"subflow","name":"[CAM] MJPEG stream","info":"Provides MJPEG data stream to [AI] Detect subflows. \n\nIP-cameras with MJPEG support are compatible.\n\nTested with Basler BIP2-series cameras.\n\nstream_url:\nFor example, in Basler camera, URL is:\n- http://<ip>/cgi-bin/mjpeg?mode=live&stream=1&fps=5\n\nstream_id:\nThis parameter is id which is used to identify datasource in Tequ-API.\n\nhttps://tequ-api.eu-de-mybluemix.net","category":"Tequ-API Client","in":[{"x":80,"y":80,"wires":[{"id":"b1b20213f85b0885"}]}],"out":[{"x":1230,"y":140,"wires":[{"id":"3bd6b5fde8e8d55d","port":0}]},{"x":1190,"y":200,"wires":[{"id":"c6162b2ea8fee499","port":0}]},{"x":1200,"y":260,"wires":[{"id":"d14829fe158c91d7","port":0}]}],"env":[{"name":"stream_url","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"stream_id","type":"str","value":"","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"limited_stream_rate","type":"str","value":"1000","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"0.5 frames / s"},"v":"2000"},{"l":{"en-US":"1 frames / s"},"v":"1000"},{"l":{"en-US":"5 frames / s"},"v":"200"},{"l":{"en-US":"7.5 frames / s"},"v":"150"},{"l":{"en-US":"10 frames / s"},"v":"100"},{"l":{"en-US":"20 frames / s"},"v":"50"},{"l":{"en-US":"25 frames / s"},"v":"40"},{"l":{"en-US":"50 frames / s"},"v":"20"}]}}}],"meta":{"version":"0.0.1","author":"[email protected]","desc":"Provides MJPEG data stream to [AI] Detect subflows.","license":"MIT"},"color":"#A6BBCF","inputLabels":["Inject to start"],"outputLabels":["Stream speed out [ frames / s]","Limited stream out","Full speed stream out"],"icon":"font-awesome/fa-video-camera","status":{"x":1120,"y":320,"wires":[{"id":"ad67dfe697063dac","port":0}]}},{"id":"5d5c83b6c13135a8","type":"subflow","name":"Parse JPEG ","info":"Parses JPEG image from MJPEG stream and adds metadata to msg.\r\n\r\nReads or adds:\r\n - Basic image info (width,height,size) \r\n - Exif data\r\n - Local timestamp, UTC timestamp, Unix timestamp \r\n - Thumbnail of the original image\r\n - Coordinates (if given)\r\n\r\n Output message is formatted to Tequ-API compatible format.\r\n\r\n","category":"Tequ-API Client","in":[{"x":40,"y":60,"wires":[{"id":"d62df9289b1bd8f3"}]}],"out":[{"x":960,"y":480,"wires":[{"id":"c34da99ee513c4c1","port":1}]}],"env":[{"name":"is_stream","type":"bool","value":"true","ui":{"label":{"en-US":"is_stream?"},"type":"input","opts":{"types":["bool","env"]}}},{"name":"latitude","type":"num","value":"66.503059","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"longitude","type":"num","value":"25.726967","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"thumbnail","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}},{"name":"width","type":"num","value":"50","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-parse-mjpeg","version":"0.0.1","author":"[email protected]","desc":"Parse JPEG from stream and add metadata to image","license":"MIT"},"color":"#3FADB5","inputLabels":["MJPEG stream in"],"outputLabels":["image out"],"icon":"font-awesome/fa-image","status":{"x":780,"y":540,"wires":[{"id":"d2a991ca2c10cafd","port":0}]}},{"id":"c19ac6bd.2a9d08","type":"function","z":"83a7a965.1808a8","name":"Annotate with canvas","func":"const img = msg.payload;\nconst objects = msg.data.properties.computer_vision.result\nconst labels = msg.data.properties.computer_vision.labels\n\nconst image_type = env.get(\"image_type\");\nconst image_settings = env.get(\"image_settings\");\nconst bbox_lineWidth = env.get(\"bbox_lineWidth\");\nconst bbox_text_color = env.get(\"bbox_text_color\");\nconst label_offset_x = env.get(\"label_offset_x\");\nconst label_offset_y = env.get(\"label_offset_y\");\nconst bbox_font = env.get(\"bbox_font\");\nconst COLORS = env.get(\"box_colors\");\n\n\n//Define threshold\nlet threshold = 0;\n\nconst global_settings = global.get(\"settings\") || undefined\nlet thresholdType = \"\"\n\nif(global_settings !== undefined){\n if(\"threshold\" in global_settings){\n threshold = global_settings[\"threshold\"]\n thresholdType = \"global\";\n }\n}\n\nelse if(\"threshold\" in msg){\n threshold = msg.threshold;\n thresholdType = \"msg\";\n if(threshold < 0){\n threshold = 0\n }\n else if(threshold > 1){\n threshold = 1\n }\n}\n\nelse{\n threshold = env.get(\"threshold\");\n thresholdType = \"env\";\n}\n\nmsg.thresholdUsed = threshold;\nmsg.thresholdTypeUsed = thresholdType;\n\nasync function annotateImage(image) {\n const localImage = await canvas.loadImage(image); \n const cvs = canvas.createCanvas(localImage.width, localImage.height);\n const ctx = cvs.getContext('2d'); \n ctx.drawImage(localImage, 0, 0); \n \n objects.forEach((obj) => {\n if(labels.includes(obj.class) && obj.score >= threshold){\n let [x, y, w, h] = obj.bbox;\n ctx.lineWidth = bbox_lineWidth;\n ctx.strokeStyle = COLORS[obj.class];\n ctx.strokeRect(x, y, w, h);\n ctx.fillStyle = bbox_text_color;\n ctx.font = bbox_font;\n ctx.fillText(obj.class+\" \"+Math.round(obj.score*100)+\" %\",x+label_offset_x,y+label_offset_y);\n }\n });\n \n return cvs.toBuffer(image_type, image_settings);\n}\n\nif(objects.length > 0){\n msg.data.properties.object.data.annotated.image = await annotateImage(img) \n msg.objects_found = true\n}\nelse{\n msg.objects_found = false\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"canvas","module":"canvas"}],"x":440,"y":140,"wires":[["a801355d.9f7ac8"]]},{"id":"d05bfd8e.a02e","type":"change","z":"83a7a965.1808a8","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":140,"wires":[["c19ac6bd.2a9d08"]]},{"id":"a801355d.9f7ac8","type":"change","z":"83a7a965.1808a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.annotated.annotation_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"},{"t":"set","p":"payload.annotation.objects_found","pt":"msg","to":"objects_found","tot":"msg"},{"t":"delete","p":"annotated_image","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":140,"wires":[["c20a6448.e6f218"]]},{"id":"4e5f5c6c.bcf214","type":"change","z":"83a7a965.1808a8","name":"delete useless","rules":[{"t":"delete","p":"annotated_image","pt":"msg"},{"t":"delete","p":"start","pt":"msg"},{"t":"delete","p":"resize_start","pt":"msg"},{"t":"delete","p":"thresholdTypeUsed","pt":"msg"},{"t":"delete","p":"threshold","pt":"msg"},{"t":"delete","p":"thresholdUsed","pt":"msg"},{"t":"delete","p":"start","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":140,"wires":[[]]},{"id":"c20a6448.e6f218","type":"switch","z":"83a7a965.1808a8","name":"objects found?","property":"objects_found","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":260,"wires":[["5fae1e95eb3561e9"],["0ec56ca8f000a540"]]},{"id":"a9379cd1321a02da","type":"function","z":"83a7a965.1808a8","name":"","func":"node.status({ fill: \"green\", shape: \"dot\", text: msg.thresholdTypeUsed + \" \" + msg.thresholdUsed + \" in \" + msg.data.properties.object.data.annotated.total_ms+\" ms\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1040,"y":240,"wires":[]},{"id":"0ec56ca8f000a540","type":"function","z":"83a7a965.1808a8","name":"","func":"node.status({fill:\"green\",shape:\"dot\",text:msg.thresholdTypeUsed+\" \"+msg.thresholdUsed+\" No objects to annotate\"})\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":300,"wires":[["4e5f5c6c.bcf214"]]},{"id":"7fd4f6bf24348b12","type":"status","z":"83a7a965.1808a8","name":"","scope":null,"x":860,"y":340,"wires":[[]]},{"id":"5fae1e95eb3561e9","type":"change","z":"83a7a965.1808a8","name":"timer","rules":[{"t":"set","p":"resize_start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":240,"wires":[["f5809fcdc54a540e"]]},{"id":"f5809fcdc54a540e","type":"function","z":"83a7a965.1808a8","name":"resize","func":"let input = msg.data.properties.object.data.annotated.image;\n\nlet resized = await sharp(input)\n .metadata()\n .then(({ width }) => sharp(input)\n .resize({ width: 200 })\n .toBuffer()\n);\n\nmsg.data.properties.object.data.annotated.thumbnail = resized.toString('base64');\nmsg.data.properties.object.data.annotated.image = (msg.data.properties.object.data.annotated.image).toString('base64')\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"sharp","module":"sharp"}],"x":630,"y":240,"wires":[["e0f13103c7faabff"]]},{"id":"e0f13103c7faabff","type":"change","z":"83a7a965.1808a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.annotated.thumbnail_ms","pt":"msg","to":"$millis() - msg.resize_start","tot":"jsonata"},{"t":"set","p":"data.properties.object.data.annotated.total_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":240,"wires":[["4e5f5c6c.bcf214","a9379cd1321a02da"]]},{"id":"d9a2420055236c2b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"SIGTERM","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":120,"wires":[["99ac100731d2d825"]]},{"id":"be99e21d6ee788c1","type":"function","z":"fa7f491898fed374","name":"construct gst pipeline","func":"let serial = env.get(\"serial\");\nlet model = env.get(\"model\");\nlet pfs_file = env.get(\"pfs_file\");\nlet source = env.get(\"video_source\");\nlet v4l2_device = env.get(\"v4l2_device\");\nlet manufacturer = env.get(\"manufacturer\");\n\nlet enable_rtsp = env.get(\"enable_rtsp\")\nlet rtsp_width = env.get(\"rtsp_width\");\nlet rtsp_height = env.get(\"rtsp_height\");\nlet rtsp_framerate = env.get(\"rtsp_framerate\");\nlet rtsp_encoder = env.get(\"rtsp_encoder\");\nlet rtsp_font_size = env.get(\"rtsp_font_size\");\nlet rtsp_server = env.get(\"rtsp_server\");\n\nlet enable_mjpeg = env.get(\"enable_mjpeg\")\nlet mjpeg_width = env.get(\"mjpeg_width\");\nlet mjpeg_height = env.get(\"mjpeg_height\");\nlet mjpeg_framerate = env.get(\"mjpeg_framerate\");\nlet mjpeg_font_size = env.get(\"mjpeg_font_size\");\n\n\nlet video_width = env.get(\"video_width\");\nlet video_height = env.get(\"video_height\");\nlet video_format = env.get(\"video_format\");\nlet video_type = env.get(\"video_type\");\nlet video_framerate = env.get(\"video_framerate\");\nlet tcp_host = env.get(\"tcp_host\");\nlet tcp_port = env.get(\"tcp_port\");\nlet gst_pipeline;\n\n\n\n\nlet gst_msg = {}\n\nif (source == \"pylonsrc\"){\n gst_pipeline = \n source + ' capture-error=skip device-serial-number=\"' + serial + '\" pfs-location=' + pfs_file; \n \n gst_pipeline = gst_pipeline + ' ! \"' + video_type + ',width=' + video_width + ',height=' + video_height + ',framerate=' + video_framerate + '/1,format=' + video_format+ '\"'; \n gst_pipeline = gst_pipeline + ' ! tee name = video_out';\n\n\n if (enable_mjpeg){\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + mjpeg_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + mjpeg_width + ',height=' + mjpeg_height + ',framerate=' + mjpeg_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! nvjpegenc ! taginject tags = \"application-name=tequ-gst-1.0,copyright=Lapland_UAS,description=serialnumber_' + serial + ',artist=Tequ,device-manufacturer=' + manufacturer +',device-model='+model+'\" ! jifmux ! queue ! tcpclientsink host='+tcp_host+' port='+tcp_port;\n }\n if (enable_rtsp){\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + rtsp_font_size +'\" ! videoscale ! videorate ! \"' + video_type + ',width=' + rtsp_width + ',height=' + rtsp_height + ',framerate=' + rtsp_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! ' +rtsp_encoder+' ! queue ! rtspclientsink location = '+rtsp_server+serial+'';\n }\n}\nelse if (source == \"v4l2src\"){\n gst_pipeline =\n source + ' device=\"' + v4l2_device+'\"'; \n gst_pipeline = gst_pipeline + ' ! videoscale ! \"' + video_type + ',width=' + video_width + ',height=' + video_height + ',framerate=' + video_framerate + '/1,format=' + video_format + '\"';\n gst_pipeline = gst_pipeline + ' ! tee name = video_out';\n\n if (enable_mjpeg) {\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + mjpeg_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + mjpeg_width + ',height=' + mjpeg_height + ',framerate=' + mjpeg_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! nvjpegenc ! taginject tags = \"application-name=tequ-gst-1.0,copyright=Lapland_UAS,description=serialnumber_' + serial + ',artist=Tequ,device-manufacturer=' + manufacturer + ',device-model=' + model + '\" ! jifmux ! queue ! tcpclientsink host=' + tcp_host + ' port=' + tcp_port;\n }\n if (enable_rtsp) {\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + rtsp_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + rtsp_width + ',height=' + rtsp_height + ',framerate=' + rtsp_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! ' + rtsp_encoder + ' ! queue ! rtspclientsink location = ' + rtsp_server + serial + '';\n }\n}\nelse {\n node.status({ fill: \"red\", shape: \"ring\", text: \"src: \" + source +\" is not supported\" });\n return null;\n}\n\ngst_msg.payload = gst_pipeline;\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Launching...\"});\nreturn gst_msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":320,"wires":[["99ac100731d2d825","ab1595a359c8a71b"]]},{"id":"99ac100731d2d825","type":"exec","z":"fa7f491898fed374","command":"gst-launch-1.0","addpay":"payload","append":"","useSpawn":"true","timer":"","winHide":false,"oldrc":false,"name":"gst-launch","x":710,"y":120,"wires":[["361321e30bc9bba9"],["dd701ced077fb628"],["d86014e70dadc4b2"]]},{"id":"8ba82764fc44edf8","type":"delay","z":"fa7f491898fed374","name":"","pauseType":"random","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"6","randomLast":"22","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":480,"y":240,"wires":[["be99e21d6ee788c1"]]},{"id":"f6110566b977602b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"SIGTERM","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":180,"wires":[["8ba82764fc44edf8","99ac100731d2d825"]]},{"id":"6abd0b160a7877dd","type":"status","z":"fa7f491898fed374","name":"","scope":["be99e21d6ee788c1","99ac100731d2d825","54dc40fe44895f9a"],"x":760,"y":360,"wires":[[]]},{"id":"54dc40fe44895f9a","type":"function","z":"fa7f491898fed374","name":"cmd?","func":"let topic = msg.topic;\n\nif(topic == \"kill\"){\n node.status({fill:\"red\",shape:\"ring\",text:\"cmd: kill\"});\n return [msg,null,null]\n}\nelse if (topic == \"restart\") {\n node.status({ fill: \"yellow\", shape: \"ring\", text: \"cmd: restart\" });\n return [null, msg, null]\n}\nelse if (topic == \"start\") {\n node.status({ fill: \"blue\", shape: \"ring\", text: \"cmd: start\" });\n return [null, null, msg]\n}\n\nreturn msg;","outputs":3,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":200,"wires":[["d9a2420055236c2b"],["f6110566b977602b"],["be99e21d6ee788c1"]]},{"id":"ab1595a359c8a71b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"pipeline-info","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":320,"wires":[[]]},{"id":"dd701ced077fb628","type":"change","z":"fa7f491898fed374","name":"stderr","rules":[{"t":"set","p":"topic","pt":"msg","to":"stderr","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":120,"wires":[[]]},{"id":"361321e30bc9bba9","type":"change","z":"fa7f491898fed374","name":"stdout","rules":[{"t":"set","p":"topic","pt":"msg","to":"stdout","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":80,"wires":[[]]},{"id":"d86014e70dadc4b2","type":"change","z":"fa7f491898fed374","name":"return code","rules":[{"t":"set","p":"topic","pt":"msg","to":"return code","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":160,"wires":[[]]},{"id":"4676b6d77fb4c9fd","type":"msg-speed","z":"d9dd49bd747346d4","name":"","frequency":"sec","interval":"5","estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":210,"y":60,"wires":[["75a772553f72adc5"],[]]},{"id":"75a772553f72adc5","type":"switch","z":"d9dd49bd747346d4","name":"== 0","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":190,"y":160,"wires":[["48bd712e32556613"]]},{"id":"48bd712e32556613","type":"delay","z":"d9dd49bd747346d4","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":210,"y":220,"wires":[["10b1bb59b99fd89e"]]},{"id":"10b1bb59b99fd89e","type":"trigger","z":"d9dd49bd747346d4","name":"","op1":"{\"topic\":\"restart\",\"payload\":\"ok\"}","op2":"","op1type":"json","op2type":"nul","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":380,"y":220,"wires":[["860b8a639262a949"]]},{"id":"67250f6441a6d8f2","type":"change","z":"d9dd49bd747346d4","name":"restart","rules":[{"t":"set","p":"topic","pt":"msg","to":"restart","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":220,"wires":[["abcd5255fa959167"]]},{"id":"abcd5255fa959167","type":"function","z":"d9dd49bd747346d4","name":"Restart","func":"node.status({fill:\"red\",shape:\"ring\",text:\"no data, restart\"});\nreturn msg;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":180,"wires":[]},{"id":"42e72deef2a5b5b1","type":"status","z":"d9dd49bd747346d4","name":"","scope":["4676b6d77fb4c9fd","abcd5255fa959167"],"x":640,"y":340,"wires":[[]]},{"id":"883688b62b7bec6b","type":"inject","z":"d9dd49bd747346d4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":130,"y":20,"wires":[["4676b6d77fb4c9fd"]]},{"id":"860b8a639262a949","type":"delay","z":"d9dd49bd747346d4","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"5","randomLast":"25","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":520,"y":220,"wires":[["67250f6441a6d8f2"]]},{"id":"b63e9a83f3001f21","type":"function","z":"fd51dfdc3367d25c","name":"Triton request","func":"if(\"tensor\" in msg){\n const serverUrl = env.get(\"server_url\");\n const modelName = env.get(\"model_name\");\n const requestTimeout = env.get(\"request_timeout\");\n const tensor_data = msg.tensor.data;\n const inference_header_length = msg.tensor.inference_header_length;\n\n //Construct Triton Inference Server HTTP API message\n msg.request_start = Date.now();\n msg.payload = tensor_data\n msg.method = \"POST\";\n msg.requestTimeout = requestTimeout;\n msg.url = serverUrl + \"/v2/models/\" + modelName + \"/infer\";\n msg.headers = {\n \"Content-Type\": \"application/octet-stream\",\n \"Inference-Header-Content-Length\": inference_header_length,\n };\n\n return msg;\n}\nelse{\n node.status({ fill: \"red\", shape: \"dot\", text: \"No msg.tensor in input msg\" });\n node.error(\"No msg.tensor in input msg\", msg);\n return null;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"// Code added here will be run when the\n// node is being stopped or re-deployed.\ncontext.set(\"piscina\",{})","libs":[{"var":"pis","module":"piscina"},{"var":"fs","module":"fs"},{"var":"zlib","module":"zlib"},{"var":"os","module":"os"},{"var":"process","module":"process"},{"var":"path","module":"path"}],"x":520,"y":100,"wires":[["3937c53e6f34bf73"]]},{"id":"3937c53e6f34bf73","type":"http request","z":"fd51dfdc3367d25c","name":"req","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":true,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":690,"y":100,"wires":[["7451b5b3b174fc54"]]},{"id":"5368623e2deefd7e","type":"status","z":"fd51dfdc3367d25c","name":"","scope":["b63e9a83f3001f21","7451b5b3b174fc54","7276cd4d5b2ed247","c9d10c33a635199d"],"x":680,"y":180,"wires":[[]]},{"id":"7451b5b3b174fc54","type":"function","z":"fd51dfdc3367d25c","name":"Process req","func":"let statuscode = msg.statusCode;\nlet request_ms = Date.now() - msg.request_start;\nlet color = \"\"\nlet rate_limit_ms = 0\nmsg.request_ms = request_ms\n\ntry{\n rate_limit_ms = parseInt(env.get(\"rate_limit_ms\"))\n}\ncatch(e){\n //\n}\n\nif (statuscode == 200){\n color = \"blue\"\n delete msg.request_start;\n delete msg.headers;\n delete msg.statusCode;\n delete msg.method;\n delete msg.retry;\n delete msg.url;\n delete msg.responseUrl;\n delete msg.requestTimeout;\n delete msg.redirectList;\n \n if(rate_limit_ms === 0){\n color = \"blue\"\n node.status({\n fill: color, shape: \"dot\", text: statuscode + \" | \" + request_ms + \" ms\"\n }); \n }\n else{\n color = \"yellow\"\n const rate = Math.round(1000 / rate_limit_ms*100)/100\n node.status({\n fill: color, shape: \"dot\", text: statuscode + \" | \" + request_ms + \" ms | \" + rate+\" msg/s\"\n }); \n }\n \n \n return msg;\n}\n\nelse{\n color = \"red\"\n node.status({ fill: color, shape: \"dot\", text: statuscode + \" | \"+msg.payload.error});\n node.error(\"Processing request failed\", msg);\n return null;\n} ","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":100,"wires":[[]]},{"id":"db3449811636781b","type":"http request","z":"fd51dfdc3367d25c","name":"status request","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":600,"y":420,"wires":[["c9d10c33a635199d"]]},{"id":"7276cd4d5b2ed247","type":"function","z":"fd51dfdc3367d25c","name":"request","func":"let modelName = env.get(\"model_name\")\nlet serverUrl = env.get(\"server_url\")\n\nmsg.requestTimeout = 1000;\nmsg.method = \"GET\";\nmsg.url = serverUrl+\"/v2/models/\"+modelName+\"/config\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":420,"wires":[["db3449811636781b"]]},{"id":"c9d10c33a635199d","type":"function","z":"fd51dfdc3367d25c","name":"status","func":"let statusCode = msg.statusCode;\nlet parsed_value;\nlet modelName = env.get(\"model_name\")\n\nif(statusCode == 200){\n flow.set(\"ready\",true) \n node.status({fill:\"green\",shape:\"dot\",text:\" Server ready.\"}); \n return msg;\n}\nelse{\n flow.set(\"ready\",false)\n node.status({fill:\"red\",shape:\"dot\",text:msg.statusCode+\": \"+\"Server is not ready or model not found.\"}); \n return null\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":770,"y":420,"wires":[[]]},{"id":"861ee57d416b8b03","type":"inject","z":"fd51dfdc3367d25c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"10","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"ready","payloadType":"flow","x":210,"y":420,"wires":[["7276cd4d5b2ed247"]]},{"id":"837af87e0b706d16","type":"switch","z":"fd51dfdc3367d25c","name":"ready?","property":"ready","propertyType":"flow","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":210,"y":100,"wires":[["1abffcc5defb1aaa"],[]]},{"id":"8e4df5803e108905","type":"change","z":"fd51dfdc3367d25c","name":"","rules":[{"t":"set","p":"ready","pt":"flow","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":480,"wires":[[]]},{"id":"b7e78ff17bb440b8","type":"inject","z":"fd51dfdc3367d25c","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":210,"y":480,"wires":[["8e4df5803e108905"]]},{"id":"1abffcc5defb1aaa","type":"switch","z":"fd51dfdc3367d25c","name":"rate limit?","property":"rate_limit_ms","propertyType":"env","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":160,"wires":[["b63e9a83f3001f21"],["2cc1bd4e5a083146"]]},{"id":"8c7c992ba1c6145c","type":"delay","z":"fd51dfdc3367d25c","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":true,"outputs":1,"x":410,"y":220,"wires":[["b63e9a83f3001f21"]]},{"id":"2cc1bd4e5a083146","type":"change","z":"fd51dfdc3367d25c","name":"","rules":[{"t":"set","p":"rate","pt":"msg","to":"rate_limit_ms","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":220,"wires":[["8c7c992ba1c6145c"]]},{"id":"557647c8b195bdea","type":"function","z":"fde3bd1da88bc03c","name":"Image to tensor","func":"//Get a worker from the pool and execute the task\nconst start = Date.now();\nconst image = msg.payload;\nlet piscina = context.get(\"piscina\")\nlet pre_process_time;\n\ntry{\n let result = await piscina.run({jpeg:image,gzip:false});\n \n msg.tensor = {\n \"image\":image,\n \"data\":Buffer.from(result.tensorBuffer),\n \"tensor_shape\":result.tensorShape,\n \"inference_header_length\":result.inference_header_length,\n \"image_tensor_buffer_length\":result.image_tensor_buffer_length\n }\n \n pre_process_time = Date.now() - start;\n msg.data.properties.computer_vision.pre_process_ms = pre_process_time\n node.status({fill:\"green\",shape:\"dot\",text:pre_process_time+\" ms\"}); \n return msg;\n}\ncatch(e){\n node.status({fill:\"red\",shape:\"dot\",text:\"Convert failed...\"}); \n node.error(\"Image to tensor conversion failed. Probably input is not an image buffer.\", msg);\n}","outputs":1,"noerr":0,"initialize":"let nr_folder;\nconst scriptName = 'numjs_piscina_worker.js';\nvar worker_path = \"\"\nconst platform = os.platform()\nvar worker_script;\nlet sep;\nlet numberOfWorkers;\n\nnode.warn(\"Platform: \" + platform)\n\nif(platform == \"win32\"){\n sep = \"\\\\\"\n nr_folder = path.resolve()\n worker_path = path.resolve(scriptName)\n worker_script = \"console.log(\\\"Worker starting...\\\");\\r\\nlet nj;\\r\\nlet zlib;\\r\\n\\r\\n\\r\\ntry{\\r\\n\\tnj = require(\\\"./node_modules\\//numjs\\\")\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(\\\"Loading numjs failed\\\")\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\ntry{\\r\\n\\tzlib = require(\\'zlib\\');\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\nmodule.exports = async ({jpeg,gzip}) => {\\r\\n\\ttry{\\r\\n\\t\\tconst start = Date.now();\\t\\r\\n\\t\\tconst img = nj.images.read(jpeg);\\r\\n\\t\\tconst dataBuffer = Buffer.from(img.selection.data);\\r\\n\\t\\tconst shape = [1].concat(img.shape);\\r\\n\\t\\tconst image_tensor_buffer_length = dataBuffer.length\\r\\n\\t\\t\\r\\n\\t\\t\\r\\n\\t\\tconst inference_header = {\\r\\n\\t\\t \\\"model_name\\\" : \\\"test\\\",\\r\\n\\t\\t \\\"inputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"input_tensor\\\",\\r\\n\\t\\t\\t \\\"shape\\\" : shape,\\r\\n\\t\\t\\t \\\"datatype\\\" : \\\"UINT8\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t \\\"binary_data_size\\\":image_tensor_buffer_length\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ],\\r\\n\\t\\t \\\"outputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_scores\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_boxes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_classes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tconst inference_header_buffer = Buffer.from(JSON.stringify(inference_header))\\r\\n\\t\\tconst inference_header_length = inference_header_buffer.length\\r\\n\\t\\tlet payload = Buffer.concat([inference_header_buffer,dataBuffer])\\r\\n\\t\\ttime_ms = Date.now() - start;\\r\\n\\t\\t\\r\\n\\t\\tif(gzip){\\r\\n\\t\\t\\tpayload = zlib.gzipSync(payload)\\r\\n\\t\\t}\\r\\n\\t\\t\\r\\n\\t\\tresult = {\\r\\n\\t\\t\\t\\\"tensorBuffer\\\" : payload,\\r\\n\\t\\t\\t\\\"Content-Type\\\" : \\\"application\\/octet-stream\\\",\\r\\n\\t\\t\\t\\\"inference_header_length\\\": inference_header_length,\\r\\n\\t\\t\\t\\\"image_tensor_buffer_length\\\":image_tensor_buffer_length,\\r\\n\\t\\t\\t\\\"tensorShape\\\":shape,\\r\\n\\t\\t\\t\\\"processing_time\\\":time_ms,\\r\\n\\t\\t\\t\\\"payload\\\":jpeg\\r\\n\\t\\t}\\t\\t\\r\\n\\t\\treturn result\\t\\t\\r\\n\\t}\\r\\n\\tcatch(e){\\r\\n\\t\\tconsole.log(e)\\r\\n\\t}\\r\\n\\t\\t\\r\\n}\"\n}\nelse{\n nr_folder = path.resolve(\".node-red\")\n node.warn(nr_folder)\n worker_path = path.resolve(\".node-red\",scriptName)\n node.warn(worker_path)\n sep = \"/\" \n worker_script = \"console.log(\\\"Worker starting...\\\");\\r\\nlet nj;\\r\\nlet zlib;\\r\\n\\r\\n\\r\\ntry{\\r\\n\\tnj = require(\\\"./node_modules\\//numjs\\\")\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(\\\"Loading numjs failed\\\")\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\ntry{\\r\\n\\tzlib = require(\\'zlib\\');\\r\\n}\\r\\ncatch(e){\\r\\n\\tconsole.log(e)\\r\\n}\\r\\n\\r\\nmodule.exports = async ({jpeg,gzip}) => {\\r\\n\\ttry{\\r\\n\\t\\tconst start = Date.now();\\t\\r\\n\\t\\tconst img = nj.images.read(jpeg);\\r\\n\\t\\tconst dataBuffer = Buffer.from(img.selection.data);\\r\\n\\t\\tconst shape = [1].concat(img.shape);\\r\\n\\t\\tconst image_tensor_buffer_length = dataBuffer.length\\r\\n\\t\\t\\r\\n\\t\\t\\r\\n\\t\\tconst inference_header = {\\r\\n\\t\\t \\\"model_name\\\" : \\\"test\\\",\\r\\n\\t\\t \\\"inputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"input_tensor\\\",\\r\\n\\t\\t\\t \\\"shape\\\" : shape,\\r\\n\\t\\t\\t \\\"datatype\\\" : \\\"UINT8\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t \\\"binary_data_size\\\":image_tensor_buffer_length\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ],\\r\\n\\t\\t \\\"outputs\\\" : [\\r\\n\\t\\t\\t{\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_scores\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_boxes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t},\\r\\n\\t\\t\\t {\\r\\n\\t\\t\\t \\\"name\\\" : \\\"detection_classes\\\",\\r\\n\\t\\t\\t \\\"parameters\\\" : {\\r\\n\\t\\t\\t\\t\\\"binary_data\\\" : false\\r\\n\\t\\t\\t }\\r\\n\\t\\t\\t}\\r\\n\\t\\t ]\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\tconst inference_header_buffer = Buffer.from(JSON.stringify(inference_header))\\r\\n\\t\\tconst inference_header_length = inference_header_buffer.length\\r\\n\\t\\tlet payload = Buffer.concat([inference_header_buffer,dataBuffer])\\r\\n\\t\\ttime_ms = Date.now() - start;\\r\\n\\t\\t\\r\\n\\t\\tif(gzip){\\r\\n\\t\\t\\tpayload = zlib.gzipSync(payload)\\r\\n\\t\\t}\\r\\n\\t\\t\\r\\n\\t\\tresult = {\\r\\n\\t\\t\\t\\\"tensorBuffer\\\" : payload,\\r\\n\\t\\t\\t\\\"Content-Type\\\" : \\\"application\\/octet-stream\\\",\\r\\n\\t\\t\\t\\\"inference_header_length\\\": inference_header_length,\\r\\n\\t\\t\\t\\\"image_tensor_buffer_length\\\":image_tensor_buffer_length,\\r\\n\\t\\t\\t\\\"tensorShape\\\":shape,\\r\\n\\t\\t\\t\\\"processing_time\\\":time_ms,\\r\\n\\t\\t\\t\\\"payload\\\":jpeg\\r\\n\\t\\t}\\t\\t\\r\\n\\t\\treturn result\\t\\t\\r\\n\\t}\\r\\n\\tcatch(e){\\r\\n\\t\\tconsole.log(e)\\r\\n\\t}\\r\\n\\t\\t\\r\\n}\"\n}\n\ntry{\n numberOfWorkers = 2\n}\ncatch(e){\n node.warn(\"Loading numberOfWorkers from env variable failed... using default value = 1\")\n node.warn(e)\n numberOfWorkers = 1\n}\n\nfs.writeFile(worker_path, worker_script, function (err) {\n if (err) {\n node.error(\"Cannot create web_worker_test_script.js file: \" + err);\n }\n});\n\ntry{\n const piscina = new pis.Piscina({\n filename: worker_path,\n maxThreads: numberOfWorkers\n });\n \n context.set(\"piscina\",piscina)\n node.status({fill:\"green\", shape:\"dot\", text:\"Piscina initialized\"});\n}\ncatch(error){\n node.warn(error)\n node.status({fill:\"red\", shape:\"dot\", text:\"Initializing piscina failed...\"});\n}","finalize":"// Code added here will be run when the\n// node is being stopped or re-deployed.\ncontext.set(\"piscina\",{})","libs":[{"var":"pis","module":"piscina"},{"var":"fs","module":"fs"},{"var":"os","module":"os"},{"var":"process","module":"process"},{"var":"path","module":"path"}],"x":220,"y":60,"wires":[[]]},{"id":"752a76d98d97af39","type":"status","z":"fde3bd1da88bc03c","name":"","scope":null,"x":240,"y":140,"wires":[[]]},{"id":"1e80d9526ad0c4ee","type":"function","z":"9215deec580c5391","name":"Post-process","func":"function chunk(arr, chunkSize) {\n if (chunkSize <= 0) throw \"Invalid chunk size\";\n var R = [];\n for (var i = 0, len = arr.length; i < len; i += chunkSize)\n R.push(arr.slice(i, i + chunkSize));\n return R;\n}\n\ntry{\n let ready = flow.get(\"ready\") || false;\n\n if (ready){\n \n let start = Date.now()\n let inference_result = msg.payload;\n let results = [];\n const modelName = env.get(\"model_name\")\n const model = flow.get(modelName);\n const labels = model.parameters.labels;\n const metadata = model.parameters.metadata;\n const ts = msg.ts;\n let post_process_time = 0;\n const threshold = env.get(\"threshold\")\n msg.threshold = threshold;\n const image_width = msg.data.properties.object.data.width;\n const image_height = msg.data.properties.object.data.height;\n\n let scores;\n let boxes;\n let names;\n let newObject;\n\n for(let i=0;i<(inference_result.outputs).length;i++){ \n if(inference_result.outputs[i][\"name\"] == \"detection_scores\"){\n scores = inference_result.outputs[i].data\n }\n else if(inference_result.outputs[i][\"name\"] == \"detection_boxes\"){\n boxes = inference_result.outputs[i].data\n boxes = chunk(boxes,4) \n }\n else if(inference_result.outputs[i][\"name\"] == \"detection_classes\"){\n names = inference_result.outputs[i].data \n }\n } \n\n for (let i = 0; i < scores.length; i++) {\n if (scores[i] > threshold) {\n newObject = {\n \"bbox\":[\n boxes[i][1] * image_width,\n boxes[i][0] * image_height,\n (boxes[i][3] - boxes[i][1]) * image_width,\n (boxes[i][2] - boxes[i][0]) * image_height\n ],\n \"class\":labels[names[i]-1],\n \"label\":labels[names[i]-1],\n \"score\":scores[i],\n \"length_cm\":NaN\n }\n results.push(newObject)\n }\n }\n\n post_process_time = Date.now() - start; \n\n msg.data.properties.computer_vision.result = results;\n msg.data.properties.computer_vision.model = modelName;\n msg.data.properties.computer_vision.inference_time = msg.request_ms;\n msg.data.properties.computer_vision.type = \"object detection\";\n msg.data.properties.computer_vision.metadata = metadata;\n msg.data.properties.computer_vision.labels = labels;\n msg.data.properties.computer_vision.threshold = msg.threshold;\n msg.data.properties.computer_vision.validated = false;\n msg.data.properties.computer_vision.post_process_time = post_process_time;\n\n msg.payload = msg.tensor.image;\n delete msg.tensor;\n delete msg.request_ms;\n\n const objects_count = results.length\n\n if (objects_count > 0 ){ \n msg.objects_found = true \n node.status({ fill: \"blue\", shape: \"dot\", text: \"Objects found:\" + objects_count});\n return msg;\n }\n else{\n node.status({fill: \"red\", shape: \"dot\", text: \" No objects over threshold: \" +threshold});\n return msg;\n }\n \n }\n else{\n node.status({ fill: \"red\", shape: \"dot\", text: \"Modeldata is not loaded\"});\n return null;\n }\n}\ncatch(e){\n node.error(\"Post process failed.\", msg);\n return null;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":120,"wires":[[]]},{"id":"bc716e2cbc7c0995","type":"http request","z":"9215deec580c5391","name":"status request","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":500,"y":220,"wires":[["c42a4bd0916459d6"]]},{"id":"e070e6af761a0137","type":"function","z":"9215deec580c5391","name":"request","func":"let modelName = env.get(\"model_name\")\nlet serverUrl = env.get(\"server_url\")\n\nmsg.requestTimeout = 1000;\nmsg.method = \"GET\";\nmsg.url = serverUrl+\"/v2/models/\"+modelName+\"/config\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":220,"wires":[["bc716e2cbc7c0995"]]},{"id":"c42a4bd0916459d6","type":"function","z":"9215deec580c5391","name":"status","func":"let statusCode = msg.statusCode;\nlet parsed_value;\nlet modelName = env.get(\"model_name\")\n\nif(statusCode == 200){\n let model_data = msg.payload;\n parsed_value = JSON.parse(model_data.parameters.metadata.string_value)\n model_data.parameters.labels = parsed_value.labels\n model_data.parameters.metadata = parsed_value.metadata\n flow.set(\"ready\",true) \n node.status({fill:\"green\",shape:\"dot\",text:\" Model configuration loaded.\"}); \n flow.set(modelName,model_data) \n return null;\n}\nelse{\n flow.set(\"ready\",false)\n node.status({fill:\"red\",shape:\"dot\",text:msg.statusCode+\": \"+\"Server is not ready or model not found.\"}); \n return msg\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":670,"y":220,"wires":[["7169ecadae48d625"]]},{"id":"973d9f1bf645853c","type":"inject","z":"9215deec580c5391","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"2","topic":"","payload":"ready","payloadType":"flow","x":110,"y":220,"wires":[["e070e6af761a0137"]]},{"id":"b93022c83cb00303","type":"status","z":"9215deec580c5391","name":"","scope":["1e80d9526ad0c4ee","c42a4bd0916459d6"],"x":500,"y":360,"wires":[[]]},{"id":"7169ecadae48d625","type":"delay","z":"9215deec580c5391","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":120,"y":300,"wires":[["e070e6af761a0137"]]},{"id":"5b933476.fc386c","type":"http request","z":"fcd42407.59d1a8","name":"POST","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":true,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":450,"y":100,"wires":[["5b3e2fe4.4c3f9"]]},{"id":"f17ef03d.d18bf","type":"function","z":"fcd42407.59d1a8","name":"HTTP request","func":"let times_to_try;\nlet token;\n\nif('token' in msg){\n times_to_try = env.get(\"times_to_try\")\n token = msg.token;\n msg.data = msg.payload;\n msg.method = \"POST\";\n msg.url = env.get(\"API_URL\")+\"/api/v1/image/add\"\n msg.headers = {\n \"Content-Type\": \"application/json\",\n 'Authorization': \"Bearer \"+token \n };\n node.status({fill:\"blue\",shape:\"dot\",text:\"Sending image...\"})\n return [msg,null];\n}\nelse{\n times_to_try = env.get(\"times_to_try\")\n token = msg.token;\n msg.data = msg.payload;\n msg.method = \"POST\";\n msg.url = env.get(\"API_URL\")+\"/api/v1/image/add\"\n msg.headers = {\n \"Content-Type\": \"application/json\",\n 'Authorization': \"Bearer \"+token \n };\n msg.statusCode = 401;\n node.status({fill:\"red\",shape:\"dot\",text:\"msg.token is missing\"})\n return [null,msg];\n}","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":560,"y":40,"wires":[["5b933476.fc386c"],["5b3e2fe4.4c3f9"]]},{"id":"5b3e2fe4.4c3f9","type":"switch","z":"fcd42407.59d1a8","name":"statusCode?","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"200","vt":"num"},{"t":"eq","v":"201","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":630,"y":100,"wires":[["68394e6b.8b877"],["68394e6b.8b877"],["b6efc528.054bc8"]]},{"id":"f4f14ebd.6e975","type":"link out","z":"fcd42407.59d1a8","name":"","links":["d1c084fc.4da468"],"x":1175,"y":120,"wires":[]},{"id":"d1c084fc.4da468","type":"link in","z":"fcd42407.59d1a8","name":"Try again","links":["f4f14ebd.6e975"],"x":55,"y":100,"wires":[["a8257482.0d16e8"]]},{"id":"b6efc528.054bc8","type":"function","z":"fcd42407.59d1a8","name":"Format for resend","func":"let times_to_try = env.get(\"times_to_try\")\n\nif(msg.times_to_try >= times_to_try){\n node.status({fill:\"red\",shape:\"dot\",text:msg.statusCode+\": \"+msg.payload.message})\n msg.times_to_try = msg.times_to_try + 1\n return msg;\n}\nelse{\n msg.payload = msg.data\n msg.times_to_try = msg.times_to_try + 1\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Trying again... \"+msg.times_to_try+\"/\"+times_to_try})\n return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":830,"y":120,"wires":[["e8a7bd1f.28f73"]]},{"id":"e8a7bd1f.28f73","type":"delay","z":"fcd42407.59d1a8","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"5","randomLast":"10","randomUnits":"seconds","drop":false,"outputs":1,"x":1020,"y":120,"wires":[["f4f14ebd.6e975"]]},{"id":"9363fb9a.c3f578","type":"status","z":"fcd42407.59d1a8","name":"","scope":["f17ef03d.d18bf","b6efc528.054bc8","f6e7b71a.50b0f8","9fb35f6f.022b","ca8420ca.fbcfa"],"x":1040,"y":340,"wires":[[]]},{"id":"f6e7b71a.50b0f8","type":"function","z":"fcd42407.59d1a8","name":"Status","func":"node.status({fill:\"green\",shape:\"dot\",text:\"Image sent @\"+msg.sent_timestamp+\" in \"+msg.send_time+\" ms\"})\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1070,"y":60,"wires":[[]]},{"id":"aba7379c.9aec88","type":"change","z":"fcd42407.59d1a8","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":40,"wires":[["f17ef03d.d18bf"]]},{"id":"68394e6b.8b877","type":"change","z":"fcd42407.59d1a8","name":"end timer","rules":[{"t":"set","p":"send_time","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":60,"wires":[["8a74eebe.fdbc8"]]},{"id":"80c6d087.30ca7","type":"change","z":"fcd42407.59d1a8","name":"","rules":[{"t":"set","p":"times_to_try","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":200,"y":40,"wires":[["aba7379c.9aec88"]]},{"id":"a8257482.0d16e8","type":"switch","z":"fcd42407.59d1a8","name":"times_to_try?","property":"times_to_try","propertyType":"msg","rules":[{"t":"gt","v":"times_to_try","vt":"env"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":180,"y":100,"wires":[["2164bc8e0654a805"],["aba7379c.9aec88"]]},{"id":"9fb35f6f.022b","type":"file","z":"fcd42407.59d1a8","name":"","filename":"filename","filenameType":"msg","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":620,"y":220,"wires":[["ca8420ca.fbcfa"]]},{"id":"3faa6785.3e0888","type":"function","z":"fcd42407.59d1a8","name":"Format filename","func":"let name = (msg.data.properties.object.data.original.objectname).split(\".\")[0]\nconst platform = os.platform()\nlet base_path = env.get(\"path\")\n\nif (platform == \"win32\"){\n msg.filename = base_path + \"\\\\\" + \"tequ_api_images\" + \"\\\\\" +msg.ts_for_file + \"\\\\\" + name + \".json\";\n}\nelse{\n msg.filename = base_path + \"/\" + \"tequ_api_images\" + \"/\" + msg.ts_for_file + \"/\" + name + \".json\";\n}\nmsg.payload = msg.data;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"os","module":"os"}],"x":440,"y":220,"wires":[["9fb35f6f.022b"]]},{"id":"ca8420ca.fbcfa","type":"function","z":"fcd42407.59d1a8","name":"Update status","func":"node.status({fill:\"blue\",shape:\"dot\",text:\"Payload saved to file.\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":220,"wires":[]},{"id":"235873ad.c9440c","type":"moment","z":"fcd42407.59d1a8","name":"","topic":"","input":"","inputType":"date","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"YYYY-MM-DD","locale":"en-US","output":"ts_for_file","outputType":"msg","outTz":"ETC/UTC","x":200,"y":220,"wires":[["3faa6785.3e0888"]]},{"id":"8a74eebe.fdbc8","type":"moment","z":"fcd42407.59d1a8","name":"ts","topic":"","input":"","inputType":"date","inTz":"Europe/Kiev","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH:mm:ss","locale":"en-US","output":"sent_timestamp","outputType":"msg","outTz":"Europe/Kiev","x":950,"y":60,"wires":[["f6e7b71a.50b0f8"]]},{"id":"2164bc8e0654a805","type":"switch","z":"fcd42407.59d1a8","name":"Save failed","property":"save_failed","propertyType":"env","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":170,"y":160,"wires":[["235873ad.c9440c"]]},{"id":"dfacae6d.01672","type":"function","z":"ffeafac1.b0db18","name":"App-ID Token","func":"if(msg.topic == \"force_update\"){\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Forced update.\"})\n}\nelse{\n node.status({fill:\"yellow\",shape:\"dot\",text:\"Updating token...\"})\n}\n\nlet username = env.get(\"username\");\nlet password = env.get(\"password\");\n\nmsg.url = env.get(\"API_URL\")+\"/api/v1/token\"\nmsg.method = 'POST';\n\nmsg.payload = {\n \"grant_type\":\"password\",\n \"username\":username,\n \"password\":password\n};\n\nmsg.headers = {\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n};\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":720,"y":280,"wires":[["bffe1286.5564"]]},{"id":"bffe1286.5564","type":"http request","z":"ffeafac1.b0db18","name":"req","method":"use","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":890,"y":300,"wires":[["c4734d48.7f0ff"]]},{"id":"c4734d48.7f0ff","type":"function","z":"ffeafac1.b0db18","name":"Parse response","func":"var token = msg.payload.access_token;\nvar decoded = jwtDecode(token);\nmsg.payload = {\n \"decoded\":decoded,\n \"token\":token\n}\nnode.status({fill:\"green\",shape:\"dot\",text:\"Token updated.\"})\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"jwtDecode","module":"jwt-decode"}],"x":1060,"y":300,"wires":[[]]},{"id":"db473541.b967b8","type":"switch","z":"ffeafac1.b0db18","name":"check keys","property":"payload","propertyType":"msg","rules":[{"t":"hask","v":"exp","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":230,"y":200,"wires":[["50252e9e.d28d4"],["dfacae6d.01672"]]},{"id":"50252e9e.d28d4","type":"function","z":"ffeafac1.b0db18","name":"Check token","func":"let jwt = msg.payload;\nlet time_left = jwt.exp - Math.round(new Date().getTime()/1000);\n\nif(time_left > 120){\n node.status({fill:\"green\",shape:\"dot\",text:\"TOKEN OK. \"+time_left+\" s left.\"})\n msg.do_login = false;\n}\nelse{\n node.status({fill:\"red\",shape:\"dot\",text:\"Token expired. LOGIN again\"})\n msg.do_login = true;\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":710,"y":140,"wires":[["2c7d2b4f.126d34"]]},{"id":"2c7d2b4f.126d34","type":"switch","z":"ffeafac1.b0db18","name":"LOGIN?","property":"do_login","propertyType":"msg","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":700,"y":200,"wires":[["dfacae6d.01672"]]},{"id":"d7310f56.fb383","type":"switch","z":"ffeafac1.b0db18","name":"Force update","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"force_update","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":230,"y":140,"wires":[["dfacae6d.01672"],["db473541.b967b8"]]},{"id":"6096db38.546e94","type":"status","z":"ffeafac1.b0db18","name":"","scope":["dfacae6d.01672","c4734d48.7f0ff","50252e9e.d28d4","431c0f8ee889f44d"],"x":1080,"y":360,"wires":[[]]},{"id":"431c0f8ee889f44d","type":"function","z":"ffeafac1.b0db18","name":"Status","func":"node.status({fill:\"red\",shape:\"dot\",text:\"Please supply decoded token in msg.payload\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":690,"y":340,"wires":[]},{"id":"eb06f89989a8028c","type":"function","z":"75015de274d71273","name":"Format payload","func":"const newMsg = {\n \"payload\":msg.data\n }\nreturn newMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":200,"wires":[[]]},{"id":"77e4f7126f22a6a9","type":"function","z":"75015de274d71273","name":"enabled?","func":"const enabled = env.get(\"enable\")\nconst objects_found = msg.objects_found;\n\nif(enabled){\n \n if (objects_found){\n node.status({ fill: \"green\", shape: \"dot\", text: \"Tequ-API enabled\" });\n return msg;\n }\n else{\n node.status({ fill: \"yellow\", shape: \"dot\", text: \"Tequ-API enabled, but no annotated objects\" });\n return null;\n } \n}\nelse{\n node.status({ fill: \"red\", shape: \"dot\", text: \"Tequ-API disabled\" });\n return null;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":280,"y":200,"wires":[["eb06f89989a8028c"]]},{"id":"40ba865bf8f26d27","type":"status","z":"75015de274d71273","name":"","scope":null,"x":480,"y":280,"wires":[[]]},{"id":"410561693652da44","type":"multipart-decoder","z":"1810b5ccd40a609b","name":"Datasource","ret":"bin","url":"","tls":"","delay":0,"maximum":"2000000","blockSize":1,"x":350,"y":180,"wires":[["6eede8fca838830a"]]},{"id":"6eede8fca838830a","type":"msg-speed","z":"1810b5ccd40a609b","name":"Img / s","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":510,"y":180,"wires":[["050f32b35d92d45f","3bd6b5fde8e8d55d","6e3133797d3e8b1f"],["c749b5b474586313"]]},{"id":"c6162b2ea8fee499","type":"delay","z":"1810b5ccd40a609b","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":true,"outputs":1,"x":930,"y":200,"wires":[[]]},{"id":"831ad89c1c587e0d","type":"change","z":"1810b5ccd40a609b","name":"stop","rules":[{"t":"set","p":"stop","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":200,"wires":[["410561693652da44"]]},{"id":"b1b20213f85b0885","type":"change","z":"1810b5ccd40a609b","name":"start","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"},{"t":"set","p":"url","pt":"msg","to":"stream_url","tot":"env"},{"t":"set","p":"topic","pt":"msg","to":"stream_id","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":190,"y":160,"wires":[["410561693652da44"]]},{"id":"acf75d136f1c23eb","type":"link in","z":"1810b5ccd40a609b","name":"stop stream #2","links":["11c17645f87c4694"],"x":95,"y":200,"wires":[["831ad89c1c587e0d"]]},{"id":"fb24d1d454820fc7","type":"link in","z":"1810b5ccd40a609b","name":"start stream #2","links":["17639f356d82e82b"],"x":95,"y":160,"wires":[["b1b20213f85b0885"]]},{"id":"050f32b35d92d45f","type":"switch","z":"1810b5ccd40a609b","name":"== 0","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":670,"y":80,"wires":[["279e811e6f2610ac"]]},{"id":"11c17645f87c4694","type":"link out","z":"1810b5ccd40a609b","name":"stop cmd 2 out","links":["acf75d136f1c23eb"],"x":1155,"y":40,"wires":[]},{"id":"ba52fa6c7ac82aeb","type":"trigger","z":"1810b5ccd40a609b","name":"","op1":"","op2":"","op1type":"nul","op2type":"date","duration":"5","extend":false,"units":"s","reset":"","bytopic":"all","outputs":1,"x":1020,"y":80,"wires":[["17639f356d82e82b"]]},{"id":"17639f356d82e82b","type":"link out","z":"1810b5ccd40a609b","name":"trigger 2 out","links":["fb24d1d454820fc7"],"x":1155,"y":80,"wires":[]},{"id":"279e811e6f2610ac","type":"delay","z":"1810b5ccd40a609b","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"outputs":1,"x":830,"y":80,"wires":[["ba52fa6c7ac82aeb","11c17645f87c4694"]]},{"id":"d14829fe158c91d7","type":"function","z":"1810b5ccd40a609b","name":"isBuffer?","func":"let timestamp = msg.next_timestamp;\nlet image = msg.payload;\nmsg.mimetype = \"image/jpeg\";\nlet fps = flow.get(\"speed\")\n\nif(Buffer.isBuffer(image)){\n node.status({ fill: \"green\", shape: \"dot\", text: env.get(\"stream_id\") + \" | \"+fps+\"/s | \"+timestamp}); \n msg.rate = env.get(\"limited_stream_rate\")\n return msg;\n}\nelse{\n node.status({fill:\"red\",shape:\"dot\",text:timestamp + \" Not an image\"}); \n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":680,"y":240,"wires":[["c6162b2ea8fee499"]]},{"id":"3bd6b5fde8e8d55d","type":"change","z":"1810b5ccd40a609b","name":"Set datasource to topic","rules":[{"t":"set","p":"topic","pt":"msg","to":"stream_id","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":140,"wires":[[]]},{"id":"ad67dfe697063dac","type":"status","z":"1810b5ccd40a609b","name":"","scope":["d14829fe158c91d7","410561693652da44"],"x":680,"y":320,"wires":[[]]},{"id":"c749b5b474586313","type":"moment","z":"1810b5ccd40a609b","name":"set ts","topic":"","input":"","inputType":"date","inTz":"Europe/Kiev","adjAmount":0,"adjType":"days","adjDir":"add","format":"HH:mm:ss.SSS","locale":"en-US","output":"next_timestamp","outputType":"msg","outTz":"Europe/Kiev","x":510,"y":240,"wires":[["d14829fe158c91d7"]]},{"id":"d0ce9708ef9f084a","type":"inject","z":"1810b5ccd40a609b","name":"","props":[{"p":"rate","v":"limited_stream_rate","vt":"env"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","x":690,"y":400,"wires":[["c6162b2ea8fee499"]]},{"id":"6e3133797d3e8b1f","type":"change","z":"1810b5ccd40a609b","name":"","rules":[{"t":"set","p":"speed","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":80,"wires":[[]]},{"id":"9b77a1ba8d383f27","type":"image-info","z":"5d5c83b6c13135a8","name":"","x":170,"y":360,"wires":[["1878be93a74d761a"]]},{"id":"1878be93a74d761a","type":"exif","z":"5d5c83b6c13135a8","name":"","mode":"normal","property":"payload","x":150,"y":420,"wires":[["2f6de45da98c05fd"]]},{"id":"35c15d25bfbd1356","type":"moment","z":"5d5c83b6c13135a8","name":"","topic":"","input":"","inputType":"date","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"en-US","output":"utc_timestamp","outputType":"msg","outTz":"Europe/Helsinki","x":200,"y":180,"wires":[["330989ac4c8f8cf6"]]},{"id":"330989ac4c8f8cf6","type":"moment","z":"5d5c83b6c13135a8","name":"","topic":"","input":"utc_timestamp","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"YYYY-MM-DD HH:mm:ss","locale":"en-US","output":"local_timestamp","outputType":"msg","outTz":"Europe/Helsinki","x":200,"y":240,"wires":[["5cccff5536a027e4"]]},{"id":"5cccff5536a027e4","type":"moment","z":"5d5c83b6c13135a8","name":"","topic":"","input":"utc_timestamp","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"x","locale":"en-US","output":"unix_timestamp","outputType":"msg","outTz":"ETC/UTC","x":200,"y":300,"wires":[["9b77a1ba8d383f27"]]},{"id":"d2a991ca2c10cafd","type":"status","z":"5d5c83b6c13135a8","name":"","scope":["c34da99ee513c4c1"],"x":600,"y":540,"wires":[[]]},{"id":"f140c0330ec0ab32","type":"function","z":"5d5c83b6c13135a8","name":"Reformat data","func":"let type;\nlet random_name = uuid.v4();\nlet image_type = msg.type;\nlet file_extension;\nlet latitude = Number(env.get(\"latitude\"))\nlet longitude = Number(env.get(\"longitude\"))\nlet unix_timestamp = parseInt(msg.unix_timestamp);\nlet serial;\ntry{\n serial = (msg.exif.image.ImageDescription).split(\"_\")[1];\n}\ncatch(e){\n serial = \"unknown\"\n}\n\nlet datasource = serial;\n\nif (image_type == \"jpg\") {\n image_type = \"image/jpeg\"\n file_extension = \".jpg\"\n}\nelse if (image_type == \"png\") {\n image_type = \"image/png\"\n file_extension = \".png\"\n}\n\nmsg.topic = serial;\nmsg.datasource = serial;\nmsg.random_name = random_name;\nmsg.file_extension = file_extension;\n\nlet parameters = {\n \"owner\": msg.exif.image.Copyright,\n \"version\": msg.exif.image.Software,\n \"model\": msg.exif.image.Model,\n \"serial\": serial,\n \"manufacturer\": msg.exif.image.Make\n}\n\nmsg.data = {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [longitude, latitude]\n },\n \"properties\": {\n \"datasource\": datasource,\n \"local_timestamp\": msg.local_timestamp,\n \"utc_timestamp\": msg.utc_timestamp,\n \"unix_timestamp\": unix_timestamp,\n \"cos\": {\n \"bucket\": \"\",\n \"region\": \"\",\n \"service_id\": \"\"\n },\n \"object\": {\n \"type\": image_type,\n \"data\": {\n \"width\": msg.width,\n \"height\": msg.height,\n \"size\": (msg.payload).length,\n \"exif\": msg.exif,\n \"parameters\": parameters,\n \"original\": {\n \"image\": (msg.payload).toString('base64'),\n \"objectname\": datasource + \"-\" + random_name + file_extension,\n \"thumbnail\": (msg.thumbnail).toString('base64'),\n \"thumbnail_ms\": msg.thumbnail_ms,\n \"mjpeg_process_ms\":0\n },\n \"annotated\": {\n \"image\": \"\",\n \"objectname\": datasource + \"-\" + random_name+ \"_annotated\"+file_extension,\n \"thumbnail\": \"\",\n \"thumbnail_ms\":0,\n \"annotation_ms\":0,\n \"total_ms\":0\n }\n }\n },\n \"computer_vision\": {\n \"type\": \"\",\n \"model\": \"\",\n \"inference_time\": \"\",\n \"result\": \"\"\n }\n }\n}\n\ndelete msg.settings;\ndelete msg.width;\ndelete msg.height;\ndelete msg.type;\ndelete msg.exif;\ndelete msg.thumbnail;\ndelete msg.utc_timestamp;\ndelete msg.local_timestamp;\ndelete msg.unix_timestamp;\ndelete msg.start;\ndelete msg.thumbnail_ms;\ndelete msg.datasource;\ndelete msg.random_name;\ndelete msg.file_extension;\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"uuid","module":"uuid"}],"x":620,"y":400,"wires":[["05e6cd55803f2ffc"]]},{"id":"2f6de45da98c05fd","type":"change","z":"5d5c83b6c13135a8","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":420,"wires":[["6f7a9496e5823e9c"]]},{"id":"689a113d37af985b","type":"change","z":"5d5c83b6c13135a8","name":"end timer","rules":[{"t":"set","p":"thumbnail_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":340,"wires":[["f140c0330ec0ab32"]]},{"id":"ba2cdf3619350fee","type":"change","z":"5d5c83b6c13135a8","name":"timer","rules":[{"t":"set","p":"process_start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["35c15d25bfbd1356"]]},{"id":"6f7a9496e5823e9c","type":"function","z":"5d5c83b6c13135a8","name":"resize","func":"let input = msg.payload;\nlet width = env.get(\"thumbnail_width\")\nlet create_thumbnail = env.get(\"thumbnail\")\nlet thumbnail;\n\nif (create_thumbnail){\n thumbnail = await sharp(input)\n .metadata()\n .then(({ width }) => sharp(input)\n .resize({ width: width })\n .toBuffer()\n );\n\n \n}\nelse{\n thumbnail = []\n}\nmsg.thumbnail = thumbnail\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"sharp","module":"sharp"}],"x":450,"y":340,"wires":[["689a113d37af985b"]]},{"id":"05e6cd55803f2ffc","type":"change","z":"5d5c83b6c13135a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.original.mjpeg_process_ms","pt":"msg","to":"$millis() - msg.process_start","tot":"jsonata"},{"t":"delete","p":"process_start","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":460,"wires":[["c34da99ee513c4c1"]]},{"id":"5e012d5439e4c4b4","type":"split","z":"5d5c83b6c13135a8","name":"","splt":"[255, 216, 255]","spltType":"bin","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":330,"y":40,"wires":[["0f73083f245f1440"]]},{"id":"0f73083f245f1440","type":"function","z":"5d5c83b6c13135a8","name":"Join","func":"let header = Buffer.from(msg.parts.ch);\nlet image = Buffer.from(msg.payload);\nlet arr = [header,image]\nmsg.payload = Buffer.concat(arr)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":40,"wires":[["ba2cdf3619350fee"]]},{"id":"c34da99ee513c4c1","type":"msg-speed","z":"5d5c83b6c13135a8","name":"images","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":760,"y":460,"wires":[[],[]]},{"id":"d62df9289b1bd8f3","type":"switch","z":"5d5c83b6c13135a8","name":"is_stream?","property":"is_stream","propertyType":"env","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":170,"y":60,"wires":[["5e012d5439e4c4b4"],["ba2cdf3619350fee"]]},{"id":"0890af5e685af9f7","type":"subflow:1810b5ccd40a609b","z":"95ebe51baa66ead1","name":"40198132","env":[{"name":"stream_url","value":"http://192.168.86.121:1880/camera/id/40198132/stream/1","type":"str"},{"name":"stream_id","value":"40198132","type":"str"}],"x":300,"y":80,"wires":[[],[],["c0bdeec189cc7e81"]]},{"id":"fcfcf9210e15cd57","type":"inject","z":"95ebe51baa66ead1","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":110,"y":80,"wires":[["0890af5e685af9f7","cb95842a551b8d9d","b3d6bd66d99bb253","cd6d152f8f399ee8","502c0f0c6fe21422"]]},{"id":"cb95842a551b8d9d","type":"subflow:1810b5ccd40a609b","z":"95ebe51baa66ead1","name":"40204286","env":[{"name":"stream_url","value":"http://192.168.86.121:1880/camera/id/40204286/stream/1","type":"str"},{"name":"stream_id","value":"40204286","type":"str"}],"x":300,"y":160,"wires":[[],[],["45e670be922e56ae"]]},{"id":"b3d6bd66d99bb253","type":"subflow:1810b5ccd40a609b","z":"95ebe51baa66ead1","name":"23751808","env":[{"name":"stream_url","value":"http://192.168.86.121:1880/camera/id/23751808/stream/1","type":"str"},{"name":"stream_id","value":"23751808","type":"str"}],"x":300,"y":240,"wires":[[],[],["3287846f49abca62"]]},{"id":"cd6d152f8f399ee8","type":"subflow:1810b5ccd40a609b","z":"95ebe51baa66ead1","name":"40165426","env":[{"name":"stream_url","value":"http://192.168.86.121:1880/camera/id/40165426/stream/1","type":"str"},{"name":"stream_id","value":"40165426","type":"str"}],"x":300,"y":320,"wires":[[],[],["6e32196b71a5c821"]]},{"id":"502c0f0c6fe21422","type":"subflow:1810b5ccd40a609b","z":"95ebe51baa66ead1","name":"7B5B8BEF","env":[{"name":"stream_url","value":"http://192.168.86.121:1880/camera/id/7B5B8BEF/stream/1","type":"str"},{"name":"stream_id","value":"7B5B8BEF","type":"str"}],"x":310,"y":400,"wires":[[],[],["39a84a0d0e3bc62e"]]},{"id":"c0bdeec189cc7e81","type":"link out","z":"95ebe51baa66ead1","name":"link out 6","mode":"link","links":["7c76c55127eb9816"],"x":525,"y":100,"wires":[]},{"id":"45e670be922e56ae","type":"link out","z":"95ebe51baa66ead1","name":"link out 7","mode":"link","links":["7c76c55127eb9816"],"x":525,"y":180,"wires":[]},{"id":"3287846f49abca62","type":"link out","z":"95ebe51baa66ead1","name":"link out 8","mode":"link","links":["7c76c55127eb9816"],"x":525,"y":260,"wires":[]},{"id":"6e32196b71a5c821","type":"link out","z":"95ebe51baa66ead1","name":"link out 9","mode":"link","links":["7c76c55127eb9816"],"x":525,"y":340,"wires":[]},{"id":"39a84a0d0e3bc62e","type":"link out","z":"95ebe51baa66ead1","name":"link out 10","mode":"link","links":["7c76c55127eb9816"],"x":525,"y":420,"wires":[]},{"id":"9721d71a45af7eb5","type":"msg-speed","z":"88f8f06219122b1d","name":"Inferences","frequency":"sec","interval":"1","estimation":true,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":930,"y":140,"wires":[[],["b56dbf4649869c7f"]]},{"id":"370ef41edc3f7b8a","type":"subflow:83a7a965.1808a8","z":"88f8f06219122b1d","name":"","env":[{"name":"threshold","value":"0.80","type":"num"},{"name":"labels","value":"[\"fish\",\"perch\", \"pike\", \"rainbow trout\", \"salmon\", \"trout\", \"cyprinidae\", \"zander\", \"smolt\", \"bream\", \"teddy_bear\"]","type":"json"}],"x":1100,"y":300,"wires":[["4239127242a1d3f6"]]},{"id":"4239127242a1d3f6","type":"link out","z":"88f8f06219122b1d","name":"Processed data out","mode":"link","links":["9c5ab2626688d1fd"],"x":1245,"y":300,"wires":[]},{"id":"e0d971f1bdb1c5d0","type":"catch","z":"88f8f06219122b1d","name":"","scope":null,"uncaught":false,"x":540,"y":540,"wires":[["c8ca5ddecdb7b754"]]},{"id":"c8ca5ddecdb7b754","type":"debug","z":"88f8f06219122b1d","name":"debug 10","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":680,"y":540,"wires":[]},{"id":"f250c0709c7a33e1","type":"comment","z":"88f8f06219122b1d","name":"Convert image to tensor and send Tensor to Triton Inference Server, process response and annotate it","info":"","x":530,"y":20,"wires":[]},{"id":"8d2c0d8b504f5e3c","type":"random-output","z":"88f8f06219122b1d","name":"rnd","outputs":5,"useWeights":false,"weights":["1","1","1","1","1","1","1","1","1"],"x":130,"y":240,"wires":[["798557d0e0e1610c"],["67fba945829f5b2b"],["b78a7ba80baafe6b"],["209d7368edebf18f"],["8f0c976f0ef71c4f"]]},{"id":"e15802e24fdc8a4d","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8010","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"}],"x":700,"y":140,"wires":[["9721d71a45af7eb5"]]},{"id":"b56dbf4649869c7f","type":"subflow:9215deec580c5391","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8010","type":"str"},{"name":"threshold","value":"0.60","type":"num"}],"x":1030,"y":220,"wires":[["370ef41edc3f7b8a"]]},{"id":"8fc0e996bd18ec10","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8020","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"}],"x":700,"y":200,"wires":[["9721d71a45af7eb5"]]},{"id":"7338505a38a56291","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":500,"y":140,"wires":[["e15802e24fdc8a4d"]]},{"id":"f7bf2150aa06ab9c","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":500,"y":200,"wires":[["8fc0e996bd18ec10"]]},{"id":"0b5e87a85ae01a92","type":"msg-speed","z":"88f8f06219122b1d","name":"images","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":240,"y":60,"wires":[[],["8d2c0d8b504f5e3c"]]},{"id":"94fb34abee55b6c2","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8030","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"}],"x":700,"y":260,"wires":[["9721d71a45af7eb5"]]},{"id":"093dc3d7014c8a1d","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8040","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"}],"x":700,"y":320,"wires":[["9721d71a45af7eb5"]]},{"id":"2ab913e5d264f577","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":500,"y":260,"wires":[["94fb34abee55b6c2"]]},{"id":"fe270303ec501006","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":500,"y":320,"wires":[["093dc3d7014c8a1d"]]},{"id":"7c76c55127eb9816","type":"link in","z":"88f8f06219122b1d","name":"Inference in","links":["45e670be922e56ae","c0bdeec189cc7e81","3287846f49abca62","6e32196b71a5c821","39a84a0d0e3bc62e"],"x":135,"y":60,"wires":[["0b5e87a85ae01a92"]]},{"id":"798557d0e0e1610c","type":"subflow:5d5c83b6c13135a8","z":"88f8f06219122b1d","name":"Parse JPEG","env":[{"name":"is_stream","value":"false","type":"bool"},{"name":"thumbnail_width","value":"50","type":"num"}],"x":330,"y":140,"wires":[["7338505a38a56291"]]},{"id":"67fba945829f5b2b","type":"subflow:5d5c83b6c13135a8","z":"88f8f06219122b1d","name":"Parse JPEG","env":[{"name":"is_stream","value":"false","type":"bool"},{"name":"thumbnail_width","value":"50","type":"num"}],"x":330,"y":200,"wires":[["f7bf2150aa06ab9c"]]},{"id":"b78a7ba80baafe6b","type":"subflow:5d5c83b6c13135a8","z":"88f8f06219122b1d","name":"Parse JPEG","env":[{"name":"is_stream","value":"false","type":"bool"},{"name":"thumbnail_width","value":"50","type":"num"}],"x":330,"y":260,"wires":[["2ab913e5d264f577"]]},{"id":"209d7368edebf18f","type":"subflow:5d5c83b6c13135a8","z":"88f8f06219122b1d","name":"Parse JPEG","env":[{"name":"is_stream","value":"false","type":"bool"},{"name":"thumbnail_width","value":"50","type":"num"}],"x":330,"y":320,"wires":[["fe270303ec501006"]]},{"id":"48cf188535ee357d","type":"subflow:fd51dfdc3367d25c","z":"88f8f06219122b1d","name":"","env":[{"name":"server_url","value":"localhost:8050","type":"str"},{"name":"model_name","value":"ssd-example-model","type":"str"},{"name":"request_timeout","value":"5000","type":"num"}],"x":700,"y":380,"wires":[["9721d71a45af7eb5"]]},{"id":"21c69fadeb49dc14","type":"subflow:fde3bd1da88bc03c","z":"88f8f06219122b1d","name":"","x":500,"y":380,"wires":[["48cf188535ee357d"]]},{"id":"8f0c976f0ef71c4f","type":"subflow:5d5c83b6c13135a8","z":"88f8f06219122b1d","name":"Parse JPEG","env":[{"name":"is_stream","value":"false","type":"bool"},{"name":"thumbnail_width","value":"50","type":"num"}],"x":330,"y":380,"wires":[["21c69fadeb49dc14"]]},{"id":"082771590bd65966","type":"comment","z":"9baae2baa8d6b1c7","name":"Start Triton Inference Server in multiple Dockers","info":"","x":220,"y":20,"wires":[]},{"id":"50cc98aa6ef19343","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 17","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":160,"wires":[]},{"id":"9f176bad102d9916","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 18","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":200,"wires":[]},{"id":"dec57918c3fc39ef","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":240,"wires":[]},{"id":"a9b0e7e1026709ef","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":220,"wires":[["17727c001180e47a"]]},{"id":"b72eb0783ff35f2f","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 20","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":40,"wires":[]},{"id":"59646a804798ed3f","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 21","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":80,"wires":[]},{"id":"a131f967956dd191","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 22","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":120,"wires":[]},{"id":"4553da76f4261f77","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":100,"wires":[["ddfa1169c57b0442"]]},{"id":"17727c001180e47a","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8020","command":"docker","args":"run --rm -p8020:8000 -p8021:8001 -p8022:8002 -v /home/tequ/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":220,"wires":[["50cc98aa6ef19343"],["9f176bad102d9916"],["dec57918c3fc39ef","bda28be5ac07aa12"]]},{"id":"ddfa1169c57b0442","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8010","command":"docker","args":"run --rm -p8010:8000 -p8011:8001 -p8012:8002 -v /home/tequ/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":100,"wires":[["b72eb0783ff35f2f"],["59646a804798ed3f"],["a131f967956dd191","1b6122abdafec689"]]},{"id":"bc6e11416e47f742","type":"exec","z":"9baae2baa8d6b1c7","command":"docker ps","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":220,"y":720,"wires":[["cd58ae7a65883e9a"],["ced3ba1d9e1136b3"],["586eb208f10fb950"]]},{"id":"b12af62701f9eb2e","type":"inject","z":"9baae2baa8d6b1c7","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":780,"wires":[["bc6e11416e47f742"]]},{"id":"ced3ba1d9e1136b3","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 28","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":400,"y":740,"wires":[]},{"id":"586eb208f10fb950","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 29","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":400,"y":780,"wires":[]},{"id":"cd58ae7a65883e9a","type":"split","z":"9baae2baa8d6b1c7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":390,"y":680,"wires":[["8eb8bc474d1db305"]]},{"id":"8eb8bc474d1db305","type":"join","z":"9baae2baa8d6b1c7","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":510,"y":680,"wires":[["5a9860316b7627f7"]]},{"id":"5a9860316b7627f7","type":"function","z":"9baae2baa8d6b1c7","name":"Get docker ids","func":"let values = (msg.payload).slice(1);;\nnode.warn(values)\nlet params;\n\nfor(let value in values){\n let item = values[value]\n if(item.length > 5){\n node.send({\"payload\":item.split(\" \")[0]})\n }\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":660,"y":680,"wires":[["4c8547a23123be74"]]},{"id":"4c8547a23123be74","type":"exec","z":"9baae2baa8d6b1c7","command":"docker stop ","addpay":"payload","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":830,"y":680,"wires":[["d1c0f1c5853f1f31"],["4cff2888777ec2dc"],["1108a8961e17efa5"]]},{"id":"d1c0f1c5853f1f31","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 30","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1000,"y":640,"wires":[]},{"id":"4cff2888777ec2dc","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 31","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1000,"y":680,"wires":[]},{"id":"1108a8961e17efa5","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 32","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1000,"y":720,"wires":[]},{"id":"977f7c2bef187e2e","type":"delay","z":"9baae2baa8d6b1c7","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":210,"y":660,"wires":[["bc6e11416e47f742"]]},{"id":"1b6122abdafec689","type":"link out","z":"9baae2baa8d6b1c7","name":"link out 5","mode":"link","links":["d2ddf97bf235b212"],"x":395,"y":140,"wires":[]},{"id":"d2ddf97bf235b212","type":"link in","z":"9baae2baa8d6b1c7","name":"reset dockers","links":["1b6122abdafec689","bda28be5ac07aa12","cfb961dd5a105ac6","31f5e6c1d3605637","2d6bae36cbaee302"],"x":95,"y":660,"wires":[["977f7c2bef187e2e"]]},{"id":"0b9bece6c192d7e2","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 34","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":400,"wires":[]},{"id":"d4f4f331567780d1","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 35","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":440,"wires":[]},{"id":"8e616bfaa20e0f05","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 36","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":480,"wires":[]},{"id":"d6c50685526a1d33","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":460,"wires":[["cea536d5b0f1b2c8"]]},{"id":"621e15a090eac72a","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 37","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":280,"wires":[]},{"id":"e2cc8b25298fba9a","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 38","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":320,"wires":[]},{"id":"adc69e75ccaaff9e","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 39","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":360,"wires":[]},{"id":"df12917451cc824e","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":340,"wires":[["528e26e95bea2eb4"]]},{"id":"cea536d5b0f1b2c8","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8040","command":"docker","args":"run --rm -p8040:8000 -p8041:8001 -p8042:8002 -v /home/tequ/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":460,"wires":[["0b9bece6c192d7e2"],["d4f4f331567780d1"],["8e616bfaa20e0f05","31f5e6c1d3605637"]]},{"id":"528e26e95bea2eb4","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8030","command":"docker","args":"run --rm -p8030:8000 -p8031:8001 -p8032:8002 -v /home/tequ/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":340,"wires":[["621e15a090eac72a"],["e2cc8b25298fba9a"],["adc69e75ccaaff9e","cfb961dd5a105ac6"]]},{"id":"f5fc6d0ec2dd3ec2","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 40","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":520,"wires":[]},{"id":"59a20e5e34d42b13","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 41","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":560,"wires":[]},{"id":"c0b1f90c54a3e4a4","type":"debug","z":"9baae2baa8d6b1c7","name":"debug 42","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":600,"wires":[]},{"id":"eac01b7e815bf8a7","type":"inject","z":"9baae2baa8d6b1c7","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":560,"wires":[["eabb15ec86d78e89"]]},{"id":"eabb15ec86d78e89","type":"daemon","z":"9baae2baa8d6b1c7","name":"Docker #8050","command":"docker","args":"run --rm -p8050:8000 -p8051:8001 -p8052:8002 -v /home/tequ/model_repository:/models nvcr.io/nvidia/tritonserver:22.12-tf2-python-py3 tritonserver --model-repository=/models --backend-config=tensorflow,version=2 --strict-model-config=false","autorun":true,"cr":false,"redo":true,"op":"string","closer":"SIGKILL","x":260,"y":560,"wires":[["f5fc6d0ec2dd3ec2"],["59a20e5e34d42b13"],["c0b1f90c54a3e4a4","2d6bae36cbaee302"]]},{"id":"bda28be5ac07aa12","type":"link out","z":"9baae2baa8d6b1c7","name":"link out 11","mode":"link","links":["d2ddf97bf235b212"],"x":395,"y":260,"wires":[]},{"id":"cfb961dd5a105ac6","type":"link out","z":"9baae2baa8d6b1c7","name":"link out 12","mode":"link","links":["d2ddf97bf235b212"],"x":395,"y":380,"wires":[]},{"id":"31f5e6c1d3605637","type":"link out","z":"9baae2baa8d6b1c7","name":"link out 13","mode":"link","links":["d2ddf97bf235b212"],"x":395,"y":500,"wires":[]},{"id":"2d6bae36cbaee302","type":"link out","z":"9baae2baa8d6b1c7","name":"link out 14","mode":"link","links":["d2ddf97bf235b212"],"x":395,"y":600,"wires":[]},{"id":"bfefca2ed130df7b","type":"subflow:ffeafac1.b0db18","z":"3ec4ce3c762176f0","name":"","env":[{"name":"username","value":"[email protected]","type":"str"},{"name":"password","type":"cred"}],"x":360,"y":300,"wires":[["d8812de9ce65e8fc"],[]]},{"id":"b0fb8fb2ca0301c9","type":"inject","z":"3ec4ce3c762176f0","name":"Update token","props":[{"p":"payload"}],"repeat":"300","crontab":"","once":true,"onceDelay":"30","topic":"","payload":"token[\"decoded\"]","payloadType":"global","x":160,"y":300,"wires":[["bfefca2ed130df7b"]]},{"id":"2b71fd0f0164cecc","type":"debug","z":"3ec4ce3c762176f0","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":300,"wires":[]},{"id":"d8812de9ce65e8fc","type":"change","z":"3ec4ce3c762176f0","name":"Set token","rules":[{"t":"set","p":"token","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":300,"wires":[["2b71fd0f0164cecc"]]},{"id":"c946848d995ec807","type":"debug","z":"3ec4ce3c762176f0","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":710,"y":200,"wires":[]},{"id":"46239ba840509f9e","type":"change","z":"3ec4ce3c762176f0","name":"Get token","rules":[{"t":"set","p":"token","pt":"msg","to":"token[\"token\"]","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":180,"y":200,"wires":[["fd12eb9c9c42c7dc"]]},{"id":"fd12eb9c9c42c7dc","type":"subflow:fcd42407.59d1a8","z":"3ec4ce3c762176f0","name":"","env":[{"name":"path","value":"/tmp/","type":"str"},{"name":"API_BASE_URL","value":"http://tequ-api-node-red-app","type":"str"}],"x":370,"y":200,"wires":[["c946848d995ec807"]]},{"id":"adeb94966ac47e8b","type":"inject","z":"3ec4ce3c762176f0","name":"Force update","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"5","topic":"force_update","x":170,"y":340,"wires":[["bfefca2ed130df7b"]]},{"id":"9c5ab2626688d1fd","type":"link in","z":"3ec4ce3c762176f0","name":"Images in","links":["4239127242a1d3f6"],"x":215,"y":100,"wires":[["b45f2a621969e6a5"]]},{"id":"5fbedcb3d4aa8974","type":"debug","z":"3ec4ce3c762176f0","name":"debug 41","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":720,"y":100,"wires":[]},{"id":"a142491676d98081","type":"catch","z":"3ec4ce3c762176f0","name":"","scope":null,"uncaught":false,"x":380,"y":400,"wires":[["a93839af2f73eeeb"]]},{"id":"a93839af2f73eeeb","type":"debug","z":"3ec4ce3c762176f0","name":"debug 42","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":720,"y":400,"wires":[]},{"id":"b45f2a621969e6a5","type":"subflow:75015de274d71273","z":"3ec4ce3c762176f0","name":"[API] Format data","env":[{"name":"enable","value":"false","type":"bool"}],"x":370,"y":100,"wires":[["5fbedcb3d4aa8974","46239ba840509f9e"]]},{"id":"382b06a3458ac107","type":"comment","z":"3ec4ce3c762176f0","name":"Images in","info":"","x":140,"y":60,"wires":[]}]
Example flow 3
- Connects to single Basler camera using GStreamer
- Parses JPEG stream from camera
- Opens RTSP server
- Publishes stream to RTSP
- Published MJPEG stream
[{"id":"04508fd4d91dd935","type":"tab","label":"RTSP","disabled":false,"info":"","env":[]},{"id":"332da02c8e396138","type":"tab","label":"GStreamer","disabled":false,"info":"","env":[]},{"id":"0d2c119e1f2d1adf","type":"tab","label":"Parse streams","disabled":false,"info":"","env":[]},{"id":"9489aca61655e278","type":"subflow","name":"DART - 40122260","info":"","category":"","in":[],"out":[{"x":920,"y":140,"wires":[{"id":"a54b868b7849ee23","port":1}]}],"env":[],"meta":{},"color":"#3FADB5","icon":"font-awesome/fa-video-camera","status":{"x":920,"y":300,"wires":[{"id":"558d1d9c457f3888","port":0}]}},{"id":"cba4bad7675abd95","type":"subflow","name":"DART - 40165426","info":"","category":"","in":[],"out":[{"x":900,"y":120,"wires":[{"id":"d62c1ede1f9d0f60","port":1}]}],"env":[],"meta":{},"color":"#3FADB5","icon":"font-awesome/fa-video-camera","status":{"x":900,"y":260,"wires":[{"id":"cbfa5a775aa79a82","port":0}]}},{"id":"ef3a418b8488d340","type":"subflow","name":"ACE - 23751808","info":"","category":"","in":[],"out":[{"x":860,"y":160,"wires":[{"id":"ee8d5a5e1687826c","port":1}]}],"env":[],"meta":{},"color":"#3FADB5","icon":"font-awesome/fa-video-camera","status":{"x":860,"y":300,"wires":[{"id":"2d12ae806a0eccd0","port":0}]}},{"id":"d171990f671be011","type":"subflow","name":"GigE - 40204286","info":"","category":"","in":[],"out":[{"x":820,"y":100,"wires":[{"id":"47882daff4ab657c","port":1}]}],"env":[],"meta":{},"color":"#DDAA99","status":{"x":820,"y":240,"wires":[{"id":"65607485fd3aca3c","port":0}]}},{"id":"83a7a965.1808a8","type":"subflow","name":"[IMG] Annotate","info":"","category":"Tequ-API Client","in":[{"x":120,"y":140,"wires":[{"id":"d05bfd8e.a02e"}]}],"out":[{"x":1080,"y":140,"wires":[{"id":"4e5f5c6c.bcf214","port":0}]}],"env":[{"name":"box_colors","type":"json","value":"{\"fish\":\"#FFFFFF\",\"pike\":\"#006400\",\"perch\":\"#008000\",\"smolt\":\"#ADD8E6\",\"salmon\":\"#0000FF\",\"trout\":\"#0000FF\",\"cyprinidae\":\"#808080\",\"zander\":\"#009000\",\"bream\":\"#008800\"}","ui":{"type":"input","opts":{"types":["json"]}}},{"name":"image_settings","type":"json","value":"{\"quality\":0.8}","ui":{"type":"input","opts":{"types":["json"]}}},{"name":"image_type","type":"str","value":"image/jpeg","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"JPG"},"v":"image/jpeg"},{"l":{"en-US":"PNG"},"v":"image/png"}]}}},{"name":"bbox_lineWidth","type":"num","value":"5","ui":{"type":"spinner","opts":{"min":0,"max":10}}},{"name":"bbox_text_color","type":"str","value":"white","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"white"},"v":"white"},{"l":{"en-US":"black"},"v":"black"},{"l":{"en-US":"blue"},"v":"blue"},{"l":{"en-US":"green"},"v":"green"},{"l":{"en-US":"yellow"},"v":"yellow"},{"l":{"en-US":"red"},"v":"red"},{"l":{"en-US":"orange"},"v":"orange"}]}}},{"name":"bbox_font","type":"str","value":"30px Arial","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"5px Arial"},"v":"5 px Arial"},{"l":{"en-US":"10px Arial"},"v":"10px Arial"},{"l":{"en-US":"15px Arial"},"v":"15px Arial"},{"l":{"en-US":"20px Arial"},"v":"20px Arial"},{"l":{"en-US":"25px Arial"},"v":"25px Arial"},{"l":{"en-US":"30px Arial"},"v":"30px Arial"},{"l":{"en-US":"35px Arial"},"v":"35px Arial"},{"l":{"en-US":"40px Arial"},"v":"40px Arial"},{"l":{"en-US":"45px Arial"},"v":"45px Arial"},{"l":{"en-US":"50px Arial"},"v":"50px Arial"}]}}},{"name":"label_offset_x","type":"num","value":"0","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"label_offset_y","type":"num","value":"30","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"threshold","type":"num","value":"0.75","ui":{"type":"spinner","opts":{"min":0,"max":1}}}],"meta":{"module":"[IMG] Annotate","version":"0.0.1","author":"[email protected]","desc":"Annotates prediction results from [AI] Detect subflows.","license":"MIT"},"color":"#87A980","icon":"font-awesome/fa-pencil-square-o","status":{"x":1080,"y":340,"wires":[{"id":"7fd4f6bf24348b12","port":0}]}},{"id":"fa7f491898fed374","type":"subflow","name":"gst-jetson","info":"","category":"Tequ-API Client","in":[{"x":120,"y":200,"wires":[{"id":"54dc40fe44895f9a"}]}],"out":[{"x":1100,"y":120,"wires":[{"id":"ab1595a359c8a71b","port":0},{"id":"dd701ced077fb628","port":0},{"id":"361321e30bc9bba9","port":0},{"id":"d86014e70dadc4b2","port":0}]}],"env":[{"name":"video_source","type":"str","value":"pylonsrc","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"pylonsrc"},"v":"pylonsrc"},{"l":{"en-US":"v4l2src"},"v":"v4l2src"}]}}},{"name":"v4l2_device","type":"str","value":"/dev/video0","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"serial","type":"str","value":"40257292","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"model","type":"str","value":"daA3840-45uc","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"manufacturer","type":"str","value":"Basler","ui":{"type":"input","opts":{"types":["str","env"]}}},{"name":"pfs_file","type":"str","value":"/home/tequ/40257292.pfs","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"enable_mjpeg","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool"]}}},{"name":"mjpeg_width","type":"num","value":"1920","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_height","type":"num","value":"1080","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_framerate","type":"num","value":"5","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"mjpeg_font_size","type":"num","value":"8","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"enable_rtsp","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool"]}}},{"name":"rtsp_width","type":"num","value":"3840","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_height","type":"num","value":"2160","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_font_size","type":"str","value":"4","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"rtsp_server","type":"str","value":"rtsp://localhost:8554/","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"rtsp_framerate","type":"num","value":"10","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"rtsp_encoder","type":"str","value":"nvv4l2h265enc","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"nvv4l2h265enc"},"v":"nvv4l2h265enc"},{"l":{"en-US":"nvv4l2h264enc"},"v":"nvv4l2h264enc"}]}}},{"name":"tcp_host","type":"str","value":"localhost","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"tcp_port","type":"num","value":"50001","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"video_width","type":"num","value":"3840","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"video_height","type":"num","value":"2160","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"video_type","type":"str","value":"video/x-raw","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"video_format","type":"str","value":"YUY2","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"video_framerate","type":"num","value":"10","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-basler-gst-jetson","version":"0.0.1","author":"[email protected]","desc":"Launch and control GStreamer pipelines.","license":"MIT"},"color":"#3FADB5","inputLabels":["command in"],"outputLabels":["info out"],"icon":"node-red/bridge.svg","status":{"x":1060,"y":360,"wires":[{"id":"6abd0b160a7877dd","port":0}]}},{"id":"21dbb5f62f40368e","type":"subflow","name":"Parse JPEG","info":"Parses JPEG image from MJPEG stream and adds metadata to msg.\r\n\r\nReads or adds:\r\n - Basic image info (width,height,size) \r\n - Exif data\r\n - Local timestamp, UTC timestamp, Unix timestamp \r\n - Thumbnail of the original image\r\n - Coordinates (if given)\r\n\r\n Output message is formatted to Tequ-API compatible format.\r\n\r\n","category":"Tequ-API Client","in":[{"x":40,"y":60,"wires":[{"id":"2ab9331e24332f8a"}]}],"out":[{"x":960,"y":480,"wires":[{"id":"b2856c4181e5257e","port":1}]}],"env":[{"name":"is_stream","type":"bool","value":"true","ui":{"label":{"en-US":"is_stream?"},"type":"input","opts":{"types":["bool","env"]}}},{"name":"latitude","type":"num","value":"66.503059","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"longitude","type":"num","value":"25.726967","ui":{"type":"input","opts":{"types":["num","env"]}}},{"name":"thumbnail","type":"bool","value":"true","ui":{"type":"input","opts":{"types":["bool","env"]}}},{"name":"width","type":"num","value":"50","ui":{"type":"input","opts":{"types":["num","env"]}}}],"meta":{"module":"tequ-parse-mjpeg","version":"0.0.1","author":"[email protected]","desc":"Parse JPEG from stream and add metadata to image","license":"MIT"},"color":"#3FADB5","inputLabels":["MJPEG stream in"],"outputLabels":["image out"],"icon":"font-awesome/fa-image","status":{"x":780,"y":540,"wires":[{"id":"64555399f8f3f8de","port":0}]}},{"id":"d9dd49bd747346d4","type":"subflow","name":"gst WD","info":"","category":"Tequ-API Client","in":[{"x":80,"y":60,"wires":[{"id":"4676b6d77fb4c9fd"}]}],"out":[{"x":840,"y":220,"wires":[{"id":"67250f6441a6d8f2","port":0}]},{"x":780,"y":60,"wires":[{"id":"4676b6d77fb4c9fd","port":1}]}],"env":[],"meta":{},"color":"#3FADB5","inputLabels":["Stream data in"],"outputLabels":["Restart cmd out",""],"icon":"font-awesome/fa-search","status":{"x":780,"y":340,"wires":[{"id":"42e72deef2a5b5b1","port":0}]}},{"id":"0c43c098ada195e0","type":"multipart-encoder","z":"9489aca61655e278","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":610,"y":240,"wires":[[]]},{"id":"0beed39026218af1","type":"http in","z":"9489aca61655e278","name":"","url":"/camera/id/40122260/stream/fps/max","method":"get","upload":false,"swaggerDoc":"","x":240,"y":240,"wires":[["0c43c098ada195e0"]]},{"id":"e92bb2d855ae25fb","type":"pipe2jpeg","z":"9489aca61655e278","name":"","x":380,"y":140,"wires":[["a54b868b7849ee23"]]},{"id":"a54b868b7849ee23","type":"msg-speed","z":"9489aca61655e278","name":"","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":570,"y":140,"wires":[[],["0c43c098ada195e0"]]},{"id":"558d1d9c457f3888","type":"status","z":"9489aca61655e278","name":"","scope":["a54b868b7849ee23","4021d05ed95b25e5"],"x":660,"y":300,"wires":[[]]},{"id":"8646bdc2b099d28d","type":"tcp in","z":"9489aca61655e278","name":"","server":"client","host":"localhost","port":"50001","datamode":"stream","datatype":"buffer","newline":"","topic":"40122260","base64":false,"x":170,"y":140,"wires":[["e92bb2d855ae25fb"]]},{"id":"68de1621a284bede","type":"tcp in","z":"cba4bad7675abd95","name":"","server":"client","host":"localhost","port":"50002","datamode":"stream","datatype":"buffer","newline":"","topic":"40165426","base64":false,"x":190,"y":120,"wires":[["1409f32e6d7ee8fa"]]},{"id":"d62c1ede1f9d0f60","type":"msg-speed","z":"cba4bad7675abd95","name":"DART - 40165426","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":690,"y":120,"wires":[[],["b31df317bcbfa3da"]]},{"id":"c09ddb13c15e3b57","type":"http in","z":"cba4bad7675abd95","name":"","url":"/camera/id/40165426/stream/fps/max","method":"get","upload":false,"swaggerDoc":"","x":260,"y":200,"wires":[["b31df317bcbfa3da"]]},{"id":"b31df317bcbfa3da","type":"multipart-encoder","z":"cba4bad7675abd95","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":710,"y":200,"wires":[[]]},{"id":"cbfa5a775aa79a82","type":"status","z":"cba4bad7675abd95","name":"","scope":["68de1621a284bede","d62c1ede1f9d0f60"],"x":760,"y":260,"wires":[[]]},{"id":"1409f32e6d7ee8fa","type":"pipe2jpeg","z":"cba4bad7675abd95","name":"","x":400,"y":120,"wires":[["d62c1ede1f9d0f60"]]},{"id":"d0a1b87c63a5e47b","type":"tcp in","z":"ef3a418b8488d340","name":"","server":"client","host":"localhost","port":"50003","datamode":"stream","datatype":"buffer","newline":"","topic":"23751808","base64":false,"x":250,"y":160,"wires":[["dc53ae2179753594"]]},{"id":"ee8d5a5e1687826c","type":"msg-speed","z":"ef3a418b8488d340","name":"msg-speed","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":650,"y":160,"wires":[[],["b8026a3fda41f254"]]},{"id":"a14caa8068688f1c","type":"http in","z":"ef3a418b8488d340","name":"","url":"/camera/id/23751808/stream/fps/max","method":"get","upload":false,"swaggerDoc":"","x":320,"y":220,"wires":[["b8026a3fda41f254"]]},{"id":"b8026a3fda41f254","type":"multipart-encoder","z":"ef3a418b8488d340","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":690,"y":220,"wires":[[]]},{"id":"dc53ae2179753594","type":"pipe2jpeg","z":"ef3a418b8488d340","name":"","x":420,"y":160,"wires":[["ee8d5a5e1687826c"]]},{"id":"2d12ae806a0eccd0","type":"status","z":"ef3a418b8488d340","name":"","scope":["d0a1b87c63a5e47b","ee8d5a5e1687826c"],"x":740,"y":300,"wires":[[]]},{"id":"274554060b15887c","type":"tcp in","z":"d171990f671be011","name":"","server":"client","host":"localhost","port":"50004","datamode":"stream","datatype":"buffer","newline":"","topic":"23751808","base64":false,"tls":"","x":170,"y":100,"wires":[["6d7196931ed7981a"]]},{"id":"47882daff4ab657c","type":"msg-speed","z":"d171990f671be011","name":"msg-speed","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":570,"y":100,"wires":[[],["1ac21286fa1dcc12"]]},{"id":"62400fdaae22b32d","type":"http in","z":"d171990f671be011","name":"","url":"/camera/id/40204286/stream/fps/max","method":"get","upload":false,"swaggerDoc":"","x":240,"y":160,"wires":[["1ac21286fa1dcc12"]]},{"id":"1ac21286fa1dcc12","type":"multipart-encoder","z":"d171990f671be011","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":610,"y":160,"wires":[[]]},{"id":"6d7196931ed7981a","type":"pipe2jpeg","z":"d171990f671be011","name":"","x":340,"y":100,"wires":[["47882daff4ab657c"]]},{"id":"65607485fd3aca3c","type":"status","z":"d171990f671be011","name":"","scope":["274554060b15887c","47882daff4ab657c"],"x":660,"y":240,"wires":[[]]},{"id":"c19ac6bd.2a9d08","type":"function","z":"83a7a965.1808a8","name":"Annotate with canvas","func":"const img = msg.payload;\nconst objects = msg.data.properties.computer_vision.result\nconst labels = msg.data.properties.computer_vision.labels\n\nconst image_type = env.get(\"image_type\");\nconst image_settings = env.get(\"image_settings\");\nconst bbox_lineWidth = env.get(\"bbox_lineWidth\");\nconst bbox_text_color = env.get(\"bbox_text_color\");\nconst label_offset_x = env.get(\"label_offset_x\");\nconst label_offset_y = env.get(\"label_offset_y\");\nconst bbox_font = env.get(\"bbox_font\");\nconst COLORS = env.get(\"box_colors\");\n\n\n//Define threshold\nlet threshold = 0;\n\nconst global_settings = global.get(\"settings\") || undefined\nlet thresholdType = \"\"\n\nif(global_settings !== undefined){\n if(\"threshold\" in global_settings){\n threshold = global_settings[\"threshold\"]\n thresholdType = \"global\";\n }\n}\n\nelse if(\"threshold\" in msg){\n threshold = msg.threshold;\n thresholdType = \"msg\";\n if(threshold < 0){\n threshold = 0\n }\n else if(threshold > 1){\n threshold = 1\n }\n}\n\nelse{\n threshold = env.get(\"threshold\");\n thresholdType = \"env\";\n}\n\nmsg.thresholdUsed = threshold;\nmsg.thresholdTypeUsed = thresholdType;\n\nasync function annotateImage(image) {\n const localImage = await canvas.loadImage(image); \n const cvs = canvas.createCanvas(localImage.width, localImage.height);\n const ctx = cvs.getContext('2d'); \n ctx.drawImage(localImage, 0, 0); \n \n objects.forEach((obj) => {\n if(labels.includes(obj.class) && obj.score >= threshold){\n let [x, y, w, h] = obj.bbox;\n ctx.lineWidth = bbox_lineWidth;\n ctx.strokeStyle = COLORS[obj.class];\n ctx.strokeRect(x, y, w, h);\n ctx.fillStyle = bbox_text_color;\n ctx.font = bbox_font;\n ctx.fillText(obj.class+\" \"+Math.round(obj.score*100)+\" %\",x+label_offset_x,y+label_offset_y);\n }\n });\n \n return cvs.toBuffer(image_type, image_settings);\n}\n\nif(objects.length > 0){\n msg.data.properties.object.data.annotated.image = await annotateImage(img) \n msg.objects_found = true\n}\nelse{\n msg.objects_found = false\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"canvas","module":"canvas"}],"x":440,"y":140,"wires":[["a801355d.9f7ac8"]]},{"id":"d05bfd8e.a02e","type":"change","z":"83a7a965.1808a8","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":140,"wires":[["c19ac6bd.2a9d08"]]},{"id":"a801355d.9f7ac8","type":"change","z":"83a7a965.1808a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.annotated.annotation_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"},{"t":"set","p":"payload.annotation.objects_found","pt":"msg","to":"objects_found","tot":"msg"},{"t":"delete","p":"annotated_image","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":140,"wires":[["c20a6448.e6f218"]]},{"id":"4e5f5c6c.bcf214","type":"change","z":"83a7a965.1808a8","name":"delete useless","rules":[{"t":"delete","p":"annotated_image","pt":"msg"},{"t":"delete","p":"start","pt":"msg"},{"t":"delete","p":"resize_start","pt":"msg"},{"t":"delete","p":"thresholdTypeUsed","pt":"msg"},{"t":"delete","p":"threshold","pt":"msg"},{"t":"delete","p":"thresholdUsed","pt":"msg"},{"t":"delete","p":"start","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":900,"y":140,"wires":[[]]},{"id":"c20a6448.e6f218","type":"switch","z":"83a7a965.1808a8","name":"objects found?","property":"objects_found","propertyType":"msg","rules":[{"t":"true"},{"t":"false"}],"checkall":"true","repair":false,"outputs":2,"x":220,"y":260,"wires":[["5fae1e95eb3561e9"],["0ec56ca8f000a540"]]},{"id":"a9379cd1321a02da","type":"function","z":"83a7a965.1808a8","name":"","func":"node.status({ fill: \"green\", shape: \"dot\", text: msg.thresholdTypeUsed + \" \" + msg.thresholdUsed + \" in \" + msg.data.properties.object.data.annotated.total_ms+\" ms\"})","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1040,"y":240,"wires":[]},{"id":"0ec56ca8f000a540","type":"function","z":"83a7a965.1808a8","name":"","func":"node.status({fill:\"green\",shape:\"dot\",text:msg.thresholdTypeUsed+\" \"+msg.thresholdUsed+\" No objects to annotate\"})\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":500,"y":300,"wires":[["4e5f5c6c.bcf214"]]},{"id":"7fd4f6bf24348b12","type":"status","z":"83a7a965.1808a8","name":"","scope":null,"x":860,"y":340,"wires":[[]]},{"id":"5fae1e95eb3561e9","type":"change","z":"83a7a965.1808a8","name":"timer","rules":[{"t":"set","p":"resize_start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":240,"wires":[["f5809fcdc54a540e"]]},{"id":"f5809fcdc54a540e","type":"function","z":"83a7a965.1808a8","name":"resize","func":"let input = msg.data.properties.object.data.annotated.image;\n\nlet resized = await sharp(input)\n .metadata()\n .then(({ width }) => sharp(input)\n .resize({ width: 200 })\n .toBuffer()\n);\n\nmsg.data.properties.object.data.annotated.thumbnail = resized.toString('base64');\nmsg.data.properties.object.data.annotated.image = (msg.data.properties.object.data.annotated.image).toString('base64')\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"sharp","module":"sharp"}],"x":630,"y":240,"wires":[["e0f13103c7faabff"]]},{"id":"e0f13103c7faabff","type":"change","z":"83a7a965.1808a8","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.annotated.thumbnail_ms","pt":"msg","to":"$millis() - msg.resize_start","tot":"jsonata"},{"t":"set","p":"data.properties.object.data.annotated.total_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":780,"y":240,"wires":[["4e5f5c6c.bcf214","a9379cd1321a02da"]]},{"id":"d9a2420055236c2b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"SIGTERM","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":120,"wires":[["99ac100731d2d825"]]},{"id":"be99e21d6ee788c1","type":"function","z":"fa7f491898fed374","name":"construct gst pipeline","func":"let serial = env.get(\"serial\");\nlet model = env.get(\"model\");\nlet pfs_file = env.get(\"pfs_file\");\nlet source = env.get(\"video_source\");\nlet v4l2_device = env.get(\"v4l2_device\");\nlet manufacturer = env.get(\"manufacturer\");\n\nlet enable_rtsp = env.get(\"enable_rtsp\")\nlet rtsp_width = env.get(\"rtsp_width\");\nlet rtsp_height = env.get(\"rtsp_height\");\nlet rtsp_framerate = env.get(\"rtsp_framerate\");\nlet rtsp_encoder = env.get(\"rtsp_encoder\");\nlet rtsp_font_size = env.get(\"rtsp_font_size\");\nlet rtsp_server = env.get(\"rtsp_server\");\n\nlet enable_mjpeg = env.get(\"enable_mjpeg\")\nlet mjpeg_width = env.get(\"mjpeg_width\");\nlet mjpeg_height = env.get(\"mjpeg_height\");\nlet mjpeg_framerate = env.get(\"mjpeg_framerate\");\nlet mjpeg_font_size = env.get(\"mjpeg_font_size\");\n\n\nlet video_width = env.get(\"video_width\");\nlet video_height = env.get(\"video_height\");\nlet video_format = env.get(\"video_format\");\nlet video_type = env.get(\"video_type\");\nlet video_framerate = env.get(\"video_framerate\");\nlet tcp_host = env.get(\"tcp_host\");\nlet tcp_port = env.get(\"tcp_port\");\nlet gst_pipeline;\n\n\n\n\nlet gst_msg = {}\n\nif (source == \"pylonsrc\"){\n gst_pipeline = \n source + ' capture-error=skip device-serial-number=\"' + serial + '\" pfs-location=' + pfs_file; \n \n gst_pipeline = gst_pipeline + ' ! \"' + video_type + ',width=' + video_width + ',height=' + video_height + ',framerate=' + video_framerate + '/1,format=' + video_format+ '\"'; \n gst_pipeline = gst_pipeline + ' ! tee name = video_out';\n\n\n if (enable_mjpeg){\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + mjpeg_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + mjpeg_width + ',height=' + mjpeg_height + ',framerate=' + mjpeg_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! nvjpegenc ! taginject tags = \"application-name=tequ-gst-1.0,copyright=Lapland_UAS,description=serialnumber_' + serial + ',artist=Tequ,device-manufacturer=' + manufacturer +',device-model='+model+'\" ! jifmux ! queue ! tcpclientsink host='+tcp_host+' port='+tcp_port;\n }\n if (enable_rtsp){\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + rtsp_font_size +'\" ! videoscale ! videorate ! \"' + video_type + ',width=' + rtsp_width + ',height=' + rtsp_height + ',framerate=' + rtsp_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! ' +rtsp_encoder+' ! queue ! rtspclientsink location = '+rtsp_server+serial+'';\n }\n}\nelse if (source == \"v4l2src\"){\n gst_pipeline =\n source + ' device=\"' + v4l2_device+'\"'; \n gst_pipeline = gst_pipeline + ' ! videoscale ! \"' + video_type + ',width=' + video_width + ',height=' + video_height + ',framerate=' + video_framerate + '/1,format=' + video_format + '\"';\n gst_pipeline = gst_pipeline + ' ! tee name = video_out';\n\n if (enable_mjpeg) {\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + mjpeg_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + mjpeg_width + ',height=' + mjpeg_height + ',framerate=' + mjpeg_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! nvjpegenc ! taginject tags = \"application-name=tequ-gst-1.0,copyright=Lapland_UAS,description=serialnumber_' + serial + ',artist=Tequ,device-manufacturer=' + manufacturer + ',device-model=' + model + '\" ! jifmux ! queue ! tcpclientsink host=' + tcp_host + ' port=' + tcp_port;\n }\n if (enable_rtsp) {\n gst_pipeline = gst_pipeline + ' video_out. ! clockoverlay time-format=\"%d-%m-%Y %H:%M:%S - ' + serial + '\" font-desc=\"Sans, ' + rtsp_font_size + '\" ! videoscale ! videorate ! \"' + video_type + ',width=' + rtsp_width + ',height=' + rtsp_height + ',framerate=' + rtsp_framerate + '/1,format=' + video_format + '\" ! nvvidconv ! ' + rtsp_encoder + ' ! queue ! rtspclientsink location = ' + rtsp_server + serial + '';\n }\n}\nelse {\n node.status({ fill: \"red\", shape: \"ring\", text: \"src: \" + source +\" is not supported\" });\n return null;\n}\n\ngst_msg.payload = gst_pipeline;\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Launching...\"});\nreturn gst_msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":320,"wires":[["99ac100731d2d825","ab1595a359c8a71b"]]},{"id":"99ac100731d2d825","type":"exec","z":"fa7f491898fed374","command":"gst-launch-1.0","addpay":"payload","append":"","useSpawn":"true","timer":"","winHide":false,"oldrc":false,"name":"gst-launch","x":710,"y":120,"wires":[["361321e30bc9bba9"],["dd701ced077fb628"],["d86014e70dadc4b2"]]},{"id":"8ba82764fc44edf8","type":"delay","z":"fa7f491898fed374","name":"","pauseType":"random","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"6","randomLast":"22","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":480,"y":240,"wires":[["be99e21d6ee788c1"]]},{"id":"f6110566b977602b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"kill","pt":"msg","to":"SIGTERM","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":180,"wires":[["8ba82764fc44edf8","99ac100731d2d825"]]},{"id":"6abd0b160a7877dd","type":"status","z":"fa7f491898fed374","name":"","scope":["be99e21d6ee788c1","99ac100731d2d825","54dc40fe44895f9a"],"x":760,"y":360,"wires":[[]]},{"id":"54dc40fe44895f9a","type":"function","z":"fa7f491898fed374","name":"cmd?","func":"let topic = msg.topic;\n\nif(topic == \"kill\"){\n node.status({fill:\"red\",shape:\"ring\",text:\"cmd: kill\"});\n return [msg,null,null]\n}\nelse if (topic == \"restart\") {\n node.status({ fill: \"yellow\", shape: \"ring\", text: \"cmd: restart\" });\n return [null, msg, null]\n}\nelse if (topic == \"start\") {\n node.status({ fill: \"blue\", shape: \"ring\", text: \"cmd: start\" });\n return [null, null, msg]\n}\n\nreturn msg;","outputs":3,"noerr":0,"initialize":"","finalize":"","libs":[],"x":230,"y":200,"wires":[["d9a2420055236c2b"],["f6110566b977602b"],["be99e21d6ee788c1"]]},{"id":"ab1595a359c8a71b","type":"change","z":"fa7f491898fed374","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"pipeline-info","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":320,"wires":[[]]},{"id":"dd701ced077fb628","type":"change","z":"fa7f491898fed374","name":"stderr","rules":[{"t":"set","p":"topic","pt":"msg","to":"stderr","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":120,"wires":[[]]},{"id":"361321e30bc9bba9","type":"change","z":"fa7f491898fed374","name":"stdout","rules":[{"t":"set","p":"topic","pt":"msg","to":"stdout","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":80,"wires":[[]]},{"id":"d86014e70dadc4b2","type":"change","z":"fa7f491898fed374","name":"return code","rules":[{"t":"set","p":"topic","pt":"msg","to":"return code","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":160,"wires":[[]]},{"id":"e0bb72dfae4ee3a3","type":"image-info","z":"21dbb5f62f40368e","name":"","x":170,"y":360,"wires":[["e4dd6a59044e7bfa"]]},{"id":"e4dd6a59044e7bfa","type":"exif","z":"21dbb5f62f40368e","name":"","mode":"normal","property":"payload","x":150,"y":420,"wires":[["8f854870.b60a68"]]},{"id":"f89675e462ce03bb","type":"moment","z":"21dbb5f62f40368e","name":"","topic":"","input":"","inputType":"date","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"en-US","output":"utc_timestamp","outputType":"msg","outTz":"Europe/Helsinki","x":200,"y":180,"wires":[["0aa0578efb06e6b3"]]},{"id":"0aa0578efb06e6b3","type":"moment","z":"21dbb5f62f40368e","name":"","topic":"","input":"utc_timestamp","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"YYYY-MM-DD HH:mm:ss","locale":"en-US","output":"local_timestamp","outputType":"msg","outTz":"Europe/Helsinki","x":200,"y":240,"wires":[["684d7d4f12541303"]]},{"id":"684d7d4f12541303","type":"moment","z":"21dbb5f62f40368e","name":"","topic":"","input":"utc_timestamp","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"x","locale":"en-US","output":"unix_timestamp","outputType":"msg","outTz":"ETC/UTC","x":200,"y":300,"wires":[["e0bb72dfae4ee3a3"]]},{"id":"64555399f8f3f8de","type":"status","z":"21dbb5f62f40368e","name":"","scope":["b2856c4181e5257e"],"x":600,"y":540,"wires":[[]]},{"id":"13ad0fba970dab22","type":"function","z":"21dbb5f62f40368e","name":"Reformat data","func":"let type;\nlet random_name = uuid.v4();\nlet image_type = msg.type;\nlet file_extension;\nlet latitude = Number(env.get(\"latitude\"))\nlet longitude = Number(env.get(\"longitude\"))\nlet unix_timestamp = parseInt(msg.unix_timestamp);\nlet serial;\ntry{\n serial = (msg.exif.image.ImageDescription).split(\"_\")[1];\n}\ncatch(e){\n serial = \"unknown\"\n}\n\nlet datasource = serial;\n\nif (image_type == \"jpg\") {\n image_type = \"image/jpeg\"\n file_extension = \".jpg\"\n}\nelse if (image_type == \"png\") {\n image_type = \"image/png\"\n file_extension = \".png\"\n}\n\nmsg.topic = serial;\nmsg.datasource = serial;\nmsg.random_name = random_name;\nmsg.file_extension = file_extension;\n\nlet parameters = {\n \"owner\": msg.exif.image.Copyright,\n \"version\": msg.exif.image.Software,\n \"model\": msg.exif.image.Model,\n \"serial\": serial,\n \"manufacturer\": msg.exif.image.Make\n}\n\nmsg.data = {\n \"type\": \"Feature\",\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [longitude, latitude]\n },\n \"properties\": {\n \"datasource\": datasource,\n \"local_timestamp\": msg.local_timestamp,\n \"utc_timestamp\": msg.utc_timestamp,\n \"unix_timestamp\": unix_timestamp,\n \"cos\": {\n \"bucket\": \"\",\n \"region\": \"\",\n \"service_id\": \"\"\n },\n \"object\": {\n \"type\": image_type,\n \"data\": {\n \"width\": msg.width,\n \"height\": msg.height,\n \"size\": (msg.payload).length,\n \"exif\": msg.exif,\n \"parameters\": parameters,\n \"original\": {\n \"image\": (msg.payload).toString('base64'),\n \"objectname\": datasource + \"-\" + random_name + file_extension,\n \"thumbnail\": (msg.thumbnail).toString('base64'),\n \"thumbnail_ms\": msg.thumbnail_ms,\n \"mjpeg_process_ms\":0\n },\n \"annotated\": {\n \"image\": \"\",\n \"objectname\": datasource + \"-\" + random_name+ \"_annotated\"+file_extension,\n \"thumbnail\": \"\",\n \"thumbnail_ms\":0,\n \"annotation_ms\":0,\n \"total_ms\":0\n }\n }\n },\n \"computer_vision\": {\n \"type\": \"\",\n \"model\": \"\",\n \"inference_time\": \"\",\n \"result\": \"\"\n }\n }\n}\n\ndelete msg.settings;\ndelete msg.width;\ndelete msg.height;\ndelete msg.type;\ndelete msg.exif;\ndelete msg.thumbnail;\ndelete msg.utc_timestamp;\ndelete msg.local_timestamp;\ndelete msg.unix_timestamp;\ndelete msg.start;\ndelete msg.thumbnail_ms;\ndelete msg.datasource;\ndelete msg.random_name;\ndelete msg.file_extension;\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"uuid","module":"uuid"}],"x":620,"y":400,"wires":[["cfd1798c21f67f4b"]]},{"id":"8f854870.b60a68","type":"change","z":"21dbb5f62f40368e","name":"timer","rules":[{"t":"set","p":"start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":420,"wires":[["7ebfd14d.6f0a2"]]},{"id":"11af73fe.677eac","type":"change","z":"21dbb5f62f40368e","name":"end timer","rules":[{"t":"set","p":"thumbnail_ms","pt":"msg","to":"$millis() - msg.start","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":340,"wires":[["13ad0fba970dab22"]]},{"id":"24296ef596b98b25","type":"change","z":"21dbb5f62f40368e","name":"timer","rules":[{"t":"set","p":"process_start","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":100,"wires":[["f89675e462ce03bb"]]},{"id":"7ebfd14d.6f0a2","type":"function","z":"21dbb5f62f40368e","name":"resize","func":"let input = msg.payload;\nlet width = env.get(\"thumbnail_width\")\nlet create_thumbnail = env.get(\"thumbnail\")\nlet thumbnail;\n\nif (create_thumbnail){\n thumbnail = await sharp(input)\n .metadata()\n .then(({ width }) => sharp(input)\n .resize({ width: width })\n .toBuffer()\n );\n\n \n}\nelse{\n thumbnail = []\n}\nmsg.thumbnail = thumbnail\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"sharp","module":"sharp"}],"x":450,"y":340,"wires":[["11af73fe.677eac"]]},{"id":"cfd1798c21f67f4b","type":"change","z":"21dbb5f62f40368e","name":"end timer","rules":[{"t":"set","p":"data.properties.object.data.original.mjpeg_process_ms","pt":"msg","to":"$millis() - msg.process_start","tot":"jsonata"},{"t":"delete","p":"process_start","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":460,"wires":[["b2856c4181e5257e"]]},{"id":"79f2e9e678938947","type":"split","z":"21dbb5f62f40368e","name":"","splt":"[255, 216, 255]","spltType":"bin","arraySplt":1,"arraySpltType":"len","stream":true,"addname":"","x":330,"y":40,"wires":[["ce93aab9fcf9afda"]]},{"id":"ce93aab9fcf9afda","type":"function","z":"21dbb5f62f40368e","name":"Join","func":"let header = Buffer.from(msg.parts.ch);\nlet image = Buffer.from(msg.payload);\nlet arr = [header,image]\nmsg.payload = Buffer.concat(arr)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":40,"wires":[["24296ef596b98b25"]]},{"id":"b2856c4181e5257e","type":"msg-speed","z":"21dbb5f62f40368e","name":"images","frequency":"sec","interval":1,"estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":760,"y":460,"wires":[[],[]]},{"id":"2ab9331e24332f8a","type":"switch","z":"21dbb5f62f40368e","name":"is_stream?","property":"is_stream","propertyType":"env","rules":[{"t":"true"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":170,"y":60,"wires":[["79f2e9e678938947"],["24296ef596b98b25"]]},{"id":"4676b6d77fb4c9fd","type":"msg-speed","z":"d9dd49bd747346d4","name":"","frequency":"sec","interval":"5","estimation":false,"ignore":false,"pauseAtStartup":false,"topicDependent":false,"x":210,"y":60,"wires":[["75a772553f72adc5"],[]]},{"id":"75a772553f72adc5","type":"switch","z":"d9dd49bd747346d4","name":"== 0","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":170,"y":160,"wires":[["48bd712e32556613"]]},{"id":"48bd712e32556613","type":"delay","z":"d9dd49bd747346d4","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"minute","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":180,"y":220,"wires":[["10b1bb59b99fd89e"]]},{"id":"10b1bb59b99fd89e","type":"trigger","z":"d9dd49bd747346d4","name":"","op1":"{\"topic\":\"restart\",\"payload\":\"ok\"}","op2":"","op1type":"json","op2type":"nul","duration":"5","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":380,"y":220,"wires":[["860b8a639262a949"]]},{"id":"67250f6441a6d8f2","type":"change","z":"d9dd49bd747346d4","name":"restart","rules":[{"t":"set","p":"topic","pt":"msg","to":"restart","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":220,"wires":[["abcd5255fa959167"]]},{"id":"abcd5255fa959167","type":"function","z":"d9dd49bd747346d4","name":"Restart","func":"node.status({fill:\"red\",shape:\"ring\",text:\"no data, restart\"});\nreturn msg;","outputs":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":820,"y":180,"wires":[]},{"id":"42e72deef2a5b5b1","type":"status","z":"d9dd49bd747346d4","name":"","scope":["4676b6d77fb4c9fd","abcd5255fa959167"],"x":640,"y":340,"wires":[[]]},{"id":"883688b62b7bec6b","type":"inject","z":"d9dd49bd747346d4","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":"1","topic":"","payload":"","payloadType":"date","x":130,"y":20,"wires":[["4676b6d77fb4c9fd"]]},{"id":"860b8a639262a949","type":"delay","z":"d9dd49bd747346d4","name":"","pauseType":"random","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"5","randomLast":"25","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":520,"y":220,"wires":[["67250f6441a6d8f2"]]},{"id":"449388bafc5ced99","type":"inject","z":"04508fd4d91dd935","name":"KILL","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":100,"wires":[["fe9c51b3673ce6ee"]]},{"id":"bb209580ff5b4836","type":"debug","z":"04508fd4d91dd935","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":470,"y":60,"wires":[]},{"id":"5d12eb90f740fdd6","type":"debug","z":"04508fd4d91dd935","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":470,"y":100,"wires":[]},{"id":"fe9c51b3673ce6ee","type":"daemon","z":"04508fd4d91dd935","name":"RTSP server","command":"/home/tequ/rtsp-simple-server/rtsp-simple-server","args":"/home/tequ/rtsp-simple-server/rtsp-simple-server.yml","autorun":true,"cr":true,"redo":true,"op":"string","closer":"SIGKILL","x":270,"y":100,"wires":[["bb209580ff5b4836"],["5d12eb90f740fdd6"],["03372fcec2f8d5be"]]},{"id":"f4e0dab8f6118c77","type":"comment","z":"04508fd4d91dd935","name":"Start local RTSP server ","info":"","x":160,"y":40,"wires":[]},{"id":"03372fcec2f8d5be","type":"debug","z":"04508fd4d91dd935","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":470,"y":140,"wires":[]},{"id":"b50216a2b31d801b","type":"inject","z":"332da02c8e396138","name":"kill","props":[{"p":"kill","v":"SIGTERM","vt":"str"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"kill","x":130,"y":100,"wires":[["d22449da926eb9b1"]]},{"id":"d22449da926eb9b1","type":"subflow:fa7f491898fed374","z":"332da02c8e396138","name":"gst Basler 40198132","env":[{"name":"serial","value":"40198132","type":"str"},{"name":"pfs_file","value":"/home/tequ/40198132.pfs","type":"str"},{"name":"mjpeg_width","value":"854","type":"num"},{"name":"mjpeg_height","value":"480","type":"num"},{"name":"mjpeg_framerate","value":"10","type":"num"},{"name":"rtsp_encoder","value":"nvv4l2h264enc","type":"str"},{"name":"framerate","value":"5","type":"num"}],"x":360,"y":60,"wires":[["21f2142dbe030a40"]]},{"id":"9e2794684ea9e823","type":"link in","z":"332da02c8e396138","name":"40198132 in","links":["3b4445143b5d37b1"],"x":165,"y":60,"wires":[["d22449da926eb9b1"]]},{"id":"21f2142dbe030a40","type":"debug","z":"332da02c8e396138","name":"Log","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":550,"y":60,"wires":[]},{"id":"927817224e3149a0","type":"comment","z":"332da02c8e396138","name":"Start GStreamer and connect to Basler camera using camera Serial number","info":"","x":290,"y":20,"wires":[]},{"id":"dfefe6ec0d823cdb","type":"inject","z":"332da02c8e396138","name":"start","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":"1","topic":"start","payload":"","payloadType":"date","x":130,"y":140,"wires":[["d22449da926eb9b1"]]},{"id":"3097982829e635f4","type":"tcp in","z":"0d2c119e1f2d1adf","name":"","server":"server","host":"localhost","port":"50001","datamode":"stream","datatype":"buffer","newline":"","topic":"","trim":false,"base64":false,"tls":"","x":110,"y":60,"wires":[["09f9c5151ea072ae"]]},{"id":"3b4445143b5d37b1","type":"link out","z":"0d2c119e1f2d1adf","name":"40198132 wd out","mode":"link","links":["9e2794684ea9e823"],"x":625,"y":40,"wires":[]},{"id":"09f9c5151ea072ae","type":"subflow:21dbb5f62f40368e","z":"0d2c119e1f2d1adf","name":"Parse JPEG","env":[{"name":"thumbnail","value":"false","type":"bool"},{"name":"thumbnail_width","value":"50","type":"num"}],"x":310,"y":60,"wires":[["ecf6867daa7efe37"]]},{"id":"ecf6867daa7efe37","type":"subflow:d9dd49bd747346d4","z":"0d2c119e1f2d1adf","name":"","x":480,"y":60,"wires":[["3b4445143b5d37b1"],["105f5bee0e3a36ca"]]},{"id":"105f5bee0e3a36ca","type":"link out","z":"0d2c119e1f2d1adf","name":"JPEGs out","mode":"link","links":["70b287d622b1444c","d4207e520d8f51aa","f707dcdac040c0ad"],"x":625,"y":80,"wires":[]},{"id":"a2db749f57aed2eb","type":"catch","z":"0d2c119e1f2d1adf","name":"","scope":null,"uncaught":false,"x":240,"y":280,"wires":[["13cf22af4398336a"]]},{"id":"13cf22af4398336a","type":"debug","z":"0d2c119e1f2d1adf","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":400,"y":280,"wires":[]},{"id":"e881009b9922778f","type":"comment","z":"0d2c119e1f2d1adf","name":"Receive JPEG stream from GStreamer, parse JPEGs","info":"","x":220,"y":20,"wires":[]},{"id":"bef8e6b5d81557a0","type":"switch","z":"0d2c119e1f2d1adf","name":"Camera ID?","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"40198132","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":220,"wires":[["b053e148e82ca078"]]},{"id":"f707dcdac040c0ad","type":"link in","z":"0d2c119e1f2d1adf","name":"JPEGs in","links":["105f5bee0e3a36ca","4523844c7f21ed3e","a0e008ef8a207cdc","aad43f8362deb0db","c1c1f56ebd3de480"],"x":425,"y":180,"wires":[["bef8e6b5d81557a0"]]},{"id":"a221a34a58b5e202","type":"change","z":"0d2c119e1f2d1adf","name":"set","rules":[{"t":"set","p":"topic","pt":"msg","to":"req.params.id","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":220,"wires":[["bef8e6b5d81557a0"]]},{"id":"b053e148e82ca078","type":"multipart-encoder","z":"0d2c119e1f2d1adf","name":"Encode MJPEG stream","statusCode":"","ignoreMessages":true,"outputOneNew":false,"outputIfSingle":false,"outputIfAll":false,"globalHeaders":{"Content-Type":"multipart/x-mixed-replace;boundary=--myboundary","Connection":"keep-alive","Expires":"Fri, 01 Jan 1990 00:00:00 GMT","Cache-Control":"no-cache, no-store, max-age=0, must-revalidate","Pragma":"no-cache"},"partHeaders":{"Content-Type":"image/jpeg"},"destination":"all","highWaterMark":16384,"x":750,"y":220,"wires":[[]]},{"id":"b6b77db57ece09b4","type":"http in","z":"0d2c119e1f2d1adf","name":"","url":"/camera/id/:id/stream/:stream","method":"get","upload":false,"swaggerDoc":"","x":160,"y":220,"wires":[["a221a34a58b5e202"]]},{"id":"e3f10ecc442f9b85","type":"comment","z":"0d2c119e1f2d1adf","name":"Publish MJPEG stream","info":"","x":120,"y":180,"wires":[]}]