Giter VIP home page Giter VIP logo

trakhound / mtconnect.net Goto Github PK

View Code? Open in Web Editor NEW
93.0 93.0 36.0 8.6 MB

Fully featured .NET library in C# to build MTConnect Agent, Adapter, and Client Applications. Pre-built Agents with Windows Installers. Support for Windows and Linux. Supports MTConnect Versions up to 2.3. Supports .NET Framework 4.6.1 up to .NET 8

Home Page: http://www.TrakHound.com

License: MIT License

C# 99.90% Inno Setup 0.10%
adapter agent csharp dotnet iiot industry40 manufacturing mqtt mtconnect trakhound vbnet

mtconnect.net's People

Contributors

m2rtviljaste avatar patrickritchie avatar sergiigulyk avatar victoririzarx3d avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mtconnect.net's Issues

Loader Exceptions after upgrade from 3.0.1

Hi

I updated library from 3.0.1 to 3.2 version and I writed the follow c# code into my existing project:

var Client= new MTConnectCurrentClient(@"10.0.0.204:8040", "NH802HB0002"); if (current != null) { var document = Client.Get(); } Client.OnInternalError += Errore;

On Client.Get() one internal error occured with two exceptions (italian language):

Il metodo 'AuthenticateAsync' del tipo 'Microsoft.AspNetCore.Http.Authentication.Internal.DefaultAuthenticationManager' dell'assembly 'Microsoft.AspNetCore.Http, Version=2.2.2.0, Culture=neutral, PublicKeyToken=adb9793829ddae60' non ha un'implementazione.

Non è stato possibile caricare il tipo 'Microsoft.AspNetCore.Http.Features.Authentication.ChallengeBehavior' dall'assembly 'Microsoft.AspNetCore.Http.Features, Version=5.0.15.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.

If I create a new Visual Studio project the error does not occur.

What happen?
Is there any conflict with the dependencies of the other nuget packages?

Thanks
Tomaso

ObservationInput.ChangeId not unique.

Different DataItems have the same ChangeId. It appears that the ChangeId is calcuated from ObservationInput.Values, in which case, the values for both of these observations are the same.

image

image

image

Problems with multi-threaded initialization of type ids

Hi Patrick

Long time since I wrote you the last time :)
I see that development is going on. Thank you for your work!

However, I want to complain about minor, but annoying, bug with _typeIds creation
If you go to e.g. DataItem.cs
image
you will see that adding new type id is protected by the lock.
Not the case for ConditionObservation.cs, EventObservation.cs, SampleObservation.cs
image
Could you please add the same protection for these three and release it in 5.4.x as well?
I am ready to make a PR myself, but I am not sure where is the tip of the stable 5.4.x version.

Best wishes,
Sergii

Component hierarchy from devices.xml is lost

Hi Patrick,

At the moment when probe arrives all components are placed on the first level of hierarchy.
image
So the structure is lost. I cannot figure out who is child of whom.
I found that you was trying to track hierarchy in public void AssignTypePaths(), but completely commented out this code in 0e50b3b
Instead of just fixing component hierarchy I decided to ask what are your thoughts/ideas? How you saw it implemented?

Best regards,
Sergii

Questions about ShdrClient implementation

Hi @PatrickRitchie,

I am investigating a bug when ShdrClient constantly disconnects and reconnects to our machine. I found a few suspicious places in the ShdrClient implementation and I would like to discuss and confirm if they are bugs with you before actually proceed with further actions.

The first potential issue is with ShdrClient.ProcessResponse method. It assumes that incoming char buffer always contains full data strings delimited with \n. But what if read from stream happens in the middle of receiving and you get in the buffer partial data string? The "end" of the string come only with next buffer and next char array. I do not see that this case is handled and from what I see partial chunk is non processed in current chunk and the "end" is not processed in next chunk. So one line is dropped and we have data loss.
In case of complete unluckness with timings and small amount of data you can potentially have a lot or even all data items corrupted
So the question is: why are you sure that the situation cannot happen?

The second potential issue is on line 276 of ShdrClient:

image

In case when DataAvailable and data is read from the stream you still delay further processing by 1 millisecond. I assume that if a machine sends too much data or too often it can lead to the stream buffer overflow as code will not be able to process data fast enough.

I would expect to have Thread.Sleep(1) under line 273 inside of else statement to have "Process data as fast as possible, wait one millisecond otherwise".

The probability of the issue is very low as thread block is only 1 millisecond, machines usually do not send so much data and read buffer is big enough.

AgentConfiguration.Read ignores path argument

Hi @PatrickRitchie

We are testing now the agent implementation on v6.4.0 and we are realizing that the agent is ignoring the configuration path we are providing via the CLI arguments and always falling back to the default configuration

We are testing on Ubuntu 20.04, and built the v6.4.0 branch using dotnet publish -c:Debug -r:linux-x64 -f:net8.0 -o:dist --sc

We run the agent with ./mtconnect_dotnet_agent /home/user/data/state/mt_connect/agent.config.yaml

The custom config on the path we specify is a copy of the default agent configuration with a couple of minor changes

And this is the log output we get, Notice how it chooses the default configuration on /usr/local/mtconnect_dotnet_agent/agent.config.yaml although we would expect to use the one passed in the CLI argument

