Skip to content

Commit 4fbc595

Browse files
authored
Merge pull request #50 from OpenCommissioning/49-un_client_connection_error
49 un client connection error
2 parents e96899b + 51e18c8 commit 4fbc595

12 files changed

Lines changed: 195 additions & 12 deletions

File tree

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System.Text.RegularExpressions;
2+
using UnityEngine;
3+
4+
namespace OC.Communication
5+
{
6+
public static class ClientVariableExtension
7+
{
8+
private static readonly Regex InvalidChars = new ("[^A-Za-z0-9_]", RegexOptions.Compiled);
9+
10+
/// <summary>
11+
/// Returns true if:
12+
/// - name is not null/empty
13+
/// - first char is a letter
14+
/// - all chars are letters, digits or underscore
15+
/// </summary>
16+
public static bool IsVariableNameValid(string name)
17+
{
18+
if (string.IsNullOrEmpty(name)) return false;
19+
if (!char.IsLetter(name[0])) return false;
20+
21+
for (var i = 1; i < name.Length; i++)
22+
{
23+
var character = name[i];
24+
if (!(char.IsLetterOrDigit(character) || character == '_')) return false;
25+
}
26+
27+
return true;
28+
}
29+
30+
/// <summary>
31+
/// Replace spaces and hyphens with underscore
32+
/// Remove any other invalid characters
33+
/// Ensure it starts with a letter by prefixing 'A' if needed
34+
/// </summary>
35+
public static string CorrectVariableName(string input)
36+
{
37+
if (string.IsNullOrEmpty(input)) return input;
38+
39+
var withUnderscores = Regex.Replace(input, @"[\s-]+", "_");
40+
var cleaned = InvalidChars.Replace(withUnderscores, "");
41+
42+
if (char.IsLetter(cleaned[0])) return cleaned;
43+
44+
var name = "A" + cleaned;
45+
46+
cleaned = name;
47+
48+
return cleaned;
49+
}
50+
}
51+
}

Runtime/Scripts/Communication/Client/ClientVariableExtension.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Runtime/Scripts/Communication/Client/TwinCAT/TcAdsClient.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Xml.Linq;
33
using UnityEngine;
4-
using AdsClient = TwinCAT.Ads.TcAdsClient;
54

65
namespace OC.Communication.TwinCAT
76
{

Runtime/Scripts/Communication/Client/TwinCAT/TcAdsClientConfig.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public bool Verbose
6262
Name = "Client",
6363
Reconnect = true,
6464
NetId = "Local",
65-
Port = 351,
65+
Port = 851,
6666
ClearBuffer = true,
6767
Verbose = false
6868
};

Runtime/Scripts/Communication/Link/Hierarchy.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#if UNITY_EDITOR
2+
using UnityEditor;
3+
#endif
4+
15
using UnityEngine;
26

37
namespace OC.Communication
@@ -17,7 +21,34 @@ public class Hierarchy : MonoBehaviour
1721

1822
private string GetName()
1923
{
20-
return string.IsNullOrEmpty(_name) ? transform.name : _name;
24+
if (string.IsNullOrEmpty(_name))
25+
{
26+
if (!ClientVariableExtension.IsVariableNameValid(transform.name))
27+
{
28+
var validName = ClientVariableExtension.CorrectVariableName(transform.name);
29+
#if UNITY_EDITOR
30+
Debug.LogWarning($"Hierarchy GameObject name {transform.name} is invalid! The name is modified to {validName}", this);
31+
transform.name = validName;
32+
EditorUtility.SetDirty(this);
33+
#endif
34+
}
35+
36+
return transform.name;
37+
}
38+
else
39+
{
40+
if (!ClientVariableExtension.IsVariableNameValid(_name))
41+
{
42+
var validCustomName = ClientVariableExtension.CorrectVariableName(_name);
43+
#if UNITY_EDITOR
44+
Debug.LogWarning($"Hierarchy name {_name} is invalid! The name is modified to {validCustomName}");
45+
_name = validCustomName;
46+
EditorUtility.SetDirty(this);
47+
#endif
48+
}
49+
50+
return _name;
51+
}
2152
}
2253

2354
public Transform GetParent()

Runtime/Scripts/Communication/Link/Link.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ public Link(Component component)
6868
public void Initialize(Component component)
6969
{
7070
_component = component;
71-
_name = this.GetName();
72-
_path = this.GetPath();
71+
_name = this.GetHierarchyName();
72+
_path = this.GetHierarchyPath();
7373
_client = this.GetClient();
7474
_connectors = new List<Connector>();
7575
}

Runtime/Scripts/Communication/Link/LinkExtension.cs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,52 @@
11
using UnityEngine;
2+
#if UNITY_EDITOR
3+
using UnityEditor;
4+
#endif
25

