Несмотря на все мои усилия, я не нашел учебных пособий о том, как передавать действующие данные датчиков через 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 .Это просто говорит о том, что это не были какие-либо данные датчика ...?