Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions MTConnect.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-AgentModule-HttpServer", "agent\Modules\MTConnect.NET-AgentModule-HttpServer\MTConnect.NET-AgentModule-HttpServer.csproj", "{7025F1F6-F914-4830-8171-30872F184918}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-AgentModule-ShdrAdapter", "agent\Modules\MTConnect.NET-AgentModule-ShdrAdapter\MTConnect.NET-AgentModule-ShdrAdapter.csproj", "{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-AgentModule-WebUI", "agent\Modules\MTConnect.NET-AgentModule-WebUI\MTConnect.NET-AgentModule-WebUI.csproj", "{0443E446-52DA-4812-B8BD-F2555B5AD7C8}"
EndProject
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MTConnect.NET-AdapterModule-MQTT", "adapter\Modules\MTConnect.NET-AdapterModule-MQTT\MTConnect.NET-AdapterModule-MQTT.csproj", "{BEBFD8B9-5448-49F9-BC92-C98564AA7C72}"
EndProject
Expand Down Expand Up @@ -336,13 +338,21 @@ Global
{7025F1F6-F914-4830-8171-30872F184918}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7025F1F6-F914-4830-8171-30872F184918}.Release|Any CPU.Build.0 = Release|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Docker|Any CPU.ActiveCfg = Debug|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Docker|Any CPU.ActiveCfg = Debug|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Docker|Any CPU.Build.0 = Debug|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Docker|Any CPU.Build.0 = Debug|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Package|Any CPU.ActiveCfg = Package|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Package|Any CPU.ActiveCfg = Package|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Package|Any CPU.Build.0 = Package|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Package|Any CPU.Build.0 = Package|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E}.Release|Any CPU.Build.0 = Release|Any CPU
{0443E446-52DA-4812-B8BD-F2555B5AD7C8}.Release|Any CPU.Build.0 = Release|Any CPU
{BEBFD8B9-5448-49F9-BC92-C98564AA7C72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEBFD8B9-5448-49F9-BC92-C98564AA7C72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEBFD8B9-5448-49F9-BC92-C98564AA7C72}.Docker|Any CPU.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -552,6 +562,7 @@ Global
{2104A3F5-A157-4763-8B90-38CD103D93D8} = {0F01D2F5-0CFA-4DAE-A0FD-5733D291F6FB}
{7025F1F6-F914-4830-8171-30872F184918} = {0F01D2F5-0CFA-4DAE-A0FD-5733D291F6FB}
{B6AAE7CE-AEBF-4F1A-929F-01665E85109E} = {0F01D2F5-0CFA-4DAE-A0FD-5733D291F6FB}
{0443E446-52DA-4812-B8BD-F2555B5AD7C8} = {0F01D2F5-0CFA-4DAE-A0FD-5733D291F6FB}
{BEBFD8B9-5448-49F9-BC92-C98564AA7C72} = {494ACCF3-8FB7-429D-9119-92F7DD646B5F}
{D2125645-0149-4D2D-BBF6-5E36E6EBB6C1} = {494ACCF3-8FB7-429D-9119-92F7DD646B5F}
{B4A1AFBE-5D57-45BA-B735-A2C2C20A971C} = {B7CCD58C-A3F3-43BE-BBF8-2B20D118C39D}
Expand Down
3 changes: 3 additions & 0 deletions agent/MTConnect.NET-Agent/agent.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ processors:
# - Modules -
modules:

- web-ui: # - Add Web UI module (browse data and edit this configuration at http://localhost:5080)
port: 5080

- http-server: # - Add HTTP Server module
port: 5000
indentOutput: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<ProjectReference Include="..\Modules\MTConnect.NET-AgentModule-MqttBroker\MTConnect.NET-AgentModule-MqttBroker.csproj" />
<ProjectReference Include="..\Modules\MTConnect.NET-AgentModule-MqttRelay\MTConnect.NET-AgentModule-MqttRelay.csproj" />
<ProjectReference Include="..\Modules\MTConnect.NET-AgentModule-ShdrAdapter\MTConnect.NET-AgentModule-ShdrAdapter.csproj" />
<ProjectReference Include="..\Modules\MTConnect.NET-AgentModule-WebUI\MTConnect.NET-AgentModule-WebUI.csproj" />
<ProjectReference Include="..\Processors\MTConnect.NET-AgentProcessor-Python\MTConnect.NET-AgentProcessor-Python.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# - Modules -
modules:

# - web-ui: # - Add Web UI module (browse data and edit this configuration at http://localhost:5080)
# server: localhost
# port: 5080
# allowConfigurationEdit: true

- http-server: # - Add HTTP Server module
# hostname: localhost
port: 5000
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<TargetFrameworks>net8.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<TargetFrameworks>net461;net462;net47;net471;net472;net48;netstandard2.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<DebugSymbols>false</DebugSymbols>
<DebugType>None</DebugType>
<Optimize>true</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Package'">
<TargetFrameworks>net461;net462;net47;net471;net472;net48;netstandard2.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
<Optimize>true</Optimize>
</PropertyGroup>

