Initial commit
This commit is contained in:
@@ -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";
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public enum ScriptEngineState
|
||||
{
|
||||
Initializing = 0,
|
||||
Resetting,
|
||||
Idle,
|
||||
Building,
|
||||
Ready,
|
||||
Starting,
|
||||
Running,
|
||||
Stopping,
|
||||
BuildError,
|
||||
Fault,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public record ScriptFileDto(string Name, int Level, string Code);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public record ScriptFolderDto(string Name, int Level, ScriptFolderDto[] Folders, ScriptFileDto[] Files);
|
||||
@@ -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();
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public record ScriptMissionDto(string Name, ScriptMissionParameterDto[] Parameters);
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public record ScriptMissionParameterDto(string Name, string Type, string? Default);
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public enum ScriptMissionState
|
||||
{
|
||||
Idle = 0,
|
||||
Running,
|
||||
Canceling,
|
||||
Pausing,
|
||||
Paused,
|
||||
Resuming,
|
||||
Canceled,
|
||||
Completed,
|
||||
Error,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public record ScriptTaskDto(string Name, int Interval, bool Enabled, long ExecutionCount);
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public enum ScriptTaskState
|
||||
{
|
||||
Idle = 0,
|
||||
Running,
|
||||
Pausing,
|
||||
Paused,
|
||||
Resuming,
|
||||
Stopping,
|
||||
Stopped,
|
||||
Error,
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public record ScriptVariableDto(string Name, string TypeName, string Value, bool Writeable);
|
||||
Reference in New Issue
Block a user