MASAファミリーのバケットを使ってゼロからIoTプラットフォームを構築 (2) デバイスの登録

序文

どのデバイスも IoT プラットフォームにアクセスできないようにしたいので、デバイスの通常のアクセス プロセスは次のとおりです . 2. ホスト コンピューターが IoT バックグラウンド インターフェイスを呼び出し、UUIDProductIDを送信します。3. バックグラウンド インターフェイスは、デバイスが登録されているかどうかを判断し、登録されていない場合は、ProductIDと特定の規則に従ってDeviceNamePasswordを生成し、インターフェイスを介してホスト コンピュータ ソフトウェアに返します。4. 上位コンピュータ ソフトウェアは、インターフェイスから返されたデータをシリアル ポート経由でデバイスに書き込みます。

1. デバイス登録の流れ

ここには主に 4 つの概念が含まれます。 IoT プラットフォームまたは MQTT 上のデバイスの名前、ほとんどの名前は製品に関連しています) 4. パスワード (デバイスが MQTT に接続するためのパスワード)

2.MQTT登録

1. EMQX に認証方法を追加する

組み込みデータベース方式を選択すると、パスワード認証に組み込みデータベースが使用されます

アカウントの種類にユーザー名を選択し、デフォルトの暗号化方法とソルト追加方法をそのまま使用します。

[作成] をクリックすると、新しく作成された認証方法が認証メニューに表示され、ステータスは [接続済み] になります。

[ユーザー管理] -> [追加] をクリックして、ユーザーを手動で作成します

ここでのシナリオでは、ホスト コンピューターを使用して IoT バックエンドを呼び出し、IoT インターフェイスは内部で EMQX インターフェイスを呼び出してユーザーを自動的に作成します。

2.API キーの作成

インターフェイスの呼び出しには認証が必要です. ここでは Api キー メソッドを使用します. システム設定 -> API キーで API キーを作成します

シークレット キーは、作成時にプレーン テキストのみを表示します。API キーとシークレット キーを記録する必要があります。

3. インターフェイスを呼び出してユーザーを作成する

ブラウザでEMQXのRestAPI Swaggerを開きます

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

We can create users through this interface.ここでのAuthenticator ID は、上で作成した組み込みデータベース Password Basedの ID です。

この ID は、次の認証方法によって取得されます。

認証に API キーとシークレット キーを直接使用し、インターフェイスは Id: password_based:built_in_databaseを返します。

認証の Post インターフェースを呼び出し、id フィールドに password_based:built_in_database を入力し、要求本文にデバイスの user_id とパスワードを入力して、ユーザーを正常に作成します。

また、Deshboard インターフェイスで新しく作成されたユーザーを確認できます

3. 試験装置の接続

MQTTX を使用して、mqtt プロトコルを介して EMQX に接続するクライアント デバイスをシミュレートし、新しい接続を作成し、アドレス、ポート、および Api を介して作成したばかりのユーザー名とパスワードを入力します。

[接続] をクリックして、デバイスが mqtt に正常に接続できることを確認します。

ダッシュボードで現在接続されているクライアント ID などの情報を確認することもできます。

4.コードを書く

Add the DeviceController controller in the MASA.IoT.WebApi project and add the DeviceRegAsync method for device registration. デバイスが登録されていない (UUID データベースが存在しない) 場合、デバイス名は ProductCode に従って生成され、 name は製品サプライヤー番号になります。時間とシーケンス番号で始まります。次に、デバイスを EMQX に追加し、同時にデータベースに保存します。デバイスがすでに登録されている場合は、データベースからデバイスの登録情報を直接取得して返します。コードの書き方は比較的簡単なので、ここでは繰り返しません。

//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;
        }
    }
}

ここでは、単純なアルゴリズムを使用してデバイス名を生成します

// 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());
            }
        }
    }
}

要約する

以上がこの記事の内容です. この記事では, EMQX でユーザーを作成し, アカウントのパスワードを介してインターフェイスを介して EMQX に接続するプロセスを紹介します. EMQX でサポートされている他の多くのアカウント認識方法があります. たとえば, JWT 認証方法ワンタイム パスワード認証を許可することができます. 証明書の有効期間を制御することができます. これについては、次の章の特定のアプリケーションで説明します.

完全なコードはこちら: https://github.com/sunday866/MASA.IoT-Training-Demos


コードの寄稿、使用、発行など、MASA に関心をお持ちの場合は、お問い合わせください。

WeChat:MasaStackTechOps

QQ:7424099

{{o.name}}
{{m.name}}

おすすめ

転載: my.oschina.net/u/5447363/blog/8707487