diff --git a/sites/en/static/js/language-switcher.js b/sites/en/static/js/language-switcher.js
index 050a1e1f64544..9c8bd3c479a06 100644
--- a/sites/en/static/js/language-switcher.js
+++ b/sites/en/static/js/language-switcher.js
@@ -1,6 +1,6 @@
// 语言切换器 - 生产环境优化版本
-// 生成时间: 2026-03-11 13:45:57 (北京时间)
-// 多语言页面: 2207 个
+// 生成时间: 2026-03-12 17:40:12 (北京时间)
+// 多语言页面: 2209 个
(function() {
'use strict';
@@ -13186,6 +13186,16 @@
"es",
"ja"
],
+ "/t2000_faq": [
+ "cn",
+ "es",
+ "ja"
+ ],
+ "/t2000_payload_format": [
+ "cn",
+ "es",
+ "ja"
+ ],
"/": [
"en",
"cn",
diff --git a/sites/es/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/es_FAQ.md b/sites/es/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/es_FAQ.md
new file mode 100644
index 0000000000000..0c2f60cbd3e1e
--- /dev/null
+++ b/sites/es/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/es_FAQ.md
@@ -0,0 +1,136 @@
+---
+description: Preguntas frecuentes sobre el rastreador SenseCAP T2000
+title: Preguntas frecuentes
+keywords:
+ - Tracker
+ - SenseCAP
+image: https://files.seeedstudio.com/wiki/SenseCAP/SenseCAP_T2000_Tracker/SenseCAP_T2000_Tracker_QuickStart.webp
+slug: /t2000_faq
+last_update:
+ date: 3/12/2026
+ author: Janet
+createdAt: '2026-03-12'
+updatedAt: '2026-03-12'
+url: https://wiki.seeedstudio.com/es/t2000_faq/
+---
+
+# Preguntas frecuentes
+
+### Relacionado con la localización
+
+
+¿Cuál es la precisión típica de posicionamiento GNSS del T2000?
+
+- En condiciones de cielo abierto, la precisión de posicionamiento GNSS del T2000 suele alcanzar un nivel de precisión de metros.
+- Los resultados de las pruebas muestran un CEP50 (Error Circular Probable al 50%) de aproximadamente **5–7 metros**, lo que significa que más de la mitad de los puntos de localización caen dentro de este rango respecto a la posición real.
+- La precisión de posicionamiento real puede variar según el entorno, la visibilidad de los satélites, las condiciones de instalación, etc.
+
+
+
+
+
+
+¿Por qué a veces el posicionamiento GNSS muestra deriva o no hay datos de latitud y longitud GNSS?
+
+- La precisión del GNSS puede verse afectada por varios factores ambientales:
+ - Edificios, árboles u otros obstáculos que bloquean las señales de los satélites.
+ - Efectos multitrayectoria causados por reflexiones de señales en paredes o superficies metálicas.
+ - Interferencias electromagnéticas de equipos electrónicos cercanos.
+ - Mala orientación de la antena o lugar de instalación inadecuado.
+
+- En algunos casos, el dispositivo puede no informar datos de latitud y longitud GNSS porque el escaneo GNSS ha excedido el tiempo de espera. Este estado puede verse en la carga útil de subida, donde el campo de **estado de posicionamiento** mostrará **"GNSS scan timeout"** debido a las mismas condiciones ambientales mencionadas anteriormente.
+
+- Para obtener los mejores resultados, instala el dispositivo en un área exterior abierta con una vista despejada del cielo.
+
+
+
+
+
+¿Cómo se debe instalar el T2000 para lograr el mejor rendimiento GNSS?
+
+- Coloca el dispositivo en un entorno abierto con obstrucción mínima a las señales de los satélites.
+- Asegúrate de que el área de la antena GNSS esté orientada hacia arriba, hacia el cielo.
+- Evita instalar el dispositivo cerca de objetos metálicos grandes o estructuras densas.
+- Evita cubrir el dispositivo o colocarlo dentro de recintos metálicos sellados.
+
+
+
+
+
+¿Por qué la localización por Wi‑Fi o Bluetooth no se muestra en el mapa de la app SenseCraft?
+
+- La localización por Wi‑Fi y Bluetooth requiere un servicio de análisis de mapas de terceros, que debe ser invocado por los usuarios para el análisis. Actualmente, la app SenseCraft solo admite la visualización de posicionamiento GNSS.
+
+
+
+
+
+Para más detalles sobre el posicionamiento GNSS, consulta el blog: [¿Qué tan precisa es la localización GNSS del SenseCAP T2000?](https://www.seeedstudio.com/blog/2026/01/19/how-accurate-is-the-sensecap-t2000-gnss-positioning/)
+
+
+### Relacionado con la batería
+
+
+¿Cuál es la diferencia entre la batería del T2000-A/B y la del T2000-C?
+
+- **T2000-A/B**
+ - Alimentado por una **batería primaria de 8000mAh**.
+ - Diseñado para despliegues a largo plazo sin recarga.
+
+- **T2000-C**
+ - Alimentado por una **batería recargable de 4000mAh**.
+ - Equipado con un **panel solar de 0.5W** para funcionamiento continuo en exteriores.
+ - Adecuado para despliegues donde haya luz solar disponible y se necesite minimizar el mantenimiento.
+
+
+
+
+
+¿Qué tan eficiente es la carga solar en el T2000-C?
+
+- El T2000-C utiliza un **panel solar de 0.5W con una batería recargable** para admitir un funcionamiento prolongado en exteriores.
+- El panel solar puede generar **hasta unos 60mA de corriente de carga**, produciendo aproximadamente **60mAh** de energía por hora en buenas condiciones de luz solar (estos datos son solo de referencia).
+
+
+
+
+
+¿Qué factores afectan la eficiencia de la carga solar?
+
+- El rendimiento de la carga solar puede variar según:
+ - La exposición e intensidad de la luz solar
+ - La orientación del panel y el ángulo de instalación
+ - Las sombras de objetos cercanos
+ - Polvo, suciedad o residuos en el panel solar
+ - Temperatura ambiente (la carga de la batería funciona entre 0–45°C)
+
+- Para obtener el mejor rendimiento, instala el dispositivo en un lugar con luz solar directa y revisa periódicamente la superficie del panel.
+
+
+
+
+
+¿Puede el T2000-C funcionar de forma continua con energía solar?
+
+- En configuraciones de bajo consumo (como intervalos de subida más largos), la carga solar incluso puede mantener o aumentar el nivel de la batería durante el funcionamiento diario.
+- Sin embargo, los intervalos de reporte frecuentes (por ejemplo, cada 1 minuto) pueden consumir más energía de la que el panel solar puede reponer.
+- Para un análisis más detallado del rendimiento de la carga solar, consulta el siguiente blog: [¿Qué tan eficiente es la carga solar en el SenseCAP T2000‑C?](https://www.seeedstudio.com/blog/2026/01/19/how-efficient-is-the-solar-charging-on-the-sensecap-t2000-c/)
+
+
+
+La vida útil estimada de la batería puede calcularse utilizando la siguiente [Calculadora de vida útil de la batería](https://files.seeedstudio.com/products/SenseCAP/T2000_Tracker/SenseCAP_Tracker_Battery_Life_Calculator_T2000.xls).
+
+
+## Soporte técnico y debate sobre el producto
+
+Gracias por elegir nuestros productos. Estamos aquí para ofrecerte diferentes tipos de soporte y garantizar que tu experiencia con nuestros productos sea lo más fluida posible. Ofrecemos varios canales de comunicación para adaptarnos a diferentes preferencias y necesidades.
+
+
diff --git a/sites/es/docs/Sensor/SenseCAP/es_SenseCAP_Decoder.md b/sites/es/docs/Sensor/SenseCAP/es_SenseCAP_Decoder.md
index 4e5b7b7c4ab01..f3f5b5b5aa335 100644
--- a/sites/es/docs/Sensor/SenseCAP/es_SenseCAP_Decoder.md
+++ b/sites/es/docs/Sensor/SenseCAP/es_SenseCAP_Decoder.md
@@ -1,29 +1,29 @@
---
description: SenseCAP_Decoder
-title: SenseCAP Decoder
+title: Decodificador SenseCAP
keywords:
- SenseCAP_Decoder
image: https://files.seeedstudio.com/wiki/wiki-platform/S-tempor.png
slug: /SenseCAP_Decoder
last_update:
- date: 1/26/2026
+ date: 3/12/2026
author: Janet
createdAt: '2023-08-24'
-updatedAt: '2026-03-03'
+updatedAt: '2026-03-12'
url: https://wiki.seeedstudio.com/es/SenseCAP_Decoder/
---
-El decodificador SenseCAP se utiliza para decodificar los mensajes LoRaWAN enviados desde los dispositivos SenseCAP LoRaWAN®. Después de la decodificación, las aplicaciones de los usuarios obtendrán mensajes más amigables y legibles.
+El decodificador SenseCAP se utiliza para decodificar los mensajes LoRaWAN enviados desde los dispositivos LoRaWAN® SenseCAP. Después de la decodificación, las aplicaciones de los usuarios obtendrán mensajes más amigables y legibles.
-### SenseCAP T1000 Tracker
+### Rastreador SenseCAP T1000
-El [**SenseCAP T1000**](https://www.seeedstudio.com/sensecap-t1000-tracker?utm_source=emailsig&utm_medium=emailsig&utm_campaign=emailsig) es un rastreador LoRaWAN® compacto que utiliza GNSS/Wi-Fi/Bluetooth para un seguimiento preciso de ubicación en interiores y exteriores. Cuenta con capacidades de auto-geo-adaptación, almacenamiento local de datos y una impresionante duración de batería de meses. Además, está equipado con sensores de temperatura, luz y movimiento, lo que lo hace ideal para una variedad de aplicaciones basadas en ubicación.
+[**SenseCAP T1000**](https://www.seeedstudio.com/sensecap-t1000-tracker?utm_source=emailsig&utm_medium=emailsig&utm_campaign=emailsig) es un rastreador LoRaWAN® compacto que utiliza GNSS/Wi-Fi/Bluetooth para un seguimiento de ubicación preciso tanto en interiores como en exteriores. Cuenta con capacidades de auto geo-adaptación, almacenamiento local de datos y una impresionante autonomía de batería de varios meses. Además, está equipado con sensores de temperatura, luz y movimiento, lo que lo hace ideal para una variedad de aplicaciones basadas en la ubicación.

@@ -49,833 +49,6 @@ function decodeUplink (input) {
decoded.messages.push({fport: fport, payload: bytesString})
return { data: decoded }
}
- if (fport !== 5) {
- decoded.valid = false
- return { data: decoded }
- }
- 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)
- }
- }
- // decoded.messages = measurement
- 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 = []
-
- for (let i = 0; i < messageValue.length; i++) {
- let remainMessage = messageValue
- let dataId = remainMessage.substring(0, 2).toUpperCase()
- let dataValue
- let dataObj = {}
- let packageLen
- switch (dataId) {
- case '01':
- packageLen = 94
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '02':
- packageLen = 32
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '03':
- packageLen = 64
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '04':
- packageLen = 20
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '05':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '06':
- packageLen = 44
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '07':
- packageLen = 84
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '08':
- packageLen = 70
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '09':
- packageLen = 36
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0A':
- packageLen = 76
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0B':
- packageLen = 62
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0C':
- packageLen = 2
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- break
- case '0D':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0E':
- packageLen = getInt(remainMessage.substring(8, 10)) * 2 + 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, 8) + remainMessage.substring(10, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0F':
- packageLen = 34
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '10':
- packageLen = 26
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '11':
- packageLen = 28
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- default:
- return frameArray
- }
- if (dataValue.length < 2) {
- break
- }
- frameArray.push(dataObj)
- }
- return frameArray
-}
-
-function deserialize (dataId, dataValue) {
- let measurementArray = []
- let eventList = []
- let measurement = {}
- let collectTime = 0
- let groupId = 0
- let shardFlag = {}
- let payload = ''
- let result = []
- let dataArr = []
- switch (dataId) {
- case '01':
- measurementArray = getUpShortInfo(dataValue)
- measurementArray.push(...getMotionSetting(dataValue.substring(30, 40)))
- measurementArray.push(...getStaticSetting(dataValue.substring(40, 46)))
- measurementArray.push(...getShockSetting(dataValue.substring(46, 52)))
- measurementArray.push(...getTempSetting(dataValue.substring(52, 72)))
- measurementArray.push(...getLightSetting(dataValue.substring(72, 92)))
- break
- case '02':
- measurementArray = getUpShortInfo(dataValue)
- break
- case '03':
- measurementArray.push(...getMotionSetting(dataValue.substring(0, 10)))
- measurementArray.push(...getStaticSetting(dataValue.substring(10, 16)))
- measurementArray.push(...getShockSetting(dataValue.substring(16, 22)))
- measurementArray.push(...getTempSetting(dataValue.substring(22, 42)))
- measurementArray.push(...getLightSetting(dataValue.substring(42, 62)))
- break
- case '04':
- let interval = 0
- let workMode = getInt(dataValue.substring(0, 2))
- let heartbeatInterval = getMinsByMin(dataValue.substring(4, 8))
- let periodicInterval = getMinsByMin(dataValue.substring(8, 12))
- let 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', type: 'Work Mode', measurementValue: workMode},
- {measurementId: '3942', type: 'Heartbeat Interval', measurementValue: heartbeatInterval},
- {measurementId: '3943', type: 'Periodic Interval', measurementValue: periodicInterval},
- {measurementId: '3944', type: 'Event Interval', measurementValue: eventInterval},
- {measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(dataValue.substring(16, 18))},
- {measurementId: '3900', type: 'Uplink Interval', measurementValue: interval}
- ]
- break;
- case '05':
- measurementArray = [
- {measurementId: '3000', type: 'Battery', measurementValue: getBattery(dataValue.substring(0, 2))},
- {measurementId: '3940', type: 'Work Mode', measurementValue: getWorkingMode(dataValue.substring(2, 4))},
- {measurementId: '3965', type: 'Positioning Strategy', measurementValue: getPositioningStrategy(dataValue.substring(4, 6))},
- {measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(dataValue.substring(6, 8))}
- ]
- break
- case '06':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}
- ]
- break
- case '07':
- eventList = getEventStatus(dataValue.substring(0, 6))
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(80, 82))}
- ]
- break
- case '08':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(66, 68))}
- ]
- break
- case '09':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(32, 34))}
- ]
- break
- case '0A':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(72, 74))}
- ]
- break
- case '0B':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(58, 60))},
- ]
- 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 '0E':
- shardFlag = getShardFlag(dataValue.substring(0, 2))
- groupId = getInt(dataValue.substring(2, 6))
- payload = dataValue.substring(6)
- measurement = {
- measurementId: '6152',
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'gnss-ng payload',
- measurementValue: payload
- }
- measurementArray.push(measurement)
- break
- case '0F':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- shardFlag = getShardFlag(dataValue.substring(26, 28))
- groupId = getInt(dataValue.substring(28, 32))
- measurementArray.push({
- measurementId: '4200',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Event Status',
- measurementValue: getEventStatus(dataValue.substring(0, 6))
- })
- measurementArray.push({
- measurementId: '4097',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
- })
- measurementArray.push({
- measurementId: '4199',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
- })
- measurementArray.push({
- measurementId: '3000',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
- })
- break
- case '10':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- shardFlag = getShardFlag(dataValue.substring(18, 20))
- groupId = getInt(dataValue.substring(20, 24))
- measurementArray.push({
- measurementId: '4200',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Event Status',
- measurementValue: getEventStatus(dataValue.substring(0, 6))
- })
- measurementArray.push({
- measurementId: '3000',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(16, 18))
- })
- break
- case '11':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray.push({
- measurementId: '3576',
- timestamp: collectTime,
- type: 'Positing Status',
- measurementValue: '' + getPositingStatus(dataValue.substring(0, 2))
- })
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '4200',
- type: 'Event Status',
- measurementValue: getEventStatus(dataValue.substring(2, 8))
- })
- if (!isNaN(parseFloat(getSensorValue(dataValue.substring(16, 20), 10)))) {
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '4097',
- type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
- })
- }
- if (!isNaN(parseFloat(getSensorValue(dataValue.substring(20, 24))))) {
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '4199',
- type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
- })
- }
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '3000',
- type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
- })
- break
- }
- return measurementArray
-}
-
-function getMotionId (str) {
- return getInt(str)
-}
-
-function getPositingStatus (str) {
- return getInt(str)
-}
-
-function getUpShortInfo (messageValue) {
- return [
- {
- measurementId: '3000', type: 'Battery', measurementValue: getBattery(messageValue.substring(0, 2))
- }, {
- measurementId: '3502', type: 'Firmware Version', measurementValue: getSoftVersion(messageValue.substring(2, 6))
- }, {
- measurementId: '3001', type: 'Hardware Version', measurementValue: getHardVersion(messageValue.substring(6, 10))
- }, {
- measurementId: '3940', type: 'Work Mode', measurementValue: getWorkingMode(messageValue.substring(10, 12))
- }, {
- measurementId: '3965', type: 'Positioning Strategy', measurementValue: getPositioningStrategy(messageValue.substring(12, 14))
- }, {
- measurementId: '3942', type: 'Heartbeat Interval', measurementValue: getMinsByMin(messageValue.substring(14, 18))
- }, {
- measurementId: '3943', type: 'Periodic Interval', measurementValue: getMinsByMin(messageValue.substring(18, 22))
- }, {
- measurementId: '3944', type: 'Event Interval', measurementValue: getMinsByMin(messageValue.substring(22, 26))
- }, {
- measurementId: '3945', type: 'Sensor Enable', measurementValue: getInt(messageValue.substring(26, 28))
- }, {
- measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(messageValue.substring(28, 30))
- }
- ]
-}
-
-function getMotionSetting (str) {
- return [
- {measurementId: '3946', type: 'Motion Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3947', type: 'Any Motion Threshold', measurementValue: getSensorValue(str.substring(2, 6), 1)},
- {measurementId: '3948', type: 'Motion Start Interval', measurementValue: getMinsByMin(str.substring(6, 10))},
- ]
-}
-
-function getStaticSetting (str) {
- return [
- {measurementId: '3949', type: 'Static Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3950', type: 'Device Static Timeout', measurementValue: getMinsByMin(str.substring(2, 6))}
- ]
-}
-
-function getShockSetting (str) {
- return [
- {measurementId: '3951', type: 'Shock Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3952', type: 'Shock Threshold', measurementValue: getInt(str.substring(2, 6))}
- ]
-}
-
-function getTempSetting (str) {
- return [
- {measurementId: '3953', type: 'Temp Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3954', type: 'Event Temp Interval', measurementValue: getMinsByMin(str.substring(2, 6))},
- {measurementId: '3955', type: 'Event Temp Sample Interval', measurementValue: getSecondsByInt(str.substring(6, 10))},
- {measurementId: '3956', type: 'Temp ThMax', measurementValue: getSensorValue(str.substring(10, 14), 10)},
- {measurementId: '3957', type: 'Temp ThMin', measurementValue: getSensorValue(str.substring(14, 18), 10)},
- {measurementId: '3958', type: 'Temp Warning Type', measurementValue: getInt(str.substring(18, 20))}
- ]
-}
-
-function getLightSetting (str) {
- return [
- {measurementId: '3959', type: 'Light Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3960', type: 'Event Light Interval', measurementValue: getMinsByMin(str.substring(2, 6))},
- {measurementId: '3961', type: 'Event Light Sample Interval', measurementValue: getSecondsByInt(str.substring(6, 10))},
- {measurementId: '3962', type: 'Light ThMax', measurementValue: getSensorValue(str.substring(10, 14), 10)},
- {measurementId: '3963', type: 'Light ThMin', measurementValue: getSensorValue(str.substring(14, 18), 10)},
- {measurementId: '3964', type: 'Light Warning Type', measurementValue: getInt(str.substring(18, 20))}
- ]
-}
-
-function getShardFlag (str) {
- let bitStr = getByteArray(str)
- return {
- count: parseInt(bitStr.substring(0, 4), 2),
- index: parseInt(bitStr.substring(4), 2)
- }
-}
-
-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 getSecondsByInt (str) {
- return getInt(str)
-}
-
-function getMinsByMin (str) {
- return getInt(str)
-}
-
-function getSensorValue (str, dig) {
- if (str === '8000') {
- return null
- } else {
- 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 '-' + 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 getSOSMode (str) {
- return loraWANV2DataFormat(str)
-}
-
-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) {
- // return getInt(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()
- let event = []
- for (let i = 0; i < bitArr.length; i++) {
- if (bitArr[i] !== '1') {
- continue
- }
- switch (i){
- case 0:
- event.push({id:1, eventName:"Start moving event."})
- break
- case 1:
- event.push({id:2, eventName:"End movement event."})
- break
- case 2:
- event.push({id:3, eventName:"Motionless event."})
- break
- case 3:
- event.push({id:4, eventName:"Shock event."})
- break
- case 4:
- event.push({id:5, eventName:"Temperature event."})
- break
- case 5:
- event.push({id:6, eventName:"Light event."})
- break
- case 6:
- event.push({id:7, eventName:"SOS event."})
- break
- case 7:
- event.push({id:8, eventName:"Press once event."})
- break
- }
- }
- 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
-}
-```
-
-
-
-
-
-Para Helium
-
-```cpp
-function Decoder (bytes, port) {
- const bytesString = bytes2HexString(bytes)
- const originMessage = bytesString.toLocaleUpperCase()
- const fport = parseInt(port)
- const decoded = {
- valid: true,
- err: 0,
- payload: bytesString,
- messages: []
- }
-
- if (fport === 199 || fport === 192) {
- decoded.messages.push({fport: fport, payload: bytesString})
- return { data: decoded }
- }
- if (fport !== 5) {
- decoded.valid = false
- return { data: decoded }
- }
-
let measurement = messageAnalyzed(originMessage)
if (measurement.length === 0) {
decoded.valid = false
@@ -899,7 +72,6 @@ function Decoder (bytes, port) {
decoded.messages.push(elements)
}
}
- // decoded.messages = measurement
return { data: decoded }
}
@@ -922,7 +94,6 @@ function messageAnalyzed (messageValue) {
function unpack (messageValue) {
let frameArray = []
-
for (let i = 0; i < messageValue.length; i++) {
let remainMessage = messageValue
let dataId = remainMessage.substring(0, 2).toUpperCase()
@@ -931,148 +102,93 @@ function unpack (messageValue) {
let packageLen
switch (dataId) {
case '01':
- packageLen = 94
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 94)
+ messageValue = remainMessage.substring(94)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '02':
- packageLen = 32
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 32)
+ messageValue = remainMessage.substring(32)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '03':
- packageLen = 64
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 64)
+ messageValue = remainMessage.substring(64)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '04':
- packageLen = 20
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 20)
+ messageValue = remainMessage.substring(20)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '05':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 10)
+ messageValue = remainMessage.substring(10)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '06':
- packageLen = 44
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 44)
+ messageValue = remainMessage.substring(44)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '07':
- packageLen = 84
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 84)
+ messageValue = remainMessage.substring(84)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '08':
- packageLen = 70
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 70)
+ messageValue = remainMessage.substring(70)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '09':
- packageLen = 36
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 36)
+ messageValue = remainMessage.substring(36)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0A':
- packageLen = 76
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 76)
+ messageValue = remainMessage.substring(76)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0B':
- packageLen = 62
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 62)
+ messageValue = remainMessage.substring(62)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0C':
- packageLen = 2
- if (remainMessage.length < packageLen) {
- return frameArray
- }
break
case '0D':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 10)
+ messageValue = remainMessage.substring(10)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0E':
packageLen = getInt(remainMessage.substring(8, 10)) * 2 + 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
dataValue = remainMessage.substring(2, 8) + remainMessage.substring(10, packageLen)
messageValue = remainMessage.substring(packageLen)
dataObj = {
@@ -1080,34 +196,50 @@ function unpack (messageValue) {
}
break
case '0F':
- packageLen = 34
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 34)
+ messageValue = remainMessage.substring(34)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '10':
- packageLen = 26
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 26)
+ messageValue = remainMessage.substring(26)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '11':
- packageLen = 28
- if (remainMessage.length < packageLen) {
- return frameArray
+ dataValue = remainMessage.substring(2, 28)
+ messageValue = remainMessage.substring(28)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
}
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ break
+ case '1A':
+ dataValue = remainMessage.substring(2, 56)
+ messageValue = remainMessage.substring(56)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
+ }
+ break
+ case '1B':
+ dataValue = remainMessage.substring(2, 96)
+ messageValue = remainMessage.substring(96)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
+ }
+ break
+ case '1C':
+ dataValue = remainMessage.substring(2, 82)
+ messageValue = remainMessage.substring(82)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
+ }
+ break
+ case '1D':
+ dataValue = remainMessage.substring(2, 40)
+ messageValue = remainMessage.substring(40)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
@@ -1131,8 +263,7 @@ function deserialize (dataId, dataValue) {
let groupId = 0
let shardFlag = {}
let payload = ''
- let result = []
- let dataArr = []
+ let motionId = ''
switch (dataId) {
case '01':
measurementArray = getUpShortInfo(dataValue)
@@ -1188,59 +319,65 @@ function deserialize (dataId, dataValue) {
break
case '06':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '4197', timestamp: collectTime, motionId: motionId, type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
+ {measurementId: '4198', timestamp: collectTime, motionId: motionId, type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
+ {measurementId: '4097', timestamp: collectTime, motionId: motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId: motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}
]
break
case '07':
eventList = getEventStatus(dataValue.substring(0, 6))
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(80, 82))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5001', timestamp: collectTime, motionId: motionId, type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
+ {measurementId: '4097', timestamp: collectTime, motionId: motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId: motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(80, 82))}
]
break
case '08':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(66, 68))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5002', timestamp: collectTime, motionId: motionId, type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
+ {measurementId: '4097', timestamp: collectTime, motionId: motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId: motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(66, 68))}
]
break
case '09':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(32, 34))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '4197', timestamp: collectTime, motionId: motionId, type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
+ {measurementId: '4198', timestamp: collectTime, motionId: motionId, type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(32, 34))}
]
break
case '0A':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(72, 74))}
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5001', timestamp: collectTime, motionId, type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(72, 74))}
]
break
case '0B':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(58, 60))},
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5002', timestamp: collectTime, motionId, type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(58, 60))},
]
break
case '0D':
@@ -1277,10 +414,11 @@ function deserialize (dataId, dataValue) {
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
shardFlag = getShardFlag(dataValue.substring(26, 28))
groupId = getInt(dataValue.substring(28, 32))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray.push({
measurementId: '4200',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
@@ -1290,42 +428,43 @@ function deserialize (dataId, dataValue) {
measurementArray.push({
measurementId: '4097',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
+ measurementValue: getSensorValue(dataValue.substring(16, 20), 10)
})
measurementArray.push({
measurementId: '4199',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
+ measurementValue: getSensorValue(dataValue.substring(20, 24))
})
measurementArray.push({
measurementId: '3000',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
+ measurementValue: getBattery(dataValue.substring(24, 26))
})
break
case '10':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
shardFlag = getShardFlag(dataValue.substring(18, 20))
groupId = getInt(dataValue.substring(20, 24))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray.push({
measurementId: '4200',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
@@ -1335,12 +474,12 @@ function deserialize (dataId, dataValue) {
measurementArray.push({
measurementId: '3000',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(16, 18))
+ measurementValue: getBattery(dataValue.substring(16, 18))
})
break
case '11':
@@ -1348,8 +487,8 @@ function deserialize (dataId, dataValue) {
measurementArray.push({
measurementId: '3576',
timestamp: collectTime,
- type: 'Positing Status',
- measurementValue: '' + getPositingStatus(dataValue.substring(0, 2))
+ type: 'Positioning Status',
+ measurementValue: getPositingStatus(dataValue.substring(0, 2))
})
measurementArray.push({
timestamp: collectTime,
@@ -1362,7 +501,7 @@ function deserialize (dataId, dataValue) {
timestamp: collectTime,
measurementId: '4097',
type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
+ measurementValue: getSensorValue(dataValue.substring(16, 20), 10)
})
}
if (!isNaN(parseFloat(getSensorValue(dataValue.substring(20, 24))))) {
@@ -1370,14 +509,112 @@ function deserialize (dataId, dataValue) {
timestamp: collectTime,
measurementId: '4199',
type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
+ measurementValue: getSensorValue(dataValue.substring(20, 24))
})
}
measurementArray.push({
timestamp: collectTime,
measurementId: '3000',
type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
+ measurementValue: getBattery(dataValue.substring(24, 26))
+ })
+ break
+ case '1A':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
+ measurementArray = [
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '4197', timestamp: collectTime, motionId, type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
+ {measurementId: '4198', timestamp: collectTime, motionId, type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
+ {measurementId: '4097', timestamp: collectTime, motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
+ {measurementId: '4210', timestamp: collectTime, motionId, type: 'AccelerometerX', measurementValue: getSensorValue(dataValue.substring(40, 44))},
+ {measurementId: '4211', timestamp: collectTime, motionId, type: 'AccelerometerY', measurementValue: getSensorValue(dataValue.substring(44, 48))},
+ {measurementId: '4212', timestamp: collectTime, motionId, type: 'AccelerometerZ', measurementValue: getSensorValue(dataValue.substring(48, 52))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(52, 54))},
+ ]
+ break
+ case '1B':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
+ measurementArray = [
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5001', timestamp: collectTime, motionId, type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
+ {measurementId: '4097', timestamp: collectTime, motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
+ {measurementId: '4210', timestamp: collectTime, motionId, type: 'AccelerometerX', measurementValue: getSensorValue(dataValue.substring(80, 84))},
+ {measurementId: '4211', timestamp: collectTime, motionId, type: 'AccelerometerY', measurementValue: getSensorValue(dataValue.substring(84, 88))},
+ {measurementId: '4212', timestamp: collectTime, motionId, type: 'AccelerometerZ', measurementValue: getSensorValue(dataValue.substring(88, 92))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(92, 94))}
+ ]
+ break
+ case '1C':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
+ measurementArray = [
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5002', timestamp: collectTime, motionId, type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
+ {measurementId: '4097', timestamp: collectTime, motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
+ {measurementId: '4210', timestamp: collectTime, motionId, type: 'AccelerometerX', measurementValue: getSensorValue(dataValue.substring(66, 70))},
+ {measurementId: '4211', timestamp: collectTime, motionId, type: 'AccelerometerY', measurementValue: getSensorValue(dataValue.substring(70, 74))},
+ {measurementId: '4212', timestamp: collectTime, motionId, type: 'AccelerometerZ', measurementValue: getSensorValue(dataValue.substring(74, 78))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(78, 80))}
+ ]
+ break
+ case '1D':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ measurementArray.push({
+ measurementId: '3576',
+ timestamp: collectTime,
+ type: 'Positioning Status',
+ measurementValue: getPositingStatus(dataValue.substring(0, 2))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4200',
+ type: 'Event Status',
+ measurementValue: getEventStatus(dataValue.substring(2, 8))
+ })
+ if (!isNaN(parseFloat(getSensorValue(dataValue.substring(16, 20), 10)))) {
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4097',
+ type: 'Air Temperature',
+ measurementValue: getSensorValue(dataValue.substring(16, 20), 10)
+ })
+ }
+ if (!isNaN(parseFloat(getSensorValue(dataValue.substring(20, 24))))) {
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4199',
+ type: 'Light',
+ measurementValue: getSensorValue(dataValue.substring(20, 24))
+ })
+ }
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4210',
+ type: 'AccelerometerX',
+ measurementValue: getSensorValue(dataValue.substring(24, 28))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4211',
+ type: 'AccelerometerY',
+ measurementValue: getSensorValue(dataValue.substring(28, 32))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4212',
+ type: 'AccelerometerZ',
+ measurementValue: getSensorValue(dataValue.substring(32, 36))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '3000',
+ type: 'Battery',
+ measurementValue: getBattery(dataValue.substring(36, 38))
})
break
}
@@ -1389,6 +626,39 @@ function getMotionId (str) {
}
function getPositingStatus (str) {
+ let status = getInt(str)
+ switch (status) {
+ case 0:
+ return {id:status, statusName:"locate successful."}
+ case 1:
+ return {id:status, statusName:"The GNSS scan timed out."}
+ case 2:
+ return {id:status, statusName:"The Wi-Fi scan timed out."}
+ case 3:
+ return {id:status, statusName:"The Wi-Fi + GNSS scan timed out."}
+ case 4:
+ return {id:status, statusName:"The GNSS + Wi-Fi scan timed out."}
+ case 5:
+ return {id:status, statusName:"The Bluetooth scan timed out."}
+ case 6:
+ return {id:status, statusName:"The Bluetooth + Wi-Fi scan timed out."}
+ case 7:
+ return {id:status, statusName:"The Bluetooth + GNSS scan timed out."}
+ case 8:
+ return {id:status, statusName:"The Bluetooth + Wi-Fi + GNSS scan timed out."}
+ case 9:
+ return {id:status, statusName:"Location Server failed to parse the GNSS location."}
+ case 10:
+ return {id:status, statusName:"Location Server failed to parse the Wi-Fi location."}
+ case 11:
+ return {id:status, statusName:"Location Server failed to parse the Bluetooth location."}
+ case 12:
+ return {id:status, statusName:"Failed to parse location due to the poor accuracy."}
+ case 13:
+ return {id:status, statusName:"Time synchronization failed."}
+ case 14:
+ return {id:status, statusName:"Failed due to the old Almanac."}
+ }
return getInt(str)
}
@@ -1526,7 +796,7 @@ function loraWANV2DataFormat (str, divisor = 1) {
}
})
str2 = parseInt(reverseArr.join(''), 2) + 1
- return '-' + str2 / divisor
+ return parseFloat('-' + str2 / divisor)
}
return parseInt(str2, 2) / divisor
}
@@ -1603,7 +873,6 @@ function getInt (str) {
}
function getEventStatus (str) {
- // return getInt(str)
let bitStr = getByteArray(str)
let bitArr = []
for (let i = 0; i < bitStr.length; i++) {
@@ -3334,17 +2603,17 @@ exports.handler = async (event) => {
-### SenseCAP T2000 Tracker
+### Rastreador SenseCAP T2000
#### Decodificador
-[**SenseCAP T2000 Tracker**](https://www.seeedstudio.com/SenseCAP-Asset-Tracker-T2000-A-p-6580.html), un rastreador de activos LoRaWAN® de grado industrial, soporta posicionamiento GNSS, Bluetooth y Wi-Fi para un seguimiento confiable en entornos interiores y exteriores. Cuenta con protección IP67, un acelerómetro de 3 ejes integrado que detecta el estado de movimiento, y un botón anti-manipulación que activa una alarma de máxima prioridad si el dispositivo es removido. El T2000-A y T2000-B soportan operación de batería de larga duración, mientras que el T2000-C alimentado por energía solar con batería recargable asegura uso continuo en exteriores, haciendo que la serie sea ideal para seguimiento de activos a largo plazo y libre de mantenimiento.
+[**SenseCAP T2000 Tracker**](https://www.seeedstudio.com/SenseCAP-Asset-Tracker-T2000-A-p-6580.html), un rastreador de activos LoRaWAN® de grado industrial, es compatible con posicionamiento GNSS, Bluetooth y Wi‑Fi para un seguimiento fiable en entornos interiores y exteriores. Cuenta con protección IP67, un acelerómetro triaxial integrado que detecta el estado de movimiento y un botón antimanipulación que activa una alarma de máxima prioridad si se retira el dispositivo. El T2000-A y el T2000-B admiten un funcionamiento prolongado con batería, mientras que el T2000-C con energía solar y batería recargable garantiza un uso continuo en exteriores, lo que hace que la serie sea ideal para el seguimiento de activos a largo plazo y sin mantenimiento.

@@ -5527,17 +4796,17 @@ exports.handler = async (event) => {
```
-### Wio Tracker 1110 Dev Board
+### Placa de desarrollo Wio Tracker 1110
-La [Wio Tracker 1110 Dev Board](https://www.seeedstudio.com/Wio-Tracker-1110-Dev-Board-p-5799.html) está basada en el [Módulo Inalámbrico Wio-WM1110](https://www.seeedstudio.com/Wio-WM1110-Module-LR1110-and-nRF52840-p-5676.html) e integra el transceptor LoRa® [LR1110 de Semtech](https://www.semtech.com/products/wireless-rf/lora-edge/lr1110) y un front-end de radio multipropósito para geolocalización, es una plataforma de desarrollo de seguimiento basada en LoRa fácil de usar.
+La [Wio Tracker 1110 Dev Board](https://www.seeedstudio.com/Wio-Tracker-1110-Dev-Board-p-5799.html) está basada en el [módulo inalámbrico Wio-WM1110](https://www.seeedstudio.com/Wio-WM1110-Module-LR1110-and-nRF52840-p-5676.html) e integra el transceptor LoRa® [LR1110 de Semtech](https://www.semtech.com/products/wireless-rf/lora-edge/lr1110) y un front-end de radio multipropósito para geolocalización; es una plataforma de desarrollo de rastreo basada en LoRa, fácil de usar.
-Con su tamaño compacto y interfaces ricas, la Wio Tracker 1110 Dev Board está convenientemente equipada con una antena integrada para fácil despliegue. Soporta el entorno de desarrollo Arduino y la pila de protocolos LoRaWAN, haciéndola ideal para proyectos IoT relacionados con seguimiento.
+Con su tamaño compacto y sus interfaces ricas, la Wio Tracker 1110 Dev Board está convenientemente equipada con una antena integrada para un despliegue sencillo. Es compatible con el entorno de desarrollo de Arduino y la pila de protocolos LoRaWAN, lo que la hace ideal para proyectos de IoT relacionados con el rastreo.

@@ -7468,13 +6737,13 @@ function loraWANV2PositiveDataFormat(str) {
### Sensores LoRaWAN SenseCAP S210X
-[SenseCAP S210X](https://www.seeedstudio.com/catalogsearch/result/?q=s210x) es una serie de sensores inalámbricos LoRaWAN®. Puede cubrir un rango de transmisión de 2km en escenas urbanas y 10km en escenas de línea de vista mientras mantiene un menor consumo de energía durante el proceso de transmisión. Junto con una batería reemplazable que soporta hasta 10 años de uso y una carcasa industrial IP66. Soporta temperatura de funcionamiento de -40 ~ 85℃ y puede ser desplegado en entornos hostiles. SenseCAP S210X es compatible con el protocolo LoRaWAN® V1.0.3 y puede trabajar con gateway LoRaWAN®.
+[SenseCAP S210X](https://www.seeedstudio.com/catalogsearch/result/?q=s210x) es una serie de sensores inalámbricos LoRaWAN®. Puede cubrir un rango de transmisión de 2 km en escenarios urbanos y 10 km en escenarios de línea de vista, manteniendo un menor consumo de energía durante el proceso de transmisión. Junto con una batería reemplazable que admite hasta 10 años de uso y una carcasa industrial IP66. Admite una temperatura de funcionamiento de -40 ~ 85 ℃ y puede desplegarse en entornos hostiles. SenseCAP S210X es compatible con el protocolo LoRaWAN® V1.0.3 y puede funcionar con una puerta de enlace LoRaWAN®.

@@ -9140,15 +8409,15 @@ exports.handler = async (event) => {
-### SenseCAP S2100 Data Logger
+### Registrador de Datos SenseCAP S2100
-El [SenseCAP S2100 Data Logger](https://www.seeedstudio.com/SenseCAP-S2100-LoRaWAN-Data-Logger-p-5361.html) es un dispositivo versátil que puede conectarse a sensores MODBUS-RTU RS485/Analógicos/GPIO, permitiendo la transmisión fácil de datos a la red LoRaWAN. Con su diseño LoRa e IP66, este dispositivo cuenta con una estabilidad y confiabilidad impresionantes, y puede cubrir un largo rango de transmisión mientras mantiene un consumo de energía ultra bajo. Es perfecto para uso exterior, y puede ser alimentado por batería o conectado a una fuente de alimentación externa de 12V para mayor flexibilidad. Cuando se conecta a la fuente de alimentación de 12V, la batería incorporada reemplazable actúa como fuente de energía de respaldo. Además, el S2100 Data Logger está optimizado para OTA con Bluetooth incorporado, haciendo que la configuración y actualizaciones sean rápidas y simples. Para completar, el convertidor S2110 permite al S2100 Data Logger conectarse a Sensores Grove, convirtiéndolo en una excelente opción para sensores LoRaWAN de nivel industrial DIY y despliegue a pequeña escala.
+[SenseCAP S2100 Data Logger](https://www.seeedstudio.com/SenseCAP-S2100-LoRaWAN-Data-Logger-p-5361.html) es un dispositivo versátil que puede conectarse a sensores MODBUS-RTU RS485/Analógico/GPIO, lo que permite una transmisión sencilla de datos a la red LoRaWAN. Con su diseño LoRa e IP66, este dispositivo ofrece una estabilidad y fiabilidad impresionantes, y puede cubrir un largo alcance de transmisión manteniendo un consumo de energía ultra bajo. Es perfecto para uso en exteriores y puede alimentarse mediante batería o conectarse a una fuente de alimentación externa de 12 V para una flexibilidad aún mayor. Cuando está conectado a la fuente de alimentación de 12 V, la batería interna reemplazable actúa como fuente de alimentación de respaldo. Además, el Registrador de Datos S2100 está optimizado para OTA con Bluetooth integrado, lo que hace que la configuración y las actualizaciones sean rápidas y sencillas. Para rematar, el convertidor S2110 permite que el Registrador de Datos S2100 se conecte a sensores Grove, lo que lo convierte en una excelente opción para sensores LoRaWAN de nivel industrial DIY y despliegues a pequeña escala.

@@ -10403,15 +9672,15 @@ function bytes2HexString (arrBytes) {
---
-### SenseCAP S2120 Sensor Meteorológico 8-en-1
+### SenseCAP S2120 Sensor meteorológico 8 en 1
-El [Sensor Meteorológico LoRaWAN SenseCAP S2120 8-en-1](https://www.seeedstudio.com/sensecap-s2120-lorawan-8-in-1-weather-sensor-p-5436.html) mide temperatura del aire, humedad, velocidad del viento, dirección del viento, precipitación, intensidad de luz, índice UV y presión barométrica. Permite un bajo costo de mantenimiento por su consumo ultra bajo de energía, rendimiento confiable, Bluetooth integrado y servicio de aplicación para configuración OTA y gestión remota de dispositivos. Soporta aplicaciones multi-escenario como patio trasero, jardines, agricultura inteligente, meteorología, ciudad inteligente, etc.
+[SenseCAP S2120 8-in-1 LoRaWAN Weather Sensor](https://www.seeedstudio.com/sensecap-s2120-lorawan-8-in-1-weather-sensor-p-5436.html) mide la temperatura del aire, la humedad, la velocidad del viento, la dirección del viento, la lluvia, la intensidad de la luz, el índice UV y la presión barométrica. Permite un bajo coste de mantenimiento gracias a su consumo de energía ultrabajo, rendimiento fiable, Bluetooth integrado y servicio de aplicación para configuración OTA y gestión remota del dispositivo. Es compatible con aplicaciones en múltiples escenarios como patios traseros, jardines, agricultura inteligente, meteorología, ciudad inteligente, etc.

@@ -10423,7 +9692,7 @@ import Tabs3 from '@theme/Tabs';
import TabItem3 from '@theme/TabItem';
-
+
@@ -10886,7 +10155,7 @@ function bytes2HexString (arrBytes) {
-
+
@@ -11508,15 +10777,15 @@ function Decoder (bytes, port) {
---
-### SenseCAP A1101 - Sensor de IA de Visión LoRaWAN
+### SenseCAP A1101 - LoRaWAN Vision AI Sensor
-[SenseCAP A1101 - Sensor de IA de Visión LoRaWAN](https://www.seeedstudio.com/SenseCAP-A1101-LoRaWAN-Vision-AI-Sensor-p-5367.html) es un sensor de imagen inteligente habilitado con TinyML Edge AI. Soporta una variedad de modelos de IA como reconocimiento de imágenes, conteo de personas, detección de objetivos, reconocimiento de medidores, etc. También soporta el entrenamiento de modelos con TensorFlow Lite.
+[SenseCAP A1101 - LoRaWAN Vision AI Sensor](https://www.seeedstudio.com/SenseCAP-A1101-LoRaWAN-Vision-AI-Sensor-p-5367.html) es un sensor de imagen inteligente TinyML Edge AI habilitado. Es compatible con una variedad de modelos de IA, como reconocimiento de imágenes, conteo de personas, detección de objetivos, reconocimiento de medidores, etc. También admite el entrenamiento de modelos con TensorFlow Lite.

@@ -11528,7 +10797,7 @@ import Tabs4 from '@theme/Tabs';
import TabItem4 from '@theme/TabItem';
-
+
@@ -12568,36 +11837,36 @@ function toBinary (arr) {
---
-### Cómo Usar
+### Cómo usar
##### Preparación
-Antes de configurar el decodificador, configure correctamente sus sensores y gateway según el manual del producto, y luego conéctese al servidor de red LoRaWAN que necesite.
+Antes de configurar el decodificador, configura correctamente tus sensores y gateway de acuerdo con el manual del producto y luego conéctate al servidor de red LoRaWAN que necesites.
-Tomamos The Things Stack como ejemplo, configure el decodificador según los siguientes pasos:
+Tomamos The Things Stack como ejemplo, configura el decodificador según los siguientes pasos:
-##### Configurar el Decodificador de Payload
+##### Configurar el decodificador de carga útil
-- Navegue a la pestaña `Payload Formats` de su dispositivo.
-- Seleccione `Custom` para `Payload Format`
-- Copie y pegue todo el contenido de `decoder.js` en el área de texto `decoder`.
-- Haga clic en `save payload functions`
+- Navega a la pestaña `Payload Formats` de tu dispositivo.
+- Selecciona `Custom` para `Payload Format`
+- Copia y pega todo el contenido de `decoder.js` en el área de texto `decoder`.
+- Haz clic en `save payload functions`

-##### Verificar los Mensajes Decodificados
+##### Comprobar los mensajes decodificados
-Puede probar el script de decodificación con un payload de muestra primero.
+Puedes probar primero el script de decodificación con una carga útil de ejemplo.
-Para hacer esto, copie un paquete de datos sin procesar como `01 01 10 98 53 00 00 01 02 10 A8 7A 00 00 AF 51` en la entrada de texto `Payload`, y seleccione el `FPort` según el manual del dispositivo, luego haga clic en el botón `Test`. Verá una estructura JSON analizada exitosamente a continuación.
+Para ello, copia un paquete de datos en bruto como `01 01 10 98 53 00 00 01 02 10 A8 7A 00 00 AF 51` en la entrada de texto `Payload`, selecciona el `FPort` de acuerdo con el manual del dispositivo y luego haz clic en el botón `Test`. Verás una estructura JSON analizada correctamente debajo.

-Ahora veamos la magia del script. Navegamos a la pestaña `Live Data`, y puede expandir cualquier mensaje cargado para verificar los `Event Fields` en el payload. Estos campos son poblados por el script.
+Luego veamos la magia del script. Navegamos a la pestaña `Live Data`, y puedes expandir cualquier mensaje subido para comprobar los `Event Fields` en la carga útil. Estos campos son rellenados por el script.

-Si está suscrito a los mensajes con la API de Datos MQTT de TTN, también obtendrá campos de payload JSON analizados.
+Si estás suscribiendo los mensajes con el TTN's MQTT Data API, también obtendrás campos de carga útil JSON ya analizados.
```cpp
Client mosq-TCSlhYcKaRCn3cIePE received PUBLISH (d0, q0, r0, m0, 'lorawan868/devices/2cf7f12010700041/up', ... (719 bytes))
@@ -12606,4 +11875,4 @@ lorawan868/devices/2cf7f12010700041/up {"app_id":"lorawan868","dev_id":"2cf7f120
### Recurso
-[Decodificador SenseCAP](https://github.com/Seeed-Solution/SenseCAP-Decoder)
+[SenseCAP Decoder](https://github.com/Seeed-Solution/SenseCAP-Decoder)
diff --git a/sites/es/sidebars.js b/sites/es/sidebars.js
index e67ddfe846bee..502d193ab76a6 100644
--- a/sites/es/sidebars.js
+++ b/sites/es/sidebars.js
@@ -714,6 +714,8 @@ const sidebars = {
label: 'Guía del usuario',
items: [
'Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/es_Quick_Start',
+ 'Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/es_Payload_Format',
+ 'Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/es_FAQ',
],
},
{
diff --git a/sites/es/static/js/language-switcher.js b/sites/es/static/js/language-switcher.js
index 050a1e1f64544..9c8bd3c479a06 100644
--- a/sites/es/static/js/language-switcher.js
+++ b/sites/es/static/js/language-switcher.js
@@ -1,6 +1,6 @@
// 语言切换器 - 生产环境优化版本
-// 生成时间: 2026-03-11 13:45:57 (北京时间)
-// 多语言页面: 2207 个
+// 生成时间: 2026-03-12 17:40:12 (北京时间)
+// 多语言页面: 2209 个
(function() {
'use strict';
@@ -13186,6 +13186,16 @@
"es",
"ja"
],
+ "/t2000_faq": [
+ "cn",
+ "es",
+ "ja"
+ ],
+ "/t2000_payload_format": [
+ "cn",
+ "es",
+ "ja"
+ ],
"/": [
"en",
"cn",
diff --git a/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/ja_FAQ.md b/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/ja_FAQ.md
new file mode 100644
index 0000000000000..15d0390916c7b
--- /dev/null
+++ b/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/ja_FAQ.md
@@ -0,0 +1,136 @@
+---
+description: SenseCAP T2000 Tracker よくある質問
+title: よくある質問
+keywords:
+ - Tracker
+ - SenseCAP
+image: https://files.seeedstudio.com/wiki/SenseCAP/SenseCAP_T2000_Tracker/SenseCAP_T2000_Tracker_QuickStart.webp
+slug: /t2000_faq
+last_update:
+ date: 3/12/2026
+ author: Janet
+createdAt: '2026-03-12'
+updatedAt: '2026-03-12'
+url: https://wiki.seeedstudio.com/ja/t2000_faq/
+---
+
+# よくある質問
+
+### 位置情報関連
+
+
+T2000 の一般的な GNSS 測位精度はどのくらいですか?
+
+- 開けた空の下では、T2000 の GNSS 測位精度は一般的にメートルレベルの精度に達します。
+- テスト結果では CEP50(50%円形誤差半径)はおよそ **5~7 メートル** であり、これは位置ポイントの半数以上が真の位置からこの範囲内に収まることを意味します。
+- 実際の測位精度は、環境、衛星の見通し、設置条件などによって変動する場合があります。
+
+
+
+
+
+
+なぜ GNSS 測位がドリフトして見えたり、GNSS の緯度・経度データが表示されないことがあるのですか?
+
+- GNSS の精度は、いくつかの環境要因の影響を受ける可能性があります:
+ - 建物、樹木、その他の障害物による衛星信号の遮断。
+ - 壁や金属面での信号反射によって生じるマルチパス効果。
+ - 近くの電子機器からの電磁干渉。
+ - アンテナの向きや設置場所が不適切。
+
+- 場合によっては、GNSS スキャンがタイムアウトしたために、デバイスが GNSS の緯度・経度データを報告しないことがあります。この状態はアップリンクペイロードで確認でき、上記と同じ環境条件により、**測位ステータス** フィールドに **"GNSS scan timeout"** と表示されます。
+
+- 最良の結果を得るには、空がよく見える屋外の開けた場所にデバイスを設置してください。
+
+
+
+
+
+最良の GNSS 性能を得るために、T2000 はどのように設置すればよいですか?
+
+- 衛星信号の遮蔽物が最小限となる開けた環境にデバイスを設置してください。
+- GNSS アンテナ部分が空に向かって上向きになるようにしてください。
+- 大きな金属物体や高密度の構造物の近くへの設置は避けてください。
+- デバイスを覆ったり、密閉された金属ケースの中に入れたりしないでください。
+
+
+
+
+
+なぜ SenseCraft App の地図に Wi-Fi や Bluetooth の位置情報が表示されないのですか?
+
+- Wi-Fi および Bluetooth の位置情報には、ユーザーが呼び出して解析を行うサードパーティの地図解析サービスが必要です。現在、SenseCraft App がサポートしているのは GNSS 測位の表示のみです。
+
+
+
+
+
+GNSS 測位の詳細については、次のブログを参照してください:[How Accurate is the SenseCAP T2000 GNSS Positioning?](https://www.seeedstudio.com/blog/2026/01/19/how-accurate-is-the-sensecap-t2000-gnss-positioning/)
+
+
+### バッテリー関連
+
+
+T2000-A/B と T2000-C のバッテリーの違いは何ですか?
+
+- **T2000-A/B**
+ - **8000mAh の一次電池**で駆動します。
+ - 充電なしでの長期展開向けに設計されています。
+
+- **T2000-C**
+ - **4000mAh の充電式バッテリー**で駆動します。
+ - 屋外での連続動作を実現するために、**0.5W のソーラーパネル**を搭載しています。
+ - 日照が得られ、メンテナンスを最小限に抑えたい設置環境に適しています。
+
+
+
+
+
+T2000-C のソーラー充電効率はどのくらいですか?
+
+- T2000-C は、長期の屋外運用をサポートするために、**0.5W のソーラーパネルと充電式バッテリー**を使用しています。
+- 良好な日照条件下では、ソーラーパネルは **最大約 60mA の充電電流**を生成し、1 時間あたりおよそ **60mAh** のエネルギーを供給できます(このデータは参考値です)。
+
+
+
+
+
+ソーラー充電効率に影響する要因は何ですか?
+
+- ソーラー充電性能は、次のような要因によって変動します:
+ - 日照時間と日射強度
+ - パネルの向きと設置角度
+ - 近くの物体による影
+ - ソーラーパネル上のほこり、汚れ、ゴミ
+ - 周囲温度(バッテリー充電は 0~45°C の間で動作)
+
+- 最良の性能を得るには、直射日光が当たる場所にデバイスを設置し、定期的にパネル表面を確認してください。
+
+
+
+
+
+T2000-C はソーラー電源だけで連続動作できますか?
+
+- 低消費電力構成(アップリンク間隔を長くするなど)の場合、ソーラー充電によって日常運用中でもバッテリーレベルを維持、あるいは増加させることができます。
+- しかし、(1 分ごとのような)頻繁な送信間隔では、ソーラーパネルが補える量より多くの電力を消費する可能性があります。
+- ソーラー充電性能のより詳細な分析については、次のブログを参照してください:[How Efficient Is the Solar Charging on the SenseCAP T2000‑C?](https://www.seeedstudio.com/blog/2026/01/19/how-efficient-is-the-solar-charging-on-the-sensecap-t2000-c/)
+
+
+
+推定バッテリー寿命は、次の [Battery Life Calculator](https://files.seeedstudio.com/products/SenseCAP/T2000_Tracker/SenseCAP_Tracker_Battery_Life_Calculator_T2000.xls) を使用して算出できます。
+
+
+## 技術サポートと製品ディスカッション
+
+弊社製品をお選びいただきありがとうございます。弊社は、製品をできるだけスムーズにご利用いただけるよう、さまざまなサポートを提供しています。お好みやニーズに応じて選択いただける複数のコミュニケーションチャネルをご用意しています。
+
+
+
+
\ No newline at end of file
diff --git a/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/ja_Payload_Format.md b/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/ja_Payload_Format.md
new file mode 100644
index 0000000000000..e6b620cd77f02
--- /dev/null
+++ b/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/User_Guide/ja_Payload_Format.md
@@ -0,0 +1,522 @@
+---
+description: SenseCAP T2000 Tracker ペイロードフォーマット
+title: ペイロードフォーマット
+keywords:
+ - トラッカー
+ - SenseCAP
+image: https://files.seeedstudio.com/wiki/SenseCAP/SenseCAP_T2000_Tracker/SenseCAP_T2000_Tracker_QuickStart.webp
+slug: /t2000_payload_format
+last_update:
+ date: 3/12/2026
+ author: Janet
+createdAt: '2026-03-12'
+updatedAt: '2026-03-12'
+url: https://wiki.seeedstudio.com/ja/t2000_payload_format/
+---
+
+# ペイロードフォーマット
+
+## アップリンクパケットの解析
+
+トラッカーのデータプロトコルは、異なる情報に対応するために複数のパケットを提供しており、各パケットのバイト数は異なる場合があります。フレームの構造は下図のとおりです。フレーム内容は**ビッグエンディアンのバイト順**で送信されます。
+
+|データ ID|データ値|
+| - | :- |
+|1 バイト|50 バイト(最大)|
+
+**データ ID**: 機能番号。
+**データ値**: 位置情報、センサーデータおよびその他の情報。
+
+### 電源オンパケット (0x27)
+
+電源オンパケットは、デバイスの起動直後に送信されます。現在の設定パラメータとデバイスステータスが含まれます。フレーム ID は `0x27` で、全長は 46 バイトです。
+
+| 0x27 | Byte2 | Byte3~4 | Byte5~6 | Byte7 | Byte8 | Byte9~10 | Byte11~12 |
+| :--: | :---: | :-----: | :-----: | :--: | :--: | :------: | :-------: |
+| ID | バッテリーレベル | ソフトウェアバージョン | ハードウェアバージョン | 動作モード | 測位ストラテジー | ハートビート間隔 | 周期モードアップリンク間隔 |
+
+| Byte13~14 | Byte15 | Byte16 | Byte17 | Byte18 | Byte19~20 | Byte21~22 |
+| :-------: | :----: | :----: | :----: | :----: | :-------: | :-------: |
+| イベントモードアップリンク間隔 | 3 軸加速度センサー有効化 | 分解アラーム有効化 | GNSS スキャンタイムアウト | 動作イベント有効化 | 3 軸動作しきい値 | 動作時アップリンク間隔 |
+
+| Byte23 | Byte24~25 | Byte26 | Byte27~28 | Byte29 | Byte30 | Byte31~46 |
+| :----: | :-------: | :----: | :-------: | :----: | :----: | :-------: |
+| 静止イベント有効化 | 静止タイムアウト | 衝撃イベント有効化 | 3 軸衝撃しきい値 | iBeacon スキャンタイムアウト (s) | UUID フィルター有効バイト数 | UUID フィルター (16 バイト) |
+
+**生ペイロード例**
+
+`27 56 0100 0101 01 08 02d0 003c 003c 00 01 3c 00 001e 0005 00 0168 00 012c 03 00 00000000000000000000000000000000`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 27 | 27 はパケット ID です |
+| 2 | バッテリーレベル | uint8 | 56 | `0x56` = 86(DEC)
バッテリーレベルは 86% です |
+| 3~4 | ソフトウェアバージョン | uint16 | 0100 | `0x0100` = v1.0
ソフトウェアバージョンは v1.0 です |
+| 5~6 | ハードウェアバージョン | uint16 | 0101 | `0x0101` = v1.1
ハードウェアバージョンは v1.1 です |
+| 7 | 動作モード | uint8 | 01 | 01 = 周期モード
`00`: 待機モード
`01`: 周期モード
`02`: イベントモード |
+| 8 | 測位ストラテジー | uint8 | 00 | 07 = 0x07、デバイスが Bluetooth + Wi-Fi + GNSS の測位ストラテジーを使用することを意味します
`00`: GNSS のみ
`01`: Wi-Fi のみ
`02`: Wi-Fi + GNSS
`03`: GNSS + Wi-Fi
`04`: Bluetooth のみ
`05`: Bluetooth + Wi-Fi
`06`: Bluetooth + GNSS
`07`: Bluetooth + Wi-Fi + GNSS
`08`: GNSS + Bluetooth |
+| 9~10 | ハートビート間隔 | uint16 | 02d0 | `0x02D0` = 720 分 |
+| 11~12 | 周期モードアップリンク間隔 | uint16 | 003c | `0x003C` = 60 分 |
+| 13~14 | イベントモードアップリンク間隔 | uint16 | 003c | `0x003C` = 60 分 |
+| 15 | 3 軸加速度センサー有効化 | uint8 | 00 | `00`: 無効
`01`: 有効 |
+| 16 | 分解アラーム有効化 | uint8 | 01 | `00`: 無効
`01`: 有効 |
+| 17 | GNSS スキャンタイムアウト | uint8 | 3c | `0x3C` = 60 秒 |
+| 18 | 動作イベント有効化 | uint8 | 00 | `00`: 無効
`01`: 有効 |
+| 19~20 | 3 軸動作しきい値 | uint16 | 001e | `0x001e` = 30 mg |
+| 21~22 | 動作時アップリンク間隔 | uint16 | 0005 | `0x05` = 5 分 |
+| 23 | 静止イベント有効化 | uint8 | 00 | `0x00`: 無効
`0x01`: 有効 |
+| 24~25 | 静止タイムアウト | uint16 | 0168 | `0x0168` = 360 分 |
+| 26 | 衝撃イベント有効化 | uint8 | 00 | `00`: 無効
`01`: 有効 |
+| 27~28 | 3 軸衝撃しきい値 | uint16 | 012c | `0x012c` = 300 mg |
+| 29 | iBeacon スキャンタイムアウト (s) | uint8 | 03 | `0x03` = 3 秒 |
+| 30 | UUID フィルター有効バイト数 | uint8 | 00 | UUID フィルター内の有効バイト数 (0–16) |
+| 31~46 | UUID フィルター | 16 bytes | 0000000000000000
0000000000000000 | 16 バイトの Bluetooth UUID フィルター。先頭 N バイト(byte30 で定義)が有効です |
+
+### 周期モードパケット (0x28)
+
+周期モードパラメータパケットには、現在の動作モード設定が含まれます。フレーム ID は `0x28` で、全長は 30 バイトです。
+
+| 0x28 | Byte2 | Byte3 | Byte4~5 | Byte6~7 | Byte8~9 | Byte10 | Byte11 | Byte12 | Byte13 | Byte14 | Byte15~30 |
+| :--: | :---: | :---: | :-----: | :-----: | :-----: | :----: | :----: | :----: | :----: | :----: | :-------: |
+| ID | 動作モード | 測位ストラテジー | ハートビート間隔 | アップリンク間隔 | イベントモードアップリンク間隔 | 3 軸加速度センサー有効化 | 分解アラーム有効化 | GNSS スキャンタイムアウト | iBeacon スキャンタイムアウト | UUID フィルター有効バイト数 | UUID フィルター (16 バイト) |
+
+**生ペイロード例**
+
+`28 01 07 02d0 003c 003c 01 00 3c 0a 10 00000000000000000000000000000000`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 28 | 28 はパケット ID です |
+| 2 | 動作モード | uint8 | 01 | 01 = 周期モード
`00`: 待機モード
`01`: 周期モード
`02`: イベントモード |
+| 3 | 測位ストラテジー | uint8 | 07 | 07 = 0x07、デバイスが Bluetooth + Wi-Fi + GNSS の測位ストラテジーを使用することを意味します
`00`: GNSS のみ
`01`: Wi-Fi のみ
`02`: Wi-Fi + GNSS
`03`: GNSS + Wi-Fi
`04`: Bluetooth のみ
`05`: Bluetooth + Wi-Fi
`06`: Bluetooth + GNSS
`07`: Bluetooth + Wi-Fi + GNSS
`08`: GNSS + Bluetooth |
+| 4~5 | ハートビート間隔 | uint16 | 02d0 | `0x02D0` = 720 分 |
+| 6~7 | アップリンク間隔 | uint16 | 003c | `0x003C` = 60 分 |
+| 8~9 | イベントモードアップリンク間隔 | uint16 | 003c | `0x003C` = 60 分
イベントがトリガーされない場合、データは 60 分ごとにアップロードされます。
|
+| 10 | 3 軸加速度センサー有効化 | uint8 | 01 | `00`: 無効
`01`: 有効 |
+| 11 | 分解アラーム有効化 | uint8 | 00 | `00`: 無効
`01`: 有効 |
+| 12 | GNSS スキャンタイムアウト | uint8 | 3c | `0x3C` = 60 秒 |
+| 13 | iBeacon スキャンタイムアウト | uint8 | 0a | `0x0A` = 10 秒 |
+| 14 | UUID フィルター有効バイト数 | uint8 | 10 | UUID フィルター内の有効バイト数 (0–16) |
+| 15~30 | UUID フィルター | 16 bytes | 0000000000000000
0000000000000000 | 16 バイトの Bluetooth UUID フィルター。先頭 N バイト(byte14 で定義)が有効です |
+
+### イベントモードパケット (0x29)
+
+イベントパラメータパケットには、動作、静止、および衝撃イベントの設定が含まれます。フレーム ID は `0x29` で、全長は 12 バイトです。
+
+| 0x29 | Byte2 | Byte3~4 | Byte5~6 | Byte7 | Byte8~9 | Byte10 | Byte11~12 |
+| :--: | :---: | :-----: | :-----: | :--: | :-----: | :----: | :-------: |
+| ID | 動作イベント有効化 | 3 軸動作しきい値 | 動作時アップリンク間隔 | 静止イベント有効化 | 静止タイムアウト | 衝撃イベント有効化 | 3 軸衝撃しきい値 |
+
+**生ペイロード例**
+
+`29 01 0064 001e 01 012c 00 012c`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 29 | 29 はパケット ID です |
+| 2 | 動作イベント有効化 | uint8 | 01 | `00`: 無効
`01`: 有効 |
+| 3~4 | 3 軸動作しきい値 | uint16 | 0064 | `0x0064` = 100 mg |
+| 5~6 | 動作時アップリンク間隔 | uint16 | 001e | `0x001E` = 30 分 |
+| 7 | 静止イベント有効化 | uint8 | 01 | `0x00`: 無効
`0x01`: 有効 |
+| 8~9 | 静止タイムアウト | uint16 | 012c | `0x012C` = 300 分 |
+| 10 | 衝撃イベント有効化 | uint8 | 00 | `0x00`: 無効
`0x01`: 有効 |
+| 11~12 | 3 軸衝撃しきい値 | uint16 | 0000 | `0x012c` = 300 mg |
+
+### ハートビートパケット (0x2A)
+
+ハートビートパケットは、デバイスが現在のステータスを報告するために定期的に送信されます。基本的なデバイス情報とセンサー状態が含まれます。フレーム ID は `0x2A` で、全長は 6 バイトです。
+
+| 0x2A | Byte2 | Byte3 | Byte4 | Byte5 | Byte6 |
+| :--: | :---: | :---: | :---: | :---: | :---: |
+| ID | バッテリーレベル | 動作モード | 測位ストラテジー | 3 軸加速度センサー有効化 | 分解アラーム有効化 |
+
+**生ペイロード例**
+
+`2a 56 01 07 01 00`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 2A | 2A はパケット ID です |
+| 2 | バッテリーレベル | uint8 | 56 | `0x56` = 86(DEC)
バッテリーレベルは 86% です |
+| 3 | 動作モード | uint8 | 01 | 01 = 周期モード
`00`: 待機モード
`01`: 周期モード
`02`: イベントモード |
+| 4 | 測位ストラテジー | uint8 | 07 | 07 = 0x07、デバイスが Bluetooth + Wi-Fi + GNSS の測位ストラテジーを使用することを意味します
`00`: GNSS のみ
`01`: Wi-Fi のみ
`02`: Wi-Fi + GNSS
`03`: GNSS + Wi-Fi
`04`: Bluetooth のみ
`05`: Bluetooth + Wi-Fi
`06`: Bluetooth + GNSS
`07`: Bluetooth + Wi-Fi + GNSS
`08`: GNSS + Bluetooth |
+| 5 | 3 軸加速度センサー有効化 | uint8 | 01 | `00`: 無効
`01`: 有効 |
+| 6 | 分解アラーム有効化 | uint8 | 00 | `00`: 無効
`01`: 有効 |
+
+### GNSS 位置情報データパケット (加速度センサーオン, 0x2B)
+
+GPS 位置情報データパケットには、GNSS 測位データに加え、加速度センサーおよびバッテリー情報が含まれます。フレーム ID は `0x2B` で、全長は 23 バイトです。
+
+| 0x2B | Byte2~3 | Byte4 | Byte5~8 | Byte9~10 | Byte11~12 | Byte13~14 | Byte15~18 | Byte19~22 | Byte23 |
+| :--: | :-----: | :--: | :-----: | :------: | :-------: | :-------: | :------: | :------: | :---: |
+| ID | イベントステータス | モーション ID | UTC タイムスタンプ | 加速度 X | 加速度 Y | 加速度 Z | 経度 | 緯度 | バッテリーレベル |
+
+**生ペイロード例**
+
+`2b 0100 00 694b3dc6 032f fffe 0241 06ca5098 01587ee4 62`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 2B | 2B はパケット ID です |
+| 2~3 | イベントステータス | uint16 | 0100 | `0x0100` = 分解イベント
Bit 0: false
Bit 1: 動作開始イベント
Bit 2: 動作終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 動作開始イベント
`0x0002`: 動作終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント |
+| 4 | モーション ID | uint8 | 00 | `0`: 特定の動作として記録する必要はありません。
`1~255`: 同一の動作状態下で報告された測位データ(同じ ID は同じ動作を指します) |
+| 5~8 | UTC タイムスタンプ | uint32 | 694b3dc6 | `0x694B3DC6` = 1766538694(DEC) 秒
UTC 時刻に変換:
2025-12-24 01:11:34 |
+| 9~10 | 加速度 X | int16 | 032f | `0x032F` = 815 mg |
+| 11~12 | 加速度 Y | int16 | fffe | `0xFFFE` = -2 mg |
+| 13~14 | 加速度 Z | int16 | 0241 | `0x0241` = 577 mg |
+| 15~18 | 経度 | uint32 | 06ca5098 | `0x06CA5098` = 113,922,200 → 113.922200° |
+| 19~22 | 緯度 | uint32 | 01587ee4 | `0x01587EE4` = 22,576,868 → 22.576868° |
+| 23 | バッテリーレベル | uint8 | 62 | `0x62` = 98% |
+
+### Wi-Fi 位置情報データパケット(加速度センサーオン, 0x2C)
+
+Wi-Fi 位置情報パケットには、Wi-Fi スキャン結果に加えて加速度センサーおよびバッテリー情報が含まれます。フレーム ID は `0x2C` で、全長はスキャンされた Wi-Fi アクセスポイントの数に応じて動的に変化します(23 + (n-1) * 7 バイト、ここで n は MAC-RSSI ペアの数です)。
+
+| 0x2C | Byte2~3 | Byte4 | Byte5~8 | Byte9~10 | Byte11~12 | Byte13~14 | Byte15 | Byte16 | Byte17+(n-1)*7 ~ Byte23+(n-1)*7 |
+| :--: | :-----: | :--: | :-----: | :------: | :-------: | :-------: | :---: | :---: | :---------------------------: |
+| ID | イベントステータス | モーション ID | UTC タイムスタンプ | 加速度センサー X | 加速度センサー Y | 加速度センサー Z | バッテリーレベル | MAC-RSSI カウント (n) | MAC-RSSI ペア (n) |
+
+**MAC-RSSI フォーマット**
+
+| Byte0~5 | Byte6 |
+| :-----: | :---: |
+| MAC アドレス (6 bytes) | RSSI (int8) |
+
+**生ペイロード例**
+
+`2c 0000 00 69685f82 0004 0015 03e5 64 05 107c61841bf8 e4 3447d468f627 e1 a4ba70bc229d d3 9483c46d5dfc d2 4c10d567b467 d0`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 2C | 2C はパケット ID です |
+| 2~3 | イベントステータス | uint16 | 0000 |`0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント|
+| 4 | モーション ID | uint8 | 00 | `0`: 特定のモーションとして記録する必要はありません。
`1~255`: 同一モーション状態下で報告される測位データ(同じ ID は同じモーションを指します) |
+| 5~8 | UTC タイムスタンプ | uint32 | 69685f82 | `0x69685F82` = 1768447874(DEC) 秒
UTC 時刻に変換:
2026-01-15 03:31:14 |
+| 9~10 | 加速度センサー X | int16 | 0004 | `0x0004` = 4 mg |
+| 11~12 | 加速度センサー Y | int16 | 0015 | `0x0015` = 21 mg |
+| 13~14 | 加速度センサー Z | int16 | 03e5 | `0x03E5` = 997 mg |
+| 15 | バッテリーレベル | uint8 | 64 | `0x64` = 100% |
+| 16 | MAC-RSSI カウント (n) | uint8 | 05 | 検出された Wi-Fi アクセスポイントの数(n = 5) |
+| 17~23 | MAC-RSSI ペア 1 | 7 bytes | 107c61841bf8 e4 | MAC: `10:7C:61:84:1B:F8`, RSSI: `0xE4` = -28 (int8) |
+| 24~30 | MAC-RSSI ペア 2 | 7 bytes | 3447d468f627 e1 | MAC: `34:47:D4:68:F6:27`, RSSI: `0xE1` = -31 (int8) |
+| 31~37 | MAC-RSSI ペア 3 | 7 bytes | a4ba70bc229d d3 | MAC: `A4:BA:70:BC:22:9D`, RSSI: `0xD3` = -45 (int8) |
+| 38~44 | MAC-RSSI ペア 4 | 7 bytes | 9483c46d5dfc d2 | MAC: `94:83:C4:6D:5D:FC`, RSSI: `0xD2` = -46 (int8) |
+| 45~51 | MAC-RSSI ペア 5 | 7 bytes | 4c10d567b467 d0 | MAC: `4C:10:D5:67:B4:67`, RSSI: `0xD0` = -48 (int8) |
+
+### BLE 位置情報データパケット(加速度センサーオン,0x2D)
+
+BLE 位置情報パケットには、Bluetooth スキャン結果に加えて加速度センサーおよびバッテリー情報が含まれます。フレーム ID は `0x2D` で、全長はスキャンされた Bluetooth デバイスの数に応じて動的に変化します(23 + (n-1) * 7 バイト、ここで n は MAC-RSSI ペアの数で、最大 n = 5)。
+
+| 0x2D | Byte2~3 | Byte4 | Byte5~8 | Byte9~10 | Byte11~12 | Byte13~14 | Byte15 | Byte16 | Byte17+(n-1)*7 ~ Byte23+(n-1)*7 |
+| :--: | :-----: | :--: | :-----: | :------: | :-------: | :-------: | :---: | :---: | :---------------------------: |
+| ID | イベントステータス | モーション ID | UTC タイムスタンプ | 加速度センサー X | 加速度センサー Y | 加速度センサー Z | バッテリーレベル | MAC-RSSI カウント (n) | MAC-RSSI ペア (n) |
+
+**MAC-RSSI フォーマット**
+
+| Byte0~5 | Byte6 |
+| :-----: | :---: |
+| MAC アドレス (6 bytes) | RSSI (int8) |
+
+**生ペイロード例**
+
+`2d 0000 00 69686032 fff9 0015 03df 64 05 c30000564b3b ce c20303003f00 ce 588c81a0fbf2 cc c20303003f03 cb c30000564af2 c7`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 2D | 2D はパケット ID です |
+| 2~3 | イベントステータス | uint16 | 0000 |`0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント|
+| 4 | モーション ID | uint8 | 00 | `0`: 特定のモーションとして記録する必要はありません。
`1~255`: 同一モーション状態下で報告される測位データ(同じ ID は同じモーションを指します) |
+| 5~8 | UTC タイムスタンプ | uint32 | 69686032 | `0x69686032` = 1768448050(DEC) 秒
UTC 時刻に変換:
2026-01-15 03:34:10 |
+| 9~10 | 加速度センサー X | int16 | fff9 | `0xFFF9` = -7 mg |
+| 11~12 | 加速度センサー Y | int16 | 0015 | `0x0015` = 21 mg |
+| 13~14 | 加速度センサー Z | int16 | 03df | `0x03DF` = 991 mg |
+| 15 | バッテリーレベル | uint8 | 64 | `0x64` = 100% |
+| 16 | MAC-RSSI カウント (n) | uint8 | 05 | 検出された Bluetooth デバイスの数(n = 5、最大 5) |
+| 17~23 | MAC-RSSI ペア 1 | 7 bytes | c30000564b3b ce | MAC: `C3:00:00:56:4B:3B`, RSSI: `0xCE` = -50 (int8) |
+| 24~30 | MAC-RSSI ペア 2 | 7 bytes | c20303003f00 ce | MAC: `C2:03:03:00:3F:00`, RSSI: `0xCE` = -50 (int8) |
+| 31~37 | MAC-RSSI ペア 3 | 7 bytes | 588c81a0fbf2 cc | MAC: `58:8C:81:A0:FB:F2`, RSSI: `0xCC` = -52 (int8) |
+| 38~44 | MAC-RSSI ペア 4 | 7 bytes | c20303003f03 cb | MAC: `C2:03:03:00:3F:03`, RSSI: `0xCB` = -53 (int8) |
+| 45~51 | MAC-RSSI ペア 5 | 7 bytes | c30000564af2 c7 | MAC: `C3:00:00:56:4A:F2`, RSSI: `0xC7` = -57 (int8) |
+
+### GNSS 位置情報データパケット(加速度センサーオフ, 0x2E)
+
+GNSS 位置情報データパケットには、GPS 測位データに加えてバッテリー情報が含まれます。フレーム ID は `0x2E` で、全長は 17 バイトです。
+
+| 0x2E | Byte2~3 | Byte4 | Byte5~8 | Byte9~12 | Byte13~16 | Byte17 |
+| :--: | :-----: | :--: | :-----: | :------: | :-------: | :----: |
+| ID | イベントステータス | モーション ID | UTC タイムスタンプ | 経度 | 緯度 | バッテリーレベル |
+
+**生ペイロード例**
+
+`2e 0100 01 64f1a2b3 06ca5098 01587ee4 62`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 2E | 2E はパケット ID です |
+| 2~3 | イベントステータス | uint16 | 0000 |`0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント|
+| 4 | モーション ID | uint8 | 00 | `0`: 特定のモーションとして記録する必要はありません。
`1~255`: 同一モーション状態下で報告される測位データ(同じ ID は同じモーションを指します) |
+| 5~8 | UTC タイムスタンプ | uint32 | 64f1a2b3 | `0x64f1a2b3` = 1693557427(DEC) 秒
UTC 時刻に変換:
2023-09-01 08:37:07 |
+| 9~12 | 経度 | uint32 | 06ca5098 | `0x06CA5098` = 113,922,200 → 113.922200° |
+| 13~16 | 緯度 | uint32 | 01587ee4 | `0x01587EE4` = 22,576,868 → 22.576868° |
+| 17 | バッテリーレベル | uint8 | 62 | `0x62` = 98% |
+
+### Wi-Fi 位置情報データパケット(加速度センサーオフ, 0x2F)
+
+Wi-Fi 位置情報データパケットには、Wi-Fi スキャン結果に加えてバッテリー情報が含まれます。フレーム ID は `0x2F` で、全長はスキャンされた Wi-Fi アクセスポイントの数に応じて動的に変化します(17 + (n-1) * 7 バイト、ここで n は MAC-RSSI ペアの数で、最大 n = 5)。
+
+| 0x2F | Byte2~3 | Byte4 | Byte5~8 | Byte9 | Byte10 | Byte11+(n-1)*7 ~ Byte16+(n-1)*7 |
+| :--: | :-----: | :--: | :-----: | :---: | :----: | :---------------------------: |
+| ID | イベントステータス | モーション ID | UTC タイムスタンプ | バッテリーレベル | MAC-RSSI カウント (n) | MAC-RSSI ペア (n) |
+
+**MAC-RSSI フォーマット**
+
+| Byte0~5 | Byte6 |
+| :-----: | :---: |
+| MAC アドレス (6 bytes) | RSSI (int8) |
+
+**生ペイロード例**
+
+`2f 0000 00 69685f82 64 05 107c61841bf8 e4 3447d468f627 e1 a4ba70bc229d d3 9483c46d5dfc d2 4c10d567b467 d0`
+
+| Byte | 値 | 型 | 生データ | 説明 |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 2F | 2F はパケット ID です |
+| 2~3 | イベントステータス | uint16 | 0000 |`0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント|
+| 4 | モーション ID | uint8 | 00 | `0`: 特定のモーションとして記録する必要はありません。
`1~255`: 同一モーション状態下で報告される測位データ(同じ ID は同じモーションを指します) |
+| 5~8 | UTC タイムスタンプ | uint32 | 69685f82 | `0x69685F82` = 1768447874(DEC) 秒
UTC 時刻に変換:
2026-01-15 03:31:14 |
+| 9 | バッテリーレベル | uint8 | 64 | `0x64` = 100% |
+| 10 | MAC-RSSI カウント (n) | uint8 | 05 | 検出された Wi-Fi アクセスポイントの数(n = 5、最大 5) |
+| 11~17 | MAC-RSSI ペア 1 | 7 bytes | 107c61841bf8 e4 | MAC: `10:7C:61:84:1B:F8`,
RSSI: `0xE4` = -28 (int8) |
+| 18~24 | MAC-RSSI ペア 2 | 7 bytes | 3447d468f627 e1 | MAC: `34:47:D4:68:F6:27`,
RSSI: `0xE1` = -31 (int8) |
+| 25~31 | MAC-RSSI ペア 3 | 7 bytes | a4ba70bc229d d3 | MAC: `A4:BA:70:BC:22:9D`,
RSSI: `0xD3` = -45 (int8) |
+| 32~38 | MAC-RSSI ペア 4 | 7 bytes | 9483c46d5dfc d2 | MAC: `94:83:C4:6D:5D:FC`,
RSSI: `0xD2` = -46 (int8) |
+| 39~45 | MAC-RSSI ペア 5 | 7 bytes | 4c10d567b467 d0 | MAC: `4C:10:D5:67:B4:67`,
RSSI: `0xD0` = -48 (int8) |
+
+### BLE 位置情報データパケット(加速度センサー Off, 0x30)
+
+BLE 位置情報データパケットには、Bluetooth スキャン結果とバッテリー情報が含まれます。フレーム ID は `0x30` で、全長はスキャンされた Bluetooth デバイス数に応じて動的に変化します(17 + (n-1) * 7 バイト、n は MAC-RSSI ペアの数で、最大 n = 5)。
+
+| 0x30 | Byte2~3 | Byte4 | Byte5~8 | Byte9 | Byte10 | Byte11+(n-1)*7 ~ Byte16+(n-1)*7 |
+| :--: | :-----: | :--: | :-----: | :---: | :----: | :---------------------------: |
+| ID | イベントステータス | モーション ID | UTC タイムスタンプ | バッテリーレベル | MAC-RSSI カウント (n) | MAC-RSSI ペア (n) |
+
+**MAC-RSSI フォーマット**
+
+| Byte0~5 | Byte6 |
+| :-----: | :---: |
+| MAC アドレス (6 bytes) | RSSI (int8) |
+
+**生ペイロード例**
+
+`30 0000 00 69686032 64 05 c30000564b3b ce c20303003f00 ce 588c81a0fbf2 cc c20303003f03 cb c30000564af2 c7`
+
+| Byte | Value | Type | Raw Data | Description |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 30 | 30 はパケット ID です |
+| 2~3 | イベントステータス | uint16 | 0000 |`0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント|
+| 4 | モーション ID | uint8 | 00 | `0`: 特定のモーションとして記録する必要はありません。
`1~255`: 同一モーション状態で報告された位置情報データ(同じ ID は同じモーションを示す) |
+| 5~8 | UTC タイムスタンプ | uint32 | 69686032 | `0x69686032` = 1768448050(DEC) 秒
UTC 時刻に変換:
2026-01-15 03:34:10 |
+| 9 | バッテリーレベル | uint8 | 64 | `0x64` = 100% |
+| 10 | MAC-RSSI カウント (n) | uint8 | 05 | 検出された Bluetooth デバイス数(n = 5、最大 5) |
+| 11~17 | MAC-RSSI ペア 1 | 7 bytes | c30000564b3b ce | MAC: `C3:00:00:56:4B:3B`,
RSSI: `0xCE` = -50 (int8) |
+| 18~24 | MAC-RSSI ペア 2 | 7 bytes | c20303003f00 ce | MAC: `C2:03:03:00:3F:00`,
RSSI: `0xCE` = -50 (int8) |
+| 25~31 | MAC-RSSI ペア 3 | 7 bytes | 588c81a0fbf2 cc | MAC: `58:8C:81:A0:FB:F2`,
RSSI: `0xCC` = -52 (int8) |
+| 32~38 | MAC-RSSI ペア 4 | 7 bytes | c20303003f03 cb | MAC: `C2:03:03:00:3F:03`,
RSSI: `0xCB` = -53 (int8) |
+| 39~45 | MAC-RSSI ペア 5 | 7 bytes | c30000564af2 c7 | MAC: `C3:00:00:56:4A:F2`,
RSSI: `0xC7` = -57 (int8) |
+
+### 加速度センサー付き位置情報ステータスパケット (0x31)
+
+位置情報ステータスパケットには、位置情報ステータスに加えて、加速度センサーデータ、イベントステータス、およびバッテリー情報が含まれます。フレーム ID は `0x31` で、全長は 15 バイトです。
+
+| 0x31 | Byte2 | Byte3~4 | Byte5~8 | Byte9~10 | Byte11~12 | Byte13~14 | Byte15 |
+| :--: | :---: | :-----: | :-----: | :------: | :-------: | :-------: | :---: |
+| ID | 位置情報ステータス | イベントステータス | UTC タイムスタンプ | 加速度センサー X | 加速度センサー Y | 加速度センサー Z | バッテリーレベル |
+
+**生ペイロード例**
+
+`31 00 0100 694b3db0 003a 039d fe84 62`
+
+| Byte | Value | Type | Raw Data | Description |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 31 | 31 はパケット ID です |
+| 2 | 位置情報ステータス | uint8 | 00 |`0x00`: 位置特定成功。
`0x01`: GNSS スキャンがタイムアウトしました。
`0x02`: Wi-Fi スキャンがタイムアウトしました。
`0x03`: Wi-Fi + GNSS スキャンがタイムアウトしました。
`0x04`: GNSS + Wi-Fi スキャンがタイムアウトしました。
`0x05`: Bluetooth スキャンがタイムアウトしました。
`0x06`: Bluetooth + Wi-Fi スキャンがタイムアウトしました。
`0x07`: Bluetooth + GNSS スキャンがタイムアウトしました。
`0x08`: Bluetooth + Wi-Fi + GNSS スキャンがタイムアウトしました。
`0x09`: Location Server が GNSS 位置情報の解析に失敗しました。
`0x0A`: Location Server が Wi-Fi 位置情報の解析に失敗しました。
`0x0B`: Location Server が Bluetooth 位置情報の解析に失敗しました。
`0x0C`: 精度が低いため位置情報の解析に失敗しました。
`0x0D`: 時刻同期に失敗しました。
`0x0E`: 古い Almanac が原因で失敗しました。
`0x0F`: GNSS + Bluetooth スキャンがタイムアウトしました。 |
+| 3~4 | イベントステータス | uint16 | 0000 |`0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント |
+| 5~8 | UTC タイムスタンプ | uint32 | 694B3DB0 | `0x694B3DB0` = 1766538672(DEC) 秒
UTC 時刻に変換:
2025-12-24 01:11:12 |
+| 9~10 | 加速度センサー X | int16 | 003a | `0x003A` = 58 mg |
+| 11~12 | 加速度センサー Y | int16 | 039d | `0x039D` = 925 mg |
+| 13~14 | 加速度センサー Z | int16 | fe84 | `0xFE84` = -380 mg |
+| 15 | バッテリーレベル | uint8 | 62 | `0x62` = 98% |
+
+### 位置情報ステータスパケット(加速度センサー Off, 0x32)
+
+位置情報ステータスパケットには、位置情報ステータスに加えて、イベントステータスとバッテリー情報が含まれます。フレーム ID は `0x32` で、全長は 9 バイトです。
+
+| 0x32 | Byte2 | Byte3~4 | Byte5~8 | Byte9 |
+| :--: | :---: | :-----: | :-----: | :---: |
+| ID | 位置情報ステータス | イベントステータス | UTC タイムスタンプ | バッテリーレベル |
+
+**生ペイロード例**
+
+`32 00 0100 694b3db0 62`
+
+| Byte | Value | Type | Raw Data | Description |
+| :---: | :--- | :---: | :---: | :--- |
+| 1 | フレーム ID | uint8 | 32 | 32 はパケット ID です |
+| 2 | 位置情報ステータス | uint8 | 00 |`0x00`: 位置特定成功。
`0x01`: GNSS スキャンがタイムアウトしました。
`0x02`: Wi-Fi スキャンがタイムアウトしました。
`0x03`: Wi-Fi + GNSS スキャンがタイムアウトしました。
`0x04`: GNSS + Wi-Fi スキャンがタイムアウトしました。
`0x05`: Bluetooth スキャンがタイムアウトしました。
`0x06`: Bluetooth + Wi-Fi スキャンがタイムアウトしました。
`0x07`: Bluetooth + GNSS スキャンがタイムアウトしました。
`0x08`: Bluetooth + Wi-Fi + GNSS スキャンがタイムアウトしました。
`0x09`: Location Server が GNSS 位置情報の解析に失敗しました。
`0x0A`: Location Server が Wi-Fi 位置情報の解析に失敗しました。
`0x0B`: Location Server が Bluetooth 位置情報の解析に失敗しました。
`0x0C`: 精度が低いため位置情報の解析に失敗しました。
`0x0D`: 時刻同期に失敗しました。
`0x0E`: 古い Almanac が原因で失敗しました。
`0x0F`: GNSS + Bluetooth スキャンがタイムアウトしました。 |
+| 3~4 | イベントステータス | uint16 | 0100 | `0x0000` = イベント未発生
Bit 0: false
Bit 1: 移動開始イベント
Bit 2: 移動終了イベント
Bit 3: 静止イベント
Bit 4: 衝撃イベント
Bit 5: 温度イベント
Bit 6: 光イベント
Bit 7: SOS イベント
Bit 8: 1 回押下イベント
Bit 9: 分解イベント
16 進数への変換:
`0x0001`: 移動開始イベント
`0x0002`: 移動終了イベント
`0x0004`: 静止イベント
`0x0008`: 衝撃イベント
`0x0010`: 温度イベント
`0x0020`: 光イベント
`0x0040`: SOS イベント
`0x0080`: 1 回押下イベント
`0x0100`: 分解イベント |
+| 5~8 | UTC タイムスタンプ | uint32 | 694B3DB0 | `0x694B3DB0` = 1766538672(DEC) 秒
UTC 時刻に変換:
2025-12-24 01:11:12 |
+| 9 | バッテリーレベル | uint8 | 62 | `0x62` = 98% |
+
+## ダウンリンクパケット, FPort=5
+
+トラッカーは LoRaWAN をサポートしており、いくつかのコマンドをダウンリンクしてパラメータを調整できます。デバイスが休止状態の場合、ダウンリンクコマンドは、デバイスが次回データをアップロードするために起床したときに有効になります。
+
+LoRaWAN Class A の仕様上、ダウンリンクウィンドウはアップリンク後にのみ開くため、コマンドはリアルタイムではありません。例えば、報告間隔が 10 分に設定されている場合、デバイスが次の送信ウィンドウでダウンリンクコマンドを受信するまでに最大 10 分かかる可能性があります。
+
+**注意: FPort=5**
+
+### デバイスステータス要求パケット (0x8F)
+
+|0x8F|
+| - |
+|ID|
+
+例:
+
+8F: 最新のデバイスステータスおよび位置情報パケットを要求します。
+
+### 動作モード & 位置情報戦略の設定 (0x90)
+
+|0x90|Byte2|Byte3|Byte4~5|Byte6~7|Byte8~9|
+| - | :- | :- | :- | :- | :- |
+|ID|動作モード|位置情報戦略|ハートビート間隔|周期モードアップリンク間隔|イベントモードアップリンク間隔|
+
+|Byte10|Byte11|Byte12|Byte13|Byte14|Byte15~30|
+| - | - | - | - | - | :- |
+|3 軸加速度センサー有効化|分解アラーム有効化|GNSS スキャンタイムアウト (S)|iBeacon スキャンタイムアウト (S)|UUID フィルタ有効バイト数|UUID フィルタ|
+
+注意:
+ハートビート間隔 / 周期モードアップリンク間隔 / イベントモードアップリンク間隔の単位:**分**
+
+例:
+
+`90 01 01 02d0 0014 0005 01 01 1e 0a 10 00000000000000000000000000000000`
+
+
+|**Byte**|**Value**|**Type**|**Raw Data**|**Description**|
+| - | - | - | - | - |
+|1|フレーム ID|uint8|90|90 はパケット ID です|
+|2|動作モード|uint8|01|01 = 周期モード
`00`: スタンバイモード
`01`: 周期モード
`02`: イベントモード|
+|3|位置情報戦略|uint8|01|`00`: GNSS のみ
`01`: Wi-Fi のみ
`02`: Wi-Fi + GNSS
`03`: GNSS + Wi-Fi
`04`: Bluetooth のみ
`05`: Bluetooth + Wi-Fi
`06`: Bluetooth + GNSS
`07`: Bluetooth + Wi-Fi + GNSS
`08`: GNSS + Bluetooth |
+|4~5|ハートビート間隔 | uint16 | 02d0 | `0x02D0` = 720 分|
+|6~7|周期モードアップリンク間隔|uint16|0014|`0x0014` = 20 分 |
+|8~9|イベントモードアップリンク間隔|uint16|0005|`0x0005` = 5 分
イベントが発生しない場合、データは 5 分ごとにアップロードされます。
|
+|10|3 軸加速度センサー有効化|uint8|01|`00`: 無効
`01`: 有効|
+|11|分解アラーム有効化|uint8|01|`00`: 無効
`01`: 有効|
+|12|GNSS スキャンタイムアウト|uint8|1E|`0x1E` = 30 秒 |
+|13|iBeacon スキャンタイムアウト|uint8|0A|`0x0A` = 10 秒 |
+|14|UUID フィルタ有効バイト数|uint8|10| UUID フィルタ内の有効バイト数 (0–16)|
+|15~30|UUID フィルタ| 16 bytes | 0000000000000000
0000000000000000 | 16 バイトの Bluetooth UUID フィルタ。先頭の N バイトのみ(byte30 で定義)が有効|
+
+
+### イベントモードしきい値の設定 (0x91)
+
+|0x91|Byte2|Byte3~4|Byte5~6|Byte7|Byte8~9|
+| - | :- | :- | :- | :- | :- |
+|ID|モーションイベントを有効化|3軸モーションしきい値|モーション時のアップリンク間隔|静止イベントを有効化|静止タイムアウト|
+
+|Byte10|Byte11~12|
+| - | :- |
+|ショックイベントを有効化|3軸ショックしきい値|
+
+
+例:
+
+`91 01 001e 0005 01 01 2c`
+
+|**Byte**|**値**|**型**|**生データ**|**説明**|
+| - | - | - | - | - |
+|1|フレーム ID|uint8|91|91 はパケット ID です|
+|2|モーションイベントを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|3~4|3軸モーションしきい値|uint16|001e|`0x001E` = 30 mg
加速度が 30 mg を超えると、デバイスは動作中であると判断します
|
+|5~6|モーション時のアップリンク間隔|uint16|0005|`0x0005` = 5 分
モーションが検出されると、報告間隔は 5 分になります
|
+|7|静止イベントを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|8~9|静止タイムアウト|uint16|012c|`0x012C` = 300 分
デバイスが 300 分以上静止したままの場合、静止イベントがトリガーされます
|
+|10|ショックイベントを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|11~12|3軸ショックしきい値|uint16|012c|`0x012C` = 300 mg
加速度が 300 mg を超えると、ショックイベントがトリガーされます
|
+
+### デバイスステータスパケットの要求 (0x92)
+
+|0x92|
+| - |
+|ID|
+
+例:
+
+92: GNSS 位置情報の取得を強制します。
+
+### 動作モード & 測位戦略 & イベントモードしきい値の設定 (0x97)
+
+|0x97|Byte2|Byte3|Byte4~5|Byte6~7|Byte8~9|
+| - | :- | :- | :- | :- | :- |
+|ID|動作モード|測位戦略|ハートビート間隔|周期モードアップリンク間隔|イベントモードアップリンク間隔|
+
+|Byte10|Byte11|Byte12|Byte13|Byte14|Byte15~30|
+| - | :- | :- | :- | :- | :- |
+|3軸加速度センサを有効化|分解アラームを有効化|GNSS スキャンタイムアウト|iBeacon スキャンタイムアウト|UUID フィルタ有効バイト数|UUID フィルタ|
+
+#### モーションイベント設定
+|Byte31|Byte32~33|Byte34~35|
+| - | :- | :- |
+|モーションイベントを有効化|3軸モーションしきい値|モーション時のアップリンク間隔|
+
+#### 静止イベント設定
+|Byte36|Byte37~38|
+| - | :- |
+|静止イベントを有効化|静止タイムアウト|
+
+
+#### ショックイベント設定
+|Byte39|Byte40~41|
+| - | :- |
+|ショックイベントを有効化|3軸ショックしきい値|
+
+例:
+
+`97 01 02 003c 001e 000a 01 01 0a 05 10 00000000000000000000000000000000 01 001e 0005 01 012c 01 012c`
+
+|**Byte**|**値**|**型**|**生データ**|**説明**|
+| - | - | - | - | - |
+|1|フレーム ID|uint8|97|97 はパケット ID です|
+|2|動作モード|uint8|01|`00`: スタンバイモード
`01`: 周期モード
`02`: イベントモード|
+|3|測位戦略|uint8|02|`00`: GNSS のみ
`01`: Wi-Fi のみ
`02`: Wi-Fi + GNSS
`03`: GNSS + Wi-Fi
`04`: Bluetooth のみ
`05`: Bluetooth + Wi-Fi
`06`: Bluetooth + GNSS
`07`: Bluetooth + Wi-Fi + GNSS
`08`: GNSS + Bluetooth |
+|4~5|ハートビート間隔|uint16|003c|`0x003C` = 60 秒|
+|6~7|周期モードアップリンク間隔|uint16|001e|`0x001E` = 30 秒|
+|8~9|イベントモードアップリンク間隔|uint16|000a|`0x000A` = 10 分
イベントがトリガーされない場合、データは 10 分ごとにアップロードされます。
|
+|10|3軸加速度センサを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|11|分解アラームを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|12|GNSS スキャンタイムアウト|uint8|0a|`0x0A` = 10 秒|
+|13|iBeacon スキャンタイムアウト|uint8|05|`0x05` = 5 秒|
+|14|UUID フィルタ有効バイト数|uint8|10|`0x10` = 16 バイト|
+|15~30|UUID フィルタ|byte[16]|0000000000000000
0000000000000000|UUID フィルタ値 (16 バイト)
|
+|31|モーションイベントを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|32~33|3軸モーションしきい値|uint16|001e|`0x001E` = 30 mg |
+|34~35|モーション時のアップリンク間隔|uint16|0005|`0x0005` = 5 分
モーションが検出されると、報告間隔は 5 分になります|
+|36|静止イベントを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|37~38|静止タイムアウト|uint16|012c|`0x012C` = 300 分 |
+|39|ショックイベントを有効化|uint8|01|`00`: 無効
`01`: 有効|
+|40~41|3軸ショックしきい値|uint16|012c|`0x012C` = 300 mg |
+
+## 技術サポート & 製品ディスカッション
+
+弊社製品をお選びいただきありがとうございます。弊社は、製品をできるだけスムーズにご利用いただけるよう、さまざまなサポートを提供しています。お好みやニーズに応じて選択いただける、複数のコミュニケーションチャネルをご用意しています。
+
+
+
+
\ No newline at end of file
diff --git a/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/ja_SenseCAP_T2000_intro.md b/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/ja_SenseCAP_T2000_intro.md
index e4e7a083c9429..edee83623a4eb 100644
--- a/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/ja_SenseCAP_T2000_intro.md
+++ b/sites/ja/docs/Sensor/SenseCAP/SenseCAP_T2000_Tracker/ja_SenseCAP_T2000_intro.md
@@ -2,31 +2,33 @@
description: SenseCAP T2000 トラッカー
title: SenseCAP T2000 トラッカー
keywords:
- - Tracker
+ - トラッカー
- SenseCAP
image: https://files.seeedstudio.com/wiki/wiki-platform/S-tempor.png
slug: /sensecap_t2000_tracker
last_update:
- date: 1/28/2026
+ date: 3/12/2026
author: Janet
-createdAt: '2025-12-01'
-updatedAt: '2026-03-03'
+createdAt: '2025-11-27'
+updatedAt: '2026-03-12'
url: https://wiki.seeedstudio.com/ja/sensecap_t2000_tracker/
---

-[**SenseCAP T2000 トラッカー**](https://www.seeedstudio.com/SenseCAP-Asset-Tracker-T2000-A-p-6580.html)は、産業グレードのLoRaWAN®アセットトラッカーで、GNSS、Bluetooth、Wi-Fi測位をサポートし、屋内外環境での信頼性の高い追跡を実現します。IP67保護、動作状態を検出する内蔵3軸加速度計、デバイスが取り外された場合に最優先アラームをトリガーするタンパー防止ボタンを備えています。T2000-AとT2000-Bは長時間のバッテリー動作をサポートし、充電式バッテリーを搭載したソーラー電源のT2000-Cは継続的な屋外使用を保証し、このシリーズを長期間のメンテナンスフリーなアセット追跡に最適にしています。
+[**SenseCAP T2000 Tracker**](https://www.seeedstudio.com/SenseCAP-Asset-Tracker-T2000-A-p-6580.html) は、産業グレードの LoRaWAN® アセットトラッカーであり、GNSS、Bluetooth、Wi-Fi 位置測位をサポートし、屋内外の環境において信頼性の高いトラッキングを実現します。IP67 保護等級、動作状態を検知する内蔵 3 軸加速度センサー、そしてデバイスが取り外された際に最優先アラームをトリガーするタンパー防止ボタンを備えています。T2000-A と T2000-B は長期間動作するバッテリー駆動に対応し、充電式バッテリーを備えたソーラー駆動の T2000-C は屋外での連続使用を可能にすることで、このシリーズを長期的かつメンテナンスフリーなアセットトラッキングに最適なものとしています。
SenseCAP T2000 トラッカーのカタログ
-### LoRaWAN®ネットワークサーバーとの統合
+### LoRaWAN® ネットワークサーバーとの統合
-## 技術サポート & 製品ディスカッション
+## 技術サポートと製品ディスカッション
-弊社製品をお選びいただき、ありがとうございます!弊社製品での体験が可能な限りスムーズになるよう、さまざまなサポートを提供いたします。異なる好みやニーズに対応するため、複数のコミュニケーションチャンネルを提供しています。
+弊社製品をお選びいただきありがとうございます。私たちは、お客様が製品をできるだけスムーズにご利用いただけるよう、さまざまなサポートを提供しています。お好みやニーズに応じてお選びいただける、複数のコミュニケーションチャネルをご用意しています。
-#### デコーダー
+#### デコーダ
-TTN(ChirpStack V4)向け
+TTN 用(ChirpStack V4)
```cpp
function decodeUplink (input) {
@@ -49,833 +49,6 @@ function decodeUplink (input) {
decoded.messages.push({fport: fport, payload: bytesString})
return { data: decoded }
}
- if (fport !== 5) {
- decoded.valid = false
- return { data: decoded }
- }
- 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)
- }
- }
- // decoded.messages = measurement
- 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 = []
-
- for (let i = 0; i < messageValue.length; i++) {
- let remainMessage = messageValue
- let dataId = remainMessage.substring(0, 2).toUpperCase()
- let dataValue
- let dataObj = {}
- let packageLen
- switch (dataId) {
- case '01':
- packageLen = 94
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '02':
- packageLen = 32
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '03':
- packageLen = 64
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '04':
- packageLen = 20
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '05':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '06':
- packageLen = 44
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '07':
- packageLen = 84
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '08':
- packageLen = 70
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '09':
- packageLen = 36
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0A':
- packageLen = 76
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0B':
- packageLen = 62
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0C':
- packageLen = 2
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- break
- case '0D':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0E':
- packageLen = getInt(remainMessage.substring(8, 10)) * 2 + 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, 8) + remainMessage.substring(10, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '0F':
- packageLen = 34
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '10':
- packageLen = 26
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- case '11':
- packageLen = 28
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
- dataObj = {
- 'dataId': dataId, 'dataValue': dataValue
- }
- break
- default:
- return frameArray
- }
- if (dataValue.length < 2) {
- break
- }
- frameArray.push(dataObj)
- }
- return frameArray
-}
-
-function deserialize (dataId, dataValue) {
- let measurementArray = []
- let eventList = []
- let measurement = {}
- let collectTime = 0
- let groupId = 0
- let shardFlag = {}
- let payload = ''
- let result = []
- let dataArr = []
- switch (dataId) {
- case '01':
- measurementArray = getUpShortInfo(dataValue)
- measurementArray.push(...getMotionSetting(dataValue.substring(30, 40)))
- measurementArray.push(...getStaticSetting(dataValue.substring(40, 46)))
- measurementArray.push(...getShockSetting(dataValue.substring(46, 52)))
- measurementArray.push(...getTempSetting(dataValue.substring(52, 72)))
- measurementArray.push(...getLightSetting(dataValue.substring(72, 92)))
- break
- case '02':
- measurementArray = getUpShortInfo(dataValue)
- break
- case '03':
- measurementArray.push(...getMotionSetting(dataValue.substring(0, 10)))
- measurementArray.push(...getStaticSetting(dataValue.substring(10, 16)))
- measurementArray.push(...getShockSetting(dataValue.substring(16, 22)))
- measurementArray.push(...getTempSetting(dataValue.substring(22, 42)))
- measurementArray.push(...getLightSetting(dataValue.substring(42, 62)))
- break
- case '04':
- let interval = 0
- let workMode = getInt(dataValue.substring(0, 2))
- let heartbeatInterval = getMinsByMin(dataValue.substring(4, 8))
- let periodicInterval = getMinsByMin(dataValue.substring(8, 12))
- let 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', type: 'Work Mode', measurementValue: workMode},
- {measurementId: '3942', type: 'Heartbeat Interval', measurementValue: heartbeatInterval},
- {measurementId: '3943', type: 'Periodic Interval', measurementValue: periodicInterval},
- {measurementId: '3944', type: 'Event Interval', measurementValue: eventInterval},
- {measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(dataValue.substring(16, 18))},
- {measurementId: '3900', type: 'Uplink Interval', measurementValue: interval}
- ]
- break;
- case '05':
- measurementArray = [
- {measurementId: '3000', type: 'Battery', measurementValue: getBattery(dataValue.substring(0, 2))},
- {measurementId: '3940', type: 'Work Mode', measurementValue: getWorkingMode(dataValue.substring(2, 4))},
- {measurementId: '3965', type: 'Positioning Strategy', measurementValue: getPositioningStrategy(dataValue.substring(4, 6))},
- {measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(dataValue.substring(6, 8))}
- ]
- break
- case '06':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}
- ]
- break
- case '07':
- eventList = getEventStatus(dataValue.substring(0, 6))
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(80, 82))}
- ]
- break
- case '08':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(66, 68))}
- ]
- break
- case '09':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(32, 34))}
- ]
- break
- case '0A':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(72, 74))}
- ]
- break
- case '0B':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(58, 60))},
- ]
- 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 '0E':
- shardFlag = getShardFlag(dataValue.substring(0, 2))
- groupId = getInt(dataValue.substring(2, 6))
- payload = dataValue.substring(6)
- measurement = {
- measurementId: '6152',
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'gnss-ng payload',
- measurementValue: payload
- }
- measurementArray.push(measurement)
- break
- case '0F':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- shardFlag = getShardFlag(dataValue.substring(26, 28))
- groupId = getInt(dataValue.substring(28, 32))
- measurementArray.push({
- measurementId: '4200',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Event Status',
- measurementValue: getEventStatus(dataValue.substring(0, 6))
- })
- measurementArray.push({
- measurementId: '4097',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
- })
- measurementArray.push({
- measurementId: '4199',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
- })
- measurementArray.push({
- measurementId: '3000',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
- })
- break
- case '10':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- shardFlag = getShardFlag(dataValue.substring(18, 20))
- groupId = getInt(dataValue.substring(20, 24))
- measurementArray.push({
- measurementId: '4200',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Event Status',
- measurementValue: getEventStatus(dataValue.substring(0, 6))
- })
- measurementArray.push({
- measurementId: '3000',
- timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
- groupId: groupId,
- index: shardFlag.index,
- count: shardFlag.count,
- type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(16, 18))
- })
- break
- case '11':
- collectTime = getUTCTimestamp(dataValue.substring(8, 16))
- measurementArray.push({
- measurementId: '3576',
- timestamp: collectTime,
- type: 'Positing Status',
- measurementValue: '' + getPositingStatus(dataValue.substring(0, 2))
- })
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '4200',
- type: 'Event Status',
- measurementValue: getEventStatus(dataValue.substring(2, 8))
- })
- if (!isNaN(parseFloat(getSensorValue(dataValue.substring(16, 20), 10)))) {
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '4097',
- type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
- })
- }
- if (!isNaN(parseFloat(getSensorValue(dataValue.substring(20, 24))))) {
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '4199',
- type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
- })
- }
- measurementArray.push({
- timestamp: collectTime,
- measurementId: '3000',
- type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
- })
- break
- }
- return measurementArray
-}
-
-function getMotionId (str) {
- return getInt(str)
-}
-
-function getPositingStatus (str) {
- return getInt(str)
-}
-
-function getUpShortInfo (messageValue) {
- return [
- {
- measurementId: '3000', type: 'Battery', measurementValue: getBattery(messageValue.substring(0, 2))
- }, {
- measurementId: '3502', type: 'Firmware Version', measurementValue: getSoftVersion(messageValue.substring(2, 6))
- }, {
- measurementId: '3001', type: 'Hardware Version', measurementValue: getHardVersion(messageValue.substring(6, 10))
- }, {
- measurementId: '3940', type: 'Work Mode', measurementValue: getWorkingMode(messageValue.substring(10, 12))
- }, {
- measurementId: '3965', type: 'Positioning Strategy', measurementValue: getPositioningStrategy(messageValue.substring(12, 14))
- }, {
- measurementId: '3942', type: 'Heartbeat Interval', measurementValue: getMinsByMin(messageValue.substring(14, 18))
- }, {
- measurementId: '3943', type: 'Periodic Interval', measurementValue: getMinsByMin(messageValue.substring(18, 22))
- }, {
- measurementId: '3944', type: 'Event Interval', measurementValue: getMinsByMin(messageValue.substring(22, 26))
- }, {
- measurementId: '3945', type: 'Sensor Enable', measurementValue: getInt(messageValue.substring(26, 28))
- }, {
- measurementId: '3941', type: 'SOS Mode', measurementValue: getSOSMode(messageValue.substring(28, 30))
- }
- ]
-}
-
-function getMotionSetting (str) {
- return [
- {measurementId: '3946', type: 'Motion Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3947', type: 'Any Motion Threshold', measurementValue: getSensorValue(str.substring(2, 6), 1)},
- {measurementId: '3948', type: 'Motion Start Interval', measurementValue: getMinsByMin(str.substring(6, 10))},
- ]
-}
-
-function getStaticSetting (str) {
- return [
- {measurementId: '3949', type: 'Static Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3950', type: 'Device Static Timeout', measurementValue: getMinsByMin(str.substring(2, 6))}
- ]
-}
-
-function getShockSetting (str) {
- return [
- {measurementId: '3951', type: 'Shock Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3952', type: 'Shock Threshold', measurementValue: getInt(str.substring(2, 6))}
- ]
-}
-
-function getTempSetting (str) {
- return [
- {measurementId: '3953', type: 'Temp Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3954', type: 'Event Temp Interval', measurementValue: getMinsByMin(str.substring(2, 6))},
- {measurementId: '3955', type: 'Event Temp Sample Interval', measurementValue: getSecondsByInt(str.substring(6, 10))},
- {measurementId: '3956', type: 'Temp ThMax', measurementValue: getSensorValue(str.substring(10, 14), 10)},
- {measurementId: '3957', type: 'Temp ThMin', measurementValue: getSensorValue(str.substring(14, 18), 10)},
- {measurementId: '3958', type: 'Temp Warning Type', measurementValue: getInt(str.substring(18, 20))}
- ]
-}
-
-function getLightSetting (str) {
- return [
- {measurementId: '3959', type: 'Light Enable', measurementValue: getInt(str.substring(0, 2))},
- {measurementId: '3960', type: 'Event Light Interval', measurementValue: getMinsByMin(str.substring(2, 6))},
- {measurementId: '3961', type: 'Event Light Sample Interval', measurementValue: getSecondsByInt(str.substring(6, 10))},
- {measurementId: '3962', type: 'Light ThMax', measurementValue: getSensorValue(str.substring(10, 14), 10)},
- {measurementId: '3963', type: 'Light ThMin', measurementValue: getSensorValue(str.substring(14, 18), 10)},
- {measurementId: '3964', type: 'Light Warning Type', measurementValue: getInt(str.substring(18, 20))}
- ]
-}
-
-function getShardFlag (str) {
- let bitStr = getByteArray(str)
- return {
- count: parseInt(bitStr.substring(0, 4), 2),
- index: parseInt(bitStr.substring(4), 2)
- }
-}
-
-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 getSecondsByInt (str) {
- return getInt(str)
-}
-
-function getMinsByMin (str) {
- return getInt(str)
-}
-
-function getSensorValue (str, dig) {
- if (str === '8000') {
- return null
- } else {
- 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 '-' + 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 getSOSMode (str) {
- return loraWANV2DataFormat(str)
-}
-
-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) {
- // return getInt(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()
- let event = []
- for (let i = 0; i < bitArr.length; i++) {
- if (bitArr[i] !== '1') {
- continue
- }
- switch (i){
- case 0:
- event.push({id:1, eventName:"Start moving event."})
- break
- case 1:
- event.push({id:2, eventName:"End movement event."})
- break
- case 2:
- event.push({id:3, eventName:"Motionless event."})
- break
- case 3:
- event.push({id:4, eventName:"Shock event."})
- break
- case 4:
- event.push({id:5, eventName:"Temperature event."})
- break
- case 5:
- event.push({id:6, eventName:"Light event."})
- break
- case 6:
- event.push({id:7, eventName:"SOS event."})
- break
- case 7:
- event.push({id:8, eventName:"Press once event."})
- break
- }
- }
- 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
-}
-```
-
-
-
-
-
-Helium 向け
-
-```cpp
-function Decoder (bytes, port) {
- const bytesString = bytes2HexString(bytes)
- const originMessage = bytesString.toLocaleUpperCase()
- const fport = parseInt(port)
- const decoded = {
- valid: true,
- err: 0,
- payload: bytesString,
- messages: []
- }
-
- if (fport === 199 || fport === 192) {
- decoded.messages.push({fport: fport, payload: bytesString})
- return { data: decoded }
- }
- if (fport !== 5) {
- decoded.valid = false
- return { data: decoded }
- }
-
let measurement = messageAnalyzed(originMessage)
if (measurement.length === 0) {
decoded.valid = false
@@ -899,7 +72,6 @@ function Decoder (bytes, port) {
decoded.messages.push(elements)
}
}
- // decoded.messages = measurement
return { data: decoded }
}
@@ -922,7 +94,6 @@ function messageAnalyzed (messageValue) {
function unpack (messageValue) {
let frameArray = []
-
for (let i = 0; i < messageValue.length; i++) {
let remainMessage = messageValue
let dataId = remainMessage.substring(0, 2).toUpperCase()
@@ -931,148 +102,93 @@ function unpack (messageValue) {
let packageLen
switch (dataId) {
case '01':
- packageLen = 94
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 94)
+ messageValue = remainMessage.substring(94)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '02':
- packageLen = 32
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 32)
+ messageValue = remainMessage.substring(32)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '03':
- packageLen = 64
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 64)
+ messageValue = remainMessage.substring(64)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '04':
- packageLen = 20
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 20)
+ messageValue = remainMessage.substring(20)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '05':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 10)
+ messageValue = remainMessage.substring(10)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '06':
- packageLen = 44
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 44)
+ messageValue = remainMessage.substring(44)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '07':
- packageLen = 84
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 84)
+ messageValue = remainMessage.substring(84)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '08':
- packageLen = 70
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 70)
+ messageValue = remainMessage.substring(70)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '09':
- packageLen = 36
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 36)
+ messageValue = remainMessage.substring(36)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0A':
- packageLen = 76
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 76)
+ messageValue = remainMessage.substring(76)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0B':
- packageLen = 62
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 62)
+ messageValue = remainMessage.substring(62)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0C':
- packageLen = 2
- if (remainMessage.length < packageLen) {
- return frameArray
- }
break
case '0D':
- packageLen = 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 10)
+ messageValue = remainMessage.substring(10)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '0E':
packageLen = getInt(remainMessage.substring(8, 10)) * 2 + 10
- if (remainMessage.length < packageLen) {
- return frameArray
- }
dataValue = remainMessage.substring(2, 8) + remainMessage.substring(10, packageLen)
messageValue = remainMessage.substring(packageLen)
dataObj = {
@@ -1080,34 +196,50 @@ function unpack (messageValue) {
}
break
case '0F':
- packageLen = 34
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 34)
+ messageValue = remainMessage.substring(34)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '10':
- packageLen = 26
- if (remainMessage.length < packageLen) {
- return frameArray
- }
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ dataValue = remainMessage.substring(2, 26)
+ messageValue = remainMessage.substring(26)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
break
case '11':
- packageLen = 28
- if (remainMessage.length < packageLen) {
- return frameArray
+ dataValue = remainMessage.substring(2, 28)
+ messageValue = remainMessage.substring(28)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
}
- dataValue = remainMessage.substring(2, packageLen)
- messageValue = remainMessage.substring(packageLen)
+ break
+ case '1A':
+ dataValue = remainMessage.substring(2, 56)
+ messageValue = remainMessage.substring(56)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
+ }
+ break
+ case '1B':
+ dataValue = remainMessage.substring(2, 96)
+ messageValue = remainMessage.substring(96)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
+ }
+ break
+ case '1C':
+ dataValue = remainMessage.substring(2, 82)
+ messageValue = remainMessage.substring(82)
+ dataObj = {
+ 'dataId': dataId, 'dataValue': dataValue
+ }
+ break
+ case '1D':
+ dataValue = remainMessage.substring(2, 40)
+ messageValue = remainMessage.substring(40)
dataObj = {
'dataId': dataId, 'dataValue': dataValue
}
@@ -1131,8 +263,7 @@ function deserialize (dataId, dataValue) {
let groupId = 0
let shardFlag = {}
let payload = ''
- let result = []
- let dataArr = []
+ let motionId = ''
switch (dataId) {
case '01':
measurementArray = getUpShortInfo(dataValue)
@@ -1188,59 +319,65 @@ function deserialize (dataId, dataValue) {
break
case '06':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '4197', timestamp: collectTime, motionId: motionId, type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
+ {measurementId: '4198', timestamp: collectTime, motionId: motionId, type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
+ {measurementId: '4097', timestamp: collectTime, motionId: motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId: motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(40, 42))}
]
break
case '07':
eventList = getEventStatus(dataValue.substring(0, 6))
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(80, 82))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5001', timestamp: collectTime, motionId: motionId, type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
+ {measurementId: '4097', timestamp: collectTime, motionId: motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId: motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(80, 82))}
]
break
case '08':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '4097', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
- {measurementId: '4199', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(66, 68))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5002', timestamp: collectTime, motionId: motionId, type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
+ {measurementId: '4097', timestamp: collectTime, motionId: motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId: motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(66, 68))}
]
break
case '09':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '4197', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
- {measurementId: '4198', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(32, 34))}
+ {measurementId: '4200', timestamp: collectTime, motionId: motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '4197', timestamp: collectTime, motionId: motionId, type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
+ {measurementId: '4198', timestamp: collectTime, motionId: motionId, type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
+ {measurementId: '3000', timestamp: collectTime, motionId: motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(32, 34))}
]
break
case '0A':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5001', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(72, 74))}
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5001', timestamp: collectTime, motionId, type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(72, 74))}
]
break
case '0B':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray = [
- {measurementId: '4200', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
- {measurementId: '5002', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
- {measurementId: '3000', timestamp: collectTime, motionId: getMotionId(dataValue.substring(6, 8)), type: 'Battery', measurementValue: getBattery(dataValue.substring(58, 60))},
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5002', timestamp: collectTime, motionId, type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(58, 60))},
]
break
case '0D':
@@ -1277,10 +414,11 @@ function deserialize (dataId, dataValue) {
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
shardFlag = getShardFlag(dataValue.substring(26, 28))
groupId = getInt(dataValue.substring(28, 32))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray.push({
measurementId: '4200',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
@@ -1290,42 +428,43 @@ function deserialize (dataId, dataValue) {
measurementArray.push({
measurementId: '4097',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
+ measurementValue: getSensorValue(dataValue.substring(16, 20), 10)
})
measurementArray.push({
measurementId: '4199',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
+ measurementValue: getSensorValue(dataValue.substring(20, 24))
})
measurementArray.push({
measurementId: '3000',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
+ measurementValue: getBattery(dataValue.substring(24, 26))
})
break
case '10':
collectTime = getUTCTimestamp(dataValue.substring(8, 16))
shardFlag = getShardFlag(dataValue.substring(18, 20))
groupId = getInt(dataValue.substring(20, 24))
+ motionId = getMotionId(dataValue.substring(6, 8))
measurementArray.push({
measurementId: '4200',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
@@ -1335,12 +474,12 @@ function deserialize (dataId, dataValue) {
measurementArray.push({
measurementId: '3000',
timestamp: collectTime,
- motionId: getMotionId(dataValue.substring(6, 8)),
+ motionId,
groupId: groupId,
index: shardFlag.index,
count: shardFlag.count,
type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(16, 18))
+ measurementValue: getBattery(dataValue.substring(16, 18))
})
break
case '11':
@@ -1348,8 +487,8 @@ function deserialize (dataId, dataValue) {
measurementArray.push({
measurementId: '3576',
timestamp: collectTime,
- type: 'Positing Status',
- measurementValue: '' + getPositingStatus(dataValue.substring(0, 2))
+ type: 'Positioning Status',
+ measurementValue: getPositingStatus(dataValue.substring(0, 2))
})
measurementArray.push({
timestamp: collectTime,
@@ -1362,7 +501,7 @@ function deserialize (dataId, dataValue) {
timestamp: collectTime,
measurementId: '4097',
type: 'Air Temperature',
- measurementValue: '' + getSensorValue(dataValue.substring(16, 20), 10)
+ measurementValue: getSensorValue(dataValue.substring(16, 20), 10)
})
}
if (!isNaN(parseFloat(getSensorValue(dataValue.substring(20, 24))))) {
@@ -1370,14 +509,112 @@ function deserialize (dataId, dataValue) {
timestamp: collectTime,
measurementId: '4199',
type: 'Light',
- measurementValue: '' + getSensorValue(dataValue.substring(20, 24))
+ measurementValue: getSensorValue(dataValue.substring(20, 24))
})
}
measurementArray.push({
timestamp: collectTime,
measurementId: '3000',
type: 'Battery',
- measurementValue: '' + getBattery(dataValue.substring(24, 26))
+ measurementValue: getBattery(dataValue.substring(24, 26))
+ })
+ break
+ case '1A':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
+ measurementArray = [
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '4197', timestamp: collectTime, motionId, type: 'Longitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(16, 24), 1000000))},
+ {measurementId: '4198', timestamp: collectTime, motionId, type: 'Latitude', measurementValue: parseFloat(getSensorValue(dataValue.substring(24, 32), 1000000))},
+ {measurementId: '4097', timestamp: collectTime, motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(32, 36), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(36, 40))},
+ {measurementId: '4210', timestamp: collectTime, motionId, type: 'AccelerometerX', measurementValue: getSensorValue(dataValue.substring(40, 44))},
+ {measurementId: '4211', timestamp: collectTime, motionId, type: 'AccelerometerY', measurementValue: getSensorValue(dataValue.substring(44, 48))},
+ {measurementId: '4212', timestamp: collectTime, motionId, type: 'AccelerometerZ', measurementValue: getSensorValue(dataValue.substring(48, 52))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(52, 54))},
+ ]
+ break
+ case '1B':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
+ measurementArray = [
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5001', timestamp: collectTime, motionId, type: 'Wi-Fi Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 72))},
+ {measurementId: '4097', timestamp: collectTime, motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(72, 76), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(76, 80))},
+ {measurementId: '4210', timestamp: collectTime, motionId, type: 'AccelerometerX', measurementValue: getSensorValue(dataValue.substring(80, 84))},
+ {measurementId: '4211', timestamp: collectTime, motionId, type: 'AccelerometerY', measurementValue: getSensorValue(dataValue.substring(84, 88))},
+ {measurementId: '4212', timestamp: collectTime, motionId, type: 'AccelerometerZ', measurementValue: getSensorValue(dataValue.substring(88, 92))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(92, 94))}
+ ]
+ break
+ case '1C':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ motionId = getMotionId(dataValue.substring(6, 8))
+ measurementArray = [
+ {measurementId: '4200', timestamp: collectTime, motionId, type: 'Event Status', measurementValue: getEventStatus(dataValue.substring(0, 6))},
+ {measurementId: '5002', timestamp: collectTime, motionId, type: 'BLE Scan', measurementValue: getMacAndRssiObj(dataValue.substring(16, 58))},
+ {measurementId: '4097', timestamp: collectTime, motionId, type: 'Air Temperature', measurementValue: getSensorValue(dataValue.substring(58, 62), 10)},
+ {measurementId: '4199', timestamp: collectTime, motionId, type: 'Light', measurementValue: getSensorValue(dataValue.substring(62, 66))},
+ {measurementId: '4210', timestamp: collectTime, motionId, type: 'AccelerometerX', measurementValue: getSensorValue(dataValue.substring(66, 70))},
+ {measurementId: '4211', timestamp: collectTime, motionId, type: 'AccelerometerY', measurementValue: getSensorValue(dataValue.substring(70, 74))},
+ {measurementId: '4212', timestamp: collectTime, motionId, type: 'AccelerometerZ', measurementValue: getSensorValue(dataValue.substring(74, 78))},
+ {measurementId: '3000', timestamp: collectTime, motionId, type: 'Battery', measurementValue: getBattery(dataValue.substring(78, 80))}
+ ]
+ break
+ case '1D':
+ collectTime = getUTCTimestamp(dataValue.substring(8, 16))
+ measurementArray.push({
+ measurementId: '3576',
+ timestamp: collectTime,
+ type: 'Positioning Status',
+ measurementValue: getPositingStatus(dataValue.substring(0, 2))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4200',
+ type: 'Event Status',
+ measurementValue: getEventStatus(dataValue.substring(2, 8))
+ })
+ if (!isNaN(parseFloat(getSensorValue(dataValue.substring(16, 20), 10)))) {
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4097',
+ type: 'Air Temperature',
+ measurementValue: getSensorValue(dataValue.substring(16, 20), 10)
+ })
+ }
+ if (!isNaN(parseFloat(getSensorValue(dataValue.substring(20, 24))))) {
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4199',
+ type: 'Light',
+ measurementValue: getSensorValue(dataValue.substring(20, 24))
+ })
+ }
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4210',
+ type: 'AccelerometerX',
+ measurementValue: getSensorValue(dataValue.substring(24, 28))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4211',
+ type: 'AccelerometerY',
+ measurementValue: getSensorValue(dataValue.substring(28, 32))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '4212',
+ type: 'AccelerometerZ',
+ measurementValue: getSensorValue(dataValue.substring(32, 36))
+ })
+ measurementArray.push({
+ timestamp: collectTime,
+ measurementId: '3000',
+ type: 'Battery',
+ measurementValue: getBattery(dataValue.substring(36, 38))
})
break
}
@@ -1389,6 +626,39 @@ function getMotionId (str) {
}
function getPositingStatus (str) {
+ let status = getInt(str)
+ switch (status) {
+ case 0:
+ return {id:status, statusName:"locate successful."}
+ case 1:
+ return {id:status, statusName:"The GNSS scan timed out."}
+ case 2:
+ return {id:status, statusName:"The Wi-Fi scan timed out."}
+ case 3:
+ return {id:status, statusName:"The Wi-Fi + GNSS scan timed out."}
+ case 4:
+ return {id:status, statusName:"The GNSS + Wi-Fi scan timed out."}
+ case 5:
+ return {id:status, statusName:"The Bluetooth scan timed out."}
+ case 6:
+ return {id:status, statusName:"The Bluetooth + Wi-Fi scan timed out."}
+ case 7:
+ return {id:status, statusName:"The Bluetooth + GNSS scan timed out."}
+ case 8:
+ return {id:status, statusName:"The Bluetooth + Wi-Fi + GNSS scan timed out."}
+ case 9:
+ return {id:status, statusName:"Location Server failed to parse the GNSS location."}
+ case 10:
+ return {id:status, statusName:"Location Server failed to parse the Wi-Fi location."}
+ case 11:
+ return {id:status, statusName:"Location Server failed to parse the Bluetooth location."}
+ case 12:
+ return {id:status, statusName:"Failed to parse location due to the poor accuracy."}
+ case 13:
+ return {id:status, statusName:"Time synchronization failed."}
+ case 14:
+ return {id:status, statusName:"Failed due to the old Almanac."}
+ }
return getInt(str)
}
@@ -1526,7 +796,7 @@ function loraWANV2DataFormat (str, divisor = 1) {
}
})
str2 = parseInt(reverseArr.join(''), 2) + 1
- return '-' + str2 / divisor
+ return parseFloat('-' + str2 / divisor)
}
return parseInt(str2, 2) / divisor
}
@@ -1603,7 +873,6 @@ function getInt (str) {
}
function getEventStatus (str) {
- // return getInt(str)
let bitStr = getByteArray(str)
let bitArr = []
for (let i = 0; i < bitStr.length; i++) {
@@ -1676,7 +945,7 @@ function loraWANV2PositiveDataFormat (str, divisor = 1) {
-ChirpStack(V3)の場合
+ChirpStack(V3)向け
```cpp
// Decode decodes an array of bytes into an object.
@@ -2779,7 +2048,7 @@ function loraWANV2PositiveDataFormat(str) {
-AWS向け
+AWS 向け
```cpp
const AWS = require('aws-sdk');
@@ -3336,9 +2605,9 @@ exports.handler = async (event) => {
### SenseCAP T2000 トラッカー
-#### デコーダー
+#### デコーダ
-[**SenseCAP T2000 トラッカー**](https://www.seeedstudio.com/SenseCAP-Asset-Tracker-T2000-A-p-6580.html)は、産業グレードのLoRaWAN®アセットトラッカーで、GNSS、Bluetooth、Wi-Fi測位をサポートし、屋内外環境での信頼性の高い追跡を実現します。IP67保護機能、動作状態を検出する内蔵3軸加速度計、デバイスが取り外された際に最優先アラームをトリガーする改ざん防止ボタンを備えています。T2000-AとT2000-Bは長時間のバッテリー動作をサポートし、充電式バッテリー付きソーラー電源のT2000-Cは継続的な屋外使用を保証し、このシリーズは長期間のメンテナンスフリーなアセット追跡に最適です。
+[**SenseCAP T2000 Tracker**](https://www.seeedstudio.com/SenseCAP-Asset-Tracker-T2000-A-p-6580.html) は、産業グレードの LoRaWAN® アセットトラッカーであり、GNSS、Bluetooth、Wi-Fi 位置情報をサポートし、屋内外の環境において信頼性の高いトラッキングを実現します。IP67 保護等級、動作状態を検知する内蔵 3 軸加速度センサ、取り外された場合に最優先アラームをトリガーするタンパー防止ボタンを備えています。T2000-A および T2000-B は長期間動作するバッテリ駆動をサポートし、充電式バッテリを備えたソーラ駆動の T2000-C は屋外での連続使用を可能にします。これにより、このシリーズは長期にわたるメンテナンスフリーのアセットトラッキングに最適です。

@@ -3351,7 +2620,7 @@ exports.handler = async (event) => {
-TTN(ChirpStack V4)向け
+TTN 用(ChirpStack V4)
```cpp
function decodeUplink (input) {
@@ -4063,7 +3332,7 @@ function loraWANV2PositiveDataFormat (str, divisor = 1) {
-Helium 向け
+Helium 用
```cpp
function Decoder (bytes, port) {
@@ -5527,11 +4796,11 @@ exports.handler = async (event) => {
```
-### Wio Tracker 1110 Dev Board
+### Wio Tracker 1110 開発ボード
-[Wio Tracker 1110 Dev Board](https://www.seeedstudio.com/Wio-Tracker-1110-Dev-Board-p-5799.html)は、[Wio-WM1110 Wireless Module](https://www.seeedstudio.com/Wio-WM1110-Module-LR1110-and-nRF52840-p-5676.html)をベースとし、[Semtech の LR1110](https://www.semtech.com/products/wireless-rf/lora-edge/lr1110) LoRa® トランシーバーと位置情報取得用の多目的無線フロントエンドを統合した、ユーザーフレンドリーな LoRa ベースのトラッキング開発プラットフォームです。
+[Wio Tracker 1110 Dev Board](https://www.seeedstudio.com/Wio-Tracker-1110-Dev-Board-p-5799.html) は、[Wio-WM1110 Wireless Module](https://www.seeedstudio.com/Wio-WM1110-Module-LR1110-and-nRF52840-p-5676.html) をベースとしており、[Semtech's LR1110](https://www.semtech.com/products/wireless-rf/lora-edge/lr1110) LoRa® トランシーバと測位用の多目的 RF フロントエンドを統合した、ユーザーフレンドリーな LoRa ベースのトラッキング開発プラットフォームです。
-コンパクトなサイズと豊富なインターフェースを備えた Wio Tracker 1110 Dev Board は、簡単な展開のためのオンボードアンテナを便利に装備しています。Arduino 開発環境と LoRaWAN プロトコルスタックをサポートし、トラッキング関連の IoT プロジェクトに最適です。
+コンパクトなサイズと豊富なインターフェースを備えた Wio Tracker 1110 Dev Board は、オンボードアンテナを搭載しており、容易に展開できます。Arduino 開発環境と LoRaWAN プロトコルスタックをサポートしているため、トラッキング関連の IoT プロジェクトに最適です。

@@ -5541,11 +4810,11 @@ exports.handler = async (event) => {
-#### デコーダー
+#### デコーダ