diff --git a/bascula_autonoma_1.json b/bascula_autonoma_1.json
index c64154f..101ec81 100644
--- a/bascula_autonoma_1.json
+++ b/bascula_autonoma_1.json
@@ -292,7 +292,8 @@
"f3676f905e4ade55",
"ff3913749bd9e2f3",
"6af84585bb71f167",
- "a0f7956de8f33a0b"
+ "a0f7956de8f33a0b",
+ "b22cc0f171be84d5"
],
"x": 54,
"y": 893,
@@ -656,7 +657,8 @@
"9b0761cc102bc028",
"8385582377c91fb6",
"a0aa0f96fe081912",
- "730bbe3df0ab62db"
+ "730bbe3df0ab62db",
+ "4abf2246aa647ea1"
],
"x": 1504,
"y": 1319,
@@ -796,7 +798,7 @@
{
"id": "be0e1690e4e13e0d",
"type": "websocket-client",
- "path": "ws://servidor.com:1880",
+ "path": "ws://servidor.com:25009",
"tls": "",
"wholemsg": "false",
"hb": "20",
@@ -1198,7 +1200,7 @@
"z": "953e8740401d175c",
"g": "2af1fbc4.72dce4",
"name": "envio QR/RFID",
- "func": "\nlet mensaje1 = \"\";let mensaje2 = \"\";let reverseid = \"\";//cada mensaje es enviado y usado como una linea en html\nnode.status({fill:\"green\",shape:\"dot\",text:msg.payload});\nif (msg.id_topic == \"QR\") { //check si el mensaje es del lector de QR\n //if (flow.get(\"peso_estable_flag\") && flow.get(\"modo_automatico\")) {\n if (!flow.get(\"peso_bajo_flag\") ) {\n mensaje1 = \"Lectura del QR:\";\n mensaje2 = msg.payload;\n flow.set(\"esperando_id\", false) // No permitimos envio de otro ID en esta pesada\n flow.set(\"last_QR\", msg.payload)\n msg.payload = {};\n msg.id_topic = \"QR\"\n msg.payload.QR = mensaje2;\n msg.payload.QR_ok_flag = true;\n flow.set(\"QR_ok_flag\", true); // marcamos que hemos colocado un codigo QR en last_QR\n flow.set(\"RFID_ok_flag\", false);\n flow.set(\"ID_enviado\", false) // lo pongo temporalmente para hacer pruebas. Normalmente solo se permite enviar un QR\n }\n else {\n mensaje1 = \"Lectura de QR para BD\";\n mensaje2 = msg.payload;\n //msg.hex = Number(mensaje2).toString(16);\n flow.set(\"last_QR\", msg.payload)\n msg.payload = {};\n msg.id_topic = \"QR\"\n msg.payload.QR = mensaje2;\n flow.set(\"QR_ok_flag\", true);\n msg.payload.totem_id = flow.get(\"totem_id\");\n msg.payload.numero_vial = flow.get(\"numero_vial\");\n msg.payload.tipo = \"QR_BD\";\n flow.set(\"ID_enviado\", false)\n \n }\n \n}\nelse{ //mensaje viene del lector de RFID\n reverseid = msg.payload.match(/[a-fA-F0-9]{2}/g).reverse().join('')\n msg.reverseidH = reverseid\n msg.reverseidD = parseInt(reverseid, 16)\n if (flow.get(\"rfid_invertido\")) {\n mensaje2 = msg.reverseidD\n }\n else{\n mensaje2 = parseInt(msg.payload, 16);\n }\n \n if (!flow.get(\"peso_bajo_flag\")) {\n mensaje1 = \"Lectura del RFID:\";\n flow.set(\"last_RFID\", mensaje2);\n msg.payload = {}\n msg.id_topic = \"rfid\"\n msg.payload.RFID = mensaje2;\n flow.set(\"RFID_ok_flag\", true);\n flow.set(\"QR_ok_flag\", false);\n flow.set(\"esperando_id\", false) // No permitimos lectura de otro ID\n msg.payload.RFID_ok_flag = flow.get(\"RFID_ok_flag\");\n if(flow.get(\"semaforo\") == \"red\"){\n msg.payload.matricula = flow.get(\"matricula\");\n }\n \n msg.payload.tipo = \"user_id\";\n msg.payload.totem_id = flow.get(\"totem_id\");\n msg.payload.numero_vial = flow.get(\"numero_vial\");\n \n }\n else{\n mensaje1 = \"Lectura de RFID para BD\";\n msg.payload = {};\n flow.set(\"last_RFID\", mensaje2);\n msg.id_topic == \"rfid\"\n msg.payload.RFID = mensaje2;\n flow.set(\"RFID_ok_flag\", true);\n msg.payload.RFID_ok_flag = flow.get(\"RFID_ok_flag\");\n msg.payload.totem_id = flow.get(\"totem_id\");\n msg.payload.numero_vial = flow.get(\"numero_vial\");\n msg.payload.tipo = \"RFID_BD\";\n flow.set(\"ID_enviado\", false)\n \n \n }\n \n}\n\nmsg.level = flow.get(\"audio_level\")\nif(!flow.get(\"ID_enviado\")){\n node.send(msg)\n flow.set(\"ID_enviado\", true)\n}\nreturn ;",
+ "func": "\nlet mensaje1 = \"\";let mensaje2 = \"\";let reverseid = \"\";//cada mensaje es enviado y usado como una linea en html\nnode.status({fill:\"green\",shape:\"dot\",text:msg.payload});\nif (msg.id_topic == \"QR\") { //check si el mensaje es del lector de QR\n //if (flow.get(\"peso_estable_flag\") && flow.get(\"modo_automatico\")) {\n if (!flow.get(\"peso_bajo_flag\") ) {\n mensaje1 = \"Lectura del QR:\";\n mensaje2 = msg.payload;\n flow.set(\"esperando_id\", false) // No permitimos envio de otro ID en esta pesada\n flow.set(\"last_QR\", msg.payload)\n msg.payload = {};\n msg.id_topic = \"QR\"\n msg.payload.QR = mensaje2;\n msg.payload.QR_ok_flag = true;\n flow.set(\"QR_ok_flag\", true); // marcamos que hemos colocado un codigo QR en last_QR\n flow.set(\"RFID_ok_flag\", false);\n flow.set(\"ID_enviado\", false) // lo pongo temporalmente para hacer pruebas. Normalmente solo se permite enviar un QR\n }\n else {\n mensaje1 = \"Lectura de QR para BD\";\n mensaje2 = msg.payload;\n //msg.hex = Number(mensaje2).toString(16);\n flow.set(\"last_QR\", msg.payload)\n msg.payload = {};\n msg.id_topic = \"QR\"\n msg.payload.QR = mensaje2;\n flow.set(\"QR_ok_flag\", true);\n msg.payload.totem_id = flow.get(\"totem_id\");\n msg.payload.numero_vial = flow.get(\"numero_vial\");\n msg.payload.tipo = \"QR_BD\";\n flow.set(\"ID_enviado\", false)\n \n }\n \n}\nelse{ //mensaje viene del lector de RFID\n reverseid = msg.payload.match(/[a-fA-F0-9]{2}/g).reverse().join('')\n msg.reverseidH = reverseid\n msg.reverseidD = parseInt(reverseid, 16)\n msg.nonreverseidD = parseInt(msg.payload, 16);\n msg.nonreverseidH = msg.payload\n if (flow.get(\"rfid_invertido\")) {\n mensaje2 = msg.reverseidD\n }\n else{\n mensaje2 = parseInt(msg.payload, 16);\n }\n \n if (!flow.get(\"peso_bajo_flag\")) {\n mensaje1 = \"Lectura del RFID:\";\n flow.set(\"last_RFID\", mensaje2);\n msg.payload = {}\n msg.id_topic = \"rfid\"\n msg.payload.RFID = mensaje2;\n flow.set(\"RFID_ok_flag\", true);\n flow.set(\"QR_ok_flag\", false);\n flow.set(\"esperando_id\", false) // No permitimos lectura de otro ID\n msg.payload.RFID_ok_flag = flow.get(\"RFID_ok_flag\");\n if(flow.get(\"semaforo\") == \"red\"){\n msg.payload.matricula = flow.get(\"matricula\");\n }\n \n msg.payload.tipo = \"user_id\";\n msg.payload.totem_id = flow.get(\"totem_id\");\n msg.payload.numero_vial = flow.get(\"numero_vial\");\n \n }\n else{\n mensaje1 = \"Lectura de RFID para BD\";\n msg.payload = {};\n flow.set(\"last_RFID\", mensaje2);\n msg.id_topic == \"rfid\"\n msg.payload.RFID = mensaje2;\n flow.set(\"RFID_ok_flag\", true);\n msg.payload.RFID_ok_flag = flow.get(\"RFID_ok_flag\");\n msg.payload.totem_id = flow.get(\"totem_id\");\n msg.payload.numero_vial = flow.get(\"numero_vial\");\n msg.payload.tipo = \"RFID_BD\";\n flow.set(\"ID_enviado\", false)\n \n \n }\n \n}\n\nmsg.level = flow.get(\"audio_level\")\nif(!flow.get(\"ID_enviado\")){\n node.send(msg)\n flow.set(\"ID_enviado\", true)\n}\nreturn ;",
"outputs": 1,
"timeout": "",
"noerr": 0,
@@ -1304,7 +1306,7 @@
"z": "953e8740401d175c",
"g": "2af1fbc4.72dce4",
"name": "Tipo de Lector",
- "func": "if (flow.get(\"lector_activo\")){\n flow.set(\"lector_activo\", false)\n if (flow.get(\"tipo_de_lector\") == \"Kimaldi\"){\n var rx = msg.payload\n const regex = /\\[([^\\]]+)\\]/;\n const match = rx.match(regex);\n const contentInsideBrackets = match ? match[1] : null;\n var type = rx.substring(2,4)\n msg.payload = contentInsideBrackets\n msg.id_topic = type\n }\n else{\n var mensaje2 = msg.payload\n var index = mensaje2.indexOf(\"-\"); // Gets the first index where a - occours\n msg.id_topic = mensaje2.substr(0, index); // Gets the first part\n msg.payload = mensaje2.substr(index + 1); // Gets the text part\n\n }\n \n setTimeout(function () {\n flow.set(\"lector_activo\", true)\n }, 2000);\n if (flow.get(\"esperando_id\")){\n node.send(msg)\n }\n}\nreturn msg ;",
+ "func": "//node.warn(\"dato1 = \" + msg.payload)\nif (flow.get(\"lector_activo\")){\n flow.set(\"lector_activo\", false)\n if (flow.get(\"tipo_de_lector\") == \"Kimaldi\"){\n var rx = msg.payload\n const regex = /\\[([^\\]]+)\\]/;\n const match = rx.match(regex);\n const contentInsideBrackets = match ? match[1] : null;\n var type = rx.substring(2,4)\n msg.payload = contentInsideBrackets\n msg.id_topic = type\n //node.warn(\"dato2 = \" + msg.payload)\n }\n else{\n //node.warn(\"dato = \" + msg.payload)\n let dato = String(msg.payload).replace(/^[^A-Za-z0-9]*/, '').trim();\n let partes = dato.split('-');\n let tipo = partes[0];\n node.warn(\"tipo = \" + tipo)\n if (tipo !== \"QR\" && tipo !== \"rfid\") {\n node.warn(\"Tipo no reconocido antes del guion: \" + tipo);\n return null;\n }\n msg.id_topic = tipo; // QR o rfid\n msg.payload = partes.slice(1).join('-'); // todo lo que va después del primer guion\n\n /*\n var mensaje2 = msg.payload\n var index = mensaje2.indexOf(\"-\"); // Gets the first index where a - occours\n msg.id_topic = mensaje2.substr(0, index); // Gets the first part\n msg.payload = mensaje2.substr(index + 1); // Gets the text part\n */\n }\n \n setTimeout(function () {\n flow.set(\"lector_activo\", true)\n }, 2000);\n if (flow.get(\"esperando_id\")){\n node.send(msg)\n }\n}\nreturn ;",
"outputs": 1,
"timeout": "",
"noerr": 0,
@@ -2163,6 +2165,7 @@
"id": "0bc82cd2485c7679",
"type": "inject",
"z": "953e8740401d175c",
+ "d": true,
"g": "6443f177eec330e4",
"name": "distance ID1",
"props": [
@@ -3205,7 +3208,7 @@
"order": 1,
"width": "10",
"height": "4",
- "format": "\n
\n",
+ "format": "\n\n\n\n",
"storeOutMessages": true,
"fwdInMessages": true,
"resendOnRefresh": true,
@@ -3540,8 +3543,8 @@
"z": "953e8740401d175c",
"g": "646bdfb9988a1708",
"name": "Check JSON content",
- "func": "if ((msg.payload.totem_id == flow.get(\"totem_id\") || msg.payload.totem_id == \"*\") && msg.payload.numero_vial == flow.get(\"numero_vial\")) { // verifica que los datos son para este totem\n//if (msg.payload.numero_vial == flow.get(\"numero_vial\")) { // verifica que los datos son para este vial \n //guarda los elementos JSON recibidos del supervisor\n /*\n if (msg.payload.hasOwnProperty(\"numero_vial\")){\n flow.set(\"numero_vial\", msg.payload.numero_vial);\n }\n */\n if (msg.payload.hasOwnProperty(\"peso\")){\n flow.set(\"peso\", msg.payload.peso);\n \n }\n if (flow.get(\"supervisor\")) {\n if (msg.payload.hasOwnProperty(\"peso_estable\")) {\n flow.set(\"peso_estable\", msg.payload.peso_estable);\n }\n if (msg.payload.hasOwnProperty(\"peso_estable_flag\")) {\n flow.set(\"peso_estable_flag\", msg.payload.peso_estable_flag);\n }\n if (msg.payload.hasOwnProperty(\"fin_pesada_flag\")) {\n flow.set(\"fin_pesada_flag\", msg.payload.fin_pesada_flag);\n }\n if (msg.payload.hasOwnProperty(\"firma_cmd_flag\")) {\n flow.set(\"firma_cmd_flag\", msg.payload.firma_cmd_flag);\n flow.set(\"firma_flag\", true);\n }\n if (msg.payload.hasOwnProperty(\"remover_firma\")) {\n flow.set(\"remover_firma\", msg.payload.remover_firma);\n }\n if (msg.payload.hasOwnProperty(\"id_leido\")) {\n flow.set(\"id_leido\", msg.payload.id_leido);\n }\n if (msg.payload.hasOwnProperty(\"id_no_leido\")) {\n flow.set(\"id_no_leido\", msg.payload.id_no_leido);\n }\n if (msg.payload.hasOwnProperty(\"id_tarjeta\")) {\n flow.set(\"id_tarjeta\", msg.payload.id_tarjeta);\n }\n if (msg.payload.hasOwnProperty(\"matricula\")) {\n flow.set(\"matricula\", msg.payload.matricula);\n }\n \n }\n //****************************** RESPUESTA DE LA REVISION DE LA UBICACION INTERNA EN BD *******************************************\n if (msg.payload.hasOwnProperty(\"ubicacion_interna\")) {\n flow.set(\"ubicacion_recibida\", true)\n flow.set(\"ubicacion_interna\", msg.payload.ubicacion_interna) // si true -> se encontro ubicacion, si false -> No hay ubicacion en BD\n flow.set(\"dirigirse\", msg.payload.descripcion) // Sitio donde debe dirigirse\n\n }\n //****************************** RESPUESTA DE LA REVISION DE LA MATRICULA EN BD *******************************************\n if (msg.payload.hasOwnProperty(\"registrada\")) {\n //node.warn(\"por aqui paso\")\n flow.set(\"matricula_revisada\", true);\n flow.set(\"matricula_autorizada\", msg.payload.registrada)\n if(msg.payload.registrada){ // la matricula esta registrada y por lo tanto autorizada\n //node.warn(\"pma = \" + msg.payload.pma + \" tara = \" + msg.payload.tara)\n flow.set(\"pma\", msg.payload.pma)\n flow.set(\"tara\", msg.payload.tara)\n flow.set(\"entransito\", msg.payload.transito)\n flow.set(\"tipo_movimiento\", msg.payload.transito ? \"final\" : \"inicial\");// Si esta en transito = final en caso contrario = inicial\n if (msg.payload.aviso_identificacion){ // si la matricula existe una sola vez en Matriculas_Identificadores y la descripcion tiene coma, hay que sacar anuncio de identificacion\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\")); \n }\n if (!flow.get(\"entransito\")){\n \n }\n }\n }\n \n //******************************** RESPUESTA DE REVISION DEL CODIGO DE LA TARJETA RFID EN BD *****************************\n if (msg.payload.hasOwnProperty(\"rfid_revisado\")) {\n flow.set(\"RFID_revisado\", msg.payload.rfid_revisado);\n flow.set(\"RFID_verificado\", msg.payload.rfid_verificado);\n //*************Si la tarjeta existe recuperamos los datos asociados ***************************\n if(msg.payload.rfid_verificado){\n flow.set(\"cliente\", msg.payload.cliente)\n flow.set(\"residuo\", msg.payload.residuo)\n //Para el caso de RFID recibimos la matricula asociada a la tarjeta y no importa ahora la matricula leida de la camara ANPR\n //por eso a continuación comenzamos a buscar en BD si esta matricula tiene transito. (Ya sabemos que existe en BD y esta autorizada) \n flow.set(\"matricula\", msg.payload.matricula)// Toda tarjeta debe tener una matricula asociada en BD. Leemos y guardamos dicha matricula recibida\n if (flow.get(\"matricula\")) {\n //armamos los flags para que el nodo matricula 2 pueda solicitar a BD la verificacion de esta matricula, si esta en transito o si no lo esta\n flow.set(\"matricula_leida_flag\", true)\n flow.set(\"matricula_formato_flag\", true)\n flow.set(\"matricula_ok_flag\", true)\n flow.set(\"matricula_revisada\", false)\n flow.set(\"matriculacheck_solicitada\", false)\n }\n \n }\n }\n\n //******************************** RESPUESTA DE REVISION DEL CODIGO QR EN BD *****************************\n if (msg.payload.hasOwnProperty(\"qr_revisado\")) {\n flow.set(\"QR_revisado\", msg.payload.qr_revisado);\n flow.set(\"QR_verificado\", msg.payload.qr_verificado);\n flow.set(\"ID_obligatorio_tmp\", false) // en caso que ID_obligatorio = false, pero usuario presenta un QR entonces hay que verificar que esta en BD y puede pasar a ser obligatorio para verificar que esta en BD\n //*************Si el codigo QR existe recuperamos los datos asociados ***************************\n if(msg.payload.qr_verificado){\n flow.set(\"cliente\", msg.payload.cliente)\n flow.set(\"residuo\", msg.payload.residuo)\n \n /* Este codigo era para verificar la matricula pero ahora el QR no esta asociado a matricula\n if (flow.get(\"matricula\") == msg.payload.matricula){ // si la matricula coincide con la leida damos por finalizado el chequeo de matricula\n flow.set(\"matricula_formato_flag\", true) // indica matricula esta en formato\n flow.set(\"matricula_ok_flag\", true)\n flow.set(\"matricula_revisada\", true) //se ha revisado la existencia de la matricula en BD\n flow.set(\"matricula_autorizada\", true) // matricula autorizada\n \n }\n else{\n // Si la matricula es diferente tomamos como matricula la recibida de la BD\n // Ahora tenemos que confirmar si esa matricula esta en transito para saber el tipo de movimiento que vamos agestionar en esta pesada\n //por lo tanto ponemos los flags para que pueda volver a buscar la matricula en BD.\n flow.set(\"matricula_revisada\", false) // Se pone en false para volver a revisar la matricula correcta\n //node.warn(\"matricula leida = \" + flow.get(\"matricula\") + \" ; matricula del qr = \" + msg.payload.matricula)\n flow.set(\"matricula_autorizada\", false) // matricula autorizada\n flow.set(\"matriculacheck_solicitada\", false) // para poder volver a consultar una matricula\n flow.set(\"matricula_formato_flag\", true) // indica matricula esta en formato\n flow.set(\"matricula_ok_flag\", true) // aseguramos que la matricula puede ser buscada en la base de datos en el nodo matricula\n flow.set(\"matricula_leida_flag\", true) // aseguramos que la matricula puede ser buscada en la base de datos en el nodo matricula\n flow.set(\"matricula\", msg.payload.matricula) // guardamos la matricula correcta\n }\n */\n }\n else{\n flow.set(\"ID_obligatorio_tmp\", true)// en caso que ID_obligatorio = false, pero usuario presenta un QR entonces hay que verificar que esta en BD asi que temporalmente el QR pasa a obligatorio\n }\n }\n\n //--------------------- Recepcion de la lista de materiales para el menu -------------------------\n\n if (msg.payload.hasOwnProperty(\"lista\") && msg.payload.hasOwnProperty(\"encabezado_lista\") && flow.get(\"menu_activo\")) {\n flow.set(\"lista_flag\", true)\n flow.set(\"encabezado_lista\", msg.payload.encabezado_lista)\n flow.set(\"lista_array\", msg.payload.lista)\n flow.set(\"menu_inicio\", msg.payload.menu_inicio)\n\n flow.set(\"window_men_m3\", \"\"); // eliminamos mensaje de \"Acerque QR o Tarjeta\" de la pantalla en caso que este puesto\n }\n else {\n \n flow.set(\"lista_flag\", false)\n \n }\n //---------------------- FIN de Recepcion de la lista de materiales para el menu ----------------------\n\n //---------------------- BOTONES EN LA PANTALLA -------------------------------------------------------\n if (msg.payload.hasOwnProperty(\"button\")) {\n flow.set(\"button\", msg.payload.button);\n }\n if (msg.payload.hasOwnProperty(\"button1\")) {\n flow.set(\"button1\", msg.payload.button1);\n }\n if (msg.payload.hasOwnProperty(\"button2\")) {\n flow.set(\"button2\", msg.payload.button2);\n }\n //************** APAGADO / ENCENDIDO DE LA PANTALLA ******************************** \n if (msg.payload.hasOwnProperty(\"screenOn_flag\")){\n flow.set(\"screenOn_flag\", msg.payload.screenOn_flag);\n if(msg.payload.screenOn_flag){\n \n node.send([null, {\"payload\":\"sudo echo 0 > /sys/class/backlight/rpi_backlight/bl_power\"}]);\n //node.send([null, {\"payload\":\"xset -display :0 dpms force on\"}]);\n }\n else{\n node.send([null, {\"payload\":\"sudo echo 1 > /sys/class/backlight/rpi_backlight/bl_power\"}]);\n //node.send([null, {\"payload\":\"xset -display :0 dpms force off\"}]);\n }\n }\n // **********************************************************\n if (msg.payload.hasOwnProperty(\"modo_totem\")){ // chequea si cambiamos el modo de trabajo del totem\n flow.set(\"modo_totem\", msg.payload.modo_totem);\n }\n if (msg.payload.hasOwnProperty(\"uso_detector_ok\")){ \n flow.set(\"uso_detector_ok\", msg.payload.uso_detector_ok);\n }\n \n \n if (msg.payload.hasOwnProperty(\"badplate\")){ // chequea si tenemos que pedir corrección de matricula\n flow.set(\"badplate\", msg.payload.badplate);\n }\n \n //------------------------ Hacer display de un BOTON de VALIDACION a la salida ------------------------\n/* \n if (msg.payload.hasOwnProperty(\"botonsalida\")){ // chequea si tenemos que pedir boton de salida en pantalla\n flow.set(\"botonsalida\", msg.payload.botonsalida);\n if (msg.payload.hasOwnProperty(\"botonsalida_txt\")){\n flow.set(\"botonsalida_txt\", msg.payload.botonsalida_txt);\n }\n if (msg.payload.hasOwnProperty(\"botonsalida_color\")){\n flow.set(\"botonsalida_color\", msg.payload.botonsalida_color);\n }\n if (msg.payload.hasOwnProperty(\"botonsalida_txt_color\")){\n flow.set(\"botonsalida_txt_color\", msg.payload.botonsalida_txt_color);\n }\n if (msg.payload.hasOwnProperty(\"botonsalida_mensaje1\")){\n flow.set(\"botonsalida_mensaje1\", msg.payload.botonsalida_mensaje1);\n }\n }\n*/\n //*********************************** RESET REMOTO *****************************************************\n if (msg.payload.hasOwnProperty(\"reboot_flag\")){ // comando para resetear el dispositivo desde el supervisor\n \n if(msg.payload.reboot_flag){ \n node.send([null, {payload:\"sudo shutdown -r now\"}]);\n }\n \n }\n //===================== deteccion de comando para iniciar la configuración ===========================================================\n if (msg.payload.hasOwnProperty(\"init_config\")) {\n if (msg.payload.init_config == true){\n node.send([null, null, {payload: 1}])\n }\n }\n \n //===================== deteccion de comando para gestionar semaforo ===========================================================\n if (msg.payload.hasOwnProperty(\"semaforoabierto\")) {\n if (msg.payload.semaforoabierto == true) {\n flow.set(\"semaforo\", \"green\")\n flow.set(\"semaforoabierto\", true) \n }\n else{\n flow.set(\"semaforo\", \"red\")\n flow.set(\"semaforoabierto\", false) \n }\n }\n \n //===================== deteccion de comando para abrir barrera ===========================================================\n if (msg.payload.hasOwnProperty(\"abrirbarrera\")) {\n if (msg.payload.abrirbarrera == true) {\n node.send([ null, null, null, { payload: 0 }])\n setTimeout(function () {\n node.send([null, null, null, { payload: 1 }])\n }, flow.get(\"relay2_pulse\"));\n }\n \n }\n //=====================================================================================================================================\n \n \n \n \n \nmsg = {payload: 1};\nreturn msg\n}\nelse{\n\n return // en caso de no ser el mensaje para este dispositivo no enviamos mensaje al proximo nodo, de esa manera no habra ninguna respuesta de este dispositivo\n}\n\n",
- "outputs": 4,
+ "func": "if ((msg.payload.totem_id == flow.get(\"totem_id\") || msg.payload.totem_id == \"*\") && msg.payload.numero_vial == flow.get(\"numero_vial\")) { // verifica que los datos son para este totem\n//if (msg.payload.numero_vial == flow.get(\"numero_vial\")) { // verifica que los datos son para este vial \n //guarda los elementos JSON recibidos del supervisor\n /*\n if (msg.payload.hasOwnProperty(\"numero_vial\")){\n flow.set(\"numero_vial\", msg.payload.numero_vial);\n }\n */\n if (msg.payload.hasOwnProperty(\"peso\")){\n flow.set(\"peso\", msg.payload.peso);\n \n }\n if (flow.get(\"supervisor\")) {\n if (msg.payload.hasOwnProperty(\"peso_estable\")) {\n flow.set(\"peso_estable\", msg.payload.peso_estable);\n }\n if (msg.payload.hasOwnProperty(\"peso_estable_flag\")) {\n flow.set(\"peso_estable_flag\", msg.payload.peso_estable_flag);\n }\n if (msg.payload.hasOwnProperty(\"fin_pesada_flag\")) {\n flow.set(\"fin_pesada_flag\", msg.payload.fin_pesada_flag);\n }\n if (msg.payload.hasOwnProperty(\"firma_cmd_flag\")) {\n flow.set(\"firma_cmd_flag\", msg.payload.firma_cmd_flag);\n flow.set(\"firma_flag\", true);\n }\n if (msg.payload.hasOwnProperty(\"remover_firma\")) {\n flow.set(\"remover_firma\", msg.payload.remover_firma);\n }\n if (msg.payload.hasOwnProperty(\"id_leido\")) {\n flow.set(\"id_leido\", msg.payload.id_leido);\n }\n if (msg.payload.hasOwnProperty(\"id_no_leido\")) {\n flow.set(\"id_no_leido\", msg.payload.id_no_leido);\n }\n if (msg.payload.hasOwnProperty(\"id_tarjeta\")) {\n flow.set(\"id_tarjeta\", msg.payload.id_tarjeta);\n }\n if (msg.payload.hasOwnProperty(\"matricula\")) {\n flow.set(\"matricula\", msg.payload.matricula);\n }\n \n }\n //****************************** RESPUESTA DE LA REVISION DE LA UBICACION INTERNA EN BD *******************************************\n if (msg.payload.hasOwnProperty(\"ubicacion_interna\")) {\n flow.set(\"ubicacion_recibida\", true)\n flow.set(\"ubicacion_interna\", msg.payload.ubicacion_interna) // si true -> se encontro ubicacion, si false -> No hay ubicacion en BD\n flow.set(\"dirigirse\", msg.payload.descripcion) // Sitio donde debe dirigirse\n\n }\n //****************************** RESPUESTA DE LA REVISION DE LA MATRICULA EN BD *******************************************\n if (msg.payload.hasOwnProperty(\"registrada\")) {\n //node.warn(\"por aqui paso\")\n flow.set(\"matricula_revisada\", true);\n flow.set(\"matricula_autorizada\", msg.payload.registrada)\n if(msg.payload.registrada){ // la matricula esta registrada y por lo tanto autorizada\n //node.warn(\"pma = \" + msg.payload.pma + \" tara = \" + msg.payload.tara)\n flow.set(\"pma\", msg.payload.pma)\n flow.set(\"tara\", msg.payload.tara)\n flow.set(\"entransito\", msg.payload.transito)\n flow.set(\"tipo_movimiento\", msg.payload.transito ? \"final\" : \"inicial\");// Si esta en transito = final en caso contrario = inicial\n if (msg.payload.aviso_identificacion){ // si la matricula existe una sola vez en Matriculas_Identificadores y la descripcion tiene coma, hay que sacar anuncio de identificacion\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\")); \n }\n if (!flow.get(\"entransito\")){\n \n }\n }\n }\n \n //******************************** RESPUESTA DE REVISION DEL CODIGO DE LA TARJETA RFID EN BD *****************************\n if (msg.payload.hasOwnProperty(\"rfid_revisado\")) {\n flow.set(\"RFID_revisado\", msg.payload.rfid_revisado);\n flow.set(\"RFID_verificado\", msg.payload.rfid_verificado);\n //*************Si la tarjeta existe recuperamos los datos asociados ***************************\n if(msg.payload.rfid_verificado){\n flow.set(\"cliente\", msg.payload.cliente)\n flow.set(\"residuo\", msg.payload.residuo)\n //Para el caso de RFID recibimos la matricula asociada a la tarjeta y no importa ahora la matricula leida de la camara ANPR\n //por eso a continuación comenzamos a buscar en BD si esta matricula tiene transito. (Ya sabemos que existe en BD y esta autorizada) \n flow.set(\"matricula\", msg.payload.matricula)// Toda tarjeta debe tener una matricula asociada en BD. Leemos y guardamos dicha matricula recibida\n if (flow.get(\"matricula\")) {\n //armamos los flags para que el nodo matricula 2 pueda solicitar a BD la verificacion de esta matricula, si esta en transito o si no lo esta\n flow.set(\"matricula_leida_flag\", true)\n flow.set(\"matricula_formato_flag\", true)\n flow.set(\"matricula_ok_flag\", true)\n flow.set(\"matricula_revisada\", false)\n flow.set(\"matriculacheck_solicitada\", false)\n }\n \n }\n }\n\n //******************************** RESPUESTA DE REVISION DEL CODIGO QR EN BD *****************************\n if (msg.payload.hasOwnProperty(\"qr_revisado\")) {\n flow.set(\"QR_revisado\", msg.payload.qr_revisado);\n flow.set(\"QR_verificado\", msg.payload.qr_verificado);\n flow.set(\"ID_obligatorio_tmp\", false) // en caso que ID_obligatorio = false, pero usuario presenta un QR entonces hay que verificar que esta en BD y puede pasar a ser obligatorio para verificar que esta en BD\n //*************Si el codigo QR existe recuperamos los datos asociados ***************************\n if(msg.payload.qr_verificado){\n flow.set(\"cliente\", msg.payload.cliente)\n flow.set(\"residuo\", msg.payload.residuo)\n \n /* Este codigo era para verificar la matricula pero ahora el QR no esta asociado a matricula\n if (flow.get(\"matricula\") == msg.payload.matricula){ // si la matricula coincide con la leida damos por finalizado el chequeo de matricula\n flow.set(\"matricula_formato_flag\", true) // indica matricula esta en formato\n flow.set(\"matricula_ok_flag\", true)\n flow.set(\"matricula_revisada\", true) //se ha revisado la existencia de la matricula en BD\n flow.set(\"matricula_autorizada\", true) // matricula autorizada\n \n }\n else{\n // Si la matricula es diferente tomamos como matricula la recibida de la BD\n // Ahora tenemos que confirmar si esa matricula esta en transito para saber el tipo de movimiento que vamos agestionar en esta pesada\n //por lo tanto ponemos los flags para que pueda volver a buscar la matricula en BD.\n flow.set(\"matricula_revisada\", false) // Se pone en false para volver a revisar la matricula correcta\n //node.warn(\"matricula leida = \" + flow.get(\"matricula\") + \" ; matricula del qr = \" + msg.payload.matricula)\n flow.set(\"matricula_autorizada\", false) // matricula autorizada\n flow.set(\"matriculacheck_solicitada\", false) // para poder volver a consultar una matricula\n flow.set(\"matricula_formato_flag\", true) // indica matricula esta en formato\n flow.set(\"matricula_ok_flag\", true) // aseguramos que la matricula puede ser buscada en la base de datos en el nodo matricula\n flow.set(\"matricula_leida_flag\", true) // aseguramos que la matricula puede ser buscada en la base de datos en el nodo matricula\n flow.set(\"matricula\", msg.payload.matricula) // guardamos la matricula correcta\n }\n */\n }\n else{\n flow.set(\"ID_obligatorio_tmp\", true)// en caso que ID_obligatorio = false, pero usuario presenta un QR entonces hay que verificar que esta en BD asi que temporalmente el QR pasa a obligatorio\n }\n }\n\n //--------------------- Recepcion de la lista de materiales para el menu -------------------------\n\n if (msg.payload.hasOwnProperty(\"lista\") && msg.payload.hasOwnProperty(\"encabezado_lista\") && flow.get(\"menu_activo\")) {\n flow.set(\"lista_flag\", true)\n flow.set(\"encabezado_lista\", msg.payload.encabezado_lista)\n flow.set(\"lista_array\", msg.payload.lista)\n flow.set(\"menu_inicio\", msg.payload.menu_inicio)\n\n flow.set(\"window_men_m3\", \"\"); // eliminamos mensaje de \"Acerque QR o Tarjeta\" de la pantalla en caso que este puesto\n }\n else {\n \n flow.set(\"lista_flag\", false)\n \n }\n //---------------------- FIN de Recepcion de la lista de materiales para el menu ----------------------\n\n //---------------------- BOTONES EN LA PANTALLA -------------------------------------------------------\n if (msg.payload.hasOwnProperty(\"button\")) {\n flow.set(\"button\", msg.payload.button);\n }\n if (msg.payload.hasOwnProperty(\"button1\")) {\n flow.set(\"button1\", msg.payload.button1);\n }\n if (msg.payload.hasOwnProperty(\"button2\")) {\n flow.set(\"button2\", msg.payload.button2);\n }\n //************** APAGADO / ENCENDIDO DE LA PANTALLA ******************************** \n if (msg.payload.hasOwnProperty(\"screenOn_flag\")){\n flow.set(\"screenOn_flag\", msg.payload.screenOn_flag);\n if(msg.payload.screenOn_flag){\n \n node.send([null, {\"payload\":\"sudo echo 0 > /sys/class/backlight/rpi_backlight/bl_power\"}]);\n //node.send([null, {\"payload\":\"xset -display :0 dpms force on\"}]);\n }\n else{\n node.send([null, {\"payload\":\"sudo echo 1 > /sys/class/backlight/rpi_backlight/bl_power\"}]);\n //node.send([null, {\"payload\":\"xset -display :0 dpms force off\"}]);\n }\n }\n // **********************************************************\n if (msg.payload.hasOwnProperty(\"modo_totem\")){ // chequea si cambiamos el modo de trabajo del totem\n flow.set(\"modo_totem\", msg.payload.modo_totem);\n }\n if (msg.payload.hasOwnProperty(\"uso_detector_ok\")){ \n flow.set(\"uso_detector_ok\", msg.payload.uso_detector_ok);\n }\n \n \n if (msg.payload.hasOwnProperty(\"badplate\")){ // chequea si tenemos que pedir corrección de matricula\n flow.set(\"badplate\", msg.payload.badplate);\n }\n \n //------------------------ Hacer display de un BOTON de VALIDACION a la salida ------------------------\n/* \n if (msg.payload.hasOwnProperty(\"botonsalida\")){ // chequea si tenemos que pedir boton de salida en pantalla\n flow.set(\"botonsalida\", msg.payload.botonsalida);\n if (msg.payload.hasOwnProperty(\"botonsalida_txt\")){\n flow.set(\"botonsalida_txt\", msg.payload.botonsalida_txt);\n }\n if (msg.payload.hasOwnProperty(\"botonsalida_color\")){\n flow.set(\"botonsalida_color\", msg.payload.botonsalida_color);\n }\n if (msg.payload.hasOwnProperty(\"botonsalida_txt_color\")){\n flow.set(\"botonsalida_txt_color\", msg.payload.botonsalida_txt_color);\n }\n if (msg.payload.hasOwnProperty(\"botonsalida_mensaje1\")){\n flow.set(\"botonsalida_mensaje1\", msg.payload.botonsalida_mensaje1);\n }\n }\n*/\n //*********************************** RESET REMOTO *****************************************************\n if (msg.payload.hasOwnProperty(\"reboot_flag\")){ // comando para resetear el dispositivo desde el supervisor\n \n if(msg.payload.reboot_flag){ \n node.send([null, {payload:\"sudo shutdown -r now\"}]);\n }\n \n }\n //===================== deteccion de comando para iniciar la configuración ===========================================================\n if (msg.payload.hasOwnProperty(\"init_config\")) {\n if (msg.payload.init_config == true){\n node.send([null, null, {payload: 1}])\n }\n }\n \n //===================== deteccion de comando para gestionar semaforo ===========================================================\n if (msg.payload.hasOwnProperty(\"semaforoabierto\")) {\n if (msg.payload.semaforoabierto == true) {\n if (flow.get(\"semaforo\") == \"red\") {\n setTimeout(function () {// se elimina cualquier notificacion en el display\n node.send([null, null, null, null, { payload: \"\" }])\n }, 1500)\n }\n flow.set(\"semaforo\", \"green\")\n flow.set(\"semaforoabierto\", true) \n }\n else{\n flow.set(\"semaforo\", \"red\")\n flow.set(\"semaforoabierto\", false) \n }\n }\n \n //===================== deteccion de comando para abrir barrera ===========================================================\n if (msg.payload.hasOwnProperty(\"abrirbarrera\")) {\n if (msg.payload.abrirbarrera == true) {\n node.send([ null, null, null, { payload: 0 }])\n setTimeout(function () {\n node.send([null, null, null, { payload: 1 }])\n }, flow.get(\"relay2_pulse\"));\n }\n \n }\n //=====================================================================================================================================\n \n \n \n \n \nmsg = {payload: 1};\nreturn msg\n}\nelse{\n\n return // en caso de no ser el mensaje para este dispositivo no enviamos mensaje al proximo nodo, de esa manera no habra ninguna respuesta de este dispositivo\n}\n\n",
+ "outputs": 5,
"timeout": "",
"noerr": 0,
"initialize": "",
@@ -3562,6 +3565,9 @@
],
[
"cf7b0c00631682b2"
+ ],
+ [
+ "b22cc0f171be84d5"
]
]
},
@@ -3712,7 +3718,7 @@
"da672c95637f91bd"
],
"x": 735,
- "y": 1340,
+ "y": 1320,
"wires": []
},
{
@@ -3931,7 +3937,7 @@
"cc25836d7a7314ad"
],
"x": 735,
- "y": 1300,
+ "y": 1280,
"wires": []
},
{
@@ -3942,7 +3948,7 @@
"name": "Codiciones Operacion",
"info": "Este sistema puede funcionar con un Totem o con dos Totems (bascula bidireccional).\nAl entrar el vehiculo en la bascula, este es detectado por el evento bascula, al superar el peso minimo,\ny/o por el detector de presencia de vehiculos situado en el Totem (remoto) por donde entra el vehiculo. Es de notar que \nsi hemos configurado la modalidad con dos Totem, el evento bascula no inicia el request del snapshot, en ese caso lo hace el detector.\nEstos eventos hacen que el Totem correspondiente genere un request de snapshot a la camara para leer la matricula del vehiculo entrante. \nSimultaneamente el evento bascula (peso > pmin) genera un UUID para abrir un movimiento en la bascula y lo rellena\ncon los parametros hasta ese momento conocidos como hora de entrada, nombre del totem, modo_Totem, UUID...\nAl llegar el resultado del snapshot, el RPi revisa si la matricula corresponde a una matricula bajo el formato correcto\nen cuyo caso se da por valida. En caso que NO sea valida, se revisa si el Totem ha sido habilitado para editar matriculas, si ese \nfuera el caso se saca en pantalla el editor de matriculas. En caso contrario se saca un mensaje en pantalla indicando que tiene que \ndar retroceso y volver a entrar. En caso que el conductor presente una tarjeta rfid autorizada se puede continuar el proceso\nsin matricula.\nUna vez que la matricula esta dentro del formato, revisamos si el Totem ha sido habilitado para mostrar el boton en pantalla \nde Validacion (o de salida), de manera que el conductor una vez frente al Totem pueda dar por concluida la pesada. \nEn este punto el Totem espera o un QR o un RFID o un Detector de vehiculo o un Boton de Validacion para poder seguir. Una vez detectado algunos de Estos\ncondiciones, el peso en ese momento en la bascula se recoge como peso estable. Para dar por finalizada tenemos que revisar si hay algunos\nparametros configurados como obligatorio por ejemplo es obligatorio presentar el QR y/o clicar el boton de Validacion, de manera que hasta \nque no se cumplan los obligatorios junto con las condiciones anteriores no se puede continuar. Una vez recibido el ultimo parametro\nobligatorio damos por finalizada la pesada y se pone el semaforo en Verde para que el vehiculo abandone la bascula.\nAl momento de poner el semaforo en verde se envia el registro al supervisor para que lo registre en BD, incluyendo ahora los datos recogidos como matricula, \nhora de salida, firma, etc. \n\n",
"x": 580,
- "y": 1440,
+ "y": 1480,
"wires": []
},
{
@@ -3992,7 +3998,7 @@
"z": "953e8740401d175c",
"g": "646bdfb9988a1708",
"name": "Analisis del modo \\n de Operacion",
- "func": "//***************************** Selecciona Modo de Operacion **************************************************\nif (!flow.get(\"supervisor\")) {\n if (flow.get(\"peso_estable_flag\")) { //El peso estable se obtiene cuando el vehiculo esta frente al Totem (QR / RFID o sino Detector Local ON o bien pulsar un boton que aparezca en pantalla)\n if (flow.get(\"tipo_movimiento\") == \"final\") {\n flow.set(\"firma_ok_flag\", true) // indicamos que la firma esta hecha, esta no hace falta para la salida\n }\n let ID_verificado = flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\")\n if (flow.get(\"firma_obligatoria\") && !flow.get(\"firma_flag\") &&!flow.get(\"firma_ok_flag\") && !flow.get(\"supervisor\") && (!flow.get(\"menu_activo\") || (flow.get(\"menu_activo\") && (flow.get(\"menu_seleccionado_flag\") || ID_verificado)))) { //chequea si tenemos que solicitar firma\n /*\n El if anterior se cumple si:\n - firma_obligatoria es true y firma_ok_flag es false y firma_flag es false y si supervisor es false y ademas si menu_activo es false o bien menu_activo es true y menu_seleccionado_flag es true (osea se ha seleccionado el menu)\n Con esto aseguramos que la firma la sacamos una vez que el usuario ha hecho la seleccion del menu (en caso de existir) y no antes.\n */\n // hemos cambiado \"firma_habilitada\" por \"firma_obligatoria\" porque finalmente con un solo parametro es suficiente\n // finalmente hacemos el llamado a la firma solamente durante el movimiento inicial\n if (flow.get(\"tipo_movimiento\") == \"inicial\") {\n flow.set(\"firma_flag\", true) // solicitud de firma\n setTimeout(() => {\n //node.warn(\"solicitando firma\")\n node.send([{ \"payload\": { \"tab\": \"Firma\" } }, { payload: \"firma\" }, null, null, {payload:\"\"}])\n }, 2000);\n }\n /*\n else if (flow.get(\"tipo_movimiento\") == \"final\") {\n flow.set(\"firma_ok_flag\", true) // indicamos que la firma esta hecha, esta no hace falta para la salida\n }\n */\n }\n\n //=============================================================================================================================================\n //====================================================== MODO DE OPERACION ====================================================================\n //=============================================================================================================================================\n let modo = flow.get(\"modo_totem\")\n // -----------------------------------------------------COMUN PARA TODOS LOS MODOS ------------------------------------------------------------\n let detector_flag = (flow.get(\"distance_flag_SET\") && (flow.get(\"sentido\") == \"entrada\") && flow.get(\"sensor_distancia_local\")) || false;\n let boton_flag = flow.get(\"salida_valida_flag\") || false;\n let matricula_flag = flow.get(\"matricula_ok_flag\") || false;\n let register_flag = flow.get(\"movimiento_registrado_flag\"); //si true, indica que el movimiento ha sido enviado\n let firma_flag = flow.get(\"firma_ok_flag\")\n let menu_activo = flow.get(\"menu_activo\") // el menu activo se configura en el archivo de configuracion\n let menu_selected = flow.get(\"menu_seleccionado_flag\") // este flag se activa cuando el conductor selecciona el residuo del menu y lo envia (en caso de menu_activo = true)\n //let ID_verificado = flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\")\n \n // Reglas de obligatoriedad configurables en archivo de configuracion\n let ID_presentado = flow.get(\"ID_presentado\")\n let ID_obligatorio = flow.get(\"ID_obligatorio\") || (flow.get(\"ID_obligatorio_tmp\") || false)\n let detector_obligatorio = flow.get(\"detector_obligatorio\") || false; // este es el detector de presencia de vehiculo frente al totem\n let boton_obligatorio = flow.get(\"boton_obligatorio\") || false; // Este corresponde al boton de la pantalla de Validacion en caso de estar habilitado\n let firma_obligatoria = flow.get(\"firma_obligatoria\") || false;\n //let matricula_obligatoria = flow.get(\"matricula_obligatoria\") || false\n let matricula_obligatoria = flow.get(\"matricula_obligatoria\") || true // siempre es obligatoria. Es el punto central para gestionar elos movimientos en BD\n let imagen_contexto_ok = flow.get(\"camara_contexto_rx\") || !flow.get(\"camara_contexto\") || flow.get(\"camara_contexto_estado\") === \"ok\" || flow.get(\"camara_contexto_estado\") === \"fail\"\n //Se evalua flow.get(\"camara_contexto_estado\")-> si es \"ok\" significa que se recibio la imagen. Si es \"fail\" significa que se agotaron los dos tiempos de espera de los dos intentos\n //los valores posibles de \"camara_contexto_estado\" son \"idle\", waiting1\", \"waiting2\", \"ok\", \"fail\".\n //idle = no se ha iniciado ninguna solicitud de imagen de contexto. \"waiting1\" = Se inicio la primera solicitud de imagen de contexto. \"waiting2\" = Se inicio la segunda solicitud\n //\"ok\" = imagen de contexto recibida. \"fail\" = se enviaron dos intentos y se esperaron los dos tiempos previstos pero no se recibio imagen de contexto.\n \n // Evaluación de cumplimiento de Flags actuales y Flags obligatorios\n //let ID_ok = !ID_obligatorio || ID_verificado\n let ID_ok = (!ID_obligatorio && !ID_presentado) || ID_verificado;\n let detector_ok = !detector_obligatorio || detector_flag;\n if (flow.get(\"tipo_movimiento\") == \"inicial\") { boton_flag = true } // en movimiento inicial no tiene sentido el boton\n let boton_ok = !boton_obligatorio || boton_flag;\n let firma_ok = !firma_obligatoria || firma_flag;\n //**************************************************** Excepcion para Trajeta RFID **************************************************\n //*********************************** No es necesario tener la matricula del Vehiculo ni poner boton de salida *******************************\n if (flow.get(\"RFID_verificado\")) { \n matricula_flag = true \n boton_ok = true\n }\n \n let matricula_ok = !matricula_obligatoria || matricula_flag\n let seleccion_ok\n if(flow.get(\"tipo_movimiento\") == \"inicial\"){\n seleccion_ok = !menu_activo || menu_selected || ID_verificado // Si el menu esta activo, el ID_verificado permite saltar la seleccion del residuo\n\n if (ID_verificado && menu_activo) {\n // ==================== eliminamos mensaje y boton del menu debido a que tenemos ID del residuo (Tarjeta o QR) ================================\n flow.set(\"startmenu_flag\", false) // para poder eliminar el boton y borrar el mensaje em \"window_men_m1\"\n flow.set(\"window_men_m1\", \"\") // colocamos mensaje vacio en el espacio del mensaje 1 donde decia Haga click Abajo\n }\n }\n else if(flow.get(\"tipo_movimiento\") == \"final\"){\n //seleccion_ok = !menu_activo || menu_selected || ID_verificado || boton_flag\n seleccion_ok = true\n ID_ok = !flow.get(\"salida_ID_obligatorio\") || ID_verificado\n }\n \n //************************ SOLICITUD DE UBICACION INTERNA Y NOTIFICACION AL CONDUCTOR ***************************************/\n // ****** OJO AQUI ***** Mientras \"ubicacion_recibida\" no cambie a true, es decir hasta que la BD no conteste el request, esto seguira enviando el request nuevamente\n // Es decir que si se pierde comunicacion esto enviara siempre que pueda entrar en este codigo.\n let requerimientos_ok = ID_ok && boton_ok && firma_ok && matricula_ok && seleccion_ok && flow.get(\"mostrar_ubicacion\") && !flow.get(\"mostrar_ubicacion_ok\") && (flow.get(\"tipo_movimiento\") === \"inicial\")\n //node.warn(\"requerimientos_ok = \" + requerimientos_ok)\n //node.warn(\"seleccion = \" + seleccion_ok + \" ; matricula = \" + matricula_ok + \" ; boton = \" + boton_ok + \" ; firma = \" + firma_ok + \" ; mostrar_ubicacion = \" + flow.get(\"mostrar_ubicacion\") + \" ; movimiento = \" + (flow.get(\"tipo_movimiento\") === \"inicial\"))\n \n if (requerimientos_ok) {\n if (!flow.get(\"ubicacion_recibida\")) { // Si aun no hemos recibido el aviso de la ubicacion, la solicitamos\n let id_residuo\n if (flow.get(\"last_QR\") != \"-\") { id_residuo = flow.get(\"last_QR\") }\n else if (flow.get(\"last_RFID\") != \"-\") { id_residuo = flow.get(\"last_RFID\") }\n else if (flow.get(\"id_seleccionado\") != \"no recibido\") { id_residuo = flow.get(\"id_seleccionado\") }\n msg.payload = { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), device: \"supervisor\", accion: \"check_ubicacion\", id_residuo: id_residuo }\n node.send([null, null, msg, null])\n //node.warn(\"enviado solicitud de ubicacion\")\n }\n\n //if (flow.get(\"ubicacion_recibida\")) { // Con flow.get(\"mostrar_ubicacion_ok\") aseguramos que solo sacamos la notificacion una vez\n else {\n //Aqui sacamos notificacion al conductor\n\n flow.set(\"mostrar_ubicacion_ok\", true) //marcamos que ya hemos recibido respuesta del ubicacion\n if (!flow.get(\"ubicacion_interna\")) { // si no se ha recibido el flag de ubicacion interna en true es que no existe ubicacion especifica para ese residuo\n flow.set(\"dirigirse\", \"NO HAY UBICACION DEFINIDA\")\n }\n //node.warn(\"DIRIGIRSE A : \" + flow.get(\"dirigirse\"))// aqui enviamos la notificacion al conductor\n // esperamos un tiempo para que este mensaje quede de ultimo y no sea sustituido por la notificacion del contenido y procedencia\n setTimeout(() => { \n node.send([null, null, null, null, {\n payload:\n \"\" +\n \"
ATENCION
\" +\n \"
\" + flow.get(\"dirigirse\") + \"
\" +\n \"
\"\n }])\n }, 2000);\n \n\n }\n }\n if (flow.get(\"tipo_movimiento\") === \"final\") { flow.set(\"mostrar_ubicacion_ok\", true) }\n let ubicacion_ok = !flow.get(\"mostrar_ubicacion\") || flow.get(\"mostrar_ubicacion_ok\")\n //******************************************************************************************************************************************************** */\n \n \n let todos_obligatorios_ok;\n\n switch (modo) {\n\n case \"A\": //************************************** MODO A [ Matricula - QR / RFID - sensor local - boton de salida ]***************************************************** */\n // aqui revisamos si se recibio matricula y un evento que indique que el conductor esta frente al totem\n // puede ser alguno de los siguientes eslementos:\n // - un QR o una tarjeta RFID\n // - el boton de activacion de salida que ponemos en pantalla en caso de estar habilitado para ello en el archivo de configuración\n // - el sensor local de presencia de vehiculo\n // - la seleccion del menu\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento que se active el semaforo en verde\n // Adidionalmente se revisa si existe algun parametro OBLIGATORIO (presente en la configuracion ) que se deba recibir antes de dar por finalizada la pesada. \n // Un evento obligatorio podria ser La tarjeta RFID o el QR o pulsar el boton de Validacion\n\n //******************************** AQUI PONDREMOS EL ANALISIS DE LA RX DE LA IMAGEN DE CONTEXTO ********************************************** */\n \n\n todos_obligatorios_ok = ID_ok && detector_ok && boton_ok && seleccion_ok && !register_flag && firma_ok && matricula_ok && ubicacion_ok && imagen_contexto_ok;\n //OJO \"register_flag\" debe ser false lo cual indica que aun no hemos enviado el movimiento.\n node.warn(\"todos obligatorios = \" + todos_obligatorios_ok)\n node.warn(\"ID_ok = \" + ID_ok + \" ; detector_ok = \" + detector_ok + \" ; register_flag = \" + register_flag + \" ; seleccion = \" + seleccion_ok + \n \" ; matricula = \" + matricula_ok + \" ; boton = \" + boton_ok + \" ; ubicacion = \" + ubicacion_ok + \" ; imagen_contexto = \" + imagen_contexto_ok)\n \n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n //Agregamos al registro los nuevos datos recogidos\n //node.warn(\"matricula ok\")\n let new_register = flow.get(\"register\")\n new_register.matricula = flow.get(\"matricula\")\n new_register.matriculaeditada = flow.get(\"matricula_editada_flag\")\n new_register.nombre_imagen = flow.get(\"nombre_imagen\")\n new_register.qr = flow.get(\"last_QR\")\n new_register.nombre_contexto = flow.get(\"nombre_contexto\") // el nombre se asigna al recibir la imagen en el nodo \"convert to base64\"\n /*\n if (flow.get(\"tipo_movimiento\") == \"inicial\"){\n new_register.qr = flow.get(\"last_QR\")\n }\n else if (flow.get(\"tipo_movimiento\") == \"final\"){\n new_register.qrsalida = flow.get(\"last_QR\")\n }\n */\n new_register.rfid = flow.get(\"last_RFID\")\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = flow.get(\"nombre_firma\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"camara_contexto\")) {\n new_register.imagen_contexto = flow.get(\"last_camara_contexto\")\n }\n if (flow.get(\"menu_activo\")){\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n if (!flow.get(\"movimiento_enviado\")){\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n }\n //------------------------------------------------------------------------------------------------------------------------------------------\n //node.warn(\"revisando QR / RFID flags\")\n \n if (flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\") || !flow.get(\"ID_obligatorio\")) {\n flow.set(\"window_men_m3\", \"\");\n }\n else {\n //node.warn(\"sacamos mensaje de identificacion\")\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\")); // solicitamos por pantalla una identificación de tipo QR o RFID\n }//-----------------------------------------------------------------------------------------------------------------------------------------\n break;\n\n case \"B\": //************************************** MODO B [ Matricula - sensor local - boton de salida ] *****************************************************\n // aqui revisamos si se recibio matricula y un evento que indique que el conductor esta frente al totem\n // puede ser alguno de los siguientes elementos:\n // - el boton de activacion de salida que ponemos en pantalla en caso de estar habilitado para ello en el archivo de configuración\n // - el sensor local de presencia de vehiculo\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento se actibve el semaforo en verde.\n // Adidionalmente se revisa si existe algun parametro OBLIGATORIO que se deba recibir antes de dar por finalizada la pesada. \n // Un evento obligatorio podria ser La tarjeta RFID o el QR o pulsar el boton de Validacion\n\n todos_obligatorios_ok = detector_ok && boton_ok && seleccion_ok && !register_flag && firma_ok && matricula_ok && ubicacion_ok;\n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n //Agregamos al registro los nuevos datos recogidos\n let new_register = flow.get(\"register\")\n new_register.matricula = flow.get(\"matricula\")\n new_register.matriculaeditada = flow.get(\"matricula_editada_flag\")\n new_register.nombre_imagen = flow.get(\"nombre_imagen\")\n new_register.qr = \"Sin Lector de QR\"\n new_register.rfid = \"Sin Lector de RFID\"\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = \"firma-\" + flow.get(\"nombre_imagen\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"menu_activo\")) {\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n break;\n case \"C\": //************************************** MODO C [ QR / RFID - sensor local - boton de salida ]*****************************************************\n // aqui revisamos si se recibio un evento que indique que el conductor esta frente al totem\n // puede ser alguno de los siguientes eslementos:\n // - un QR o una tarjeta RFID\n // - el boton de activacion de salida que ponemos en pantalla en caso de estar habilitado para ello en el archivo de configuración\n // - el sensor local de presencia de vehiculo\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento que se active el semaforo en verde.\n // Adidionalmente se revisa si existe algun parametro OBLIGATORIO que se deba recibir antes de dar por finalizada la pesada. \n // Un evento obligatorio podria ser La tarjeta RFID o el QR o pulsar el boton de Validacion\n\n todos_obligatorios_ok = ID_ok && detector_ok && boton_ok && seleccion_ok && !register_flag && firma_ok && ubicacion_ok;\n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n\n //Agregamos al registro los nuevos datos recogidos\n let new_register = flow.get(\"register\")\n new_register.matricula = \"Sin Camara\"\n new_register.matriculaeditada = false\n new_register.nombre_imagen = \"Sin Camara\"\n new_register.qr = flow.get(\"last_QR\")\n new_register.rfid = flow.get(\"last_RFID\")\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = \"firma-\" + flow.get(\"nombre_imagen\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"menu_activo\")) {\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n //------------------------------------------------------------------------------------------------------------------------------------------\n if (flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\") || !flow.get(\"ID_obligatorio\")) {\n flow.set(\"window_men_m3\", \"\");\n }\n else {\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"));\n }//-----------------------------------------------------------------------------------------------------------------------------------------\n\n break;\n case \"D\": //************************************** MODO D [boton de salida ]*****************************************************\n // aqui revisamos si se recibio el boton de validacion que indica que el conductor esta frente al totem\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento que el semaforo se active en verde.\n boton_flag = flow.get(\"salida_valida_flag\") || false;\n\n boton_obligatorio = seleccion_ok && (flow.get(\"boton_obligatorio\") || false); // Este corresponde al boton de la pantalla de Validacion en caso de estar habilitado\n register_flag = flow.get(\"movimiento_registrado_flag\")\n\n // Evaluación de cumplimiento de Flags actuales y Flags obligatorios\n\n boton_ok = !boton_obligatorio || boton_flag;\n\n todos_obligatorios_ok = boton_ok && !register_flag && firma_ok && ubicacion_ok;\n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n\n //Agregamos al registro los nuevos datos recogidos\n let new_register = flow.get(\"register\")\n new_register.matricula = \"Sin Camara\"\n new_register.matriculaeditada = false\n new_register.nombre_imagen = \"Sin Camara\"\n new_register.qr = \"Sin Lector de QR\"\n new_register.rfid = \"Sin Lector de RFID\"\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = \"firma-\" + flow.get(\"nombre_imagen\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"menu_activo\")) {\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n\n break;\n\n }// termina el codigo del SWITCH CASE\n //*************************************************** PREPARACION Y ENVIO DEL MOVIMIENTO *******************************************************\n if (flow.get(\"movimiento_registrado_flag\") && !flow.get(\"supervisor\") && flow.get(\"totem_master\") && (flow.get(\"tipo_movimiento\") != \"nodefinido\")&& !flow.get(\"movimiento_enviado\")) {\n let date = new Date();\n let timestamp = parseInt(date.getTime() / 1000);\n flow.set(\"horasalida\", new Date(date.getTime()).toLocaleString()) // Convierte a formato legible\n\n let new_register = flow.get(\"register\")\n new_register.horasalida = flow.get(\"horasalida\")\n new_register.pesoestable = flow.get(\"peso_estable\")\n new_register.timestamp = timestamp\n //hay que revisar imagen, QR y RFID ya que no en todos los casos estan presentes\n\n let obj = new_register;\n delete obj.sincro\n new_register = obj\n new_register.imagen = flow.get(\"matricula_image\")\n if (flow.get(\"firma_obligatoria\")) { // cambiamos \"firma_habilitada\" por \"firma_obligatoria\"\n new_register.firma = flow.get(\"last_firma\")\n }\n if(flow.get(\"camara_contexto\")){\n new_register.imagen_contexto = flow.get(\"last_camara_contexto\")\n }\n\n flow.set(\"movimiento_registrado_flag\", false) // evitamos que podamos entrar en este espacio hasta nuevo registro\n\n // *********************** preparamos json con movimiento para enviar al supervisor local de la bascula *****************\n let msg_mov = { payload: {} }\n new_register.tara = flow.get(\"tara\")\n new_register.destareautomatico = flow.get(\"destareautomatico\")\n msg_mov.payload.device = \"supervisor\"\n msg_mov.payload.totem_id = flow.get(\"totem_id\")\n msg_mov.payload.accion = \"movimiento\"\n //msg_mov.payload.tipo = flow.get(\"modelo\") // entrada / salida\n msg_mov.payload.tipomovimiento = flow.get(\"tipo_movimiento\")\n //msg_mov.payload.urlapi = flow.get(\"url_API\")\n msg_mov.payload.movimiento = new_register // enviamos el registro del movimiento con las imagenes de matricula y de firma\n flow.set(\"movimiento_enviado\", true)\n flow.set(\"new_register\", {}) // inicializamos el registro para evitar cualquier posible duplicado en bd\n node.send([null, null, msg_mov, null])\n }\n\n }\n}\nreturn ([null, null, null, msg, null])",
+ "func": "//***************************** Selecciona Modo de Operacion **************************************************\nif (!flow.get(\"supervisor\")) {\n if (flow.get(\"peso_estable_flag\")) { //El peso estable se obtiene cuando el vehiculo esta frente al Totem (QR / RFID o sino Detector Local ON o bien pulsar un boton que aparezca en pantalla)\n if (flow.get(\"tipo_movimiento\") == \"final\") {\n flow.set(\"firma_ok_flag\", true) // indicamos que la firma esta hecha, esta no hace falta para la salida\n }\n let ID_verificado = flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\")\n if (flow.get(\"firma_obligatoria\") && !flow.get(\"firma_flag\") &&!flow.get(\"firma_ok_flag\") && !flow.get(\"supervisor\") && (!flow.get(\"menu_activo\") || (flow.get(\"menu_activo\") && (flow.get(\"menu_seleccionado_flag\") || ID_verificado)))) { //chequea si tenemos que solicitar firma\n /*\n El if anterior se cumple si:\n - firma_obligatoria es true y firma_ok_flag es false y firma_flag es false y si supervisor es false y ademas si menu_activo es false o bien menu_activo es true y menu_seleccionado_flag es true (osea se ha seleccionado el menu)\n Con esto aseguramos que la firma la sacamos una vez que el usuario ha hecho la seleccion del menu (en caso de existir) y no antes.\n */\n // hemos cambiado \"firma_habilitada\" por \"firma_obligatoria\" porque finalmente con un solo parametro es suficiente\n // finalmente hacemos el llamado a la firma solamente durante el movimiento inicial\n if (flow.get(\"tipo_movimiento\") == \"inicial\") {\n flow.set(\"firma_flag\", true) // solicitud de firma\n setTimeout(() => {\n //node.warn(\"solicitando firma\")\n node.send([{ \"payload\": { \"tab\": \"Firma\" } }, { payload: \"firma\" }, null, null, {payload:\"\"}])\n }, 2000);\n }\n /*\n else if (flow.get(\"tipo_movimiento\") == \"final\") {\n flow.set(\"firma_ok_flag\", true) // indicamos que la firma esta hecha, esta no hace falta para la salida\n }\n */\n }\n\n //=============================================================================================================================================\n //====================================================== MODO DE OPERACION ====================================================================\n //=============================================================================================================================================\n let modo = flow.get(\"modo_totem\")\n // -----------------------------------------------------COMUN PARA TODOS LOS MODOS ------------------------------------------------------------\n let detector_flag = (flow.get(\"distance_flag_SET\") && (flow.get(\"sentido\") == \"entrada\") && flow.get(\"sensor_distancia_local\")) || false;\n let boton_flag = flow.get(\"salida_valida_flag\") || false;\n let matricula_flag = flow.get(\"matricula_ok_flag\") || false;\n let register_flag = flow.get(\"movimiento_registrado_flag\"); //si true, indica que el movimiento ha sido enviado\n let firma_flag = flow.get(\"firma_ok_flag\")\n let menu_activo = flow.get(\"menu_activo\") // el menu activo se configura en el archivo de configuracion\n let menu_selected = flow.get(\"menu_seleccionado_flag\") // este flag se activa cuando el conductor selecciona el residuo del menu y lo envia (en caso de menu_activo = true)\n //let ID_verificado = flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\")\n \n // Reglas de obligatoriedad configurables en archivo de configuracion\n let ID_presentado = flow.get(\"ID_presentado\")\n let ID_obligatorio = flow.get(\"ID_obligatorio\") || (flow.get(\"ID_obligatorio_tmp\") || false)\n let detector_obligatorio = flow.get(\"detector_obligatorio\") || false; // este es el detector de presencia de vehiculo frente al totem\n let boton_obligatorio = flow.get(\"boton_obligatorio\") || false; // Este corresponde al boton de la pantalla de Validacion en caso de estar habilitado\n let firma_obligatoria = flow.get(\"firma_obligatoria\") || false;\n //let matricula_obligatoria = flow.get(\"matricula_obligatoria\") || false\n let matricula_obligatoria = flow.get(\"matricula_obligatoria\") || true // siempre es obligatoria. Es el punto central para gestionar elos movimientos en BD\n let imagen_contexto_ok = flow.get(\"camara_contexto_rx\") || !flow.get(\"camara_contexto\") || flow.get(\"camara_contexto_estado\") === \"ok\" || flow.get(\"camara_contexto_estado\") === \"fail\"\n //Se evalua flow.get(\"camara_contexto_estado\")-> si es \"ok\" significa que se recibio la imagen. Si es \"fail\" significa que se agotaron los dos tiempos de espera de los dos intentos\n //los valores posibles de \"camara_contexto_estado\" son \"idle\", waiting1\", \"waiting2\", \"ok\", \"fail\".\n //idle = no se ha iniciado ninguna solicitud de imagen de contexto. \"waiting1\" = Se inicio la primera solicitud de imagen de contexto. \"waiting2\" = Se inicio la segunda solicitud\n //\"ok\" = imagen de contexto recibida. \"fail\" = se enviaron dos intentos y se esperaron los dos tiempos previstos pero no se recibio imagen de contexto.\n \n // Evaluación de cumplimiento de Flags actuales y Flags obligatorios\n //let ID_ok = !ID_obligatorio || ID_verificado\n let ID_ok = (!ID_obligatorio && !ID_presentado) || ID_verificado;\n let detector_ok = !detector_obligatorio || detector_flag;\n if (flow.get(\"tipo_movimiento\") == \"inicial\") { boton_flag = true } // en movimiento inicial no tiene sentido el boton\n let boton_ok = !boton_obligatorio || boton_flag;\n let firma_ok = !firma_obligatoria || firma_flag;\n //**************************************************** Excepcion para Trajeta RFID **************************************************\n //*********************************** No es necesario tener la matricula del Vehiculo ni poner boton de salida *******************************\n if (flow.get(\"RFID_verificado\")) { \n matricula_flag = true \n boton_ok = true\n }\n \n let matricula_ok = !matricula_obligatoria || matricula_flag\n let seleccion_ok\n if(flow.get(\"tipo_movimiento\") == \"inicial\"){\n seleccion_ok = !menu_activo || menu_selected || ID_verificado // Si el menu esta activo, el ID_verificado permite saltar la seleccion del residuo\n\n if (ID_verificado && menu_activo) {\n // ==================== eliminamos mensaje y boton del menu debido a que tenemos ID del residuo (Tarjeta o QR) ================================\n flow.set(\"startmenu_flag\", false) // para poder eliminar el boton y borrar el mensaje em \"window_men_m1\"\n flow.set(\"window_men_m1\", \"\") // colocamos mensaje vacio en el espacio del mensaje 1 donde decia Haga click Abajo\n }\n }\n else if(flow.get(\"tipo_movimiento\") == \"final\"){\n //seleccion_ok = !menu_activo || menu_selected || ID_verificado || boton_flag\n seleccion_ok = true\n ID_ok = !flow.get(\"salida_ID_obligatorio\") || ID_verificado\n }\n \n //************************ SOLICITUD DE UBICACION INTERNA Y NOTIFICACION AL CONDUCTOR ***************************************/\n // ****** OJO AQUI ***** Mientras \"ubicacion_recibida\" no cambie a true, es decir hasta que la BD no conteste el request, esto seguira enviando el request nuevamente\n // Es decir que si se pierde comunicacion esto enviara siempre que pueda entrar en este codigo.\n let requerimientos_ok = ID_ok && boton_ok && firma_ok && matricula_ok && seleccion_ok && flow.get(\"mostrar_ubicacion\") && !flow.get(\"mostrar_ubicacion_ok\") && (flow.get(\"tipo_movimiento\") === \"inicial\")\n //node.warn(\"requerimientos_ok = \" + requerimientos_ok)\n //node.warn(\"seleccion = \" + seleccion_ok + \" ; matricula = \" + matricula_ok + \" ; boton = \" + boton_ok + \" ; firma = \" + firma_ok + \" ; mostrar_ubicacion = \" + flow.get(\"mostrar_ubicacion\") + \" ; movimiento = \" + (flow.get(\"tipo_movimiento\") === \"inicial\"))\n \n if (requerimientos_ok) {\n if (!flow.get(\"ubicacion_recibida\")) { // Si aun no hemos recibido el aviso de la ubicacion, la solicitamos\n let id_residuo\n if (flow.get(\"last_QR\") != \"-\") { id_residuo = flow.get(\"last_QR\") }\n else if (flow.get(\"last_RFID\") != \"-\") { id_residuo = flow.get(\"last_RFID\") }\n else if (flow.get(\"id_seleccionado\") != \"no recibido\") { id_residuo = flow.get(\"id_seleccionado\") }\n msg.payload = { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), device: \"supervisor\", accion: \"check_ubicacion\", id_residuo: id_residuo }\n node.send([null, null, msg, null])\n //node.warn(\"enviado solicitud de ubicacion\")\n }\n\n //if (flow.get(\"ubicacion_recibida\")) { // Con flow.get(\"mostrar_ubicacion_ok\") aseguramos que solo sacamos la notificacion una vez\n else {\n //Aqui sacamos notificacion al conductor\n \n flow.set(\"mostrar_ubicacion_ok\", true) //marcamos que ya hemos recibido respuesta del ubicacion\n if (!flow.get(\"ubicacion_interna\")) { // si no se ha recibido el flag de ubicacion interna en true es que no existe ubicacion especifica para ese residuo\n flow.set(\"dirigirse\", \"NO HAY UBICACION DEFINIDA\")\n }\n //node.warn(\"DIRIGIRSE A : \" + flow.get(\"dirigirse\"))// aqui enviamos la notificacion al conductor\n // esperamos un tiempo para que este mensaje quede de ultimo y no sea sustituido por la notificacion del contenido y procedencia\n setTimeout(() => { \n node.send([null, null, null, null, {\n payload:\n \"\" +\n \"
ATENCION
\" +\n \"
\" + flow.get(\"dirigirse\") + \"
\" +\n \"
\"\n }])\n }, 2000);\n \n\n }\n }\n if (flow.get(\"tipo_movimiento\") === \"final\" || flow.get(\"tipobascula\") === \"salida\" ) { flow.set(\"mostrar_ubicacion_ok\", true) }\n let ubicacion_ok = !flow.get(\"mostrar_ubicacion\") || flow.get(\"mostrar_ubicacion_ok\")\n //******************************************************************************************************************************************************** */\n \n \n let todos_obligatorios_ok;\n\n switch (modo) {\n\n case \"A\": //************************************** MODO A [ Matricula - QR / RFID - sensor local - boton de salida ]***************************************************** */\n // aqui revisamos si se recibio matricula y un evento que indique que el conductor esta frente al totem\n // puede ser alguno de los siguientes eslementos:\n // - un QR o una tarjeta RFID\n // - el boton de activacion de salida que ponemos en pantalla en caso de estar habilitado para ello en el archivo de configuración\n // - el sensor local de presencia de vehiculo\n // - la seleccion del menu\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento que se active el semaforo en verde\n // Adidionalmente se revisa si existe algun parametro OBLIGATORIO (presente en la configuracion ) que se deba recibir antes de dar por finalizada la pesada. \n // Un evento obligatorio podria ser La tarjeta RFID o el QR o pulsar el boton de Validacion\n\n //******************************** AQUI PONDREMOS EL ANALISIS DE LA RX DE LA IMAGEN DE CONTEXTO ********************************************** */\n \n\n todos_obligatorios_ok = ID_ok && detector_ok && boton_ok && seleccion_ok && !register_flag && firma_ok && matricula_ok && ubicacion_ok && imagen_contexto_ok;\n //OJO \"register_flag\" debe ser false lo cual indica que aun no hemos enviado el movimiento.\n node.warn(\"todos obligatorios = \" + todos_obligatorios_ok)\n node.warn(\"ID_ok = \" + ID_ok + \" ; detector_ok = \" + detector_ok + \" ; register_flag = \" + register_flag + \" ; seleccion = \" + seleccion_ok + \n \" ; matricula = \" + matricula_ok + \" ; boton = \" + boton_ok + \" ; ubicacion = \" + ubicacion_ok + \" ; imagen_contexto = \" + imagen_contexto_ok)\n \n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n //Agregamos al registro los nuevos datos recogidos\n //node.warn(\"matricula ok\")\n let new_register = flow.get(\"register\")\n new_register.matricula = flow.get(\"matricula\")\n new_register.matriculaeditada = flow.get(\"matricula_editada_flag\")\n new_register.nombre_imagen = flow.get(\"nombre_imagen\")\n new_register.qr = flow.get(\"last_QR\")\n new_register.nombre_contexto = flow.get(\"nombre_contexto\") // el nombre se asigna al recibir la imagen en el nodo \"convert to base64\"\n /*\n if (flow.get(\"tipo_movimiento\") == \"inicial\"){\n new_register.qr = flow.get(\"last_QR\")\n }\n else if (flow.get(\"tipo_movimiento\") == \"final\"){\n new_register.qrsalida = flow.get(\"last_QR\")\n }\n */\n new_register.rfid = flow.get(\"last_RFID\")\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = flow.get(\"nombre_firma\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"camara_contexto\")) {\n new_register.imagen_contexto = flow.get(\"last_camara_contexto\")\n }\n if (flow.get(\"menu_activo\")){\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n if (!flow.get(\"movimiento_enviado\")){\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n }\n //------------------------------------------------------------------------------------------------------------------------------------------\n //node.warn(\"revisando QR / RFID flags\")\n \n if (flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\") || !flow.get(\"ID_obligatorio\")) {\n flow.set(\"window_men_m3\", \"\");\n }\n else {\n //node.warn(\"sacamos mensaje de identificacion\")\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\")); // solicitamos por pantalla una identificación de tipo QR o RFID\n }//-----------------------------------------------------------------------------------------------------------------------------------------\n break;\n\n case \"B\": //************************************** MODO B [ Matricula - sensor local - boton de salida ] *****************************************************\n // aqui revisamos si se recibio matricula y un evento que indique que el conductor esta frente al totem\n // puede ser alguno de los siguientes elementos:\n // - el boton de activacion de salida que ponemos en pantalla en caso de estar habilitado para ello en el archivo de configuración\n // - el sensor local de presencia de vehiculo\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento se actibve el semaforo en verde.\n // Adidionalmente se revisa si existe algun parametro OBLIGATORIO que se deba recibir antes de dar por finalizada la pesada. \n // Un evento obligatorio podria ser La tarjeta RFID o el QR o pulsar el boton de Validacion\n\n todos_obligatorios_ok = detector_ok && boton_ok && seleccion_ok && !register_flag && firma_ok && matricula_ok && ubicacion_ok;\n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n //Agregamos al registro los nuevos datos recogidos\n let new_register = flow.get(\"register\")\n new_register.matricula = flow.get(\"matricula\")\n new_register.matriculaeditada = flow.get(\"matricula_editada_flag\")\n new_register.nombre_imagen = flow.get(\"nombre_imagen\")\n new_register.qr = \"Sin Lector de QR\"\n new_register.rfid = \"Sin Lector de RFID\"\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = \"firma-\" + flow.get(\"nombre_imagen\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"menu_activo\")) {\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n break;\n case \"C\": //************************************** MODO C [ QR / RFID - sensor local - boton de salida ]*****************************************************\n // aqui revisamos si se recibio un evento que indique que el conductor esta frente al totem\n // puede ser alguno de los siguientes eslementos:\n // - un QR o una tarjeta RFID\n // - el boton de activacion de salida que ponemos en pantalla en caso de estar habilitado para ello en el archivo de configuración\n // - el sensor local de presencia de vehiculo\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento que se active el semaforo en verde.\n // Adidionalmente se revisa si existe algun parametro OBLIGATORIO que se deba recibir antes de dar por finalizada la pesada. \n // Un evento obligatorio podria ser La tarjeta RFID o el QR o pulsar el boton de Validacion\n\n todos_obligatorios_ok = ID_ok && detector_ok && boton_ok && seleccion_ok && !register_flag && firma_ok && ubicacion_ok;\n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n\n //Agregamos al registro los nuevos datos recogidos\n let new_register = flow.get(\"register\")\n new_register.matricula = \"Sin Camara\"\n new_register.matriculaeditada = false\n new_register.nombre_imagen = \"Sin Camara\"\n new_register.qr = flow.get(\"last_QR\")\n new_register.rfid = flow.get(\"last_RFID\")\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = \"firma-\" + flow.get(\"nombre_imagen\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"menu_activo\")) {\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n //------------------------------------------------------------------------------------------------------------------------------------------\n if (flow.get(\"QR_verificado\") || flow.get(\"RFID_verificado\") || !flow.get(\"ID_obligatorio\")) {\n flow.set(\"window_men_m3\", \"\");\n }\n else {\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"));\n }//-----------------------------------------------------------------------------------------------------------------------------------------\n\n break;\n case \"D\": //************************************** MODO D [boton de salida ]*****************************************************\n // aqui revisamos si se recibio el boton de validacion que indica que el conductor esta frente al totem\n // El flag movimiento_registrado_flag se revisa para asegurar que se registra una sola vez al cumplir las condiciones\n // El registro queda en memoria, este se pasa a BD solamente al momento que el semaforo se active en verde.\n boton_flag = flow.get(\"salida_valida_flag\") || false;\n\n boton_obligatorio = seleccion_ok && (flow.get(\"boton_obligatorio\") || false); // Este corresponde al boton de la pantalla de Validacion en caso de estar habilitado\n register_flag = flow.get(\"movimiento_registrado_flag\")\n\n // Evaluación de cumplimiento de Flags actuales y Flags obligatorios\n\n boton_ok = !boton_obligatorio || boton_flag;\n\n todos_obligatorios_ok = boton_ok && !register_flag && firma_ok && ubicacion_ok;\n if (todos_obligatorios_ok) { // Cerramos el registro con los parametros hasta ahora recogidos\n\n //Agregamos al registro los nuevos datos recogidos\n let new_register = flow.get(\"register\")\n new_register.matricula = \"Sin Camara\"\n new_register.matriculaeditada = false\n new_register.nombre_imagen = \"Sin Camara\"\n new_register.qr = \"Sin Lector de QR\"\n new_register.rfid = \"Sin Lector de RFID\"\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n if (flow.get(\"firma_obligatoria\") && flow.get(\"firma_ok_flag\")) {\n new_register.nombre_firma = \"firma-\" + flow.get(\"nombre_imagen\")\n new_register.firmaobligatoria = true\n }\n else {\n new_register.nombre_firma = \"No Habilitada\"\n new_register.firmaobligatoria = false\n }\n if (flow.get(\"menu_activo\")) {\n new_register.id_seleccionado = flow.get(\"id_seleccionado\")\n }\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n flow.set(\"fin_pesada_flag\", true)\n }\n\n break;\n\n }// termina el codigo del SWITCH CASE\n //*************************************************** PREPARACION Y ENVIO DEL MOVIMIENTO *******************************************************\n if (flow.get(\"movimiento_registrado_flag\") && !flow.get(\"supervisor\") && flow.get(\"totem_master\") && (flow.get(\"tipo_movimiento\") != \"nodefinido\")&& !flow.get(\"movimiento_enviado\")) {\n let date = new Date();\n let timestamp = parseInt(date.getTime() / 1000);\n flow.set(\"horasalida\", new Date(date.getTime()).toLocaleString()) // Convierte a formato legible\n\n let new_register = flow.get(\"register\")\n new_register.horasalida = flow.get(\"horasalida\")\n new_register.pesoestable = flow.get(\"peso_estable\")\n new_register.timestamp = timestamp\n //hay que revisar imagen, QR y RFID ya que no en todos los casos estan presentes\n\n let obj = new_register;\n delete obj.sincro\n new_register = obj\n new_register.imagen = flow.get(\"matricula_image\")\n if (flow.get(\"firma_obligatoria\")) { // cambiamos \"firma_habilitada\" por \"firma_obligatoria\"\n new_register.firma = flow.get(\"last_firma\")\n }\n if(flow.get(\"camara_contexto\")){\n new_register.imagen_contexto = flow.get(\"last_camara_contexto\")\n }\n\n flow.set(\"movimiento_registrado_flag\", false) // evitamos que podamos entrar en este espacio hasta nuevo registro\n\n // *********************** preparamos json con movimiento para enviar al supervisor local de la bascula *****************\n let msg_mov = { payload: {} }\n new_register.tara = flow.get(\"tara\")\n new_register.destareautomatico = flow.get(\"destareautomatico\")\n msg_mov.payload.device = \"supervisor\"\n msg_mov.payload.totem_id = flow.get(\"totem_id\")\n msg_mov.payload.accion = \"movimiento\"\n //msg_mov.payload.tipo = flow.get(\"modelo\") // entrada / salida\n msg_mov.payload.tipomovimiento = flow.get(\"tipo_movimiento\")\n //msg_mov.payload.urlapi = flow.get(\"url_API\")\n msg_mov.payload.movimiento = new_register // enviamos el registro del movimiento con las imagenes de matricula y de firma\n flow.set(\"movimiento_enviado\", true)\n flow.set(\"new_register\", {}) // inicializamos el registro para evitar cualquier posible duplicado en bd\n\n if (flow.get(\"tipobascula\") == \"salida\" && flow.get(\"tipo_movimiento\") == \"inicial\") { // evita que la bascula de salida genere movimiento inicial\n msg_mov = null\n }\n node.send([null, null, msg_mov, null])\n }\n\n }\n}\nreturn ([null, null, null, msg, null])",
"outputs": 5,
"timeout": 0,
"noerr": 0,
@@ -5074,7 +5080,8 @@
"f75c248d56207759",
"b6a2b0d90858876e",
"42499939644932e1",
- "a0f7956de8f33a0b"
+ "a0f7956de8f33a0b",
+ "4abf2246aa647ea1"
],
"x": 1725,
"y": 820,
@@ -5787,7 +5794,7 @@
"z": "953e8740401d175c",
"g": "595fb0f89af85c42",
"name": "config edit",
- "func": "const config = JSON.parse(msg.payload);\nmsg ={}; // clear msg object\nlet read;\nlet config_general = []\nlet config_tiempos = []\nlet config_mensajes = []\nlet config_sensor = []\nlet config_camara = []\nlet config_conex = []\nlet config_tipos = []\n\nconfig.general = toObject(config.general);\nconfig.camara = toObject(config.camara);\nconfig.conexion = toObject(config.conexion);\nconfig.sensores = toObject(config.sensores);\nconfig.mensajes = toObject(config.mensajes);\nconfig.tiempos = toObject(config.tiempos);\n\nconst tiposOriginales = config.tipos || {};\n\n\n// Aseguramos que cada tipo esté como array vacío si no tiene nada\nfor (let i = 1; i <= 6; i++) {\n if (!Array.isArray(tiposOriginales[i])) {\n tiposOriginales[i] = [];\n }\n}\nflow.set(\"tiposDatosGlobal\", tiposOriginales);\n\nconfig.tipos = tiposOriginales;\n\n\n\n//**************************** Parametros de Validacion OBLIGATORIOS para PESADA FINALIZADA ***************************************\n// Estos parametros pueden ser: QR / RFID / Boton Validacion / Detector Vehiculo \n//*********************************************************************************************************************************\n/*read = config.QR_obligatorio;\nconfig_general.push({ \"parametro\": \"QR_obligatorio\", \"valor\": read })\nflow.set(\"QR_obligatorio\", read);\nread = config.RFID_obligatorio;\nconfig_general.push({ \"parametro\": \"RFID_obligatorio\", \"valor\": read })\nflow.set(\"RFID_obligatorio\", read);\n\nread = config.general.funcion_totem;\nconfig_general.push({ \"parametro\": \"funcion_totem\", \"valor\": read })\nflow.set(\"funcion_totem\", read);\n\nread = config.general.identificacion_esp;\nconfig_general.push({ \"parametro\": \"identificacion_esp\", \"valor\": read })\nflow.set(\"identificacion_esp\", read);\n\nread = config.tiempos.timer1;\nconfig_tiempos.push({ \"parametro\": \"timer1\", \"valor\": read })\nflow.set(\"timer1\", read);\n\n*/\n\nread = config.general.Tipo_Configuracion;\nconfig_general.push({ \"parametro\": \"Tipo_Configuracion\", \"valor\": read })\nflow.set(\"Tipo_Configuracion\", read);\n\nread = config.general.ID_obligatorio;\nconfig_general.push({ \"parametro\": \"ID_obligatorio\", \"valor\": read })\nflow.set(\"ID_obligatorio\", read);\n\nread = config.general.salida_ID_obligatorio;\nconfig_general.push({ \"parametro\": \"salida_ID_obligatorio\", \"valor\": read })\nflow.set(\"salida_ID_obligatorio\", read);\n\nread = config.general.detector_obligatorio;\nconfig_general.push({ \"parametro\": \"detector_obligatorio\", \"valor\": read })\nflow.set(\"detector_obligatorio\", read);\n\nread = config.general.boton_obligatorio;\nconfig_general.push({ \"parametro\": \"boton_obligatorio\", \"valor\": read })\nflow.set(\"boton_obligatorio\", read);\nread = config.general.firma_obligatoria;\nconfig_general.push({ \"parametro\": \"firma_obligatoria\", \"valor\": read })\nflow.set(\"firma_obligatoria\", read);\nread = config.general.matricula_obligatoria;\nconfig_general.push({ \"parametro\": \"matricula_obligatoria\", \"valor\": read })\nflow.set(\"matricula_obligatoria\", read);\n\n\n\n//==================================================================================================================================\nread = config.general.edicion_matricula;\nconfig_general.push({ \"parametro\": \"edicion_matricula\", \"valor\": read })\nflow.set(\"edicion_matricula\", read); // Habilita la edicion de matricula\n\nread = config.general.botonsalida_activo;\nconfig_general.push({ \"parametro\": \"botonsalida_activo\", \"valor\": read })\nflow.set(\"botonsalida_activo\", read); // Permite poner boton de salida\n\nread = config.general.menu_activo;\nconfig_general.push({ \"parametro\": \"menu_activo\", \"valor\": read })\nflow.set(\"menu_activo\", read); // Permite poner los menus de contratacion\n\n/*\nread = config.general.firma_habilitada;\nconfig_general.push({ \"parametro\": \"firma_habilitada\", \"valor\": read })\nflow.set(\"firma_habilitada\", read); // Habilita la edicion de firma\n*/\n\nread = config.general.barrera_habilitada;\nconfig_general.push({ \"parametro\": \"barrera_habilitada\", \"valor\": read })\nflow.set(\"barrera_habilitada\", read); // Habilita el uso de barrera\n\nread = config.general.mostrar_ubicacion\nconfig_general.push({ \"parametro\": \"mostrar_ubicacion\", \"valor\": read })\nflow.set(\"mostrar_ubicacion\", read);\n\nread = config.general.switch_2_Totem_page;\nflow.set(\"switch_2_Totem_page\", read); // si igual a true cambia a pagina principal del totem siempre que se active la bascula\n// Con esto aseguramos que si queda abierta una ventana de configuracion se pueda quitar automaticamente\nconfig_general.push({ \"parametro\": \"switch_2_Totem_page\", \"valor\": read })\n\n//flow.set(\"peso\", read); // crea variable para recibir peso del supervisor\n\nread = parseInt(config.general.peso_minimo); // peso minimo para utilizado para indicar cuando hay vehiculo en la balanza o no\nconfig_general.push({ \"parametro\": \"peso_minimo\", \"valor\": read })\nflow.set(\"peso_minimo\", read);\n\nread = config.general.formatoPais; // peso minimo para utilizado para indicar cuando hay vehiculo en la balanza o no\nconfig_general.push({ \"parametro\": \"formatoPais\", \"valor\": read })\nflow.set(\"formatoPais\", read);\n\n//------------------- TOTEM MASTER tiempo de confirmacion -------------------------------------\nread = config.tiempos.confirm_master_time;\nconfig_tiempos.push({ \"parametro\": \"confirm_master_time\", \"valor\": read })\nflow.set(\"confirm_master_time\", read);\n//---------------------------------------------------------------------------------------------\n\n\nread = config.general.audio_level;\nconfig_general.push({ \"parametro\": \"audio_level\", \"valor\": read })\nflow.set(\"audio_level\", read);\n//-------------------------------------------------------\nread = config.general.mante_code_RFID; //codigo RFID para pasar a pantalla de mantenimiento\nconfig_general.push({ \"parametro\": \"mante_code_RFID\", \"valor\": read })\nflow.set(\"mante_code_RFID\", read)\nread = config.general.mante_code_QR; //codigo QR para pasar a pantalla de mantenimiento\nconfig_general.push({ \"parametro\": \"mante_code_QR\", \"valor\": read })\nflow.set(\"mante_code_QR\", read)\n\n//------------------------------- MENSAJES -------------------------\nread = config.tiempos.tiempo_mensaje;\nconfig_tiempos.push({ \"parametro\": \"tiempo_mensaje\", \"valor\": read })\nflow.set(\"tiempo_mensaje\", read);\n\nread = config.tiempos.relay2_pulse // duración del pulso generado en el relay 2 al terminar el pesaje para abrir barrera\nconfig_tiempos.push({ \"parametro\": \"relay2_pulse\", \"valor\": read })\nflow.set(\"relay2_pulse\", read);\n\nread = config.mensajes.mensaje2 // no se usa\nconfig_mensajes.push({ \"parametro\": \"mensaje2\", \"valor\": read })\nflow.set(\"mensaje2\", read);\nread = config.mensajes.mensaje1 // no se usa\nconfig_mensajes.push({ \"parametro\": \"mensaje1\", \"valor\": read })\nflow.set(\"mensaje1\", read);\nread = config.general.init_screen\nconfig_general.push({ \"parametro\": \"init_screen\", \"valor\": read })\nflow.set(\"init_screen\", read);\n\n//-------------------------------------------------------\nread = config.general.totem_serial // seriall asignado a este dispositivo\nconfig_general.push({ \"parametro\": \"totem_serial\", \"valor\": read })\nflow.set(\"totem_serial\", read);\n\n//---------------------------------------- Parametros por defecto del boton de salida para VALIDACION -----------------------------------------------------------\nread = config.mensajes.botonsalida_txt_def\nconfig_mensajes.push({ \"parametro\": \"botonsalida_txt_def\", \"valor\": read })\nflow.set(\"botonsalida_txt_def\", read)\nread = config.general.botonsalida_color_def\nconfig_general.push({ \"parametro\": \"botonsalida_color_def\", \"valor\": read })\nflow.set(\"botonsalida_color_def\", read)\nread = config.general.botonsalida_txt_color_def\nconfig_general.push({ \"parametro\": \"botonsalida_txt_color_def\", \"valor\": read })\nflow.set(\"botonsalida_txt_color_def\", read)\nread = config.mensajes.botonsalida_mensaje1\nconfig_mensajes.push({ \"parametro\": \"botonsalida_mensaje1\", \"valor\": read })\nflow.set(\"botonsalida_mensaje1\", read)\nread = config.mensajes.botonsalida_mensaje1_def\nconfig_mensajes.push({ \"parametro\": \"botonsalida_mensaje1_def\", \"valor\": read })\nflow.set(\"botonsalida_mensaje1_def\", read)\n\n//----------------------------------------- Textos Predefinidos -------------------------------------------------------------------------\nread = config.mensajes.men_pesaje_listo;\nconfig_mensajes.push({ \"parametro\": \"men_pesaje_listo\", \"valor\": read })\nflow.set(\"men_pesaje_listo\", read);\nread = config.mensajes.men_peso_estable;\nconfig_mensajes.push({ \"parametro\": \"men_peso_estable\", \"valor\": read })\nflow.set(\"men_peso_estable\", read);\nread = config.mensajes.men_identificacion;\nconfig_mensajes.push({ \"parametro\": \"men_identificacion\", \"valor\": read })\nflow.set(\"men_identificacion\", read);\nread = config.mensajes.men_salida;\nconfig_mensajes.push({ \"parametro\": \"men_salida\", \"valor\": read })\nflow.set(\"men_salida\", read);\nread = config.mensajes.id_titulo_matricula;\nconfig_mensajes.push({ \"parametro\": \"id_titulo_matricula\", \"valor\": read })\nflow.set(\"id_titulo_matricula\", read);\nread = config.mensajes.id_titulo_id;\nconfig_mensajes.push({ \"parametro\": \"id_titulo_id\", \"valor\": read })\nflow.set(\"id_titulo_id\", read);\nread = config.mensajes.id_leido;\nconfig_mensajes.push({ \"parametro\": \"id_leido\", \"valor\": read })\nflow.set(\"id_leido\", read);\nread = config.mensajes.id_no_leido;\nconfig_mensajes.push({ \"parametro\": \"id_no_leido\", \"valor\": read })\nflow.set(\"id_no_leido\", read);\n\n//===================================================CONEXION / CAMARA / SENSOR =====================================================\n//====================================================================================================================================\n\n\nread = config.conexion.modo_totem;\nconfig_conex.push({ \"parametro\": \"modo_totem\", \"valor\": read })\nflow.set(\"modo_totem\", read); // Modo de funcionamiento del totem\n\n\n//-----------------------------Gestion de IP fija / IP DHCP------------------------------------------------------\nvar ipdevice_flag = false // variables temporales para saber si hay cambios en las ip\nvar iprouter_flag = false\nread = config.conexion.ipdevice // direccion IP del dispositivo\nconfig_conex.push({ \"parametro\": \"ipdevice\", \"valor\": read })\nif (flow.get(\"ipdevice\") != read) {\n flow.set(\"ipdevice\", read);\n ipdevice_flag = true;\n}\nread = config.conexion.iprouter // direccion IP del router\nconfig_conex.push({ \"parametro\": \"iprouter\", \"valor\": read })\nif (flow.get(\"iprouter\") != read) {\n flow.set(\"iprouter\", read);\n iprouter_flag = true;\n}\nread = config.conexion.dhcp_flag // flag del DHCP\nconfig_conex.push({ \"parametro\": \"dhcp_flag\", \"valor\": read })\nif (flow.get(\"dhcp_flag\") != read) {\n flow.set(\"dhcp_flag\", read); // el dhcp_flag ha cambiado\n if (flow.get(\"dhcp_flag\")) {\n node.send([null, { payload: \". /home/trypton/scripts/enable_dhcp.sh\" }])\n }\n else {\n node.send([null, { payload: \". /home/trypton/scripts/enable_ipstatic.sh \" + flow.get(\"ipdevice\") + \"/24 \" + flow.get(\"iprouter\") }])\n }\n}\nelse { // el dhcp_flag no ha cambiado\n if (!flow.get(\"dhcp_flag\")) {\n if (ipdevice_flag || iprouter_flag) {\n node.send([null, { payload: \". /home/trypton/scripts/enable_ipstatic.sh \" + flow.get(\"ipdevice\") + \"/24 \" + flow.get(\"iprouter\") }])\n }\n }\n else {\n node.send([null, { payload: \". /home/trypton/scripts/enable_dhcp.sh\" }])\n }\n}\nflow.set(\"dhcpname_on\", \"IP Fija\") // texto que sale en el boton de la pantalla de mantenimiento\nflow.set(\"dhcpname_off\", \"DHCP\")\n//-----------------------------------Websocket IP--------------------------------------------------------------------------------------\nread = config.conexion.websocket_puerto // direccion IP del websocket del supervisor\nconfig_conex.push({ \"parametro\": \"websocket_puerto\", \"valor\": read })\nflow.set(\"websocket_puerto\", read);\nread = config.conexion.websocket_url\nconfig_conex.push({ \"parametro\": \"websocket_url\", \"valor\": read })\nif (flow.get(\"websocket_url\") != read) {\n flow.set(\"websocket_url\", read);\n node.send([{ payload: read + \" servidor.com\" }, null])\n}\n//----------------------------------- ENVIO DE MOVIMIENTOS --------------------------------------------------------------------------------------\nread = config.conexion.movimientosxmqtt;\nconfig_conex.push({ \"parametro\": \"movimientosxmqtt\", \"valor\": read })\nflow.set(\"movimientosxmqtt\", read); // Modo de envio de movimientos\n\nread = config.conexion.movimientosxapi;\nconfig_conex.push({ \"parametro\": \"movimientosxapi\", \"valor\": read })\nflow.set(\"movimientosxapi\", read); // Modo de envio de movimientos\n\n//----------------------------------- DEFINICION DEL BROKER DE MQTT --------------------------------------------------------------------------------------\n/*\nread = config.conexion.broker_url;\nconfig_conex.push({ \"parametro\": \"broker_url\", \"valor\": read })\nflow.set(\"broker_url\", read); // direccion del broker\n\nread = config.conexion.broker_port;\nconfig_conex.push({ \"parametro\": \"broker_port\", \"valor\": read })\nflow.set(\"broker_port\", read); // puerto del broker\n\nread = config.conexion.broker_username;\nconfig_conex.push({ \"parametro\": \"broker_username\", \"valor\": read })\nflow.set(\"broker_username\", read); // username del broker\n\nread = config.conexion.broker_pass;\nconfig_conex.push({ \"parametro\": \"broker_pass\", \"valor\": read })\nflow.set(\"broker_pass\", read); // password del broker\n*/\n/*\n//-------------------------------------------------- URL de la API de URBASER(Trypton) ------------------------------------------------------------------------------\nread = config.conexion.url_API;\nconfig_conex.push({ \"parametro\": \"url_API\", \"valor\": read })\nflow.set(\"url_API\", read); // Modo de funcionamiento del totem\n*/\nflow.set(\"semaforo\", \"green\")\n\n//------------------------------------Lector de QR / RF----------------------------------------------------------\nread = config.sensores.tipo_de_lector\nconfig_sensor.push({ \"parametro\": \"tipo_de_lector\", \"valor\": read })\nflow.set(\"tipo_de_lector\", read); //tipo de lector QR / RF\nread = config.sensores.rfid_invertido\nconfig_sensor.push({ \"parametro\": \"rfid_invertido\", \"valor\": read })\nflow.set(\"rfid_invertido\", read);\nflow.set(\"lector_activo\", true) // activamos el lector\nflow.set(\"ID_enviado\", false) // variable para controlar un solo envio de RFID / QR\n\n//-------------------------------------sensor de distancia-------------------------------------------------------\nread = config.sensores.sensor_distancia_local\nconfig_sensor.push({ \"parametro\": \"sensor_distancia_local\", \"valor\": read })\nflow.set(\"sensor_distancia_local\", read);\nread = config.sensores.sensor_distancia_remoto\nconfig_sensor.push({ \"parametro\": \"sensor_distancia_remoto\", \"valor\": read })\nflow.set(\"sensor_distancia_remoto\", read);\nflow.set(\"distance_flag_remote\", false)\nread = config.sensores.distance_min\nconfig_sensor.push({ \"parametro\": \"distance_min\", \"valor\": read })\nflow.set(\"distance_min\", read);\nread = config.sensores.min_cnt_in_ok\nconfig_sensor.push({ \"parametro\": \"min_cnt_in_ok\", \"valor\": read })\nflow.set(\"min_cnt_in_ok\", read);\nread = config.sensores.min_cnt_out_ok\nconfig_sensor.push({ \"parametro\": \"min_cnt_out_ok\", \"valor\": read })\nflow.set(\"min_cnt_out_ok\", read);\nflow.set(\"dist_in_counter\", 0);\nflow.set(\"dist_out_counter\", 0);\n\n//---------------------------------------Totems y Camara------------------------------------------------------------------------------\nread = config.conexion.totem_qty\nconfig_conex.push({ \"parametro\": \"totem_qty\", \"valor\": read })\nflow.set(\"totem_qty\", read);\nread = config.conexion.tipobascula\nconfig_conex.push({ \"parametro\": \"tipobascula\", \"valor\": read })\nflow.set(\"tipobascula\", read);\nread = config.conexion.totem_id_remoto\nconfig_conex.push({ \"parametro\": \"totem_id_remoto\", \"valor\": read })\nflow.set(\"totem_id_remoto\", read);\nread = config.conexion.totem_id\nconfig_conex.push({ \"parametro\": \"totem_id\", \"valor\": read })\nflow.set(\"totem_id\", read);\nread = config.conexion.numero_vial;\nconfig_conex.push({ \"parametro\": \"numero_vial\", \"valor\": read })\nflow.set(\"numero_vial\", read);\nread = config.conexion.ip_totem_pareja\nconfig_conex.push({ \"parametro\": \"ip_totem_pareja\", \"valor\": read })\nflow.set(\"ip_totem_pareja\", read);\nread = config.conexion.envia_mat_img\nconfig_conex.push({ \"parametro\": \"envia_mat_img\", \"valor\": read })\nflow.set(\"envia_mat_img\", read);\n\nread = config.camara.camara_matricula\nconfig_camara.push({ \"parametro\": \"camara_matricula\", \"valor\": read })\nflow.set(\"camara_matricula\", read);\nread = config.camara.camaraID\nconfig_camara.push({ \"parametro\": \"camaraID\", \"valor\": read })\nflow.set(\"camaraID\", read);\nread = config.camara.camara_IP\nconfig_camara.push({ \"parametro\": \"camara_IP\", \"valor\": read })\nflow.set(\"camara_IP\", read);\nread = config.camara.camara_contexto\nconfig_camara.push({ \"parametro\": \"camara_contexto\", \"valor\": read })\nflow.set(\"camara_contexto\", read);\nread = config.camara.camara_contexto_IP\nconfig_camara.push({ \"parametro\": \"camara_contexto_IP\", \"valor\": read })\nflow.set(\"camara_contexto_IP\", read);\nread = config.tiempos.camara_contexto_delay1\nconfig_tiempos.push({ \"parametro\": \"camara_contexto_delay1\", \"valor\": read })\nflow.set(\"camara_contexto_delay1\", read);\nread = config.tiempos.camara_contexto_delay2\nconfig_tiempos.push({ \"parametro\": \"camara_contexto_delay2\", \"valor\": read })\nflow.set(\"camara_contexto_delay2\", read);\n\n//---------------------------------------Lectura de Matricula-----------------------------------------------------------------------\nread = config.tiempos.time_max_2_bascula\nconfig_tiempos.push({ \"parametro\": \"time_max_2_bascula\", \"valor\": read })\nflow.set(\"time_max_2_bascula\", read);\nread = config.tiempos.wait_time_to_send_plate\nconfig_tiempos.push({ \"parametro\": \"wait_time_to_send_plate\", \"valor\": read })\nflow.set(\"wait_time_to_send_plate\", read);\nread = config.tiempos.max_wait_time_to_send_plate\nconfig_tiempos.push({ \"parametro\": \"max_wait_time_to_send_plate\", \"valor\": read })\nflow.set(\"max_wait_time_to_send_plate\", read);\nread = config.tiempos.max_time_bascula_sensor\nconfig_tiempos.push({ \"parametro\": \"max_time_bascula_sensor\", \"valor\": read })\nflow.set(\"max_time_bascula_sensor\", read);\nread = config.tiempos.time_to_snapshot\nconfig_tiempos.push({ \"parametro\": \"time_to_snapshot\", \"valor\": read })\nflow.set(\"time_to_snapshot\", read);\nflow.set(\"plate_sent\", false);\nflow.set(\"anpr0_flag\", false);\n\n//----------------------------------------Flags evento bascula---------------------------------------------------------------------------------------------\nflow.set(\"peso_trigger_OFF\", true);\nflow.set(\"peso_trigger_ON\", false);\n\n//-------------------------------------------------------------------------------------------------------------------------------------\n\nread = config.conexion.supervisor\nconfig_conex.push({ \"parametro\": \"supervisor\", \"valor\": read })\nflow.set(\"supervisor\", read);\n\n//---------------------------------------- Flags edicion de matricula ---------------------------------------------------------------------------------------------\nflow.set(\"badplate\", false) // inicializa flag de solicitu de modificación de matricula\nflow.set(\"prechar\", \"*\") // inicializa variable con caracter de prefijo para el $watch del nodo display de edicion de matricula\n\nflow.set(\"config_general\", config_general)\nflow.set(\"config_tiempos\", config_tiempos)\nflow.set(\"config_mensajes\", config_mensajes)\nflow.set(\"config_conex\", config_conex)\nflow.set(\"config_camara\", config_camara)\nflow.set(\"config_sensor\", config_sensor)\n\nflow.set(\"tiposDatosGlobal\", tiposOriginales) // Pasamos los datos de cada tipo a una variable de flow\n//notese que estos datos son leidos del archivo, sin hacerles transformacion a objeto.\n\n// Vamos a ver si tenemos que aplicar algun tipo de configuracion particular al tipo que se ha seleccionado en la configuracion (Tipo_Configuracion)\nconst tipo = parseInt(config.general.Tipo_Configuracion, 10); // asegura que el numero es integer\n\nif (tipo > 0 && tipo <= 9) {\n const tipoDatos = config.tipos[tipo] || [];\n\n tipoDatos.forEach(item => {\n let valor = item.valor;\n\n if (valor === \"true\") valor = true;\n if (valor === \"false\") valor = false;\n\n flow.set(item.parametro, valor); // sobre escribimos el valor configurado con la configuracion que este definida en el tipo.\n });\n}\n\n\n\n//Esto es exclusivo para el dispositivo de desarrollo para poder apagar el equipo dandole tres veces al titulo TARJETA ID\nflow.set(\"shut_flag\", false);\nflow.set(\"shut_count\",0)\nreturn;\n\n\n//*********************************************************** FUNCIONES **************************************************/\nfunction toObject(array) {\n const obj = {};\n array.forEach(el => {\n obj[el.parametro] = el.valor;\n });\n return obj;\n}\n",
+ "func": "const config = JSON.parse(msg.payload);\nmsg ={}; // clear msg object\nlet read;\nlet config_general = []\nlet config_tiempos = []\nlet config_mensajes = []\nlet config_sensor = []\nlet config_camara = []\nlet config_conex = []\nlet config_tipos = []\n\nconfig.general = toObject(config.general);\nconfig.camara = toObject(config.camara);\nconfig.conexion = toObject(config.conexion);\nconfig.sensores = toObject(config.sensores);\nconfig.mensajes = toObject(config.mensajes);\nconfig.tiempos = toObject(config.tiempos);\n\nconst tiposOriginales = config.tipos || {};\n\n\n// Aseguramos que cada tipo esté como array vacío si no tiene nada\nfor (let i = 1; i <= 6; i++) {\n if (!Array.isArray(tiposOriginales[i])) {\n tiposOriginales[i] = [];\n }\n}\nflow.set(\"tiposDatosGlobal\", tiposOriginales);\n\nconfig.tipos = tiposOriginales;\n\n\n\n//**************************** Parametros de Validacion OBLIGATORIOS para PESADA FINALIZADA ***************************************\n// Estos parametros pueden ser: QR / RFID / Boton Validacion / Detector Vehiculo \n//*********************************************************************************************************************************\n/*read = config.QR_obligatorio;\nconfig_general.push({ \"parametro\": \"QR_obligatorio\", \"valor\": read })\nflow.set(\"QR_obligatorio\", read);\nread = config.RFID_obligatorio;\nconfig_general.push({ \"parametro\": \"RFID_obligatorio\", \"valor\": read })\nflow.set(\"RFID_obligatorio\", read);\n\nread = config.general.funcion_totem;\nconfig_general.push({ \"parametro\": \"funcion_totem\", \"valor\": read })\nflow.set(\"funcion_totem\", read);\n\nread = config.general.identificacion_esp;\nconfig_general.push({ \"parametro\": \"identificacion_esp\", \"valor\": read })\nflow.set(\"identificacion_esp\", read);\n\nread = config.tiempos.timer1;\nconfig_tiempos.push({ \"parametro\": \"timer1\", \"valor\": read })\nflow.set(\"timer1\", read);\n\n*/\n\nread = config.general.Tipo_Configuracion;\nconfig_general.push({ \"parametro\": \"Tipo_Configuracion\", \"valor\": read })\nflow.set(\"Tipo_Configuracion\", read);\n\nread = config.general.ID_obligatorio;\nconfig_general.push({ \"parametro\": \"ID_obligatorio\", \"valor\": read })\nflow.set(\"ID_obligatorio\", read);\n\nread = config.general.salida_ID_obligatorio;\nconfig_general.push({ \"parametro\": \"salida_ID_obligatorio\", \"valor\": read })\nflow.set(\"salida_ID_obligatorio\", read);\n\nread = config.general.detector_obligatorio;\nconfig_general.push({ \"parametro\": \"detector_obligatorio\", \"valor\": read })\nflow.set(\"detector_obligatorio\", read);\n\nread = config.general.boton_obligatorio;\nconfig_general.push({ \"parametro\": \"boton_obligatorio\", \"valor\": read })\nflow.set(\"boton_obligatorio\", read);\nread = config.general.firma_obligatoria;\nconfig_general.push({ \"parametro\": \"firma_obligatoria\", \"valor\": read })\nflow.set(\"firma_obligatoria\", read);\nread = config.general.matricula_obligatoria;\nconfig_general.push({ \"parametro\": \"matricula_obligatoria\", \"valor\": read })\nflow.set(\"matricula_obligatoria\", read);\n\n\n\n//==================================================================================================================================\nread = config.general.edicion_matricula;\nconfig_general.push({ \"parametro\": \"edicion_matricula\", \"valor\": read })\nflow.set(\"edicion_matricula\", read); // Habilita la edicion de matricula\n\nread = config.general.botonsalida_activo;\nconfig_general.push({ \"parametro\": \"botonsalida_activo\", \"valor\": read })\nflow.set(\"botonsalida_activo\", read); // Permite poner boton de salida\n\nread = config.general.menu_activo;\nconfig_general.push({ \"parametro\": \"menu_activo\", \"valor\": read })\nflow.set(\"menu_activo\", read); // Permite poner los menus de contratacion\n\n/*\nread = config.general.firma_habilitada;\nconfig_general.push({ \"parametro\": \"firma_habilitada\", \"valor\": read })\nflow.set(\"firma_habilitada\", read); // Habilita la edicion de firma\n*/\n\nread = config.general.barrera_habilitada;\nconfig_general.push({ \"parametro\": \"barrera_habilitada\", \"valor\": read })\nflow.set(\"barrera_habilitada\", read); // Habilita el uso de barrera\n\nread = config.general.mostrar_ubicacion\nconfig_general.push({ \"parametro\": \"mostrar_ubicacion\", \"valor\": read })\nflow.set(\"mostrar_ubicacion\", read);\n\nread = config.general.switch_2_Totem_page;\nflow.set(\"switch_2_Totem_page\", read); // si igual a true cambia a pagina principal del totem siempre que se active la bascula\n// Con esto aseguramos que si queda abierta una ventana de configuracion se pueda quitar automaticamente\nconfig_general.push({ \"parametro\": \"switch_2_Totem_page\", \"valor\": read })\n\n//flow.set(\"peso\", read); // crea variable para recibir peso del supervisor\n\nread = parseInt(config.general.peso_minimo); // peso minimo para utilizado para indicar cuando hay vehiculo en la balanza o no\nconfig_general.push({ \"parametro\": \"peso_minimo\", \"valor\": read })\nflow.set(\"peso_minimo\", read);\n\nread = config.general.formatoPais; // peso minimo para utilizado para indicar cuando hay vehiculo en la balanza o no\nconfig_general.push({ \"parametro\": \"formatoPais\", \"valor\": read })\nflow.set(\"formatoPais\", read);\n\n//------------------- TOTEM MASTER tiempo de confirmacion -------------------------------------\nread = config.tiempos.confirm_master_time;\nconfig_tiempos.push({ \"parametro\": \"confirm_master_time\", \"valor\": read })\nflow.set(\"confirm_master_time\", read);\n//---------------------------------------------------------------------------------------------\n\n\nread = config.general.audio_level;\nconfig_general.push({ \"parametro\": \"audio_level\", \"valor\": read })\nflow.set(\"audio_level\", read);\n//-------------------------------------------------------\nread = config.general.mante_code_RFID; //codigo RFID para pasar a pantalla de mantenimiento\nconfig_general.push({ \"parametro\": \"mante_code_RFID\", \"valor\": read })\nflow.set(\"mante_code_RFID\", read)\nread = config.general.mante_code_QR; //codigo QR para pasar a pantalla de mantenimiento\nconfig_general.push({ \"parametro\": \"mante_code_QR\", \"valor\": read })\nflow.set(\"mante_code_QR\", read)\n\n//------------------------------- MENSAJES -------------------------\nread = config.tiempos.tiempo_mensaje;\nconfig_tiempos.push({ \"parametro\": \"tiempo_mensaje\", \"valor\": read })\nflow.set(\"tiempo_mensaje\", read);\n\nread = config.tiempos.relay2_pulse // duración del pulso generado en el relay 2 al terminar el pesaje para abrir barrera\nconfig_tiempos.push({ \"parametro\": \"relay2_pulse\", \"valor\": read })\nflow.set(\"relay2_pulse\", read);\n\nread = config.mensajes.mensaje2 // no se usa\nconfig_mensajes.push({ \"parametro\": \"mensaje2\", \"valor\": read })\nflow.set(\"mensaje2\", read);\nread = config.mensajes.mensaje1 // no se usa\nconfig_mensajes.push({ \"parametro\": \"mensaje1\", \"valor\": read })\nflow.set(\"mensaje1\", read);\nread = config.general.init_screen\nconfig_general.push({ \"parametro\": \"init_screen\", \"valor\": read })\nflow.set(\"init_screen\", read);\n\nread = config.mensajes.no_pendiente\nconfig_mensajes.push({ \"parametro\": \"no_pendiente\", \"valor\": read })\nflow.set(\"no_pendiente\", read);\nread = config.mensajes.pendiente\nconfig_mensajes.push({ \"parametro\": \"pendiente\", \"valor\": read })\nflow.set(\"pendiente\", read);\n\n//-------------------------------------------------------\nread = config.general.totem_serial // serial asignado a este dispositivo\nconfig_general.push({ \"parametro\": \"totem_serial\", \"valor\": read })\nflow.set(\"totem_serial\", read);\n\n//---------------------------------------- Parametros por defecto del boton de salida para VALIDACION -----------------------------------------------------------\nread = config.mensajes.botonsalida_txt_def\nconfig_mensajes.push({ \"parametro\": \"botonsalida_txt_def\", \"valor\": read })\nflow.set(\"botonsalida_txt_def\", read)\nread = config.general.botonsalida_color_def\nconfig_general.push({ \"parametro\": \"botonsalida_color_def\", \"valor\": read })\nflow.set(\"botonsalida_color_def\", read)\nread = config.general.botonsalida_txt_color_def\nconfig_general.push({ \"parametro\": \"botonsalida_txt_color_def\", \"valor\": read })\nflow.set(\"botonsalida_txt_color_def\", read)\nread = config.mensajes.botonsalida_mensaje1\nconfig_mensajes.push({ \"parametro\": \"botonsalida_mensaje1\", \"valor\": read })\nflow.set(\"botonsalida_mensaje1\", read)\nread = config.mensajes.botonsalida_mensaje1_def\nconfig_mensajes.push({ \"parametro\": \"botonsalida_mensaje1_def\", \"valor\": read })\nflow.set(\"botonsalida_mensaje1_def\", read)\n\n//----------------------------------------- Textos Predefinidos -------------------------------------------------------------------------\nread = config.mensajes.men_pesaje_listo;\nconfig_mensajes.push({ \"parametro\": \"men_pesaje_listo\", \"valor\": read })\nflow.set(\"men_pesaje_listo\", read);\nread = config.mensajes.men_peso_estable;\nconfig_mensajes.push({ \"parametro\": \"men_peso_estable\", \"valor\": read })\nflow.set(\"men_peso_estable\", read);\nread = config.mensajes.men_identificacion;\nconfig_mensajes.push({ \"parametro\": \"men_identificacion\", \"valor\": read })\nflow.set(\"men_identificacion\", read);\nread = config.mensajes.men_salida;\nconfig_mensajes.push({ \"parametro\": \"men_salida\", \"valor\": read })\nflow.set(\"men_salida\", read);\nread = config.mensajes.id_titulo_matricula;\nconfig_mensajes.push({ \"parametro\": \"id_titulo_matricula\", \"valor\": read })\nflow.set(\"id_titulo_matricula\", read);\nread = config.mensajes.id_titulo_id;\nconfig_mensajes.push({ \"parametro\": \"id_titulo_id\", \"valor\": read })\nflow.set(\"id_titulo_id\", read);\nread = config.mensajes.id_leido;\nconfig_mensajes.push({ \"parametro\": \"id_leido\", \"valor\": read })\nflow.set(\"id_leido\", read);\nread = config.mensajes.id_no_leido;\nconfig_mensajes.push({ \"parametro\": \"id_no_leido\", \"valor\": read })\nflow.set(\"id_no_leido\", read);\n\n//===================================================CONEXION / CAMARA / SENSOR =====================================================\n//====================================================================================================================================\n\n\nread = config.conexion.modo_totem;\nconfig_conex.push({ \"parametro\": \"modo_totem\", \"valor\": read })\nflow.set(\"modo_totem\", read); // Modo de funcionamiento del totem\n\n\n//-----------------------------Gestion de IP fija / IP DHCP------------------------------------------------------\nvar ipdevice_flag = false // variables temporales para saber si hay cambios en las ip\nvar iprouter_flag = false\nread = config.conexion.ipdevice // direccion IP del dispositivo\nconfig_conex.push({ \"parametro\": \"ipdevice\", \"valor\": read })\nif (flow.get(\"ipdevice\") != read) {\n flow.set(\"ipdevice\", read);\n ipdevice_flag = true;\n}\nread = config.conexion.iprouter // direccion IP del router\nconfig_conex.push({ \"parametro\": \"iprouter\", \"valor\": read })\nif (flow.get(\"iprouter\") != read) {\n flow.set(\"iprouter\", read);\n iprouter_flag = true;\n}\nread = config.conexion.dhcp_flag // flag del DHCP\nconfig_conex.push({ \"parametro\": \"dhcp_flag\", \"valor\": read })\nif (flow.get(\"dhcp_flag\") != read) {\n flow.set(\"dhcp_flag\", read); // el dhcp_flag ha cambiado\n if (flow.get(\"dhcp_flag\")) {\n node.send([null, { payload: \". /home/trypton/scripts/enable_dhcp.sh\" }])\n }\n else {\n node.send([null, { payload: \". /home/trypton/scripts/enable_ipstatic.sh \" + flow.get(\"ipdevice\") + \"/24 \" + flow.get(\"iprouter\") }])\n }\n}\nelse { // el dhcp_flag no ha cambiado\n if (!flow.get(\"dhcp_flag\")) {\n if (ipdevice_flag || iprouter_flag) {\n node.send([null, { payload: \". /home/trypton/scripts/enable_ipstatic.sh \" + flow.get(\"ipdevice\") + \"/24 \" + flow.get(\"iprouter\") }])\n }\n }\n else {\n node.send([null, { payload: \". /home/trypton/scripts/enable_dhcp.sh\" }])\n }\n}\nflow.set(\"dhcpname_on\", \"IP Fija\") // texto que sale en el boton de la pantalla de mantenimiento\nflow.set(\"dhcpname_off\", \"DHCP\")\n//-----------------------------------Websocket IP--------------------------------------------------------------------------------------\nread = config.conexion.websocket_puerto // direccion IP del websocket del supervisor\nconfig_conex.push({ \"parametro\": \"websocket_puerto\", \"valor\": read })\nflow.set(\"websocket_puerto\", read);\nread = config.conexion.websocket_url\nconfig_conex.push({ \"parametro\": \"websocket_url\", \"valor\": read })\nif (flow.get(\"websocket_url\") != read) {\n flow.set(\"websocket_url\", read);\n node.send([{ payload: read + \" servidor.com\" }, null])\n}\n//----------------------------------- ENVIO DE MOVIMIENTOS --------------------------------------------------------------------------------------\nread = config.conexion.movimientosxmqtt;\nconfig_conex.push({ \"parametro\": \"movimientosxmqtt\", \"valor\": read })\nflow.set(\"movimientosxmqtt\", read); // Modo de envio de movimientos\n\nread = config.conexion.movimientosxapi;\nconfig_conex.push({ \"parametro\": \"movimientosxapi\", \"valor\": read })\nflow.set(\"movimientosxapi\", read); // Modo de envio de movimientos\n\n//----------------------------------- DEFINICION DEL BROKER DE MQTT --------------------------------------------------------------------------------------\n/*\nread = config.conexion.broker_url;\nconfig_conex.push({ \"parametro\": \"broker_url\", \"valor\": read })\nflow.set(\"broker_url\", read); // direccion del broker\n\nread = config.conexion.broker_port;\nconfig_conex.push({ \"parametro\": \"broker_port\", \"valor\": read })\nflow.set(\"broker_port\", read); // puerto del broker\n\nread = config.conexion.broker_username;\nconfig_conex.push({ \"parametro\": \"broker_username\", \"valor\": read })\nflow.set(\"broker_username\", read); // username del broker\n\nread = config.conexion.broker_pass;\nconfig_conex.push({ \"parametro\": \"broker_pass\", \"valor\": read })\nflow.set(\"broker_pass\", read); // password del broker\n*/\n/*\n//-------------------------------------------------- URL de la API de URBASER(Trypton) ------------------------------------------------------------------------------\nread = config.conexion.url_API;\nconfig_conex.push({ \"parametro\": \"url_API\", \"valor\": read })\nflow.set(\"url_API\", read); // Modo de funcionamiento del totem\n*/\nflow.set(\"semaforo\", \"green\")\n\n//------------------------------------Lector de QR / RF----------------------------------------------------------\nread = config.sensores.tipo_de_lector\nconfig_sensor.push({ \"parametro\": \"tipo_de_lector\", \"valor\": read })\nflow.set(\"tipo_de_lector\", read); //tipo de lector QR / RF\nread = config.sensores.rfid_invertido\nconfig_sensor.push({ \"parametro\": \"rfid_invertido\", \"valor\": read })\nflow.set(\"rfid_invertido\", read);\nflow.set(\"lector_activo\", true) // activamos el lector\nflow.set(\"ID_enviado\", false) // variable para controlar un solo envio de RFID / QR\n\n//-------------------------------------sensor de distancia-------------------------------------------------------\nread = config.sensores.sensor_distancia_local\nconfig_sensor.push({ \"parametro\": \"sensor_distancia_local\", \"valor\": read })\nflow.set(\"sensor_distancia_local\", read);\nread = config.sensores.sensor_distancia_remoto\nconfig_sensor.push({ \"parametro\": \"sensor_distancia_remoto\", \"valor\": read })\nflow.set(\"sensor_distancia_remoto\", read);\nflow.set(\"distance_flag_remote\", false)\nread = config.sensores.distance_min\nconfig_sensor.push({ \"parametro\": \"distance_min\", \"valor\": read })\nflow.set(\"distance_min\", read);\nread = config.sensores.min_cnt_in_ok\nconfig_sensor.push({ \"parametro\": \"min_cnt_in_ok\", \"valor\": read })\nflow.set(\"min_cnt_in_ok\", read);\nread = config.sensores.min_cnt_out_ok\nconfig_sensor.push({ \"parametro\": \"min_cnt_out_ok\", \"valor\": read })\nflow.set(\"min_cnt_out_ok\", read);\nflow.set(\"dist_in_counter\", 0);\nflow.set(\"dist_out_counter\", 0);\n\n//---------------------------------------Totems y Camara------------------------------------------------------------------------------\nread = config.conexion.totem_qty\nconfig_conex.push({ \"parametro\": \"totem_qty\", \"valor\": read })\nflow.set(\"totem_qty\", read);\nread = config.conexion.tipobascula\nconfig_conex.push({ \"parametro\": \"tipobascula\", \"valor\": read })\nflow.set(\"tipobascula\", read);\nread = config.conexion.totem_id_remoto\nconfig_conex.push({ \"parametro\": \"totem_id_remoto\", \"valor\": read })\nflow.set(\"totem_id_remoto\", read);\nread = config.conexion.totem_id\nconfig_conex.push({ \"parametro\": \"totem_id\", \"valor\": read })\nflow.set(\"totem_id\", read);\nread = config.conexion.numero_vial;\nconfig_conex.push({ \"parametro\": \"numero_vial\", \"valor\": read })\nflow.set(\"numero_vial\", read);\nread = config.conexion.ip_totem_pareja\nconfig_conex.push({ \"parametro\": \"ip_totem_pareja\", \"valor\": read })\nflow.set(\"ip_totem_pareja\", read);\nread = config.conexion.envia_mat_img\nconfig_conex.push({ \"parametro\": \"envia_mat_img\", \"valor\": read })\nflow.set(\"envia_mat_img\", read);\n\nread = config.camara.camara_matricula\nconfig_camara.push({ \"parametro\": \"camara_matricula\", \"valor\": read })\nflow.set(\"camara_matricula\", read);\nread = config.camara.camaraID\nconfig_camara.push({ \"parametro\": \"camaraID\", \"valor\": read })\nflow.set(\"camaraID\", read);\nread = config.camara.camara_IP\nconfig_camara.push({ \"parametro\": \"camara_IP\", \"valor\": read })\nflow.set(\"camara_IP\", read);\nread = config.camara.camara_contexto\nconfig_camara.push({ \"parametro\": \"camara_contexto\", \"valor\": read })\nflow.set(\"camara_contexto\", read);\nread = config.camara.camara_contexto_IP\nconfig_camara.push({ \"parametro\": \"camara_contexto_IP\", \"valor\": read })\nflow.set(\"camara_contexto_IP\", read);\nread = config.tiempos.camara_contexto_delay1\nconfig_tiempos.push({ \"parametro\": \"camara_contexto_delay1\", \"valor\": read })\nflow.set(\"camara_contexto_delay1\", read);\nread = config.tiempos.camara_contexto_delay2\nconfig_tiempos.push({ \"parametro\": \"camara_contexto_delay2\", \"valor\": read })\nflow.set(\"camara_contexto_delay2\", read);\n\n//---------------------------------------Lectura de Matricula-----------------------------------------------------------------------\nread = config.tiempos.time_max_2_bascula\nconfig_tiempos.push({ \"parametro\": \"time_max_2_bascula\", \"valor\": read })\nflow.set(\"time_max_2_bascula\", read);\nread = config.tiempos.wait_time_to_send_plate\nconfig_tiempos.push({ \"parametro\": \"wait_time_to_send_plate\", \"valor\": read })\nflow.set(\"wait_time_to_send_plate\", read);\nread = config.tiempos.max_wait_time_to_send_plate\nconfig_tiempos.push({ \"parametro\": \"max_wait_time_to_send_plate\", \"valor\": read })\nflow.set(\"max_wait_time_to_send_plate\", read);\nread = config.tiempos.max_time_bascula_sensor\nconfig_tiempos.push({ \"parametro\": \"max_time_bascula_sensor\", \"valor\": read })\nflow.set(\"max_time_bascula_sensor\", read);\nread = config.tiempos.time_to_snapshot\nconfig_tiempos.push({ \"parametro\": \"time_to_snapshot\", \"valor\": read })\nflow.set(\"time_to_snapshot\", read);\nflow.set(\"plate_sent\", false);\nflow.set(\"anpr0_flag\", false);\n\n//----------------------------------------Flags evento bascula---------------------------------------------------------------------------------------------\nflow.set(\"peso_trigger_OFF\", true);\nflow.set(\"peso_trigger_ON\", false);\n\n//-------------------------------------------------------------------------------------------------------------------------------------\n\nread = config.conexion.supervisor\nconfig_conex.push({ \"parametro\": \"supervisor\", \"valor\": read })\nflow.set(\"supervisor\", read);\n\n//---------------------------------------- Flags edicion de matricula ---------------------------------------------------------------------------------------------\nflow.set(\"badplate\", false) // inicializa flag de solicitu de modificación de matricula\nflow.set(\"prechar\", \"*\") // inicializa variable con caracter de prefijo para el $watch del nodo display de edicion de matricula\n\nflow.set(\"config_general\", config_general)\nflow.set(\"config_tiempos\", config_tiempos)\nflow.set(\"config_mensajes\", config_mensajes)\nflow.set(\"config_conex\", config_conex)\nflow.set(\"config_camara\", config_camara)\nflow.set(\"config_sensor\", config_sensor)\n\nflow.set(\"tiposDatosGlobal\", tiposOriginales) // Pasamos los datos de cada tipo a una variable de flow\n//notese que estos datos son leidos del archivo, sin hacerles transformacion a objeto.\n\n// Vamos a ver si tenemos que aplicar algun tipo de configuracion particular al tipo que se ha seleccionado en la configuracion (Tipo_Configuracion)\nconst tipo = parseInt(config.general.Tipo_Configuracion, 10); // asegura que el numero es integer\n\nif (tipo > 0 && tipo <= 9) {\n const tipoDatos = config.tipos[tipo] || [];\n\n tipoDatos.forEach(item => {\n let valor = item.valor;\n\n if (valor === \"true\") valor = true;\n if (valor === \"false\") valor = false;\n\n flow.set(item.parametro, valor); // sobre escribimos el valor configurado con la configuracion que este definida en el tipo.\n });\n}\n\n\n\n//Esto es exclusivo para el dispositivo de desarrollo para poder apagar el equipo dandole tres veces al titulo TARJETA ID\nflow.set(\"shut_flag\", false);\nflow.set(\"shut_count\",0)\nreturn;\n\n\n//*********************************************************** FUNCIONES **************************************************/\nfunction toObject(array) {\n const obj = {};\n array.forEach(el => {\n obj[el.parametro] = el.valor;\n });\n return obj;\n}\n",
"outputs": 2,
"timeout": 0,
"noerr": 0,
@@ -5884,7 +5891,7 @@
"6f9cc9fc71e8ca71"
],
"x": 735,
- "y": 1380,
+ "y": 1360,
"wires": []
},
{
@@ -5909,8 +5916,8 @@
"id": "53335688d117ec96",
"type": "comment",
"z": "953e8740401d175c",
- "name": "Version 1.45 de bascula autonoma",
- "info": "**Version 1.45** 17/05/2026\nSe ha agregado codigo en el nodo \"Envia Matricula\" y en el nodo \"Convert to B64\" para en caso en que el flag \"envia_mat_img\" este en true enviar la matricula,\nla imagen de la matricula y la imagen de contexto al supervisor en el momento que se obtengan con la finalidad de que el supervisor a su vez la envie en\nbroadcasting para que los interesados puedan obtener en tiempo real esta informaciones y plasmarlas sobre una pantalla. La idea es que se envia al servidor \npara que disponga de esa informacion en alguna pagina web\nLa trama que se envia al supervisor en el caso de la matricula es:\n{payload: { device: \"supervisor\", accion: \"lastplate\", data: {numero_vial: 2, totem_id: \"totem_2\", matricula: \"1234ABC\", imagen: imgBase64}}}\nen el caso de la imagen de contexto es:\n{payload: { device: \"supervisor\", accion: \"lastcontext\", data: {numero_vial: 2, totem_id: \"totem_2\", imagen_contexto: imgBase64}}}\nAmbas tramas se envian al momento de recibir las imagenes en el Totem.\nPor su lado el Supervisor envia las siguientes tramas para matricula y para contexto:\n{payload:{sender:\"supervisor\", device:\"servidor\", accion:\"lastplate\", data:{totem_id:\"totem_2\", numero_vial:2, matricula:\"1234ABC\", imagen:imgBase64}}}\n{payload:{sender:\"supervisor\", device:\"servidor\", accion:\"lastcontext\", data:{totem_id:\"totem_2\", numero_vial:2, imagen_contexto:imgBase64}}}\nEl flag \"envia_mat_img\" es configurable a traves del menu de configuracion en el apartado Comunicacion.\n\nSe agrego un nodo \"estado semaforo\" antes de accionar el semaforo fisicamente, la idea de este nodo es que envie el estado del semaforo via websocket cada\nvez que este cambia de estado, de esta forma podemos mantener un estado tiempo real en cualquier sitio remoto con solo observar esta trama. El envio se hace\nal supervisor que es quien sirve el websocket. La trama es la siguiente: \n{device:\"supervisor\", accion: \"semaforo_status\", status:{totem_id:flow.get(\"totem_id\"), numero_vial:flow.get(\"numero_vial\"), semaforo:semaforo}}\nCuando llegue al supervisor este enviara una trama al servidor asi (esta trama va en broadcasting osea que fisicamente llega a todos los clientes de websocket):\n{payload:{sender:\"supervisor\", device:\"servidor\", accion:\"update_semaforo\", semaforo:{totem_id:totem, numero_vial:vial, semaforo:semaforo}}}\n\n**Version 1.44** 14/05/2026\nPara asegurar que las basculas de un solo totem se usan para su proposito (entrada / salida) se ha introducido un nuevo parametro configurable para \ndefinir el proposito de la bascula. Esto evitara que una matricula que no tiene transito salga por la bascula, igualmente esta la opcion \nde si un vehiculo ya tiene transito no pueda utilizar la bascula de entrada. En caso que queramos anular esta funcionalidad solo hay que \nconfigurar el parametro con el valor \"ambos\". Todo esto es valido solamente cuando tenemos un solo totem en la bascula.\n\n**Version 1.43** 11/05/2026\nHemos introducido un cambio significativo en la gestion del ID. Hasta ahora ele flag definitivo de ID_ok = !ID_obligatorio || ID_verificado Lo que quiere decir \nque el ID esta ok cuando el ID_obligatorio esta en false es decir no es obligatorio o cuando si es obligatorio y el ID_verificado esta en true, es decir \nesta autorizado para entrar. Pero si el ID_obligatorio esta en false y se presenta un ID cualquiera vamos a obtener ID_ok = true es decir esta autorizado.\nHemos introducido un nuevo estado que es ID_presentado y ahora la condicion es ID_ok = (!ID_obligatorio && !ID_presentado) || ID_verificado es decir que \nID_ok depende de ID_verificado si ID_obligatorio esta en true o si ID_presentado esta en true. En caso de que ID_obligatorio este en false y ID_presentado este\ntambien en false entonce ID_ok no interfiere en la autorizacion es decir esta en true, todo depende del menu de seleccion si existe.\nPara esto hemos cambiado en el nodo de \"Analisis del modo de Operacion\" linea 59 \"let ID_ok = !ID_obligatorio || ID_verificado\" por la nueva\nlet ID_ok = (!ID_obligatorio && !ID_presentado) || ID_verificado;\nAdicionalmernte en el nodo QR / RFID hemos activado el ID_presentado cada vez que leemos un ID. Este parametro se resetea en el nodo de peso cada vez que hay una nueva pesada\n\nEn el nodo de matricula (linea 27) hacemos el cambio del flag ID_obligatorio al flag salida_ID_obligatorio cuando el movimiento es final. De esta forma ID_obligatorio aplica a la entrada \nexclusivamente y salida_ID_obligatorio aplica a la salida solamente.\nEn el nodo QR/RFID hemos agregado la puesta a cero del flag de QR(linea 67) y del RFID(linea 126) cuando se trata de un ID incorrecto para que el usuario pueda volver a colocar otro ID.\n\n\n**Version 1.42** 29/04/2026\nEn el nodo \"Analisis\" en la linea 116 hemos puesto un timer que espera unos segundos antes de sacar la notificacion de ubicacion. Esto se hace para esperar a que la notificacion anterior en caso de existir\npermanezca un tiempo y en todo caso para que esta sea la ultima notificacion que quede en pantalla hasta que el vehiculo abandone la bascula. \nEliminamos de la pantalla el mensaje Acerque QR o Tarjeta en caso de recibir una lista de menu. Esto lo hacemos en el nodo \"check json\".\nEn el nodo \"Envio de Mensajes\" (linea 65) eliminamos las notificaciones que haya al final del movimiento (final de pesada) salvo si la notificacion es de Ubicacion.\nSe hicieron cambios en index.html y en index.js del uibuilder /totem/ para incluir en el menu de Tipo de Configuracion un boton (LISTA DE PARAMETROS) que nos permita visualizar todos los parametros que podemos incluir en cualquiera de los tipos de configuracion\nSe introdujo un chequeo en el nodo \"QR/RFID\" en la linea 37 para eliminar el boton de salida (simular que fue pulsado) cuando se recibe un QR valido durante el movimiento final. Lo mismo hacemos mas abajo en la recepcion de RFID.\nEn la parte RFID dado que luego de recibir la tarjeta validada en BD todavia necesitamos validar si la matricula asociada a la tarjeta tiene vehiculo en transito, esto hace que el estado movimiento = inicial puede permanecer por mas tiempo (mientras se chequea si hay transito) por lo tanto en el chequeo \ntenemos que meter la variable \"matricula_revisada\" como requisito para avanzar ya que es quien nos indica si el estado del movimiento ya es definitivo. Recordemos que este chequeo solo lo queremos hacer durante el movimiento final, es decir cuando el vehiculo esta cerrando toda la pesada.\n\n\n**Version 1.41** 1/04/2026\n- Dado que puede darse el caso que la camara de contexto no responda en un determinado momento a la solicitud de imagen, se han introducido unas condiciones para tratar de obtener\nla imagen de contexto en caso de fallo temporal. El metodo resumido es el siguiente: Cuando estamos seguros que el vehiculo esta correctamente posicionado\nen la bascula (peso estable) hacemos una solicitud y marcamos un estado (\"waiting1\"), esperamos por la imagen un tiempo definido en la variable (\"camara_contexto_delay1\") \nencaso de no llegar hacemos una segunda solicitud y marcamos el estado (\"waiting2\") y esperamos por la imagen un tiempo definido en la variable (\"camara_contexto_delay2\").\nMientras tanto el semaforo esta en rojo esperando la imagen de contexto, suponiendo que todo lo demas esta ok. Al cabo del ultimo tiempo, marcamos el nuevo estado\nen funcion de lo sucedido, \"ok\" si recibimos la imagen \"fail\" si no la hemos recibido. En cualquiera de los dos casos el semaforo pasa a verde y se continua con la pesada\nEn caso de no tener imagen de contexto, el nombre de la imagen ira vacio (\"\") al igual que la imagen.\n\n**Version 1.4** 25/03/2026\n- Debido a nuevo requerimiento se introduce la opcion (configurable) de tener una camara de contexto en la bascula. Esta camara en caso de estar\nhabilitada en la configuracion tomara una imagen en el momento en que el camion este completamente en la bascula, para ello hemos introducido un codigo en el nodo\n\"estable\" que es donde se hace la deteccion del camion completamente en la bascula. Posteriormente en el nodo \"Analisis del modo de Operacion\" es\ndonde verificamos que la imagen fue tomada y la colocamos en el registro que se esta haciendo para generar el movimiento correspondiente. El Grupo \n\"CAMARA CONTEXTO\" posee los nodos de solicitud de imagen y de recepcion de la misma. La configuracion de IP de la camara se hace en la pantalla\nde configuracion al igual que su habilitacion en el sistema.\n- Como herramienta de ayuda para saber si el Totem esta en capacidad de solicitar y de recibir la imagen de contexto enviada por la camara\nse ha incluido una funcion en el menu de configuracion -> Pruebas del sistema -> Pedir Snapshot de contexto de forma que el usuario pueda visualizar \nla imagen actual que la camara esta enviando y pueda de esa forma confirmar el correcto funcionamiento de la conexión y de los equipos.\n\n**Version 1.3.2** \n- Eliminado la inicializacion en el nodo peso del flag distance_flag_SET del detector de vehiculos. Esto ocasionaba problemas en si \ncoincidia que estaba contando los pulsos de salida y antes de finalizar las bascula se ponia en peso < pmin. En esa situacion el detector\nse quedaba bloqueado in poder indicar detector OFF.\n\n- Hemos colocado un codigo de dos lineas para eliminar el boton del menu activo \"COMPLETAR INFO\" en caso que se presente una tarjeta o un codigo QR. \nEsto lo hicimos en el nodo \"Analisis del modo de Operacion\" en la linea 70 donde chequeamos si estamos en movimiento inicial.\n\n- Corregido un \"error\" que no permitia cerrar el movimiento inicial cuando se pasaba una tarjeta si teniamos el menu activo y la firma obligatoria. \nSe agrego una condicion (\"ID_verificado\") en la condicion global para llamar a la firma. Esto es en el nodo \"Analisis de Operacion\" en las primeras lineas\nif (flow.get(\"firma_obligatoria\") && !flow.get(\"firma_flag\") && !flow.get(\"firma_ok_flag\") && !flow.get(\"supervisor\") && (!flow.get(\"menu_activo\") || (flow.get(\"menu_activo\") && (flow.get(\"menu_seleccionado_flag\") || ID_verificado)))) \nCon esto permite continuar con la firma en caso que tengamos menu_activo y firma obligatoria y entremos con tarjeta o con codigo QR.\n\n**Version 1.3.1**\n- Hemos colocado una opcion mas en el menu de configuración en \"Pruebas del Sistema\" -> \"Probar Sensor\". Esto permite visualizar la salida del valor\nde la distancia que esta midiendo el sensor cada segundo. Para que el medidor no este continuamente inundando el configurador con el dato de distancia\nhemos colocado un switch el cual solo deja pasar ese dato cuando se activa el menu, lo inhabilita cuando se sale del menu.\n\n- Hemos puesto el flag flow.set(\"RFID_ok_flag\", false) cuando leemos un QR y flow.set(\"QR_ok_flag\", false) cuando leemos una tarjeta, esto permite\nque se utilice un QR aunque primero hayamos metido una tarjeta invalida y viceversa. Se hizo en el nodo \"envio QR/RFID\".\n\n**Version 1.3** \n- En esta version hemos cambiado los timers a modo contexto local (del nodo) Importante este punto ya que el timer es un objeto no serializable\ny por lo tanto no deberiamos guardar en contexto flow o global ya que esos contextos estan previstos para objetos serializables (estados, valores, arrays, json...)\nSi lo ponemos en flow el timer puede romperse, quedar corrupto, o incoherente al hacer deploy o cualquier operacion de inicio.\nlo limpio es hacerlo en el contexto del nodo y poner el cierre del timer al salir del nodo en node.on(\"close\"). En su lugar ponemos el codigo\nen la pestaña del editor del nodo \"Al final\" que es lo mismo. La pestaña Close se refiere a cuando el nodered se reinicia, se hace redeploy etc..\n\n- Hemos cambiado los timers del snapshot en Analisis detector y Analisis de peso, igualmente hemos cambiado la forma de apagarlo desde otro nodo.\nPara ello hemos implementado en el nodo donde reside el timer un codigo que se activa cuando topic = cancel_snapshot_timer.\n\n- Se arreglo la repeticion del mensaje (audio) de firme en la pantalla. Para ello hemos inluido el flag de solicitud de firma en el \"if\" de envio del mensaje\n de manera que si ya se hizo solicitud de la firma no se aplica el mensaje nuevamente.\n\n- Hemos puesto un nuevo nodo (esperar) en el grupo deteccion de matricula para evitar un posible aunque remoto caso cuando se activa el detector remoto pero no se activa la bascula\ndurante unos segundos. La descripcion esta en un nodo comentario \"CASO QUE PODRIA BLOQUEAR EL SISTEMA\" que se encuentra en el grupo \"ITSAPI - WEB SERVER Y ANALISIS\".\n\n**Version 1.2** Hemos agregado una nueva funcionalidad para indicarle al conductor acerca de la ubicacion interna donde debe dirigirse con el residuo que\ntransporta. Esta notificacion se muestra una vez que hayan cumplido todos los requisitos de entrada y antes de poner el semaforo en verde. \nPara esta funcionalidad hemos introducido un codigo en el nodo \"Analisis del modo de Operacion\" (lineas 76 a 112) y en el nodo \"check json content\"\nen las lineas 44 a 50 bajo el titulo \"RESPUESTA DE LA REVISION DE LA UBICACION INTERNA EN BD\". Si recibimos respuesta positiva de la BD es decir que si \ntiene ubicacion interna el residuo presentado entonces sacamos notificacion con lo que dice el campo de descripcion encontrado en la tabla, en caso contrario\nel mensaje que aparece en pantalla es diciendo que no hay ubicacion para ese residuo.\nSe ha hecho una modificacion en el nodo \"detector rx\" para inicializar todas las variables del Totem cuando ocurra una falsa deteccion de vehiculo, es decir \ncuando que se recibe la señal de detector remoto ON pero no se activa la bascula en el tiempo previsto. Dado que en ese momento hay variables que han cambiado de estado \ny ademas se ha recibido una imagen, es necesario forzar la inicializacion de todas las variables ya que el peso no se ha movido de cero. Si dejamos las variables\nsin inicializar, cuando un vehiculo entre es probable que haya estados confusos.\n\n**Version 1.12** Se corrigio el nodo peso estable para procesar correctamente el valor de Peso Maximo Admitido y sacar un mensaje que no se pueda borrar\nhasta que el vehiculo abandone la bascula. Se agrego un nodo para mantener el aviso de salir de la bascula en caso de PMA, si el usuario pulsa OK.\nCorregido en el nodo \"check JSON content\" la recepcion de la matricula asociada a una tarjeta. Hemos activado los flags correspondientes para que el nodo \n\"matricula 2\" pueda hacer el chequeo de la matricula respecto a si esta o no en transito. \nEn el nodo \"Analisis del modo de operacion\" hemos puesto una condicion para no mostrar el boton de salida cuando el usuario utiliza una tarjerta valida.\nEn el nodo \"Analisis del modo de operacion\" hemos colocado una condicion para sacar la pantalla de firma. Esta condicion es que se trate de que estamos en \nel proceso de movimiento inicial. Adicionalmente si estamos en el proceso de movimiento final y la firma es obligatoria, marcamos el flag de firma como si estuviera\nrealizada ya que para la salida no es preciso firmar.\nEn el archivo generado de la firma se elimino el encabezado \"data:image/png Base64,\" Esto lo hacemos en el nodo firma en la linea 252 del script.\ndataUrl = canvas.toDataURL().split(\",\")[1];\n\n**Version 1.11**Se puso una condicion (peso en bascula > pmin) en el nodo \"enviar matricula\" para enviar matricula al nodo de analisis. Esto evita que se este\nenviando matricula si se recibe sin que haya vehiculo en bascula. Esto no evita que se reciban matriculas automaticas antes de entrar el vehiculo en la bascula.\nEstas ultimas fotos se conservan en memoria hasta que el vehiculo entre en la bascula y pueden ser utilizadas como foto principal en caso de fallo en la solicitud.\nHemos eliminado en la linea 156 del nodo matricula2 la condicion de \"qr_revisado\" para eximirlo de disponer de matricula debido a que ahora el codigo qr puede estar asociado a varias matriculas.\ny por lo tanto sera necesario disponer de una matricula a pesar de tener el codigo de autorizacio (solo indica residuo).\nHemos inicializado la matricula [flow.set(\"matricula\", \"Sin Matricula\")] tambien en el momento en que el peso supera a pmin por primera vez (es decir entrando en la bascula).\nSe agrego en la salida de la edicion de matricula [flow.set(\"matriculacheck_solicitada\", false)] para permitir que se busque nuevamente la matricula en BD.\n\n**Version 1.1** Hemos agregado excepcion de obligacion de tener que disponer de matricula para el caso de presentar una tarjeta RFID. Anteriormente se habia puesto en el nodo de \"Analisis\ndel modo de operacion\" (*let matricula_obligatoria = flow.get(\"matricula_obligatoria\") || true // siempre es obligatoria*) una linea para obligar a tener siempre matricula,\nindependiente de lo que este configurado en el archivo de configuracion. Ahora esa linea sigue funcionando pero en el caso de la tarjeta se permite que no haya matricula ya que esta identificacion \ncontiene la matricula unica. Ver linea 53 en el nodo mencionado anteriormente. No es el caso de los QR los cuales puede haber el mismo GUUID asociados a diferentes matriculas.\n\nSe han agregado nos nuevos campos a la tabla movimierntos_cerrados en el supervisor estos campos son \"qr_salida\" y \"rfid_salida\". La presencia de estos \ndos campos es para disponer de la identificaciob utilizada en salida en caso de hacerlo. Para ello en el nodo \"Analisis del modo de Operacion\" se evalua \nsi estamos en el movimiento inicial o final para ver cual campo es el que tenemos que rellenar. Est se hace el la linea nº 100\nSe ha moviso la inicializacion flow.set(\"distance_flag_SET\", false) al momento donde la bascula pasa de peso < pmin por primera vez. \nAntes se inicializaba cada vez que el peso que llegaba era menor que pmin. Esto podia ocasionar un error ya que el nodo detector perdia el control\nde este flag al ser inicializado cada vez que el peso < pmin.\n\nEl nodo \"matricula 2\" sustituye al nodo matricula anterior. Este nuevo contiene todas las modificaciones necesarias para adaptarse a los \nnuevos requerimientos de la bascula automatica\n\nPara que el QR pueda entrar en la planta es necesario que la matricula este disponible.\nEn caso de que la matricula leida sea diferente a la matricula obtenida en la BD luego de enviar el QR se toma la matricula leida de la BD\n\n**version 1.0.** Este codigo de Bascula Autonoma sale a partir del Totem Autonomo. Todo el codigo relativo a la gestion de BAse de Datos se traslada al RPI Supervisor\nEn este RPi solo queda lo relativo a la gestion de sensores, camaras, lectores de Identioficacion, semaforo, barrera y la pantalla para que el usuario \npueda interactuar con el sistema como por ejemplo hacer seleccion del residuo a traves de un menu de seleccion.\n\nEn esta version se ha introducido el termino PMA(Peso Maximo Autorizado. Este es un valor que el Totem recibe cuando el Supervisor le envia la autorizacion\nde la matricula junto con la tara- El Totem revisa el peso estable del vehiculo con el PMA recibidoy en caso de ser superior se envia un aviso en la pantalla\nindicandole al conductor que debe retroceder ya que supera el peso admitido.\n\nOtra función que contiene esta version es el chequeo de la Tara. Si el valor recibido de la Tara es superior a cero entonces el movimiento inicial recibido por el supervisor \nes enviado como movimiento cerrado al Servidor.Realmente para el Totem es transparente. La gestion de la Tara en efecto la hace el Supervisor una vez que recibe\nel movimiento inicial que envia el Totem.",
+ "name": "Version 1.46 de bascula autonoma",
+ "info": "**Version 1.46** 20/05/2026\nSe ha agregado un nodo de notificacion al inicio del proceso para permitir eliminar cualquier notificacion presente en caso de recibir un comando de poner el \nsemaforo en verde cuando el estado esta en rojo. Esto se hace en el nodo check JSON content\n- 1/06/2026 Se cambio el tratamiento del QR / RFID en el nodo \"tipo de lector\" para evitar caracteres aleatorios no ASCII que en ocasiones envia el lector de QR\n\n**Version 1.45** 17/05/2026\nSe ha agregado codigo en el nodo \"Envia Matricula\" y en el nodo \"Convert to B64\" para en caso en que el flag \"envia_mat_img\" este en true enviar la matricula,\nla imagen de la matricula y la imagen de contexto al supervisor en el momento que se obtengan, con la finalidad de que el supervisor a su vez la envie en\nbroadcasting para que los interesados puedan obtener en tiempo real estas informaciones y plasmarlas sobre una pantalla. Tal vez esta funcionalidad es mas para desarrollo\nya que esta informacion se envia al servidor via API una vez que el usuario es autenticado.\nLa trama que se envia al supervisor en el caso de la matricula es:\n{payload: { device: \"supervisor\", accion: \"lastplate\", data: {numero_vial: 2, totem_id: \"totem_2\", matricula: \"1234ABC\", imagen: imgBase64}}}\nen el caso de la imagen de contexto es:\n{payload: { device: \"supervisor\", accion: \"lastcontext\", data: {numero_vial: 2, totem_id: \"totem_2\", imagen_contexto: imgBase64}}}\nAmbas tramas se envian al momento de recibir las imagenes en el Totem.\nPor su lado el Supervisor envia las siguientes tramas para matricula y para contexto:\n{payload:{sender:\"supervisor\", device:\"servidor\", accion:\"lastplate\", data:{totem_id:\"totem_2\", numero_vial:2, matricula:\"1234ABC\", imagen:imgBase64}}}\n{payload:{sender:\"supervisor\", device:\"servidor\", accion:\"lastcontext\", data:{totem_id:\"totem_2\", numero_vial:2, imagen_contexto:imgBase64}}}\nEl flag \"envia_mat_img\" es configurable a traves del menu de configuracion en el apartado Comunicacion.\n\nSe agrego un nodo \"estado semaforo\" antes de accionar el semaforo fisicamente, la idea de este nodo es que envie el estado del semaforo via websocket cada\nvez que este cambia de estado, de esta forma podemos mantener un estado tiempo real en cualquier sitio remoto con solo observar esta trama. El envio se hace\nal supervisor que es quien sirve el websockety se hace solamente si se detecta un cambio de estado del semaforo. La trama es la siguiente: \n{device:\"supervisor\", accion: \"semaforo_status\", status:{totem_id:flow.get(\"totem_id\"), numero_vial:flow.get(\"numero_vial\"), semaforo:semaforo}}\nCuando llegue al supervisor, este enviara una trama al servidor asi: (esta trama va en broadcasting osea que fisicamente llega a todos los clientes de websocket):\n{payload:{sender:\"supervisor\", device:\"servidor\", accion:\"update_semaforo\", semaforo:{totem_id:totem, numero_vial:vial, semaforo:semaforo}}}\n\nEn el nodo \"Analisis del Modo de Operacion\" se agrego un chequeo al final del nodo para evitar que se haga un movimiento inicial cuando la bascula es del tipo salida\nadicionalmente tambien se chequea para evitar que muestre ubicacion en caso que se presente un QR o tarjeta\n\n**Version 1.44** 14/05/2026\nPara asegurar que las basculas de un solo totem se usan para su proposito (entrada / salida) se ha introducido un nuevo parametro configurable para \ndefinir el proposito de la bascula. Esto evitara que una matricula que no tiene transito salga por la bascula, igualmente esta la opcion \nde si un vehiculo ya tiene transito no pueda utilizar la bascula de entrada. En caso que queramos anular esta funcionalidad solo hay que \nconfigurar el parametro con el valor \"ambos\". Todo esto es valido solamente cuando tenemos un solo totem en la bascula.\nLos mensajes tanto para la entrada como para la salida son configurables y se encuentran el el menu de configuracion en el boton mensajes bajo los nombres\n\"no_pendiente\" para la bascula de salida y \"pendiente\" para la bascula de entrada.\n\n**Version 1.43** 11/05/2026\nHemos introducido un cambio significativo en la gestion del ID. Hasta ahora ele flag definitivo de ID_ok = !ID_obligatorio || ID_verificado Lo que quiere decir \nque el ID esta ok cuando el ID_obligatorio esta en false es decir no es obligatorio o cuando si es obligatorio y el ID_verificado esta en true, es decir \nesta autorizado para entrar. Pero si el ID_obligatorio esta en false y se presenta un ID cualquiera vamos a obtener ID_ok = true es decir esta autorizado.\nHemos introducido un nuevo estado que es ID_presentado y ahora la condicion es ID_ok = (!ID_obligatorio && !ID_presentado) || ID_verificado es decir que \nID_ok depende de ID_verificado si ID_obligatorio esta en true o si ID_presentado esta en true. En caso de que ID_obligatorio este en false y ID_presentado este\ntambien en false entonce ID_ok no interfiere en la autorizacion es decir esta en true, todo depende del menu de seleccion si existe.\nPara esto hemos cambiado en el nodo de \"Analisis del modo de Operacion\" linea 59 \"let ID_ok = !ID_obligatorio || ID_verificado\" por la nueva\nlet ID_ok = (!ID_obligatorio && !ID_presentado) || ID_verificado;\nAdicionalmernte en el nodo QR / RFID hemos activado el ID_presentado cada vez que leemos un ID. Este parametro se resetea en el nodo de peso cada vez que hay una nueva pesada\n\nEn el nodo de matricula (linea 27) hacemos el cambio del flag ID_obligatorio al flag salida_ID_obligatorio cuando el movimiento es final. De esta forma ID_obligatorio aplica a la entrada \nexclusivamente y salida_ID_obligatorio aplica a la salida solamente.\nEn el nodo QR/RFID hemos agregado la puesta a cero del flag de QR(linea 67) y del RFID(linea 126) cuando se trata de un ID incorrecto para que el usuario pueda volver a colocar otro ID.\n\n\n**Version 1.42** 29/04/2026\nEn el nodo \"Analisis\" en la linea 116 hemos puesto un timer que espera unos segundos antes de sacar la notificacion de ubicacion. Esto se hace para esperar a que la notificacion anterior en caso de existir\npermanezca un tiempo y en todo caso para que esta sea la ultima notificacion que quede en pantalla hasta que el vehiculo abandone la bascula. \nEliminamos de la pantalla el mensaje Acerque QR o Tarjeta en caso de recibir una lista de menu. Esto lo hacemos en el nodo \"check json\".\nEn el nodo \"Envio de Mensajes\" (linea 65) eliminamos las notificaciones que haya al final del movimiento (final de pesada) salvo si la notificacion es de Ubicacion.\nSe hicieron cambios en index.html y en index.js del uibuilder /totem/ para incluir en el menu de Tipo de Configuracion un boton (LISTA DE PARAMETROS) que nos permita visualizar todos los parametros que podemos incluir en cualquiera de los tipos de configuracion\nSe introdujo un chequeo en el nodo \"QR/RFID\" en la linea 37 para eliminar el boton de salida (simular que fue pulsado) cuando se recibe un QR valido durante el movimiento final. Lo mismo hacemos mas abajo en la recepcion de RFID.\nEn la parte RFID dado que luego de recibir la tarjeta validada en BD todavia necesitamos validar si la matricula asociada a la tarjeta tiene vehiculo en transito, esto hace que el estado movimiento = inicial puede permanecer por mas tiempo (mientras se chequea si hay transito) por lo tanto en el chequeo \ntenemos que meter la variable \"matricula_revisada\" como requisito para avanzar ya que es quien nos indica si el estado del movimiento ya es definitivo. Recordemos que este chequeo solo lo queremos hacer durante el movimiento final, es decir cuando el vehiculo esta cerrando toda la pesada.\n\n\n**Version 1.41** 1/04/2026\n- Dado que puede darse el caso que la camara de contexto no responda en un determinado momento a la solicitud de imagen, se han introducido unas condiciones para tratar de obtener\nla imagen de contexto en caso de fallo temporal. El metodo resumido es el siguiente: Cuando estamos seguros que el vehiculo esta correctamente posicionado\nen la bascula (peso estable) hacemos una solicitud y marcamos un estado (\"waiting1\"), esperamos por la imagen un tiempo definido en la variable (\"camara_contexto_delay1\") \nencaso de no llegar hacemos una segunda solicitud y marcamos el estado (\"waiting2\") y esperamos por la imagen un tiempo definido en la variable (\"camara_contexto_delay2\").\nMientras tanto el semaforo esta en rojo esperando la imagen de contexto, suponiendo que todo lo demas esta ok. Al cabo del ultimo tiempo, marcamos el nuevo estado\nen funcion de lo sucedido, \"ok\" si recibimos la imagen \"fail\" si no la hemos recibido. En cualquiera de los dos casos el semaforo pasa a verde y se continua con la pesada\nEn caso de no tener imagen de contexto, el nombre de la imagen ira vacio (\"\") al igual que la imagen.\n\n**Version 1.4** 25/03/2026\n- Debido a nuevo requerimiento se introduce la opcion (configurable) de tener una camara de contexto en la bascula. Esta camara en caso de estar\nhabilitada en la configuracion tomara una imagen en el momento en que el camion este completamente en la bascula, para ello hemos introducido un codigo en el nodo\n\"estable\" que es donde se hace la deteccion del camion completamente en la bascula. Posteriormente en el nodo \"Analisis del modo de Operacion\" es\ndonde verificamos que la imagen fue tomada y la colocamos en el registro que se esta haciendo para generar el movimiento correspondiente. El Grupo \n\"CAMARA CONTEXTO\" posee los nodos de solicitud de imagen y de recepcion de la misma. La configuracion de IP de la camara se hace en la pantalla\nde configuracion al igual que su habilitacion en el sistema.\n- Como herramienta de ayuda para saber si el Totem esta en capacidad de solicitar y de recibir la imagen de contexto enviada por la camara\nse ha incluido una funcion en el menu de configuracion -> Pruebas del sistema -> Pedir Snapshot de contexto de forma que el usuario pueda visualizar \nla imagen actual que la camara esta enviando y pueda de esa forma confirmar el correcto funcionamiento de la conexión y de los equipos.\n\n**Version 1.3.2** \n- Eliminado la inicializacion en el nodo peso del flag distance_flag_SET del detector de vehiculos. Esto ocasionaba problemas en si \ncoincidia que estaba contando los pulsos de salida y antes de finalizar las bascula se ponia en peso < pmin. En esa situacion el detector\nse quedaba bloqueado in poder indicar detector OFF.\n\n- Hemos colocado un codigo de dos lineas para eliminar el boton del menu activo \"COMPLETAR INFO\" en caso que se presente una tarjeta o un codigo QR. \nEsto lo hicimos en el nodo \"Analisis del modo de Operacion\" en la linea 70 donde chequeamos si estamos en movimiento inicial.\n\n- Corregido un \"error\" que no permitia cerrar el movimiento inicial cuando se pasaba una tarjeta si teniamos el menu activo y la firma obligatoria. \nSe agrego una condicion (\"ID_verificado\") en la condicion global para llamar a la firma. Esto es en el nodo \"Analisis de Operacion\" en las primeras lineas\nif (flow.get(\"firma_obligatoria\") && !flow.get(\"firma_flag\") && !flow.get(\"firma_ok_flag\") && !flow.get(\"supervisor\") && (!flow.get(\"menu_activo\") || (flow.get(\"menu_activo\") && (flow.get(\"menu_seleccionado_flag\") || ID_verificado)))) \nCon esto permite continuar con la firma en caso que tengamos menu_activo y firma obligatoria y entremos con tarjeta o con codigo QR.\n\n**Version 1.3.1**\n- Hemos colocado una opcion mas en el menu de configuración en \"Pruebas del Sistema\" -> \"Probar Sensor\". Esto permite visualizar la salida del valor\nde la distancia que esta midiendo el sensor cada segundo. Para que el medidor no este continuamente inundando el configurador con el dato de distancia\nhemos colocado un switch el cual solo deja pasar ese dato cuando se activa el menu, lo inhabilita cuando se sale del menu.\n\n- Hemos puesto el flag flow.set(\"RFID_ok_flag\", false) cuando leemos un QR y flow.set(\"QR_ok_flag\", false) cuando leemos una tarjeta, esto permite\nque se utilice un QR aunque primero hayamos metido una tarjeta invalida y viceversa. Se hizo en el nodo \"envio QR/RFID\".\n\n**Version 1.3** \n- En esta version hemos cambiado los timers a modo contexto local (del nodo) Importante este punto ya que el timer es un objeto no serializable\ny por lo tanto no deberiamos guardar en contexto flow o global ya que esos contextos estan previstos para objetos serializables (estados, valores, arrays, json...)\nSi lo ponemos en flow el timer puede romperse, quedar corrupto, o incoherente al hacer deploy o cualquier operacion de inicio.\nlo limpio es hacerlo en el contexto del nodo y poner el cierre del timer al salir del nodo en node.on(\"close\"). En su lugar ponemos el codigo\nen la pestaña del editor del nodo \"Al final\" que es lo mismo. La pestaña Close se refiere a cuando el nodered se reinicia, se hace redeploy etc..\n\n- Hemos cambiado los timers del snapshot en Analisis detector y Analisis de peso, igualmente hemos cambiado la forma de apagarlo desde otro nodo.\nPara ello hemos implementado en el nodo donde reside el timer un codigo que se activa cuando topic = cancel_snapshot_timer.\n\n- Se arreglo la repeticion del mensaje (audio) de firme en la pantalla. Para ello hemos inluido el flag de solicitud de firma en el \"if\" de envio del mensaje\n de manera que si ya se hizo solicitud de la firma no se aplica el mensaje nuevamente.\n\n- Hemos puesto un nuevo nodo (esperar) en el grupo deteccion de matricula para evitar un posible aunque remoto caso cuando se activa el detector remoto pero no se activa la bascula\ndurante unos segundos. La descripcion esta en un nodo comentario \"CASO QUE PODRIA BLOQUEAR EL SISTEMA\" que se encuentra en el grupo \"ITSAPI - WEB SERVER Y ANALISIS\".\n\n**Version 1.2** Hemos agregado una nueva funcionalidad para indicarle al conductor acerca de la ubicacion interna donde debe dirigirse con el residuo que\ntransporta. Esta notificacion se muestra una vez que hayan cumplido todos los requisitos de entrada y antes de poner el semaforo en verde. \nPara esta funcionalidad hemos introducido un codigo en el nodo \"Analisis del modo de Operacion\" (lineas 76 a 112) y en el nodo \"check json content\"\nen las lineas 44 a 50 bajo el titulo \"RESPUESTA DE LA REVISION DE LA UBICACION INTERNA EN BD\". Si recibimos respuesta positiva de la BD es decir que si \ntiene ubicacion interna el residuo presentado entonces sacamos notificacion con lo que dice el campo de descripcion encontrado en la tabla, en caso contrario\nel mensaje que aparece en pantalla es diciendo que no hay ubicacion para ese residuo.\nSe ha hecho una modificacion en el nodo \"detector rx\" para inicializar todas las variables del Totem cuando ocurra una falsa deteccion de vehiculo, es decir \ncuando que se recibe la señal de detector remoto ON pero no se activa la bascula en el tiempo previsto. Dado que en ese momento hay variables que han cambiado de estado \ny ademas se ha recibido una imagen, es necesario forzar la inicializacion de todas las variables ya que el peso no se ha movido de cero. Si dejamos las variables\nsin inicializar, cuando un vehiculo entre es probable que haya estados confusos.\n\n**Version 1.12** Se corrigio el nodo peso estable para procesar correctamente el valor de Peso Maximo Admitido y sacar un mensaje que no se pueda borrar\nhasta que el vehiculo abandone la bascula. Se agrego un nodo para mantener el aviso de salir de la bascula en caso de PMA, si el usuario pulsa OK.\nCorregido en el nodo \"check JSON content\" la recepcion de la matricula asociada a una tarjeta. Hemos activado los flags correspondientes para que el nodo \n\"matricula 2\" pueda hacer el chequeo de la matricula respecto a si esta o no en transito. \nEn el nodo \"Analisis del modo de operacion\" hemos puesto una condicion para no mostrar el boton de salida cuando el usuario utiliza una tarjerta valida.\nEn el nodo \"Analisis del modo de operacion\" hemos colocado una condicion para sacar la pantalla de firma. Esta condicion es que se trate de que estamos en \nel proceso de movimiento inicial. Adicionalmente si estamos en el proceso de movimiento final y la firma es obligatoria, marcamos el flag de firma como si estuviera\nrealizada ya que para la salida no es preciso firmar.\nEn el archivo generado de la firma se elimino el encabezado \"data:image/png Base64,\" Esto lo hacemos en el nodo firma en la linea 252 del script.\ndataUrl = canvas.toDataURL().split(\",\")[1];\n\n**Version 1.11**Se puso una condicion (peso en bascula > pmin) en el nodo \"enviar matricula\" para enviar matricula al nodo de analisis. Esto evita que se este\nenviando matricula si se recibe sin que haya vehiculo en bascula. Esto no evita que se reciban matriculas automaticas antes de entrar el vehiculo en la bascula.\nEstas ultimas fotos se conservan en memoria hasta que el vehiculo entre en la bascula y pueden ser utilizadas como foto principal en caso de fallo en la solicitud.\nHemos eliminado en la linea 156 del nodo matricula2 la condicion de \"qr_revisado\" para eximirlo de disponer de matricula debido a que ahora el codigo qr puede estar asociado a varias matriculas.\ny por lo tanto sera necesario disponer de una matricula a pesar de tener el codigo de autorizacio (solo indica residuo).\nHemos inicializado la matricula [flow.set(\"matricula\", \"Sin Matricula\")] tambien en el momento en que el peso supera a pmin por primera vez (es decir entrando en la bascula).\nSe agrego en la salida de la edicion de matricula [flow.set(\"matriculacheck_solicitada\", false)] para permitir que se busque nuevamente la matricula en BD.\n\n**Version 1.1** Hemos agregado excepcion de obligacion de tener que disponer de matricula para el caso de presentar una tarjeta RFID. Anteriormente se habia puesto en el nodo de \"Analisis\ndel modo de operacion\" (*let matricula_obligatoria = flow.get(\"matricula_obligatoria\") || true // siempre es obligatoria*) una linea para obligar a tener siempre matricula,\nindependiente de lo que este configurado en el archivo de configuracion. Ahora esa linea sigue funcionando pero en el caso de la tarjeta se permite que no haya matricula ya que esta identificacion \ncontiene la matricula unica. Ver linea 53 en el nodo mencionado anteriormente. No es el caso de los QR los cuales puede haber el mismo GUUID asociados a diferentes matriculas.\n\nSe han agregado nos nuevos campos a la tabla movimierntos_cerrados en el supervisor estos campos son \"qr_salida\" y \"rfid_salida\". La presencia de estos \ndos campos es para disponer de la identificaciob utilizada en salida en caso de hacerlo. Para ello en el nodo \"Analisis del modo de Operacion\" se evalua \nsi estamos en el movimiento inicial o final para ver cual campo es el que tenemos que rellenar. Est se hace el la linea nº 100\nSe ha moviso la inicializacion flow.set(\"distance_flag_SET\", false) al momento donde la bascula pasa de peso < pmin por primera vez. \nAntes se inicializaba cada vez que el peso que llegaba era menor que pmin. Esto podia ocasionar un error ya que el nodo detector perdia el control\nde este flag al ser inicializado cada vez que el peso < pmin.\n\nEl nodo \"matricula 2\" sustituye al nodo matricula anterior. Este nuevo contiene todas las modificaciones necesarias para adaptarse a los \nnuevos requerimientos de la bascula automatica\n\nPara que el QR pueda entrar en la planta es necesario que la matricula este disponible.\nEn caso de que la matricula leida sea diferente a la matricula obtenida en la BD luego de enviar el QR se toma la matricula leida de la BD\n\n**version 1.0.** Este codigo de Bascula Autonoma sale a partir del Totem Autonomo. Todo el codigo relativo a la gestion de BAse de Datos se traslada al RPI Supervisor\nEn este RPi solo queda lo relativo a la gestion de sensores, camaras, lectores de Identioficacion, semaforo, barrera y la pantalla para que el usuario \npueda interactuar con el sistema como por ejemplo hacer seleccion del residuo a traves de un menu de seleccion.\n\nEn esta version se ha introducido el termino PMA(Peso Maximo Autorizado. Este es un valor que el Totem recibe cuando el Supervisor le envia la autorizacion\nde la matricula junto con la tara- El Totem revisa el peso estable del vehiculo con el PMA recibidoy en caso de ser superior se envia un aviso en la pantalla\nindicandole al conductor que debe retroceder ya que supera el peso admitido.\n\nOtra función que contiene esta version es el chequeo de la Tara. Si el valor recibido de la Tara es superior a cero entonces el movimiento inicial recibido por el supervisor \nes enviado como movimiento cerrado al Servidor.Realmente para el Totem es transparente. La gestion de la Tara en efecto la hace el Supervisor una vez que recibe\nel movimiento inicial que envia el Totem.",
"x": 1300,
"y": 800,
"wires": []
@@ -6334,7 +6341,7 @@
"z": "953e8740401d175c",
"g": "9328043d4e9512a9",
"name": "matricula-2",
- "func": "// DEFINICION DE ALGUNOS FLAGS UTILIZADOS EN EL NODO\n//matricula_leida_flag: Si es igual a true, indica que hemos recibido matrícula de la camara.La matrícula puede ser valida o no.Sólo indica recepción de objeto de camara\n//peso_bajo_flag: Si es igual a true, indica que el ESTADO del peso esta por debajo del peso minimo.\n//Sirve para tomar unas acciones una sola vez cuándo se detecta peso > pmin(el flag esta en true en ese momento) y luego el flag pasa a false es decir el ESTADO ahora es peso por encima del minimo.\n//matricula_revisada: Si true, indica que la matrícula ha sido revisada en la Base de Datos\n//matricula_autorizada: Si true, indica que la matrícula ha sido encontrada en la base de datos y esta autorizada es decir dispone de un contrato por lo tanto el usuario va a recibir un menu en pantalla.\n//matricula_ok_flag : Si igual a true indica que el proceso de lectura de matrícula (camara o edicion en pantalla) ha sido completado satisfactoriamente y el sistema puede seguir adelante.\n//matricula_formato_flag: Si es igual a true indica que la matrícula recibida de la camara tiene el formato adecuado o que el conductor ha introducido en la pantalla una matrícula correcta en formato.\n//edicion_matricula: Si true, indica que el usuario puede utilizar el editor de matrícula en caso de error de lectura, para colocar la matrícula correcta.\n//editor_matricula_ok: Si true, indica que el usuario ha aceptado abrir el editor de matrículas.\n\n\n//====================================== Chequea validez de Matricula ========================================\nlet repetir_matricula = false // variable para gestionar repeticion de la edicion de matricula en caso de error en la introduccion\nif (flow.get(\"matricula_leida_flag\") && !flow.get(\"supervisor\") && flow.get(\"totem_master\") && !flow.get(\"peso_bajo_flag\")) { // Primero verifica si se ha leido y si esta aun en proceso\n if (flow.get(\"matricula_formato_flag\")) {// Verifica si la matricula recibida o editada esta en formato\n flow.set(\"matricula_ok_flag\", true) // matricula conforme en formato para seguir adelante con el proceso\n if (flow.get(\"matricula_revisada\")) {//chequea si ya se ha revisado la existencia de la matricula en BD\n if (flow.get(\"matricula_autorizada\")) {// Revisa si la matricula esta autorizada en BD\n flow.set(\"matricula_leida_flag\", false) // proceso de matricula ya finalizado, evita entrar aqui otra vez\n \n if (flow.get(\"totem_qty\") === 1 && flow.get(\"tipobascula\") === \"entrada\" && flow.get(\"entransito\")) {\n flow.set(\"botonsalida\", false) //elimina posibilidad de presentar boton de OK\n flow.set(\"tipo_movimiento\", undefined) // no permite tomar accione a posteriori\n //node.send([null, { payload: `MATRICULA ${flow.get(\"matricula\")} TIENE UN TRANSITO PENDIENTE
AVISE AL BASCULISTA
` }, null])\n node.send([null, {\n payload: `MATRICULA ${flow.get(\"matricula\")} TIENE UN TRANSITO PENDIENTE
AVISE AL BASCULISTA
`}, null])\n } \n \n \n\n if (flow.get(\"tipo_movimiento\") == \"final\" && flow.get(\"salida_ID_obligatorio\") == true) {\n //node.warn(\"activado boton de salida\")\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"));\n }\n else if (flow.get(\"tipo_movimiento\") == \"final\" && flow.get(\"botonsalida\") == false) {\n flow.set(\"botonsalida\", true)\n }\n //else if (flow.get(\"tipo_movimiento\") == \"inicial\" && !flow.get(\"menu_activo\")) {\n else if (flow.get(\"tipo_movimiento\") == \"inicial\" ) { // sacamos siempre el mensaje aunque sea opcional el ID\n\n if (flow.get(\"totem_qty\") === 1 && flow.get(\"tipobascula\") === \"salida\" && !flow.get(\"entransito\")) {\n node.send([null, { payload: `MATRICULA ${flow.get(\"matricula\")} NO TIENE TRANSITO PENDIENTE
AVISE AL BASCULISTA
` }, null])\n }\n else{\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"));\n }\n }\n \n }\n else {\n\n // SIN edicion de matricula\n if (!flow.get(\"edicion_matricula\") && !flow.get(\"nota_avise_basculista_done\")) {\n node.send([null, { payload: \"MATRICULA NO REGISTRADA
AVISE AL BASCULISTA
\" }, null])\n flow.set(\"nota_avise_basculista_done\", true)\n }\n\n // Matricula editada anteriormente\n else if (flow.get(\"editor_matricula_ok\") && !flow.get(\"nota_vuelva_intentar_done\")) {\n node.send([null, { payload: \"MATRICULA NO REGISTRADA
VUELVA A INTENTARLO
\" }, null])\n flow.set(\"nota_vuelva_intentar_done\", true)\n flow.set(\"badplate\", true) // para poder volver a sacar anuncio de matricula mala y editor de matricula\n flow.set(\"badplate_llamado\", false)\n repetir_matricula = true // para poder hacer un delay antes de sacar anuncio de editor\n }\n\n // Edicion de Matricula\n else if (flow.get(\"edicion_matricula\") && !flow.get(\"nota_modifique_matricula_done\")) {\n node.send([null, { payload: \"MATRICULA NO REGISTRADA
MODIFIQUE MATRICULA
\" }, null])\n flow.set(\"nota_modifique_matricula_done\", true)\n flow.set(\"nota_vuelva_intentar_done\", true)\n flow.set(\"badplate\", true) // para poder volver a sacar anuncio de matricula mala y editor de matricula\n repetir_matricula = true // para poder hacer un delay antes de sacar anuncio de editor\n }\n /*\n //CON identificacion especial\n else if (flow.get(\"identificacion_esp\")) {\n flow.set(\"matricula_leida_flag\", false) // marcamos como si la matricula se hubiera leido ya que aplicamos identificacion especial\n flow.set(\"identificacion_esp_aplicada\", true)\n flow.set(\"matricula_ok_flag\", true) // marcamos como matricula conforme para seguir adelante con el proceso\n flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n if (flow.get(\"botonsalida_activo\")) {\n flow.set(\"botonsalida\", true)\n }\n node.send([null, { payload: \"MATRICULA ERRONEA
DEBE PRESENTAR UN QR O TARJETA VALIDA
\" }, null])\n }\n \n if (((flow.get(\"QR_revisado\") && flow.get(\"QR_verificado\")) || (flow.get(\"QR_revisado\") && flow.get(\"QR_verificado\"))) && flow.get(\"matricula_autorizada\")){\n\n }\n */\n }\n }\n else {// como aun no se ha revisado en BD entonces enviamos solicitud al Supervisor\n if(!flow.get(\"matriculacheck_solicitada\")){\n let matricula = flow.get(\"matricula\")\n //msg.topic = `SELECT v.Matricula, v.Autorizado FROM Vehiculos v WHERE v.Matricula = ('${matricula}')`;\n msg.payload = { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), device: \"supervisor\", accion: \"check\", matricula: matricula }\n node.send([null, null, msg])\n flow.set(\"matriculacheck_solicitada\", true) // marca que se solicito revision de matricula\n setTimeout(function () { // timer para revisar si recibimos respuesta de BD\n if(!flow.get(\"matricula_revisada\")){ // Si matricula no ha sido revisada se vuelve a activar el chequeo de la matricula\n flow.set(\"matriculacheck_solicitada\", false)\n node.send([{payload:1}, null, null])\n }\n }, 5000)\n \n }\n }\n \n /*\n \n if(flow.get(\"menu_activo\")){// chequea si el totem debe estar pendiente de las matriculas y los contratos\n //================================================== MENU ACTIVO ================================================================================\n \n }\n //============================================================= MENU NO ACTIVO ======================================================================================\n else {// MATRICULA en formato, SIN MENU ACTIVO\n //node.warn(\"sin menu, matricula ok\")\n \n flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"))\n //node.send([null, { payload: \"MATRICULA OK
DEBE PRESENTAR UN QR O TARJETA VALIDA
\" }, null])\n let matricula = flow.get(\"matricula\")\n msg.payload = { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), device: \"supervisor\", accion: \"check\", matricula: matricula }\n node.send([null, null, msg]) \n //Guardamos la imagen del vehiculo en un archivo. Lo hacemos aqui y no al recibir la imagen por si hubo una edicion de la matricula\n //en ese caso el nombre de la imagen fue regenerado con la nueva matricula\n //flow.set(\"matricula_leida_flag\", false) // proceso de matricula ya finalizado, evita entrar aqui otra vez\n let msg_plate = { payload: flow.get(\"matricula_image\"), filename: flow.get(\"path_images\") + flow.get(\"nombre_imagen\") }\n node.send([msg_plate, null])\n\n }\n */\n }\n //=============================== MATRICULA FUERA DE FORMATO =====================================\n else {\n // CON Edicion de Matricula\n if (flow.get(\"edicion_matricula\")) { \n if (!flow.get(\"editor_matricula_ok\")) {// Si la edicion ha sido habilitada y aun no hemos sacado el editor de matricula entonces sacamos la ventana de edicion\n flow.set(\"badplate\", true)\n //flow.set(\"badplate_llamado\", false) // permite sacar nuevamente la notificacion para editar matricula\n }\n\n //Caso donde el usuario no hace edicion sino que presenta identificacion\n //if(flow.get(\"RFID_revisado\") || flow.get(\"qr_revisado\")){\n if(flow.get(\"RFID_revisado\")){ // consideramos solo tarjeta ya que el QR puede estar asociado a varias matriculas\n flow.set(\"matricula_leida_flag\", false) // marcamos como si la matricula se hubiera leido ya que aplicamos identificacion especial\n flow.set(\"identificacion_esp_aplicada\", true)\n flow.set(\"matricula_ok_flag\", true) // marcamos como matricula conforme para seguir adelante con el proceso\n //flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n }\n\n }\n\n // SIN Edicion de Matricula\n else if (!flow.get(\"edicion_matricula\")) { // si edicion de matricula no esta habilitada solicitamos que el vehiculo entre de nuevo en la bascula\n //completamos datos del registro para registrar el movimiento al momento que el peso < pmin\n \n //node.send([null, { payload: \"MATRICULA ERRONEA
VUELVA A ENTRAR EN LA BASCULA O PRESENTE UNA IDENTIFICACION
\" }, null])\n let matricula = flow.get(\"matricula\")\n node.send([\n null,\n {\n payload:\n \"\" +\n \"
MATRICULA ERRONEA
\" +\n \"
Matrícula: \" + matricula + \"
\" +\n \"
VUELVA A ENTRAR EN LA BASCULA O PRESENTE UNA IDENTIFICACION
\" +\n \"
\"\n },\n null\n ]);\n\n\n\n\n\n\n//Tengo que analizar el caso cuando no hay editor de matricula . Hay que salir de la bascula o presentar un ID para verificar la matricula asociada\n// **************************************************************************************\n\n\n/* PARTE ANTERIOR *******************************************************************\n\n // SIN Identificacion Especial\n if (!flow.get(\"identificacion_esp\")) {\n let new_register = flow.get(\"register\")\n new_register.matricula = flow.get(\"matricula\")\n new_register.matriculaeditada = flow.get(\"matricula_editada_flag\")\n new_register.nombre_imagen = flow.get(\"nombre_imagen\")\n new_register.qr = flow.get(\"last_QR\")\n new_register.rfid = flow.get(\"last_RFID\")\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n //sacamos notificacion en pantalla para volver a entrar en bascula\n node.send([null, { payload: \"MATRICULA ERRONEA
VUELVA A ENTRAR EN LA BASCULA
\" }, null])\n }\n\n // CON Identificacion Especial y QR o RFID revisado (autorizado)\n //else if (flow.get(\"RFID_revisado\") || flow.get(\"QR_revisado\")) {//caso donde identificacion_esp es verdadero\n else{\n flow.set(\"matricula_leida_flag\", false) // marcamos como si la matricula se hubiera leido ya que aplicamos identificacion especial\n flow.set(\"identificacion_esp_aplicada\", true)\n flow.set(\"matricula_ok_flag\", true) // marcamos como matricula conforme para seguir adelante con el proceso\n flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n if (flow.get(\"botonsalida_activo\")) {\n flow.set(\"botonsalida\", true)\n }\n node.send([null, { payload: \"MATRICULA ERRONEA
DEBE PRESENTAR UN QR O TARJETA VALIDA
\" }, null])\n }\n\n************************************************************************************/\n\n }\n }\n}\n\n//------------------------------------------ Edicion de Matricula ------------------------------------------------------\nif (flow.get(\"badplate\") && !flow.get(\"badplate_llamado\")) { // se ejecuta si no se ha llamado antes\n flow.set(\"badplate_llamado\", true) // Marcamos que hemos sacado la notificacion \n let matricula = flow.get(\"matricula\")\n if (matricula == \"NOT FOUND\" || matricula == \"\"){ // evitamos escribir NOT FOUND en la pantalla de edicion de matricula\n matricula = \"\"\n }\n const matricula_array = matricula.split('')\n const matricula_final = new Array(8) // Tamaño maximo de la matricula\n for (let i = 0; i < matricula_array.length; i++) {\n matricula_final[i] = matricula_array[i];\n }\n flow.set(\"matricula_array\", matricula_final)\n //node.warn(\"matricula_revisada = \" + flow.get(\"matricula_revisada\") + \" matricula = \" + matricula)\n if(repetir_matricula != true){\n node.send([null, {payload:\"MATRICULA ERRONEA
MODIFIQUE EN LA SIGUIENTE PANTALLA
\", matricula:matricula_final, size:matricula_final.length}])\n }\n else\n setTimeout(() => {\n node.send([null, { payload: \"MODIFIQUE MATRICULA
EN LA SIGUIENTE PANTALLA
\", matricula: matricula_final, size: matricula_final.length }])\n }, 3000); \n}\n//-------------------------------------------------------------------------------------------------------------------------\n //=============================================================================================================\nreturn;",
+ "func": "// DEFINICION DE ALGUNOS FLAGS UTILIZADOS EN EL NODO\n//matricula_leida_flag: Si es igual a true, indica que hemos recibido matrícula de la camara.La matrícula puede ser valida o no.Sólo indica recepción de objeto de camara\n//peso_bajo_flag: Si es igual a true, indica que el ESTADO del peso esta por debajo del peso minimo.\n//Sirve para tomar unas acciones una sola vez cuándo se detecta peso > pmin(el flag esta en true en ese momento) y luego el flag pasa a false es decir el ESTADO ahora es peso por encima del minimo.\n//matricula_revisada: Si true, indica que la matrícula ha sido revisada en la Base de Datos\n//matricula_autorizada: Si true, indica que la matrícula ha sido encontrada en la base de datos y esta autorizada es decir dispone de un contrato por lo tanto el usuario va a recibir un menu en pantalla.\n//matricula_ok_flag : Si igual a true indica que el proceso de lectura de matrícula (camara o edicion en pantalla) ha sido completado satisfactoriamente y el sistema puede seguir adelante.\n//matricula_formato_flag: Si es igual a true indica que la matrícula recibida de la camara tiene el formato adecuado o que el conductor ha introducido en la pantalla una matrícula correcta en formato.\n//edicion_matricula: Si true, indica que el usuario puede utilizar el editor de matrícula en caso de error de lectura, para colocar la matrícula correcta.\n//editor_matricula_ok: Si true, indica que el usuario ha aceptado abrir el editor de matrículas.\n\n\n//====================================== Chequea validez de Matricula ========================================\nlet repetir_matricula = false // variable para gestionar repeticion de la edicion de matricula en caso de error en la introduccion\nif (flow.get(\"matricula_leida_flag\") && !flow.get(\"supervisor\") && flow.get(\"totem_master\") && !flow.get(\"peso_bajo_flag\")) { // Primero verifica si se ha leido y si esta aun en proceso\n if (flow.get(\"matricula_formato_flag\")) {// Verifica si la matricula recibida o editada esta en formato\n flow.set(\"matricula_ok_flag\", true) // matricula conforme en formato para seguir adelante con el proceso\n if (flow.get(\"matricula_revisada\")) {//chequea si ya se ha revisado la existencia de la matricula en BD\n if (flow.get(\"matricula_autorizada\")) {// Revisa si la matricula esta autorizada en BD\n flow.set(\"matricula_leida_flag\", false) // proceso de matricula ya finalizado, evita entrar aqui otra vez\n \n if (flow.get(\"totem_qty\") === 1 && flow.get(\"tipobascula\") === \"entrada\" && flow.get(\"entransito\")) {\n flow.set(\"botonsalida\", false) //elimina posibilidad de presentar boton de OK\n flow.set(\"tipo_movimiento\", undefined) // no permite tomar acciones a posteriori es decir no genera movimiento\n node.send([null, {\n payload: `MATRICULA ${flow.get(\"matricula\")} ${flow.get(\"pendiente\")}
AVISE AL BASCULISTA
`}, null])\n } \n \n \n\n if (flow.get(\"tipo_movimiento\") == \"final\" && flow.get(\"salida_ID_obligatorio\") == true) {\n //node.warn(\"activado boton de salida\")\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"));\n }\n else if (flow.get(\"tipo_movimiento\") == \"final\" && flow.get(\"botonsalida\") == false) {\n flow.set(\"botonsalida\", true)\n }\n //else if (flow.get(\"tipo_movimiento\") == \"inicial\" && !flow.get(\"menu_activo\")) {\n else if (flow.get(\"tipo_movimiento\") == \"inicial\" ) { // sacamos siempre el mensaje aunque sea opcional el ID\n\n if (flow.get(\"totem_qty\") === 1 && flow.get(\"tipobascula\") === \"salida\" && !flow.get(\"entransito\")) {\n node.send([null, { payload: `MATRICULA ${flow.get(\"matricula\")} ${flow.get(\"no_pendiente\")}
AVISE AL BASCULISTA
` }, null])\n }\n else{\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"));\n }\n }\n \n }\n else {\n\n // SIN edicion de matricula\n if (!flow.get(\"edicion_matricula\") && !flow.get(\"nota_avise_basculista_done\")) {\n node.send([null, { payload: \"MATRICULA NO REGISTRADA
AVISE AL BASCULISTA
\" }, null])\n flow.set(\"nota_avise_basculista_done\", true)\n }\n\n // Matricula editada anteriormente\n else if (flow.get(\"editor_matricula_ok\") && !flow.get(\"nota_vuelva_intentar_done\")) {\n node.send([null, { payload: \"MATRICULA NO REGISTRADA
VUELVA A INTENTARLO
\" }, null])\n flow.set(\"nota_vuelva_intentar_done\", true)\n flow.set(\"badplate\", true) // para poder volver a sacar anuncio de matricula mala y editor de matricula\n flow.set(\"badplate_llamado\", false)\n repetir_matricula = true // para poder hacer un delay antes de sacar anuncio de editor\n }\n\n // Edicion de Matricula\n else if (flow.get(\"edicion_matricula\") && !flow.get(\"nota_modifique_matricula_done\")) {\n node.send([null, { payload: \"MATRICULA NO REGISTRADA
MODIFIQUE MATRICULA
\" }, null])\n flow.set(\"nota_modifique_matricula_done\", true)\n flow.set(\"nota_vuelva_intentar_done\", true)\n flow.set(\"badplate\", true) // para poder volver a sacar anuncio de matricula mala y editor de matricula\n repetir_matricula = true // para poder hacer un delay antes de sacar anuncio de editor\n }\n /*\n //CON identificacion especial\n else if (flow.get(\"identificacion_esp\")) {\n flow.set(\"matricula_leida_flag\", false) // marcamos como si la matricula se hubiera leido ya que aplicamos identificacion especial\n flow.set(\"identificacion_esp_aplicada\", true)\n flow.set(\"matricula_ok_flag\", true) // marcamos como matricula conforme para seguir adelante con el proceso\n flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n if (flow.get(\"botonsalida_activo\")) {\n flow.set(\"botonsalida\", true)\n }\n node.send([null, { payload: \"MATRICULA ERRONEA
DEBE PRESENTAR UN QR O TARJETA VALIDA
\" }, null])\n }\n \n if (((flow.get(\"QR_revisado\") && flow.get(\"QR_verificado\")) || (flow.get(\"QR_revisado\") && flow.get(\"QR_verificado\"))) && flow.get(\"matricula_autorizada\")){\n\n }\n */\n }\n }\n else {// como aun no se ha revisado en BD entonces enviamos solicitud al Supervisor\n if(!flow.get(\"matriculacheck_solicitada\")){\n let matricula = flow.get(\"matricula\")\n //msg.topic = `SELECT v.Matricula, v.Autorizado FROM Vehiculos v WHERE v.Matricula = ('${matricula}')`;\n msg.payload = { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), device: \"supervisor\", accion: \"check\", matricula: matricula }\n node.send([null, null, msg])\n flow.set(\"matriculacheck_solicitada\", true) // marca que se solicito revision de matricula\n setTimeout(function () { // timer para revisar si recibimos respuesta de BD\n if(!flow.get(\"matricula_revisada\")){ // Si matricula no ha sido revisada se vuelve a activar el chequeo de la matricula\n flow.set(\"matriculacheck_solicitada\", false)\n node.send([{payload:1}, null, null])\n }\n }, 5000)\n \n }\n }\n \n /*\n \n if(flow.get(\"menu_activo\")){// chequea si el totem debe estar pendiente de las matriculas y los contratos\n //================================================== MENU ACTIVO ================================================================================\n \n }\n //============================================================= MENU NO ACTIVO ======================================================================================\n else {// MATRICULA en formato, SIN MENU ACTIVO\n //node.warn(\"sin menu, matricula ok\")\n \n flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n flow.set(\"window_men_m3\", flow.get(\"men_identificacion\"))\n //node.send([null, { payload: \"MATRICULA OK
DEBE PRESENTAR UN QR O TARJETA VALIDA
\" }, null])\n let matricula = flow.get(\"matricula\")\n msg.payload = { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), device: \"supervisor\", accion: \"check\", matricula: matricula }\n node.send([null, null, msg]) \n //Guardamos la imagen del vehiculo en un archivo. Lo hacemos aqui y no al recibir la imagen por si hubo una edicion de la matricula\n //en ese caso el nombre de la imagen fue regenerado con la nueva matricula\n //flow.set(\"matricula_leida_flag\", false) // proceso de matricula ya finalizado, evita entrar aqui otra vez\n let msg_plate = { payload: flow.get(\"matricula_image\"), filename: flow.get(\"path_images\") + flow.get(\"nombre_imagen\") }\n node.send([msg_plate, null])\n\n }\n */\n }\n //=============================== MATRICULA FUERA DE FORMATO =====================================\n else {\n // CON Edicion de Matricula\n if (flow.get(\"edicion_matricula\")) { \n if (!flow.get(\"editor_matricula_ok\")) {// Si la edicion ha sido habilitada y aun no hemos sacado el editor de matricula entonces sacamos la ventana de edicion\n flow.set(\"badplate\", true)\n //flow.set(\"badplate_llamado\", false) // permite sacar nuevamente la notificacion para editar matricula\n }\n\n //Caso donde el usuario no hace edicion sino que presenta identificacion\n //if(flow.get(\"RFID_revisado\") || flow.get(\"qr_revisado\")){\n if(flow.get(\"RFID_revisado\")){ // consideramos solo tarjeta ya que el QR puede estar asociado a varias matriculas\n flow.set(\"matricula_leida_flag\", false) // marcamos como si la matricula se hubiera leido ya que aplicamos identificacion especial\n flow.set(\"identificacion_esp_aplicada\", true)\n flow.set(\"matricula_ok_flag\", true) // marcamos como matricula conforme para seguir adelante con el proceso\n //flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n }\n\n }\n\n // SIN Edicion de Matricula\n else if (!flow.get(\"edicion_matricula\")) { // si edicion de matricula no esta habilitada solicitamos que el vehiculo entre de nuevo en la bascula\n //completamos datos del registro para registrar el movimiento al momento que el peso < pmin\n \n //node.send([null, { payload: \"MATRICULA ERRONEA
VUELVA A ENTRAR EN LA BASCULA O PRESENTE UNA IDENTIFICACION
\" }, null])\n let matricula = flow.get(\"matricula\")\n node.send([\n null,\n {\n payload:\n \"\" +\n \"
MATRICULA ERRONEA
\" +\n \"
Matrícula: \" + matricula + \"
\" +\n \"
VUELVA A ENTRAR EN LA BASCULA O PRESENTE UNA IDENTIFICACION
\" +\n \"
\"\n },\n null\n ]);\n\n\n\n\n\n\n//Tengo que analizar el caso cuando no hay editor de matricula . Hay que salir de la bascula o presentar un ID para verificar la matricula asociada\n// **************************************************************************************\n\n\n/* PARTE ANTERIOR *******************************************************************\n\n // SIN Identificacion Especial\n if (!flow.get(\"identificacion_esp\")) {\n let new_register = flow.get(\"register\")\n new_register.matricula = flow.get(\"matricula\")\n new_register.matriculaeditada = flow.get(\"matricula_editada_flag\")\n new_register.nombre_imagen = flow.get(\"nombre_imagen\")\n new_register.qr = flow.get(\"last_QR\")\n new_register.rfid = flow.get(\"last_RFID\")\n new_register.sentido = flow.get(\"sentido\")\n new_register.botonvalidacion = flow.get(\"salida_valida_flag\")\n\n flow.set(\"register\", new_register)\n flow.set(\"movimiento_registrado_flag\", true)\n //sacamos notificacion en pantalla para volver a entrar en bascula\n node.send([null, { payload: \"MATRICULA ERRONEA
VUELVA A ENTRAR EN LA BASCULA
\" }, null])\n }\n\n // CON Identificacion Especial y QR o RFID revisado (autorizado)\n //else if (flow.get(\"RFID_revisado\") || flow.get(\"QR_revisado\")) {//caso donde identificacion_esp es verdadero\n else{\n flow.set(\"matricula_leida_flag\", false) // marcamos como si la matricula se hubiera leido ya que aplicamos identificacion especial\n flow.set(\"identificacion_esp_aplicada\", true)\n flow.set(\"matricula_ok_flag\", true) // marcamos como matricula conforme para seguir adelante con el proceso\n flow.set(\"identificacion_pendiente\", true) // pendiente de presentar identificacion\n if (flow.get(\"botonsalida_activo\")) {\n flow.set(\"botonsalida\", true)\n }\n node.send([null, { payload: \"MATRICULA ERRONEA
DEBE PRESENTAR UN QR O TARJETA VALIDA
\" }, null])\n }\n\n************************************************************************************/\n\n }\n }\n}\n\n//------------------------------------------ Edicion de Matricula ------------------------------------------------------\nif (flow.get(\"badplate\") && !flow.get(\"badplate_llamado\")) { // se ejecuta si no se ha llamado antes\n flow.set(\"badplate_llamado\", true) // Marcamos que hemos sacado la notificacion \n let matricula = flow.get(\"matricula\")\n if (matricula == \"NOT FOUND\" || matricula == \"\"){ // evitamos escribir NOT FOUND en la pantalla de edicion de matricula\n matricula = \"\"\n }\n const matricula_array = matricula.split('')\n const matricula_final = new Array(8) // Tamaño maximo de la matricula\n for (let i = 0; i < matricula_array.length; i++) {\n matricula_final[i] = matricula_array[i];\n }\n flow.set(\"matricula_array\", matricula_final)\n //node.warn(\"matricula_revisada = \" + flow.get(\"matricula_revisada\") + \" matricula = \" + matricula)\n if(repetir_matricula != true){\n node.send([null, {payload:\"MATRICULA ERRONEA
MODIFIQUE EN LA SIGUIENTE PANTALLA
\", matricula:matricula_final, size:matricula_final.length}])\n }\n else\n setTimeout(() => {\n node.send([null, { payload: \"MODIFIQUE MATRICULA
EN LA SIGUIENTE PANTALLA
\", matricula: matricula_final, size: matricula_final.length }])\n }, 3000); \n}\n//-------------------------------------------------------------------------------------------------------------------------\n //=============================================================================================================\nreturn;",
"outputs": 3,
"timeout": 0,
"noerr": 0,
@@ -6514,9 +6521,9 @@
"type": "comment",
"z": "953e8740401d175c",
"g": "61f2c799bf9b937c",
- "name": "CASO QUE PODRIA BLOQUEAR EL SISTEMA",
+ "name": "CASO QUE PODRIA BLOQUEAR EL SISTEMA (RESUELTO)",
"info": "Caso de dos Totems en bascula bidireccional\nSi recibimos una señal del detector remoto en ON esto solicita un snapshot al cabo de 1 segundo.\nSi la imagen llega antes que la bascula haya superado el pmin. El sistema se va a bloquear \nporque en el nodo \"envia matricula\" se hace un chequeo de peso_bajo_flag y si esta en true es decir no ha superado el pmin\nentonces no envia la matricula y por ende el sistema no se mueve mas porque a este bloque no llegan mas \neventos que lo puedan hacer reaccionar.\n\nEste es un caso que en la realidad no deberia suceder, salvo que el vehiculo active el detector y se detenga inmediatamente\nen esa posicion unos segundos sin haber tocado la bascula, de forma que la imagen de la matricula llega al totem \npero la senal de la bascula (peso > pmin) llega un tiempo despues que llego la imagen al nodo \"envia matricula\".\n\nPara resolver esta posible situacion lo que vamos a hacer es incluir un nodo de timer rearmable (nodo \"espera\") que solamente va a \nfuncionar cuando totem_qty = 2. Este nodo intercalado entre el que recibe el mensaje con la matricula procesada (\"envia matricula\") \ny el que recibe la matricula de la camara (analisis de camara\"), se asegura que antes de pedir al nodo \"enviar matricula\" que la envie, haya llegado \nel evento de la bascula observando el flag \"peso_bajo_flag\" hasta que este tenga el estado false.\nEn ese momento envia el mensaje original ( {payload: 1}) al nodo \"enviar_matricula\" para que continue el proceso. De lo contrario se queda observando \ncada 400 ms a ver si el flag del peso ha cambiado de estado.\nEn caso de que \"nunca\" llegue el peso, porque el camion se salio en retroceso o por otra circustancia, el timer se autoextingue al cabo de X segundos\n",
- "x": 4280,
+ "x": 4320,
"y": 1380,
"wires": []
},
@@ -7103,7 +7110,7 @@
"g": "1b1ee13b380e32b6",
"name": "convert to base64",
"func": "const reqIdActual = flow.get(\"camara_contexto_reqid\");\nconst estado = flow.get(\"camara_contexto_estado\") || \"idle\";\nconst reqIdMsg = msg.contexto_reqid;\n// Ignorar respuestas viejas o fuera de contexto\nif (reqIdMsg && reqIdMsg !== reqIdActual) {\n node.warn(\"Respuesta de contexto ignorada por reqId antiguo\");\n return null;\n}\n// Si ya estaba resuelto, ignoramos duplicados\nif (estado === \"ok\" || estado === \"fail\") {\n return null;\n}\n\n// Validar contenido recibido\nlet imagenB64 = \"\";\n\nif (Buffer.isBuffer(msg.payload)) {\n imagenB64 = msg.payload.toString(\"base64\");\n} else if (typeof msg.payload === \"string\") {\n imagenB64 = msg.payload;\n} else {\n node.warn(\"La respuesta de la cámara no contiene imagen válida\");\n return null;\n}\n\n// Guardar resultado exitoso\nflow.set(\"last_camara_contexto\", imagenB64);\nflow.set(\"camara_contexto_rx\", true);\nflow.set(\"camara_contexto_estado\", \"ok\");\n\n//Generamos nombre del archivo de la imagen recibida\nlet now = new Date()\nlet nowdate = now.toLocaleString(\"sv-SE\").replace(/[- :]/g, \"\")\nif (flow.get(\"tipo_movimiento\") === \"inicial\") {\n flow.set(\"nombre_contexto\", flow.get(\"matricula\") + \"-contexto_i-\" + nowdate + \".jpg\")\n}\nelse {\n flow.set(\"nombre_contexto\", flow.get(\"matricula\") + \"-contexto_f-\" + nowdate + \".jpg\")\n}\n\n// Cancelar timers pendientes\nconst t1 = flow.get(\"camara_contexto_timer1\");\nif (t1) clearTimeout(t1);\nconst t2 = flow.get(\"camara_contexto_timer2\");\nif (t2) clearTimeout(t2);\nflow.set(\"camara_contexto_timer1\", null);\nflow.set(\"camara_contexto_timer2\", null);\n\nmsg.camara_contexto_estado = \"ok\";\n\n//======================================= ENVIO DE IMAGEN PARA MONITOREO ===========================================================\n// verificamos si tenemos que enviar la imagen de contexto al supervisor\nlet newmsg = flow.get(\"envia_mat_img\")\n ? {\n payload: { device: \"supervisor\", accion: \"lastcontext\", data: { numero_vial: flow.get(\"numero_vial\"), totem_id: flow.get(\"totem_id\"), imagen_contexto: imagenB64 } }\n }\n : null;\n//====================================================================================================\nreturn [{ payload: 1 }, newmsg];\n\n\n/*\n\n// msg.payload llega como Buffer\nif (Buffer.isBuffer(msg.payload)) {\n msg.payload = msg.payload.toString('base64');\n flow.set(\"last_camara_contexto\", msg.payload)\n flow.set(\"camara_contexto_rx\", true)\n let now = new Date()\n //const nowdate = now.toLocaleString('es-ES', { hour12: false });\n let nowdate = now.toLocaleString(\"sv-SE\").replace(/[- :]/g, \"\")\n if(flow.get(\"tipo_movimiento\") === \"inicial\"){\n flow.set(\"nombre_contexto\", flow.get(\"matricula\") + \"-contexto_i-\" + nowdate + \".jpg\")\n }\n else{\n flow.set(\"nombre_contexto\", flow.get(\"matricula\") + \"-contexto_f-\" + nowdate + \".jpg\")\n }\n}\nreturn {payload:1};\n*/",
- "outputs": 1,
+ "outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
@@ -7114,6 +7121,9 @@
"wires": [
[
"8385582377c91fb6"
+ ],
+ [
+ "4abf2246aa647ea1"
]
]
},
@@ -7193,7 +7203,7 @@
"z": "953e8740401d175c",
"g": "1b1ee13b380e32b6",
"name": "debug 1",
- "active": false,
+ "active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
@@ -7504,7 +7514,7 @@
"z": "953e8740401d175c",
"g": "646bdfb9988a1708",
"name": "estado semaforo",
- "func": "let semaforo = msg.payload ? \"green\": \"red\"\nmsg = {}\nmsg.payload = {device:\"supervisor\", accion: \"semaforo_status\", status:{totem_id:flow.get(\"totem_id\"), numero_vial:flow.get(\"numero_vial\"), semaforo:semaforo}}\nreturn msg;",
+ "func": "let semaforo = msg.payload ? \"green\": \"red\"\nmsg = {}\nif (semaforo != flow.get(\"ultimosemaforo\")){\n msg.payload = {device:\"supervisor\", accion: \"semaforo_status\", status:{totem_id:flow.get(\"totem_id\"), numero_vial:flow.get(\"numero_vial\"), semaforo:semaforo}}\n}\nflow.set(\"ultimosemaforo\", semaforo)\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
@@ -7532,5 +7542,236 @@
"x": 2355,
"y": 1300,
"wires": []
+ },
+ {
+ "id": "4abf2246aa647ea1",
+ "type": "link out",
+ "z": "953e8740401d175c",
+ "g": "1b1ee13b380e32b6",
+ "name": "link out 11",
+ "mode": "link",
+ "links": [
+ "0df0c819dae1658d"
+ ],
+ "x": 2025,
+ "y": 1400,
+ "wires": []
+ },
+ {
+ "id": "b22cc0f171be84d5",
+ "type": "ui_toast",
+ "z": "953e8740401d175c",
+ "g": "646bdfb9988a1708",
+ "position": "dialog",
+ "displayTime": "3",
+ "highlight": "",
+ "sendall": true,
+ "outputs": 1,
+ "ok": "\"\"",
+ "cancel": "",
+ "raw": false,
+ "className": "",
+ "topic": "",
+ "name": "Borrado de notificacion",
+ "x": 780,
+ "y": 1420,
+ "wires": [
+ []
+ ]
+ },
+ {
+ "id": "92dffe7da586f32e",
+ "type": "inject",
+ "z": "953e8740401d175c",
+ "name": "",
+ "props": [
+ {
+ "p": "payload"
+ },
+ {
+ "p": "topic",
+ "vt": "str"
+ }
+ ],
+ "repeat": "",
+ "crontab": "",
+ "once": false,
+ "onceDelay": 0.1,
+ "topic": "",
+ "payload": "3QR-9940533C-D9E3-4411-AE36-37DFCB03AF1F",
+ "payloadType": "str",
+ "x": 530,
+ "y": 460,
+ "wires": [
+ [
+ "a66f75ea959be3c4"
+ ]
+ ]
+ },
+ {
+ "id": "a5f9f0f4bf8bc429",
+ "type": "inject",
+ "z": "953e8740401d175c",
+ "name": "true",
+ "props": [
+ {
+ "p": "payload"
+ },
+ {
+ "p": "topic",
+ "vt": "str"
+ }
+ ],
+ "repeat": "",
+ "crontab": "",
+ "once": false,
+ "onceDelay": 0.1,
+ "topic": "",
+ "payload": "true",
+ "payloadType": "bool",
+ "x": 290,
+ "y": 540,
+ "wires": [
+ [
+ "3f41c63bd591b883"
+ ]
+ ]
+ },
+ {
+ "id": "3f41c63bd591b883",
+ "type": "change",
+ "z": "953e8740401d175c",
+ "name": "lector",
+ "rules": [
+ {
+ "t": "set",
+ "p": "lector_activo",
+ "pt": "flow",
+ "to": "payload",
+ "tot": "msg"
+ }
+ ],
+ "action": "",
+ "property": "",
+ "from": "",
+ "to": "",
+ "reg": false,
+ "x": 470,
+ "y": 540,
+ "wires": [
+ []
+ ]
+ },
+ {
+ "id": "e066d7682dbcbf88",
+ "type": "inject",
+ "z": "953e8740401d175c",
+ "name": "true",
+ "props": [
+ {
+ "p": "payload"
+ },
+ {
+ "p": "topic",
+ "vt": "str"
+ }
+ ],
+ "repeat": "",
+ "crontab": "",
+ "once": false,
+ "onceDelay": 0.1,
+ "topic": "",
+ "payload": "false",
+ "payloadType": "bool",
+ "x": 290,
+ "y": 600,
+ "wires": [
+ [
+ "3f41c63bd591b883"
+ ]
+ ]
+ },
+ {
+ "id": "5b26b10de750bc67",
+ "type": "inject",
+ "z": "953e8740401d175c",
+ "name": "true",
+ "props": [
+ {
+ "p": "payload"
+ },
+ {
+ "p": "topic",
+ "vt": "str"
+ }
+ ],
+ "repeat": "",
+ "crontab": "",
+ "once": false,
+ "onceDelay": 0.1,
+ "topic": "",
+ "payload": "true",
+ "payloadType": "bool",
+ "x": 510,
+ "y": 640,
+ "wires": [
+ [
+ "f872e72c3f1884ef"
+ ]
+ ]
+ },
+ {
+ "id": "f872e72c3f1884ef",
+ "type": "change",
+ "z": "953e8740401d175c",
+ "name": "esperando id",
+ "rules": [
+ {
+ "t": "set",
+ "p": "esperando_id",
+ "pt": "flow",
+ "to": "payload",
+ "tot": "msg"
+ }
+ ],
+ "action": "",
+ "property": "",
+ "from": "",
+ "to": "",
+ "reg": false,
+ "x": 710,
+ "y": 640,
+ "wires": [
+ []
+ ]
+ },
+ {
+ "id": "aed4b39f69cb7666",
+ "type": "inject",
+ "z": "953e8740401d175c",
+ "name": "true",
+ "props": [
+ {
+ "p": "payload"
+ },
+ {
+ "p": "topic",
+ "vt": "str"
+ }
+ ],
+ "repeat": "",
+ "crontab": "",
+ "once": false,
+ "onceDelay": 0.1,
+ "topic": "",
+ "payload": "false",
+ "payloadType": "bool",
+ "x": 510,
+ "y": 700,
+ "wires": [
+ [
+ "f872e72c3f1884ef"
+ ]
+ ]
}
]
\ No newline at end of file