This commit is contained in:
Sergio Pernas 2022-03-11 16:51:17 -03:00
parent 2be22e95ae
commit 8c4fe31648
1 changed files with 379 additions and 309 deletions

688
README.md
View File

@ -1,342 +1,360 @@
# Adquisidor
[TOC]
Protocolo de comunicaciones en serie inspirado en el protocolo **1-Wire** para el control de dispositivos adquisidores.
## Especificaciones
Se comparte un único bus de trasporte de tramas entre dispositivos:
- Un dispositivo controlador arbitra el uso y disposición del medio, ademas de enviar órdenes a los dispositivos adquisidores y recibir respuestas.
- Los dispositivos adquisidores vuelcan tramas al medio como respuesta a peticiones del controlador. Estos dispositivos nunca deben ocupar el bus de forma arbitraria.
## Enlace de datos
### Interfaz física
El transporte de datos se realiza por un medio compartido, un único bus conectado a las interfaces Tx y Rx de todos los dispisitivos.
# Registrador de datos 'nodemecu'
![](/home/sergio/BarraDEV/Proyectos/Plataforma de monitoreo/Adquisidor/README.img/image 01.png)
El registrador de datos 'nodemecu' es un programa que se encarga de:
- Tomar datos de los sensores asociados a los arduinos.
- Enviar los datos a un servidor para su presentación.
### Protocolo de solicutd y respuesta (PESR)
## Instalación
La comunicación entre dispositivos es por envío y recepción de dos tipos de tramas bajo un protocolo común:
### Requisitos
- Solicitud (Controlador).
- Respuesta (Adquisidor).
Las tramas se componen de 18 bytes:
- Prefijo de sincronización (2 bytes).
- Cabecera (5 bytes).
- Payload (10 bytes).
- Fin de trama (1 byte).
**Nota:** Si bien se contabilizan los bytes de sincronización, estos no son parte de la trama en si mismos.
Las tramas poseen campos comunes para todas las operaciones y dispositivos: prefijo, cabecera y fin de trama. Quedando el campo payload para la estructura de datos y los datos.
#### Estructura de trama genérica
| Campo | Tipo de dato | Valor | Dato | Descripción |
| ----- | ------------ | ----- | --------- | ------------------------------------------------------------ |
| | | | | **PREFIJO** |
| 0 | BYTE | 0xAA | Prefijo 1 | Inicio de sincronización. |
| 1 | BYTE | 0xCC | Prefijo 2 | Fin de sincronización. |
| | | | | **CABECERA** |
| 0 | BYTE | | DevID | Id del dispositivo **al que** consulta/responde.<br>Para el controlador siempre es 0x00 (ver **IDs de dispositivos**). |
| 1 | BYTE | | SrcID | Id del dispositivo **que** consulta/responde.<br/>Para el controlador siempre es 0x00 (ver **IDs de dispositivos**). |
| 2 | BYTE | | ReqID | Número de pedido. |
| 3 | BYTE | | Cmd | Número de comando (ver **Tabla de comandos**). |
| 4 | BYTE | | CodErr | Código de error (ver **Error codes**) |
| | | | | **PAYLOAD** |
| 5 | | | Gap[0] | Datos que se tranportan. En caso de campos vacios<br>o de valor *null* se completa con 0x00. |
| ... | | | Gap[..] | |
| 14 | | | Gap[9] | Datos que se tranportan. En caso de campos vacios<br/>o de valor *null* se completa con 0x00. |
| | | | | **FIN TRAMA** |
| 15 | BYTE | | Cks | Campo de verificación de trama por suma simple. |
- Raspberry (cualquier versión).
- Sistema operativo 'Raspberry Pi OS Lite.
- Instalador 'Raspberry Pi Imager'
- Una tarjeta MicroSD Clase 10 de al menos 4GB.
## Ciclo de control y respuesta
### Instalación del sistema operativo
El sistema se compone por un dispositivo *controlador* cuya ID de dispositivo siempre es `0x00`, los dispositivos *adquisidores* deben tener una ID de dispositivo única e irrepetible.
**Paso 1**
El controlador recorre de forma cíclica los adquisidores solicitando los datos asociados a los sensores.
Descargar la ultima versión de 'Raspberry Pi OS Lite':
### Asignación de ID
https://www.raspberrypi.com/software/operating-systems/
Todo el sistema se completa como un array de adquisidores, donde el puerto de conexión determina la ID de dispositivo.
**Paso 2**
| Salida digital Controlador | Adquisidor | ID |
| -------------------------- | ---------- | ---- |
| DO1 | 1 | 0x01 |
| DO2 | 2 | 0x02 |
| DO3 | 3 | 0x03 |
| DO4 | 4 | 0x04 |
Descargar el instalador 'Raspberry Pi Imager':
El adquisidor recibe (según la salida digital del controlador) una ID que siempre es la misma para el mismo puerto, al intercambiar los adquisidores de puerto se asume un cambio de ID para el adquisidor.
https://downloads.raspberrypi.org/imager/imager_latest.exe
### Adquisidores
**Paso 3**
Los adquisidores pueden manejar varios sensores, en muchos casos un mismo integrado puede censar múltiples variables, como por ejemplo presión y temperatura. Por lo tanto cada adquisidor al ser consultado va a responder tantas veces como sensores tenga.
Insertar la tarjeta MicroSD en la computadora.
**Paso 4**
Abrir 'Raspberry Pi Imager':
- **CHOOSE OS**: Seleccionar la imagen 'Raspberry Pi OS Lite' descargada el paso 1.
- **CHOOSE STORAGE**: Seleccionar la tarjeta MicroSD.
- **WRITE**: Comienza a grabar el sistema operativo en la tarjeta.
**Paso 5**
Una vez que finaliza la grabación extraer la tarjeta MicroSD y colocarla en la Raspberry.
### Instalación de 'nodemecu'
**Paso 1**
Abra una terminal e instale 'git'.
```
// Dispositivo adquisidor
int STOTAL=4; // Total de sensores
float SEN01; //Información devuelta por el sensor
float SEN02;
float SEN03;
float SEN04;
byte STYPE01; // Tipo, ej. Temperatura
byte STYPE02;
byte STYPE03;
byte STYPE04;
$ sudo apt update && apt install git
```
Ver tabla de **tipos de sensores**.
**Paso 2**
### Solicitud de sensores
1. El controlador envía una **trama de solicitud** con el comando **CON** (ver **tabla de comandos**) y una **ID de dispositivo**.
2. El adquisidor recibe la petición y responde con un comando **ACK**.
3. El controlador responde el **ACK** con un comando **GET**.
4. El adquisidor envía una trama por cada sensor según la **trama de respuesta** con la siguiente información:
- Comando de respuesta **ACK**.
- Total de sensores.
- Valor recogido por el sensor.
- Tipo de sensor.
- Código de error **0x00**.
5. El adquisidor responde con un comando **FIN** con el último envío de datos, entonces el controlador continua con el siguiente adquisidor.
### Manejo de errores
- Cuando el adquisidor no esta listo para recoger datos de los sensores responde con un **FIN** y un código de error **0x01**. El controlador continúa con el siguiente adquisidor.
- Cuando el adquisidor detecta fallos en un sensor o no recibe datos de éste, se responde con un **ACK** , un código de error **0x02** y un valor **ZERO** de recogida para dicho sensor.
### Tiempos de espera
- El controlador espera un máximo de 500 milisegundos antes de pasar al siguiente adquisidor.
## Máquina de estados
### Adquisidor
El adquisidor funciona de forma independiente del controlador en relación a los métodos de medición y las operaciones automatizadas asociadas a dicho proceso de medición: El controlador solicita datos, el adquisidor los provee.
Es importante tener en cuenta que el rol del controlador **no** es realizar mediciones, ni automatizar procesos.
Por lo tanto, el adquisidor se cimienta bajo la estructura lógica de una máquina de estados transductora. Este modelo permite definir un esquema de estados de forma genérica:
- Recepción de datos.
- Procesamiento de datos.
- Ejecución de tareas
- Salida de datos
La máquina de estados deja la libre incorporación de funciones y sub programas que son ejecutados en el estado deseado según la información recibida bajo el protocolo de comunicación PSR.
## Tramas
### Trama de solicitud
Es la trama enviada por el controlador, se establece el comando y se espera respuesta.
| Campo | Tipo de dato | Valor | Dato | Descripción |
| ----- | ------------ | ----- | ------- | ------------------------------------------------------------ |
| 0 | BYTE | | DstID | Id del dispositivo **al que** consulta/responde.<br>Para el controlador siempre es 0x00 (ver **IDs de dispositivos**). |
| 1 | BYTE | 0x00 | SrcID | Id del dispositivo **que** consulta/responde.<br/>Para el controlador siempre es 0x00 (ver **IDs de dispositivos**). |
| 2 | BYTE | | ReqID | Número de pedido. |
| 3 | BYTE | | Cmd | Número de comando (ver **Tabla de comandos**). |
| 4 | BYTE | | CodErr | Código de error (ver **Error codes**) |
| 5 | | | Gap[0] | Datos que se tranportan. En caso de campos vacios<br>o de valor *null* se completa con 0x00. |
| ... | | | Gap[..] | |
| 14 | | | Gap[9] | Datos que se tranportan. En caso de campos vacios<br/>o de valor *null* se completa con 0x00. |
| 15 | BYTE | | Cks | Campo de verificación de trama por suma simple. |
### Trama de respuesta
| Campo | Tipo de dato | Valor | Dato | Descripción |
| ----- | ------------ | ----- | ------- | ------------------------------------------------------------ |
| 0 | BYTE | | DevID | Id del dispositivo **al que** consulta/responde.<br>Para el controlador siempre es 0x00 (ver **IDs de dispositivos**). |
| 1 | BYTE | 0x00 | SrcID | Id del dispositivo **que** consulta/responde.<br/>Para el controlador siempre es 0x00 (ver **IDs de dispositivos**). |
| 2 | BYTE | | TranID | Identificador de transacción. |
| 3 | BYTE | | Cmd | Número de comando (ver **Tabla de comandos**). |
| 4 | BYTE | | CodErr | Código de error (ver **Error codes**). |
| 5 | BYTE | | Stotal | Cantidad de sensores. |
| 6 | BYTE | | Snum | Numero de sensor con el que contesta. |
| 7 | BYTE | | Stype | Tipo de sensor. |
| 8~11 | BYTE | | Value | Valor recogido por el sensor (punto flotante). |
| ... | | | Gap[..] | |
| 14 | | | Gap[3] | Datos que se tranportan. En caso de campos vacios<br/>o de valor *null* se completa con 0x00. |
| 15 | BYTE | | Cks | Campo de verificación de trama por suma simple. |
## Tablas
### Tabla de comandos
| Comando | Decimal | Hexadecimal | Descripción |
| ------- | ------- | ----------- | ------------------------------------------------------------ |
| CON | 170 | 0xAA | Evalúa si hay un dispositivo conectado. |
| ACK | 171 | 0xAB | Como respuesta a un `CON`, se evalúa disponibilidad del dispositivo. |
| GET | 172 | 0xAC | Solicitud de entrega de datos al adquisidor. |
| POST | 173 | 0xAD | Envío de datos al adquisidor. |
| RESET | 174 | 0xAE | Reinicio de adquisidor. |
| FIN | 175 | 0xAF | Fin de entrega de datos. |
| | | | **RESERVADOS** |
| | | | **COMANDOS NO DEFINIDOS** |
| | 190~200 | | Comandos personalizados. |
### Códigos de error
| Código | Decimal | Hexadecimal | Descripción |
| ------- | ------- | ----------- | ------------------------------------------------ |
| Success | 0 | 0x00 | Nada que informar. |
| Espera | 1 | 0x01 | El dispositivo no esta listo para enviar datos. |
| Fallo | 2 | 0x02 | No se puede acceder a la información del sensor. |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
#### Tabla de sensores
| Código | Sensor | |
| ------ | -------------------------- | ---- |
| 0x01 | Temperatura en cetígrados. | |
| 0x02 | Humedad relativa. | |
| 0x03 | Presión. | |
| | | |
## Esquemas de conexión
### Controlador
Raspberry PI 4 GPIO pin out.
| Pin | Tipo | Descripción |
| ---- | ------- | ------------------------------- |
| 4 | Vin 5V | Alimentación. |
| 6 | GND | Retorno alimentación. |
| 8 | UART TX | Bus de datos compartido con RX. |
| 10 | UART RX | Bus de datos compartido con TX. |
| 12 | GPIO18 | Asignador de ID 0x01 |
| 16 | GPIO23 | Asignador de ID 0x02 |
| 18 | GPIO24 | Asignador de ID 0x03 |
| 22 | GPIO25 | Asignador de ID 0x04 |
![](/home/sergio/BarraDEV/Proyectos/Controlador adquisidor/README.img/esquema-pines-gpio.png)
### Adquisidor
Arduino nano v2.3
| Pin | Tipo | Descripción |
| ---- | ------- | ------------------------------- |
| 1 | UART TX | Bus de datos compartido con RX. |
| 2 | UART RX | Bus de datos compartido con TX. |
| 5 | D2 | Receptor ID |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
## API
### JSON
Clonar el repositorio 'nodemecu'.
```
{
"transaction_uuid" : "",
"controller_id": "id raspberry";
"timestamp" : "terminadas todas las lecturas",
"error_code" : "value",
"coordinates" : {
"lat": 1,
"lng": 1
},
"battery_status" : "value",
"sample": "si hay muestra para retirar",
"storage": "uso del almacenamiento",
"arduinos": [
{
"id": 1,
"sensores": [
{
"timestamp": 20211017,
"type": "temperatura",
"value": 30,
"unit": "C",
"error": 200
},
{
"timestamp": 20211017,
"type": "humedad",
"value": 100,
"unit": "%"
},
{
"timestamp": 20211017,
"type": "presion",
"value": 70,
"unit": "Hpa"
}
]
},
{
"id": 2,
"sensores": []
}
]
}
$ git clone https://gitea.nulo.in/Nodemecu/nodemecu.git
```
### URL
Resultado.
```
https://ectomobile.sutty.nl/transactions
Clonando en 'nodemecu'...
remote: Enumerating objects: 179, done.
remote: Counting objects: 100% (179/179), done.
remote: Compressing objects: 100% (176/176), done.
remote: Total 179 (delta 97), reused 0 (delta 0), pack-reused 0
Recibiendo objetos: 100% (179/179), 394.81 KiB | 933.00 KiB/s, listo.
Resolviendo deltas: 100% (97/97), listo.
```
**Paso 3**
Ingresar al directorio 'nodemecu'.
```
$ cd nodemecu
```
Lanzar script de instalación.
```
$ sudo ./instalador
```
Resultado.
```
...
Created symlink /etc/systemd/system/multi-user.target.wants/nodemecu.service → /lib/systemd/system/nodemecu.service.
4. Configurar
- Ejecute 'sudo nodemecu configurar' para comenzar.
-Ejecute 'sudo nodemecu modo sensores' para obtener datos desde sensores.
- Ejecute 'sudo nodemecu captura iniciar' para comenzar a tomar datos de sensores o datos de prueba.
- Ejecute 'sudo systemctl start nodemecu.service' para iniciar el envío de datos.
```
### Configurar dispositivo
El 'CLI' es la interfaz de comandos para administrar 'nodemecu', debemos utilizarla para los primeros pasos luego de la instalación del programa:
- Determinar el nombre del dispositivo.
- Determinar la URL del servidor donde se enviarán los datos.
- Intervalo de toma de mediciones.
**Paso 1: Configuración**
Ejecute el asistente de configuración y complete las preguntas.
```
$ sudo nodemecu configurar
```
Resultado.
```
Complete los cambios a continuación:
Nombre del dispositivo.
nombre: calle falsa 123
nombre: calle_falsa_123
Servidor de entrega de datos.
servidor (ej. https://url.del/servidor): https://servidor.de.envio
Servidor https://servidor.de.envio
Intervalo de toma de muestras, entre 1 y 60 minutos.
intervalo: 5
Intervalo seteado en 5
Creando juego de llaves
Generating public/private ecdsa key pair.
Your identification has been saved in /opt/nodemecu/llaves/calle_falsa_123.pem.
Your public key has been saved in /opt/nodemecu/llaves/calle_falsa_123.pem.pub.
The key fingerprint is:
SHA256:7ZSKlfxybO/ssa63EeGVRDzMjcNKCOI4Kfx++V7o9vg root@raspberrypi
The key's randomart image is:
+---[ECDSA 256]---+
| . .. . *oo |
| . + . . ..O..|
| o + . ...oo |
| o . . o o.o |
| . S + o |
| . + B . |
| . + + B o |
| . o.* o.+ |
| o=oE*O. |
+----[SHA256]-----+
El modo de operación por defecto es 'test' y se envían datos simulados, cambie a 'sensores' con el comando 'sudo nodemecu modo sensores'
```
**Paso 2: Modo de operación**
Determine si los datos a registrar son simulados u obtenidos de sensores físicos, 'nodemecu' por defecto esta configurado para trabajar con datos simulados, si lo prefiere así entonces salte este paso, de lo contrario cambie el modo de operación.
Cambio de modo de operación.
```
$ sudo nodemecu modo sensores
```
**Paso 3: Captura o toma de datos**
Al ser instalado 'nodemecu' no realiza ningún tipo de captura de datos, para ello debe activar la captura.
Activar captura.
```
$ sudo nodemecu captura iniciar
```
Resultado.
```
Iniciando la captura de datos en modo 'sensores'
Desea continuar? Presione 'enter' para continuar o 'ctrl-c' para cancelar...
Se tomarán datos cada 5 minutos.
```
**Paso 4: Envío de datos**
Nodemecu utiliza el administrador de servicios 'systemd' para gestionar el programa que se encarga de enviar al servidor los datos registrados, se debe activar e iniciar el servicio para comience el envío de datos.
Activar servicio con el arranque del sistema, si no realiza este paso deberá hacer el inicio manual cada vez que se arranque el sistema.
```
$ sudo systemctl enable nodemecu.service
```
Resultado.
```
Created symlink /etc/systemd/system/multi-user.target.wants/nodemecu.service → /lib/systemd/system/nodemecu.service.
```
Iniciar el envío de datos.
```
$ sudo systemctl start nodemecu.service
```
Ver estado del servicio.
```
$ sudo systemctl status nodemecu.service
```
Resultado (se sale con 'q').
```
● nodemecu.service - Procesador de pila y transmisor de datos Nodemecu.
Loaded: loaded (/lib/systemd/system/nodemecu.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2022-03-11 16:25:57 -03; 39s ago
Main PID: 18283 (registrador)
Tasks: 2 (limit: 2181)
CGroup: /system.slice/nodemecu.service
├─18283 /bin/bash /opt/nodemecu/registrador
└─18567 ping -c 1 fsf.org
...
```
## Comandos nodemecu
Lista de comandos de ' nodemecu CLI'
#### Establecer o cambiar nombre del dispositivo.
Establece o cambia el nombre definido para el dispositivo, se recomienda usar solo caracteres alfanuméricos y sin espacios.
```
$ sudo nodemecu nombre nombre_del_dispositivo
```
#### Servidor de entrega de datos
Establece o modifica el servidor de entrega de datos.
```
$ sudo nodemecu servidor https://url_o_ip_del.servidor
```
#### Modo de operación
Cambia al modo de operación con respecto a la captura de datos:
- 'test' genera y registra datos simulados.
- 'sensores' toma datos realoes de los sensores.
Para generar datos simulados.
```
$ sudo nodemecu modo test
```
Para tomar datos de sensores.
```
$ sudo nodemecu modo sensores
```
#### Toma de datos
Permite detener la toma o captura de datos ya sean simulados o de sensores.
Para iniciar la captura.
```
$ sudo nodemecu captura iniciar
```
Para detener la captura
```
$ sudo nodemecu captura detener
```
#### Intervalo de toma de datos
Cada cuanto tiempo se toman datos, sean simulados o de sensores. Indique en minutos (1~60).
Configurar intervalo, en el ejemplo se configura para que tome datos cada 1 minuto.
```
$ sudo nodemecu intervalo 1
```
#### Llaves
Cada registro va firmado para validar la autenticidad y que no haya sido modificado el envío al servidor, para ello se utilizan llaves digitales, la creación de estas llaves esta automatizada cuando se ejecuta el comando `$ sudo nodemecu configurar `. Puede generar en cualquier momento una nueva llave, se recomienda esta acción si modifica el nombre del dispositivo.
Generación de llave.
```
$ sudo nodemecu cllave
```
#### Envío de datos
El envío de datos es una operación separada de la captura, el segundo toma datos y los guarda en el dispositivo, el primero envía esos datos a un servidor para procesar y mostrar la información.
Iniciar el envío de datos.
```
$ sudo systemctl start nodemecu.service
```
Detener el envío de datos.
```
$ sudo systemctl stop nodemecu.service
```
Activar el envío de datos con el arranque del sistema.
```
$ sudo systemctl enable nodemecu.service
```
Desactivar el envío de datos con el arranque del sistema.
```
$ sudo systemctl disable nodemecu.service
```
Ver el estado del servicio de envío de datos.
```
$ sudo systemctl status nodemecu.service
```
@ -345,3 +363,55 @@ https://ectomobile.sutty.nl/transactions