Skip to main content

Conectar a AWS IoT Core

AWS IoT proporciona los servicios en la nube que conectan tus dispositivos IoT a otros dispositivos y servicios en la nube de AWS. AWS IoT proporciona software de dispositivo que puede ayudarte a integrar tus dispositivos IoT en soluciones basadas en AWS IoT. Si tus dispositivos pueden conectarse a AWS IoT, AWS IoT puede conectarlos a los servicios en la nube que AWS proporciona.

Inicia sesión en la consola de AWS IoT

info

Si no tienes una cuenta de AWS, haz clic aquí para crear una.

Agregar Gateway

Navega a Internet of Things, luego haz clic en IoT Core.

pir

En el menú izquierdo, selecciona LPWAN devicesGateways, haz clic en Add gateway

pir

Gateway's EUI: El EUI de tu gateway, puedes encontrarlo en la etiqueta del dispositivo.
Frequency: La banda de frecuencia del gateway.
Name: Nombra tu gateway (opcional)
SubBand: Opcionalmente, también puedes especificar datos de configuración LoRaWAN como las subbandas que quieres usar y filtros que pueden controlar el flujo de tráfico. Para más información, consulta Configure position of wireless resources with AWS IoT Core for LoRaWAN.

pir

Configurar tu gateway

Certificado del Gateway

Para autenticar tu gateway de modo que pueda comunicarse de forma segura con AWS IoT, tu gateway LoRaWAN debe presentar una clave privada y certificado a AWS IoT Core for LoRaWAN.

Haz clic en Create certificate.

pir

Descarga y guarda los archivos de certificado y los certificados de confianza del servidor.

pir

Debería haber cuatro archivos dentro, los usarás más tarde para configurar el gateway.

pir

Permisos del Gateway

Si no has creado el rol IAM IoTWirelessGatewayCertManagerRole para tu cuenta, crea el rol antes de continuar agregando el gateway. Tus gateways no podrán comunicarse con AWS IoT sin este rol.

Elige el Rol: IoT Wireless Gateway Cert Manager Role, luego envía la configuración.

pir

Copia la URL CUPS, la usaremos en el siguiente paso.

pir

Configuración del Gateway

Inicia sesión en la página de configuración Luci del gateway, consulta Get_Started para más detalles.

Navega a LoRa > LoRa Network.

Mode: Basic Station
Gateway EUI: Tu eui del gateway
Server: CUPS Server
URL: La URL CUPS que copiamos antes
Authentication Mode: TLS Server and Client Authentication

pir

Copia el contenido del archivo de certificado que descargamos antes (el certificado se puede abrir en forma de texto).

pir

Navega a la página de Gateways y elige el gateway que has agregado.

En la sección de detalles específicos de LoRaWAN de la página de detalles del Gateway, verás el estado de conexión y la fecha y hora en que se recibió el último uplink.

pir

Agregar Perfiles

Los perfiles de dispositivo y servicio se pueden definir para describir configuraciones comunes de dispositivos. Estos perfiles describen parámetros de configuración que son compartidos por dispositivos para facilitar la adición de esos dispositivos. AWS IoT Core for LoRaWAN soporta perfiles de dispositivo y perfiles de servicio.

Agregar Perfiles de Dispositivos

Navega a Devices > Profiles, haz clic en Add device profile.

pir

Proporciona un nombre de perfil de dispositivo, selecciona la banda de frecuencia (RfRegion) que estás usando para el dispositivo y gateway, y mantén las otras configuraciones en los valores predeterminados.

pir

Agregar Perfiles de Servicio

Navega a Devices > Profiles, haz clic en Add service profile

pir

Se recomienda que dejes habilitada la configuración Add gateway meta data para que recibas metadatos adicionales del gateway para cada payload, como RSSI y SNR para la transmisión de datos.

pir

Agregar Destino

Navega a LPWAN Devices > Destination, haz clic en Add destination.

pir

