iFactory.Godot/Artists/Scripts/Factory/SCADAService.cs

168 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using BITKit.Core.Entites;
using BITKit.Packages.Core.LazyLoad;
using Cysharp.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BITKit;
/// <summary>
/// 单例SCADA Service,从http接口获取json后解析为指定数据
/// </summary>
public partial class SCADAService : Node,IProvider<string>,IActivable
{
public const string _CurrentAngle="CurrentAngle";
public const string _CurrentRotation="CurrentRotation";
/// <summary>
/// 在构造函数中注入依赖
/// </summary>
public SCADAService()
{
BITApp.ServiceCollection.AddSingleton(this);
}
/// <summary>
/// 获取json的Url
/// </summary>
private readonly DataReference<string> _url = new("SCADA_GetInfos");
/// <summary>
/// 是否固定控制的Entity如果固定只会刷新一次如果不固定每帧都会刷新
/// </summary>
[Export]
private bool fixedEntities;
/// <summary>
/// 是否启用
/// </summary>
[Export]
public bool Enabled { get; set; } = true;
/// <summary>
/// 已加载的Entity
/// </summary>
private readonly Dictionary<string, IEntity> _entities = new();
/// <summary>
/// 获取Entity并加载依赖
/// </summary>
public override async void _Ready()
{
if (!fixedEntities) return;
await UniTask.Yield();
LoadAllEntities();
BIT4Log.Log<SCADAService>($"已加载{_entities.Count}个设备");
if (string.IsNullOrEmpty(_url))
{
BIT4Log.Warning("SCADA Url为空");
}
else
{
BIT4Log.Log<SCADAService>($"已找到SCADA_GetInfos:\t{_url.Get()}");
}
}
/// <summary>
/// 内部方法从EntityService加载所有Entity
/// </summary>
private void LoadAllEntities()
{
foreach (var entity in DI.Get<IEntitiesService>().Entities)
{
if (entity.TryGetComponent<IdComponent>(out var deviceComponent))
{
_entities.Add(deviceComponent.Id,deviceComponent.Entity);
}
}
}
/// <summary>
/// 从http请求json
/// </summary>
/// <summary>
/// 解析json
/// </summary>
/// <param name="json">从SCADA获取的Json</param>
public void Set(string json)
{
if(Enabled is false)return;
//首先从result中获取数组
var jArray = JsonConvert.DeserializeObject<JObject>(json)["result"]!.ToObject<JArray>();
//然后遍历所有数组的内容
foreach (var element in jArray)
{
//获取数组元素的Id
var id = element["id"]!.ToObject<string>();
//通过Id查找已加载的Entity
if (!_entities.TryGetValue(id, out var entity)) continue;
//加载数组中的"value"为json
var _key = element["value"]!.ToString();
string _json;
if (_key.Substring(0) is "\"")
{
_json = element["value"]!.ToObject<string>();
}
else
{
_json = element["value"].ToString();
}
//获取被加载为string的json
var obj = JsonConvert.DeserializeObject(_json);
//反序列化string为原始json
var value = JObject.Parse(obj!.ToString()!);
//提交json和entity
ProcessEntity(value,entity);
}
}
/// <summary>
/// 提交jObject数据和Entity进行解析和处理
/// </summary>
/// <param name="jObject">json [result] [index] [value] 中的原始json</param>
/// <param name="entity">引用实体如PLC-ZL</param>
private static void ProcessEntity(JObject jObject, IEntity entity)
{
//从Entity中加载所有Rotation Component
var rotationComponents = entity
.Components
.Where(x => x is RotationComponent)
.Select((x => (RotationComponent)x));
//遍历所有Rotation Component
foreach (var rotationComponent in rotationComponents)
{
//加载rotation需要的path,如 var angle = value["J1"]
var path = rotationComponent.Path;
//加载以获取到的角度
var rawAngle = jObject[path]!.ToObject<float>();
//补间角度
var currentAngle = rotationComponent.CurrentAngle = Mathf.Lerp(rotationComponent.CurrentAngle, rawAngle,
90 * BITAppForGodot.DeltaTime);
//最终角度 = 当前角度*角度权重 + 角度偏移 + 原始角度
var euler = currentAngle * rotationComponent.Weight + rotationComponent.Offset + rotationComponent.OriginalEuler;
//为Node3D.Rotation提交最后的角度计算结果
euler.X = Mathf.DegToRad(euler.X);
euler.Y = Mathf.DegToRad(euler.Y);
euler.Z = Mathf.DegToRad(euler.Z);
rotationComponent.node3D.Rotation = euler;
//rotationComponent.RotationDegrees = euler;
rotationComponent.SetMeta(_CurrentAngle,(int)rawAngle);
rotationComponent.SetMeta(_CurrentRotation,euler);
}
}
public string Get()
{
throw new NotImplementedException();
}
public void SetActive(bool active) => Enabled = active;
}