{"id":3798,"date":"2021-10-24T17:07:25","date_gmt":"2021-10-24T22:07:25","guid":{"rendered":"http:\/\/blog.espol.edu.ec\/girni\/?p=3798"},"modified":"2026-08-04T10:35:22","modified_gmt":"2026-08-04T15:35:22","slug":"lorawan-leer-states-json-python","status":"publish","type":"post","link":"https:\/\/blog.espol.edu.ec\/girni\/lorawan-leer-states-json-python\/","title":{"rendered":"2.1 States.json - extraer datos.csv con Python"},"content":{"rendered":"\n<p>El procesamiento de los datos hist\u00f3ricos de \"<strong>un sensor<\/strong>\" en una ubicaci\u00f3n se realiza con Python desde el archivo generado en la secci\u00f3n anterior. Esta forma se obtiene un archivo nuevo y de menor tama\u00f1o para procesar con los datos de solo el dispositivo que se propone analizar.<\/p>\n\n\n\n<p class=\"has-text-align-center\"><a href=\"https:\/\/www.dropbox.com\/scl\/fi\/to49zdkw7e8yb5mbdgjkw\/states20211022.json?rlkey=q2z3hq4octqeylok4fazav0j0&amp;st=18rnjf46&amp;dl=0\">states20211022.json<\/a><\/p>\n\n\n\n<p>El formato de la tabla es el mismo que el observado en \"DB Browser\".<\/p>\n\n\n\n<figure class=\"wp-block-image alignwide size-full\"><a href=\"http:\/\/blog.espol.edu.ec\/girni\/files\/2021\/10\/DBBrowser04.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1294\" height=\"323\" src=\"https:\/\/blog.espol.edu.ec\/girni\/files\/2021\/10\/DBBrowser04.png\" alt=\"DB Browser 04\" class=\"wp-image-3799\" srcset=\"https:\/\/blog.espol.edu.ec\/girni\/files\/2021\/10\/DBBrowser04.png 1294w, https:\/\/blog.espol.edu.ec\/girni\/files\/2021\/10\/DBBrowser04-300x75.png 300w, https:\/\/blog.espol.edu.ec\/girni\/files\/2021\/10\/DBBrowser04-768x192.png 768w, https:\/\/blog.espol.edu.ec\/girni\/files\/2021\/10\/DBBrowser04-1024x256.png 1024w\" sizes=\"auto, (max-width: 1294px) 100vw, 1294px\" \/><\/a><\/figure>\n\n\n\n<p>Los campos a usar son principalmente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\"<strong><em>entity_id<\/em><\/strong>\" para la selecci\u00f3n de un sensor,<\/li>\n\n\n\n<li>\"<strong><em>attributes<\/em><\/strong>\" donde previamente se configur\u00f3 para guardar&nbsp; el mensaje mqtt de cada transmisi\u00f3n<\/li>\n\n\n\n<li>\"<strong><em>created<\/em><\/strong>\" que contine la fecha y hora de creaci\u00f3n del registro. referenciada a GMT=0.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Par\u00e1metros guardados en attributes<\/h2>\n\n\n\n<p>El campo \"<em><strong>attributes<\/strong><\/em>\" de cada registro contiene varios par\u00e1metros posibles a usar en el formato del mensaje. Un ejemplo del contenido se indica en el recuadro en rojo mostrado en lala figura anterior, y se presenta a continuaci\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>{<span style=\"color: #008000\">\"applicationID\"<\/span>:<span style=\"color: #008000\">\"4\"<\/span>,\n <span style=\"color: #008000\">\"applicationName\"<\/span>:<span style=\"color: #008000\">\"Leer_RssiSNR\"<\/span>,\n <span style=\"color: #008000\">\"deviceName\"<\/span>:<span style=\"color: #008000\">\"cc11Pruebas\"<\/span>,\n <span style=\"color: #008000\">\"devEUI\"<\/span>:<span style=\"color: #008000\">\"pT7GFa7ePxE=\"<\/span>,\n <span style=\"color: #008000\">\"rxInfo\"<\/span>:&#091;{<span style=\"color: #008000\">\"gatewayID\"<\/span>:<span style=\"color: #008000\">\"uCfr\/\/4dylc=\"<\/span>,\n            <span style=\"color: #008000\">\"time\"<\/span>:null,<span style=\"color: #008000\">\"timeSinceGPSEpoch\"<\/span>:null,\n            <span style=\"color: #008000\">\"rssi\"<\/span>:-63,\n            <span style=\"color: #008000\">\"loRaSNR\"<\/span>:10.8,\n            <span style=\"color: #008000\">\"channel\"<\/span>:3,\n            <span style=\"color: #008000\">\"rfChain\"<\/span>:0,\n            <span style=\"color: #008000\">\"board\"<\/span>:0,\n            <span style=\"color: #008000\">\"antenna\"<\/span>:0,\n            <span style=\"color: #008000\">\"location\"<\/span>:{<span style=\"color: #008000\">\"latitude\"<\/span>:-2.1418242484279535,\n                        <span style=\"color: #008000\">\"longitude\"<\/span>:-79.96711134910585,\n                        <span style=\"color: #008000\">\"altitude\"<\/span>:20,\n                        <span style=\"color: #008000\">\"source\"<\/span>:<span style=\"color: #008000\">\"UNKNOWN\"<\/span>,\n                        <span style=\"color: #008000\">\"accuracy\"<\/span>:0},\n            <span style=\"color: #008000\">\"fineTimestampType\"<\/span>:<span style=\"color: #008000\">\"NONE\"<\/span>,\n            <span style=\"color: #008000\">\"context\"<\/span>:<span style=\"color: #008000\">\"CmMVZA==\"<\/span>,\n            <span style=\"color: #008000\">\"uplinkID\"<\/span>:<span style=\"color: #008000\">\"I7NWhENCQyaFtYoZIDw3KQ==\"<\/span>,\n            <span style=\"color: #008000\">\"crcStatus\"<\/span>:<span style=\"color: #008000\">\"CRC_OK\"<\/span>}],\n <span style=\"color: #008000\">\"txInfo\"<\/span>:{<span style=\"color: #008000\">\"frequency\"<\/span>:902900000,\n           <span style=\"color: #008000\">\"modulation\"<\/span>:<span style=\"color: #008000\">\"LORA\"<\/span>,\n           <span style=\"color: #008000\">\"loRaModulationInfo\"<\/span>:{<span style=\"color: #008000\">\"bandwidth\"<\/span>:125,\n                                 <span style=\"color: #008000\">\"spreadingFactor\"<\/span>:10,\n                                 <span style=\"color: #008000\">\"codeRate\"<\/span>:<span style=\"color: #008000\">\"4\/5\"<\/span>,\n                                 <span style=\"color: #008000\">\"polarizationInversion\"<\/span>:false}\n           },\n <span style=\"color: #008000\">\"adr\"<\/span>:true,\n <span style=\"color: #008000\">\"dr\"<\/span>:0,\n <span style=\"color: #008000\">\"fCnt\"<\/span>:778,\n <span style=\"color: #008000\">\"fPort\"<\/span>:4,\n <span style=\"color: #008000\">\"data\"<\/span>:<span style=\"color: #008000\">\"KwcK9A8=\"<\/span>,\n <span style=\"color: #008000\">\"objectJSON\"<\/span>:<span style=\"color: #008000\">\"{\\\"Down_datarate\\\":10,\\\"Down_rssi\\\":-43,\\\"Down_snr\\\":7,\\\"bateria_V\\\":4.08}\"<\/span>,\n <span style=\"color: #008000\">\"tags\"<\/span>:{},\n <span style=\"color: #008000\">\"confirmedUplink\"<\/span>:true,\n <span style=\"color: #008000\">\"devAddr\"<\/span>:<span style=\"color: #008000\">\"AVqCdA==\"<\/span>,\n <span style=\"color: #008000\">\"publishedAt\"<\/span>:<span style=\"color: #008000\">\"2021-10-21T16:28:36.265518462Z\"<\/span>,\n <span style=\"color: #008000\">\"unit_of_measurement\"<\/span>:<span style=\"color: #008000\">\"dBm\"<\/span>,\n <span style=\"color: #008000\">\"friendly_name\"<\/span>:<span style=\"color: #008000\">\"rssi_up_cc11\"<\/span>\n }<\/code><\/pre>\n\n\n\n<p>El formato del ejemplo mostrado se realiz\u00f3 con el editor de Python para facilidad de lectura,<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Procesamiento de datos para un sensor<\/h2>\n\n\n\n<p>El procesamiento de cada registro se realiza separando los <strong>campos<\/strong> a usar, en una tabla los campos representan las&nbsp; columnas a usar.<\/p>\n\n\n\n<p>La selecci\u00f3n del dispositivos se realiza comparando con \"<strong>entity_id<\/strong>\".<\/p>\n\n\n\n<p>El intervalo de fechas permite usar ventanas de tiempo de observaci\u00f3n. La fecha y hora registrada se encuentra referenciadas a GMT=0, dado que en el pa\u00eds donde se realizan las muestras usa GMT=-5, se realiza un desplazamiento en las horas para facilitar la identificaci\u00f3n de las franjas horarias.<\/p>\n\n\n\n<p>Los identificadores de gateways se simplifican con el diccionario gateway, que deben ser previamente identificados buscando en el archivo.json como \"gatewayID\". Tambi\u00e9n se revisa el n\u00famero de trama (fCnt) para registrar las recepci\u00f3n de tramas repetidas en cada gateway, registrando los valores en una lista, para posteriormente, seleccionar el valor mayor, menor, promedio).<\/p>\n\n\n\n<p>Los par\u00e1metros de recepci\u00f3n en el gateway se encuentran en \"<strong><em>rx_datos<\/em><\/strong>\" en el siguiente orden: rssi, loRaSNR, channel, rfChain, frequency<\/p>\n\n\n\n<p>El resultado de la selecci\u00f3n de los datos se guarda en un nuevo archivo en formato<strong>.csv<\/strong> para facilitar la lectura de los datos con otros programas.<\/p>\n\n\n\n<p>Otra forma de guardar los datos en en formato.json, que puede ser le\u00edda con la librer\u00eda Pandas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Instrucciones en Python para tabla CSV<\/h2>\n\n\n<div class=\"wp-block-syntaxhighlighter-code alignwide\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# Lectura de archivo.json hacia una tabla0\n# selecciona registros de &quot;un sensor&quot;\n# graba unreporte.csv con pandas\n# http:\/\/blog.espol.edu.ec\/girni\/\n\nimport numpy as np\nimport json\nimport pandas as pd\nimport datetime as dt\nimport os\n\n# INGRESO\n# archivo de entrada\nunarchivoDB = &quot;states20211022.json&quot;\ncarpeta_DB  = &quot;BaseDatosJSON&quot;\n\n# fecha intervalo\nfechainicio = &quot;2021-10-21 11:00:00.0&quot;\nfechafin    = &quot;2021-10-22 11:50:00.0&quot;\nzonaGMT     = -5\n\nunsensor    = &quot;sensor.rssi_up_cc12&quot;\nmodelo_disp = &quot;modulo&quot; # capsula, modulo desarrollo\nubicado     = &quot;LOS22&quot;\ncarpeta_rsm = &quot;resultado_Test&quot;\n\n# gatewayID simplifica identificador \ngatewayDB   = {'uCfr\/\/4dylc=':'Gw03'}\n\n# PROCEDIMIENTO -----\ncampos = &#x5B;'domain','entity_id','state','attributes','created']\n\n# Lectura de archivo json, cambia a formato DataFrame\ntabla0 = pd.DataFrame()\narchivo_ruta  = carpeta_DB + '\/' + unarchivoDB\narchivoexiste = os.path.exists(archivo_ruta)\nif archivoexiste:\n    tabla0 = pd.read_json(archivo_ruta)\n    tabla0 = pd.DataFrame(tabla0,columns=campos)\nelse:\n    print(' ERROR: NO se encuentra el archivo...')\n    print('        revise el nombre de archivo. ')\n\n# Revisa cada registro \nleidos = 0\ntabla  = {}\nif archivoexiste:\n    # Intervalo de fecha como datetime\n    hora_desplaza  = dt.timedelta(hours = abs(zonaGMT))\n    fechaformatoDB = '%Y-%m-%dT%H:%M:%S.%f'\n    fechaformato   = '%Y-%m-%d %H:%M:%S.%f'\n    fechatxt     = fechainicio&#x5B;0:np.min(&#x5B;26,len(fechainicio)])]\n    fechainicio  = dt.datetime.strptime(fechatxt,fechaformato)\n    fechatxt     = fechafin&#x5B;0:np.min(&#x5B;26,len(fechafin)])]\n    fechafin     = dt.datetime.strptime(fechatxt,fechaformato)\n\n    # datos de trama\n    for cadaregistro in tabla0.index:\n        unatrama   = tabla0&#x5B;'attributes']&#x5B;cadaregistro]\n        trama_mqtt = json.loads(unatrama)\n        \n        # selecciona registro por sensor, en fecha y con datos\n        cualsensor = (tabla0&#x5B;'entity_id']&#x5B;cadaregistro] == unsensor)\n        \n        unafecha = tabla0&#x5B;'created']&#x5B;cadaregistro]\n        unafecha = unafecha&#x5B;0:np.min(&#x5B;26,len(unafecha)])]\n        unafecha = dt.datetime.strptime(unafecha,fechaformato)\n        unafecha = unafecha - hora_desplaza\n        \n        enfecha  = (unafecha&gt;=fechainicio) and (unafecha&lt;=fechafin)\n        condatos = 'applicationID' in trama_mqtt.keys()\n        \n        selecciona = cualsensor and condatos and enfecha\n        if (selecciona == True):        \n            # datos en la mensaje MQTT\n            publishedAt = trama_mqtt&#x5B;&quot;publishedAt&quot;]\n            publishedAt = publishedAt&#x5B;0:np.min(&#x5B;26,len(publishedAt)])]\n            publishedAt = dt.datetime.strptime(publishedAt,fechaformatoDB)\n            publishedAt = publishedAt - hora_desplaza\n            \n            friendly_name = trama_mqtt&#x5B;&quot;friendly_name&quot;]\n            deviceName    = trama_mqtt&#x5B;&quot;deviceName&quot;]\n            dispositivo   = friendly_name.split('_')&#x5B;2]\n            \n            dr      = trama_mqtt&#x5B;&quot;dr&quot;]\n            fCnt    = trama_mqtt&#x5B;&quot;fCnt&quot;]\n            fPort   = trama_mqtt&#x5B;&quot;fPort&quot;]\n            freq_tx = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;frequency&quot;]\n            bandwidth = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;loRaModulationInfo&quot;]&#x5B;&quot;bandwidth&quot;]\n            spreadingFactor = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;loRaModulationInfo&quot;]&#x5B;&quot;spreadingFactor&quot;]\n\n            objectJSON = trama_mqtt&#x5B;&quot;objectJSON&quot;]\n            datosensor = json.loads(objectJSON)\n                 \n            datostrama = {&quot;publishedAt&quot;: publishedAt,\n                          &quot;dispositivo&quot;: dispositivo,\n                          &quot;fCnt&quot;: fCnt}\n            \n            # revisa gateway en la red LoRaWan\n            tamano = len(trama_mqtt&#x5B;&quot;rxInfo&quot;])\n            i = 0\n            while i&lt;tamano:\n                gatewayID = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;gatewayID&quot;]\n                rssi      = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;rssi&quot;]\n                loRaSNR   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;loRaSNR&quot;]\n                channel   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;channel&quot;]\n                rfChain   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;rfChain&quot;]\n                gtwNum    = gatewayDB&#x5B;gatewayID]\n                \n                # registra en tabla, incluyendo tramas repetidas\n                datostrama&#x5B;'rssi_up']    = rssi\n                datostrama&#x5B;'snr_up']     = loRaSNR\n                datostrama&#x5B;'channel_up'] = channel\n                datostrama&#x5B;'rfChain_up'] = rfChain\n                datostrama&#x5B;'gtw_rx']     = gtwNum\n                i = i + 1\n\n            # dato del sensor\n            equivale = {'Down_datarate': 'dr_down',\n                        'Down_rssi'    : 'rssi_down',\n                        'Down_snr'     : 'snr_down',\n                        'bateria_V'    : 'bateria_V'}\n            for undato in datosensor:\n                if undato in equivale.keys():\n                    datostrama&#x5B;equivale&#x5B;undato]] = datosensor&#x5B;undato]\n                else:\n                    datostrama&#x5B;undato] = datosensor&#x5B;undato]\n\n            # datos, otros valores\n            datostrama&#x5B;&quot;frequency&quot;] = freq_tx\n            datostrama&#x5B;&quot;bandwidth&quot;] = bandwidth\n            datostrama&#x5B;&quot;spreadingFactor&quot;] = spreadingFactor\n            datostrama&#x5B;&quot;fPort&quot;]   = fPort\n            datostrama&#x5B;&quot;dr&quot;]      = dr\n            datostrama&#x5B;&quot;created&quot;] = unafecha\n\n            leidos = leidos + 1\n            \n            # revisa registro repetido\n            repetido = False\n            if leidos&gt;1:\n                trama_num  = (fCnt == tabla&#x5B;leidos-1]&#x5B;'fCnt'])\n                fecha_pub  = (publishedAt == tabla&#x5B;leidos-1]&#x5B;'publishedAt'])\n                gtwNum_rep = (gtwNum == tabla&#x5B;leidos-1]&#x5B;'gtw_rx'])\n                repetido   = (trama_num and fecha_pub and gtwNum_rep)\n            if not(repetido):\n                tabla&#x5B;leidos] = datostrama\n            else:\n                leidos = leidos - 1\n\n    # convierte diccionario a DataFrame\n    if len(tabla)&gt;0:\n        tabla = pd.DataFrame(tabla)\n        tabla = tabla.T\n        # a\u00f1ade ubicaci\u00f3n y modelo (capsula o modulo desarrollo)\n        tabla.insert(1,'ubicado',ubicado)\n        tabla.insert(2,'modelo_disp',modelo_disp)\n        \n# directorio de resultados\nif len(carpeta_rsm) &gt; 0:\n    if not(os.path.exists(carpeta_rsm)):\n        os.makedirs(carpeta_rsm)\n    carpeta_rsm = carpeta_rsm + '\/'\n\n# SALIDA\nprint('registros leidos:     ', len(tabla0))\nprint('registros procesados: ', leidos)\nprint(tabla)\n\n# guarda el reporte en csv\nif len(tabla)&gt;0:\n    unreporte = carpeta_rsm+'data_'+ubicado+'.csv'\n    tabla.to_csv(unreporte)\n<\/pre><\/div>\n\n\n<p>el resultado de puede visualiza como:<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>registros leidos:      7090\nregistros procesados:  98\n                  publishedAt ubicado modelo_disp dispositivo  ... spreadingFactor fPort dr                    created\n1  2021-10-21 11:34:07.079188   LOS22      modulo        cc12  ...              10     4  0 2021-10-21 11:34:07.105036\n2  2021-10-21 11:49:07.862255   LOS22      modulo        cc12  ...              10     4  0 2021-10-21 11:49:07.876219\n3  2021-10-21 12:04:07.931128   LOS22      modulo        cc12  ...              10     4  0 2021-10-21 12:04:07.943781\n4  2021-10-21 12:19:08.489097   LOS22      modulo        cc12  ...              10     4  0 2021-10-21 12:19:08.504848\n5  2021-10-21 12:34:08.479274   LOS22      modulo        cc12  ...              10     4  0 2021-10-21 12:34:08.494229\n..                        ...     ...         ...         ...  ...             ...   ... ..                        ...\n94 2021-10-22 10:49:46.742877   LOS22      modulo        cc12  ...              10     4  0 2021-10-22 10:49:46.756601\n95 2021-10-22 11:04:47.636628   LOS22      modulo        cc12  ...              10     4  0 2021-10-22 11:04:47.652299\n96 2021-10-22 11:19:48.310535   LOS22      modulo        cc12  ...              10     4  0 2021-10-22 11:19:48.331143\n97 2021-10-22 11:34:49.209626   LOS22      modulo        cc12  ...              10     4  0 2021-10-22 11:34:49.224717\n98 2021-10-22 11:49:49.638194   LOS22      modulo        cc12  ...              10     4  0 2021-10-22 11:49:49.651398\n\n&#091;98 rows x 20 columns]\n&gt;&gt;&gt;<\/code><\/pre>\n\n\n\n<p>y el archivo resultante se presenta como:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><a href=\"https:\/\/www.dropbox.com\/scl\/fi\/88w8yy9u7apqz0n8vfi63\/data_LOS22.csv?rlkey=fwhl7uvahakly8z70yrkg7yon&amp;st=iy7vpk8a&amp;dl=0\">data_LOS22.csv<\/a><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h2 class=\"wp-block-heading\">Instrucciones en Python para tabla JSON<\/h2>\n\n\n<div class=\"wp-block-syntaxhighlighter-code alignwide\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# Lectura de archivo.json hacia una tabla1\n# selecciona registros de &quot;un sensor&quot;\n# graba unreporte.json con pandas\n\nimport numpy as np\nimport json\nimport pandas as pd\nimport datetime as dt\n\n# INGRESO\n\n# archivo de entrada\nunarchivo   = 'states20211022.json'\n\nfechainicio = '2021-10-21 19:00:00.0'\nfechafin    = '2021-10-22 17:10:00.0'\n\nunsensor    = 'sensor.rssi_up_cc22'\n# archivo de salida\nunreporte   = 'tramas20211022_cc12.json'\n\n# PROCEDIMIENTO -----\n# columnas o campos a usar\ncampos    = &#x5B;'domain','entity_id','state',\n             'attributes','created']\n# gatewayID simplifica identificador \ngateway   = {'uCfr\/\/5zvhk=':'Gw01',\n             'uCfr\/\/4dylc=':'Gw03'}\n\n# Lectura de archivo json\ntabla0 = pd.read_json(unarchivo)\n# Cambia a formato DataFrame\ntabla0 = pd.DataFrame(tabla0,columns=campos)\n\n# Revisa cada registro \nleidos = 0\ntabla  = {}\n\n# Intervalo de fecha como datetime\nformato     = '%Y-%m-%d %H:%M:%S.%f'\nfechainicio = fechainicio&#x5B;0:np.min(&#x5B;26,len(fechainicio)])]\nfechainicio = dt.datetime.strptime(fechainicio,formato)\nfechafin    = fechafin&#x5B;0:np.min(&#x5B;26,len(fechafin)])]\nfechafin    = dt.datetime.strptime(fechafin,formato)\n\n# datos de trama\nfor cadaregistro in tabla0.index:\n    unatrama   = tabla0&#x5B;'attributes']&#x5B;cadaregistro]\n    trama_mqtt = json.loads(unatrama)\n    \n    # selecciona registro por sensor, en fecha y con datos\n    cualsensor = (tabla0&#x5B;'entity_id']&#x5B;cadaregistro] == unsensor)\n    \n    unafecha = tabla0&#x5B;'created']&#x5B;cadaregistro]\n    unafecha = unafecha&#x5B;0:np.min(&#x5B;26,len(unafecha)])]\n    unafecha = dt.datetime.strptime(unafecha,formato)\n    \n    enfecha  = (unafecha&gt;=fechainicio) and (unafecha&lt;=fechafin)\n    condatos   = 'applicationID' in trama_mqtt.keys()\n    \n    selecciona = cualsensor and condatos and enfecha\n    if (selecciona == True):\n        leidos =  leidos + 1\n        \n        # datos en la mensaje MQTT\n        publishedAt = trama_mqtt&#x5B;&quot;publishedAt&quot;]\n        friendly_name = trama_mqtt&#x5B;&quot;friendly_name&quot;]\n        deviceName    = trama_mqtt&#x5B;&quot;deviceName&quot;]\n        dr    = trama_mqtt&#x5B;&quot;dr&quot;]\n        fCnt  = trama_mqtt&#x5B;&quot;fCnt&quot;]\n        fPort = trama_mqtt&#x5B;&quot;fPort&quot;]\n\n        objectJSON  = trama_mqtt&#x5B;&quot;objectJSON&quot;]\n        datosensor  = json.loads(objectJSON)\n        \n        frequency   = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;frequency&quot;]\n        bandwidth   = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;loRaModulationInfo&quot;]&#x5B;&quot;bandwidth&quot;]\n        spreadingFactor = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;loRaModulationInfo&quot;]&#x5B;&quot;spreadingFactor&quot;]\n             \n        datostrama = {&quot;publishedAt&quot;:publishedAt,\n                      &quot;fPort&quot;:fPort, &quot;dr&quot;: dr,&quot;fCnt&quot;: fCnt,\n                      &quot;frequency&quot;:  frequency,\n                      &quot;bandwidth&quot;:  bandwidth,\n                      &quot;spreadingFactor&quot;: spreadingFactor,\n                      &quot;datosensor&quot;:datosensor}\n        \n        # revisa por cada gateway en la red LoRaWan\n        tamano = len(trama_mqtt&#x5B;&quot;rxInfo&quot;])\n        i = 0\n        while i&lt;tamano:\n            gatewayID = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;gatewayID&quot;]\n            rssi      = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;rssi&quot;]\n            loRaSNR   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;loRaSNR&quot;]\n            channel   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;channel&quot;]\n            rfChain   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;rfChain&quot;]\n            gtwNum    = gateway&#x5B;gatewayID]\n            i = i+1\n            \n            # registra en tabla, incluyendo tramas repetidas\n            rx_datos = &#x5B;rssi, loRaSNR,\n                        channel, rfChain,frequency\/1e6]  \n            if not(gtwNum in datostrama.keys()):\n                datostrama&#x5B;gtwNum] = &#x5B;rx_datos]\n            else:\n                if not(rx_datos in datostrama&#x5B;gtwNum]):\n                    datostrama&#x5B;gwNum].append(rx_datos)\n        dispositivo = friendly_name.split('_')&#x5B;2]\n\n        # revisa registro repetido\n        disp_existe = dispositivo in tabla\n        if not(disp_existe):\n            tabla&#x5B;dispositivo] = {leidos:datostrama}\n        else:\n            trama_num = (fCnt == tabla&#x5B;dispositivo]&#x5B;leidos-1]&#x5B;'fCnt'])\n            fecha_pub = (publishedAt == tabla&#x5B;dispositivo]&#x5B;leidos-1]&#x5B;'publishedAt'])\n            repetido  = (trama_num and fecha_pub)\n            if not(repetido):\n                tabla&#x5B;dispositivo]&#x5B;leidos] = datostrama\n            else:\n                leidos = leidos - 1\n\n# convierte diccionario en DataFrame\ntabla = pd.DataFrame(tabla)\n\n# SALIDA\nprint('registros leidos:     ',len(tabla0))\nprint('registros procesados: ', leidos)\n\n# guarda el reporte en json\ntabla.to_json(unreporte)\n<\/pre><\/div>\n\n\n<p>El procesamiento de los datos se puede realizar con librer\u00edas como Pandas.<\/p>\n\n\n\n<p>En el procesamiento de registros, se descarta el registro de \"join\".<\/p>\n\n\n\n<p>Una muestra del reporte es:<\/p>\n\n\n\n<pre class=\"wp-block-code alignwide\"><code>registros leidos:      7090\nregistros procesados:  98\n&gt;&gt;&gt; tabla.keys()\nIndex(&#091;'cc12'], dtype='object')\n&gt;&gt;&gt; tabla&#091;'cc12'].keys()\nInt64Index(&#091; 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,\n            18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,\n            35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,\n            69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85,\n            86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98],\n           dtype='int64')\n&gt;&gt;&gt; tabla&#091;'cc12']&#091;2].keys()\ndict_keys(&#091;'publishedAt', 'fPort', 'dr', 'fCnt',\n 'frequency', 'bandwidth', 'spreadingFactor', 'datosensor',\n 'Gw03'])\n&gt;&gt;&gt; \n\n&gt;&gt;&gt; tabla&#091;'cc12']&#091;2]&#091;'datosensor'].keys()\ndict_keys(&#091;'Down_datarate', 'Down_rssi', 'Down_snr',\n 'bateria_V'])\n\n&gt;&gt;&gt; tabla&#091;'cc12']&#091;2]&#091;'Gw03']\n&#091;&#091;-84, 8.5, 1, 0, 902.5]]\n<\/code><\/pre>\n\n\n\n<p>Esta forma se obtiene un nuevo y mas peque\u00f1o archivo para procesar con los datos de solo el dispositivo que se propone analizar.<\/p>\n\n\n\n<p class=\"has-text-align-center\"><a href=\"https:\/\/www.dropbox.com\/scl\/fi\/8y4aqjt3dsnkvufobzggv\/tramas20211022_cc12.json?rlkey=vpg763u8gg8b8f4tannakh3jg&amp;st=zwzwihpe&amp;dl=0\">tramas20211022_cc12.json<\/a><\/p>\n\n\n\n<p><strong><em>Referencia<\/em><\/strong>: <a href=\"https:\/\/blog.espol.edu.ec\/algoritmos101\/fp-u08\/archivos-csv-json\/\">Archivos - csv, json<\/a> con Pandas en Fundamentos de Programaci\u00f3n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>El procesamiento de los datos hist\u00f3ricos de \"un sensor\" en una ubicaci\u00f3n se realiza con Python desde el archivo generado en la secci\u00f3n anterior. Esta forma se obtiene un archivo nuevo y de menor tama\u00f1o para procesar con los datos de solo el dispositivo que se propone analizar. states20211022.json El formato de la tabla es [&hellip;]<\/p>\n","protected":false},"author":8043,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1466681],"tags":[],"class_list":["post-3798","post","type-post","status-publish","format-standard","hentry","category-lorawan-propagacion"],"_links":{"self":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts\/3798","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/users\/8043"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/comments?post=3798"}],"version-history":[{"count":39,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts\/3798\/revisions"}],"predecessor-version":[{"id":4773,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts\/3798\/revisions\/4773"}],"wp:attachment":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/media?parent=3798"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/categories?post=3798"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/tags?post=3798"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}