Aquí selecciona Publish to AWS IoT Core Message Broker y nombra el MQTT topic del destino

Permisos: Selecciona un rol de servicio existente > IoT Wireless Gateway Cert Manager Role

info

Un nombre de destino solo puede tener caracteres alfanuméricos, - (guión) y _ (guión bajo) y no puede tener espacios.

pir

Agregar Dispositivos LoRaWAN

Agregar Dispositivo Inalámbrico

Navega a LPWAN devices > LoRaWAN> Devices, haz clic en Add wireless device.

pir

Wireless device specification: OTAA v1.0x

DevEUI / AppEUI / AppKey: se pueden encontrar en la APP SenseCraft, consulta Get_Started para más detalles.

pir

Selecciona el perfil de dispositivo y destino que creaste en el paso anterior.

pir

pir

Navega a la página de Dispositivos y elige el dispositivo que agregaste antes.

En la sección de Detalles de la página de detalles de dispositivos inalámbricos, verás la fecha recibida.

pir

Configurar el decodificador

Crear Reglas de Mensaje

Navega a la pestaña Message routingRules, y haz clic en el botón Create Rule.

pir

Nombra tu regla y envíala.

pir

SQL version: 2016-03-23
SQL statement: SELECT * FROM "YourDestinationTopic"

Aquí llenamos t2000-raw según Agregar Destino

pir

Desplázate hacia abajo a la sección Rule actions, y selecciona Lambda de Action 1, luego haz clic en Create a Lambda function.

pir

Function name: Nombra tu función.
Runtime: Node.js 24.x
Architexture: x86_64

Haz clic en el botón Create function para crear una nueva función.

pir

Después de crear la función, va a la página de configuración de la función. La configuraremos más tarde, así que simplemente regresa a la página de reglas.

Haz clic en el botón Refresh y selecciona la función Lambda que creaste anteriormente. Luego haz clic en Next para ir al Paso 4.

pir

Verifica que todos los detalles de la regla sean correctos, luego haz clic en Create para crear la regla.

pir

Configurar la Función Lambda

Regresa a la pestaña Message routingRules, selecciona la regla que creaste anteriormente.

Haz clic en Lambda desde Actions y luego haz clic en el enlace para ir a la página de configuración de la función Lambda.

pir

pir

En la siguiente página de configuración de función, renombra el archivo index.mjs a index.js, elimina todo el código y reemplázalo con el script de Resource, luego haz clic en el botón Deploy.

Decodificador para AWS
const {IoTDataPlaneClient, PublishCommand} = require("@aws-sdk/client-iot-data-plane");
const client = new IoTDataPlaneClient({
//Replace the region according to your device.
"region": "us-east-1"
});

function decodeUplink (input) {
const bytes = Buffer.from(input, 'base64');
console.log("bytes: ", bytes)
const bytesString = bytes2HexString(bytes)
const originMessage = bytesString.toLocaleUpperCase()
const decoded = {
valid: true,
err: 0,
payload: bytesString,
messages: []
}
let measurement = messageAnalyzed(originMessage)
if (measurement.length === 0) {
decoded.valid = false
return { data: decoded }
}

for (let message of measurement) {
if (message.length === 0) {
continue
}
let elements = []
for (let element of message) {
if (element.errorCode) {
decoded.err = element.errorCode
decoded.errMessage = element.error
} else {
elements.push(element)
}
}
if (elements.length > 0) {
decoded.messages.push(elements)
}
}
return { data: decoded }
}

function messageAnalyzed (messageValue) {
try {
let frames = unpack(messageValue)
let measurementResultArray = []
for (let i = 0; i < frames.length; i++) {
let item = frames[i]
let dataId = item.dataId
let dataValue = item.dataValue
let measurementArray = deserialize(dataId, dataValue)
measurementResultArray.push(measurementArray)
}
return measurementResultArray
} catch (e) {
return e.toString()
}
}

