diff options
23 files changed, 956 insertions, 118 deletions
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs index 695d71b4b..872523bd0 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs @@ -46,6 +46,7 @@ namespace Tango.PPC.Common.Connection /// Occurs when the machine has disconnected. /// </summary> public event EventHandler MachineDisconnected; + public event EventHandler<Machine> Initialized; private bool _isConnected; /// <summary> @@ -345,6 +346,8 @@ namespace Tango.PPC.Common.Connection MachineOperator.JobRunsLogger.SetDefaultMachine(Machine); + Initialized?.Invoke(this, Machine); + ConnectToMachine(); } else diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/IMachineProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/IMachineProvider.cs index 774fa7c9e..52ab2620b 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/IMachineProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/IMachineProvider.cs @@ -25,6 +25,9 @@ namespace Tango.PPC.Common.Connection /// </summary> event EventHandler MachineDisconnected; + + event EventHandler<Machine> Initialized; + /// <summary> /// Gets a value indicating whether the machine is currently connected. /// </summary> diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index 7c20d08f5..c98a47e9a 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -273,6 +273,8 @@ <Compile Include="Synchronization\SynchronizationStatusChangedEventArgs.cs" /> <Compile Include="SystemInfo\DefaultSystemInfoService.cs" /> <Compile Include="SystemInfo\ISystemInfoService.cs" /> + <Compile Include="Telemetry\ITelemetryProvider.cs" /> + <Compile Include="Telemetry\TelemetrySettings.cs" /> <Compile Include="ThreadLoading\IThreadLoadingService.cs" /> <Compile Include="UpdatePackages\DefaultPackageRunner.cs" /> <Compile Include="UpdatePackages\IPackageRunner.cs" /> @@ -680,7 +682,7 @@ </Target> <ProjectExtensions> <VisualStudio> - <UserProperties BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UseGlobalSettings="False" BuildVersion_StartDate="2000/1/1" /> + <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" /> </VisualStudio> </ProjectExtensions> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Telemetry/ITelemetryProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Telemetry/ITelemetryProvider.cs new file mode 100644 index 000000000..529775d0e --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Telemetry/ITelemetryProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.PPC.Common.Telemetry +{ + public interface ITelemetryProvider + { + TelemetrySettings Settings { get; set; } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Telemetry/TelemetrySettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Telemetry/TelemetrySettings.cs new file mode 100644 index 000000000..7acf7e197 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Telemetry/TelemetrySettings.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Logging; +using Tango.Settings; + +namespace Tango.PPC.Common.Telemetry +{ + public class TelemetrySettings : SettingsBase + { + public bool Enable { get; set; } = true; + + public bool EnableIoTHub { get; set; } = true; + public bool EnableMqtt { get; set; } = false; + + public String IoTHubConnectionString { get; set; } = "HostName=iot-twine-dev-weu.azure-devices.net;DeviceId=telemetry-dev-01;SharedAccessKey=cZhCMhiVL+TF7p13fpX+lFmyxoy8ZqCkbxUwumWw18Q="; + + /// <summary> + /// Interval for checking and reprocessing failed/pending telemetry from local storage. + /// </summary> + public TimeSpan PendingStorageCheckInterval { get; set; } = TimeSpan.FromMinutes(1); + + /// <summary> + /// Frequency at which historical sources are polled to request backlogged or missed telemetry. + /// </summary> + public TimeSpan HistorySourcesRequestInterval { get; set; } = TimeSpan.FromMinutes(1); + + /// <summary> + /// Whether exponential backoff should be applied to retry logic per destination. + /// </summary> + public bool EnableBackoff { get; set; } = false; + + /// <summary> + /// The maximum amount of time to delay retries during exponential backoff. + /// </summary> + public TimeSpan MaxExponentialBackoff { get; set; } = TimeSpan.FromHours(1); + + /// <summary> + /// Gets or sets the interval at which the published telemetry cache cleanup process should occur. + /// This defines how frequently old published telemetry entries are eligible for pruning, + /// based on their publication timestamp. + /// </summary> + public TimeSpan PublishedTelemetriesCacheCleanupInterval { get; set; } = TimeSpan.FromHours(1); + + public bool SendDiagnostics { get; set; } = true; + public TimeSpan DiagnosticsSamplingInterval { get; set; } = TimeSpan.FromSeconds(60); + public bool SendEvents { get; set; } = true; + public bool SendJobRuns { get; set; } = true; + public bool SendJobRunsHistory { get; set; } = true; + public bool SendJobStatus { get; set; } = true; + public bool SendLogs { get; set; } = true; + public bool SendMachineStatus { get; set; } = true; + public bool SendMachineUpdates { get; set; } = true; + public bool SendMachineUpdatesHistory { get; set; } = true; + public bool SendWires { get; set; } = true; + + public HashSet<LogCategory> LogCategories { get; set; } = new HashSet<LogCategory>() { LogCategory.Critical, LogCategory.Error, LogCategory.Warning }; + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config index 4d7554231..53a599bee 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config @@ -84,7 +84,7 @@ <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0" /> + <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" /> </dependentAssembly> @@ -96,6 +96,46 @@ </dependentAssembly> + <dependentAssembly> + + <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + + <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" /> + + </dependentAssembly> + + <dependentAssembly> + + <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + + </dependentAssembly> + + <dependentAssembly> + + <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" /> + + <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" /> + + </dependentAssembly> + + <dependentAssembly> + + <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + + <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" /> + + </dependentAssembly> + + <dependentAssembly> + + <assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" /> + + <bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" /> + + </dependentAssembly> + </assemblyBinding> </runtime> <entityFramework> diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj index 31c46b296..99a7e7c75 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj @@ -98,6 +98,24 @@ <Reference Include="ControlzEx, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\ControlzEx.3.0.2.4\lib\net45\ControlzEx.dll</HintPath> </Reference> + <Reference Include="DotNetty.Buffers, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Buffers.0.4.6\lib\net45\DotNetty.Buffers.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Codecs, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Codecs.0.4.6\lib\net45\DotNetty.Codecs.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Codecs.Mqtt, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Codecs.Mqtt.0.4.6\lib\net45\DotNetty.Codecs.Mqtt.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Common, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Common.0.4.6\lib\net45\DotNetty.Common.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Handlers, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Handlers.0.4.6\lib\net45\DotNetty.Handlers.dll</HintPath> + </Reference> + <Reference Include="DotNetty.Transport, Version=0.4.6.0, Culture=neutral, PublicKeyToken=bc13ca065fa06c29, processorArchitecture=MSIL"> + <HintPath>..\..\packages\DotNetty.Transport.0.4.6\lib\net45\DotNetty.Transport.dll</HintPath> + </Reference> <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> <HintPath>..\..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll</HintPath> </Reference> @@ -110,14 +128,84 @@ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <HintPath>..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath> </Reference> + <Reference Include="Microsoft.Azure.Amqp, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.Amqp.2.0.6\lib\net45\Microsoft.Azure.Amqp.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.Devices.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.Devices.Client.1.6.0\lib\net45\Microsoft.Azure.Devices.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.Devices.Shared, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.Devices.Shared.1.3.0\lib\net45\Microsoft.Azure.Devices.Shared.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Azure.KeyVault.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Data.Edm, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.Edm.5.6.4\lib\net40\Microsoft.Data.Edm.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Data.OData, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.OData.5.6.4\lib\net40\Microsoft.Data.OData.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Data.Services.Client, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.Services.Client.5.6.4\lib\net40\Microsoft.Data.Services.Client.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.1.1.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Extensions.Logging, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Extensions.Logging.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=1.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Extensions.Logging.Abstractions.1.1.1\lib\netstandard1.1\Microsoft.Extensions.Logging.Abstractions.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8\Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.dll</HintPath> + </Reference> + <Reference Include="Microsoft.Win32.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> <Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\Microsoft.WindowsAPICodePack-Core.1.1.0.0\lib\Microsoft.WindowsAPICodePack.dll</HintPath> </Reference> + <Reference Include="Microsoft.WindowsAzure.Storage, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\WindowsAzure.Storage.7.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll</HintPath> + </Reference> + <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="PCLCrypto, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d4421c8a4786956c, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PCLCrypto.2.0.147\lib\net45\PCLCrypto.dll</HintPath> + </Reference> + <Reference Include="PInvoke.BCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.BCrypt.0.3.2\lib\net40\PInvoke.BCrypt.dll</HintPath> + </Reference> + <Reference Include="PInvoke.Kernel32, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.Kernel32.0.3.2\lib\net40\PInvoke.Kernel32.dll</HintPath> + </Reference> + <Reference Include="PInvoke.NCrypt, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.NCrypt.0.3.2\lib\net40\PInvoke.NCrypt.dll</HintPath> + </Reference> + <Reference Include="PInvoke.Windows.Core, Version=0.3.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PInvoke.Windows.Core.0.3.2\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\PInvoke.Windows.Core.dll</HintPath> + </Reference> <Reference Include="SimpleValidator, Version=0.6.1.0, Culture=neutral, processorArchitecture=MSIL"> <HintPath>..\..\packages\SimpleValidator.0.6.1.0\lib\net40\SimpleValidator.dll</HintPath> </Reference> <Reference Include="System" /> + <Reference Include="System.AppContext, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.AppContext.4.3.0\lib\net46\System.AppContext.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.DataAnnotations" /> + <Reference Include="System.Console, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Console.4.3.0\lib\net46\System.Console.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> <Reference Include="System.Data" /> <Reference Include="System.Data.SQLite, Version=1.0.108.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL"> <HintPath>..\..\packages\System.Data.SQLite.Core.1.0.108.0\lib\net46\System.Data.SQLite.dll</HintPath> @@ -131,7 +219,78 @@ <HintPath>..\..\packages\System.Data.SQLite.Linq.1.0.108.0\lib\net46\System.Data.SQLite.Linq.dll</HintPath> <Private>True</Private> </Reference> + <Reference Include="System.Diagnostics.DiagnosticSource, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Diagnostics.DiagnosticSource.4.3.0\lib\net46\System.Diagnostics.DiagnosticSource.dll</HintPath> + </Reference> <Reference Include="System.Drawing" /> + <Reference Include="System.Globalization.Calendars, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.IO.Compression, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.IO.Compression.FileSystem" /> + <Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.IO.FileSystem, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.IO.FileSystem.Primitives, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.Http.4.3.0\lib\net46\System.Net.Http.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Net.Http.Formatting, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll</HintPath> + </Reference> + <Reference Include="System.Net.Sockets, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Numerics" /> + <Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="System.Spatial, Version=5.6.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Spatial.5.6.4\lib\net40\System.Spatial.dll</HintPath> + </Reference> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\..\packages\Expression.Blend.Sdk.1.0.2\lib\net45\System.Windows.Interactivity.dll</HintPath> @@ -141,10 +300,17 @@ <Reference Include="System.Core" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="System.Net.Http" /> <Reference Include="System.Xaml"> <RequiredTargetFramework>4.0</RequiredTargetFramework> </Reference> + <Reference Include="System.Xml.ReaderWriter, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Xml.ReaderWriter.4.3.0\lib\net46\System.Xml.ReaderWriter.dll</HintPath> + <Private>True</Private> + <Private>True</Private> + </Reference> + <Reference Include="Validation, Version=2.2.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Validation.2.2.8\lib\dotnet\Validation.dll</HintPath> + </Reference> <Reference Include="WindowsBase" /> <Reference Include="PresentationCore" /> <Reference Include="PresentationFramework" /> @@ -288,6 +454,7 @@ <Compile Include="PPCApplication\DefaultPPCApplicationManager.cs" /> <Compile Include="Printing\DefaultPrintingManager.cs" /> <Compile Include="RemoteActions\DefaultRemoteActionsService.cs" /> + <Compile Include="Telemetry\DefaultTelemetryProvider.cs" /> <Compile Include="Threading\DefaultDispatcherProvider.cs" /> <Compile Include="ThreadLoading\DefaultThreadLoadingService.cs" /> <Compile Include="ViewModelLocator.cs" /> @@ -707,7 +874,9 @@ </None> </ItemGroup> <ItemGroup> - <None Include="App.config" /> + <None Include="App.config"> + <SubType>Designer</SubType> + </None> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\SideChains\RealTimeGraphX-master\RealTimeGraphX.WPF\RealTimeGraphX.WPF.csproj"> @@ -778,6 +947,10 @@ <Project>{e1e66ed9-597d-45fa-8048-de90a6930484}</Project> <Name>Tango.SQLExaminer</Name> </ProjectReference> + <ProjectReference Include="..\..\Tango.Telemetry\Tango.Telemetry.csproj"> + <Project>{af593663-d4e9-4a14-a3f2-fea57f30e9e6}</Project> + <Name>Tango.Telemetry</Name> + </ProjectReference> <ProjectReference Include="..\..\Tango.TFS\Tango.TFS.csproj"> <Project>{998f8471-dc1b-41b6-9d96-354e1b4e7a32}</Project> <Name>Tango.TFS</Name> diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Telemetry/DefaultTelemetryProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Telemetry/DefaultTelemetryProvider.cs new file mode 100644 index 000000000..04837bb38 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Telemetry/DefaultTelemetryProvider.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; +using Tango.Core.DI; +using Tango.PPC.Common; +using Tango.PPC.Common.Application; +using Tango.PPC.Common.Connection; +using Tango.PPC.Common.Telemetry; +using Tango.PPC.Common.Web; +using Tango.Settings; +using Tango.Telemetry; +using Tango.Telemetry.Destinations; +using Tango.Telemetry.Helpers; +using Tango.Telemetry.Sources; + +namespace Tango.PPC.UI.Telemetry +{ + [TangoCreateWhenRegistered] + public class DefaultTelemetryProvider : ITelemetryProvider, ITelemetryCheckpointsRecoveryClient + { + private PPCWebClient _webClient; + private Machine _machine; + private IMachineProvider _machineProvider; + private PPCSettings _ppcSettings; + + public TelemetrySettings Settings { get; set; } + + public ITelemetryPublisher TelemetryPublisher { get; set; } + + public DefaultTelemetryProvider(IPPCApplicationManager applicationManager, IMachineProvider machineProvider, PPCWebClient webClient) + { + Settings = SettingsManager.Default.GetOrCreate<TelemetrySettings>(); + applicationManager.ApplicationReady += ApplicationManager_ApplicationReady; + _webClient = webClient; + _machineProvider = machineProvider; + } + + private void ApplicationManager_ApplicationReady(object sender, EventArgs e) + { + try + { + if (Settings.Enable) + { + Init(); + } + } + catch { } + } + + private void Init() + { + if (_machineProvider.Machine == null) return; + + _machine = _machineProvider.Machine; + + _ppcSettings = SettingsManager.Default.GetOrCreate<PPCSettings>(); + + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + var site = db.Sites.FirstOrDefault(x => x.Guid == _machine.SiteGuid); + + TelemetryPublisher = new TelemetryPublisher(new TelemetryPublisherConfiguration() + { + Environment = _ppcSettings.DeploymentSlot.ToString(), + Organization = _machine.Organization.Name, + Site = site?.Name, + SerialNumber = _machine.SerialNumber, + MachineType = _machine.Type, + EnableBackoff = Settings.EnableBackoff, + HistorySourcesRequestInterval = Settings.HistorySourcesRequestInterval, + MaxExponentialBackoff = Settings.MaxExponentialBackoff, + PendingStorageCheckInterval = Settings.PendingStorageCheckInterval, + }, this); + + (TelemetryPublisher.StorageManager as TelemetryLiteDBStorageManager).EnableCheckPointsRecovery = true; + (TelemetryPublisher.StorageManager as TelemetryLiteDBStorageManager).EnforceCheckpointsRecovery = true; + } + + InternetConnectivity.EnsureStarted(); + + Task.Factory.StartNew(async () => + { + while (!InternetConnectivity.IsInternetAvailable()) + { + Thread.Sleep(5000); + } + + if (!_webClient.IsAuthenticated) + { + await _webClient.Login(new LoginRequest() { Mode = LoginMode.Machine, SerialNumber = _machine.SerialNumber, MachineGuid = _machine.Guid }); + } + + var response = await _webClient.GetTelemetryDeviceConnection(new TelemetryDeviceRegistrationRequest()); + Settings.IoTHubConnectionString = response.ConnectionString; + Settings.Save(); + + if (Settings.EnableIoTHub) + { + TelemetryPublisher.RegisterDestination(new TelemetryAzureHubDestination(Settings.IoTHubConnectionString)); + } + + if (Settings.EnableMqtt) + { + TelemetryPublisher.RegisterDestination(new TelemetryMqttDestination($"Twine {_machine.SerialNumber}")); + } + + if (Settings.SendDiagnostics) + { + TelemetryPublisher.RegisterSource(new TelemetryDiagnosticsStreamingSource(_machineProvider.MachineOperator) + { + Config = new TelemetryDiagnosticsStreamingSourceConfig() + { + DiagnosticsSamplingInterval = Settings.DiagnosticsSamplingInterval, + } + }); + } + + if (Settings.SendEvents) + { + TelemetryPublisher.RegisterSource(new TelemetryEventsStreamingSource(_machineProvider.MachineOperator)); + } + + if (Settings.SendJobRuns) + { + TelemetryPublisher.RegisterSource(new TelemetryJobRunsStreamingSource(_machineProvider.MachineOperator)); + } + + if (Settings.SendJobRunsHistory) + { + TelemetryPublisher.RegisterSource(new TelemetryJobRunsHistorySource() { Config = new TelemetryJobRunsHistorySourceConfig() { MaxJobRunsPerRequest = 10 } }); + } + + if (Settings.SendJobStatus) + { + TelemetryPublisher.RegisterSource(new TelemetryJobStatusSource(_machineProvider.MachineOperator)); + } + + if (Settings.SendLogs) + { + TelemetryPublisher.RegisterSource(new TelemetryLogsStreamingSource(_machineProvider.MachineOperator) + { + Config = new TelemetryLogsStreamingSourceConfig() + { + Categories = Settings.LogCategories + } + }); + } + + if (Settings.SendMachineStatus) + { + TelemetryPublisher.RegisterSource(new TelemetryMachineStatusStreamingSource(_machineProvider.MachineOperator)); + } + + if (Settings.SendMachineUpdates) + { + TelemetryPublisher.RegisterSource(new TelemetryMachineUpdatesStreamingSource()); + } + + if (Settings.SendMachineUpdatesHistory) + { + TelemetryPublisher.RegisterSource(new TelemetryMachineUpdatesHistorySource()); + } + + if (Settings.SendWires) + { + TelemetryPublisher.RegisterSource(new TelemetryWireStreamingSource(_machineProvider.MachineOperator)); + } + + await TelemetryPublisher.Start(); + }); + } + + public async Task<List<TelemetryHistorySourceCheckPoint>> GetCheckpointsBackup() + { + var response = await _webClient.GetTelemetryCheckPoints(new TelemetryGetCheckPointsRequest()); + return response.Checkpoints + .Select(x => new TelemetryHistorySourceCheckPoint() + { + SourceName = x.SourceName, + Time = x.Time, + TotalCount = x.TotalCount + }) + .ToList(); + } + + public async Task SaveCheckpointsBackup(List<TelemetryHistorySourceCheckPoint> checkPoints) + { + await _webClient.SetTelemetryCheckPoints(new TelemetrySetCheckPointsRequest() + { + Checkpoints = checkPoints.Select(x => new TelemetryCheckPoint() + { + SourceName = x.SourceName, + Time = x.Time, + TotalCount = x.TotalCount + }).ToList() + }); + } + + public void Dispose() + { + + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs index 340ecb13e..56a8b4a2b 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs @@ -40,6 +40,7 @@ using Tango.PPC.Common.Statistics; using Tango.PPC.Common.Storage; using Tango.PPC.Common.Synchronization; using Tango.PPC.Common.SystemInfo; +using Tango.PPC.Common.Telemetry; using Tango.PPC.Common.Threading; using Tango.PPC.Common.ThreadLoading; using Tango.PPC.Common.UpdatePackages; @@ -54,6 +55,7 @@ using Tango.PPC.UI.Notifications; using Tango.PPC.UI.PPCApplication; using Tango.PPC.UI.Printing; using Tango.PPC.UI.RemoteActions; +using Tango.PPC.UI.Telemetry; using Tango.PPC.UI.Threading; using Tango.PPC.UI.ThreadLoading; using Tango.PPC.UI.ViewModels; @@ -118,6 +120,7 @@ namespace Tango.PPC.UI TangoIOC.Default.Unregister<IStatisticsService>(); TangoIOC.Default.Unregister<IJobResumeManager>(); TangoIOC.Default.Unregister<ISMSNotificationProvider>(); + TangoIOC.Default.Unregister<ITelemetryProvider>(); if (App.StartupArgs != null && App.StartupArgs.Contains("-webDebug")) { @@ -175,6 +178,7 @@ namespace Tango.PPC.UI TangoIOC.Default.Register<IStatisticsService, DefaultStatisticsService>(); TangoIOC.Default.Register<IJobResumeManager, DefaultJobResumeManager>(); TangoIOC.Default.Register<ISMSNotificationProvider, DefaultSMSNotificationProvider>(); + TangoIOC.Default.Register<ITelemetryProvider, DefaultTelemetryProvider>(); TangoIOC.Default.Register<LoadingViewVM>(); TangoIOC.Default.Register<MainViewVM>(); diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/packages.config b/Software/Visual_Studio/PPC/Tango.PPC.UI/packages.config index 9e3e48198..59e20edb2 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/packages.config +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/packages.config @@ -1,15 +1,89 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="ControlzEx" version="3.0.2.4" targetFramework="net46" /> + <package id="DotNetty.Buffers" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Codecs" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Codecs.Mqtt" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Common" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Handlers" version="0.4.6" targetFramework="net461" /> + <package id="DotNetty.Transport" version="0.4.6" targetFramework="net461" /> + <package id="EnterpriseLibrary.TransientFaultHandling" version="6.0.1304.0" targetFramework="net461" /> <package id="EntityFramework" version="6.2.0" targetFramework="net461" /> <package id="Expression.Blend.Sdk" version="1.0.2" targetFramework="net46" /> <package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net46" /> <package id="Google.Protobuf" version="3.4.1" targetFramework="net46" /> + <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net461" /> + <package id="Microsoft.Azure.Amqp" version="2.0.6" targetFramework="net461" /> + <package id="Microsoft.Azure.Devices.Client" version="1.6.0" targetFramework="net461" /> + <package id="Microsoft.Azure.Devices.Shared" version="1.3.0" targetFramework="net461" /> + <package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net461" /> + <package id="Microsoft.Data.Edm" version="5.6.4" targetFramework="net461" /> + <package id="Microsoft.Data.OData" version="5.6.4" targetFramework="net461" /> + <package id="Microsoft.Data.Services.Client" version="5.6.4" targetFramework="net461" /> + <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.1.0" targetFramework="net461" /> + <package id="Microsoft.Extensions.Logging" version="1.1.1" targetFramework="net461" /> + <package id="Microsoft.Extensions.Logging.Abstractions" version="1.1.1" targetFramework="net461" /> + <package id="Microsoft.NETCore.Platforms" version="1.1.0" targetFramework="net461" /> + <package id="Microsoft.Win32.Primitives" version="4.3.0" targetFramework="net461" /> <package id="Microsoft.WindowsAPICodePack-Core" version="1.1.0.0" targetFramework="net461" /> + <package id="NETStandard.Library" version="1.6.1" targetFramework="net461" /> + <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" /> + <package id="PCLCrypto" version="2.0.147" targetFramework="net461" /> + <package id="PInvoke.BCrypt" version="0.3.2" targetFramework="net461" /> + <package id="PInvoke.Kernel32" version="0.3.2" targetFramework="net461" /> + <package id="PInvoke.NCrypt" version="0.3.2" targetFramework="net461" /> + <package id="PInvoke.Windows.Core" version="0.3.2" targetFramework="net461" /> <package id="SimpleValidator" version="0.6.1.0" targetFramework="net46" /> + <package id="System.AppContext" version="4.3.0" targetFramework="net461" /> + <package id="System.Collections" version="4.3.0" targetFramework="net461" /> + <package id="System.Collections.Concurrent" version="4.3.0" targetFramework="net461" /> + <package id="System.ComponentModel" version="4.3.0" targetFramework="net461" /> + <package id="System.Console" version="4.3.0" targetFramework="net461" /> <package id="System.Data.SQLite" version="1.0.108.0" targetFramework="net46" /> <package id="System.Data.SQLite.Core" version="1.0.108.0" targetFramework="net46" /> <package id="System.Data.SQLite.EF6" version="1.0.108.0" targetFramework="net46" /> <package id="System.Data.SQLite.Linq" version="1.0.108.0" targetFramework="net46" /> + <package id="System.Diagnostics.Debug" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.DiagnosticSource" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.Tools" version="4.3.0" targetFramework="net461" /> + <package id="System.Diagnostics.Tracing" version="4.3.0" targetFramework="net461" /> + <package id="System.Globalization" version="4.3.0" targetFramework="net461" /> + <package id="System.Globalization.Calendars" version="4.3.0" targetFramework="net461" /> + <package id="System.IO" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.Compression" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.FileSystem" version="4.3.0" targetFramework="net461" /> + <package id="System.IO.FileSystem.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Linq" version="4.3.0" targetFramework="net461" /> + <package id="System.Linq.Expressions" version="4.3.0" targetFramework="net461" /> + <package id="System.Net.Http" version="4.3.0" targetFramework="net461" /> + <package id="System.Net.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Net.Sockets" version="4.3.0" targetFramework="net461" /> + <package id="System.ObjectModel" version="4.3.0" targetFramework="net461" /> + <package id="System.Reflection" version="4.3.0" targetFramework="net461" /> + <package id="System.Reflection.Extensions" version="4.3.0" targetFramework="net461" /> + <package id="System.Reflection.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.Extensions" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.Handles" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.InteropServices" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net461" /> + <package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" /> + <package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net461" /> + <package id="System.Spatial" version="5.6.4" targetFramework="net461" /> + <package id="System.Text.Encoding" version="4.3.0" targetFramework="net461" /> + <package id="System.Text.Encoding.Extensions" version="4.3.0" targetFramework="net461" /> + <package id="System.Text.RegularExpressions" version="4.3.0" targetFramework="net461" /> + <package id="System.Threading" version="4.3.0" targetFramework="net461" /> + <package id="System.Threading.Tasks" version="4.3.0" targetFramework="net461" /> + <package id="System.Threading.Timer" version="4.3.0" targetFramework="net461" /> + <package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="net461" /> + <package id="System.Xml.XDocument" version="4.3.0" targetFramework="net461" /> + <package id="Validation" version="2.2.8" targetFramework="net461" /> + <package id="WindowsAzure.Storage" version="7.0.0" targetFramework="net461" /> <package id="WPFMediaKit" version="2.2.0" targetFramework="net461" /> </packages>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs index 09f5ea2ac..de9168cac 100644 --- a/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs +++ b/Software/Visual_Studio/Tango.Emulations/Emulators/MachineEmulator.cs @@ -782,6 +782,7 @@ namespace Tango.Emulations.Emulators { var res = new StartMachineStatusUpdateResponse(); res.Status = MachineStatus; + res.Status.OverallTemperature = Cursor.Position.Y; if (!EmulateCorruption) { diff --git a/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs b/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs index 36604ba3c..79adfc0da 100644 --- a/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs +++ b/Software/Visual_Studio/Tango.Integration/Operation/JobHandler.cs @@ -28,6 +28,7 @@ namespace Tango.Integration.Operation protected double _last_progress; protected const int PROGRESS_REPORT_RANGE_METERS = 5; protected bool loggedContinueMessage; + private DateTime _lastProgressLogDateTime; #region Events @@ -341,25 +342,27 @@ namespace Tango.Integration.Operation protected virtual void InvalidateJobProgress(JobStatus s) { JobStatus = s; - - if (_last_progress != s.Progress) + + if (DateTime.UtcNow > _lastProgressLogDateTime.AddSeconds(5)) { - //if (LogManager.Categories.Exists(x => x == LogCategory.Debug)) - //{ + _lastProgressLogDateTime = DateTime.UtcNow; + + if (LogManager.Categories.Exists(x => x == LogCategory.Debug)) + { LogManager.Log($"Updating job progress {s.Progress}/{Status.TotalProgress}..."); - //} - //else - //{ - // if (s.Progress <= PROGRESS_REPORT_RANGE_METERS || s.Progress >= Status.TotalProgress - PROGRESS_REPORT_RANGE_METERS) - // { - // LogManager.Log($"Updating job progress {s.Progress}/{Status.TotalProgress}..."); - // } - // else if (!loggedContinueMessage) - // { - // loggedContinueMessage = true; - // LogManager.Log($"Progress logging will continue {PROGRESS_REPORT_RANGE_METERS} meters before completion..."); - // } - //} + } + else + { + if (s.Progress <= PROGRESS_REPORT_RANGE_METERS || s.Progress >= Status.TotalProgress - PROGRESS_REPORT_RANGE_METERS) + { + LogManager.Log($"Updating job progress {s.Progress}/{Status.TotalProgress}..."); + } + else if (!loggedContinueMessage) + { + loggedContinueMessage = true; + LogManager.Log($"Progress logging will continue {PROGRESS_REPORT_RANGE_METERS} meters before completion..."); + } + } } if (s.Progress < 0) @@ -378,16 +381,16 @@ namespace Tango.Integration.Operation { LogManager.Log($"Invalid job progress received '{s.Progress}' while last progress was '{_last_progress}'."); } - + _last_progress = s.Progress; - + List<Segment> unit_segments = new List<Segment>(); Status.Progress = s.Progress; Status.RemainingTime = Status.TotalTime - Job.TranslateProgressToTime(Status.Progress, ProcessParameters); Status.RemainingProgress = Status.TotalProgress - Status.Progress; - if((s.Progress < Status.SettingUpTotalProgress) || (Status.SettingUpProgress < Status.SettingUpTotalProgress)) + if ((s.Progress < Status.SettingUpTotalProgress) || (Status.SettingUpProgress < Status.SettingUpTotalProgress)) { Status.SettingUpProgress = Math.Min(s.Progress, this.Status.SettingUpTotalProgress); Status.IsSettingUp = true; @@ -437,12 +440,12 @@ namespace Tango.Integration.Operation break; } } - else if(ResumeConfig != null && ResumeConfig.GlobalStartPosition > 0) + else if (ResumeConfig != null && ResumeConfig.GlobalStartPosition > 0) { if (!Status.IsSettingUp && s.Progress <= previousUnitsLengthWithoutThis + unitLength + ProcessParameters.DryerBufferLengthMeters) { currentUnitProgress = s.Progress - previousUnitsLengthWithoutThis - ProcessParameters.DryerBufferLengthMeters; - //LogManager.Log($" JOB HANDLER currentUnitProgress before ={currentUnitProgress} progress = {s.Progress}"); + //LogManager.Log($" JOB HANDLER currentUnitProgress before ={currentUnitProgress} progress = {s.Progress}"); break; } } @@ -476,7 +479,7 @@ namespace Tango.Integration.Operation Status.CurrentUnitTotalProgress = Status.RemainingUnits > 1 && Job.EnableInterSegment ? Job.Length + (Job.InterSegmentLength) : Job.Length; - if (s.Message != _lastStatusMessage ) + if (s.Message != _lastStatusMessage) { Status.Message = s.Message; } diff --git a/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubBatchDestination.cs b/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubBatchDestination.cs new file mode 100644 index 000000000..10bc3981a --- /dev/null +++ b/Software/Visual_Studio/Tango.Telemetry/Destinations/TelemetryAzureHubBatchDestination.cs @@ -0,0 +1,208 @@ +using Microsoft.Azure.Devices.Client; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; +using Tango.Logging; +using Tango.Telemetry.Helpers; +// NEW: +using System.Timers; + +namespace Tango.Telemetry.Destinations +{ + /// <summary> + /// Represents a telemetry destination that publishes telemetry data to Azure IoT Hub using MQTT transport. + /// Now always batches and flushes once per second on a timer. + /// </summary> + public class TelemetryAzureHubBatchDestination : ExtendedObject, ITelemetryDestination + { + private DeviceClient _hubClient; + private int _batchSize; // kept for compatibility (no longer used for triggering sends) + private ConcurrentList<Message> _batch; + + // NEW: timer + lock to coordinate flushes + private Timer _flushTimer; + private readonly object _batchLock = new object(); + + private class ADXPAckage + { + public String Type { get; set; } + public String Environment { get; set; } + public String MachineType { get; set; } + public String SerialNumber { get; set; } + public String Organization { get; set; } + public String Site { get; set; } + public ITelemetry Telemetry { get; set; } + public DateTime UploadTime { get; set; } + public DateTime CreatedTime { get; set; } + public int Version { get; set; } + public String ToPayload() => JsonConvert.SerializeObject(this, Formatting.None); + } + + public string Name { get; set; } = "Azure IoT Hub"; + public string ConnectionString { get; private set; } + public ConnectionStatus HubConnectionStatus { get; private set; } + public IReadOnlyList<TelemetrySourceTypes> SupportedSourceTypes { get; private set; } + + /// <summary> + /// Kept for backward compatibility. Value is clamped 1..10 but not used to trigger flushes anymore. + /// </summary> + public int BatchSize { get => _batchSize; set => _batchSize = Math.Min(Math.Max(1, value), 10); } + + private TelemetryAzureHubBatchDestination() + { + _batch = new ConcurrentList<Message>(); + HubConnectionStatus = ConnectionStatus.Connected; + SupportedSourceTypes = new List<TelemetrySourceTypes>() + { + TelemetrySourceTypes.PendingStorage, + TelemetrySourceTypes.Streaming, + TelemetrySourceTypes.ExternalStorage + }; + BatchSize = 1; + } + + public TelemetryAzureHubBatchDestination(string connectionString) : this() + { + ConnectionString = connectionString; + } + + public Task<bool> IsAvailable() + { + if (InternetConnectivity.IsInternetAvailable()) + { + if (_hubClient == null) return Task.FromResult(true); + return Task.FromResult(HubConnectionStatus == ConnectionStatus.Connected); + } + return Task.FromResult(false); + } + + public Task Publish(TelemetryPublishPackage package, List<KeyValuePair<string, string>> properties) + { + if (_hubClient == null) + { + _hubClient = DeviceClient.CreateFromConnectionString(ConnectionString, TransportType.Mqtt); + _hubClient.OperationTimeoutInMilliseconds = 2000; + _hubClient.SetConnectionStatusChangesHandler((status, reason) => + { + HubConnectionStatus = status; + LogManager.Log($"IoT hub status changed to: {status}, Reason: {reason}.", LogCategory.Info); + }); + + // NEW: start the periodic flusher (every 1s) + EnsureFlushTimer(); + } + + var adxPackage = new ADXPAckage + { + Type = package.TelemetryName, + Version = package.TelemetryVersion, + Environment = package.Environment, + MachineType = package.MachineType, + SerialNumber = package.SerialNumber, + Organization = package.Organization, + Site = package.Site, + UploadTime = DateTime.UtcNow, + CreatedTime = package.PendingTelemetry.TelemetryObject.Time, + Telemetry = package.PendingTelemetry.TelemetryObject + }; + + var message = new Message(Encoding.UTF8.GetBytes(adxPackage.ToPayload())) + { + ContentType = "application/json", + ContentEncoding = "utf-8" + }; + + foreach (var prop in properties) + message.Properties.Add(prop.Key, prop.Value); + + // NEW: always enqueue; timer decides when to send + lock (_batchLock) + { + _batch.Add(message); + } + LogManager.Log("Queued telemetry message for 1s batch flush.", LogCategory.Debug); + + return Task.FromResult(true); + } + + // NEW: create the 1s timer (idempotent) + private void EnsureFlushTimer() + { + if (_flushTimer != null) return; + + _flushTimer = new Timer(1000); + _flushTimer.AutoReset = true; + _flushTimer.Elapsed += async (s, e) => + { + try + { + await FlushBatchAsync().ConfigureAwait(false); + } + catch (Exception ex) + { + // If send fails, drop connection so IsAvailable() reflects it and upstream can retry later + try { _hubClient?.Dispose(); } catch { /* ignore */ } + _hubClient = null; + LogManager.Log($"Azure IoT Hub flush failed: {ex.Message}", LogCategory.Warning); + } + }; + _flushTimer.Start(); + } + + // NEW: send whatever accumulated since last tick + private async Task FlushBatchAsync() + { + List<Message> toSend = null; + + lock (_batchLock) + { + if (_batch.Count == 0) return; + toSend = _batch.ToList(); + _batch.Clear(); + } + + LogManager.Log($"Sending telemetry batch of {toSend.Count} messages to Azure IoT Hub.", LogCategory.Debug); + await _hubClient.SendEventBatchAsync(toSend); + } + + public void Dispose() + { + // NEW: stop timer first to avoid races + if (_flushTimer != null) + { + _flushTimer.Stop(); + _flushTimer.Dispose(); + _flushTimer = null; + } + + // Flush any remaining messages synchronously + try + { + List<Message> toSend = null; + lock (_batchLock) + { + if (_batch.Count > 0) + { + toSend = _batch.ToList(); + _batch.Clear(); + } + } + if (_hubClient != null && toSend != null && toSend.Count > 0) + { + LogManager.Log($"Flushing {toSend.Count} remaining messages to Azure IoT Hub.", LogCategory.Info); + _hubClient.SendEventBatchAsync(toSend).GetAwaiter().GetResult(); + } + } + finally + { + _hubClient?.Dispose(); + } + } + + public override string ToString() => Name; + } +} diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSource.cs index 657fa83e8..a5b2da647 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSource.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSource.cs @@ -37,7 +37,7 @@ namespace Tango.Telemetry.Sources _diagnosticsQueue = new List<StartDiagnosticsResponse>(); } - public TelemetryDiagnosticsStreamingSource(IMachineOperator machineOperator) : base() + public TelemetryDiagnosticsStreamingSource(IMachineOperator machineOperator) : this() { _machineOperator = machineOperator; _machineOperator.DiagnosticsDataAvailable += DiagnosticsDataAvailable; diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSourceConfig.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSourceConfig.cs index c161ed680..032d318d9 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSourceConfig.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryDiagnosticsStreamingSourceConfig.cs @@ -13,7 +13,7 @@ namespace Tango.Telemetry.Sources public TelemetryDiagnosticsStreamingSourceConfig() { - DiagnosticsSamplingInterval = TimeSpan.FromSeconds(10); + DiagnosticsSamplingInterval = TimeSpan.FromSeconds(60); } } } diff --git a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobStatusSource.cs b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobStatusSource.cs index 93a5cc54e..9f7488909 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobStatusSource.cs +++ b/Software/Visual_Studio/Tango.Telemetry/Sources/TelemetryJobStatusSource.cs @@ -6,6 +6,8 @@ using System.Threading.Tasks; using Tango.BL.Entities; using Tango.Integration.Operation; using Tango.Telemetry.Telemetries; +// NEW: +using System.Timers; namespace Tango.Telemetry.Sources { @@ -17,6 +19,12 @@ namespace Tango.Telemetry.Sources private String _groupID; private DateTime _startTime; + // NEW: throttle state + private readonly object _lock = new object(); + private DateTime _lastStatusArrivedUtc; + private DateTime _lastEmittedUtc; + private Timer _emitTimer; // ticks every 1s + public bool IsStarted { get; private set; } public string Name { get; } = "Job Status Streaming"; public bool RequiresTelemetryDuplicationTracking { get; } @@ -34,6 +42,15 @@ namespace Tango.Telemetry.Sources { IsStarted = true; _machineOperator.PrintingStarted += MachineOperator_PrintingStarted; + + // NEW: start 1s emitter (idempotent) + if (_emitTimer == null) + { + _emitTimer = new Timer(1000); + _emitTimer.AutoReset = true; + _emitTimer.Elapsed += EmitTimer_Elapsed; + _emitTimer.Start(); + } } } @@ -43,6 +60,15 @@ namespace Tango.Telemetry.Sources { IsStarted = false; _machineOperator.PrintingStarted -= MachineOperator_PrintingStarted; + + // NEW: stop timer + if (_emitTimer != null) + { + _emitTimer.Stop(); + _emitTimer.Elapsed -= EmitTimer_Elapsed; + _emitTimer.Dispose(); + _emitTimer = null; + } } } @@ -58,70 +84,80 @@ namespace Tango.Telemetry.Sources } } - private void JobHandler_StatusChanged(object sender, RunningJobStatus status) + // NEW: timer tick — emit only the latest status observed within last 5 seconds, once per tick + private void EmitTimer_Elapsed(object sender, ElapsedEventArgs e) { - if (IsStarted) - { - TelemetryJobStatus tStatus = new TelemetryJobStatus(); + if (!IsStarted) return; - tStatus.JobName = _job?.Name; + TelemetryJobStatus toEmit = null; + DateTime now = DateTime.UtcNow; - if (status.ProgressMinusSettingUp > 0) - { - tStatus.Status = TelemetryJobStatus.JobStatus.InProgress; - } - - if (status.IsCompleted) - { - tStatus.Status = TelemetryJobStatus.JobStatus.Completed; - } - - if (status.IsFailed) + lock (_lock) + { + // Only emit if we have a newer status than last emitted, + // and that status is fresh (arrived within the last 5 seconds). + if (_lastStatus != null && + _lastStatusArrivedUtc > _lastEmittedUtc && + (now - _lastStatusArrivedUtc) <= TimeSpan.FromSeconds(5)) { - tStatus.Status = TelemetryJobStatus.JobStatus.Failed; + toEmit = _lastStatus; + _lastEmittedUtc = now; // mark emission (1 per tick max) } + } - if (status.IsCanceled) + if (toEmit != null) + { + TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs { - tStatus.Status = TelemetryJobStatus.JobStatus.Aborted; - } - - tStatus.ID = _groupID; - tStatus.TotalTime = status.TotalTime; - tStatus.RemainingTime = status.RemainingTime; - - tStatus.Progress = status.ProgressMinusSettingUp; - tStatus.TotalProgress = status.TotalProgressMinusSettingUp; + TelemetryObject = toEmit, + DisableDeliveryRetries = true + }); + } + } - tStatus.CurrentUnit = status.CurrentUnit; - tStatus.RemainingUnits = status.RemainingUnits; + private void JobHandler_StatusChanged(object sender, RunningJobStatus status) + { + if (!IsStarted) return; - tStatus.CurrentUnitProgress = status.CurrentUnitProgress; - tStatus.CurrentUnitTotalProgress = status.CurrentUnitTotalProgress; + // CHANGED: just update the latest snapshot fast; do NOT emit here. + var tStatus = new TelemetryJobStatus + { + JobName = _job?.Name, + ID = _groupID, + TotalTime = status.TotalTime, + RemainingTime = status.RemainingTime, + Progress = status.ProgressMinusSettingUp, + TotalProgress = status.TotalProgressMinusSettingUp, + CurrentUnit = status.CurrentUnit, + RemainingUnits = status.RemainingUnits, + CurrentUnitProgress = status.CurrentUnitProgress, + CurrentUnitTotalProgress = status.CurrentUnitTotalProgress, + Message = status.Message + }; - tStatus.Message = status.Message; + if (status.ProgressMinusSettingUp > 0) tStatus.Status = TelemetryJobStatus.JobStatus.InProgress; + if (status.IsCompleted) tStatus.Status = TelemetryJobStatus.JobStatus.Completed; + if (status.IsFailed) tStatus.Status = TelemetryJobStatus.JobStatus.Failed; + if (status.IsCanceled) tStatus.Status = TelemetryJobStatus.JobStatus.Aborted; + lock (_lock) + { _lastStatus = tStatus; - - TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs() - { - TelemetryObject = tStatus, - DisableDeliveryRetries = true - }); + _lastStatusArrivedUtc = DateTime.UtcNow; } } private void JobHandler_Failed(object sender, Exception e) { - if (_lastStatus != null) + // CHANGED: update the latest snapshot and let the timer emit it (within ~1s) + lock (_lock) { - _lastStatus.Message = e.FlattenMessage(); - - TelemetryAvailable?.Invoke(this, new TelemetryAvailableEventArgs() + if (_lastStatus != null) { - TelemetryObject = _lastStatus, - DisableDeliveryRetries = true - }); + _lastStatus.Message = e.FlattenMessage(); + _lastStatus.Status = TelemetryJobStatus.JobStatus.Failed; + _lastStatusArrivedUtc = DateTime.UtcNow; + } } } diff --git a/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj b/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj index 611734724..dc61f443d 100644 --- a/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj +++ b/Software/Visual_Studio/Tango.Telemetry/Tango.Telemetry.csproj @@ -242,6 +242,7 @@ </Reference> </ItemGroup> <ItemGroup> + <Compile Include="Destinations\TelemetryAzureHubBatchDestination.cs" /> <Compile Include="Helpers\DateTimeUTCFixer.cs" /> <Compile Include="Destinations\TelemetryAzureHubDestination.cs" /> <Compile Include="ExtensionMethods\ITelemetryExtensions.cs" /> diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs index aa50041ca..ab0ff2b58 100644 --- a/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs +++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryLiteDBStorageManager.cs @@ -56,23 +56,13 @@ namespace Tango.Telemetry Directory.CreateDirectory(Path.GetDirectoryName(DatabasePath)); - String backupPath = DatabasePath + ".bak"; - if (!File.Exists(DatabasePath)) { - if (File.Exists(backupPath)) - { - LogManager.Log("Telemetry database missing. Attempting to restore from backup.", LogCategory.Error); - File.Copy(backupPath, DatabasePath, overwrite: true); - } - else - { - LogManager.Log("Telemetry database was not found. A new one will be created and source checkpoints will be recovered from the remote service if required.", LogCategory.Critical); + LogManager.Log("Telemetry database was not found. A new one will be created and source checkpoints will be recovered from the remote service if required.", LogCategory.Critical); - if (_checkpointsRecoveryClient == null && EnableCheckPointsRecovery && EnforceCheckpointsRecovery) - { - throw new NullReferenceException("No TelemetryCheckpointsRecoveryClient was introduced. Telemetry Storage manager should not operate."); - } + if (_checkpointsRecoveryClient == null && EnableCheckPointsRecovery && EnforceCheckpointsRecovery) + { + throw new NullReferenceException("No TelemetryCheckpointsRecoveryClient was introduced. Telemetry Storage manager should not operate."); } } diff --git a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs index ceb405a4e..07ef8061e 100644 --- a/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs +++ b/Software/Visual_Studio/Tango.Telemetry/TelemetryPublisherConfiguration.cs @@ -42,7 +42,7 @@ namespace Tango.Telemetry /// <summary> /// Maximum number of telemetry packages allowed in memory queues before rejecting new packages. /// </summary> - public int MaxPendingTelemetries { get; set; } = 200; + public int MaxPendingTelemetries { get; set; } = 10000; /// <summary> /// Whether exponential backoff should be applied to retry logic per destination. diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 41266cda5..a46732956 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -746,40 +746,40 @@ namespace Tango.MachineService.Controllers } //Send Jobs - if (request.RequestJobs) - { - var jobs = new JobsCollectionBuilder(db).Set(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(request.MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildList(); + //if (request.RequestJobs) + //{ + // var jobs = new JobsCollectionBuilder(db).Set(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(request.MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildList(); - foreach (var job in jobs) - { - JobDTO dto = JobDTO.FromObservable(job); - response.Jobs.Add(dto); - } - } + // foreach (var job in jobs) + // { + // JobDTO dto = JobDTO.FromObservable(job); + // response.Jobs.Add(dto); + // } + //} //Send Job Runs - if (request.RequestJobRuns) - { - var jobRuns = db.JobRuns.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToList(); + //if (request.RequestJobRuns) + //{ + // var jobRuns = db.JobRuns.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToList(); - foreach (var jobRun in jobRuns) - { - JobRunDTO dto = JobRunDTO.FromObservable(jobRun); - response.JobRuns.Add(dto); - } - } + // foreach (var jobRun in jobRuns) + // { + // JobRunDTO dto = JobRunDTO.FromObservable(jobRun); + // response.JobRuns.Add(dto); + // } + //} //Send Machine Events - if (request.RequestMachineEvents) - { - var machineEvents = db.MachinesEvents.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToList(); + //if (request.RequestMachineEvents) + //{ + // var machineEvents = db.MachinesEvents.Where(x => x.MachineGuid == machine.Guid && !x.IsSynchronized).Take(request.MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToList(); - foreach (var machineEvent in machineEvents) - { - MachinesEventDTO dto = MachinesEventDTO.FromObservable(machineEvent); - response.MachineEvents.Add(dto); - } - } + // foreach (var machineEvent in machineEvents) + // { + // MachinesEventDTO dto = MachinesEventDTO.FromObservable(machineEvent); + // response.MachineEvents.Add(dto); + // } + //} //Send DataStore Items if (request.RequestDataStoreItems) diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj index e9c766c5d..39d815e9d 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj +++ b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj @@ -82,6 +82,13 @@ <HintPath>..\..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.3\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath> </Reference> <Reference Include="Microsoft.CSharp" /> + <Reference Include="Microsoft.Data.Edm, Version=5.8.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.Edm.5.8.5\lib\net40\Microsoft.Data.Edm.dll</HintPath> + <SpecificVersion>False</SpecificVersion> + </Reference> + <Reference Include="Microsoft.Data.OData, Version=5.8.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\Microsoft.Data.OData.5.8.5\lib\net40\Microsoft.Data.OData.dll</HintPath> + </Reference> <Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=5.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.5.0.5\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath> </Reference> @@ -224,6 +231,9 @@ <Reference Include="System.Numerics" /> <Reference Include="System.Runtime, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> <Reference Include="System.Security" /> + <Reference Include="System.Spatial, Version=5.8.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> + <HintPath>..\..\packages\System.Spatial.5.8.5\lib\net40\System.Spatial.dll</HintPath> + </Reference> <Reference Include="System.Transactions" /> <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <HintPath>..\..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath> diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Web.config b/Software/Visual_Studio/Web/Tango.MachineService/Web.config index 85260c32c..d9c0a6bdd 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Web.config +++ b/Software/Visual_Studio/Web/Tango.MachineService/Web.config @@ -176,7 +176,7 @@ </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" /> + <bindingRedirect oldVersion="0.0.0.0-5.8.5.0" newVersion="5.8.5.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.Services.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" /> @@ -184,7 +184,7 @@ </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" /> - <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" /> + <bindingRedirect oldVersion="0.0.0.0-5.8.5.0" newVersion="5.8.5.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Security.Cryptography.Algorithms" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> @@ -206,6 +206,10 @@ <assemblyIdentity name="Z.EntityFramework.Extensions" publicKeyToken="59b66d028979105b" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-4.0.50.0" newVersion="4.0.50.0" /> </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Spatial" publicKeyToken="31bf3856ad364e35" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-5.8.5.0" newVersion="5.8.5.0" /> + </dependentAssembly> </assemblyBinding> </runtime> <system.codedom> diff --git a/Software/Visual_Studio/Web/Tango.MachineService/packages.config b/Software/Visual_Studio/Web/Tango.MachineService/packages.config index a944a6267..430a39226 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/packages.config +++ b/Software/Visual_Studio/Web/Tango.MachineService/packages.config @@ -31,6 +31,8 @@ <package id="Microsoft.Azure.Devices.Shared" version="1.30.3" targetFramework="net461" /> <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.3" targetFramework="net45" /> <package id="Microsoft.CSharp" version="4.7.0" targetFramework="net461" /> + <package id="Microsoft.Data.Edm" version="5.8.5" targetFramework="net461" /> + <package id="Microsoft.Data.OData" version="5.8.5" targetFramework="net461" /> <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="5.0.5" targetFramework="net461" /> <package id="Microsoft.Net.Compilers" version="2.4.0" targetFramework="net46" developmentDependency="true" /> <package id="Microsoft.Owin" version="4.2.2" targetFramework="net461" /> @@ -47,6 +49,7 @@ <package id="System.Data.SQLite.Core" version="1.0.108.0" targetFramework="net46" /> <package id="System.Data.SQLite.EF6" version="1.0.108.0" targetFramework="net46" /> <package id="System.Data.SQLite.Linq" version="1.0.108.0" targetFramework="net46" /> + <package id="System.Spatial" version="5.8.5" targetFramework="net461" /> <package id="System.ValueTuple" version="4.5.0" targetFramework="net461" /> <package id="Twilio" version="7.6.0" targetFramework="net461" /> <package id="WebGrease" version="1.5.2" targetFramework="net45" /> |
