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:
Xiangzhi Sheng 2017-01-11 12:02:04 +08:00
Родитель 918396ffb8
Коммит 799c1210e4
8 изменённых файлов: 143 добавлений и 35 удалений

Просмотреть файл

@ -96,7 +96,7 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Common.SampleDat
} }
public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate) public SampleDataGenerator(double minValueToGenerate, double maxNonPeakValueToGenerate)
: this (minValueToGenerate, maxNonPeakValueToGenerate, 0, 0, new RandomGenerator()) : 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() private void GetNextRawValue()
{ {
double adjustment = ((2.0 * _deltaValue) * _randomGenerator.GetRandomDouble()) - _deltaValue; 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;
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Devices.DMTasks; 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.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.Telemetry.Factory;
using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Transport.Factory; using Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob.SimulatorCore.Transport.Factory;
using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Client;
@ -29,6 +30,8 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
ITelemetryFactory telemetryFactory, IConfigurationProvider configurationProvider) ITelemetryFactory telemetryFactory, IConfigurationProvider configurationProvider)
: base(logger, transportFactory, telemetryFactory, configurationProvider) : base(logger, transportFactory, telemetryFactory, configurationProvider)
{ {
_desiredPropertyUdateHandlers.Add(SetPointTempPropertyName, OnSetPointTempUpdate);
_desiredPropertyUdateHandlers.Add(TelemetryIntervalPropertyName, OnTelemetryIntervalUpdate);
} }
/// <summary> /// <summary>
@ -75,7 +78,7 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
public void ChangeSetPointTemp(double setPointTemp) public void ChangeSetPointTemp(double setPointTemp)
{ {
var remoteMonitorTelemetry = (RemoteMonitorTelemetry)_telemetryController; var remoteMonitorTelemetry = (RemoteMonitorTelemetry)_telemetryController;
remoteMonitorTelemetry.ChangeSetPointTemperature(setPointTemp); remoteMonitorTelemetry.SetPointTemperature = setPointTemp;
Logger.LogInfo("Device {0} temperature changed to {1}", DeviceID, 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); 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 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 ILogger _logger;
private readonly string _deviceId; private readonly string _deviceId;
@ -37,6 +37,8 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
_temperatureGenerator = new SampleDataGenerator(33, 36, 42, peakFrequencyInTicks); _temperatureGenerator = new SampleDataGenerator(33, 36, 42, peakFrequencyInTicks);
_humidityGenerator = new SampleDataGenerator(20, 50); _humidityGenerator = new SampleDataGenerator(20, 50);
_externalTemperatureGenerator = new SampleDataGenerator(-20, 120); _externalTemperatureGenerator = new SampleDataGenerator(-20, 120);
TelemetryIntervalInSeconds = REPORT_FREQUENCY_IN_SECONDS;
} }
public async Task SendEventsAsync(CancellationToken token, Func<object, Task> sendMessageAsync) 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 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 StartupTimePropertyName = "StartupTime";
public const string FirmwareVersionPropertyName = "FirmwareVersion"; public const string FirmwareVersionPropertyName = "FirmwareVersion";
public const string ConfigurationVersionPropertyName = "ConfigurationVersion"; public const string ConfigurationVersionPropertyName = "ConfigurationVersion";
public const string SetPointTempPropertyName = "Config.SetPointTemp";
public const string TelemetryIntervalPropertyName = "Config.TelemetryInterval";
// pointer to the currently executing event group // pointer to the currently executing event group
private int _currentEventGroup = 0; private int _currentEventGroup = 0;
@ -168,10 +170,7 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
{ {
try try
{ {
await Transport.OpenAsync(); await InitializeAsync();
await UpdateReportedPropertiesAsync();
SetMethodHandlers();
var loopTasks = new List<Task> 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> /// <summary>
/// Iterates through the list of IEventGroups and fires off the events in a given event group before moving to the next. /// 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 /// 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); 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(); var patch = new TwinCollection();
CrossSyncProperties(patch, reported, regenerate); CrossSyncProperties(patch, reported, regenerate);
AddSupportedMethods(patch, reported); AddSupportedMethods(patch, reported);
patch.Set(StartupTimePropertyName, DateTime.UtcNow.ToString()); AddConfigs(patch);
// Update ReportedProperties to IoT Hub // Update ReportedProperties to IoT Hub
await Transport.UpdateReportedPropertiesAsync(patch); await Transport.UpdateReportedPropertiesAsync(patch);
@ -454,13 +461,58 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
patch["SupportedMethods"] = supportedMethods; 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)) 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> /// <returns>Task that completes when all tasks are sent</returns>
Task SendEventsAsync(CancellationToken token, Func<object, Task> sendMessageAsync); 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); 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) public void SetMethodHandler(string methodName, MethodCallback callback)
{ {
_logger.LogInfo("SetMethodHandler called:"); _logger.LogInfo($"SetMethodHandler called: {methodName} -> {callback.Method.Name}");
_logger.LogInfo($"SetMethodHandler: methodName: {methodName}"); }
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 UpdateReportedPropertiesAsync(TwinCollection reportedProperties);
Task<TwinCollection> GetReportedPropertiesAsync(); Task<Twin> GetTwinAsync();
void SetMethodHandler(string methodName, MethodCallback callback); 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); await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties);
} }
public async Task<TwinCollection> GetReportedPropertiesAsync() public async Task<Twin> GetTwinAsync()
{ {
var twin = await _deviceClient.GetTwinAsync(); return await _deviceClient.GetTwinAsync();
return twin.Properties.Reported;
} }
public void SetMethodHandler(string methodName, MethodCallback callback) public void SetMethodHandler(string methodName, MethodCallback callback)
@ -296,6 +295,11 @@ namespace Microsoft.Azure.Devices.Applications.RemoteMonitoring.Simulator.WebJob
_deviceClient.SetMethodHandler(methodName, callback, null); _deviceClient.SetMethodHandler(methodName, callback, null);
} }
public void SetDesiredPropertyUpdateCallback(DesiredPropertyUpdateCallback callback)
{
_deviceClient.SetDesiredPropertyUpdateCallback(callback, null);
}
/// <summary> /// <summary>
/// Implement the IDisposable interface in order to close the device manager /// Implement the IDisposable interface in order to close the device manager
/// </summary> /// </summary>