function unpack (messageValue) {
let frameArray = []
const FIXED_LENGTH_PACKAGES = {
'27': 92, '28': 60, '29': 24, '2A': 12, '2B': 46, '2E': 34, '31': 30, '32': 18
}
const DYNAMIC_LENGTH_PACKAGES = {
'2C': {minLen: 32, scanCountPos: [30, 32], baseLen: 23, itemLen: 7},
'2D': {minLen: 32, scanCountPos: [30, 32], baseLen: 23, itemLen: 7},
'2F': {minLen: 20, scanCountPos: [18, 20], baseLen: 17, itemLen: 7},
'30': {minLen: 20, scanCountPos: [18, 20], baseLen: 17, itemLen: 7}
}

for (let i = 0; i < messageValue.length; i++) {
let remainMessage = messageValue
let dataId = remainMessage.substring(0, 2).toUpperCase()
let dataValue
let dataObj = {}

if (dataId === '0C') {
dataValue = ''
messageValue = remainMessage.substring(2)
dataObj = {'dataId': dataId, 'dataValue': ''}
} else if (dataId === '0D') {
dataValue = remainMessage.substring(2, 10)
messageValue = remainMessage.substring(10)
dataObj = {'dataId': dataId, 'dataValue': dataValue}
} else if (FIXED_LENGTH_PACKAGES[dataId]) {
let packageLen = FIXED_LENGTH_PACKAGES[dataId]
if (remainMessage.length < packageLen) {
return frameArray
}
dataValue = remainMessage.substring(2, packageLen)
messageValue = remainMessage.substring(packageLen)
dataObj = {'dataId': dataId, 'dataValue': dataValue}
} else if (DYNAMIC_LENGTH_PACKAGES[dataId]) {
let config = DYNAMIC_LENGTH_PACKAGES[dataId]
if (remainMessage.length < config.minLen) {
return frameArray
}
let scanCount = parseInt(remainMessage.substring(config.scanCountPos[0], config.scanCountPos[1]), 16)
let packageLen = (config.baseLen + (scanCount - 1) * config.itemLen) * 2
if (remainMessage.length < packageLen) {
return frameArray
}
dataValue = remainMessage.substring(2, packageLen)
messageValue = remainMessage.substring(packageLen)
dataObj = {'dataId': dataId, 'dataValue': dataValue}
} else {
return frameArray
}

if (dataValue.length < 2 && dataObj.dataId !== '0C') {
break
}
frameArray.push(dataObj)
}
return frameArray
}

