Use el cubo de la familia MASA para construir una plataforma IoT desde cero (2) Registro de dispositivos

prefacio

No queremos que ningún dispositivo pueda acceder a nuestra plataforma IoT, por lo que el proceso de acceso normal de un dispositivo es el siguiente: 1. El software de la computadora host lee el código de identificación único UUID del dispositivo a través del puerto serie u otros métodos . . 2. La computadora host llama a la interfaz de fondo de IoT y envía UUID y ProductID . 3. La interfaz de fondo juzga si el dispositivo ha sido registrado. Si no, el Nombre del dispositivo y la Contraseña se generan de acuerdo con el ProductID y de acuerdo con ciertas reglas y se devuelven al software de la computadora host a través de la interfaz. 4. El software de la computadora superior escribe los datos devueltos por la interfaz en el dispositivo a través del puerto serial.

1. Proceso de registro del dispositivo

Aquí involucra principalmente cuatro conceptos 1. UUID (la identificación única del dispositivo, generalmente el número de la placa de control principal del dispositivo) 2. ProductID (la identificación del producto del dispositivo, definida en el fondo de IoT) 3. DeviceName (el nombre del dispositivo en la plataforma IoT o MQTT, la mayoría de los nombres están relacionados con el producto) 4. Contraseña (la contraseña para que el dispositivo se conecte a MQTT)

2. Registro MQTT

1. Agregar método de autenticación en EMQX

Seleccione el método de base de datos integrada y la base de datos integrada se utiliza para la autenticación de contraseña

Seleccione el nombre de usuario para el tipo de cuenta y mantenga el método de cifrado predeterminado y el método de adición de sal.

Después de hacer clic en Crear, puede ver el método de autenticación recién creado en el menú de autenticación y el estado es: conectado.

Hacemos clic en Administración de usuarios -> Agregar para crear usuarios manualmente

En el escenario aquí, usamos la computadora host para llamar al back-end de IoT, y la interfaz de IoT llama internamente a la interfaz EMQX para crear usuarios automáticamente

2. Crear clave API

Llamar a la interfaz requiere autenticación. Aquí usamos el método de clave Api. Creamos una clave API en Configuración del sistema -> Clave API

La clave secreta solo mostrará el texto sin formato cuando se cree, necesitamos registrar la clave API y la clave secreta

3. Llame a la interfaz para crear un usuario

Abrimos el RestAPI swagger de EMQX en el navegador

http://localhost:18083/api-docs/index.html

Podemos crear usuarios a través de esta interfaz. El ID del autenticador aquí es el ID de la base de datos integrada basada en contraseña que creamos anteriormente .

Este ID se obtiene a través del siguiente método de autenticación

Usamos directamente la clave API y la clave secreta en la autenticación, y la interfaz devuelve Id: basado en contraseña: base de datos incorporada

Llame a la interfaz Post de autenticación, ingrese: basado en contraseña: base de datos incorporada en el campo de identificación e ingrese la identificación de usuario y la contraseña del dispositivo en el cuerpo de la solicitud para crear un usuario con éxito.

También podemos ver el usuario recién creado en la interfaz de Deshboard

3. Conexión del equipo de prueba

Usamos MQTTX para simular que el dispositivo cliente se conecta a EMQX a través del protocolo mqtt, crea una nueva conexión, completa la dirección, el puerto y el nombre de usuario y la contraseña recién creados a través de la Api.

Haga clic en Conectar y descubra que el dispositivo puede conectarse a mqtt normalmente.

También puede ver información como el ID de cliente actualmente conectado en el panel.

4. Escribir código