<PropertyGroup>
<RootNamespace>MTConnect</RootNamespace>
<Configurations>Debug;Release;Package</Configurations>

<Description>MTConnect.NET-AgentModule-WebUI hosts a lightweight browser user interface for the MTConnectAgentApplication class in the MTConnect.NET-Applications-Agents library. It lets a user browse Devices, current and sampled Observations, and Assets, and edit the Agent configuration file. Supports .NET Framework 4.6.1 up to .NET 10</Description>
<PackageReadmeFile>README-Nuget.md</PackageReadmeFile>

<!-- Optional: Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>

<!-- Optional: Embed source files that are not tracked by the source control manager in the PDB -->
<EmbedUntrackedSources>true</EmbedUntrackedSources>

<!-- Optional: Build symbol package (.snupkg) to distribute the PDB containing Source Link -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Package'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\libraries\MTConnect.NET-Common\MTConnect.NET-Common.csproj" />
</ItemGroup>

<ItemGroup>
<!-- The UI page ships inside the assembly so the module has no files to deploy alongside it -->
<EmbeddedResource Include="wwwroot\index.html" LogicalName="MTConnect.WebUI.index.html" />
<!-- Roboto / Roboto Mono (SIL OFL 1.1, see wwwroot\fonts\LICENSE-*.txt) so the UI works without internet access -->
<EmbeddedResource Include="wwwroot\fonts\*.woff2" LogicalName="MTConnect.WebUI.fonts.%(Filename)%(Extension)" />
<None Include="wwwroot\fonts\LICENSE-*.txt">
<Pack>True</Pack>
<PackagePath>\licenses\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<None Include="README-Nuget.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="../../../img/package-icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

</Project>
78 changes: 78 additions & 0 deletions agent/Modules/MTConnect.NET-AgentModule-WebUI/Module.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) 2026 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.

using MTConnect.Agents;
using MTConnect.Configurations;
using MTConnect.Logging;