function deserialize (dataId, dataValue) {
let measurementArray = []
let eventList = []
let timestamp = 0
let value = null
let motionId = 0
let scanMax = 0
let interval = 0
let workMode = 0
let heartbeatInterval = 0
let periodicInterval = 0
let eventInterval = 0
switch (dataId) {
case '0C':
measurementArray.push({type: "timeSync"})
break
case '0D':
let errorCode = getInt(dataValue)
let error = ''
switch (errorCode) {
case 1:
error = 'FAILED TO OBTAIN THE UTC TIMESTAMP'
break
case 2:
error = 'ALMANAC TOO OLD'
break
case 3:
error = 'DOPPLER ERROR'
break
}
measurementArray.push({errorCode, error})
break
case '27':
measurementArray.push(...getUpT2000(dataValue))
break
case '28':
interval = 0
workMode = getInt(dataValue.substring(0, 2))
heartbeatInterval = getMinsByMin(dataValue.substring(4, 8))
periodicInterval = getMinsByMin(dataValue.substring(8, 12))
eventInterval = getMinsByMin(dataValue.substring(12, 16))
switch (workMode) {
case 0:
interval = heartbeatInterval
break
case 1:
interval = periodicInterval
break
case 2:
interval = eventInterval
break
}
measurementArray = [
{
measurementId: '3940', measurementValue: workMode
}, {
measurementId: '3965', measurementValue: getPositioningStrategy(dataValue.substring(2, 4))
}, {
measurementId: '3942', measurementValue: heartbeatInterval
}, {
measurementId: '3943', measurementValue: periodicInterval
}, {
measurementId: '3944', measurementValue: eventInterval
}, {
measurementId: '3974', measurementValue: getInt(dataValue.substring(16, 18))
}, {
measurementId: '3976', measurementValue: getInt(dataValue.substring(18, 20))
}, {
measurementId: '3977', measurementValue: getInt(dataValue.substring(20, 22))
}, {
measurementId: '3900', measurementValue: interval
}, {
measurementId: '3978', measurementValue: getInt(dataValue.substring(22, 24))
}, {
measurementId: '3979', measurementValue: dataValue.substring(26, 26 + getInt(dataValue.substring(24, 26)) * 2)
}
]
// measurementArray.push(measurement)
break
case '29':
measurementArray.push({
measurementId: '3946', measurementValue: getInt(dataValue.substring(0, 2))
})
measurementArray.push({
measurementId: '3947', measurementValue: getSensorValue(dataValue.substring(2, 6), 1)
})
measurementArray.push({
measurementId: '3948', measurementValue: getMinsByMin(dataValue.substring(6, 10))
})
measurementArray.push({
measurementId: '3949', measurementValue: getInt(dataValue.substring(10, 12))
})
measurementArray.push({
measurementId: '3950', measurementValue: getMinsByMin(dataValue.substring(12, 16))
})
measurementArray.push({
measurementId: '3951', measurementValue: getInt(dataValue.substring(16, 18))
})
measurementArray.push({
measurementId: '3952', measurementValue: getInt(dataValue.substring(18, 22))
})
break
case '2A':
measurementArray.push({
measurementId: '3000', measurementValue: getBattery(dataValue.substring(0, 2))
})
measurementArray.push({
measurementId: '3940', measurementValue: getWorkingMode(dataValue.substring(2, 4))
})
measurementArray.push({
measurementId: '3965', measurementValue: getPositioningStrategy(dataValue.substring(4, 6))
})
measurementArray.push({
measurementId: '3974', measurementValue: getInt(dataValue.substring(6, 8))
})
measurementArray.push({
measurementId: '3976', measurementValue: getInt(dataValue.substring(8, 10))
})
break
case '2B':
eventList = getEventStatus(dataValue.substring(0, 4))
motionId = getMotionId(dataValue.substring(4, 6))
timestamp = getUTCTimestamp(dataValue.substring(6, 14))
parseAccelerometerData(dataValue, 14, timestamp, motionId, measurementArray)
parseLocationData(dataValue, 26, timestamp, motionId, measurementArray)
parseBatteryData(dataValue, 42, timestamp, motionId, measurementArray)
parseEventData(eventList, timestamp, motionId, measurementArray)
break
case '2C':
case '2D':
eventList = getEventStatus(dataValue.substring(0, 4))
motionId = getMotionId(dataValue.substring(4, 6))
timestamp = getUTCTimestamp(dataValue.substring(6, 14))
parseAccelerometerData(dataValue, 14, timestamp, motionId, measurementArray)
parseBatteryData(dataValue, 26, timestamp, motionId, measurementArray)
scanMax = getInt(dataValue.substring(28, 30))
parseScanData(scanMax, dataValue, 30, dataId === '2C' ? '5001' : '5002', timestamp, motionId, measurementArray)
parseEventData(eventList, timestamp, motionId, measurementArray)
break
case '2E':
eventList = getEventStatus(dataValue.substring(0, 4))
motionId = getMotionId(dataValue.substring(4, 6))
timestamp = getUTCTimestamp(dataValue.substring(6, 14))
parseLocationData(dataValue, 14, timestamp, motionId, measurementArray)
parseBatteryData(dataValue, 30, timestamp, motionId, measurementArray)
parseEventData(eventList, timestamp, motionId, measurementArray)
break
case '2F':
case '30':
eventList = getEventStatus(dataValue.substring(0, 4))
motionId = getMotionId(dataValue.substring(4, 6))
timestamp = getUTCTimestamp(dataValue.substring(6, 14))
parseBatteryData(dataValue, 14, timestamp, motionId, measurementArray)
scanMax = getInt(dataValue.substring(16, 18))
parseScanData(scanMax, dataValue, 18, dataId === '2F' ? '5001' : '5002', timestamp, motionId, measurementArray)
parseEventData(eventList, timestamp, motionId, measurementArray)
break
case '31':
eventList = getEventStatus(dataValue.substring(2, 6))
timestamp = getUTCTimestamp(dataValue.substring(6, 14))
measurementArray.push({
measurementId: '3576',
timestamp,
motionId,
measurementValue: getPositingStatus(dataValue.substring(0, 2))
})
parseAccelerometerData(dataValue, 14, timestamp, motionId, measurementArray)
parseBatteryData(dataValue, 26, timestamp, motionId, measurementArray)
parseEventData(eventList, timestamp, motionId, measurementArray)
break
case '32':
eventList = getEventStatus(dataValue.substring(2, 6))
timestamp = getUTCTimestamp(dataValue.substring(6, 14))
measurementArray.push({
measurementId: '3576',
timestamp,
motionId,
measurementValue: getPositingStatus(dataValue.substring(0, 2))
})
parseBatteryData(dataValue, 14, timestamp, motionId, measurementArray)
parseEventData(eventList, timestamp, motionId, measurementArray)
break
}
if (measurementArray.length > 0) {
for (let frag of measurementArray) {
if (frag.measurementId) {
frag.type = getTypeByMeasurementId(frag.measurementId)
}
}
}
return measurementArray
}