Agregue el controlador DeviceController en el proyecto MASA.IoT.WebApi y agregue el método DeviceRegAsync para el registro del dispositivo. Si el dispositivo no ha sido registrado (la base de datos UUID no existe), el nombre del dispositivo se generará de acuerdo con el ProductCode y el El nombre será el número del proveedor del producto. Comienza con la hora y el número de secuencia. Luego agregue el dispositivo a EMQX y guárdelo en la base de datos al mismo tiempo. Si el dispositivo ya ha sido registrado, obtenga directamente la información de registro del dispositivo de la base de datos y devuélvala. La escritura del código es relativamente simple, por lo que no la repetiré aquí.

//DeviceController
namespace MASA.IoT.WebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class DeviceController : ControllerBase
    {
        private readonly IDeviceHandler _deviceHandler;

        public DeviceController(IDeviceHandler deviceHandler)
        {
            _deviceHandler = deviceHandler;
        }

        [HttpPost]

        public async Task<DeviceRegResponse> DeviceRegAsync(DeviceRegRequest request)
        {
            return await _deviceHandler.DeviceRegAsync(request);
        }
    }
}

//DeviceHandler
using MASA.IoT.WebApi.Contract;
using MASA.IoT.WebApi.IHandler;
using MASA.IoT.WebApi.Models.Models;
using Microsoft.EntityFrameworkCore;

namespace MASA.IoT.WebApi.Handler
{
    public class DeviceHandler : IDeviceHandler
    {
        private readonly MASAIoTContext _ioTDbContext;
        private readonly IMqttHandler _mqttHandler;

        public DeviceHandler(MASAIoTContext ioTDbContext, IMqttHandler mqttHandler)
        {
            _ioTDbContext = ioTDbContext;
            _mqttHandler = mqttHandler;
        }

        /// <summary>
        /// 注册设备
        /// </summary>
        /// <param name="request"></param>
        /// <returns>
        /// 设备注册信息
        /// </returns>
        public async Task<DeviceRegResponse> DeviceRegAsync(DeviceRegRequest request)
        {
            var productInfo =
                await _ioTDbContext.IoTProductInfo.FirstOrDefaultAsync(o => o.ProductCode == request.ProductCode);
            if (productInfo == null)
            {
                return new DeviceRegResponse
                {
                    Succeed = false,
                    ErrMsg = "ProductCode not found"
                };
            }
            var deviceRegInfo = await GetDeviceRegInfoAsync(request);
            if (deviceRegInfo != null) //已经注册过
            {
                return deviceRegInfo;
            }
            else //没有注册过
            {
                var deviceName = await GenerateDeviceNameAsync(productInfo.SupplyNo, request.ProductCode, request.UUID);
                var password = Guid.NewGuid().ToString("N");
                var addDeviceResponse = await _mqttHandler.DeviceRegAsync(deviceName, password);
                if (addDeviceResponse.user_id == deviceName) //注册成功
                {
                    deviceRegInfo = new DeviceRegResponse
                    {
                        DeviceName = deviceName,
                        Password = password,
                        Succeed = true,
                        ErrMsg = string.Empty
                    };
                    await _ioTDbContext.IoTDeviceInfo.AddAsync(new IoTDeviceInfo
                    {
                        Id = Guid.NewGuid(),
                        DeviceName = deviceName,
                        Password = password,
                        ProductInfoId = productInfo.Id,
                    });
                    await _ioTDbContext.SaveChangesAsync();
                    return deviceRegInfo;
                }

                return new DeviceRegResponse
                {
                    Succeed = false,
                    ErrMsg = addDeviceResponse.message
                };
            }
        }

        /// <summary>
        /// 获取设备注册信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns>
        /// 设备已经注册返回设备注册信息,没有注册过返回null
        /// </returns>
        private async Task<DeviceRegResponse?> GetDeviceRegInfoAsync(DeviceRegRequest request)
        {
            var deviceware = await _ioTDbContext.IoTDevicewares.FirstOrDefaultAsync(o => o.ProductCode == request.ProductCode && o.UUID == request.UUID);

            if (deviceware == null)
            {
                return null;
            }
            else
            {
                var deviceInfo = await _ioTDbContext.IoTDeviceInfo.FirstAsync(o => o.DeviceName == deviceware.DeviceName);

                return new DeviceRegResponse
                {
                    DeviceName = deviceInfo.DeviceName,
                    Password = deviceInfo.Password,
                    Succeed = true,
                    ErrMsg = string.Empty
                };
            }
        }