--------------------
Copyright 2024 TrakHound Inc., All Rights Reserved
MTConnect.NET Agent : Version 6.4.0.0
--------------------
This application is licensed under the MIT License (https://choosealicense.com/licenses/mit/)
Source code available at Github.com (https://github.com/TrakHound/MTConnect.NET)
--------------------
2024-05-16 02:46:56.4109|INFO|application|Agent Configuration Path = /home/user/data/state/mt_connect/agent.config.yaml
2024-05-16 02:46:56.4979|INFO|application|Configuration File Read Successfully from: /usr/local/mtconnect_dotnet_agent/agent.config.yaml

Looking a bit deeper into the code, the MTConnectAgentAppllication uses the AgentConfiguration.Read method to read the configuration file passed from the CLI arguments

// Read Command Line Arguments
if (!args.IsNullOrEmpty())
{
command = args[0];
// Configuration File Path
if (args.Length > 1)
{
configFile = args[1];
_applicationLogger.Info($"Agent Configuration Path = {configFile}");
}
}

// Read the Agent Configuation File
var configuration = _initialAgentConfiguration;
if (configuration == null)
{
configuration = OnConfigurationFileRead(configFile);
if (configuration != null) _applicationLogger.Info($"Configuration File Read Successfully from: {configuration.Path}");
}

protected virtual IAgentApplicationConfiguration OnConfigurationFileRead(string configurationPath)
{
// Read the Configuration File
return AgentConfiguration.Read<AgentApplicationConfiguration>(configurationPath);
}

The AgentConfiguration.Read method, however, ignores the passed path and always constructs a default configuration file

public static T Read<T>(string path = null) where T : AgentConfiguration
{
var jsonPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, JsonFilename);
// Test for JSON Configuration File
if (File.Exists(jsonPath)) return ReadJson<T>(jsonPath);
else
{
var yamlPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, YamlFilename);
return ReadYaml<T>(yamlPath);
}
}
public static AgentConfiguration Read(Type type, string path = null)
{
var jsonPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, JsonFilename);
// Test for JSON Configuration File
if (File.Exists(jsonPath)) return ReadJson(type, jsonPath);
else
{
var yamlPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, YamlFilename);
return ReadYaml(type, yamlPath);
}
}

Receiving Category information with Flat topic mode

I'm using the Flat topic mode due to level limitation in AWS IoT Core.
By doing that I'm losing important information that i would like to get as part of each message - Category (Event/Sample/..). It would be great to keep getting this information also on the flat topic mode. Another option could be to get this as part of the payload - but currently the Json formatter skips the Category when creating the payload out of the observation:
return CreateMessage(topic, Formatters.EntityFormatter.Format(documentFormatterId, observation));

Related to a discussion in issue #42

SHDR: Empty string handling

Event with empty string is removed from SHDR stream, but leaves extra pipe. Replacing empty string with a blank space restores the data item in stream.

image

image

image

Heartbeat logic for shdr-adapter prevents correct syncronization with adapters

Hi @PatrickRitchie

I found an issue with the shdr-adapter on v6.4.1. Tested on Ubuntu 20.04

I have an adapter running locally on port 7878 for my device data. The shdr-adapter module configuration on the agent looks like this

- shdr-adapter:
    deviceKey: H350
    hostname: localhost
    port: 7878

I keep noticing that the adapter connects and disconnects at fixed intervals.

The agent logs show this every 30 seconds more or less

2024-07-31 15:55:24.5688|DEBUG|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : Listening for connection from localhost on Port 7878
2024-07-31 15:55:24.5688|INFO|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : Connected to Adapter at localhost on Port 7878
2024-07-31 15:55:24.5688|DEBUG|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : Initial PING sent to : localhost on Port 7878
2024-07-31 15:55:24.5806|DEBUG|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : PONG Received from : localhost on Port 7878 : Heartbeat = 10000ms
2024-07-31 15:55:54.5544|DEBUG|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : PING sent to : localhost on Port 7878
2024-07-31 15:56:04.5556|DEBUG|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : Unable to write data to the transport connection: Broken pipe.
2024-07-31 15:56:04.5556|INFO|modules.shdr-adapter|ID = adapter_shdr_56697b5624 : Disconnected from localhost on Port 7878

On my adapter side what I notice is that the heartbeat thread keeps timing out. From the logs you can see that the time measured between the agent receiving the PONG response to the time it tries to send the PING is 30 secs. The default timeout is 10000 ms so the adapter is waiting at most 20 seconds, therefore it times out and closes the socket, which then triggers the disconnection on the agent side because it is trying to write the PING on a closed socket

I tried to change the timeout on the agent side but still it was always sending the PING late

Looking at the code I found that the logic controlling the sending of the PING is preventing the round trip of the heartbeat to be successful because it is sending only data when the difference between the last message and the current time is larger than the timeout value AND when the difference between the last heartbeat and current time is larger than the timeout value. This makes the sending of the PING dependable on the message timing. Changing the condition to OR solves the issue

// Send PING Heartbeat if needed
if ((now - lastResponse) > heartbeat * 10000 && (now - _lastHeartbeat) > heartbeat * 10000)
{
messageBytes = Encoding.ASCII.GetBytes(PingMessage);
stream.Write(messageBytes, 0, messageBytes.Length);
PingSent?.Invoke(this, $"PING sent to : {Hostname} on Port {Port}");
_lastHeartbeat = now;
}

Making the agent honor the timeout value coming from the adapter

On the MTConnect adapter agent protocol docs it is stated that the agent should honor the adapter's timeout value once it receives a correct PONG response

The agent and the adapter have a heartbeat that makes sure each is responsive to properly handle disconnects in a timely manner. The Heartbeat frequency is set by the adapter and honored by the agent. When the agent connects to the adapter, it first sends a * PING and then expects the response * PONG where is specified in milliseconds

Currently the agent just checks that the PING text matches the pattern, parses the timeout integer, and logs the value. I have made some changes to add heartbeat as a class member that is defaulted to 10000 and, if the PONG response is correct, parse the timeout value and update the heartbeat member it and use it where needed.

I can create a PR for all of the above if it suits

Using the MQTT-Relay agent to send data to MQTT Broker with client certificate/key

I'm using the MQTT-Relay agent to read massages from a device (SHDR) and publish them to Greengrass' MQTT Broker (moquette), in order for them to end up in AWS IoT Core. Since there's a client authentication, the massage publishing is failing due to an authentication error. Is there a way to configure the client side certificates/key?