function parseAccelerometerData (dataValue, startPos, timestamp, motionId, measurementArray) {
const accelerometerIds = ['4210', '4211', '4212']
for (let i = 0; i < 3; i++) {
let value = getSignSensorValue(dataValue.substring(startPos + i * 4, startPos + (i + 1) * 4), 1)
if (value !== null) {
measurementArray.push({
measurementId: accelerometerIds[i],
timestamp,
motionId,
measurementValue: value
})
}
}
}

function parseBatteryData (dataValue, pos, timestamp, motionId, measurementArray) {
measurementArray.push({
measurementId: '3000',
timestamp,
motionId,
measurementValue: '' + getBattery(dataValue.substring(pos, pos + 2))
})
}

function parseEventData (eventList, timestamp, motionId, measurementArray) {
if (eventList && eventList.length > 0) {
measurementArray.push({
measurementId: '4200',
timestamp,
motionId,
measurementValue: eventList
})
}
}

function parseLocationData (dataValue, startPos, timestamp, motionId, measurementArray) {
measurementArray.push({
measurementId: '4197',
timestamp,
motionId,
measurementValue: '' + getSensorValue(dataValue.substring(startPos, startPos + 8), 1000000)
})
measurementArray.push({
measurementId: '4198',
timestamp,
motionId,
measurementValue: '' + getSensorValue(dataValue.substring(startPos + 8, startPos + 16), 1000000)
})
}

function parseScanData (scanMax, dataValue, startPos, measurementId, timestamp, motionId, measurementArray) {
if (scanMax && scanMax > 0) {
measurementArray.push({
measurementId,
timestamp,
motionId,
measurementValue: getMacAndRssiObj(dataValue.substring(startPos))
})
}
}