        /// <summary>
        /// 生成设备名称
        /// </summary>
        /// <param name="supplyNo"></param>
        /// <param name="productCode"></param>
        /// <param name="uuid"></param>
        /// <returns>
        /// 设备Mqtt名称
        /// </returns>
        private async Task<string> GenerateDeviceNameAsync(string supplyNo, string productCode, string uuid)
        {
            var lastDeviceware = await _ioTDbContext.IoTDevicewares.Where(o => o.ProductCode == productCode).OrderByDescending(o => o.CreationTime).FirstOrDefaultAsync();

            var newDeviceware = new IoTDevicewares
            {
                Id = Guid.NewGuid(),
                UUID = uuid,
                ProductCode = productCode,
                CreationTime = DateTime.Now
            };

            if (lastDeviceware != null && lastDeviceware.DeviceName.StartsWith(supplyNo + DateTime.Today.ToString("yyyyMMdd")))
            {
                newDeviceware.DeviceName = (long.Parse(lastDeviceware.DeviceName) + 1).ToString();
            }
            else
            {
                newDeviceware.DeviceName = supplyNo + DateTime.Today.ToString("yyyyMMdd") + "0001";
            }
            await _ioTDbContext.IoTDevicewares.AddAsync(newDeviceware);
            await _ioTDbContext.SaveChangesAsync();

            return newDeviceware.DeviceName;
        }
    }
}

Se utiliza un algoritmo simple para generar el nombre del dispositivo aquí.

// MqttHandler
using Flurl.Http;
using MASA.IoT.WebApi.Contract.Mqtt;
using MASA.IoT.WebApi.IHandler;
using Microsoft.Extensions.Options;
using System.Net;

namespace MASA.IoT.WebApi.Handler
{
    public class MqttHandler : IMqttHandler
    {
        private readonly AppSettings _appSettings;
        public MqttHandler(IOptions<AppSettings> settings)
        {
            _appSettings = settings.Value;
        }

        public async Task<AddDeviceResponse> DeviceRegAsync(string deviceName,string password)
        {
            var url = $"{_appSettings.MqttSetting.Url}/api/v5/authentication/password_based:built_in_database/users";
            var response = await url.WithBasicAuth(_appSettings.MqttSetting.ApiKey, _appSettings.MqttSetting.SecretKey).AllowAnyHttpStatus().PostJsonAsync(new AddDeviceRequest
            {
                user_id = deviceName,
                password = password,
            }
            );
            if (response.StatusCode is (int)HttpStatusCode.Created or (int)HttpStatusCode.BadRequest or (int)HttpStatusCode.NotFound)
            {
                return await response.GetJsonAsync<AddDeviceResponse>();
            }
            else
            {
                throw new UserFriendlyException(await response.GetStringAsync());
            }
        }
    }
}

Resumir

Lo anterior es el contenido de este artículo. Este artículo presenta el proceso de creación de un usuario en EMQX a través de la interfaz a través de la contraseña de la cuenta y la conexión a EMQX. Hay muchos otros métodos de reconocimiento de cuenta admitidos por EMQX. Por ejemplo, el método de autenticación JWT puede autorizar la autenticación de contraseña de un solo uso.Se puede controlar el período de validez de la certificación, que se explicará en la aplicación específica en los siguientes capítulos.

El código completo está aquí: https://github.com/sunday866/MASA.IoT-Training-Demos


Si está interesado en nuestro MASA, ya sea la contribución, el uso o la emisión del código, comuníquese con nosotros

WeChat:MasaStackTechOps

QQ:7424099

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/5447363/blog/8707487
Recomendado
Clasificación