Initial commit

This commit is contained in:
2026-07-13 09:25:40 +07:00
parent c08ff54676
commit bccfb156d7
1938 changed files with 641646 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
namespace RobotNet10.ScriptEngine.Shared;
public static class HubEndpoints
{
public const string ScriptManagerHubPath = "/hubs/script-engine/manager";
public const string ScriptConsoleHubPath = "/hubs/script-engine/console";
public const string ScriptFileManagerHubPath = "/hubs/script-engine/files";
public const string InstanceMissionHubPath = "/hubs/script-engine/instance-mission";
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Immutable;
namespace RobotNet10.ScriptEngine.Shared;
public interface IScriptEngineResource
{
Type AppGlobalType { get; }
IDictionary<string, object?> GetTaskGlobals();
IDictionary<string, object?> GetMissionGlobals(Guid id, CancellationToken cancellationToken);
ImmutableArray<string> UsingNamespaces { get; }
ImmutableArray<string> Modules { get; }
ImmutableArray<string> DocModules { get; }
}

View File

@@ -0,0 +1,59 @@
using RobotNet10.Script.IO;
namespace RobotNet10.ScriptEngine.Shared;
public interface IScriptGlobals
{
RobotNet10.Script.ILogger Logger { get; }
Guid CreateMission(string name, params object[] args);
bool CancelMission(Guid id, string reason);
void DisableTask(string name);
void EnableTask(string name);
// IO Connection Factory Methods
/// <summary>
/// Creates an HTTP connection.
/// </summary>
/// <param name="baseUrl">The base URL (e.g., "http://localhost:8080").</param>
/// <param name="timeoutSeconds">Optional timeout in seconds (default: 30).</param>
/// <returns>An HTTP connection instance.</returns>
IHttpConnection CreateHttpConnection(string baseUrl, int timeoutSeconds = 30);
/// <summary>
/// Creates a ModbusTCP connection.
/// </summary>
/// <param name="ipAddress">The IP address of the ModbusTCP server.</param>
/// <param name="port">The port number (default: 502).</param>
/// <param name="slaveId">The slave ID/unit identifier (default: 1).</param>
/// <returns>A ModbusTCP connection instance.</returns>
IModbusTcpConnection CreateModbusTcpConnection(string ipAddress, int port = 502, byte slaveId = 1);
/// <summary>
/// Creates a ProfiNet connection.
/// </summary>
/// <param name="ipAddress">The IP address of the ProfiNet device.</param>
/// <param name="slot">The slot number (default: 1).</param>
/// <param name="subslot">The subslot number (default: 1).</param>
/// <returns>A ProfiNet connection instance.</returns>
IProfiNetConnection CreateProfiNetConnection(string ipAddress, int slot = 1, int subslot = 1);
/// <summary>
/// Creates a CC-Link IE connection.
/// </summary>
/// <param name="ipAddress">The IP address of the CC-Link IE device.</param>
/// <param name="stationNumber">The station number (default: 1).</param>
/// <returns>A CC-Link IE connection instance.</returns>
ICcLinkIeConnection CreateCcLinkIeConnection(string ipAddress, int stationNumber = 1);
/// <summary>
/// Creates an OPC UA connection.
/// </summary>
/// <param name="endpointUrl">The OPC UA server endpoint URL (e.g., "opc.tcp://localhost:4840").</param>
/// <returns>An OPC UA connection instance.</returns>
IOpcUaConnection CreateOpcUaConnection(string endpointUrl);
}

View File

@@ -0,0 +1,14 @@
namespace RobotNet10.ScriptEngine.Shared;
public class InstanceMissionDto
{
public Guid Id { get; set; }
public string MissionName { get; set; } = "";
public string Parameters { get; set; } = "{}";
public DateTime CreatedAt { get; set; }
public ScriptMissionState State { get; set; }
public int TotalScore { get; set; }
public int Score { get; set; }
public DateTime StoppedAt { get; set; }
public string? Log { get; set; }
}

View File

@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Commons\RobotNet10.Script\RobotNet10.Script.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,12 @@
namespace RobotNet10.ScriptEngine.Shared;
/// <summary>
/// Information about a backup file.
/// </summary>
public class ScriptBackupInfo
{
public string FileName { get; set; } = string.Empty;
public long Size { get; set; }
public DateTime CreatedAt { get; set; }
}

View File

@@ -0,0 +1,15 @@
namespace RobotNet10.ScriptEngine.Shared;
public enum ScriptEngineState
{
Initializing = 0,
Resetting,
Idle,
Building,
Ready,
Starting,
Running,
Stopping,
BuildError,
Fault,
}

View File

@@ -0,0 +1,3 @@
namespace RobotNet10.ScriptEngine.Shared;
public record ScriptFileDto(string Name, int Level, string Code);

View File

@@ -0,0 +1,3 @@
namespace RobotNet10.ScriptEngine.Shared;
public record ScriptFolderDto(string Name, int Level, ScriptFolderDto[] Folders, ScriptFileDto[] Files);

View File

@@ -0,0 +1,224 @@
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
namespace RobotNet10.ScriptEngine.Shared;
public static partial class ScriptHelpers
{
public static string ToString(ParameterInfo parameter)
{
var modifier = "";
if (parameter.IsDefined(typeof(ParamArrayAttribute), false))
modifier = "params ";
else if (parameter.IsIn && parameter.ParameterType.IsByRef && !parameter.IsOut)
modifier = "in ";
else if (parameter.IsOut)
modifier = "out ";
else if (parameter.ParameterType.IsByRef)
modifier = "ref ";
var typeString = ScriptHelpers.ToString(
parameter.ParameterType.IsByRef
? parameter.ParameterType.GetElementType()!
: parameter.ParameterType
);
var defaultValue = "";
if (parameter.HasDefaultValue)
{
if (parameter.DefaultValue != null)
{
if (parameter.ParameterType.IsEnum)
{
defaultValue = $" = {ScriptHelpers.ToString(parameter.ParameterType)}.{parameter.DefaultValue}";
}
else if (parameter.DefaultValue is string)
{
defaultValue = $" = \"{parameter.DefaultValue}\"";
}
else if (parameter.DefaultValue is bool b)
{
defaultValue = $" = {b.ToString().ToLower()}";
}
else
{
defaultValue = $" = {parameter.DefaultValue}";
}
}
else
{
defaultValue = " = null";
}
}
return $"{modifier}{typeString} {parameter.Name}{defaultValue}";
}
public static string ToString(Type type)
{
if (type == typeof(void)) return "void";
if (type.IsGenericType)
{
var genericTypeName = type.GetGenericTypeDefinition().FullName;
if (genericTypeName == null)
return type.Name;
var backtickIndex = genericTypeName.IndexOf('`');
if (backtickIndex > 0)
genericTypeName = genericTypeName[..backtickIndex];
var genericArgs = type.GetGenericArguments();
var argsString = string.Join(", ", genericArgs.Select(ToString));
return $"{genericTypeName}<{argsString}>";
}
return type.FullName ?? type.Name;
}
public static Type? ResolveTypeFromString(string typeString)
{
typeString = typeString.Trim();
// Handle array types (e.g., System.Int32[], string[], List<int>[])
if (typeString.EndsWith("[]"))
{
var elementTypeString = typeString[..^2].Trim();
var elementType = ResolveTypeFromString(elementTypeString);
return elementType?.MakeArrayType();
}
// Trường hợp không phải generic
if (!typeString.Contains('<'))
{
return FindType(typeString);
}
// Tách phần generic
var match = GenericTypeRegex.Match(typeString);
if (!match.Success)
return null;
var genericTypeName = match.Groups["raw"].Value;
var genericArgsString = match.Groups["args"].Value;
// Phân tách các generic argument (xử lý nested generics)
var genericArgs = SplitGenericArguments(genericArgsString);
var genericType = FindType(genericTypeName + "`" + genericArgs.Count);
if (genericType == null)
return null;
var resolvedArgs = genericArgs.Select(ResolveTypeFromString).ToArray();
if (resolvedArgs.Any(t => t == null))
return null;
return genericType.MakeGenericType(resolvedArgs!);
}
public static bool ResolveValueFromString(string valueStr, Type type, out object? value)
{
// Check if type is in MissionParameterTypes
if (!SupportedTypes.Values.Contains(type))
{
value = null;
return false;
}
// Convert string to the corresponding type
if (type == typeof(string))
{
value = valueStr;
return true;
}
if (type.IsEnum)
{
value = Enum.Parse(type, valueStr, ignoreCase: true);
return true;
}
// Handle nullable types
var underlyingType = Nullable.GetUnderlyingType(type);
if (underlyingType != null)
{
value = null;
return false;
}
value = Convert.ChangeType(valueStr, type);
if (value is null)
{
return false;
}
else
{
return true;
}
}
private static List<string> SplitGenericArguments(string input)
{
var args = new List<string>();
var sb = new StringBuilder();
int depth = 0;
foreach (char c in input)
{
if (c == ',' && depth == 0)
{
args.Add(sb.ToString().Trim());
sb.Clear();
}
else
{
if (c == '<') depth++;
else if (c == '>') depth--;
sb.Append(c);
}
}
if (sb.Length > 0)
{
args.Add(sb.ToString().Trim());
}
return args;
}
public static Type? FindType(string typeName)
{
if (SupportedTypes.TryGetValue(typeName, out var systemType)) return systemType;
return AppDomain.CurrentDomain
.GetAssemblies()
.Select(a => a.GetType(typeName, false))
.FirstOrDefault(t => t != null);
}
public static readonly IReadOnlyDictionary<string, Type> SupportedTypes = new Dictionary<string, Type>()
{
["bool"] = typeof(bool),
["byte"] = typeof(byte),
["sbyte"] = typeof(sbyte),
["short"] = typeof(short),
["ushort"] = typeof(ushort),
["int"] = typeof(int),
["uint"] = typeof(uint),
["long"] = typeof(long),
["ulong"] = typeof(ulong),
["double"] = typeof(double),
["float"] = typeof(float),
["double"] = typeof(double),
["char"] = typeof(char),
["string"] = typeof(string),
["object"] = typeof(object),
};
private static readonly Regex GenericTypeRegex = CreateGenericTypeRegex();
[GeneratedRegex(@"^(?<raw>[^<]+)<(?<args>.+)>$")]
private static partial Regex CreateGenericTypeRegex();
}

View File

@@ -0,0 +1,3 @@
namespace RobotNet10.ScriptEngine.Shared;
public record ScriptMissionDto(string Name, ScriptMissionParameterDto[] Parameters);

View File

@@ -0,0 +1,3 @@
namespace RobotNet10.ScriptEngine.Shared;
public record ScriptMissionParameterDto(string Name, string Type, string? Default);

View File

@@ -0,0 +1,14 @@
namespace RobotNet10.ScriptEngine.Shared;
public enum ScriptMissionState
{
Idle = 0,
Running,
Canceling,
Pausing,
Paused,
Resuming,
Canceled,
Completed,
Error,
}

View File

@@ -0,0 +1,3 @@
namespace RobotNet10.ScriptEngine.Shared;
public record ScriptTaskDto(string Name, int Interval, bool Enabled, long ExecutionCount);

View File

@@ -0,0 +1,13 @@
namespace RobotNet10.ScriptEngine.Shared;
public enum ScriptTaskState
{
Idle = 0,
Running,
Pausing,
Paused,
Resuming,
Stopping,
Stopped,
Error,
}

View File

@@ -0,0 +1,3 @@
namespace RobotNet10.ScriptEngine.Shared;
public record ScriptVariableDto(string Name, string TypeName, string Value, bool Writeable);