function getTypeByMeasurementId (measurementId) {
const TYPE_MAP = {
'3000': 'Battery',
'3502': 'Firmware Version',
'3001': 'Hardware Version',
'3940': 'Work Mode',
'3965': 'Positioning Strategy',
'3942': 'Heartbeat Interval',
'3943': 'Periodic Interval',
'3944': 'Event Interval',
'3974': '3X Sensor Enable',
'3976': 'Anti-Theft',
'3977': 'GNSS Scan Timeout',
'3900': 'Uplink Interval',
'3978': 'BLE Scan Timeout',
'3979': 'UUID Filter',
'3946': 'Motion Enable',
'3947': 'Any Motion Threshold',
'3948': 'Motion Start Interval',
'3949': 'Static Enable',
'3950': 'Device Static Timeout',
'3951': 'Shock Enable',
'3952': 'Shock Threshold',
'4210': 'AccelerometerX',
'4211': 'AccelerometerY',
'4212': 'AccelerometerZ',
'4197': 'Longitude',
'4198': 'Latitude',
'4200': 'Event Status',
'5001': 'Wi-Fi Scan',
'5002': 'BLE Scan',
'3576': 'Positioning Status'
}
return TYPE_MAP[measurementId] || ''
}

function getMotionId (str) {
return getInt(str)
}

function getPositingStatus (str) {
let status = getInt(str)
const STATUS_MAP = {
0: "locate successful.",
1: "The GNSS scan timed out.",
2: "The Wi-Fi scan timed out.",
3: "The Wi-Fi + GNSS scan timed out.",
4: "The GNSS + Wi-Fi scan timed out.",
5: "The Bluetooth scan timed out.",
6: "The Bluetooth + Wi-Fi scan timed out.",
7: "The Bluetooth + GNSS scan timed out.",
8: "The Bluetooth + Wi-Fi + GNSS scan timed out.",
9: "Location Server failed to parse the GNSS location.",
10: "Location Server failed to parse the Wi-Fi location.",
11: "Location Server failed to parse the Bluetooth location.",
12: "Failed to parse location due to the poor accuracy.",
13: "Time synchronization failed.",
14: "Failed due to the old Almanac.",
15: "The GNSS +Bluetooth scan timed out."
}
if (STATUS_MAP[status] !== undefined) {
return {id: status, statusName: STATUS_MAP[status]}
}
return getInt(str)
}

function getUpT2000 (messageValue) {
let interval = 0
let workMode = getInt(messageValue.substring(10, 12))
let heartbeatInterval = getMinsByMin(messageValue.substring(14, 18))
let periodicInterval = getMinsByMin(messageValue.substring(18, 22))
let eventInterval = getMinsByMin(messageValue.substring(22, 26))
switch (workMode) {
case 0:
interval = heartbeatInterval
break
case 1:
interval = periodicInterval
break
case 2:
interval = eventInterval
break
}
let data = [
{
measurementId: '3000', measurementValue: getBattery(messageValue.substring(0, 2))
}, {
measurementId: '3502', measurementValue: getSoftVersion(messageValue.substring(2, 6))
}, {
measurementId: '3001', measurementValue: getHardVersion(messageValue.substring(6, 10))
}, {
measurementId: '3940', measurementValue: workMode
}, {
measurementId: '3965', measurementValue: getPositioningStrategy(messageValue.substring(12, 14))
}, {
measurementId: '3942', measurementValue: heartbeatInterval
}, {
measurementId: '3943', measurementValue: periodicInterval
}, {
measurementId: '3944', measurementValue: eventInterval
}, {
measurementId: '3974', measurementValue: getInt(messageValue.substring(26, 28))
}, {
measurementId: '3976', measurementValue: getInt(messageValue.substring(28, 30))
}, {
measurementId: '3977', measurementValue: getInt(messageValue.substring(30, 32))
}, {
measurementId: '3900', measurementValue: interval
}, {
measurementId: '3978', measurementValue: getInt(messageValue.substring(54, 56))
}, {
measurementId: '3979', measurementValue: messageValue.substring(58, 58 + getInt(messageValue.substring(56, 58)) * 2)
}
]
let motionSetting = getMotionSetting(messageValue.substring(32, 42))
let staticsSetting = getStaticSetting(messageValue.substring(42, 48))
let shockSetting = getShockSetting(messageValue.substring(48, 54))
data = [...data, ...motionSetting, ...staticsSetting, ...shockSetting]
return data
}