I couldn't find an option to work with Client certificate and a private key also by changing the code, but I did try the following code change to include client pfx certificate with a password. Running this resulted in an error as you can see below.
Any idea or suggestion how to enable working against the Greengrass MQTT?

                            if (string.IsNullOrEmpty(_configuration.MqttCert) || string.IsNullOrEmpty(_configuration.MqttCaCert))
                            {
                                mqttClientOptions = new MqttClientOptionsBuilder()
                                .WithTcpServer(_configuration.Server, _configuration.Port)
                                .Build();
                            }
                            else
                            {
                                var caCert = new X509Certificate2(_configuration.MqttCaCert);
                                var clientCert = new X509Certificate2(_configuration.MqttCert, _configuration.MqttCertPwd); 

                                mqttClientOptions = new MqttClientOptionsBuilder()
                                .WithTcpServer(_configuration.Server, _configuration.Port)
                                .WithClientId(_configuration.MqttClientId)
                                .WithTls(new MqttClientOptionsBuilderTlsParameters
                                {
                                    UseTls = true,
                                    //AllowUntrustedCertificates = true,
                                    SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
                                    Certificates = new List<X509Certificate> { caCert, clientCert }                                   
                                    
                                })

                                .Build();
                            }
                        }

2023-02-19T15:47:12.113Z [INFO] (nioEventLoopGroup-17-6) io.moquette.broker.metrics.MQTTMessageLogger: Channel Inactive. {}
2023-02-19T15:47:18.024Z [ERROR] (nioEventLoopGroup-17-7) io.moquette.broker.NewNettyMQTTHandler: Unexpected exception while processing MQTT message. Closing Netty channel. CId=null. {}
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:480)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.moquette.broker.metrics.BytesMetricsHandler.channelRead(BytesMetricsHandler.java:51)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:995)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:340)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:186)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)
at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637)
at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:295)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1342)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1235)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1284)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:449)
... 25 more

ShdrAdapter - sending latest values for all DataItems on new Agent connection

Should either of these methods send the latest values of all DataItems when a new Agent comes along and connects?

/// <summary>
/// Sends all Items that have changed since last sent to the Agent
/// </summary>
public void SendChanged()
{
WriteChangedDataItems();
WriteChangedMessages();
WriteChangedConditions();
WriteChangedTimeSeries();
WriteChangedDataSets();
WriteChangedTables();
WriteChangedAssets();
// Call Overridable Method
OnChangedSent();
}
/// <summary>
/// Sends all of the last sent Items, Assets, and Devices to the Agent. This can be used upon reconnection to the Agent
/// </summary>
public void SendLast(long timestamp = 0)
{
WriteLastDataItems(timestamp);
WriteLastMessages(timestamp);
WriteLastConditions(timestamp);
WriteLastTimeSeries(timestamp);
WriteLastDataSets(timestamp);
WriteLastTables(timestamp);
WriteAllAssets();
WriteAllDevices();
// Call Overridable Method
OnLastSent();
}

Add Multiple Devices in Embedded MTConnect Agent

@PatrickRitchie this is another great development of embedded mtconnect agent. I tested it for 1 machine and it worked as expected. I was able to route Mitsubishi CNC data to MTConnect agent. But I was only able to add 1 device in the protected override IDevice OnAddDevice() function.

Please guide how can I add x number of devices.

Cultute specific XML serialization

Hi Patrick,
I have found one funny error in Xml serialization.

public class XmlFilter
{
....
        public static void WriteXml(XmlWriter writer, IFilter filter)
        {
            if (filter != null)
            {
                writer.WriteStartElement("Filter");
                writer.WriteAttributeString("type", filter.Type.ToString());
                writer.WriteString(filter.Value.ToString());<------------------
                writer.WriteEndElement();
            }
        }

Please change pointed line to
writer.WriteValue(filter.Value);
Otherwise, double value is serialized according to the local system settings.
In my case 0.5 is serialized as 0,5 :) producing invalid xml.

Best regards,
Sergii Gulyk.

Beta 6.0.11 published docker cannot be started

Thanks for keeping great work on .NET version of an agent.

I am trying out Beta branch and cannot run the latest docker variant.

Doing:

docker pull trakhound/mtconnect.net-agent:6.0.11-beta-alpine-3.18-amd64
docker run trakhound/mtconnect.net-agent:6.0.11-beta-alpine-3.18-amd64

That results into:

The command could not be loaded, possibly because:
  * You intended to execute a .NET application:
      The application 'agent.dll' does not exist.
  * You intended to execute a .NET SDK command:
      No .NET SDKs were found.

Download a .NET SDK:
https://aka.ms/dotnet/download

Learn about SDK resolution:
https://aka.ms/dotnet/sdk-not-found

If I sh into image, then i see no executables in there:

#> docker run -it --entrypoint sh trakhound/mtconnect.net-agent:6.0.11-beta-alpine-3.18-amd64
/app # ls -la
total 28
drwxr-xr-x    1 root     root          4096 Feb  2 07:38 .
drwxr-xr-x    1 root     root          4096 Mar  4 12:16 ..
-rwxr-xr-x    1 root     root           355 Feb  2 07:38 Dockerfile
-rwxr-xr-x    1 root     root          1224 Feb  2 07:38 agent.config.default.yaml
drwxr-xr-x    2 root     root          4096 Feb  2 07:38 devices
drwxr-xr-x    2 root     root          4096 Feb  2 07:38 schemas
drwxr-xr-x    2 root     root          4096 Feb  2 07:38 styles
/app # 

I am guessing image was built from wrong cwd?

NuGet 2.7.0.28439 not built from latest github code?

I am seeing behavior in the NuGet 2.7.0.28439 that suggests it is built from code that does not incorporate code from the latest github trunk, dating back at least to February.

The Probe function is not appending "/probe" to the uri. As this is apparently a change in behavior committed to trunk in Feb 2017 (for version 1.2), and it is now December, then it would appear that the NuGet code is built from a repository that is not fully in sync with the repository code.

Just FYI

MT-Connect-MQTT-Relay Example

installing MT-Connect-Mqtt-Relay Example in source code. this MT_Connect agent publish data on external Mqtt-broker
so i not know the SHDR adaper is embedded with this agent , if yes then how to configure this or not then how or which is used for this agent

