Данные датчика поступают в концентратор IoT Azure, а затем в веб-клиент с помощью SignalR на ASP.net Core 2.1. - PullRequest
0 голосов
/ 11 сентября 2018

Несмотря на все мои усилия, я не нашел учебных пособий о том, как передавать действующие данные датчиков через Azure IoT Hub в веб-клиент с помощью SignalR, где веб-сервер работает на ASP.net Core.Я как-то запускаю его, вот что я сделал, и пара вопросов.

Во-первых, использование Azure Iot Hub действительно здорово, поскольку я использую управление устройствами, а безопасность устройств и соединений проста.Данные будут поступать в Stream Analytics и функции Azure для дальнейшей обработки, но оперативные данные также доступны в концентраторе событий.

На стороне клиента мы используем установку Vue.js, подключаясь к работающему APIASP.net Core 2.1.SignalR использует службу Azure SignalR.Это описано в документах , и мой установочный код выглядит примерно так:

app.UseFileServer();
app.UseAzureSignalR(routes =>
{
    routes.MapHub<NotificationHub>("/notification");
});

Затем в моем хабе я могу использовать группы для обработки подписок, так как несколько клиентов могут подписаться нато же устройство:

public class NotificationHub : Hub
{
    public async Task Subscribe(string deviceId)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, deviceId);
    }
    public async Task UnSubscribe(string deviceId)
    {
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, deviceId);
    }
}

Контекст концентратора доступен для внедрения, поэтому псевдокод для контроллера, желающего использовать SignalR, будет выглядеть следующим образом:

public class MyController : Controller
{
    private readonly IHubContext<NotificationHub> _hubContext;

    public MyController(IHubContext<NotificationHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task<IActionResult> MyMethod()
    {
        ...
        await _hubContext.Clients.Group("a group").SendAsync("TheMessage", "The data");
        ...
    }
}

Пока что все кажется простым.

Затем я хотел реализовать прослушиватель для концентратора событий и запустить его в качестве фоновой задачи.Оказывается, что нам нужна только одна строка кода для регистрации размещенной службы в наших файлах Startup.cs:

services.AddHostedService<IoTEventHubService>();

IoTEventHubService будет наследоваться от BackgroundService, который найденв Microsoft.Extensions.Hosting:

public class IoTEventHubService : BackgroundService
{
    private readonly IHubContext<NotificationHub> _hubContext;

    public IoTEventHubService(IHubContext<NotificationHub> hubContext)
    {
        _hubContext = hubContext;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        ...defining the names and connection strings...

        var eventProcessorHost = new EventProcessorHost(
            eventProcessorHostName,
            _eventHubName,
            PartitionReceiver.DefaultConsumerGroupName,
            _eventHubConnectionString,
            _storageConnectionString,
            leaseName);

        var options = new EventProcessorOptions
        {
            InitialOffsetProvider = (partitionId) => 
                EventPosition.FromEnqueuedTime(DateTime.UtcNow)
        };

        // Registers the Event Processor Host and starts receiving messages
        await eventProcessorHost.RegisterEventProcessorFactoryAsync(
            new IoTEventProcessorFactory(_hubContext), options);
    }

Чтобы передать параметр, _hubContext, мне пришлось использовать фабричный метод для регистрации моего обработчика событий.Моя фабрика, IoTEventProcessorFactory, наследует от IEventProcessorFactory и передает контекст концентратора дальше обработчику событий в методе CreateEventProcessor,

public IEventProcessor CreateEventProcessor(PartitionContext context)
{
    return new IoTEventProcessor(_hubContext);
}

Класс IoTEventProcessor наследуется от IEventProcessor и обрабатывает сообщения следующим образомследующее:

public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
    foreach (var eventData in messages)
    {
        // De-serializing into a IoTMessage class
        var data = JsonConvert.DeserializeObject<IoTMessage>(
            Encoding.UTF8.GetString(eventData.Body.Array));

        // I can get the device id as defined in the IoT Hub
        data.DeviceId = eventData.SystemProperties.GetValueOrDefault(
            "iothub-connection-device-id").ToString();

        // And also the time for which the message was processed
        data.EventEnqueuedUtcTime = DateTime.Parse(
            eventData.SystemProperties.GetValueOrDefault("iothub-enqueuedtime").ToString());

      // Using the hub context, we can send live data to subscribers
      _hubContext.Clients.Group(data.DeviceId).SendAsync("LiveDataMessage", data);
    }

    return context.CheckpointAsync();
}

Это работает, и клиент получает живые данные, но правильно ли он реализован?Должен ли я разместить хост процессора событий где-нибудь?В моем Application Insights я вижу большое количество (> 1000 / час, когда не поступают данные с датчиков) зависимостей «сбоев» для подключения к IoT-концентратору, но статус False .Это просто говорит о том, что это не были какие-либо данные датчика ...?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...