function getMotionSetting (str) {
return [
{measurementId: '3946', measurementValue: getInt(str.substring(0, 2))},
{measurementId: '3947', measurementValue: getSensorValue(str.substring(2, 6), 1)},
{measurementId: '3948', measurementValue: getMinsByMin(str.substring(6, 10))},
]
}

function getStaticSetting (str) {
return [
{measurementId: '3949', measurementValue: getInt(str.substring(0, 2))},
{measurementId: '3950', measurementValue: getMinsByMin(str.substring(2, 6))}
]
}

function getShockSetting (str) {
return [
{measurementId: '3951', measurementValue: getInt(str.substring(0, 2))},
{measurementId: '3952', measurementValue: getInt(str.substring(2, 6))}
]
}

function getBattery (batteryStr) {
return loraWANV2DataFormat(batteryStr)
}
function getSoftVersion (softVersion) {
return `${loraWANV2DataFormat(softVersion.substring(0, 2))}.${loraWANV2DataFormat(softVersion.substring(2, 4))}`
}
function getHardVersion (hardVersion) {
return `${loraWANV2DataFormat(hardVersion.substring(0, 2))}.${loraWANV2DataFormat(hardVersion.substring(2, 4))}`
}

function getMinsByMin (str) {
return getInt(str)
}

function getSensorValue (str, dig) {
if (str === '8000') {
return null
} else {
return loraWANV2DataFormat(str, dig)
}
}

function isNull (str) {
if (str.substring(0, 1) !== '8') {
return false
}
for (let i = 1; i < str.length; i++) {
if (str.substring(i, i + 1) !== '0') {
return false
}
}
return true
}

function getSignSensorValue (str, dig = 1) {
if (isNull(str)) {
return null
}
return loraWANV2DataFormat(str, dig)
}

function bytes2HexString (arrBytes) {
var str = ''
for (var i = 0; i < arrBytes.length; i++) {
var tmp
var num = arrBytes[i]
if (num < 0) {
tmp = (255 + num + 1).toString(16)
} else {
tmp = num.toString(16)
}
if (tmp.length === 1) {
tmp = '0' + tmp
}
str += tmp
}
return str
}
function loraWANV2DataFormat (str, divisor = 1) {
let strReverse = bigEndianTransform(str)
let str2 = toBinary(strReverse)
if (str2.substring(0, 1) === '1') {
let arr = str2.split('')
let reverseArr = arr.map((item) => {
if (parseInt(item) === 1) {
return 0
} else {
return 1
}
})
str2 = parseInt(reverseArr.join(''), 2) + 1
return parseFloat('-' + str2 / divisor)
}
return parseInt(str2, 2) / divisor
}

function bigEndianTransform (data) {
let dataArray = []
for (let i = 0; i < data.length; i += 2) {
dataArray.push(data.substring(i, i + 2))
}
return dataArray
}

function toBinary (arr) {
let binaryData = arr.map((item) => {
let data = parseInt(item, 16)
.toString(2)
let dataLength = data.length
if (data.length !== 8) {
for (let i = 0; i < 8 - dataLength; i++) {
data = `0` + data
}
}
return data
})
return binaryData.toString().replace(/,/g, '')
}

function getMacAndRssiObj (pair) {
let pairs = []
if (pair.length % 14 === 0) {
for (let i = 0; i < pair.length; i += 14) {
let mac = getMacAddress(pair.substring(i, i + 12))
if (mac) {
let rssi = getInt8RSSI(pair.substring(i + 12, i + 14))
pairs.push({mac: mac, rssi: rssi})
} else {
continue
}
}
}
return pairs
}

