This post builds on my Smartish Edge Camera – Azure IoT Image-Upload post adding two Direct Methods for Starting and Stopping the image capture and processing timer. The AzureMLMetSmartEdgeCamera supports both Azure IoT Hub and Azure IoT Central connectivity.
BEWARE – The Direct Method names are case sensitive which regularly trips me up when I use Azure IoT Explorer. If the Direct Method name is unknown a default handler is called, the issue logged and a Hyper Text Transfer Protocol(HTTP) Not Implemented(501) error returned
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Azure IoT Smart Edge Camera Service starting");
try
{
#if AZURE_IOT_HUB_CONNECTION
_deviceClient = await AzureIoTHubConnection();
#endif
#if AZURE_IOT_HUB_DPS_CONNECTION
_deviceClient = await AzureIoTHubDpsConnection();
#endif
...
_logger.LogTrace("YoloV5 model setup start");
_scorer = new YoloScorer<YoloCocoP5Model>(_applicationSettings.YoloV5ModelPath);
_logger.LogTrace("YoloV5 model setup done");
_ImageUpdatetimer = new Timer(ImageUpdateTimerCallback, null, _applicationSettings.ImageTimerDue, _applicationSettings.ImageTimerPeriod);
await _deviceClient.SetMethodHandlerAsync("ImageTimerStart", ImageTimerStartHandler, null);
await _deviceClient.SetMethodHandlerAsync("ImageTimerStop", ImageTimerStopHandler, null);
await _deviceClient.SetMethodDefaultHandlerAsync(DefaultHandler, null);
...
try
{
await Task.Delay(Timeout.Infinite, stoppingToken);
}
catch (TaskCanceledException)
{
_logger.LogInformation("Application shutown requested");
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Application startup failure");
}
finally
{
_deviceClient?.Dispose();
}
_logger.LogInformation("Azure IoT Smart Edge Camera Service shutdown");
}
private async Task<MethodResponse> ImageTimerStartHandler(MethodRequest methodRequest, object userContext)
{
_logger.LogInformation("ImageUpdatetimer Start Due:{0} Period:{1}", _applicationSettings.ImageTimerDue, _applicationSettings.ImageTimerPeriod);
_ImageUpdatetimer.Change(_applicationSettings.ImageTimerDue, _applicationSettings.ImageTimerPeriod);
return new MethodResponse((short)HttpStatusCode.OK);
}
private async Task<MethodResponse> ImageTimerStopHandler(MethodRequest methodRequest, object userContext)
{
_logger.LogInformation("ImageUpdatetimer Stop");
_ImageUpdatetimer.Change(Timeout.Infinite, Timeout.Infinite);
return new MethodResponse((short)HttpStatusCode.OK);
}
private async Task<MethodResponse> DefaultHandler(MethodRequest methodRequest, object userContext)
{
_logger.LogInformation("Direct Method default handler Name:{0}", methodRequest.Name);
return new MethodResponse((short)HttpStatusCode.NotFound);
}
I created an Azure IoT Central Template with two command capabilities. (For more detail see my post TTI V3 Connector Azure IoT Central Cloud to Device(C2D)).
Initially, I had one long post which covered Direct Methods, Readonly Properties and Updateable Properties but it got too long so I split it into three.