Add desired property Config.SetPointTemp and Config.TelemetryInterval
Expected behavior when desired.Config.SetPointTemp updated: 1. The mid-point (or average value) of temperature was updated 2. The reported property sharing the same name was update Expected behavior when desired.Config.TelemetryInterval updated: 1. The telemetry interval (a.k.a. report interval) was updated (unit: seconds) 2. The reported property sharing the same name was update Both the two desired properties will be persisted on the IoT Hub. So the effect will always be there, no matter the simulator was reboot or not, except the property was removed manually. Then it will use the default value: SetPointTemp: 34.5 TelemetryInterval: 5 second
This commit is contained in:
Родитель
918396ffb8
Коммит
799c1210e4
|
@ -26,9 +26,9 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.SampleDat
|
|||
private long _tickCounter;
|
||||
object sync = new Object();
|
||||
|
||||
public SampleDataGenerator(double minValueToGenerate,
|
||||
double maxNonPeakValueToGenerate, double minPeakValueToGenerate,
|
||||
int peakInterval, IRandomGenerator randomGenerator)
|
||||
public SampleDataGenerator(double minValueToGenerate,
|
||||
double maxNonPeakValueToGenerate, double minPeakValueToGenerate,
|
||||
int peakInterval, IRandomGenerator randomGenerator)
|
||||
{
|
||||
if (minValueToGenerate >= maxNonPeakValueToGenerate)
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.SampleDat
|
|||
|
||||
// minPeakValueToGenerate is zero when peaks are not generated
|
||||
_generatePeaks = minPeakValueToGenerate != 0 ? true : false;
|
||||
|
||||
|
||||
if (_generatePeaks && peakInterval == 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("peakInterval", "peakInterval cannot be 0.");
|
||||
|
@ -82,21 +82,21 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.SampleDat
|
|||
|
||||
}
|
||||
|
||||
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate,
|
||||
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate,
|
||||
double minPeakValueToGenerate, int peakInterval)
|
||||
: this(minValueToGenerate, maxNonPeakValueToGenerate, minPeakValueToGenerate,
|
||||
: this(minValueToGenerate, maxNonPeakValueToGenerate, minPeakValueToGenerate,
|
||||
peakInterval, new RandomGenerator())
|
||||
{
|
||||
}
|
||||
|
||||
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate,
|
||||
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate,
|
||||
IRandomGenerator randomGenerator)
|
||||
: this(minValueToGenerate, maxNonPeakValueToGenerate, 0, 0, randomGenerator)
|
||||
{
|
||||
}
|
||||
|
||||
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate)
|
||||
: this (minValueToGenerate, maxNonPeakValueToGenerate, 0, 0, new RandomGenerator())
|
||||
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate)
|
||||
: this(minValueToGenerate, maxNonPeakValueToGenerate, 0, 0, new RandomGenerator())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,11 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.SampleDat
|
|||
}
|
||||
}
|
||||
|
||||
public double GetMidPointOfRange()
|
||||
{
|
||||
return (_minValueToGenerate + _maxNonPeakValueToGenerate) / 2;
|
||||
}
|
||||
|
||||
private void GetNextRawValue()
|
||||
{
|
||||
double adjustment = ((2.0 * _deltaValue) * _randomGenerator.GetRandomDouble()) - _deltaValue;
|
||||
|
|
|
@ -10,6 +10,7 @@ using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.Sim
|
|||
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Devices;
|
||||
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Devices.DMTasks;
|
||||
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Logging;
|
||||
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Telemetry;
|
||||
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Telemetry.Factory;
|
||||
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Transport.Factory;
|
||||
using Microsoft.Azure.Devices.Client;
|
||||
|
@ -29,6 +30,8 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
ITelemetryFactory telemetryFactory, IConfigurationProvider configurationProvider)
|
||||
: base(logger, transportFactory, telemetryFactory, configurationProvider)
|
||||
{
|
||||
_desiredPropertyUdateHandlers.Add(SetPointTempPropertyName, OnSetPointTempUpdate);
|
||||
_desiredPropertyUdateHandlers.Add(TelemetryIntervalPropertyName, OnTelemetryIntervalUpdate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -75,7 +78,7 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
public void ChangeSetPointTemp(double setPointTemp)
|
||||
{
|
||||
var remoteMonitorTelemetry = (RemoteMonitorTelemetry)_telemetryController;
|
||||
remoteMonitorTelemetry.ChangeSetPointTemperature(setPointTemp);
|
||||
remoteMonitorTelemetry.SetPointTemperature = setPointTemp;
|
||||
Logger.LogInfo("Device {0} temperature changed to {1}", DeviceID, setPointTemp);
|
||||
}
|
||||
|
||||
|
@ -272,5 +275,21 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
}
|
||||
await Transport.UpdateReportedPropertiesAsync(collection);
|
||||
}
|
||||
|
||||
protected async Task OnSetPointTempUpdate(object value)
|
||||
{
|
||||
var telemetry = _telemetryController as ITelemetryWithSetPointTemperature;
|
||||
telemetry.SetPointTemperature = Convert.ToDouble(value);
|
||||
|
||||
await SetReportedPropertyAsync(SetPointTempPropertyName, telemetry.SetPointTemperature);
|
||||
}
|
||||
|
||||
protected async Task OnTelemetryIntervalUpdate(object value)
|
||||
{
|
||||
var telemetry = _telemetryController as ITelemetryWithInterval;
|
||||
telemetry.TelemetryIntervalInSeconds = Convert.ToInt32(value);
|
||||
|
||||
await SetReportedPropertyAsync(TelemetryIntervalPropertyName, telemetry.TelemetryIntervalInSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.Sim
|
|||
|
||||
namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.Cooler.Telemetry
|
||||
{
|
||||
public class RemoteMonitorTelemetry : ITelemetry
|
||||
public class RemoteMonitorTelemetry : ITelemetry, ITelemetryWithInterval, ITelemetryWithSetPointTemperature
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _deviceId;
|
||||
|
@ -32,11 +32,13 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
ActivateExternalTemperature = false;
|
||||
TelemetryActive = true;
|
||||
|
||||
int peakFrequencyInTicks = Convert.ToInt32(Math.Ceiling((double)PEAK_FREQUENCY_IN_SECONDS / REPORT_FREQUENCY_IN_SECONDS));
|
||||
int peakFrequencyInTicks = Convert.ToInt32(Math.Ceiling((double)PEAK_FREQUENCY_IN_SECONDS / REPORT_FREQUENCY_IN_SECONDS));
|
||||
|
||||
_temperatureGenerator = new SampleDataGenerator(33, 36, 42, peakFrequencyInTicks);
|
||||
_humidityGenerator = new SampleDataGenerator(20, 50);
|
||||
_externalTemperatureGenerator = new SampleDataGenerator(-20, 120);
|
||||
|
||||
TelemetryIntervalInSeconds = REPORT_FREQUENCY_IN_SECONDS;
|
||||
}
|
||||
|
||||
public async Task SendEventsAsync(CancellationToken token, Func<object, Task> sendMessageAsync)
|
||||
|
@ -67,13 +69,23 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
|
||||
await sendMessageAsync(monitorData);
|
||||
}
|
||||
await Task.Delay(TimeSpan.FromSeconds(REPORT_FREQUENCY_IN_SECONDS), token);
|
||||
await Task.Delay(TimeSpan.FromSeconds(TelemetryIntervalInSeconds), token);
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeSetPointTemperature(double newSetPointTemperature)
|
||||
public int TelemetryIntervalInSeconds { get; set; }
|
||||
|
||||
public double SetPointTemperature
|
||||
{
|
||||
_temperatureGenerator.ShiftSubsequentData(newSetPointTemperature);
|
||||
get
|
||||
{
|
||||
return _temperatureGenerator.GetMidPointOfRange();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_temperatureGenerator.ShiftSubsequentData(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,8 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
public const string StartupTimePropertyName = "StartupTime";
|
||||
public const string FirmwareVersionPropertyName = "FirmwareVersion";
|
||||
public const string ConfigurationVersionPropertyName = "ConfigurationVersion";
|
||||
public const string SetPointTempPropertyName = "Config.SetPointTemp";
|
||||
public const string TelemetryIntervalPropertyName = "Config.TelemetryInterval";
|
||||
|
||||
// pointer to the currently executing event group
|
||||
private int _currentEventGroup = 0;
|
||||
|
@ -168,10 +170,7 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
{
|
||||
try
|
||||
{
|
||||
await Transport.OpenAsync();
|
||||
await UpdateReportedPropertiesAsync();
|
||||
|
||||
SetMethodHandlers();
|
||||
await InitializeAsync();
|
||||
|
||||
var loopTasks = new List<Task>
|
||||
{
|
||||
|
@ -191,6 +190,16 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
}
|
||||
}
|
||||
|
||||
private async Task InitializeAsync()
|
||||
{
|
||||
await Transport.OpenAsync();
|
||||
SetupCallbacks();
|
||||
|
||||
var twin = await Transport.GetTwinAsync();
|
||||
await UpdateReportedPropertiesAsync(twin.Properties.Reported);
|
||||
await OnDesiredPropertyUpdate(twin.Properties.Desired, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through the list of IEventGroups and fires off the events in a given event group before moving to the next.
|
||||
/// If RepeatEventListForever is true the device will continue to loop through each event group, if false
|
||||
|
@ -351,14 +360,12 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
Logger.LogInfo("********** Processing Device {0} has been cancelled - StartReceiveLoopAsync Ending. **********", DeviceID);
|
||||
}
|
||||
|
||||
protected async Task UpdateReportedPropertiesAsync(bool regenerate = false)
|
||||
protected async Task UpdateReportedPropertiesAsync(TwinCollection reported, bool regenerate = false)
|
||||
{
|
||||
var reported = await Transport.GetReportedPropertiesAsync();
|
||||
|
||||
var patch = new TwinCollection();
|
||||
CrossSyncProperties(patch, reported, regenerate);
|
||||
AddSupportedMethods(patch, reported);
|
||||
patch.Set(StartupTimePropertyName, DateTime.UtcNow.ToString());
|
||||
AddConfigs(patch);
|
||||
|
||||
// Update ReportedProperties to IoT Hub
|
||||
await Transport.UpdateReportedPropertiesAsync(patch);
|
||||
|
@ -454,13 +461,58 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
patch["SupportedMethods"] = supportedMethods;
|
||||
}
|
||||
|
||||
private void SetMethodHandlers()
|
||||
protected void AddConfigs(TwinCollection patch)
|
||||
{
|
||||
var telemetryWithInterval = _telemetryController as ITelemetryWithInterval;
|
||||
if (telemetryWithInterval != null)
|
||||
{
|
||||
patch.Set(TelemetryIntervalPropertyName, telemetryWithInterval.TelemetryIntervalInSeconds);
|
||||
}
|
||||
|
||||
var telemetryWithSetPointTemp = _telemetryController as ITelemetryWithSetPointTemperature;
|
||||
if (telemetryWithSetPointTemp != null)
|
||||
{
|
||||
patch.Set(SetPointTempPropertyName, telemetryWithSetPointTemp.SetPointTemperature);
|
||||
}
|
||||
|
||||
patch.Set(StartupTimePropertyName, DateTime.UtcNow.ToString());
|
||||
}
|
||||
|
||||
private void SetupCallbacks()
|
||||
{
|
||||
foreach (var method in Commands.Where(c => c.DeliveryType == DeliveryType.Method))
|
||||
{
|
||||
var callback = GetType().GetMethod($"On{method.Name}").CreateDelegate(typeof(MethodCallback), this) as MethodCallback;
|
||||
try
|
||||
{
|
||||
var handler = GetType().GetMethod($"On{method.Name}").CreateDelegate(typeof(MethodCallback), this) as MethodCallback;
|
||||
|
||||
Transport.SetMethodHandler(method.Name, callback);
|
||||
Transport.SetMethodHandler(method.Name, handler);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Exception raised while adding callback for method {method.Name}: {ex}");
|
||||
}
|
||||
}
|
||||
|
||||
Transport.SetDesiredPropertyUpdateCallback(OnDesiredPropertyUpdate);
|
||||
}
|
||||
|
||||
public async Task OnDesiredPropertyUpdate(TwinCollection desiredProperties, object userContext)
|
||||
{
|
||||
foreach (var pair in desiredProperties.AsEnumerableFlatten())
|
||||
{
|
||||
Func<object, Task> handler;
|
||||
if (_desiredPropertyUdateHandlers.TryGetValue(pair.Key, out handler))
|
||||
{
|
||||
try
|
||||
{
|
||||
await handler(pair.Value.Value.Value);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Exception raised while processing desired property {pair.Key} change: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,4 +22,14 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
/// <returns>Task that completes when all tasks are sent</returns>
|
||||
Task SendEventsAsync(CancellationToken token, Func<object, Task> sendMessageAsync);
|
||||
}
|
||||
|
||||
public interface ITelemetryWithInterval
|
||||
{
|
||||
int TelemetryIntervalInSeconds { get; set; }
|
||||
}
|
||||
|
||||
public interface ITelemetryWithSetPointTemperature
|
||||
{
|
||||
double SetPointTemperature { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,17 +94,21 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
await Task.FromResult(0);
|
||||
}
|
||||
|
||||
public async Task<TwinCollection> GetReportedPropertiesAsync()
|
||||
public async Task<Twin> GetTwinAsync()
|
||||
{
|
||||
_logger.LogInfo("GetReportedPropertiesAsync called");
|
||||
_logger.LogInfo("GetTwinAsync called");
|
||||
|
||||
return await Task.FromResult(new TwinCollection());
|
||||
return await Task.FromResult(new Twin());
|
||||
}
|
||||
|
||||
public void SetMethodHandler(string methodName, MethodCallback callback)
|
||||
{
|
||||
_logger.LogInfo("SetMethodHandler called:");
|
||||
_logger.LogInfo($"SetMethodHandler: methodName: {methodName}");
|
||||
_logger.LogInfo($"SetMethodHandler called: {methodName} -> {callback.Method.Name}");
|
||||
}
|
||||
|
||||
public void SetDesiredPropertyUpdateCallback(DesiredPropertyUpdateCallback callback)
|
||||
{
|
||||
_logger.LogInfo($"SetDesiredPropertyUpdateCallback called, callback = {callback.Method.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,10 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
|
||||
Task UpdateReportedPropertiesAsync(TwinCollection reportedProperties);
|
||||
|
||||
Task<TwinCollection> GetReportedPropertiesAsync();
|
||||
Task<Twin> GetTwinAsync();
|
||||
|
||||
void SetMethodHandler(string methodName, MethodCallback callback);
|
||||
|
||||
void SetDesiredPropertyUpdateCallback(DesiredPropertyUpdateCallback callback);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -285,10 +285,9 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties);
|
||||
}
|
||||
|
||||
public async Task<TwinCollection> GetReportedPropertiesAsync()
|
||||
public async Task<Twin> GetTwinAsync()
|
||||
{
|
||||
var twin = await _deviceClient.GetTwinAsync();
|
||||
return twin.Properties.Reported;
|
||||
return await _deviceClient.GetTwinAsync();
|
||||
}
|
||||
|
||||
public void SetMethodHandler(string methodName, MethodCallback callback)
|
||||
|
@ -296,6 +295,11 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
|
|||
_deviceClient.SetMethodHandler(methodName, callback, null);
|
||||
}
|
||||
|
||||
public void SetDesiredPropertyUpdateCallback(DesiredPropertyUpdateCallback callback)
|
||||
{
|
||||
_deviceClient.SetDesiredPropertyUpdateCallback(callback, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement the IDisposable interface in order to close the device manager
|
||||
/// </summary>
|
||||
|
|
Загрузка…
Ссылка в новой задаче