config files not published

@PatrickRitchie in the latest build 6.4.3, agent.config.default.json, agent.information.json i.e., basically config files are not getting publised after building or publishing the application.

I had to add those files manually from old 6.2.2 published application.

SHDR: SetUnavailable

Expected behavior: Calling adapter.SetUnavailable should send new SHDR to Agent with value of UNAVAILABLE.
Current behavior: It does not.

DataItem before setting UNAVAILABLE.

image

DataItem after setting UNAVAILABLE.

image

Comparison in UpdateDataItem.

image

image

There are no such types as in example

// Find the first Controller component
var controller = document.Devices[0].GetComponents().Find(o => o.GetType() == typeof(MTConnectDevices.Components.Controller));

// Find DataItem by Type in the first Controller/Path component
var program = document.Devices[0].GetComponents().Find(o => o.GetType() == typeof(MTConnectDevices.Components.Path)).DataItems.Find(o => o.Type == "PROGRAM");

// Find all of the Line Types in each Controller/Path component
foreach (var path in document.Devices[0].GetComponents().FindAll(o => o.GetType() == typeof(MTConnectDevices.Components.Path)))

mqtt-relay cannot connect to broker with TLS enabled and PEM certificates

Hi @PatrickRitchie

I am having issues connecting the agent to a broker in my local network when using TLS with PEM certificates. I am testing with v6.4.1 on Ubuntu 20.04

My configuration for the mqtt-relay part of the agent looks like this

- mqtt-relay:
    QoS: 1
    allowUntrustedCertificates: true
    clientId: simulation
    currentInterval: 10000
    documentFormat: JSON
    port: 8883
    sampleInterval: 500
    server: 192.168.161.202
    tls:
      pem:
        certificateAuthority: /home/victor/venice_data/misc/certificates/gateway-SAF-Test-ID-2/GroupCACertificate.pem
        certificatePath: /home/victor/venice_data/misc/certificates/gateway-SAF-Test-ID-2/certificate.pem
        privateKeyPath: /home/victor/venice_data/misc/certificates/gateway-SAF-Test-ID-2/privateKey.pem
      verifyClientCertificate: false
    topicPrefix: MTConnect/Entity
    topicStructure: Entity

When the agent tries to connect, I get the following error on the logs

2024-06-18 03:19:10.4204|WARN|modules.mqtt-relay|MQTT Relay Connection Error : error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certifica>
2024-06-18 03:19:10.4204|WARN|modules.mqtt-relay|MQTT Relay Connection Error : Authentication failed, see inner exception.
2024-06-18 03:19:10.4204|INFO|modules.mqtt-relay|MQTT Relay Disconnected from External Broker (192.168.161.202:8883)

I am sure I can connect to the broker because using a python mqtt client with the same certificates and client ID I am able to connect without issues.

Looking into the code of the mqtt relay module I noticed that the part where we setup the certificates, the CA certificate is appended first and then we append the certificate .

// Set TLS Certificate
if (_configuration.Tls != null)
{
var certificateResults = _configuration.Tls.GetCertificate();
if (certificateResults.Success && certificateResults.Certificate != null)
{
var certificateAuthorityResults = _configuration.Tls.GetCertificateAuthority();
var certificates = new List<X509Certificate2>();
if (certificateAuthorityResults.Certificate != null)
{
certificates.Add(certificateAuthorityResults.Certificate);
}
certificates.Add(certificateResults.Certificate);

Further down in the code, however, the certificate validation handler is declared and that uses again the CA certificate for the validation.

#if NET5_0_OR_GREATER
// Setup CA Certificate
if (certificateAuthorityResults.Certificate != null)
{
tlsOptionsBuilder.WithCertificateValidationHandler((certContext) =>
{
var chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chain.ChainPolicy.VerificationTime = DateTime.Now;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);
chain.ChainPolicy.CustomTrustStore.Add(certificateAuthorityResults.Certificate);
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
// convert provided X509Certificate to X509Certificate2
var x5092 = new X509Certificate2(certContext.Certificate);
return chain.Build(x5092);
});
}
#endif

On the MQTTnet repo I cannot find exact references to how this setup is done but I imagine the CA certificate, being in that list first, will fail to validate on the broker side since it is not the "main" certificate.

As an experiment I removed the appending of the CA certificate from the certificate lists and now the relay is able to connect to the broker without an issue. Is this something that makes sense? I am not an expert on this so I might be doing something wrong.

Side notes

Exception logging

I noticed that when the agent was throwing exceptions I was seeing log lines with the following

2024-06-18 03:19:10.4204|WARN|modules.mqtt-relay|MQTT Relay Connection Error : Authentication failed, see inner exception.

When the exceptions are handled then only the last message is printed in the main connection loop, but it will not print any inner exceptions

catch (Exception ex)
{
Log(MTConnectLogLevel.Warning, $"MQTT Relay Connection Error : {ex.Message}");
}
finally
{
if (_documentServer != null) _documentServer.Stop();
}
Log(MTConnectLogLevel.Information, $"MQTT Relay Disconnected from External Broker ({_configuration.Server}:{_configuration.Port})");
await Task.Delay(_configuration.ReconnectInterval, _stop.Token);
}
catch (TaskCanceledException) { }
catch (Exception) { }

I have added some calls to exception.getBaseException() and checking for inner messages to aid on the debugging, something like

Log(MTConnectLogLevel.Warning, $"MQTT Relay Connection Error : {ex.GetBaseException().Message}")

Maybe is worth to add some of this inner exception logging or logging the full traceback?

VerifyClientCertificate option

This option allows untrusted certificates to be handled, and that is setup as expected. There are a couple of options that might be relevant to set when this parameter is set in the configuration, WithIgnoreCertificateRevocationErrors() and WithIgnoreCertificateChainErrors(). Would this be relevant?

Problem with sample stream

Hello. I apologize for my English.

