2899 lines
107 KiB
JSON
2899 lines
107 KiB
JSON
[
|
|
{
|
|
"id": "ae9e82a0a0e1eb89",
|
|
"type": "tab",
|
|
"label": "Cálculos de H3",
|
|
"disabled": false,
|
|
"info": "",
|
|
"env": []
|
|
},
|
|
{
|
|
"id": "f511dd2230a153e7",
|
|
"type": "tab",
|
|
"label": "Grafíco",
|
|
"disabled": false,
|
|
"info": "",
|
|
"env": []
|
|
},
|
|
{
|
|
"id": "230815bb0628a63e",
|
|
"type": "tab",
|
|
"label": "Modelo",
|
|
"disabled": false,
|
|
"info": "",
|
|
"env": []
|
|
},
|
|
{
|
|
"id": "56fb69eb622c3f3b",
|
|
"type": "tab",
|
|
"label": "Mapa",
|
|
"disabled": false,
|
|
"info": "",
|
|
"env": []
|
|
},
|
|
{
|
|
"id": "748b5921246ec468",
|
|
"type": "postgreSQLConfig",
|
|
"name": "PostGIS",
|
|
"host": "10.10.5.32",
|
|
"hostFieldType": "str",
|
|
"port": 5432,
|
|
"portFieldType": "num",
|
|
"database": "postgres",
|
|
"databaseFieldType": "str",
|
|
"ssl": "false",
|
|
"sslFieldType": "bool",
|
|
"applicationName": "",
|
|
"applicationNameType": "str",
|
|
"max": "500",
|
|
"maxFieldType": "num",
|
|
"idle": "100000",
|
|
"idleFieldType": "num",
|
|
"connectionTimeout": "300000",
|
|
"connectionTimeoutFieldType": "num",
|
|
"user": "postgres",
|
|
"userFieldType": "str",
|
|
"password": "tfmuocdfcarvajal",
|
|
"passwordFieldType": "str"
|
|
},
|
|
{
|
|
"id": "3afa9de4406d30d8",
|
|
"type": "ui-base",
|
|
"name": "Mapa de demanda",
|
|
"path": "/dashboard",
|
|
"appIcon": "",
|
|
"includeClientData": true,
|
|
"acceptsClientConfig": [
|
|
"ui-notification",
|
|
"ui-control"
|
|
],
|
|
"showPathInSidebar": false,
|
|
"headerContent": "dashboard",
|
|
"navigationStyle": "temporary",
|
|
"titleBarStyle": "fixed",
|
|
"showReconnectNotification": true,
|
|
"notificationDisplayTime": 1,
|
|
"showDisconnectNotification": true,
|
|
"allowInstall": true
|
|
},
|
|
{
|
|
"id": "c81bf3ad6297e603",
|
|
"type": "ui-theme",
|
|
"name": "Default Theme",
|
|
"colors": {
|
|
"surface": "#ffffff",
|
|
"primary": "#0094CE",
|
|
"bgPage": "#eeeeee",
|
|
"groupBg": "#ffffff",
|
|
"groupOutline": "#cccccc"
|
|
},
|
|
"sizes": {
|
|
"density": "default",
|
|
"pagePadding": "12px",
|
|
"groupGap": "12px",
|
|
"groupBorderRadius": "4px",
|
|
"widgetGap": "12px"
|
|
}
|
|
},
|
|
{
|
|
"id": "b332967d63ddbdfe",
|
|
"type": "ui-page",
|
|
"name": "Estimaciones",
|
|
"ui": "3afa9de4406d30d8",
|
|
"path": "/estimaciones",
|
|
"icon": "home",
|
|
"layout": "flex",
|
|
"theme": "c81bf3ad6297e603",
|
|
"breakpoints": [
|
|
{
|
|
"name": "Default",
|
|
"px": "0",
|
|
"cols": "3"
|
|
},
|
|
{
|
|
"name": "Tablet",
|
|
"px": "576",
|
|
"cols": "6"
|
|
},
|
|
{
|
|
"name": "Small Desktop",
|
|
"px": "768",
|
|
"cols": "9"
|
|
},
|
|
{
|
|
"name": "Desktop",
|
|
"px": "1024",
|
|
"cols": "12"
|
|
}
|
|
],
|
|
"order": 1,
|
|
"className": "",
|
|
"visible": true,
|
|
"disabled": false
|
|
},
|
|
{
|
|
"id": "f8afeee042444067",
|
|
"type": "ui-group",
|
|
"name": "Mapa",
|
|
"page": "b332967d63ddbdfe",
|
|
"width": 12,
|
|
"height": "9",
|
|
"order": 2,
|
|
"showTitle": true,
|
|
"className": "",
|
|
"visible": "true",
|
|
"disabled": "false",
|
|
"groupType": "default"
|
|
},
|
|
{
|
|
"id": "bb66042c3e7c9cb3",
|
|
"type": "ui-group",
|
|
"name": "Configuración",
|
|
"page": "b332967d63ddbdfe",
|
|
"width": 3,
|
|
"height": "7",
|
|
"order": 1,
|
|
"showTitle": true,
|
|
"className": "",
|
|
"visible": "true",
|
|
"disabled": "false",
|
|
"groupType": "default"
|
|
},
|
|
{
|
|
"id": "3005f842c2ae482e",
|
|
"type": "inject",
|
|
"z": "ae9e82a0a0e1eb89",
|
|
"name": "Definimos el nivel 8",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "nivel_hexagono",
|
|
"v": "8",
|
|
"vt": "num"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 130,
|
|
"y": 260,
|
|
"wires": [
|
|
[
|
|
"ee9152d1f76ccaac"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "41f3663b6be9dc20",
|
|
"type": "debug",
|
|
"z": "ae9e82a0a0e1eb89",
|
|
"name": "Resultado",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 580,
|
|
"y": 260,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "ee9152d1f76ccaac",
|
|
"type": "function",
|
|
"z": "ae9e82a0a0e1eb89",
|
|
"name": "Realizamos los calculos",
|
|
"func": "// Node-RED Function Node Script\n// Genera tabla de hexágonos recorribles según velocidad y tiempo\n\n// Obtener parámetros de entrada\nconst nivel_hexagono = msg.nivel_hexagono || 8; // nivel H3 por defecto\nconst velocidad_min = msg.velocidad_min || 10; // km/h mínima\nconst velocidad_max = msg.velocidad_max || 30; // km/h máxima \nconst tiempo_minutos = msg.tiempo_minutos || 20; // minutos disponibles\n\nlet h3 = h3Js\n\n// Validar que tenemos las librerías necesarias\nif (typeof h3 === 'undefined') {\n node.error(\"H3 library not available\");\n return null;\n}\n\ntry {\n // Calcular longitud del lado del hexágono en metros\n const longitud_lado = h3.getHexagonEdgeLengthAvg(nivel_hexagono, 'm');\n\n // Convertir velocidades de km/h a m/s\n const velocidad_min_ms = (velocidad_min * 1000) / 3600;\n const velocidad_max_ms = (velocidad_max * 1000) / 3600;\n\n // Convertir tiempo de minutos a segundos\n const tiempo_segundos = tiempo_minutos * 60;\n\n // Calcular distancias máximas recorribles\n const distancia_min = velocidad_min_ms * tiempo_segundos;\n const distancia_max = velocidad_max_ms * tiempo_segundos;\n\n // Calcular número de hexágonos en cada dirección\n const hexagonos_min = Math.floor(distancia_min / longitud_lado);\n const hexagonos_max = Math.floor(distancia_max / longitud_lado);\n\n // Generar tabla de resultados\n const tabla_resultados = [];\n\n for (let num_hexagonos = hexagonos_min; num_hexagonos <= hexagonos_max; num_hexagonos++) {\n const distancia_recorrida = num_hexagonos * longitud_lado;\n const velocidad_requerida = (distancia_recorrida / tiempo_segundos) * 3.6; // Convertir a km/h\n\n tabla_resultados.push({\n num_hexagonos: num_hexagonos,\n distancia_metros: Math.round(distancia_recorrida),\n distancia_km: (distancia_recorrida / 1000).toFixed(2),\n velocidad_requerida_kmh: velocidad_requerida.toFixed(2),\n nivel_h3: nivel_hexagono,\n lado_hexagono_m: Math.round(longitud_lado)\n });\n }\n\n // Preparar mensaje de salida\n msg.payload = {\n parametros: {\n nivel_hexagono: nivel_hexagono,\n velocidad_min_kmh: velocidad_min,\n velocidad_max_kmh: velocidad_max,\n tiempo_minutos: tiempo_minutos,\n lado_hexagono_metros: Math.round(longitud_lado)\n },\n tabla: tabla_resultados,\n resumen: {\n hexagonos_minimos: hexagonos_min,\n hexagonos_maximos: hexagonos_max,\n rango_hexagonos: `${hexagonos_min} - ${hexagonos_max}`,\n distancia_minima_km: (hexagonos_min * longitud_lado / 1000).toFixed(2),\n distancia_maxima_km: (hexagonos_max * longitud_lado / 1000).toFixed(2)\n }\n };\n\n // Agregar información adicional para debugging\n msg.hexagonInfo = {\n nivel: nivel_hexagono,\n longitud_lado: longitud_lado\n };\n\n return msg;\n\n} catch (error) {\n node.error(\"Error processing hexagon data: \" + error.message);\n msg.error = error.message;\n return msg;\n}",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 370,
|
|
"y": 260,
|
|
"wires": [
|
|
[
|
|
"41f3663b6be9dc20"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "0934bc707c9b611d",
|
|
"type": "comment",
|
|
"z": "ae9e82a0a0e1eb89",
|
|
"name": "Cálculo de la tabla de recorrido para la grua",
|
|
"info": "",
|
|
"x": 210,
|
|
"y": 180,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "d801ff754db4d5e8",
|
|
"type": "inject",
|
|
"z": "ae9e82a0a0e1eb89",
|
|
"name": "Definimos el nivel 7",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "nivel_hexagono",
|
|
"v": "7",
|
|
"vt": "num"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 130,
|
|
"y": 220,
|
|
"wires": [
|
|
[
|
|
"ee9152d1f76ccaac"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "9ca4fbaf930ad8e1",
|
|
"type": "inject",
|
|
"z": "ae9e82a0a0e1eb89",
|
|
"name": "Definimos el nivel 9",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "nivel_hexagono",
|
|
"v": "9",
|
|
"vt": "num"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 130,
|
|
"y": 300,
|
|
"wires": [
|
|
[
|
|
"ee9152d1f76ccaac"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ab02b07ce8843526",
|
|
"type": "worldmap",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"lat": "",
|
|
"lon": "",
|
|
"zoom": "",
|
|
"layer": "",
|
|
"cluster": "",
|
|
"maxage": "",
|
|
"usermenu": "show",
|
|
"layers": "show",
|
|
"panit": "false",
|
|
"panlock": "false",
|
|
"zoomlock": "false",
|
|
"hiderightclick": "false",
|
|
"coords": "false",
|
|
"showgrid": "false",
|
|
"showruler": "false",
|
|
"allowFileDrop": "false",
|
|
"path": "/worldmap",
|
|
"overlist": "DR,CO,RA,DN",
|
|
"maplist": "OSMG,OSMC,EsriC,EsriS,UKOS",
|
|
"mapname": "",
|
|
"mapurl": "",
|
|
"mapopt": "",
|
|
"mapwms": false,
|
|
"x": 440,
|
|
"y": 280,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "10f4dc8ae329f33e",
|
|
"type": "inject",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Mover mapa",
|
|
"props": [
|
|
{
|
|
"p": "payload.command",
|
|
"v": "{\"lat\":\"40.40684\",\"lon\":\"-3.5711476\"}",
|
|
"vt": "json"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"x": 290,
|
|
"y": 240,
|
|
"wires": [
|
|
[
|
|
"ab02b07ce8843526"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "5a0676c5ba4e943b",
|
|
"type": "inject",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Zoom",
|
|
"props": [
|
|
{
|
|
"p": "payload.command",
|
|
"v": "{\"zoom\":15}",
|
|
"vt": "json"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"x": 270,
|
|
"y": 280,
|
|
"wires": [
|
|
[
|
|
"ab02b07ce8843526"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "a94de8711099eff7",
|
|
"type": "inject",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "House",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "{\"name\":\"Casa\",\"icon\":\"home\",\"lat\":\"40.40412499978462\",\"lon\":\"-3.5643343002563848\"}",
|
|
"payloadType": "json",
|
|
"x": 270,
|
|
"y": 320,
|
|
"wires": [
|
|
[
|
|
"ab02b07ce8843526"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "33cf314d5cca7423",
|
|
"type": "worldmap in",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"path": "/worldmap",
|
|
"events": "connect,disconnect,point,layer,bounds,files,draw,other",
|
|
"x": 460,
|
|
"y": 760,
|
|
"wires": [
|
|
[
|
|
"bae0846569936702"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "bae0846569936702",
|
|
"type": "debug",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "debug 1",
|
|
"active": false,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 610,
|
|
"y": 760,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "acae736839e9942c",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Creación de la tabla de servicios_geo",
|
|
"query": "SELECT id_servicio,\n ST_AsGeoJSON(geom)::json AS geom\nFROM servicios_geo;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 390,
|
|
"y": 60,
|
|
"wires": [
|
|
[
|
|
"e0f0d5d6ac05abf7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "d9c3487d5a4cd9f2",
|
|
"type": "inject",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 100,
|
|
"wires": [
|
|
[
|
|
"8115125206120309"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "e0f0d5d6ac05abf7",
|
|
"type": "debug",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "debug 2",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 660,
|
|
"y": 120,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "b34c1a218cd45651",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Consulta h3",
|
|
"query": "SELECT h3_lat_lng_to_cell(POINT('37.7749, -122.4194'), 9) AS h3_index;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 290,
|
|
"y": 180,
|
|
"wires": [
|
|
[
|
|
"e0f0d5d6ac05abf7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b6be2c6139d939f0",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Consultar solo 500",
|
|
"query": "SELECT id_servicio,\n ST_AsGeoJSON(geom)::json AS geom\nFROM servicios_geo\nORDER BY id_servicio\nLIMIT 500",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 410,
|
|
"y": 120,
|
|
"wires": [
|
|
[
|
|
"e0f0d5d6ac05abf7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "9fbe677b4f48e523",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Hablitar extension h3",
|
|
"query": "CREATE EXTENSION h3;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 540,
|
|
"y": 200,
|
|
"wires": [
|
|
[
|
|
"e0f0d5d6ac05abf7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2af33006f75c5667",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Consulta h3",
|
|
"query": "SELECT h3_lat_lng_to_cell(\n point(ST_X(geom), ST_Y(geom)), -- lon, lat\n 7\n ) AS h3,\n COUNT(*) AS total\nFROM servicios_geo\nGROUP BY h3\nORDER BY total DESC;\n",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 310,
|
|
"y": 500,
|
|
"wires": [
|
|
[
|
|
"e0f0d5d6ac05abf7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "8115125206120309",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Consulta h3",
|
|
"query": "SELECT h3_lat_lng_to_cell(\n point(ST_Y(geom), ST_X(geom)), -- lat, lon\n 7\n ) AS h3,\n COUNT(*) AS total\nFROM servicios_geo\nGROUP BY h3\nORDER BY total DESC;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 310,
|
|
"y": 560,
|
|
"wires": [
|
|
[
|
|
"e0f0d5d6ac05abf7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1b3c9cf08f33d013",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Consulta h3 con geojson",
|
|
"query": "SELECT \n h3_lat_lng_to_cell(point(ST_Y(geom), ST_X(geom)), 8) AS h3,\n COUNT(*) AS total\nFROM servicios_geo\nGROUP BY h3;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 350,
|
|
"y": 620,
|
|
"wires": [
|
|
[
|
|
"307dd85fbc2e3dc9"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "77fb49d72430c2b0",
|
|
"type": "inject",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 130,
|
|
"y": 620,
|
|
"wires": [
|
|
[
|
|
"1b3c9cf08f33d013"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b660069d0a42ba72",
|
|
"type": "debug",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "GEOJSON",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 710,
|
|
"y": 580,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "fa52e6e1059e9acc",
|
|
"type": "worldmap",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"lat": "40.41341559118809",
|
|
"lon": "-3.695097056880839",
|
|
"zoom": "9",
|
|
"layer": "OSMC",
|
|
"cluster": "",
|
|
"maxage": "",
|
|
"usermenu": "show",
|
|
"layers": "show",
|
|
"panit": "false",
|
|
"panlock": "false",
|
|
"zoomlock": "false",
|
|
"hiderightclick": "false",
|
|
"coords": "none",
|
|
"showgrid": "false",
|
|
"showruler": "false",
|
|
"allowFileDrop": "false",
|
|
"path": "/worldmap",
|
|
"overlist": "",
|
|
"maplist": "OSMG,OSMC,EsriT",
|
|
"mapname": "",
|
|
"mapurl": "",
|
|
"mapopt": "",
|
|
"mapwms": false,
|
|
"x": 700,
|
|
"y": 620,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "307dd85fbc2e3dc9",
|
|
"type": "function",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Pruebas",
|
|
"func": "let h3 = h3Js;\n\n// Validar que tenemos las librerías necesarias\nif (typeof h3 === 'undefined') {\n node.error(\"H3 library not available\");\n return null;\n}\n\nconst payload = msg.payload;\n\n// Obtener el total máximo para calcular el porcentaje\nconst maxTotal = Math.max(...payload.map(i => parseFloat(i.total)));\n\nconst features = [];\n\n// --- COLORES SEGÚN PORCENTAJE ---\nfunction getFillColor(pct) {\n if (pct <= 25) return \"#00ff00\"; // verde\n if (pct <= 50) return \"#ffff00\"; // amarillo\n if (pct <= 75) return \"#ffa500\"; // naranja\n return \"#ff0000\"; // rojo\n}\n\npayload.forEach(item => {\n const h3Index = item.h3;\n const total = parseFloat(item.total);\n\n try {\n const hexBoundary = h3.cellToBoundary(h3Index, true);\n const center = h3.cellToLatLng(h3Index);\n\n // Calcular porcentaje respecto al máximo\n const pct = maxTotal > 0 ? (total / maxTotal) * 100 : 0;\n\n const fillColor = getFillColor(pct);\n\n const feature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"h3\": h3Index,\n \"total\": total,\n \"pct\": pct.toFixed(2),\n \"name\": `H3: ${h3Index} - ${pct.toFixed(1)}%`,\n \"resolution\": h3.getResolution(h3Index),\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO\n \"fill\": fillColor,\n \"fill-opacity\": 0.5,\n \"stroke\": \"#000000\",\n \"stroke-width\": 1,\n \"stroke-opacity\": 0.9\n },\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [hexBoundary]\n }\n };\n\n features.push(feature);\n\n } catch (error) {\n node.warn(`Error procesando H3 index ${h3Index}: ${error}`);\n }\n});\n\n// FeatureCollection final\nmsg.payload = {\n \"type\": \"FeatureCollection\",\n \"features\": features,\n \"Layer\": \"H3 Layer\"\n};\n\nreturn msg;\n",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 540,
|
|
"y": 620,
|
|
"wires": [
|
|
[
|
|
"fa52e6e1059e9acc",
|
|
"b660069d0a42ba72"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "27eb0e7ea2d102b6",
|
|
"type": "function",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Funciona en modo básico con colores",
|
|
"func": "let h3 = h3Js;\n\n// Validar que tenemos las librerías necesarias\nif (typeof h3 === 'undefined') {\n node.error(\"H3 library not available\");\n return null;\n}\n\nconst payload = msg.payload;\nconst features = [];\n\n// --- FUNCIONES PARA ASIGNAR COLORES SEGÚN EL TOTAL ---\nfunction getFillColor(total) {\n if (total <= 10) return \"#00ff00\"; // verde\n if (total <= 50) return \"#ffff00\"; // amarillo\n if (total <= 100) return \"#ffa500\"; // naranja\n return \"#ff0000\"; // rojo\n}\n\nfunction getStrokeColor(total) {\n return \"#000000\"; // negro (puedes cambiarlo o hacerlo dinámico también)\n}\n\n// Recorrer cada elemento del array\npayload.forEach(item => {\n const h3Index = item.h3;\n const total = parseInt(item.total);\n\n try {\n // Obtener los vértices del hexágono H3\n const hexBoundary = h3.cellToBoundary(h3Index, true);\n\n // Obtener el centro del hexágono\n const center = h3.cellToLatLng(h3Index);\n\n // Colores dinámicos\n const fillColor = getFillColor(total);\n const strokeColor = getStrokeColor(total);\n\n // Crear feature GeoJSON con estilo\n const feature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"h3\": h3Index,\n \"total\": total,\n \"value\": total,\n \"name\": `H3: ${h3Index} - Total: ${total}`,\n \"resolution\": h3.getResolution(h3Index),\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ---- ESTILO AÑADIDO ----\n \"fill\": fillColor,\n \"fill-opacity\": 0.5, // ajustable\n \"stroke\": strokeColor,\n \"stroke-width\": 1, // ajustable\n \"stroke-opacity\": 0.9 // ajustable\n },\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [hexBoundary]\n }\n };\n\n features.push(feature);\n\n } catch (error) {\n node.warn(`Error procesando H3 index ${h3Index}: ${error}`);\n }\n});\n\n// Crear el GeoJSON completo\nconst geojson = {\n \"type\": \"FeatureCollection\",\n \"features\": features,\n \"Layer\": \"H3 Layer\"\n};\n\nmsg.payload = geojson;\nreturn msg;\n",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 210,
|
|
"y": 760,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "e66c124d5be0c92e",
|
|
"type": "postgresql",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Consultar solo 500",
|
|
"query": "SELECT *\nFROM servicios_geo\nWHERE tipo_servicio != 'Base'\nLIMIT 500;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 790,
|
|
"y": 340,
|
|
"wires": [
|
|
[
|
|
"95e107f031aca0fa"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b76d4632ea730780",
|
|
"type": "inject",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 610,
|
|
"y": 340,
|
|
"wires": [
|
|
[
|
|
"e66c124d5be0c92e"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "95e107f031aca0fa",
|
|
"type": "debug",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "debug 3",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 960,
|
|
"y": 340,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "b2c5c01b68565205",
|
|
"type": "function",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Con colores por riesgo y demanda",
|
|
"func": "// NODE-RED FUNCTION: Visualizar H3 con predicciones y grúas\nconst h3 = h3Js; // Asegúrate de que h3Js está cargado globalmente\n\n// Validar librerías\nif (typeof h3 === 'undefined') {\n node.error(\"H3 library not available\");\n return null;\n}\n\nconst payload = msg.payload;\n\n// Extraer datos del payload de tu API\nconst week = payload.week || 0;\nconst dow = payload.dow || 0;\nconst hour = payload.hour || 0;\nconst recommendedH3 = payload.recommended_h3 || [];\nconst statistics = payload.statistics || [];\nconst coverage = payload.coverage || {};\nconst predictionData = payload.prediction_data || []; // Si tienes datos de predicción por celda\n\n// Si no hay datos de predicción, podemos generarlos a partir de statistics\nlet allH3Data = [];\nif (predictionData.length > 0) {\n // Si la API ya devuelve datos por celda\n allH3Data = predictionData;\n} else if (statistics.length > 0) {\n // Crear datos a partir de statistics (solo celdas con grúas)\n allH3Data = statistics.map(stat => ({\n h3: stat.h3,\n expected_demand: stat.expected_demand,\n nulo_probability: stat.nulo_probability,\n risk: stat.risk,\n coverage_radius: stat.coverage_radius,\n is_grua: true\n }));\n}\n\nconst features = [];\n\n// --- COLORES SEGÚN RIESGO ---\nfunction getRiskColor(risk, maxRisk) {\n if (maxRisk <= 0) return \"#00ff00\";\n\n const pct = (risk / maxRisk) * 100;\n\n if (pct <= 25) return \"#00ff00\"; // verde (bajo riesgo)\n if (pct <= 50) return \"#ffff00\"; // amarillo\n if (pct <= 75) return \"#ffa500\"; // naranja\n return \"#ff0000\"; // rojo (alto riesgo)\n}\n\n// --- COLORES SEGÚN DEMANDA ---\nfunction getDemandColor(demand) {\n if (demand < 2) return \"#00ff00\"; // verde (baja demanda)\n if (demand < 5) return \"#ffff00\"; // amarillo (media demanda)\n return \"#ff0000\"; // rojo (alta demanda)\n}\n\n// --- COLORES PARA GRÚAS ---\nfunction getGruaColor(index) {\n const colors = [\"#0000ff\", \"#ff00ff\", \"#00ffff\", \"#800080\"];\n return colors[index % colors.length];\n}\n\n// Calcular máximos para escalado de colores\nconst maxRisk = allH3Data.length > 0 ? Math.max(...allH3Data.map(i => parseFloat(i.risk || 0))) : 1;\nconst maxDemand = allH3Data.length > 0 ? Math.max(...allH3Data.map(i => parseFloat(i.expected_demand || 0))) : 1;\n\n// 1. Primero, pintar todas las celdas H3 con predicciones\nallH3Data.forEach((item, idx) => {\n const h3Index = item.h3;\n const risk = parseFloat(item.risk || 0);\n const demand = parseFloat(item.expected_demand || 0);\n const nuloProb = parseFloat(item.nulo_probability || 0);\n const isGrua = item.is_grua || false;\n const coverageRadius = item.coverage_radius || 0;\n\n try {\n const hexBoundary = h3.cellToBoundary(h3Index, true);\n const center = h3.cellToLatLng(h3Index);\n\n // Determinar color basado en riesgo\n const fillColor = getRiskColor(risk, maxRisk);\n\n // Opacidad diferente para grúas\n const fillOpacity = isGrua ? 0.8 : 0.4;\n\n // Ancho de borde diferente para grúas\n const strokeWidth = isGrua ? 3 : 1;\n const strokeColor = isGrua ? \"#000000\" : \"#333333\";\n\n // Texto para tooltip\n let tooltip = `H3: ${h3Index}`;\n tooltip += `\\\\nDemanda: ${demand.toFixed(2)}`;\n tooltip += `\\\\nProb. Nulo: ${(nuloProb * 100).toFixed(1)}%`;\n tooltip += `\\\\nRiesgo: ${risk.toFixed(3)}`;\n if (isGrua) {\n tooltip += `\\\\n🚨 GRÚA (Radio: ${coverageRadius})`;\n }\n\n const feature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"h3\": h3Index,\n \"risk\": risk,\n \"demand\": demand,\n \"nulo_probability\": nuloProb,\n \"coverage_radius\": coverageRadius,\n \"is_grua\": isGrua,\n \"name\": tooltip,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO\n \"fill\": fillColor,\n \"fill-opacity\": fillOpacity,\n \"stroke\": strokeColor,\n \"stroke-width\": strokeWidth,\n \"stroke-opacity\": 0.9,\n\n // Metadata adicional\n \"marker-type\": isGrua ? \"grua\" : \"prediction\"\n },\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [hexBoundary]\n }\n };\n\n features.push(feature);\n\n } catch (error) {\n node.warn(`Error procesando H3 index ${h3Index}: ${error}`);\n }\n});\n\n// 2. Añadir áreas de cobertura de las grúas (círculos)\nstatistics.forEach((grua, gruaIndex) => {\n try {\n const h3Index = grua.h3;\n const radius = grua.coverage_radius || 12;\n const cellsCovered = grua.cells_covered || 0;\n\n // Obtener celdas en el radio de cobertura\n const coveredCells = h3.gridDisk(h3Index, radius);\n\n // Crear polígono para el área de cobertura (opcional, puede ser pesado)\n // En su lugar, podemos crear un círculo aproximado\n\n const center = h3.cellToLatLng(h3Index);\n\n // Crear feature para el área de cobertura\n const coverageFeature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `Área cobertura Grúa ${gruaIndex + 1}`,\n \"grua_h3\": h3Index,\n \"radius\": radius,\n \"cells_covered\": cellsCovered,\n \"risk_covered\": grua.risk_covered || 0,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO (semi-transparente)\n \"fill\": getGruaColor(gruaIndex),\n \"fill-opacity\": 0.2,\n \"stroke\": getGruaColor(gruaIndex),\n \"stroke-width\": 2,\n \"stroke-opacity\": 0.5,\n \"marker-type\": \"coverage_area\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [center[1], center[0]]\n }\n };\n\n features.push(coverageFeature);\n\n // Añadir marcador para la grúa\n const gruaMarker = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `🚨 Grúa ${gruaIndex + 1}`,\n \"description\": `Demanda: ${grua.expected_demand?.toFixed(2) || 0}\\\\nRadio: ${radius}\\\\nCeldas cubiertas: ${cellsCovered}`,\n \"grua_index\": gruaIndex + 1,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO para marcador\n \"marker-color\": getGruaColor(gruaIndex),\n \"marker-size\": \"large\",\n \"marker-symbol\": \"warehouse\",\n \"marker-type\": \"grua_marker\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [center[1], center[0]]\n }\n };\n\n features.push(gruaMarker);\n\n } catch (error) {\n node.warn(`Error procesando área de cobertura para grúa ${grua.h3}: ${error}`);\n }\n});\n\n// 3. Añadir información general como feature\nconst infoFeature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": \"Información del Análisis\",\n \"description\": `Semana ${week}, Día ${dow}, Hora ${hour}\\\\n` +\n `Cobertura: ${coverage.coverage_percentage?.toFixed(2) || 0}%\\\\n` +\n `Riesgo cubierto: ${coverage.risk_coverage_percentage?.toFixed(2) || 0}%\\\\n` +\n `Grúas recomendadas: ${recommendedH3.length}`,\n \"marker-type\": \"info\",\n \"marker-color\": \"#333333\",\n \"marker-symbol\": \"info\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [-3.7038, 40.4168] // Madrid como referencia\n }\n};\n\nfeatures.push(infoFeature);\n\n// FeatureCollection final\nmsg.payload = {\n \"type\": \"FeatureCollection\",\n \"features\": features,\n \"metadata\": {\n \"week\": week,\n \"dow\": dow,\n \"hour\": hour,\n \"total_gruas\": recommendedH3.length,\n \"coverage_percentage\": coverage.coverage_percentage || 0,\n \"risk_coverage_percentage\": coverage.risk_coverage_percentage || 0,\n \"total_cells\": coverage.total_cells || 0,\n \"cells_covered\": coverage.cells_covered || 0\n },\n \"Layer\": \"H3 Predictions & Gruas\"\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 340,
|
|
"y": 960,
|
|
"wires": [
|
|
[
|
|
"ac4ac0ee965cef89",
|
|
"572948d3a25d485f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ac4ac0ee965cef89",
|
|
"type": "worldmap",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "",
|
|
"lat": "",
|
|
"lon": "",
|
|
"zoom": "",
|
|
"layer": "",
|
|
"cluster": "",
|
|
"maxage": "",
|
|
"usermenu": "show",
|
|
"layers": "show",
|
|
"panit": "false",
|
|
"panlock": "false",
|
|
"zoomlock": "false",
|
|
"hiderightclick": "false",
|
|
"coords": "false",
|
|
"showgrid": "false",
|
|
"showruler": "false",
|
|
"allowFileDrop": "false",
|
|
"path": "/worldmap",
|
|
"overlist": "DR,CO,RA,DN",
|
|
"maplist": "OSMG,OSMC,EsriC,EsriS,UKOS",
|
|
"mapname": "",
|
|
"mapurl": "",
|
|
"mapopt": "",
|
|
"mapwms": false,
|
|
"x": 640,
|
|
"y": 960,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "32e2494f462cc6f4",
|
|
"type": "link in",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "link in 1",
|
|
"links": [
|
|
"b63c955f07e230f1",
|
|
"c1552a91a92da199"
|
|
],
|
|
"x": 125,
|
|
"y": 1080,
|
|
"wires": [
|
|
[
|
|
"572948d3a25d485f",
|
|
"4bbf565e7701cb10"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2fc1745ca3803fcb",
|
|
"type": "function",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Solo ver las gruas",
|
|
"func": "// VERSIÓN MÍNIMA - Solo muestra las grúas\nconst h3 = h3Js;\nconst payload = msg.payload;\nconst recommendedH3 = payload.recommended_h3 || [];\n\nconst features = recommendedH3.map((h3Index, index) => {\n try {\n const center = h3.cellToLatLng(h3Index);\n return {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `Grúa ${index + 1}: ${h3Index}`,\n \"h3\": h3Index,\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [center[1], center[0]]\n }\n };\n } catch (e) {\n return null;\n }\n}).filter(f => f !== null);\n\nmsg.payload = {\n \"type\": \"FeatureCollection\",\n \"features\": features,\n \"icon\": \"truck\",\n \"layer\": \"H3 Gruas\"\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 290,
|
|
"y": 920,
|
|
"wires": [
|
|
[
|
|
"ac4ac0ee965cef89",
|
|
"572948d3a25d485f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "572948d3a25d485f",
|
|
"type": "debug",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "debug 17",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 640,
|
|
"y": 1080,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "19a26466059a3db1",
|
|
"type": "function",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Con colores con probabilidad",
|
|
"func": "// NODE-RED FUNCTION: Visualizar H3 con predicciones y grúas\nconst h3 = h3Js; // Asegúrate de que h3Js está cargado globalmente\n\n// Validar librerías\nif (typeof h3 === 'undefined') {\n node.error(\"H3 library not available\");\n return null;\n}\n\nconst payload = msg.payload;\n\n// Extraer datos del payload de tu API\nconst week = payload.week || 0;\nconst dow = payload.dow || 0;\nconst hour = payload.hour || 0;\nconst recommendedH3 = payload.recommended_h3 || [];\nconst statistics = payload.statistics || [];\nconst coverage = payload.coverage || {};\nconst predictionData = payload.prediction_data || []; // Si tienes datos de predicción por celda\n\n// Si no hay datos de predicción, podemos generarlos a partir de statistics\nlet allH3Data = [];\nif (predictionData.length > 0) {\n // Si la API ya devuelve datos por celda\n allH3Data = predictionData;\n} else if (statistics.length > 0) {\n // Crear datos a partir de statistics (solo celdas con grúas)\n allH3Data = statistics.map(stat => ({\n h3: stat.h3,\n expected_demand: stat.expected_demand,\n nulo_probability: stat.nulo_probability,\n risk: stat.risk,\n coverage_radius: stat.coverage_radius,\n is_grua: true\n }));\n}\n\nconst features = [];\n\n// --- COLORES SEGÚN PROBABILIDAD DE NULO ---\nfunction getNuloColor(nuloProbability) {\n // Convertir a porcentaje (si viene como decimal)\n const pct = nuloProbability <= 1 ? nuloProbability * 100 : nuloProbability;\n\n if (pct < 25) return \"#00ff00\"; // verde (baja probabilidad de nulo)\n if (pct < 50) return \"#ffff00\"; // amarillo\n if (pct < 75) return \"#ffa500\"; // naranja\n return \"#ff0000\"; // rojo (alta probabilidad de nulo)\n}\n\n// --- COLORES PARA GRÚAS ---\nfunction getGruaColor(index) {\n const colors = [\"#0000ff\", \"#ff00ff\", \"#00ffff\", \"#800080\"];\n return colors[index % colors.length];\n}\n\n// 1. Primero, pintar todas las celdas H3 con predicciones\nallH3Data.forEach((item, idx) => {\n const h3Index = item.h3;\n const risk = parseFloat(item.risk || 0);\n const demand = parseFloat(item.expected_demand || 0);\n const nuloProb = parseFloat(item.nulo_probability || 0);\n const isGrua = item.is_grua || false;\n const coverageRadius = item.coverage_radius || 0;\n\n try {\n const hexBoundary = h3.cellToBoundary(h3Index, true);\n const center = h3.cellToLatLng(h3Index);\n\n // Determinar color basado en probabilidad de nulo\n const fillColor = getNuloColor(nuloProb);\n\n // Opacidad diferente para grúas\n const fillOpacity = isGrua ? 0.8 : 0.4;\n\n // Ancho de borde diferente para grúas\n const strokeWidth = isGrua ? 3 : 1;\n const strokeColor = isGrua ? \"#000000\" : \"#333333\";\n\n // Texto para tooltip\n let tooltip = `H3: ${h3Index}`;\n tooltip += `\\\\nDemanda: ${demand.toFixed(2)}`;\n tooltip += `\\\\nProb. Nulo: ${(nuloProb * 100).toFixed(1)}%`;\n tooltip += `\\\\nRiesgo: ${risk.toFixed(3)}`;\n if (isGrua) {\n tooltip += `\\\\n🚨 GRÚA (Radio: ${coverageRadius})`;\n }\n\n const feature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"h3\": h3Index,\n \"risk\": risk,\n \"demand\": demand,\n \"nulo_probability\": nuloProb,\n \"coverage_radius\": coverageRadius,\n \"is_grua\": isGrua,\n \"name\": tooltip,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO\n \"fill\": fillColor,\n \"fill-opacity\": fillOpacity,\n \"stroke\": strokeColor,\n \"stroke-width\": strokeWidth,\n \"stroke-opacity\": 0.9,\n\n // Metadata adicional\n \"marker-type\": isGrua ? \"grua\" : \"prediction\",\n // Añadir nivel de color para referencia\n \"nulo_level\": nuloProb <= 0.25 ? \"bajo\" :\n nuloProb <= 0.5 ? \"medio\" :\n nuloProb <= 0.75 ? \"alto\" : \"muy_alto\"\n },\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [hexBoundary]\n }\n };\n\n features.push(feature);\n\n } catch (error) {\n node.warn(`Error procesando H3 index ${h3Index}: ${error}`);\n }\n});\n\n// 2. Añadir áreas de cobertura de las grúas (círculos)\nstatistics.forEach((grua, gruaIndex) => {\n try {\n const h3Index = grua.h3;\n const radius = grua.coverage_radius || 12;\n const cellsCovered = grua.cells_covered || 0;\n\n // Obtener celdas en el radio de cobertura\n const coveredCells = h3.gridDisk(h3Index, radius);\n\n // Crear polígono para el área de cobertura (opcional, puede ser pesado)\n // En su lugar, podemos crear un círculo aproximado\n\n const center = h3.cellToLatLng(h3Index);\n\n // Crear feature para el área de cobertura\n const coverageFeature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `Área cobertura Grúa ${gruaIndex + 1}`,\n \"grua_h3\": h3Index,\n \"radius\": radius,\n \"cells_covered\": cellsCovered,\n \"risk_covered\": grua.risk_covered || 0,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO (semi-transparente)\n \"fill\": getGruaColor(gruaIndex),\n \"fill-opacity\": 0.2,\n \"stroke\": getGruaColor(gruaIndex),\n \"stroke-width\": 2,\n \"stroke-opacity\": 0.5,\n \"marker-type\": \"coverage_area\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [center[1], center[0]]\n }\n };\n\n features.push(coverageFeature);\n\n // Añadir marcador para la grúa\n const gruaMarker = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `🚨 Grúa ${gruaIndex + 1}`,\n \"description\": `Demanda: ${grua.expected_demand?.toFixed(2) || 0}\\\\nProb. Nulo: ${(grua.nulo_probability * 100).toFixed(1)}%\\\\nRadio: ${radius}\\\\nCeldas cubiertas: ${cellsCovered}`,\n \"grua_index\": gruaIndex + 1,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO para marcador\n \"marker-color\": getGruaColor(gruaIndex),\n \"marker-size\": \"large\",\n \"marker-symbol\": \"warehouse\",\n \"marker-type\": \"grua_marker\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [center[1], center[0]]\n }\n };\n\n features.push(gruaMarker);\n\n } catch (error) {\n node.warn(`Error procesando área de cobertura para grúa ${grua.h3}: ${error}`);\n }\n});\n\n// 3. Añadir información general como feature\nconst infoFeature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": \"Información del Análisis\",\n \"description\": `Semana ${week}, Día ${dow}, Hora ${hour}\\\\n` +\n `Cobertura: ${coverage.coverage_percentage?.toFixed(2) || 0}%\\\\n` +\n `Riesgo cubierto: ${coverage.risk_coverage_percentage?.toFixed(2) || 0}%\\\\n` +\n `Grúas recomendadas: ${recommendedH3.length}`,\n \"marker-type\": \"info\",\n \"marker-color\": \"#333333\",\n \"marker-symbol\": \"info\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [-3.7038, 40.4168] // Madrid como referencia\n }\n};\n\nfeatures.push(infoFeature);\n\n// FeatureCollection final\nmsg.payload = {\n \"type\": \"FeatureCollection\",\n \"features\": features,\n \"metadata\": {\n \"week\": week,\n \"dow\": dow,\n \"hour\": hour,\n \"total_gruas\": recommendedH3.length,\n \"coverage_percentage\": coverage.coverage_percentage || 0,\n \"risk_coverage_percentage\": coverage.risk_coverage_percentage || 0,\n \"total_cells\": coverage.total_cells || 0,\n \"cells_covered\": coverage.cells_covered || 0,\n \"color_schema\": \"nulo_probability\" // Indicar qué esquema de color se usa\n },\n \"Layer\": \"H3 Predictions & Gruas\"\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 320,
|
|
"y": 1000,
|
|
"wires": [
|
|
[
|
|
"ac4ac0ee965cef89",
|
|
"572948d3a25d485f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "4bbf565e7701cb10",
|
|
"type": "function",
|
|
"z": "f511dd2230a153e7",
|
|
"name": "Con colores con probabilidad",
|
|
"func": "// NODE-RED FUNCTION: Visualizar H3 con predicciones y grúas\nconst h3 = h3Js; // Asegúrate de que h3Js está cargado globalmente\n\n// Validar librerías\nif (typeof h3 === 'undefined') {\n node.error(\"H3 library not available\");\n return null;\n}\n\nconst payload = msg.payload;\n\n// Extraer datos del payload de tu API\nconst week = payload.semana || 0;\nconst dow = payload.dia_semana || 0;\nconst hour = payload.hora || 0;\nconst recommendedH3 = payload.h3_recomendados || [];\nconst statistics = payload.estadisticas || [];\nconst coverage = payload.cobertura || {};\nconst predictionData = payload.datos_prediccion || []; // Si tienes datos de predicción por celda\n\n// Si no hay datos de predicción, podemos generarlos a partir de statistics\nlet allH3Data = [];\nif (predictionData.length > 0) {\n // Si la API ya devuelve datos por celda\n allH3Data = predictionData;\n} else if (statistics.length > 0) {\n // Crear datos a partir de statistics (solo celdas con grúas)\n allH3Data = statistics.map(stat => ({\n h3: stat.h3,\n expected_demand: stat.expected_demand,\n nulo_probability: stat.nulo_probability,\n risk: stat.risk,\n coverage_radius: stat.coverage_radius,\n is_grua: true\n }));\n}\n\nconst features = [];\n\n// --- FUNCIÓN PARA GRADIENTE DE COLOR SEGÚN PROBABILIDAD DE NULO ---\nfunction getNuloGradientColor(nuloProbability) {\n // Asegurar que el valor esté entre 0 y 1\n let pct = Math.max(0, Math.min(1, nuloProbability));\n\n // Gradiente de verde (0) a rojo (1)\n const red = Math.floor(255 * pct); // Aumenta con la probabilidad\n const green = Math.floor(255 * (1 - pct)); // Disminuye con la probabilidad\n const blue = 0; // Sin componente azul\n\n return `rgb(${red}, ${green}, ${blue})`;\n}\n\n// --- FUNCIÓN PARA CREAR CÍRCULO GEOJSON ---\nfunction createCircle(center, radiusInKm, points = 32) {\n const coords = [];\n const [lat, lng] = center;\n\n // Radio de la Tierra en kilómetros\n const earthRadius = 6371;\n\n // Convertir radio de kilómetros a radianes\n const radiusRad = radiusInKm / earthRadius;\n\n for (let i = 0; i < points; i++) {\n const angle = (i * 2 * Math.PI) / points;\n\n // Coordenadas del punto en el círculo\n const circleLat = Math.asin(\n Math.sin(lat * Math.PI / 180) * Math.cos(radiusRad) +\n Math.cos(lat * Math.PI / 180) * Math.sin(radiusRad) * Math.cos(angle)\n ) * 180 / Math.PI;\n\n const circleLng = lng + Math.atan2(\n Math.sin(angle) * Math.sin(radiusRad) * Math.cos(lat * Math.PI / 180),\n Math.cos(radiusRad) - Math.sin(lat * Math.PI / 180) * Math.sin(circleLat * Math.PI / 180)\n ) * 180 / Math.PI;\n\n coords.push([circleLng, circleLat]);\n }\n\n // Cerrar el polígono\n coords.push(coords[0]);\n\n return coords;\n}\n\n// --- COLORES PARA GRÚAS ---\nfunction getGruaColor(index) {\n const colors = [\"#0000ff\", \"#ff00ff\", \"#00ffff\", \"#800080\", \"#008000\", \"#800000\"];\n return colors[index % colors.length];\n}\n\n// 1. Primero, pintar todas las celdas H3 con predicciones\nallH3Data.forEach((item, idx) => {\n const h3Index = item.h3;\n const risk = parseFloat(item.risk || 0);\n const demand = parseFloat(item.expected_demand || 0);\n const nuloProb = parseFloat(item.nulo_probability || 0);\n const isGrua = item.is_grua || false;\n const coverageRadius = item.coverage_radius || 0;\n\n try {\n const hexBoundary = h3.cellToBoundary(h3Index, true);\n const center = h3.cellToLatLng(h3Index);\n\n // Determinar color con gradiente basado en probabilidad de nulo\n const fillColor = getNuloGradientColor(nuloProb);\n\n // Opacidad variable según probabilidad de nulo (más opaco para alta probabilidad)\n const fillOpacity = isGrua ? 0.8 : (0.3 + (nuloProb * 0.5));\n\n // Ancho de borde diferente para grúas\n const strokeWidth = isGrua ? 3 : 1;\n const strokeColor = isGrua ? \"#000000\" :\n nuloProb > 0.5 ? \"#222222\" : \"#555555\";\n\n // Texto para tooltip\n let tooltip = `H3: ${h3Index}`;\n tooltip += ` Demanda: ${demand.toFixed(2)}`;\n tooltip += ` Prob. Nulo: ${(nuloProb * 100).toFixed(1)}%`;\n tooltip += ` Riesgo: ${risk.toFixed(3)}`;\n if (isGrua) {\n tooltip += `\\\\n🚨 GRÚA (Radio: ${coverageRadius} celdas)`;\n }\n\n const feature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"h3\": h3Index,\n \"risk\": risk,\n \"demand\": demand,\n \"nulo_probability\": nuloProb,\n \"nulo_percentage\": (nuloProb * 100).toFixed(1),\n \"coverage_radius\": coverageRadius,\n \"is_grua\": isGrua,\n \"name\": tooltip,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO\n \"fill\": fillColor,\n \"fill-opacity\": fillOpacity,\n \"stroke\": strokeColor,\n \"stroke-width\": strokeWidth,\n \"stroke-opacity\": 0.9,\n\n // Metadata adicional para leyenda\n \"marker-type\": isGrua ? \"grua\" : \"prediction\",\n \"color_intensity\": nuloProb,\n \"color_category\": nuloProb < 0.25 ? \"bajo\" :\n nuloProb < 0.5 ? \"medio-bajo\" :\n nuloProb < 0.75 ? \"medio-alto\" : \"alto\"\n },\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [hexBoundary]\n }\n };\n\n features.push(feature);\n\n } catch (error) {\n node.warn(`Error procesando H3 index ${h3Index}: ${error}`);\n }\n});\n\n// 2. Añadir áreas de cobertura de las grúas como círculos\nstatistics.forEach((grua, gruaIndex) => {\n try {\n const h3Index = grua.h3;\n const radius = grua.coverage_radius || 12;\n const cellsCovered = grua.cells_covered || 0;\n const nuloProb = parseFloat(grua.nulo_probability || 0);\n\n const center = h3.cellToLatLng(h3Index);\n\n // Calcular radio aproximado en kilómetros\n // Nota: El radio en H3 es en número de celdas, no en km\n // Para convertir a km, necesitamos la resolución de las celdas\n // Asumimos resolución 9 (aprox 0.1 km² por celda)\n const cellAreaKm2 = 0.2; // Área aproximada de celda H3 res 9 en km²\n const cellDiameterKm = Math.sqrt(cellAreaKm2) * 2; // Diámetro aproximado en km\n const radiusKm = radius * cellDiameterKm;\n\n // Crear círculo para el área de cobertura\n const circleCoords = createCircle(center, radiusKm, 64);\n\n // Color para esta grúa\n const gruaColor = getGruaColor(gruaIndex);\n\n // Crear feature para el área de cobertura (círculo)\n const coverageFeature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `Área cobertura Grúa ${gruaIndex + 1}`,\n \"description\": `Radio: ${radius}<br> celdas (≈${radiusKm.toFixed(1)} km)<br>` +\n `Celdas cubiertas: ${cellsCovered}<br>` +\n `Prob. Nulo: ${(nuloProb * 100).toFixed(1)}%`,\n \"grua_h3\": h3Index,\n \"grua_index\": gruaIndex + 1,\n \"radius_cells\": radius,\n \"radius_km\": radiusKm.toFixed(1),\n \"cells_covered\": cellsCovered,\n \"risk_covered\": grua.risk_covered || 0,\n \"lat\": center[0],\n \"lon\": center[1],\n \"grua_color\": gruaColor,\n\n // ESTILO (semi-transparente)\n \"fill\": gruaColor,\n \"fill-opacity\": 0.15,\n \"stroke\": gruaColor,\n \"stroke-width\": 3,\n \"stroke-opacity\": 0.6,\n \"stroke-dasharray\": \"5,5\", // Línea punteada para mejor visibilidad\n \"marker-type\": \"coverage_area\"\n },\n \"geometry\": {\n \"type\": \"Polygon\",\n \"coordinates\": [circleCoords]\n }\n };\n\n features.push(coverageFeature);\n\n // Añadir marcador para la grúa en el centro\n const gruaMarker = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": `🚨 Grúa ${gruaIndex + 1}`,\n \"description\": `<br>Prob. Nulo: ${(nuloProb * 100).toFixed(1)}%<br>` +\n `Demanda: ${grua.expected_demand?.toFixed(2) || 0}<br>` +\n `Radio: ${radius} celdas (≈${radiusKm.toFixed(1)} km)<br>` +\n `Celdas cubiertas: ${cellsCovered}`,\n \"grua_index\": gruaIndex + 1,\n \"grua_color\": gruaColor,\n \"lat\": center[0],\n \"lon\": center[1],\n\n // ESTILO para marcador\n \"marker-color\": gruaColor,\n \"marker-size\": \"large\",\n \"marker-symbol\": \"truck\",\n \"marker-type\": \"grua_center\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [center[1], center[0]]\n }\n };\n\n features.push(gruaMarker);\n\n } catch (error) {\n node.warn(`Error procesando área de cobertura para grúa ${grua.h3}: ${error}`);\n }\n});\n\n// 3. Añadir información general como feature\nconst infoFeature = {\n \"type\": \"Feature\",\n \"properties\": {\n \"name\": \"Información del Análisis\",\n \"description\": `Semana: ${week} Día: ${dow} Hora: ${hour}<br>` +\n `Cobertura: ${coverage.coverage_percentage?.toFixed(2) || 0}%<br>` +\n `Riesgo cubierto: ${coverage.risk_coverage_percentage?.toFixed(2) || 0}%<br>` +\n `Grúas recomendadas: ${recommendedH3.length}<br>` +\n `🎨 Colores: Gradiente por probabilidad de nulo<br>` +\n `⭕ Círculos: Áreas de cobertura de grúas`,\n \"marker-type\": \"info\",\n \"marker-color\": \"#333333\",\n \"marker-symbol\": \"info\"\n },\n \"geometry\": {\n \"type\": \"Point\",\n \"coordinates\": [-3.7038, 40.4168] // Madrid como referencia\n }\n};\n\nfeatures.push(infoFeature);\n\n// FeatureCollection final\nmsg.payload = {\n \"type\": \"FeatureCollection\",\n \"features\": features,\n \"metadata\": {\n \"week\": week,\n \"dow\": dow,\n \"hour\": hour,\n \"total_gruas\": recommendedH3.length,\n \"coverage_percentage\": coverage.coverage_percentage || 0,\n \"risk_coverage_percentage\": coverage.risk_coverage_percentage || 0,\n \"total_cells\": coverage.total_cells || 0,\n \"cells_covered\": coverage.cells_covered || 0,\n \"color_schema\": \"nulo_probability_gradient\",\n \"gradient_min\": \"#00ff00\", // Verde\n \"gradient_max\": \"#ff0000\", // Rojo\n \"color_explanation\": \"Verde (0% nulo) → Rojo (100% nulo)\"\n },\n \"layer\": \"H3\"\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [
|
|
{
|
|
"var": "h3Js",
|
|
"module": "h3-js"
|
|
}
|
|
],
|
|
"x": 320,
|
|
"y": 1040,
|
|
"wires": [
|
|
[
|
|
"572948d3a25d485f",
|
|
"ac4ac0ee965cef89"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "c7c7d9aedc600352",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Generamos la vista básica de H3 con 8",
|
|
"query": "-- 1.1 Vista básica con h3 (nivel 8)\nCREATE OR REPLACE VIEW vw_servicios_h3 AS\nSELECT\n id,\n id_servicio,\n fecha_entrada,\n fecha_servicio,\n codigo_grua,\n tipo_servicio,\n geom,\n h3_lat_lng_to_cell(point(ST_Y(geom), ST_X(geom)), 8) AS h3,\n EXTRACT(HOUR FROM fecha_servicio AT TIME ZONE 'UTC')::int AS hour,\n EXTRACT(DOW FROM fecha_servicio AT TIME ZONE 'UTC')::int AS dow, -- 0 = Domingo\n EXTRACT(WEEK FROM fecha_servicio AT TIME ZONE 'UTC')::int AS week,\n CASE WHEN tipo_servicio = 'Requerimiento nulo' THEN 1 ELSE 0 END AS is_nulo\nFROM servicios_geo;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 360,
|
|
"y": 120,
|
|
"wires": [
|
|
[
|
|
"eab6c7a9df1e6c8c"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "e65ea3eb95cf6c9f",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 120,
|
|
"wires": [
|
|
[
|
|
"c7c7d9aedc600352"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "eab6c7a9df1e6c8c",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 4",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 120,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "a1c78ddc8ef1f1fd",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Generamos el nivel de demanda por hora y día de la semana modelo SQL",
|
|
"query": "-- Conteo por (dia de la semana y hora)\nCREATE OR REPLACE VIEW vw_total_by_hour_dow AS\nSELECT\n dow,\n hour,\n COUNT(*) AS total_hour_dow\nFROM vw_servicios_h3\nGROUP BY dow, hour\nORDER BY dow, hour;\n\n--- Calcular valores para día de la semana y hora, asignamos un demand_level\nCREATE OR REPLACE VIEW vw_hour_levels_dow AS\nWITH counts AS (\n SELECT dow, hour, total_hour_dow\n FROM vw_total_by_hour_dow\n),\npercentiles_per_dow AS (\n SELECT\n dow,\n percentile_cont(0.3333) WITHIN GROUP (ORDER BY total_hour_dow) AS q1,\n percentile_cont(0.6666) WITHIN GROUP (ORDER BY total_hour_dow) AS q2\n FROM counts\n GROUP BY dow\n)\nSELECT\n c.dow,\n c.hour,\n c.total_hour_dow,\n CASE\n WHEN c.total_hour_dow <= p.q1 THEN 'baja'\n WHEN c.total_hour_dow <= p.q2 THEN 'media'\n ELSE 'alta'\n END AS demand_level\nFROM counts c\nJOIN percentiles_per_dow p ON p.dow = c.dow\nORDER BY c.dow, c.hour;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 460,
|
|
"y": 180,
|
|
"wires": [
|
|
[
|
|
"e9272483eeab8c19"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "e9272483eeab8c19",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 5",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 180,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "0bec605824bbb7ea",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 180,
|
|
"wires": [
|
|
[
|
|
"a1c78ddc8ef1f1fd"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "6b5cc73d3ff597e3",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Generamos la vista de servicios etiquetados por demanda según el horario",
|
|
"query": "CREATE OR REPLACE VIEW vw_servicios_labeled AS\nSELECT s.*,\n hl.demand_level\nFROM vw_servicios_h3 s\nLEFT JOIN vw_hour_levels_dow hl\n ON s.dow = hl.dow AND s.hour = hl.hour;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 470,
|
|
"y": 240,
|
|
"wires": [
|
|
[
|
|
"ae7888f46928631e"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b2f0b35e19e565c8",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Generamos la vista de demanda_h3_hour",
|
|
"query": "--- Generamos la vista de la demanda h3 por hora modelo sql\nCREATE OR REPLACE VIEW demanda_h3_hour AS\nSELECT\n s.h3,\n s.hour,\n s.dow,\n hl.demand_level,\n COUNT(*)::int AS total_events,\n SUM(s.is_nulo)::int AS total_nulos,\n CASE WHEN COUNT(*)=0 THEN 0.0 ELSE SUM(s.is_nulo)::double precision / COUNT(*) END AS nulo_rate\nFROM vw_servicios_labeled s\nLEFT JOIN vw_hour_levels_dow hl\n ON hl.dow = s.dow\n AND hl.hour = s.hour\nGROUP BY s.h3, s.hour, s.dow, hl.demand_level;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 360,
|
|
"y": 300,
|
|
"wires": [
|
|
[
|
|
"b7999a625ea2a4f7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "94425a5d1997a6de",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Verificaciones",
|
|
"query": "--- revision de valores\nSELECT * FROM vw_hour_levels_dow ORDER BY dow, hour;\n--- por servicio tiene que tener un nivel de demanda\nSELECT * FROM vw_servicios_labeled LIMIT 20;\n--- la agregación de los valores es correcta\nSELECT * FROM demanda_h3_hour ORDER BY total_events DESC LIMIT 20;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 280,
|
|
"y": 360,
|
|
"wires": [
|
|
[
|
|
"f11aaa2122049f7e"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "6181e6dc62c93438",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 240,
|
|
"wires": [
|
|
[
|
|
"6b5cc73d3ff597e3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "01d5f95df74d1a4b",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 300,
|
|
"wires": [
|
|
[
|
|
"b2f0b35e19e565c8"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1c5af8b39a382a49",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 360,
|
|
"wires": [
|
|
[
|
|
"94425a5d1997a6de"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ae7888f46928631e",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 6",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 240,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "b7999a625ea2a4f7",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 7",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 300,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "f11aaa2122049f7e",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 8",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 360,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "1a960e62640178c4",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 480,
|
|
"wires": [
|
|
[
|
|
"239bb9ceb6c8f1a2"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "239bb9ceb6c8f1a2",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"method": "GET",
|
|
"ret": "txt",
|
|
"paytoqs": "ignore",
|
|
"url": "http://10.10.14.70:5000/predict?hour=11&dow=1&total_events=3",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 270,
|
|
"y": 480,
|
|
"wires": [
|
|
[
|
|
"3bbe9a72ae47d0d3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "3bbe9a72ae47d0d3",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 9",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 440,
|
|
"y": 480,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "df2b3c5fccde910c",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Generamos la vista de demanda_h3_hour_ml",
|
|
"query": "--- Generamos la vista de la demanda h3 por hora modelo ml\nCREATE OR REPLACE VIEW demanda_h3_hour_ml AS\nSELECT\n h3,\n week,\n dow,\n hour,\n COUNT(*)::int AS total_events,\n SUM(is_nulo)::int AS total_nulos,\n CASE\n WHEN COUNT(*) = 0 THEN 0\n ELSE SUM(is_nulo)::float / COUNT(*)\n END AS nulo_rate\nFROM vw_servicios_h3\nGROUP BY h3, week, dow, hour;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 380,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"4b916996a32da5f8"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "010bdecaa9c98232",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"df2b3c5fccde910c"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "4b916996a32da5f8",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 10",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 420,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "29d73c2064e1eba6",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 60,
|
|
"wires": [
|
|
[
|
|
"f56d3d761eefad37"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "f56d3d761eefad37",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Limpieza de la vistas",
|
|
"query": "DROP VIEW IF EXISTS vw_servicios_h3 CASCADE;",
|
|
"postgreSQLConfig": "748b5921246ec468",
|
|
"split": false,
|
|
"rowsPerMsg": 1,
|
|
"outputs": 1,
|
|
"x": 300,
|
|
"y": 60,
|
|
"wires": [
|
|
[
|
|
"716a760504fb3ce1"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "716a760504fb3ce1",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 11",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 940,
|
|
"y": 60,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "3b3a9ea3a19ff7e5",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "TRAIN",
|
|
"method": "POST",
|
|
"ret": "txt",
|
|
"paytoqs": "ignore",
|
|
"url": "http://python:5000/train",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 250,
|
|
"y": 540,
|
|
"wires": [
|
|
[
|
|
"5290cdca42f99d2c"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "4faac7a3217d6419",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 540,
|
|
"wires": [
|
|
[
|
|
"3b3a9ea3a19ff7e5"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "5290cdca42f99d2c",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 12",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 440,
|
|
"y": 540,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "ce865e88acfa3de3",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "MODELS",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "http://python:5000/models",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 260,
|
|
"y": 600,
|
|
"wires": [
|
|
[
|
|
"43f0ea10327964bc"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "41583ff4f043ae6d",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 600,
|
|
"wires": [
|
|
[
|
|
"ce865e88acfa3de3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "43f0ea10327964bc",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 13",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 440,
|
|
"y": 600,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "740a140db7cd93f9",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 660,
|
|
"wires": [
|
|
[
|
|
"7d0ae91a06114c05"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "7d0ae91a06114c05",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "RECOMMEND",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "http://10.10.11.211:5000/recommend?week=42&dow=3&hour=14&k=2",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 280,
|
|
"y": 660,
|
|
"wires": [
|
|
[
|
|
"f27c12eab34c0d48"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "f27c12eab34c0d48",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 14",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 620,
|
|
"y": 660,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "c630ce9f80c77046",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "RECOMMEND - OPTIMIZED GRUAS",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "http://python:5000/recommend?week=42&dow=3&hour=14&optimize=true&min_gruas=1&max_gruas=5&include_cell_data=true",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 350,
|
|
"y": 700,
|
|
"wires": [
|
|
[
|
|
"1d6ef76f3145f9d3",
|
|
"b63c955f07e230f1"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1d6ef76f3145f9d3",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 15",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 620,
|
|
"y": 700,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "e50b886e6d4a366e",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 700,
|
|
"wires": [
|
|
[
|
|
"c630ce9f80c77046"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b96227cc7c8c3bcd",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 740,
|
|
"wires": [
|
|
[
|
|
"dea2827d47fce819"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "dea2827d47fce819",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "RECOMMEND - OPTIMIZED COVERAGED",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "http://python:5000/recommend?week=42&dow=3&hour=14&optimize=true&target_coverage=95&include_cell_data=true",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 370,
|
|
"y": 740,
|
|
"wires": [
|
|
[
|
|
"289ab66bd5b46e06",
|
|
"b63c955f07e230f1"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "289ab66bd5b46e06",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 16",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 620,
|
|
"y": 740,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "b63c955f07e230f1",
|
|
"type": "link out",
|
|
"z": "230815bb0628a63e",
|
|
"name": "link out 1",
|
|
"mode": "link",
|
|
"links": [
|
|
"32e2494f462cc6f4"
|
|
],
|
|
"x": 265,
|
|
"y": 900,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "36934d545031c7fd",
|
|
"type": "inject",
|
|
"z": "230815bb0628a63e",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "",
|
|
"payloadType": "date",
|
|
"x": 110,
|
|
"y": 960,
|
|
"wires": [
|
|
[
|
|
"148399ac5cb60fa4"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "148399ac5cb60fa4",
|
|
"type": "http request",
|
|
"z": "230815bb0628a63e",
|
|
"name": "PREDICT",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "http://10.10.11.211:5000/predict?model_type=demand",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 260,
|
|
"y": 960,
|
|
"wires": [
|
|
[
|
|
"7b7e2d456a6ff158"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "7b7e2d456a6ff158",
|
|
"type": "debug",
|
|
"z": "230815bb0628a63e",
|
|
"name": "debug 18",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 400,
|
|
"y": 960,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "cee897cd4088d738",
|
|
"type": "ui-template",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "f8afeee042444067",
|
|
"page": "",
|
|
"ui": "",
|
|
"name": "Mapa Embebido",
|
|
"order": 1,
|
|
"width": 12,
|
|
"height": "9",
|
|
"head": "",
|
|
"format": "<iframe src=\"/worldmap\" style=\"width:100%; height:100%; border:none;\">\n</iframe>",
|
|
"storeOutMessages": true,
|
|
"passthru": true,
|
|
"resendOnRefresh": true,
|
|
"templateScope": "local",
|
|
"className": "",
|
|
"x": 120,
|
|
"y": 80,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "c2bb3385f15f27e1",
|
|
"type": "ui-text-input",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"name": "Calendario",
|
|
"label": "Fecha Estimación:",
|
|
"order": 1,
|
|
"width": 0,
|
|
"height": 0,
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"mode": "datetime-local",
|
|
"tooltip": "Añada la fecha en la que quiera la estimación ",
|
|
"delay": 300,
|
|
"passthru": false,
|
|
"sendOnDelay": false,
|
|
"sendOnBlur": true,
|
|
"sendOnEnter": true,
|
|
"className": "",
|
|
"clearable": true,
|
|
"sendOnClear": false,
|
|
"icon": "",
|
|
"iconPosition": "left",
|
|
"iconInnerPosition": "inside",
|
|
"x": 330,
|
|
"y": 40,
|
|
"wires": [
|
|
[
|
|
"a37879075935bb78"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "8236702597bcb3d2",
|
|
"type": "ui-slider",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"name": "Cobertura",
|
|
"label": "Cobertura",
|
|
"tooltip": "",
|
|
"order": 3,
|
|
"width": 0,
|
|
"height": 0,
|
|
"passthru": false,
|
|
"outs": "end",
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"thumbLabel": "true",
|
|
"showTicks": "false",
|
|
"min": "50",
|
|
"max": "95",
|
|
"step": 1,
|
|
"className": "",
|
|
"iconPrepend": "",
|
|
"iconAppend": "",
|
|
"color": "green",
|
|
"colorTrack": "red",
|
|
"colorThumb": "",
|
|
"showTextField": true,
|
|
"x": 320,
|
|
"y": 140,
|
|
"wires": [
|
|
[
|
|
"387fe5c1fac19afe"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "a67e9a88c70fb435",
|
|
"type": "ui-number-input",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"name": "Gruas",
|
|
"label": "Número de Grúas disponibles",
|
|
"order": 4,
|
|
"width": 0,
|
|
"height": 0,
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"min": "1",
|
|
"max": 10,
|
|
"step": 1,
|
|
"tooltip": "Número de gruas disponibles para las estimaciones",
|
|
"passthru": false,
|
|
"sendOnBlur": true,
|
|
"sendOnEnter": true,
|
|
"className": "",
|
|
"clearable": true,
|
|
"icon": "",
|
|
"iconPosition": "left",
|
|
"iconInnerPosition": "inside",
|
|
"spinner": "default",
|
|
"x": 310,
|
|
"y": 200,
|
|
"wires": [
|
|
[
|
|
"d62279b67e0184f1"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "e2fe0aeabbab5ac6",
|
|
"type": "ui-button-group",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "Opciones",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"order": 2,
|
|
"width": "",
|
|
"height": "",
|
|
"label": "Parámetros para las estimaciones:",
|
|
"className": "",
|
|
"rounded": false,
|
|
"useThemeColors": true,
|
|
"passthru": false,
|
|
"options": [
|
|
{
|
|
"label": "Optimo",
|
|
"icon": "map-search",
|
|
"value": "optimo",
|
|
"valueType": "str",
|
|
"color": "#009933"
|
|
},
|
|
{
|
|
"label": "Grúas ",
|
|
"icon": "truck-flatbed",
|
|
"value": "gruas",
|
|
"valueType": "str",
|
|
"color": "#999999"
|
|
}
|
|
],
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"x": 320,
|
|
"y": 80,
|
|
"wires": [
|
|
[
|
|
"9e77a7b3c8e11460"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "a8f18f06a75851a1",
|
|
"type": "ui-button",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"name": "Limpieza",
|
|
"label": "Borrar los datos del mapa",
|
|
"order": 7,
|
|
"width": 0,
|
|
"height": 0,
|
|
"emulateClick": true,
|
|
"tooltip": "",
|
|
"color": "",
|
|
"bgcolor": "",
|
|
"className": "",
|
|
"icon": "",
|
|
"iconPosition": "left",
|
|
"payload": "{\"command\":{\"clearlayer\":[\"H3\",\"layer2\"]}}",
|
|
"payloadType": "json",
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"buttonColor": "",
|
|
"textColor": "",
|
|
"iconColor": "",
|
|
"enableClick": true,
|
|
"enablePointerdown": false,
|
|
"pointerdownPayload": "",
|
|
"pointerdownPayloadType": "str",
|
|
"enablePointerup": false,
|
|
"pointerupPayload": "",
|
|
"pointerupPayloadType": "str",
|
|
"x": 320,
|
|
"y": 360,
|
|
"wires": [
|
|
[
|
|
"26adce90744a441d"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "f78b5cc7dc506422",
|
|
"type": "ui-button",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"name": "Mostrar",
|
|
"label": "Calcular los datos",
|
|
"order": 6,
|
|
"width": 0,
|
|
"height": 0,
|
|
"emulateClick": false,
|
|
"tooltip": "",
|
|
"color": "",
|
|
"bgcolor": "",
|
|
"className": "",
|
|
"icon": "",
|
|
"iconPosition": "left",
|
|
"payload": "",
|
|
"payloadType": "str",
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"buttonColor": "",
|
|
"textColor": "",
|
|
"iconColor": "",
|
|
"enableClick": true,
|
|
"enablePointerdown": false,
|
|
"pointerdownPayload": "",
|
|
"pointerdownPayloadType": "str",
|
|
"enablePointerup": false,
|
|
"pointerupPayload": "",
|
|
"pointerupPayloadType": "str",
|
|
"x": 120,
|
|
"y": 520,
|
|
"wires": [
|
|
[
|
|
"fa837f38ed1dbc1e"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "fe084cbbae83b4fa",
|
|
"type": "worldmap",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"lat": "",
|
|
"lon": "",
|
|
"zoom": "",
|
|
"layer": "",
|
|
"cluster": "",
|
|
"maxage": "",
|
|
"usermenu": "show",
|
|
"layers": "show",
|
|
"panit": "false",
|
|
"panlock": "false",
|
|
"zoomlock": "false",
|
|
"hiderightclick": "false",
|
|
"coords": "false",
|
|
"showgrid": "false",
|
|
"showruler": "false",
|
|
"allowFileDrop": "false",
|
|
"path": "/worldmap",
|
|
"overlist": "DR,CO,RA,DN",
|
|
"maplist": "OSMG,OSMC,EsriC,EsriS,UKOS",
|
|
"mapname": "",
|
|
"mapurl": "",
|
|
"mapopt": "",
|
|
"mapwms": false,
|
|
"x": 140,
|
|
"y": 120,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "f42fd41cad44b2d1",
|
|
"type": "link in",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "IN - WorldMAP",
|
|
"links": [
|
|
"26adce90744a441d"
|
|
],
|
|
"x": 45,
|
|
"y": 120,
|
|
"wires": [
|
|
[
|
|
"fe084cbbae83b4fa"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "26adce90744a441d",
|
|
"type": "link out",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "OUT - Limpiar mapa",
|
|
"mode": "link",
|
|
"links": [
|
|
"f42fd41cad44b2d1"
|
|
],
|
|
"x": 695,
|
|
"y": 360,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "a796d79ddb167eb1",
|
|
"type": "ui-dropdown",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"name": "Tráfico",
|
|
"label": "Densidad del tráfico (opcional)",
|
|
"tooltip": "",
|
|
"order": 5,
|
|
"width": 0,
|
|
"height": 0,
|
|
"passthru": false,
|
|
"multiple": false,
|
|
"chips": false,
|
|
"clearable": false,
|
|
"options": [
|
|
{
|
|
"label": "Alto",
|
|
"value": 3,
|
|
"type": "num"
|
|
},
|
|
{
|
|
"label": "Normal",
|
|
"value": 2,
|
|
"type": "num"
|
|
},
|
|
{
|
|
"label": "Bajo",
|
|
"value": 1,
|
|
"type": "num"
|
|
},
|
|
{
|
|
"label": "Sin estimación",
|
|
"value": "0",
|
|
"type": "str"
|
|
}
|
|
],
|
|
"payload": "",
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"className": "",
|
|
"typeIsComboBox": true,
|
|
"msgTrigger": "onChange",
|
|
"x": 310,
|
|
"y": 280,
|
|
"wires": [
|
|
[
|
|
"c2fd67bee1b6e31f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ebf80c2abc415017",
|
|
"type": "ui-text",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "bb66042c3e7c9cb3",
|
|
"order": 8,
|
|
"width": 0,
|
|
"height": null,
|
|
"name": "Resultados",
|
|
"label": "",
|
|
"format": "{{msg.payload}}",
|
|
"layout": "row-left",
|
|
"style": true,
|
|
"font": "Helvetica, sans-serif",
|
|
"fontSize": 16,
|
|
"color": "#717171",
|
|
"wrapText": false,
|
|
"className": "",
|
|
"value": "payload",
|
|
"valueType": "msg",
|
|
"x": 590,
|
|
"y": 420,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "a37879075935bb78",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "calendario",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 530,
|
|
"y": 40,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "9e77a7b3c8e11460",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "opcion",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 540,
|
|
"y": 80,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "5387e2228122ee16",
|
|
"type": "inject",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "Incializar Valores",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": true,
|
|
"onceDelay": "1",
|
|
"topic": "",
|
|
"payload": "iso",
|
|
"payloadType": "date",
|
|
"x": 130,
|
|
"y": 40,
|
|
"wires": [
|
|
[
|
|
"c2bb3385f15f27e1",
|
|
"e2fe0aeabbab5ac6",
|
|
"8236702597bcb3d2",
|
|
"a67e9a88c70fb435",
|
|
"a796d79ddb167eb1"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "387fe5c1fac19afe",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "cobertura",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 530,
|
|
"y": 140,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "d62279b67e0184f1",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "gruas",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 540,
|
|
"y": 200,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "5eedba05f8e677de",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "trafico",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 700,
|
|
"y": 300,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "8afe796111cb8c8d",
|
|
"type": "switch",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "opcion",
|
|
"property": "opcion",
|
|
"propertyType": "flow",
|
|
"rules": [
|
|
{
|
|
"t": "eq",
|
|
"v": "gruas",
|
|
"vt": "str"
|
|
},
|
|
{
|
|
"t": "eq",
|
|
"v": "optimo",
|
|
"vt": "str"
|
|
},
|
|
{
|
|
"t": "else"
|
|
}
|
|
],
|
|
"checkall": "true",
|
|
"repair": false,
|
|
"outputs": 3,
|
|
"x": 90,
|
|
"y": 780,
|
|
"wires": [
|
|
[
|
|
"16926b851536025d"
|
|
],
|
|
[
|
|
"9c6f7af87438a4bd"
|
|
],
|
|
[
|
|
"ec90eeee993b765a"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "447113b576ecfcba",
|
|
"type": "ui-notification",
|
|
"z": "56fb69eb622c3f3b",
|
|
"ui": "3afa9de4406d30d8",
|
|
"position": "top right",
|
|
"colorDefault": true,
|
|
"color": "#000000",
|
|
"displayTime": "10",
|
|
"showCountdown": true,
|
|
"outputs": 1,
|
|
"allowDismiss": true,
|
|
"dismissText": "Cerrar",
|
|
"allowConfirm": true,
|
|
"confirmText": "Aceptar",
|
|
"raw": false,
|
|
"className": "",
|
|
"name": "",
|
|
"x": 630,
|
|
"y": 880,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "fa837f38ed1dbc1e",
|
|
"type": "function",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "Calculamos la fecha",
|
|
"func": "let fecha = new Date(flow.get(\"calendario\"));\n\nif (isNaN(fecha.getTime())) {\n node.error(\"Fecha inválida\", msg);\n return null;\n}\n\nconst firstDayOfYear = new Date(fecha.getFullYear(), 0, 1);\n// @ts-ignore\nconst pastDaysOfYear = (fecha - firstDayOfYear) / 86400000;\nconst week = Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);\n\nconst dow = fecha.getDay();\n\nconst hour = fecha.getHours();\n\nmsg.payload = { week, dow, hour };\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 300,
|
|
"y": 520,
|
|
"wires": [
|
|
[
|
|
"8afe796111cb8c8d"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ec90eeee993b765a",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "payload",
|
|
"pt": "msg",
|
|
"to": "Es necesario indicar que calculo se necesita si por cobertura o por número de gruas.",
|
|
"tot": "str"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 340,
|
|
"y": 880,
|
|
"wires": [
|
|
[
|
|
"447113b576ecfcba"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "9c6f7af87438a4bd",
|
|
"type": "switch",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "cobertura",
|
|
"property": "cobertura",
|
|
"propertyType": "flow",
|
|
"rules": [
|
|
{
|
|
"t": "istype",
|
|
"v": "number",
|
|
"vt": "number"
|
|
},
|
|
{
|
|
"t": "else"
|
|
}
|
|
],
|
|
"checkall": "true",
|
|
"repair": false,
|
|
"outputs": 2,
|
|
"x": 260,
|
|
"y": 780,
|
|
"wires": [
|
|
[
|
|
"91d413e80d8139af"
|
|
],
|
|
[
|
|
"9af49346793df573"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "9af49346793df573",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "payload",
|
|
"pt": "msg",
|
|
"to": "Es necesario indicar la cobertura requerida",
|
|
"tot": "str"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 460,
|
|
"y": 820,
|
|
"wires": [
|
|
[
|
|
"447113b576ecfcba"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "11b08389769a3a9f",
|
|
"type": "http request",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 870,
|
|
"y": 760,
|
|
"wires": [
|
|
[
|
|
"c1552a91a92da199"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "91d413e80d8139af",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "url",
|
|
"pt": "msg",
|
|
"to": "\"http://python:5000/recommend?week=\" & payload.week &\t\"&dow=\" & payload.dow &\t\"&hour=\" & payload.hour &\t\"&traffic=\" & $flowContext(\"trafico\") &\t\"&optimize=true&include_cell_data=true&min_gruas=1&max_gruas=\" & $flowContext(\"gruas\") &\t\"&target_coverage=\" & $flowContext(\"cobertura\")",
|
|
"tot": "jsonata"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 690,
|
|
"y": 760,
|
|
"wires": [
|
|
[
|
|
"11b08389769a3a9f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "c1552a91a92da199",
|
|
"type": "link out",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "link out 2",
|
|
"mode": "link",
|
|
"links": [
|
|
"32e2494f462cc6f4",
|
|
"68707cddaa9512b9"
|
|
],
|
|
"x": 1055,
|
|
"y": 620,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "16926b851536025d",
|
|
"type": "switch",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "gruas",
|
|
"property": "gruas",
|
|
"propertyType": "flow",
|
|
"rules": [
|
|
{
|
|
"t": "istype",
|
|
"v": "number",
|
|
"vt": "number"
|
|
},
|
|
{
|
|
"t": "else"
|
|
}
|
|
],
|
|
"checkall": "true",
|
|
"repair": false,
|
|
"outputs": 2,
|
|
"x": 250,
|
|
"y": 680,
|
|
"wires": [
|
|
[
|
|
"dcd489d1ae63d998"
|
|
],
|
|
[
|
|
"1cd6a1eb10de5864"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1cd6a1eb10de5864",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "payload",
|
|
"pt": "msg",
|
|
"to": "Es necesario indicar las gruas disponibles",
|
|
"tot": "str"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 460,
|
|
"y": 720,
|
|
"wires": [
|
|
[
|
|
"447113b576ecfcba"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "dcd489d1ae63d998",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "url",
|
|
"pt": "msg",
|
|
"to": "\"http://python:5000/recommend?week=\" & payload.week &\t\"&dow=\" & payload.dow &\t\"&hour=\" & payload.hour &\t\"&traffic=\" & $flowContext(\"trafico\") &\t\"&optimize=false&include_cell_data=true&k=\" & $flowContext(\"gruas\")",
|
|
"tot": "jsonata"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 690,
|
|
"y": 660,
|
|
"wires": [
|
|
[
|
|
"2e7fc0d864b209e7"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2e7fc0d864b209e7",
|
|
"type": "http request",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"method": "GET",
|
|
"ret": "obj",
|
|
"paytoqs": "ignore",
|
|
"url": "",
|
|
"tls": "",
|
|
"persist": false,
|
|
"proxy": "",
|
|
"insecureHTTPParser": false,
|
|
"authType": "",
|
|
"senderr": false,
|
|
"headers": [],
|
|
"x": 870,
|
|
"y": 660,
|
|
"wires": [
|
|
[
|
|
"c1552a91a92da199"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "4de317cc487a47c6",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "payload",
|
|
"pt": "msg",
|
|
"to": "\"<b>Resultados:</b><br><br>\" & \"Riesgo cubierto: \" & payload.cobertura.risk_coverage_percentage &\t \" %<br>\" & \"Cobertura total: \" & payload.cobertura.coverage_percentage &\t \" %\"",
|
|
"tot": "jsonata"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 360,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"ebf80c2abc415017"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "68707cddaa9512b9",
|
|
"type": "link in",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "link in 2",
|
|
"links": [
|
|
"c1552a91a92da199"
|
|
],
|
|
"x": 215,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"4de317cc487a47c6"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "c2fd67bee1b6e31f",
|
|
"type": "switch",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "Limpiamos tráfico",
|
|
"property": "payload",
|
|
"propertyType": "msg",
|
|
"rules": [
|
|
{
|
|
"t": "eq",
|
|
"v": "0",
|
|
"vt": "num"
|
|
},
|
|
{
|
|
"t": "else"
|
|
}
|
|
],
|
|
"checkall": "true",
|
|
"repair": false,
|
|
"outputs": 2,
|
|
"x": 470,
|
|
"y": 280,
|
|
"wires": [
|
|
[
|
|
"ea73de854d597030"
|
|
],
|
|
[
|
|
"5eedba05f8e677de"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ea73de854d597030",
|
|
"type": "change",
|
|
"z": "56fb69eb622c3f3b",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "delete",
|
|
"p": "trafico",
|
|
"pt": "flow"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 690,
|
|
"y": 260,
|
|
"wires": [
|
|
[]
|
|
]
|
|
}
|
|
] |