namespace MTConnect.Modules.WebUI
{
/// <summary>
/// Agent module that hosts a browser user interface for the Agent.
/// The UI lets a user browse Devices, current / sampled Observations
/// and Assets, and view or edit the Agent configuration file.
/// </summary>
public class Module : MTConnectAgentModule
{
/// <summary>
/// Token used in <c>agent.config.yaml</c> to bind this module
/// (<c>- web-ui:</c>).
/// </summary>
public const string ConfigurationTypeId = "web-ui";
private const string ModuleId = "Web UI";

private readonly WebUiModuleConfiguration _configuration;
private WebUiServer _server;


/// <summary>
/// Initialises the module and binds the supplied controller-
/// configuration payload to <see cref="WebUiModuleConfiguration"/>.
/// </summary>
/// <param name="mtconnectAgent">Agent broker the UI reads from.</param>
/// <param name="controllerConfiguration">Raw configuration payload
/// bound to <see cref="WebUiModuleConfiguration"/>.</param>
public Module(IMTConnectAgentBroker mtconnectAgent, object controllerConfiguration) : base(mtconnectAgent)
{
Id = ModuleId;

_configuration = AgentApplicationConfiguration.GetConfiguration<WebUiModuleConfiguration>(controllerConfiguration);
if (_configuration == null) _configuration = new WebUiModuleConfiguration();
}


/// <summary>
/// Module lifecycle hook: creates the UI web server before the Agent
/// loads its devices so the per-Device Observation counts include
/// the Observations added while the devices initialize.
/// </summary>
/// <param name="initializeDataItems">Inherited flag; unused by
/// this module.</param>
protected override void OnStartBeforeLoad(bool initializeDataItems)
{
_server = new WebUiServer(_configuration, Agent);
}

/// <summary>
/// Module lifecycle hook: starts the UI web server once the Agent
/// has loaded its devices.
/// </summary>
/// <param name="initializeDataItems">Inherited flag; unused by
/// this module.</param>
protected override void OnStartAfterLoad(bool initializeDataItems)
{
if (_server == null) _server = new WebUiServer(_configuration, Agent);
_server.LogReceived += (s, message) => Log(MTConnectLogLevel.Information, message);
_server.ErrorReceived += (s, message) => Log(MTConnectLogLevel.Warning, message);
_server.Start();
}

/// <summary>
/// Module lifecycle hook: stops the UI web server.
/// </summary>
protected override void OnStop()
{
if (_server != null) _server.Stop();
}
}
}
34 changes: 34 additions & 0 deletions agent/Modules/MTConnect.NET-AgentModule-WebUI/README-Nuget.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
![MTConnect.NET Logo](https://raw.githubusercontent.com/TrakHound/MTConnect.NET/master/img/logo.png)

# MTConnect Web UI Agent Module
This Agent Module hosts a browser user interface for the MTConnect.NET Agent. It can be used to:

* View Agent information and buffer state
* Browse Devices / Components and their current Observations (with auto refresh)
* View the recent history of any Data Item
* Browse Assets and view them as MTConnectAssets XML
* View and edit the Agent configuration file (`agent.config.yaml`)

## Configuration
```yaml
modules:
- web-ui:
server: localhost
port: 5080
allowConfigurationEdit: true
```

* `server` - The hostname to bind to. Defaults to `localhost` so the UI is only reachable from the Agent machine. Set to `*` to listen on all interfaces (on Windows this requires administrator rights or a `netsh http add urlacl` reservation).

* `port` - The port the UI listens on. Default is `5080`.

* `allowConfigurationEdit` - Sets whether the Agent configuration file can be saved from the UI. Default is `true`. When `false` the configuration is shown read-only.

Open `http://localhost:5080/` in a browser once the Agent is running.

The page and its fonts (Roboto and Roboto Mono, licensed under the SIL Open Font License 1.1) are embedded in the module assembly, so the UI makes no requests outside the Agent and works on networks without internet access.

## Applying configuration changes
Saving validates the YAML, keeps a copy of the previous file as `agent.config.yaml.bak`, and writes the new file. When `monitorConfigurationFiles` is enabled (the default) the Agent detects the change and restarts itself to apply it; otherwise restart the Agent manually.

> **Security** - The UI has no authentication. Anyone who can reach it can change the Agent configuration. Keep `server: localhost` or set `allowConfigurationEdit: false` when exposing it on a network.
34 changes: 34 additions & 0 deletions agent/Modules/MTConnect.NET-AgentModule-WebUI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
![MTConnect.NET Logo](https://raw.githubusercontent.com/TrakHound/MTConnect.NET/master/img/logo.png)

# MTConnect Web UI Agent Module
This Agent Module hosts a browser user interface for the MTConnect.NET Agent. It can be used to:

* View Agent information and buffer state
* Browse Devices / Components and their current Observations (with auto refresh)
* View the recent history of any Data Item
* Browse Assets and view them as MTConnectAssets XML
* View and edit the Agent configuration file (`agent.config.yaml`)

## Configuration
```yaml
modules:
- web-ui:
server: localhost
port: 5080
allowConfigurationEdit: true
```

* `server` - The hostname to bind to. Defaults to `localhost` so the UI is only reachable from the Agent machine. Set to `*` to listen on all interfaces (on Windows this requires administrator rights or a `netsh http add urlacl` reservation).

* `port` - The port the UI listens on. Default is `5080`.

* `allowConfigurationEdit` - Sets whether the Agent configuration file can be saved from the UI. Default is `true`. When `false` the configuration is shown read-only.

Open `http://localhost:5080/` in a browser once the Agent is running.

The page and its fonts (Roboto and Roboto Mono, licensed under the SIL Open Font License 1.1) are embedded in the module assembly, so the UI makes no requests outside the Agent and works on networks without internet access.

## Applying configuration changes
Saving validates the YAML, keeps a copy of the previous file as `agent.config.yaml.bak`, and writes the new file. When `monitorConfigurationFiles` is enabled (the default) the Agent detects the change and restarts itself to apply it; otherwise restart the Agent manually.

> **Security** - The UI has no authentication. Anyone who can reach it can change the Agent configuration. Keep `server: localhost` or set `allowConfigurationEdit: false` when exposing it on a network.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2026 TrakHound Inc., All Rights Reserved.
// TrakHound Inc. licenses this file to you under the MIT license.

namespace MTConnect.Configurations
{
/// <summary>
/// Configuration shape for the Web UI agent module. Controls the
/// address the UI listens on and whether the Agent configuration
/// file may be edited from the browser.
/// </summary>
public class WebUiModuleConfiguration
{
/// <summary>
/// The hostname the UI binds to. Defaults to <c>localhost</c> so the
/// UI (and its configuration editor) is only reachable from the
/// machine the Agent runs on. Use <c>*</c> or <c>+</c> to listen on
/// every interface (may require elevated permissions on Windows).
/// </summary>
public string Server { get; set; }

/// <summary>
/// The port the UI listens on.
/// </summary>
public int Port { get; set; }

/// <summary>
/// Gets or Sets whether the Agent configuration file can be edited
/// and saved from the UI. When <c>false</c> the configuration is
/// shown read-only.
/// </summary>
public bool AllowConfigurationEdit { get; set; }


/// <summary>
/// Initialises a new instance bound to <c>localhost:5080</c> with
/// configuration editing enabled.
/// </summary>
public WebUiModuleConfiguration()
{
Server = "localhost";
Port = 5080;
AllowConfigurationEdit = true;
}
}
}
Loading
Loading