I decided to share my experience of using the library. I have several devices, one of them is MTConnect 1.3, and the other is MTConnect 1.2. when using the class MTConnectClient, everything works perfectly in the case of 1.3, but there are problems with 1.2. I started getting "error in xml document (2 2)". To quickly understand this situation, I subscribed to all events output with the class and saw the error 'the interval argument to a sample request is not supported'. After that, I started searching in the source code, made sure that when calling the Start method, we really use the sample stream, but I didn't find where the error xml document (2,2) came from. Can you recommend what I should do in this case so that the code for version 1.3 and 1.2 remains the same?

Additional question. In the Namespaces class, the Clear method should completely clear the MTConnect string, leaving only MTConnectStreams?

HTTP field from client is too long - 414

Hello,

I'm experiencing issues on a client which is using your assemblies to read from MTConnect sources.
I'm not 100% sure this will be the right place to ask this, but after 1 month of troubleshooting I'm almost out of options.

The requests seem to fail because the client is sending HTTP headers too long.

This is the error on the client, which is using MTConnect 2.0:

11:16:14.772 Driver Interface: xxx Connection Error Exception: Response status code does not indicate success: 414 (HTTP field from client is too long).

This is on one of the involved MTConnect agents, configured for 2 machines.
The agent used is: https://github.com/mtconnect/cppagent. Tried different versions, 1.4, 1.8, 2.1, but XML schemas are still 1.3 because provided by machine manufacturer (and has not released any new one yet...). If necessary I can post XML schemas involved.
Version 1.4/1.8 logs:

2023-06-06T09:39:48.291499Z: ERROR [12] HttpServer: Error processing request from: 127.0.0.1 - HTTP field from client is too long
2023-06-06T09:39:48.291716Z: DEBUG [12] agent: Returning error INVALID_REQUEST: Error processing request from: 127.0.0.1 - HTTP field from client is too long

Version 2.1 logs:

2023-06-26T14:02:00.093997Z (0x00000e48) [debug] Connector::heartbeat: Sending heartbeat
2023-06-26T14:02:00.093997Z (0x00000e48) [debug] Connector::heartbeat->Connector::sendCommand: (Port:50838) Sending PING
2023-06-26T14:02:00.093997Z (0x00000e48) [debug] Connector::reader->Connector::parseSocketBuffer->Connector::processLine: (Port:50838) Received a PONG for 10.xx.xx.xx on port 7878
2023-06-26T14:02:09.359244Z (0x00000e48) [info] SessionImpl::requested: ReST Request: From [127.0.0.1:50855]: GET /probe
2023-06-26T14:02:09.378237Z (0x00000e48) [info] SessionImpl::requested: ReST Request: From [127.0.0.1:50856]: GET /current
2023-06-26T14:02:09.411237Z (0x00000e48) [warning] SessionImpl::requested->Session::fail: Operation failed: Could not read request
2023-06-26T14:02:09.411237Z (0x00000e48) [warning] SessionImpl::requested->Session::fail: Closing: header limit exceeded - header limit exceeded

Following is a longer extract of client logs.
At first values are read, then a connection exception is thrown. This happens at every data polling from MTConnect source, be it every 1 second or every 30s.

15:00:15.010 DevicesSuccessful: Driver Interface: xxx

15:00:15.037 MTConnect Data Change Values:
Spindle_Override 93
EStop_State ARMED
avail AVAILABLE
dev_asset_chg 
dev_asset_chg UNAVAILABLE
dev_asset_rem 
dev_asset_rem UNAVAILABLE
Block_Number 0
Current_Tool 0
Feed_Override 79
Part_Count 2325
Program_Name_Editing 89552-TRATT.HWM
Program_Status READY
Rapid_Override 100
Spindle_Speed 0
Feed_Rate 0
Program_Runtime_Seconds 0
Spindle_Time 0

15:00:15.100 Driver Interface: xxx Connection Error Exception: Response status code does not indicate success: 414 (HTTP field from client is too long).
15:00:24.431 MTConnect Data Change Values:
servo UNAVAILABLE
spndl UNAVAILABLE
at UNAVAILABLE
ct UNAVAILABLE
spc UNAVAILABLE
tmp UNAVAILABLE
ct2 UNAVAILABLE
spc2 UNAVAILABLE
tmp2 UNAVAILABLE
ccond UNAVAILABLE
logic UNAVAILABLE
system UNAVAILABLE
coolhealth UNAVAILABLE
electric UNAVAILABLE
hydhealth UNAVAILABLE
lube UNAVAILABLE
motion UNAVAILABLE
path_system UNAVAILABLE
pneucond UNAVAILABLE
xt UNAVAILABLE
yt UNAVAILABLE
zt UNAVAILABLE
aaxisstate UNAVAILABLE
arf UNAVAILABLE
caxisstate UNAVAILABLE
rf UNAVAILABLE
c2axisstate UNAVAILABLE
rf2 UNAVAILABLE
estop UNAVAILABLE
pltnum UNAVAILABLE
avail UNAVAILABLE
d1_asset_chg 
d1_asset_chg UNAVAILABLE
d1_asset_rem 
d1_asset_rem UNAVAILABLE
functionalmode UNAVAILABLE
door UNAVAILABLE
Sovr UNAVAILABLE
exec UNAVAILABLE
hd1chuckstate UNAVAILABLE
ln UNAVAILABLE
mode UNAVAILABLE
pc UNAVAILABLE
pcmt UNAVAILABLE
peditmode UNAVAILABLE
peditname UNAVAILABLE
pfo UNAVAILABLE
pfr UNAVAILABLE
pgm UNAVAILABLE
seq urn:mazakusa.com:MazakStreams:1.3
seq UNAVAILABLE
spcmt UNAVAILABLE
spgm UNAVAILABLE
tid UNAVAILABLE
tid2 urn:mazakusa.com:MazakStreams:1.3
tid2 UNAVAILABLE
tid3 urn:mazakusa.com:MazakStreams:1.3
tid3 UNAVAILABLE
unit urn:mazakusa.com:MazakStreams:1.3
unit UNAVAILABLE
xaxisstate UNAVAILABLE
yaxisstate UNAVAILABLE
zaxisstate UNAVAILABLE
af UNAVAILABLE
al UNAVAILABLE
aposm UNAVAILABLE
aposw UNAVAILABLE
cf UNAVAILABLE
cl UNAVAILABLE
cposm UNAVAILABLE
cposw UNAVAILABLE
cs UNAVAILABLE
ctemp UNAVAILABLE
sl UNAVAILABLE
cf2 UNAVAILABLE
cl2 UNAVAILABLE
cpos2m UNAVAILABLE
cpos2w UNAVAILABLE
cs2 UNAVAILABLE
ctemp2 UNAVAILABLE
sl2 UNAVAILABLE
atime UNAVAILABLE
ctime UNAVAILABLE
tcltime UNAVAILABLE
yltime UNAVAILABLE
concentration UNAVAILABLE
cooltemp UNAVAILABLE
pf UNAVAILABLE
xf UNAVAILABLE
xl UNAVAILABLE
xpm UNAVAILABLE
xpw UNAVAILABLE
yf UNAVAILABLE
yl UNAVAILABLE
ypm UNAVAILABLE
ypw UNAVAILABLE
zf UNAVAILABLE
zl UNAVAILABLE
zpm UNAVAILABLE
zpw UNAVAILABLE