36
namespace OC.Communication
47
{
58
public static class LinkExtension
69
{
10+
/// <summary>
11+
/// Retrieves the name of the GameObject associated with the given <see cref="Link"/>.
12+
/// If the name is not a valid variable name according to <see cref="ClientVariableExtension"/>,
13+
/// it will be corrected on the GameObject and a warning will be logged in the Unity Editor.
14+
/// </summary>
15+
/// <param name="link">The <see cref="Link"/> whose GameObject name is being retrieved and validated.</param>
16+
/// <returns>The (original) name of the GameObject. Note that the GameObject’s name is modified in-editor if it was invalid.</returns>
717
public static string GetName(this Link link)
818
{
919
var name = link.Component.gameObject.name;
20+
21+
if (!ClientVariableExtension.IsVariableNameValid(name))
22+
{
23+
var oldName = name;
24+
name = ClientVariableExtension.CorrectVariableName(name);
25+
#if UNITY_EDITOR
26+
Debug.LogWarning($"Link component name {oldName} is invalid! The name is modified to {name}", link.Component);
27+
link.Component.gameObject.name = name;
28+
EditorUtility.SetDirty(link.Component);
29+
#endif
30+
}
31+
32+
return name;
33+
}
34+
35+
/// <summary>
36+
/// Constructs the full hierarchical name for the GameObject associated with the given <see cref="Link"/>.
37+
/// Starting from the GameObject’s own name, it traverses upward through its parent transforms.
38+
/// For each parent that has a <see cref="Hierarchy"/> component marked as a sampler (<see cref="Hierarchy.IsNameSampler"/>),
39+
/// its <see cref="Hierarchy.Name"/> is prepended (followed by an underscore) to the current name.
40+
/// The process stops when there are no more sampler hierarchies in the chain.
41+
/// </summary>
42+
/// <param name="link">The <see cref="Link"/> whose GameObject full name is being assembled.</param>
43+
/// <returns>
44+
/// A string representing the combined sampler names and the original GameObject name,
45+
/// separated by underscores (e.g. "RootSampler_SubSampler_ObjectName").
46+
/// </returns>
47+
public static string GetHierarchyName(this Link link)
48+
{
49+
var name = link.GetName();
1050
var parent = link.Parent != null ? link.Parent.transform : link.Component.transform.parent;
1151

1252
while (parent != null)
@@ -31,10 +71,29 @@ public static string GetName(this Link link)
3171

3272
return name;
3373
}
34-
35-
public static string GetPath(this Link link, bool original = false)
74+
75+
/// <summary>
76+
/// Builds a dot-separated path representing the link’s position in the client/hierarchy structure.
77+
/// Starts with the link’s own name (validated via <see cref="GetName"/>), then walks up through
78+
/// parent transforms. If a <see cref="Client"/> is encountered, its <see cref="Client.RootName"/>
79+
/// is prepended and the traversal ends. Otherwise, for each <see cref="Hierarchy"/> parent, its
80+
/// <see cref="Hierarchy.Name"/> is prepended using “.” or “_” if <see cref="Hierarchy.IsNameSampler"/>
81+
/// is true. If <paramref name="original"/> is false and the link has a <see cref="Link.Parent"/>,
82+
/// the traversal uses that chain; otherwise it uses the GameObject’s raw transform hierarchy.
83+
/// </summary>
84+
/// <param name="link">The <see cref="Link"/> whose hierarchy path is being constructed.</param>
85+
/// <param name="original">
86+
/// If false and <paramref name="link"/> has a non-null <see cref="Link.Parent"/>, use the parent link’s
87+
/// transform chain; otherwise use the GameObject’s direct transform parents.
88+
/// </param>
89+
/// <returns>
90+
/// A string combining client root and hierarchy names, separated by “.” (or “_” for samplers),
91+
/// e.g. “RootClient.ParentName.ChildName” or “Sampler1_Sampler2_ObjectName”.
92+
/// </returns>
93+
public static string GetHierarchyPath(this Link link, bool original = false)
3694
{
37-
var path = link.Component.gameObject.name;
95+
var path = link.GetName();
96+
3897
Transform parent;
3998

4099
if (!original && link.Parent != null)

Runtime/Scripts/System/ProjectTreeFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private static XElement CreateDevice(Link link)
105105

106106
if (!link.IsPathOriginal())
107107
{
108-
var path = link.GetPath(true);
108+
var path = link.GetHierarchyPath(true);
109109
device.Add(new XElement("OriginalPath", path));
110110
}
111111

Samples/Demo/0.1 Devices.unity

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,8 +1092,8 @@ MonoBehaviour:
10921092
_type: FB_Cylinder
10931093
_parent: {fileID: 0}
10941094
_attributes: []
1095-
_name: Cylinder_1
1096-
_path: MAIN.Devices.Cylinders.Cylinder_1
1095+
_name: Cylinder_11
1096+
_path: MAIN.Devices.Cylinders.Cylinder_11
10971097
_connector:
10981098
Control: 0
10991099
Status: 0
@@ -10505,7 +10505,7 @@ MonoBehaviour:
1050510505
_name: Client
1050610506
_reconnect: 1
1050710507
_netId: Local
10508-
_port: 351
10508+
_port: 851
1050910509
_clearBuffer: 1
1051010510
_verbose: 0
1051110511
--- !u!1 &2008748801

Tests/Editor/Client.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)