1205 lines
38 KiB
JSON
1205 lines
38 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": "My Dashboard",
|
|
"path": "/dashboard",
|
|
"appIcon": "",
|
|
"includeClientData": true,
|
|
"acceptsClientConfig": [
|
|
"ui-notification",
|
|
"ui-control"
|
|
],
|
|
"showPathInSidebar": false,
|
|
"headerContent": "page",
|
|
"navigationStyle": "default",
|
|
"titleBarStyle": "default",
|
|
"showReconnectNotification": true,
|
|
"notificationDisplayTime": 1,
|
|
"showDisconnectNotification": true,
|
|
"allowInstall": false
|
|
},
|
|
{
|
|
"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": "Page 1",
|
|
"ui": "3afa9de4406d30d8",
|
|
"path": "/page1",
|
|
"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": "Visualizador",
|
|
"page": "b332967d63ddbdfe",
|
|
"width": "8",
|
|
"height": "8",
|
|
"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": "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 = Sunday\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": 60,
|
|
"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": 60,
|
|
"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": 60,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "a1c78ddc8ef1f1fd",
|
|
"type": "postgresql",
|
|
"z": "230815bb0628a63e",
|
|
"name": "Generamos el nivel de demanda por hora y día de la semana",
|
|
"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": 420,
|
|
"y": 120,
|
|
"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": 120,
|
|
"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": 120,
|
|
"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": 180,
|
|
"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\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": 240,
|
|
"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": 300,
|
|
"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": 180,
|
|
"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": 240,
|
|
"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": 300,
|
|
"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": 180,
|
|
"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": 240,
|
|
"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": 300,
|
|
"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": 200,
|
|
"y": 380,
|
|
"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": 360,
|
|
"y": 380,
|
|
"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": 520,
|
|
"y": 380,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "cee897cd4088d738",
|
|
"type": "ui-template",
|
|
"z": "56fb69eb622c3f3b",
|
|
"group": "f8afeee042444067",
|
|
"page": "",
|
|
"ui": "",
|
|
"name": "Mapa Embebido",
|
|
"order": 1,
|
|
"width": 0,
|
|
"height": 0,
|
|
"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": 260,
|
|
"wires": [
|
|
[]
|
|
]
|
|
}
|
|
] |