Is there any reason I didn't find which may cause these connection errors? Is it because of the older version of MTConnect schema (1.3), and some incompatibilities?
Which I could perfectly understand, but sadly I cannot change some agent and schema versions, they are either built-in in the machines or not customizable/upgradable by me, end customer.

Any help will be very appreciated. If I missed some details or more info is needed please let me know.

Thank!

Issue with independent probe

I am having an issue where using the Probe() method does not work, but the Start() method works fine. I have tried both Probe(baseUrl) and Probe(baseUrl, DeviceName). Would appreciate any help! Thanks!

ShdrIntervalQueueAdapter ShdrCondition Fault vs AddFault behavior.

NuGet release 5.0.0.

void SetCondition(key, isFault, nativeCode, text)
{
  var c = new ShdrCondition(key);
  if(isFault) {
    c.AddFault(text, nativeCode);
  } else {
    c.AddNormal(text, nativeCode);
  }
}

Using above approach to set the condition, if I send a fault, fault, normal, normal, then all four instances register as samples at the cppagent.

2023-03-28T19:22:00Z|f_sim_p1_alm_logic|FAULT|SW0100|||PARAMETER ENABLE SWITCH ON
2023-03-28T19:22:01Z|f_sim_p1_alm_logic|FAULT|SW0100|||PARAMETER ENABLE SWITCH ON
2023-03-28T19:22:02Z|f_sim_p1_alm_logic|NORMAL|SW0100|||PARAMETER ENABLE SWITCH ON
2023-03-28T19:22:03Z|f_sim_p1_alm_logic|NORMAL|SW0100|||PARAMETER ENABLE SWITCH ON

Is it expected for the SHDR adapter to send conditions through even if they have not changed?

<Fault dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1327" timestamp="2023-03-28T19:21:06.187136Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Fault>
<Fault dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1329" timestamp="2023-03-28T19:21:07.181688Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Fault>
<Fault dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1331" timestamp="2023-03-28T19:21:08.19261Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Fault>
<Fault dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1333" timestamp="2023-03-28T19:21:09.190217Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Fault>
<Normal dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1336" timestamp="2023-03-28T19:21:10.159083Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Normal>
<Normal dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1339" timestamp="2023-03-28T19:21:11.188217Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Normal>
<Normal dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1341" timestamp="2023-03-28T19:21:12.192046Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Normal>
<Normal dataItemId="f_sim_p1_alm_logic" nativeCode="SW0100" sequence="1343" timestamp="2023-03-28T19:21:13.207794Z" type="LOGIC_PROGRAM">PARAMETER ENABLE SWITCH ONrh</Normal>

RestSharp version

I have a .NET Framework 4.5.2 application that depends on RestSharp version 106.10.1. MTConnect.NET is not compatible with this version of RestSharp and only works when the RestSharp version is set to 105.2.3.
{"Could not load file or assembly 'RestSharp, Version=105.2.3.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)":"RestSharp, Version=105.2.3.0, Culture=neutral, PublicKeyToken=null"}

ShdrQueueAdapter.AddCondition results in stack overflow

Attempting to add a condition by using a ConditionObservationInput object results in a Stack overflow...

using MTConnect.Adapters.Shdr;
using MTConnect.Observations;
using MTConnect.Observations.Input;

    var adapter = new ShdrQueueAdapter("console-adapter");
    adapter.MultilineAssets = true;
    adapter.MultilineDevices = true;
    adapter.AgentConnected += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Agent Connected");
    adapter.AgentDisconnected += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Agent Disconnected");
    adapter.PingReceived += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Agent Ping Received");
    adapter.PongSent += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Pong Sent to Agent");
    adapter.LineSent += (sender, args) => Console.WriteLine($"Agent Connection (ID = {args.ClientId}) : Line Sent : {args.Message}");
    adapter.Start();

    // var c = new ConditionObservationInput("someId", ConditionLevel.NORMAL, DateTime.Now);
    var c = new ConditionObservationInput("someId");
    adapter.AddCondition(c);

image

ShdrQueueAdapter.SendBuffer doesn't send ShdrCondition

The dataItem someId appears makes it to the agent buffer; but someId2 fails silently.

using MTConnect.Adapters.Shdr;
using MTConnect.Shdr;

var adapter = new ShdrQueueAdapter("console-adapter");

adapter.MultilineAssets = true;
adapter.MultilineDevices = true;
adapter.AgentConnected += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Agent Connected");
adapter.AgentDisconnected += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Agent Disconnected");
adapter.PingReceived += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Agent Ping Received");
adapter.PongSent += (sender, connectionId) => Console.WriteLine($"Agent Connection (ID = {connectionId}) : Pong Sent to Agent");
adapter.LineSent += (sender, args) => Console.WriteLine($"Agent Connection (ID = {args.ClientId}) : Line Sent : {args.Message}");

