[{"id":"96fcd6382cd351a6","type":"tab","label":"Envio a Meteoclimatic","disabled":false,"info":""},{"id":"274ba274ea04117d","type":"file in","z":"96fcd6382cd351a6","name":"Leer plantilla","filename":"meteoclimatic/meteoclimatic.html","filenameType":"str","format":"utf8","chunk":false,"sendError":true,"encoding":"none","allProps":false,"x":140,"y":120,"wires":[["8a9524fa049cde2e","4236d549c2902552"]]},{"id":"4236d549c2902552","type":"function","z":"96fcd6382cd351a6","name":"Convertir a base62 y crear query & url","func":"// Convertido del script Python de jmviper\n// Creditos a Meteocllimatic\n//\nfunction BaseConvert(number, fromdigits, todigits) {\n    let neg = \"\";\n    if (number[0] === \"-\") {\n        number = number.slice(1);\n        neg = \"-\";\n    }\n    let x = 0;\n    for (let n = 0; n < number.length; n++) {\n        const digit = number[n];\n        x = (x * fromdigits.length) + fromdigits.indexOf(digit);\n    }\n    let res = \"\";\n    while (x > 0) {\n        const digit = x % todigits.length;\n        res = todigits[digit] + res;\n        x = Math.floor(x / todigits.length);\n    }\n    if (neg) res = neg + res;\n    return res;\n}\n\n// Función intorfloat en JavaScript para Node-RED\nfunction intorfloat(number) {\n    number = String(number);\n    if (number.includes(\".\")) {\n        return parseFloat(number);\n    } else if (!isNaN(parseInt(number))) {\n        return parseInt(number);\n    } else {\n        return 0;\n    }\n}\n\nfunction rsentit(winddir) {\n    let sentit = winddir;\n    if (/^\\d+$/.test(winddir)) {  // Check if winddir is a digit\n        if (winddir === \"0\") winddir = \"36\";\n        return winddir;\n    }\n    switch (winddir) {\n        case \"N\":\n            sentit = \"360\";\n            break;\n        case \"NNE\":\n            sentit = \"23\";\n            break;\n        case \"NE\":\n            sentit = \"45\";\n            break;\n        case \"ENE\":\n            sentit = \"68\";\n            break;\n        case \"E\":\n            sentit = \"90\";\n            break;\n        case \"ESE\":\n            sentit = \"113\";\n            break;\n        case \"SE\":\n            sentit = \"135\";\n            break;\n        case \"SSE\":\n            sentit = \"158\";\n            break;\n        case \"S\":\n            sentit = \"180\";\n            break;\n        case \"SSW\":\n            sentit = \"203\";\n            break;\n        case \"SW\":\n            sentit = \"225\";\n            break;\n        case \"WSW\":\n            sentit = \"248\";\n            break;\n        case \"W\":\n            sentit = \"270\";\n            break;\n        case \"WNW\":\n            sentit = \"293\";\n            break;\n        case \"NW\":\n            sentit = \"315\";\n            break;\n        case \"NNW\":\n            sentit = \"338\";\n            break;\n        case \"SSO\":\n            sentit = \"203\";\n            break;\n        case \"SO\":\n            sentit = \"225\";\n            break;\n        case \"OSO\":\n            sentit = \"248\";\n            break;\n        case \"O\":\n            sentit = \"270\";\n            break;\n        case \"ONO\":\n            sentit = \"293\";\n            break;\n        case \"NO\":\n            sentit = \"315\";\n            break;\n        case \"NNO\":\n            sentit = \"338\";\n            break;\n        case \"N/A\":\n            sentit = \"0\";\n            break;\n    }\n    return sentit;\n}\n\n// Generar dict desde plantilla en fichero\nlet plantilla = msg.payload.split('\\n');\nlet valores = {};\n\nplantilla.forEach(i => {\n    i = i.substring(1);  // Elimina el primer carácter\n    if (i.includes('=')) {\n        let valor = i.trim().replace(',', '.');\n        let [clave, valorFinal] = valor.split('=');\n\n        // Comprobar si el valorFinal es numérico, si no lo es, asignar 0,\n        // salvo para las claves 'VER','COD','SIG' y 'UPD'\n        if (!isNaN(parseFloat(valorFinal)) && isFinite(valorFinal)) {\n            valores[clave] = valorFinal;\n        } else if (['VER', 'COD', 'SIG', 'UPD'].includes(clave)) {\n            valores[clave] = valorFinal;\n        } else {\n            valores[clave] = \"0\";\n        }\n    }\n});\n\n\n// INICIO Crear OTP --> NO LO REQUIERE -- Y ESO? -- COMO CONTROLAMOS EL UPDATE? -- CON EL SIG?\n\n//const crypto = require('crypto');  // Node.js crypto module\n// Recuperar el password del mensaje\n//const password = \"waspwasp\";  // Sustituye con el password real\n// Crear un hash MD5 del password\n//const hash = crypto.createHash('md5').update(password, 'utf8').digest('hex');\n// Tomar los primeros 10 caracteres del hash\n//const OTP = hash.substring(0, 10);\nconst OTP = \"aquipasswd\"\n\n//FIN Crear OTP\n\n// Definición de las bases de conversion\nconst BASE10 = \"0123456789\";\nconst BASE62 = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\n// Convertir valores numéricos en la plantilla a base62\n// Utilización de las funciones intorfloat y BaseConvert\nlet T = BaseConvert(String(parseInt(intorfloat(valores['TMP']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DHTM']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DLTM']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MHTM']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MLTM']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YHTM']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YLTM']) * 10)), BASE10, BASE62);\n\nlet H = BaseConvert(String(parseInt(intorfloat(valores['HUM']))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DHHM']))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DLHM']))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MHHM']))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MLHM']))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YHHM']))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YLHM']))), BASE10, BASE62);\n\nlet B = BaseConvert(String(parseInt(intorfloat(valores['BAR']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DHBR']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DLBR']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MHBR']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MLBR']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YHBR']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YLBR']) * 10)), BASE10, BASE62);\n\nlet W = BaseConvert(String(parseInt(intorfloat(rsentit(valores['AZI'])))), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['WND']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['WRUN']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DGST']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MGST']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YGST']) * 10)), BASE10, BASE62);\n\nlet P = BaseConvert(String(parseInt(intorfloat(valores['DPCP']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MPCP']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YPCP']) * 10)), BASE10, BASE62);\n\nlet S = BaseConvert(String(parseInt(intorfloat(valores['SUN']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DSUN']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MSUN']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YSUN']) * 10)), BASE10, BASE62);\n\nlet V = BaseConvert(String(parseInt(intorfloat(valores['UVI']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['DHUV']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['MHUV']) * 10)), BASE10, BASE62) + ';' +\n    BaseConvert(String(parseInt(intorfloat(valores['YHUV']) * 10)), BASE10, BASE62);\n\nlet U = \"3a;\" + valores['COD'] + \";\" + OTP;\n\nlet query = \"T=\" + T +\n    \"&H=\" + H +\n    \"&B=\" + B +\n    \"&W=\" + W +\n    \"&P=\" + P +\n    \"&S=\" + S +\n    \"&V=\" + V +\n    \"&U=\" + U;\n\n// EL sufijo no se requiere en Javascript\n//let suffix = '\" HTTP/1.0\\r\\nHOST: pool.meteoclimatic.com\\r\\nUser-Agent: Meteoclimatic_HTTP/1.0\\r\\n\\r\\n\").encode()'\n\nmsg.query = query;\nmsg.url = `http://pool.meteoclimatic.com/?${query}`; // El nodo de http get usará esta url\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[{"var":"cryptoJs","module":"crypto-js"}],"x":490,"y":120,"wires":[["d79fb6251539d176","6f27b4aaeeb07f4b"]]},{"id":"6f27b4aaeeb07f4b","type":"http request","z":"96fcd6382cd351a6","name":"Enviar por HTTP GET (usa msg.url)","method":"GET","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":920,"y":120,"wires":[["29f335cf988ac46d"]]},{"id":"29f335cf988ac46d","type":"debug","z":"96fcd6382cd351a6","name":"Resultado de envio","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":910,"y":220,"wires":[]},{"id":"09d5b40961537e3c","type":"inject","z":"96fcd6382cd351a6","name":"Iniciar flujo","props":[{"p":"payload"}],"repeat":"900","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":150,"y":40,"wires":[["274ba274ea04117d"]]},{"id":"8a9524fa049cde2e","type":"debug","z":"96fcd6382cd351a6","name":"Plantilla a procesar","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":170,"y":220,"wires":[]},{"id":"d79fb6251539d176","type":"debug","z":"96fcd6382cd351a6","name":"Query creado","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":460,"y":220,"wires":[]}]