IoT: decodificar display con NodeRED y OCR en local

Fecha publicación
Dificultad
Intermedio
#
37
3 more properties
Publicado
tags
arduino, esp8266, iot, internet of things, m5stack, M5core, mqtt, mosquitto, vision, ffmpeg, OCR, node-red, nodered, docker, docker-compose, tesseract, node


Descripción

Disponemos de este descalcificador instalado en el garaje:
escenari.jpg
Usando una cámara IP vamos a capturar la imagen de lo que sale en la pantalla del descalcificador. Como interface de usuario tendremos un M5Stack basado en ESP32. Así pues, cada vez que pulsemos un botón del dispositivo IoT (M5Stack) este se publicará en un broker de mensajes MQTT. Se capturará el mensaje en NodeRED donde usando un OCR instalado en local se decodificará la imagen. Concretamente usamos una aplicación de HP llamada Tesseract. Esta información se mandará de vuelta a la pantalla del M5Stack para que la visualice el usuario.

El esquema del escenario quedaría así:
IoT+IA.drawio.png
Para los que no conozcaís M5Stack tiene esta pinta:
Untitled

Flow de NodeRED

Untitled

Dependencias

Hay que tener instalado el node: node-red-contrib-tesseract
Untitled

Código del flow

YAML
[{"id":"f60a422b.eb35","type":"tab","label":"Local Vision","disabled":false,"info":""},{"id":"f3509ca4.226c3","type":"inject","z":"f60a422b.eb35","name":"manual test","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":470,"y":160,"wires":[["e66284f1.cb7528"]]},{"id":"e66284f1.cb7528","type":"exec","z":"f60a422b.eb35","command":"sudo docker run --rm jrottenberg/ffmpeg -y -rtsp_transport tcp -i 'rtsp://admin:ges2ges.@10.2.8.95/h264/ch1/sub/av_stream' -filter:v \"crop=704:536:0:20\" -vframes 1 -f image2pipe -vcodec png -","addpay":"","append":"","useSpawn":"false","timer":"60","oldrc":false,"name":"ffmpeg","x":650,"y":240,"wires":[["5e01ca97.09aef4","9fca843.eb6ac78"],["d6c548dd.75efe8"],["364d77a6.cf24b8"]]},{"id":"5e01ca97.09aef4","type":"file","z":"f60a422b.eb35","name":"debug: image.png","filename":"/data/image.png","appendNewline":true,"createDir":false,"overwriteFile":"true","encoding":"none","x":930,"y":300,"wires":[[]]},{"id":"d6c548dd.75efe8","type":"debug","z":"f60a422b.eb35","name":"ffmeg error","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":360,"wires":[]},{"id":"524fcf3b.f1e45","type":"mqtt in","z":"f60a422b.eb35","name":"display/button","topic":"display/button","qos":"2","datatype":"auto","broker":"d32bbf31.d1fa5","nl":false,"rap":true,"rh":0,"x":130,"y":240,"wires":[["b3e6e19e.fa369","56a95d95.b7bb74"]]},{"id":"5379112c.7d096","type":"switch","z":"f60a422b.eb35","name":"Button A?","property":"payload.button","propertyType":"msg","rules":[{"t":"eq","v":"A","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":480,"y":240,"wires":[["e66284f1.cb7528"]]},{"id":"b3e6e19e.fa369","type":"debug","z":"f60a422b.eb35","name":"MQTT RX msgs","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":160,"y":340,"wires":[]},{"id":"56a95d95.b7bb74","type":"json","z":"f60a422b.eb35","name":"","property":"payload","action":"","pretty":false,"x":330,"y":240,"wires":[["5379112c.7d096"]]},{"id":"364d77a6.cf24b8","type":"debug","z":"f60a422b.eb35","name":"ffmeg output code","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"msg","x":930,"y":420,"wires":[]},{"id":"9fca843.eb6ac78","type":"tesseract","z":"f60a422b.eb35","name":"OCR","language":"eng","x":750,"y":100,"wires":[["74506b90.ce8d14","75a9c4a0.c0abac"]]},{"id":"75a9c4a0.c0abac","type":"debug","z":"f60a422b.eb35","name":"debug ocr","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"msg","x":1040,"y":100,"wires":[]},{"id":"3fd0b4a1.c0f19c","type":"mqtt out","z":"f60a422b.eb35","name":"display/text","topic":"display/text","qos":"0","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"d32bbf31.d1fa5","x":1070,"y":200,"wires":[]},{"id":"74506b90.ce8d14","type":"function","z":"f60a422b.eb35","name":"clean string","func":"\nreturn {\n    payload: msg.payload.replace(/\\s{2,10}/g, ' ').trim()\n};","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":890,"y":200,"wires":[["3fd0b4a1.c0f19c","75a9c4a0.c0abac"]]},{"id":"d32bbf31.d1fa5","type":"mqtt-broker","name":"local MQTT broker","broker":"localhost","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]