adapter.Start();

for(var i = 0; i<10; i++)
{
    adapter.AddDataItem("someId", i);
    
    var c = new ShdrCondition("someId2");
    c.Fault("This is a fault", "ABCD123");
    adapter.AddCondition(c);

    adapter.SendBuffer();
    Thread.Sleep(1500);
}

Use the following code to continuously verify on Linux and fail

The self signed bidirectional authentication code using SSL/TLS has been debugged successfully on Windows, but has not passed on Linux. Error: Error while authenticating One or more errors occurred (One or more errors occurred. (The decryption operation failed, see inner exception.))

image

Please provide some correct solutions

Stream reading error

Hi Patrick,

In the changeset 9dbdbed you introduced a problem:
image
You ignore the result of ReadAsync and b never get -1 as before your change.
Instead it should be something like
image

At least there is one more place above in the same file with the same problem.

Best regards,
Sergii Gulyk.

Module http-adapter not loaded


Issue: http-adapter Module Not Loading

Description

Hi,

I have installed the MTConnect agent from the .exe file on my Windows 10 PC. I am trying to launch the .exe with the following configuration:

modules:
  - http-adapter:
      address: mtconnect.mazakcorp.com
      port: 5610
      deviceKey: M12346
      interval: 100
      heartbeat: 10000
      useSSL: false
      currentOnly: false
      useStreaming: false
      
  - mqtt-relay:
      server: localhost
      port: 1883
      topicPrefix: MTConnect
      topicStructure: Document
      documentFormat: JSON-CPPAGENT-MQTT
      currentInterval: 5000
      sampleInterval: 5000
      clientId: my-mqtt-client
      reconnectInterval: 10000
      currentOnly: false

But the agent logs show that it is not loading the http-adapter module for some reason. Here is the log:

2024-06-14 12:11:32.5885|INFO|application-logger|Agent Configuration Path = agent.config.yaml
2024-06-14 12:11:32.6718|INFO|application-logger|Configuration File Read Successfully from: C:\Program Files\TrakHound\MTConnect.NET-Agent\agent.config.yaml
2024-06-14 12:11:32.9811|INFO|application-logger|Module Loaded : MQTT Relay
2024-06-14 12:11:35.0843|INFO|modules.mqtt-relay|MQTT Relay Connected to External Broker (localhost:1883)

Is there something wrong with the configuration (because it's copied from the example on GitHub)?

Steps to Reproduce

  1. Install the MTConnect agent using the .exe file on Windows 10.
  2. Use the provided configuration.
  3. Start the agent and observe the logs.

Expected Behavior

The http-adapter module should load and connect to the specified address and port.

Actual Behavior

The http-adapter module does not load, while the mqtt-relay module connects successfully.

Environment

  • Windows 10
  • MTConnect.NET Agent version: 6.4.1.0

Q: ShdrAdapter

Can data items be added on-the-fly after the adapter Start method has been called? (Meaning, all data items do not have to be known before starting the adapter)

Performance issue with starting adapter client in tests

Discussed in #26

Originally posted by SergeyGulik May 23, 2022
Hi Patrick,

I have not put this in issues, since it not at all an issue with the code, but there exists .NET behaviour that creates me a problem.
ShdrAdapterClient.cs, line ~162
// Create new TCP Client
_client = new TcpClient(Server, Port);
On every test run I experienced 2sec delay on this line.
I am not a network guy at all, but luckily I have found this excellent answer on SO: https://stackoverflow.com/a/49348416
When I changed code like
_client = new TcpClient(AddressFamily.InterNetwork); <-- this means IP4
_client.Connect(Server, Port);
2sec delay disappeared.
This is possible solution, but according to SO answer we may also bind server to listen locally for IP6 requests.
I have not tried it yet, but wonder what would you prefer.

Best regards,
Sergii.

Addition of MTConnect Adapter Functionality

We are looking to add classes to support the MTConnect Adapter communication between the Adapter and Agent using the SHDR protocol to this library and are looking for any feedback or contributions from the community.

We would like to improve on the open source libraries already out there for Adapters as well as integrate it into this library so it is easily accessible through Nuget.

If anyone has any suggestions or would like to contribute then please feel free to add a comment here or contact us directly at [email protected]

v6.4.0: Cannot connect to local Greengrass broker (moquette)

Here is an agent config:

devices: devices

modules:
    - mqtt-relay:
          server: host.docker.internal
          port: 8883
          clientId: alex-printer-8
          certificateAuthority: certificates/certificateAuthority.pem
          pemCertificate: certificates/certificate.pem
          pemPrivateKey: certificates/privateKey.pem
#          Uncommenting this does not change much
#          allowUntrustedCertificates: true

observationBufferSize: 150000
assetBufferSize: 1000

# Sets whether the Agent buffers are durable and retain state after restart
durable: true

defaultVersion: 2.2

Starting agent with docker compose up compose config:

version: "3.8"

services:
    agent:
        image: trakhound/mtconnect.net-agent:6.0.9-beta-alpine-3.18-amd64
        volumes:
            - ./agent.config.yaml:/app/agent.config.yaml
            - ./devices:/app/devices
            - ./certificates:/app/certificates

Output on console:

⋊> docker compose up                                                                                                                   
[+] Running 1/0
 ⠿ Container mtconnectnet-agent-1  Created                                                                                                                        0.0s
Attaching to mtconnectnet-agent-1
mtconnectnet-agent-1  | --------------------
mtconnectnet-agent-1  | Copyright 2023 TrakHound Inc., All Rights Reserved
mtconnectnet-agent-1  | MTConnect.NET Agent : Version 6.0.9.0
mtconnectnet-agent-1  | --------------------
mtconnectnet-agent-1  | This application is licensed under the MIT License (https://choosealicense.com/licenses/mit/)
mtconnectnet-agent-1  | Source code available at Github.com (https://github.com/TrakHound/MTConnect.NET)
mtconnectnet-agent-1  | --------------------
mtconnectnet-agent-1  | 2024-03-05 11:50:03.2538|INFO|application|Configuration File Read Successfully from: /app/agent.config.yaml
mtconnectnet-agent-1  | 2024-03-05 11:50:03.3169|INFO|agent|Loading Observations from File Buffer...
mtconnectnet-agent-1  | 2024-03-05 11:50:03.3461|INFO|agent|15 Observations Loaded from File Buffer in (0.025s)
mtconnectnet-agent-1  | 2024-03-05 11:50:03.3476|INFO|agent|Loading Assets from File Buffer...
mtconnectnet-agent-1  | 2024-03-05 11:50:03.6038|INFO|application|Module Loaded : MQTT Relay
mtconnectnet-agent-1  | 2024-03-05 11:50:03.7549|INFO|agent|Device (M12346) Read From File : /app/devices/test.xml
mtconnectnet-agent-1  | 2024-03-05 11:50:04.1271|WARN|modules.mqtt-relay|MQTT Relay Connection Error : Authentication failed, see inner exception.
mtconnectnet-agent-1  | 2024-03-05 11:50:04.1406|INFO|modules.mqtt-relay|MQTT Relay Disconnected from External Broker (host.docker.internal:8883)
^CGracefully stopping... (press Ctrl+C again to force)

Logs from greengrass:

2024-03-05T11:50:04.109Z [ERROR] (nioEventLoopGroup-5-4) io.moquette.broker.NewNettyMQTTHandler: Unexpected exception while processing MQTT message. Closing Netty channel. CId=null. {}
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Empty server certificate chain
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:480)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.moquette.broker.metrics.BytesMetricsHandler.channelRead(BytesMetricsHandler.java:51)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:995)
	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: javax.net.ssl.SSLHandshakeException: Empty server certificate chain
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:347)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:303)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:294)
	at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:390)
	at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:375)
	at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
	at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1076)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1063)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1010)
	at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1548)
	at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1394)
	at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1235)
	at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1284)
	at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510)
	at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDe
