├── .gitignore ├── CONTRIBUTING.assets ├── image-20210616170849246.png ├── image-20210616171245562.png └── image-20210616171455593.png ├── CONTRIBUTING.md ├── DCO1.1.txt ├── HOW_TO_OPEN_PRIVATE_ISSUE ├── LICENSE ├── README.assets ├── image-20210523100742742.png ├── image-20210523103545894.png ├── image-20210523104636081.png ├── image-20210523105001539.png ├── image-20210523110805336.png ├── image-20210523111416302.png ├── image-20210523112859049.png ├── image-20210523113303257.png ├── image-20210523133355485.png ├── image-20210523134108712.png ├── image-20210523134142673.png ├── image-20210523134400043.png ├── image-20210523134551463.png └── image-20210523134817527.png ├── README.md ├── nodes ├── edge_server_infer.html ├── edge_server_infer.js ├── icons │ ├── ibm_mvi_logo_blue.png │ ├── ibm_mvi_logo_gradation.png │ ├── ibm_mvi_logo_purple.png │ ├── ibm_mvi_logo_white.png │ └── logo.pptx ├── iterate_over_objects.html ├── iterate_over_objects.js ├── object_contains.html ├── object_contains.js ├── server_infer.html └── server_infer.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | 107 | package-lock.json 108 | .node-version 109 | .project 110 | 111 | tmp 112 | -------------------------------------------------------------------------------- /CONTRIBUTING.assets/image-20210616170849246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/CONTRIBUTING.assets/image-20210616170849246.png -------------------------------------------------------------------------------- /CONTRIBUTING.assets/image-20210616171245562.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/CONTRIBUTING.assets/image-20210616171245562.png -------------------------------------------------------------------------------- /CONTRIBUTING.assets/image-20210616171455593.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/CONTRIBUTING.assets/image-20210616171455593.png -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to node-red-contrib-ibm-mvi Project 2 | 3 | 4 | 5 | ## Option1. Search your symptom or new feature in existing issues 6 | 7 | Before submitting a new issue, you may find your symptom in past discussions in [Issues](https://github.com/IBM/node-red-contrib-ibm-mvi/issues?q=is%3Aissue). 8 | 9 | 10 | 11 | 12 | 13 | ## Option2. Submit a new issue 14 | 15 | If you cannot find your symptom or , then please share the problem with us by submitting a [new issue](https://github.com/IBM/node-red-contrib-ibm-mvi/issues/new/choose). 16 | 17 | 18 | 19 | 20 | 21 | ## Option3. Fork/Branch the repository, commit your code with signoff, and send pull request 22 | 23 | 24 | 25 | ### Developer Certificate of Origin (DCO) 26 | 27 | node-red-contrib-ibm-mvi have tried to make it as easy as possible to make contributions. This applies to how we handle the legal aspects of contribution. We use the same approach - the [DCO1.1.txt](DCO1.1.txt) that the Linux® Kernel [community](https://elinux.org/Developer_Certificate_Of_Origin) uses to manage code contributions. We simply ask that when submitting a patch for review, the developer must include a sign-off statement in the commit message. Here is an example Signed-off-by line, which indicates that the submitter accepts the DCO: 28 | 29 | ``` 30 | Signed-off-by: John Doe 31 | ``` 32 | 33 | You can include this automatically when you commit a change to your local git repository using the following command: 34 | 35 | ``` 36 | git commit -s 37 | ``` 38 | 39 | 40 | 41 | ### Procedure 42 | 43 | 44 | 45 | #### Developer not in IBM 46 | 47 | 1. Push `fork` button 48 | image-20210616170849246 49 | 2. Clone your forked repo (`git clone git@github.com:YOURNAME/node-red-contrib-ibm-mvi.git`) 50 | 3. Add your changes (`git add MODIFIED_FILES`) 51 | 4. Commit your changes (`git commit -s -m 'Add some feature'`) 52 | 5. Push to the branch (`git push origin main`) 53 | 6. In `Pull requests` tab, push `New pull request` button. 54 | image-20210616171245562 55 | 7. Push `Create pull request` button. 56 | image-20210616171455593 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | #### Developer in IBM Group 68 | 69 | 1. Clone this repo (`git clone git@github.com:IBM/node-red-contrib-ibm-mvi.git`) 70 | 2. Create your feature branch (`git checkout -b my-new-feature`) 71 | 3. Add your changes (`git add MODIFIED_FILES`) 72 | 4. Commit your changes (`git commit -s -m 'Add some feature'`) 73 | 5. Push to the branch (`git push origin my-new-feature`) 74 | 6. Create a new Pull Request 75 | 76 | -------------------------------------------------------------------------------- /DCO1.1.txt: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 1 Letterman Drive 6 | Suite D4700 7 | San Francisco, CA, 94129 8 | 9 | Everyone is permitted to copy and distribute verbatim copies of this 10 | license document, but changing it is not allowed. 11 | 12 | 13 | Developer's Certificate of Origin 1.1 14 | 15 | By making a contribution to this project, I certify that: 16 | 17 | (a) The contribution was created in whole or in part by me and I 18 | have the right to submit it under the open source license 19 | indicated in the file; or 20 | 21 | (b) The contribution is based upon previous work that, to the best 22 | of my knowledge, is covered under an appropriate open source 23 | license and I have the right under that license to submit that 24 | work with modifications, whether created in whole or in part 25 | by me, under the same open source license (unless I am 26 | permitted to submit under a different license), as indicated 27 | in the file; or 28 | 29 | (c) The contribution was provided directly to me by some other 30 | person who certified (a), (b) or (c) and I have not modified 31 | it. 32 | 33 | (d) I understand and agree that this project and the contribution 34 | are public and that a record of the contribution (including all 35 | personal information I submit with it, including my sign-off) is 36 | maintained indefinitely and may be redistributed consistent with 37 | this project or the open source license(s) involved. -------------------------------------------------------------------------------- /HOW_TO_OPEN_PRIVATE_ISSUE: -------------------------------------------------------------------------------- 1 | If you found vulnerabilities of this software, you must not open a new issue for that on public repositry. 2 | Please send email to nogayama@gmail.com, nogayama@jp.ibm.com with details of the vulnerability. 3 | 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 International Business Machines 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.assets/image-20210523100742742.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523100742742.png -------------------------------------------------------------------------------- /README.assets/image-20210523103545894.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523103545894.png -------------------------------------------------------------------------------- /README.assets/image-20210523104636081.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523104636081.png -------------------------------------------------------------------------------- /README.assets/image-20210523105001539.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523105001539.png -------------------------------------------------------------------------------- /README.assets/image-20210523110805336.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523110805336.png -------------------------------------------------------------------------------- /README.assets/image-20210523111416302.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523111416302.png -------------------------------------------------------------------------------- /README.assets/image-20210523112859049.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523112859049.png -------------------------------------------------------------------------------- /README.assets/image-20210523113303257.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523113303257.png -------------------------------------------------------------------------------- /README.assets/image-20210523133355485.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523133355485.png -------------------------------------------------------------------------------- /README.assets/image-20210523134108712.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523134108712.png -------------------------------------------------------------------------------- /README.assets/image-20210523134142673.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523134142673.png -------------------------------------------------------------------------------- /README.assets/image-20210523134400043.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523134400043.png -------------------------------------------------------------------------------- /README.assets/image-20210523134551463.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523134551463.png -------------------------------------------------------------------------------- /README.assets/image-20210523134817527.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/README.assets/image-20210523134817527.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Node-RED nodes for IBM Maximo Visual Inspection (MVI) 3 | 4 | [Maximo Visual Inspection (MVI)](https://www.ibm.com/products/maximo/remote-monitoring#section-heading-4) makes computer vision with deep learning more accessible to business users. MVI includes an intuitive toolset that empowers subject matter experts to label, train, and deploy deep learning vision models, without coding or deep learning expertise. 5 | 6 | node-red-contrib-ibm-mvi is a [Node-RED](https://nodered.org/) module for IBM Maximo Visual Inspection (MVI). This repo provides nodes that make MVI easy to use. Also a flow of Node-RED is easy to understand what the flow does because of its graphical flow representation. 7 | 8 | 9 | ## Demo movies 10 | 11 | **OK** 12 | 13 | https://user-images.githubusercontent.com/11750755/122221729-87bf5880-ceec-11eb-820b-87344ebb8a37.mp4 14 | 15 | **NG**(Please play with unmute mode🔊. Node-RED sounds beep when human has a bag.) 16 | 17 | https://user-images.githubusercontent.com/11750755/122222032-d40a9880-ceec-11eb-8429-294413885682.mp4 18 | 19 | ---- 20 | 21 | **Table of Contents** 22 | - [Node-RED nodes for IBM Maximo Visual Inspection (MVI)](#node-red-nodes-for-ibm-maximo-visual-inspection--mvi-) 23 | * [Setup](#setup) 24 | * [Usage](#usage) 25 | * [Examples](#examples) 26 | + [Inspection with MVI server](#inspection-with-mvi-server) 27 | + [Inspection with MVI Edge server](#inspection-with-mvi-edge-server) 28 | + [Custom inspection with MVI edge server](#custom-inspection-with-mvi-edge-server) 29 | + [Demo movies](#demo-movies) 30 | * [Author](#author) 31 | * [License](#license) 32 | 33 | 34 | 35 | 36 | ## Setup 37 | 38 | 1. Initialize local npm environment. 39 | 40 | ```sh 41 | $ mkdir workdir && cd workdir 42 | $ npm init -y 43 | ``` 44 | 45 | 2. Install Node-RED, Email node 46 | 47 | ```sh 48 | $ npm install node-red 49 | ``` 50 | 51 | 3. Download tar.gz file from [Releases](https://github.com/IBM/node-red-contrib-ibm-mvi/releases) 52 | 53 | 4. Install tar.gz file 54 | 55 | ```sh 56 | $ npm install node-red-contrib-ibm-mvi-1.0.0.tgz 57 | ``` 58 | 59 | 60 | 61 | ## Usage 62 | 63 | 1. Start Node-RED 64 | ```sh 65 | $ ./node_modules/.bin/node-red 66 | ``` 67 | 68 | 2. Open Node-RED GUI [http://localhost:1880/](http://localhost:1880/) 69 | 70 | 3. Drag & Drop MVI nodes from pallet to flow 71 | image-20210523100742742 72 | 73 | 74 | 75 | 76 | 77 | ## Examples 78 | 79 | 80 | 81 | ### Inspection with MVI server 82 | 83 | 84 | 85 | 1. Drag & drop `http in`, `http response`, and `infer with MVI server`nodes. 86 | image-20210523134108712 87 | 88 | 2. Select `POST` method and `Accept file uploads`, and set URL `/inspect` 89 | image-20210523134551463 90 | 91 | 3. Copy inference URL by clicking `Copy` button in deployed model dashboard. 92 | image-20210523133355485 93 | 94 | 4. Paste the url to property page of `infer with MVI server` node in Node-RED. 95 | image-20210523134142673 96 | 97 | 5. Test the flow by using curl 98 | ```sh 99 | $ curl -i -F files=@path/to/wear_image.jpeg http://localhost:1880/inspect 100 | ``` 101 | 102 | 103 | ### Inspection with MVI Edge server 104 | 105 | 1. Drag & drop `http in`, `http response`, and `infer with MVI Edge server`nodes. 106 | image-20210523134400043 107 | 108 | 2. Select `POST` method and `Accept file uploads`, and set URL `/inspect` 109 | image-20210523134551463 110 | 111 | 3. Identify http port number that provides MVI Edge service on Edge Server by executing `docker ps`. For example, `8080` port provides the MVI service below. 112 | 113 | ```sh 114 | [Edge Server] $ docker ps 115 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 116 | 21851c707ce1 vision-dnn-deploy-x86:1.3.0.0 "/opt/DNN/bin/setup_…" 2 days ago Up 2 days 0.0.0.0:8080->5001/tcp wear_inspection 117 | ``` 118 | 119 | 4. Double click `Infer with MVI edge server` node and set URL `http://localhost:8080/inference` 120 | image-20210523134817527 121 | 5. Test the flow by using curl 122 | ```sh 123 | $ curl -i -F files=@path/to/wear_image.jpeg http://localhost:1880/inspect 124 | ``` 125 | 126 | 127 | 128 | 129 | ### Custom inspection with MVI edge server 130 | 131 | 1. install email node & restart Node-RED 132 | ```sh 133 | $ npm install node-red-node-email 134 | ``` 135 | 136 | 2. Copy the following json to your clipboard 137 | ```json 138 | [{"id":"f273d263.653618","type":"http in","z":"f876ec98.2830b8","name":"","url":"/inspect","method":"post","upload":true,"swaggerDoc":"","x":160,"y":60,"wires":[["94412a3.5300658"]]},{"id":"3dc74f4d.75869","type":"join","z":"f876ec98.2830b8","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":1590,"y":560,"wires":[["8fc326b.9d49ad8"]]},{"id":"8fc326b.9d49ad8","type":"http response","z":"f876ec98.2830b8","name":"return resutls as JSON","statusCode":"","headers":{},"x":1750,"y":640,"wires":[]},{"id":"66857a22.73a244","type":"ibm-mvi-iterate-over-objects","z":"f876ec98.2830b8","name":"","objectLabel":"Human","x":360,"y":240,"wires":[["de5ab147.3ba388"],["3f1cd422.3dc8fc"]]},{"id":"3f1cd422.3dc8fc","type":"http response","z":"f876ec98.2830b8","name":"return OK because of no Human","statusCode":"","headers":{},"x":650,"y":240,"wires":[]},{"id":"94412a3.5300658","type":"ibm-mvi-edge-server-infer","z":"f876ec98.2830b8","name":"","mviUriToInfer":"http://localhost:5000/inference","x":310,"y":140,"wires":[["66857a22.73a244"]]},{"id":"2426eac5.3385a6","type":"group","z":"f876ec98.2830b8","name":"Flow for each human","style":{"label":true},"nodes":["bb3efe5.05cfa8","8c656000.9efc88","638e051.737f97c","de5ab147.3ba388","eff1b3f6.6749","6d47b983.b42dc","df149778.156ee"],"x":414,"y":299,"w":1192,"h":242},{"id":"bb3efe5.05cfa8","type":"function","z":"f876ec98.2830b8","g":"2426eac5.3385a6","name":"set NG","func":"msg.payload[\"result\"] = \"NG\";\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1320,"y":500,"wires":[["3dc74f4d.75869","6d47b983.b42dc","df149778.156ee"]]},{"id":"8c656000.9efc88","type":"function","z":"f876ec98.2830b8","g":"2426eac5.3385a6","name":"set OK","func":"msg.payload[\"result\"] = \"OK\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1330,"y":340,"wires":[["3dc74f4d.75869"]]},{"id":"638e051.737f97c","type":"ibm-mvi-object-contains","z":"f876ec98.2830b8","g":"2426eac5.3385a6","name":"","objectLabel":"Bag","negation":true,"x":840,"y":360,"wires":[["eff1b3f6.6749"],["bb3efe5.05cfa8"]]},{"id":"de5ab147.3ba388","type":"ibm-mvi-object-contains","z":"f876ec98.2830b8","g":"2426eac5.3385a6","name":"","objectLabel":"RedNeckStrap","negation":false,"x":550,"y":380,"wires":[["638e051.737f97c"],["bb3efe5.05cfa8"]]},{"id":"eff1b3f6.6749","type":"ibm-mvi-object-contains","z":"f876ec98.2830b8","g":"2426eac5.3385a6","name":"","objectLabel":"PC","negation":true,"x":1080,"y":340,"wires":[["8c656000.9efc88"],["bb3efe5.05cfa8"]]},{"id":"6d47b983.b42dc","type":"e-mail","z":"f876ec98.2830b8","g":"2426eac5.3385a6","server":"your.smtp.server","port":"465","secure":true,"tls":true,"name":"","dname":"","x":1530,"y":380,"wires":[]},{"id":"df149778.156ee","type":"exec","z":"f876ec98.2830b8","g":"2426eac5.3385a6","command":"osascript -e 'display notification \"IBM Maximo Visual Inspection\" with title \"Wear rule violation is detected\"'","addpay":"","append":"","useSpawn":"false","timer":"","oldrc":false,"name":"Notify","x":1530,"y":460,"wires":[[],[],[]]}] 139 | ``` 140 | 141 | 3. Import the flow 142 | image-20210523103545894 143 | 144 | 4. Paste the JSON and click import button 145 | image-20210523104636081 146 | image-20210523105001539 147 | 148 | 149 | 4. Identify http port number that provides MVI Edge service on Edge Server by executing `docker ps`. For example, `8080` port provides the MVI service below. 150 | 151 | ```sh 152 | [Edge Server] $ docker ps 153 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 154 | 21851c707ce1 vision-dnn-deploy-x86:1.3.0.0 "/opt/DNN/bin/setup_…" 2 days ago Up 2 days 0.0.0.0:8080->5001/tcp wear_inspection 155 | 156 | ``` 157 | 158 | 5. Double click `Infer with MVI edge server` node and set URL `http://localhost:8080/inference` 159 | image-20210523110805336 160 | 161 | 6. Double click `email` node and set 162 | 163 | 1. Destination email address 164 | 2. SMTP server address 165 | 3. userID and password of the SMTP server 166 | 167 | image-20210523111416302 168 | 169 | 7. Double click `Notify` node. and set notify command. 170 | 171 | 1. **If Node-RED on MAC OS**: `osascript -e 'display notification "IBM Maximo Visual Inspection" with title "Wear rule violation is detected"'` 172 | 2. **If Node-RED on Linux**: `notify-send "Wear rule violation is detected"` 173 | image-20210523112859049 174 | 175 | 8. Click deploy button. 176 | 177 | 9. Test the flow by using curl 178 | 179 | ```sh 180 | $ curl -i -F files=@path/to/wear_image.jpeg http://localhost:1880/inspect 181 | ``` 182 | 183 | image-20210523113303257 184 | 185 | ### Demo movies 186 | 187 | #### OK 188 | 189 | https://user-images.githubusercontent.com/11750755/122221729-87bf5880-ceec-11eb-820b-87344ebb8a37.mp4 190 | 191 | #### NG 192 | 193 | https://user-images.githubusercontent.com/11750755/122222032-d40a9880-ceec-11eb-8429-294413885682.mp4 194 | 195 | 196 | Author 197 | ------ 198 | 199 | - **Takahide Nogayama** - [Nogayama](https://github.com/nogayama) 200 | 201 | 202 | License 203 | ------- 204 | 205 | This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details 206 | 207 | Contributing 208 | ------------ 209 | 210 | Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. 211 | -------------------------------------------------------------------------------- /nodes/edge_server_infer.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 29 | 30 | 40 | 41 | -------------------------------------------------------------------------------- /nodes/edge_server_infer.js: -------------------------------------------------------------------------------- 1 | // ================================================================= 2 | // node-red-contrib-ibm-mvi 3 | // 4 | // Copyright (c) 2021 Takahide Nogayama 5 | // 6 | // This software is released under the MIT License. 7 | // http://opensource.org/licenses/mit-license.php 8 | // ================================================================= 9 | 10 | module.exports = function (RED) { 11 | 12 | // ノードコンストラクタ https://nodered.jp/docs/creating-nodes/node-js#%E3%83%8E%E3%83%BC%E3%83%89%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF 13 | function EdgeServerInferNode(config) { 14 | RED.nodes.createNode(this, config); 15 | var node = this; 16 | // const mviUriToInfer = config.mviUriToInfer; 17 | 18 | // メッセージ受信 https://nodered.jp/docs/creating-nodes/node-js#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E5%8F%97%E4%BF%A1 19 | this.on('input', function (msg, send, done) { 20 | const IbmMvi = require('ibm-mvi'); 21 | 22 | IbmMvi.post_multipart_form_data(msg, send, done, config.mviUriToInfer, function () { 23 | console.log(msg._body); 24 | jsonobj = JSON.parse(msg._body) 25 | 26 | node.log(JSON.stringify(jsonobj, null, 4)); 27 | 28 | msg.payload = jsonobj; 29 | send(msg); 30 | done(); 31 | }); 32 | 33 | }); 34 | } 35 | RED.nodes.registerType("ibm-mvi-edge-server-infer", EdgeServerInferNode); 36 | } 37 | -------------------------------------------------------------------------------- /nodes/icons/ibm_mvi_logo_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/nodes/icons/ibm_mvi_logo_blue.png -------------------------------------------------------------------------------- /nodes/icons/ibm_mvi_logo_gradation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/nodes/icons/ibm_mvi_logo_gradation.png -------------------------------------------------------------------------------- /nodes/icons/ibm_mvi_logo_purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/nodes/icons/ibm_mvi_logo_purple.png -------------------------------------------------------------------------------- /nodes/icons/ibm_mvi_logo_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/nodes/icons/ibm_mvi_logo_white.png -------------------------------------------------------------------------------- /nodes/icons/logo.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/node-red-contrib-ibm-mvi/a1e66a5948eb103b54d516ec4c565ab2caa6a257/nodes/icons/logo.pptx -------------------------------------------------------------------------------- /nodes/iterate_over_objects.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 41 | 42 | 52 | 53 | -------------------------------------------------------------------------------- /nodes/iterate_over_objects.js: -------------------------------------------------------------------------------- 1 | // ================================================================= 2 | // node-red-contrib-ibm-mvi 3 | // 4 | // Copyright (c) 2021 Takahide Nogayama 5 | // 6 | // This software is released under the MIT License. 7 | // http://opensource.org/licenses/mit-license.php 8 | // ================================================================= 9 | 10 | module.exports = function (RED) { 11 | 12 | // ノードコンストラクタ https://nodered.jp/docs/creating-nodes/node-js#%E3%83%8E%E3%83%BC%E3%83%89%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF 13 | function IterateOverObjectsNode(config) { 14 | RED.nodes.createNode(this, config); 15 | var node = this; 16 | 17 | // メッセージ受信 https://nodered.jp/docs/creating-nodes/node-js#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E5%8F%97%E4%BF%A1 18 | this.on('input', function (msg, send, done) { 19 | try { 20 | const targetObjectLabel = config.objectLabel; 21 | 22 | const targetObjects = msg._mvi_res.classified.filter((detected_object) => { 23 | return (detected_object.label == targetObjectLabel); 24 | }); 25 | 26 | node.log(`Iterating over detected target objects (length==${targetObjects.length})`); 27 | 28 | if (targetObjects.length >= 1) { 29 | msg.parts = {}; 30 | msg.parts.id = RED.util.generateId(); 31 | msg.parts.type = "array"; 32 | msg.parts.len = 1; 33 | msg.parts.count = targetObjects.length; 34 | 35 | targetObjects.forEach(function (targetObject, index) { 36 | msg.parts.index = index; 37 | msg.payload = targetObject; 38 | // send(msg); 39 | 40 | node.status({ fill: "yellow", shape: "dot", text: `Iterating (${index + 1}/${targetObjects.length})` }); 41 | 42 | // send(RED.util.cloneMessage(msg)); 43 | send([RED.util.cloneMessage(msg), null]); 44 | }); 45 | 46 | node.status({ fill: "green", shape: "dot", text: `Done (${targetObjects.length}/${targetObjects.length})` }); 47 | setTimeout(function () { node.status({}); }, 10000); // clear status after 10s 48 | 49 | } else { 50 | node.status({ fill: "green", shape: "dot", text: `Object==${targetObjectLabel} is not found` }); 51 | setTimeout(function () { node.status({}); }, 10000); // clear status after 10s 52 | 53 | send([null, msg]); 54 | } 55 | 56 | 57 | } catch (err) { 58 | // エラー処理 https://nodered.jp/docs/creating-nodes/node-js#%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%A6%E7%90%86 59 | // If an error is hit, report it to the runtime 60 | if (done) { 61 | // Node-RED 1.0 compatible 62 | done(err); 63 | } else { 64 | // Node-RED 0.x compatible 65 | node.error(err, msg); 66 | } 67 | } 68 | if (done) { 69 | done(); 70 | } 71 | }); 72 | } 73 | RED.nodes.registerType("ibm-mvi-iterate-over-objects", IterateOverObjectsNode); 74 | } 75 | -------------------------------------------------------------------------------- /nodes/object_contains.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 50 | 51 | 66 | 67 | -------------------------------------------------------------------------------- /nodes/object_contains.js: -------------------------------------------------------------------------------- 1 | // ================================================================= 2 | // node-red-contrib-ibm-mvi 3 | // 4 | // Copyright (c) 2021 Takahide Nogayama 5 | // 6 | // This software is released under the MIT License. 7 | // http://opensource.org/licenses/mit-license.php 8 | // ================================================================= 9 | 10 | module.exports = function (RED) { 11 | 12 | // ノードコンストラクタ https://nodered.jp/docs/creating-nodes/node-js#%E3%83%8E%E3%83%BC%E3%83%89%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF 13 | function ObjectContainsNode(config) { 14 | RED.nodes.createNode(this, config); 15 | var node = this; 16 | 17 | // メッセージ受信 https://nodered.jp/docs/creating-nodes/node-js#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E5%8F%97%E4%BF%A1 18 | this.on('input', function (msg, send, done) { 19 | 20 | try { 21 | const IbmMvi = require('ibm-mvi'); 22 | 23 | const overlapThreshold = 0.5; 24 | const detectedObjects = msg._mvi_res.classified; 25 | 26 | const subject = msg.payload; 27 | const objectLabel = config.objectLabel; 28 | 29 | const subjectContainsObject = IbmMvi.subject_contains_one_or_more_objects(subject, objectLabel, detectedObjects, overlapThreshold); 30 | 31 | if (subjectContainsObject) { 32 | node.log(`${msg.payload.label} contains ${objectLabel}`); 33 | } else { 34 | node.log(`${msg.payload.label} does not contain ${objectLabel}`); 35 | } 36 | 37 | if (!config.negation) { 38 | if (subjectContainsObject) { 39 | node.status({ fill: "green", shape: "dot", text: `${msg.payload.label} contains ${objectLabel}` }); 40 | send([msg, null]); 41 | } else { 42 | node.status({ fill: "red", shape: "dot", text: `${msg.payload.label} does not contain ${objectLabel}` }); 43 | send([null, msg]); 44 | } 45 | } else { 46 | if (subjectContainsObject) { 47 | node.status({ fill: "red", shape: "dot", text: `${msg.payload.label} contains ${objectLabel}` }); 48 | send([null, msg]); 49 | } else { 50 | node.status({ fill: "green", shape: "dot", text: `${msg.payload.label} does not contain ${objectLabel}` }); 51 | send([msg, null]); 52 | } 53 | } 54 | 55 | setTimeout(function () { node.status({}); }, 10000); // clear status after 10s 56 | 57 | } catch (err) { 58 | // エラー処理 https://nodered.jp/docs/creating-nodes/node-js#%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%A6%E7%90%86 59 | // If an error is hit, report it to the runtime 60 | if (done) { 61 | // Node-RED 1.0 compatible 62 | done(err); 63 | } else { 64 | // Node-RED 0.x compatible 65 | node.error(err, msg); 66 | } 67 | } 68 | if (done) { 69 | done(); 70 | } 71 | }); 72 | } 73 | RED.nodes.registerType("ibm-mvi-object-contains", ObjectContainsNode); 74 | } 75 | -------------------------------------------------------------------------------- /nodes/server_infer.html: -------------------------------------------------------------------------------- 1 | 11 | 12 | 29 | 30 | 40 | 41 | -------------------------------------------------------------------------------- /nodes/server_infer.js: -------------------------------------------------------------------------------- 1 | // ================================================================= 2 | // node-red-contrib-ibm-mvi 3 | // 4 | // Copyright (c) 2021 International Business Machines 5 | // 6 | // This software is released under the MIT License. 7 | // http://opensource.org/licenses/mit-license.php 8 | // ================================================================= 9 | 10 | module.exports = function (RED) { 11 | 12 | // ノードコンストラクタ https://nodered.jp/docs/creating-nodes/node-js#%E3%83%8E%E3%83%BC%E3%83%89%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF 13 | function ServerInferNode(config) { 14 | RED.nodes.createNode(this, config); 15 | var node = this; 16 | // const mviUriToInfer = config.mviUriToInfer; 17 | 18 | // メッセージ受信 https://nodered.jp/docs/creating-nodes/node-js#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E5%8F%97%E4%BF%A1 19 | this.on('input', function (msg, send, done) { 20 | try { 21 | 22 | if (!config.mviUriToInfer) { 23 | throw "URI is not found" 24 | } 25 | 26 | const IbmMvi = require('ibm-mvi'); 27 | 28 | node.status({ fill: "yellow", shape: "dot", text: "Calling API ..." }); 29 | 30 | IbmMvi.post_multipart_form_data(node, msg, send, done, config.mviUriToInfer, function () { 31 | // console.log(msg._mvi_res_raw); 32 | jsonobj = JSON.parse(msg._mvi_res_raw) 33 | 34 | node.log(JSON.stringify(jsonobj, null, 4)); 35 | 36 | msg.payload = jsonobj; 37 | msg._mvi_res = jsonobj; 38 | 39 | node.status({ fill: "green", shape: "dot", text: "Done" }); 40 | setTimeout(function () { node.status({}); }, 10000); // clear status after 10s 41 | 42 | send(msg); 43 | done(); 44 | }); 45 | 46 | } catch (err) { 47 | // エラー処理 https://nodered.jp/docs/creating-nodes/node-js#%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%A6%E7%90%86 48 | // If an error is hit, report it to the runtime 49 | if (done) { 50 | // Node-RED 1.0 compatible 51 | done(err); 52 | } else { 53 | // Node-RED 0.x compatible 54 | node.error(err, msg); 55 | } 56 | if (done) { 57 | done(); 58 | } 59 | } 60 | 61 | 62 | // const FormData = require('form-data'); 63 | // const fs = require('fs'); 64 | // const tmp = require('tmp'); 65 | 66 | // tmp.file(function _tempFileCreated(tempfileErr, tempfilePath, tempfileFd, tempfileCleanupCallback) { 67 | // if (tempfileErr) throw tempfileErr; 68 | 69 | // console.log('File: ', tempfilePath); 70 | 71 | // fs.writeFileSync(tempfilePath, msg.req.files[0].buffer); 72 | 73 | // const form = new FormData(); 74 | // form.append('files', fs.createReadStream(tempfilePath)); 75 | 76 | // form.submit(config.mviUriToInfer, function(err, res) { 77 | // if(err){ 78 | // if(err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') { 79 | // node.error(RED._("common.notification.errors.no-response"), msg); 80 | // node.status({fill:"red", shape:"ring", text:"common.notification.errors.no-response"}); 81 | // }else{ 82 | // node.error(err,msg); 83 | // node.status({fill:"red", shape:"ring", text:err.code}); 84 | // } 85 | // msg.payload = err.toString() + " : " + url; 86 | // msg.statusCode = err.code; 87 | // send(msg); 88 | // done(); 89 | // }else{ 90 | // console.log(res.statusCode); 91 | 92 | // var body = ""; 93 | // res.on('data', function(chunk) { 94 | // body += chunk; 95 | // }); 96 | // res.on('end', function() { 97 | // // console.log(body); 98 | // jsonobj = JSON.parse(body) 99 | // tempfileCleanupCallback(); // clean up tempfile 100 | 101 | // console.log(JSON.stringify(jsonobj, null, 4)); 102 | 103 | 104 | // msg.payload = jsonobj; 105 | // send(msg); 106 | // done(); 107 | // }); 108 | // } 109 | // }); 110 | // }); 111 | }); 112 | } 113 | RED.nodes.registerType("ibm-mvi-server-infer", ServerInferNode); 114 | } 115 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-red-contrib-ibm-mvi", 3 | "version": "1.0.1", 4 | "description": "node-RED module for IBM Maximo Visual Inspection (MVI)", 5 | "homepage": "https://github.com/IBM/node-red-contrib-ibm-mvi", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/IBM/node-red-contrib-ibm-mvi.git" 12 | }, 13 | "keywords": [ 14 | "node-red", 15 | "ibm", 16 | "maximo", 17 | "visual", 18 | "inspection" 19 | ], 20 | "author": "Takahide Nogayama", 21 | "license": "MIT", 22 | "node-red": { 23 | "nodes": { 24 | "ibm-mvi-server-infer": "nodes/server_infer.js", 25 | "ibm-mvi-edge_server-infer": "nodes/edge_server_infer.js", 26 | "ibm-mvi-iterate-over-objects": "nodes/iterate_over_objects.js", 27 | "ibm-mvi-object-contains": "nodes/object_contains.js" 28 | } 29 | }, 30 | "dependencies": { 31 | "form-data": "^3.0.0", 32 | "node-red": "^1.3.5", 33 | "tmp": ">=0.1.0" 34 | }, 35 | "bugs": { 36 | "url": "https://github.com/IBM/node-red-contrib-ibm-mvi/issues" 37 | }, 38 | "main": "index.js" 39 | } 40 | --------------------------------------------------------------------------------