Ir al contenido principal
Todas las coleccionesConecta tus dispositivos
Conectar dispositivos MOKOSmart LoRaWAN con Helium y Ubidots
Conectar dispositivos MOKOSmart LoRaWAN con Helium y Ubidots

En este artículo, se utilizará la Red de Personas de Helium para proporcionar conectividad LoRaWAN a un dispositivo basado en LoRaWAN de MOKOSmart.

Sergio M avatar
Escrito por Sergio M
Actualizado hace más de 2 meses
Soluciones IoT para Deporte y Fitness - MOKOSmart #1 Solución de Dispositivo Inteligente en China

Requisitos

1. Obtener credenciales del dispositivo

Este paso requiere que ya tengas la app MKLora instalada en tu dispositivo móvil, si no lo has hecho, por favor dirígete al último ítem en la sección de requisitos anterior.

Comienza activando el Bluetooth de tu teléfono móvil, luego puedes proceder a encender tu MOKOSmart LW001-BG PRO siguiendo el procedimiento que se muestra en la siguiente imagen:

Si el procedimiento anterior fue exitoso, el LED de encendido verde parpadeará seguido del LED azul parpadeando intermitentemente y el dispositivo ahora es detectable.

Ahora, abre la "MKLora" app en tu teléfono, toca el botón "Conectar" en la esquina superior derecha, se te pedirá una contraseña, la cual por defecto es "Moko4321", escribe esta contraseña y luego presiona el botón "OK".

Después de escribir correctamente la contraseña, serás llevado a la siguiente interfaz, en la cual deberás seleccionar la pestaña "LORA" y luego la opción "Configuraciones de Conexión" como se muestra a continuación:

Una vez allí, la pantalla debería verse como la siguiente, por favor guarda los valores de "DevEUI", "AppEUI" y "AppKey" donde puedas encontrarlos fácilmente, ya que necesitamos esta información para los siguientes pasos, además, ten cuidado de no modificar ninguna de las configuraciones aquí.

2. Conectar el dispositivo al Servidor de Red

Como se mencionó anteriormente, se utilizará la Red de Helium People's como Servidor de Red LoRaWAN.

  1. Inicia sesión en Helium console y navega a la sección Dispositivos en el menú de la izquierda.

  2. Haz clic en el botón Agregar Nuevo Dispositivo para crear un nuevo dispositivo. Dale un nombre y coloca DevEUI, AppEUI y AppKey obtenidos de la sección anterior. Opcionalmente, puedes adjuntar una etiqueta al dispositivo. Se recomienda hacerlo si tienes más de un dispositivo del mismo modelo, facilitará el proceso de integración. Como sugerencia, usa el modelo del dispositivo como etiqueta.

  3. Finalmente, haz clic en Guardar Dispositivo. El nuevo dispositivo se listará junto a todos los existentes. La activación del dispositivo tomará algunos minutos, mientras tanto, podemos configurar la integración con Ubidots.

3. Escribir el decodificador para LW001-BG PRO

El siguiente paso es escribir el decodificador que analizará los datos deseados de su forma de bits en bruto. En la consola de Helium, dirígete a la sección "Funciones", luego toca el botón “Agregar nueva función”, selecciona la opción "Personalizada". Se cargará una nueva pantalla, allí le darás un nombre y escribirás la función del decodificador.

En el campo de texto para escribir la función, por favor pega el siguiente código:

function calculateDaysInAMonth(month){    var daysInMonth = 0;  switch (month)  {    case 1: daysInMonth = 31;break;    case 2: daysInMonth = 28;break;    case 3: daysInMonth = 31;break;    case 4: daysInMonth = 30;break;    case 5: daysInMonth = 31;break;    case 6: daysInMonth = 30;break;    case 7: daysInMonth = 31;break;    case 8: daysInMonth = 31;break;    case 9: daysInMonth = 30;break;    case 10: daysInMonth = 31;break;    case 11: daysInMonth = 30;break;    case 12: daysInMonth = 31;break;     }  return daysInMonth;}function timeStampParser(bytes){  var timeStamp = 0;  var years = bytes[4] << 8 | bytes[5] << 0;  var months = bytes[6] - 1;  var days = bytes[7];  var hours = bytes[8];  var minutes = bytes[9];  var seconds = bytes[10];  var timezone = bytes[11];  timeStamp = (Date.UTC(years, months, days, hours, minutes, seconds));    if(timezone > 128)  {    timezone = timezone -256;    timeStamp = timeStamp + timezone * (-1) * 60 * 60 * 1000;  }  else  {    timeStamp = timeStamp - timezone * 60 * 60 * 1000;  }  return timeStamp;}function coordinatesParser(coordinate){  //2147483648=0x80000000  //4294967296=0x100000000  if(coordinate > 2147483648){coordinate -= 4294967296};  coordinate /= 10000000;  return coordinate;}function noLocationHandler(payload,bytes){  var positioningFailureReason;    if(bytes[3] == 00){positioningFailureReason = "Tiempo de posicionamiento WIFI no suficiente"}  else if(bytes[3] == 01){positioningFailureReason = "Tiempo de estrategias de posición WIFI agotado"}  else if(bytes[3] == 02){positioningFailureReason = "Módulo WIFI no detectado"}  else if(bytes[3] == 03){positioningFailureReason = "Tiempo de posicionamiento BlueTooth no suficiente"}  else if(bytes[3] == 04){positioningFailureReason = "Tiempo de estrategias de posición BlueTooth agotado"}  else if(bytes[3] == 05){positioningFailureReason = "Difusión de BlueTooth en progreso"}  else if(bytes[3] == 06){positioningFailureReason = "Tiempo de presupuesto de posición GPS agotado"}  else if(bytes[3] == 07){positioningFailureReason = "Tiempo de posicionamiento GPS grueso agotado"}  else if(bytes[3] == 08){positioningFailureReason = "Tiempo de posicionamiento GPS fino agotado"}  else if(bytes[3] == 09){positioningFailureReason = "Tiempo de posición GPS no es suficiente"}  else if(bytes[3] == 10){positioningFailureReason = "Tiempo de posicionamiento GPS asistido agotado"}  else if(bytes[3] == 11){positioningFailureReason = "Tiempo de posicionamiento GPS de arranque en frío agotado"}  else if(bytes[3] == 12){positioningFailureReason = "Interrumpido por enlace descendente para posición"}  else if(bytes[3] == 13){positioningFailureReason = "Interrumpido posicionamiento al inicio del movimiento"}  var dummy = {      "location-fixed":{          "value":0,          "context":{              "payload-type":"no-location-fixed",              "error-source":positioningFailureReason,                        }      },  };  Object.assign(payload, dummy);  if(bytes[3] == 6 || bytes[3] == 7 || bytes[3] == 8 || bytes[3] == 9 || bytes[3] == 10 || bytes[3] == 11)  {    var podp = bytes[5] / 10; if(podp == 255){};    var cn0 = bytes[6];    var cn1 = bytes[7];    var cn2 = bytes[8];    var cn3 = bytes[9];    var errors = {      "PODP":podp,      "C/N 0":cn0,      "C/N 1":cn1,      "C/N 2":cn2,      "C/N 3":cn3,        };   Object.assign(payload["location-fixed"]["context"], errors);             }  return payload;}function locationHandler(payload,bytes){  var positioningType = bytes[3];  var timeStamp = timeStampParser(bytes);  var fixedType;  if(positioningType == 0x00){fixedType = "Wifi";}  else if(positioningType == 0x01){fixedType = "BlueTooth";}  else if(positioningType == 0x02){fixedType = "GPS";}  else   {     return {      "error": "valor de posicionamiento no válido",      "value": positioningType,       "allowed values":{          "Wifi": 0,           "BlueTooth":1,           "GPS":2      }    };  }    var dummy = {      "location-fixed":{          "value":1,          "timestamp":timeStamp,          "context":{              "payload-type":"location-fixed",              "fixed-type":fixedType          }      },  };  Object.assign(payload, dummy);  Object.assign(payload["battery-status"],{"timestamp":timeStamp});  Object.assign(payload["battery-voltage"],{"timestamp":timeStamp});  Object.assign(payload["temperature"],{"timestamp":timeStamp});  Object.assign(payload["battery-status"]["context"],{"fixed-type":fixedType});  Object.assign(payload["battery-voltage"]["context"],{"fixed-type":fixedType});  Object.assign(payload["temperature"]["context"],{"fixed-type":fixedType});      if(positioningType == 0x02)  {    var lat = (bytes[13]<< 24 | bytes[14]<< 16 | bytes[15]<< 8 | bytes[16]<< 0);    var lng = (bytes[17]<< 24 | bytes[18]<< 16 | bytes[19]<< 8 | bytes[20]<< 0);    var dummyPayload = {};        lat = coordinatesParser(lat);    lng = coordinatesParser(lng);        positionPayload = {      "position":{          "value":1,          "timestamp":timeStamp,          "context":{            "lat":lat,            "lng":lng,            "payload-type":"location-fixed",            "fixed-type":"GPS",          }           },    };    Object.assign(payload, positionPayload);  }  return payload;}function buildCommonPayload(port,batteryStatus,batteryVoltage,temperature){  var payload = {};  var contx;    if(port == 0x1){contx = "heartbeat-payload";}  else if(port == 0x2){contx = "location-fixed-payload";}  else if(port == 0x3){contx = "no-location-fixed-payload";}    payload = {           "battery-status":{              "value":batteryStatus,              "context": {                  "payload-type":contx              },              },          "battery-voltage":{              "value":batteryVoltage,              "context": {                  "payload-type":contx              },            },          "temperature":{              "value":temperature,              "context": {                  "payload-type":contx              },            },          };  return payload;}function buildPayload(bytes,port,batteryStatus,batteryVoltage,temperature){  var payload = {};      switch (port)  {    //payload de latido    case 1:       payload = buildCommonPayload(port,batteryStatus,batteryVoltage,temperature);      break;    //payload de ubicación fija    case 2:      payload = buildCommonPayload(port,batteryStatus,batteryVoltage,temperature);      payload = locationHandler(payload, bytes);      break;          //payload de falla de ubicación     case 3:       payload = buildCommonPayload(port,batteryStatus,batteryVoltage,temperature);      payload = noLocationHandler(payload,bytes);      break;  }  return payload;}function Decoder(bytes,port) {  var payload = {};  var deviceStatus = bytes[0];  var temperature = bytes[1];  var ACKAndBatteryVoltage = bytes[2];    var operationMode = deviceStatus & 0x3;//bit0~1  var batteryStatus = deviceStatus & 0x4;//bi2    var motionState = deviceStatus & (1<<5);//bit5    //corrección para el signo  if(temperature > 128){temperature -= 256;};    var _ACK = ACKAndBatteryVoltage & 0xF;  var batteryVoltage = ((ACKAndBatteryVoltage & 0xF0)>>4)*0.1 + 2.2;    payload = buildPayload(bytes, port, batteryStatus, batteryVoltage, temperature);  Object.assign(payload, {"port":port});  return payload;}

4. Configurar la integración con Ubidots

Para esta sección, necesitarás tu token de cuenta de Ubidots. Para información sobre cómo encontrarlo, echa un vistazo a este artículo.

Mientras estés en la página principal de Helium, haz clic en "Integraciones" en el lado izquierdo de la página, luego presiona el botón "Agregar Nueva Integración", selecciona la integración "Ubidots" de la lista de integraciones disponibles que se mostrará, luego deberás ingresar tu Token de Ubidots en el campo de texto "Ingresar Token de Autenticación".

Después de escribir tu token de Ubidots, toca el botón "Obtener URL de Webhook", luego se mostrará un campo de texto para que ingreses el nombre de tu integración allí, dale un nombre que coincida y luego presiona “Agregar Integración”.

5. Conectar la integración

Todo lo que queda es conectar la integración recién creada con el dispositivo que la utilizará. Por favor dirígete a la sección “Flujos”, una vez allí, deberás indicarle a Helium qué dispositivo va a usar qué decodificador y, por último, qué integración se va a utilizar.

Eso se hace fácilmente uniendo los bloques que representan cada uno de esos componentes, dirígete a la esquina superior izquierda de la página y allí podrás encontrar un menú desplegable desde donde puedes seleccionar el "Dispositivo", "Función" y "Integración". En este caso, el nombre del dispositivo es el que elegiste en el paso 2 de este artículo, la función es la función del decodificador creada en el paso 3 y, por último, la integración es la que se creó en el cuarto paso. Selecciona cada uno de esos y arrástralos al área en blanco. El siguiente GIF podría dejar todo claro para ti:

Una línea discontinua en movimiento que conecta los bloques es la confirmación de que el dispositivo está transmitiendo datos a la función del decodificador y, la salida del decodificador está siendo ingerida en el plugin de Ubidots.

Todo lo que queda es configurar la función del decodificador, para hacerlo, por favor dirígete a tu panel de control de Ubidots, haz clic en "Dispositivos" y selecciona "Plugins" del menú desplegable que se mostrará.

Una vez que se cargue la página web, verás una interfaz como la siguiente:

Si nunca has creado un plugin en Ubidots, solo habrá un ítem allí, que es la integración que acabas de crear desde el lado de la consola de Helium. Por favor haz clic en el pequeño ícono de lápiz en el lado derecho de la pantalla en el plugin correspondiente como ilustra la imagen anterior.

Después de que se cargue la página web, deberás buscar la opción "Decodificador" en el lado izquierdo de la pantalla, luego en el campo de texto donde hay un montón de código, borra todo y pega el siguiente fragmento de código:

def format_payload(args):  decoded_payload = args["decoded"]["payload"]  print({"payload":decoded_payload})  return decoded_payload

Tu dispositivo ahora está completamente configurado para enviar datos a Ubidots. Echa un vistazo a la sección "Dispositivos" en tu cuenta de Ubidots y podrás ver el dispositivo recién creado.

Puedes echar un vistazo a la variable "location-fixed" para verificar si tu dispositivo obtuvo con éxito la posición GPS o las razones por las cuales no lo hizo.

6. Solución de Problemas

Si estás recibiendo constantemente retroalimentación de "no-location-fixed" del dispositivo, puedes intentar lo siguiente:

Apaga tu dispositivo y enciéndelo nuevamente para permitir que el dispositivo sea detectable por Bluetooth, luego usa la app móvil para acceder a la configuración del dispositivo como se describe en la primera sección. Luego, dirígete a la pestaña de opciones "POSICIÓN" como se ilustra a continuación:

Una vez allí, podrás ver la opción "GPS Fix".

Toca en "GPS Fix" para cambiar el parámetro de configuración. Primero puedes intentar modificar el "Tiempo Presupuestado" estableciéndolo en un período más largo, puedes usar 76200 s. Presiona el botón Guardar en la esquina superior derecha para guardar los cambios.

Si lo anterior no soluciona el problema, puedes intentar cambiar el "Tiempo de Precisión" como se muestra a continuación.

7. Comentarios, Sugerencias y Artículos Relacionados

No dudes en publicar preguntas o sugerencias en nuestro portal comunitario, o envíanos un correo a support@ubidots.com.

Otros usuarios también encontraron útil...

¿Ha quedado contestada tu pregunta?