coder.java:449)
	... 25 more

2024-03-05T11:50:04.110Z [INFO] (nioEventLoopGroup-5-4) io.moquette.b
roker.metrics.MQTTMessageLogger: Channel Inactive. {}

I am guessing it's something about MQTT library configuration, as I can connect to same broker with same certificates using MQTT Explorer:

 MQTT_Explorer
MQTT_Explorer
MQTT_Explorer
MQTT_Explorer

In which case, Greengrass logs look like:

2024-03-05T11:56:37.269Z [INFO] (nioEventLoopGroup-5-1) io.moquette.broker.metrics.MQTTMessageLogger: C->B CONNECT <null>. {}
2024-03-05T11:56:37.877Z [INFO] (nioEventLoopGroup-5-1) com.aws.greengrass.mqtt.moquette.ClientDeviceAuthorizer: Successfully authenticated client device. {clientId=alex-printer-8, sessionId=2bfac112-3e14-4e25-9996-eeb5802dca9b}
2024-03-05T11:56:37.893Z [INFO] (nioEventLoopGroup-5-1) io.moquette.broker.metrics.MQTTMessageLogger: C->B SUBSCRIBE <alex-printer-8> to topics [MqttTopicSubscription[topicFilter=#, option=SubscriptionOption[qos=AT_MOST_ONCE, noLocal=false, retainAsPublished=false, retainHandling=SEND_AT_SUBSCRIBE]]]. {}
2024-03-05T11:56:37.894Z [INFO] (nioEventLoopGroup-5-1) io.moquette.broker.metrics.MQTTMessageLogger: C->B SUBSCRIBE <alex-printer-8> to topics [MqttTopicSubscription[topicFilter=$SYS/#, option=SubscriptionOption[qos=AT_MOST_ONCE, noLocal=false, retainAsPublished=false, retainHandling=SEND_AT_SUBSCRIBE]]]. {}
2024-03-05T11:56:37.895Z [INFO] (nioEventLoopGroup-5-1) io.moquette.broker.metrics.MQTTMessageLogger: C->B SUBSCRIBE <alex-printer-8> to topics [MqttTopicSubscription[topicFilter=$aws/#, option=SubscriptionOption[qos=AT_MOST_ONCE, noLocal=false, retainAsPublished=false, retainHandling=SEND_AT_SUBSCRIBE]]]. {}
2024-03-05T11:57:20.889Z [INFO] (nioEventLoopGroup-5-1) io.moquette.broker.metrics.MQTTMessageLogger: C->B DISCONNECT <alex-printer-8>. {}
2024-03-05T11:57:20.891Z [INFO] (nioEventLoopGroup-5-1) io.moquette.broker.metrics.MQTTMessageLogger: Channel Inactive. {}

DataItem attributes mapping

in the ReadXml in
MTConnect.MTConnectStreams.DataItemCollection
the copy attributes is never cleared. attributes are carried from the siblings.
there should be copy.Attributes.RemoveAll(); in the loop

Message Event is delivered with a wrong structure

Hi,

My Device.XML contains the following data item:

<DataItem name="XYZ" id="abc" category="EVENT" type="MESSAGE" />

When running an http agent, it appears as:

<Message dataItemId="abc" name="XYZ" sequence="614" timestamp="2023-08-17T07:57:38.6792431Z" nativeCode="Idle "/>

The expected result was:

<Message dataItemId="abc" name="XYZ"  sequence="614" timestamp="2023-08-17T07:57:38.6792431Z">Idle</Message>

Is this a bug, or am I missing something?
I'm using version 5.4.0

Thanks!

XML Document formatted whitout newline

Hello

Mazak's MT-Connet agent version 1.5.0.14 returns an XML document on a single line (see example below).
currentExample2.zip

The ReadComponentStreamXml method does not read nodes correctly resulting in an exception.
Commenting on reader.Skip (), as in the example below, the procedure seems to work, but I ask for your help to correct the problem.
image

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.