function getMacAddress (str) {
if (str.toLowerCase() === 'ffffffffffff') {
return null
}
let macArr = []
for (let i = 1; i < str.length; i++) {
if (i % 2 === 1) {
macArr.push(str.substring(i - 1, i + 1))
}
}
let mac = ''
for (let i = 0; i < macArr.length; i++) {
mac = mac + macArr[i]
if (i < macArr.length - 1) {
mac = mac + ':'
}
}
return mac
}

function getInt8RSSI (str) {
return loraWANV2DataFormat(str)
}

function getInt (str) {
return parseInt(str, 16)
}

function getEventStatus (str) {
let bitStr = getByteArray(str)
let bitArr = []
for (let i = 0; i < bitStr.length; i++) {
bitArr[i] = bitStr.substring(i, i + 1)
}
bitArr = bitArr.reverse()
const EVENT_MAP = {
0: {id: 1, eventName: "Start moving event."},
1: {id: 2, eventName: "End movement event."},
2: {id: 3, eventName: "Motionless event."},
3: {id: 4, eventName: "Shock event."},
4: {id: 5, eventName: "Temperature event."},
5: {id: 6, eventName: "Light event."},
6: {id: 7, eventName: "SOS event."},
7: {id: 8, eventName: "Press once event."},
8: {id: 9, eventName: "disassembled event"}
}
let event = []
for (let i = 0; i < bitArr.length; i++) {
if (bitArr[i] === '1' && EVENT_MAP[i]) {
event.push(EVENT_MAP[i])
}
}
return event
}

function getByteArray (str) {
let bytes = []
for (let i = 0; i < str.length; i += 2) {
bytes.push(str.substring(i, i + 2))
}
return toBinary(bytes)
}

function getWorkingMode (workingMode) {
return getInt(workingMode)
}

function getPositioningStrategy (strategy) {
return getInt(strategy)
}

function getUTCTimestamp(str){
return parseInt(loraWANV2PositiveDataFormat(str)) * 1000
}

function loraWANV2PositiveDataFormat (str, divisor = 1) {
let strReverse = bigEndianTransform(str)
let str2 = toBinary(strReverse)
return parseInt(str2, 2) / divisor
}

exports.handler = async (event) => {
try {
const lorawan_info = event["WirelessMetadata"]["LoRaWAN"];
const lorawan_data = event["PayloadData"];
const resolved_data = decodeUplink(lorawan_data, lorawan_info["FPort"])["data"];
console.log("decoded message:", JSON.stringify(resolved_data))

// publish all measurement data
const input = { // PublishRequest
topic: 'tracker/measurement',
qos: 0,
retain: false,
payload: JSON.stringify({
eui: lorawan_info["DevEui"],
timestamp: lorawan_info["Timestamp"],
data: resolved_data
})
};
const command = new PublishCommand(input);
const response = await client.send(command);
console.log("response: " + JSON.stringify(response));
return {
statusCode: 200,
body: 'Message published successfully' + JSON.stringify(event)
};
} catch (error) {
console.error('Error publishing message:', error);

return {
statusCode: 500,
body: 'Error publishing message'
};
}
};

pir

Después de configurar el decodificador, haz clic en ConfigurationPermissionsEdit.

pir

Haz clic en View the xxxxxxxxxxx role en la parte inferior.

pir

Haz clic en Add permissionsAttach policies.

pir

Busca AdministratorAccess, marca la casilla a la izquierda y luego haz clic en Add Permissions.

pir

Verificar los datos

Verifica los datos en la página MQTT test client, ingresa # y haz clic en el botón Subscribe, verás los datos.

pir

La carga útil sin procesar del T2000 Tracker se publica desde t2000-raw y los datos decodificados se publican desde tracker/measurement.

pir

pir

Recursos

Decodificador SenseCAP T2000 Tracker para AWS

Soporte Técnico y Discusión de Productos

¡Gracias por elegir nuestros productos! Estamos aquí para brindarle diferentes tipos de soporte para asegurar que su experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para satisfacer diferentes preferencias y necesidades.

Loading Comments...