2023-06-12 15:51:41 +08:00
|
|
|
|
using Godot;
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading;
|
|
|
|
|
using BITKit.Core.Entites;
|
2023-06-13 14:43:03 +08:00
|
|
|
|
using BITKit.Packages.Core.LazyLoad;
|
2023-06-12 15:51:41 +08:00
|
|
|
|
using Cysharp.Threading.Tasks;
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
|
|
|
|
namespace BITKit;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 单例SCADA Service,从http接口获取json后解析为指定数据
|
|
|
|
|
/// </summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
public partial class SCADAService : Node,IProvider<string>,IActivable
|
2023-06-12 15:51:41 +08:00
|
|
|
|
{
|
2023-06-16 17:08:59 +08:00
|
|
|
|
public const string _CurrentAngle="CurrentAngle";
|
|
|
|
|
public const string _CurrentRotation="CurrentRotation";
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 在构造函数中注入依赖
|
|
|
|
|
/// </summary>
|
|
|
|
|
public SCADAService()
|
|
|
|
|
{
|
2023-06-13 14:43:03 +08:00
|
|
|
|
BITApp.ServiceCollection.AddSingleton(this);
|
2023-06-12 15:51:41 +08:00
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取json的Url
|
|
|
|
|
/// </summary>
|
2023-06-15 21:52:13 +08:00
|
|
|
|
private readonly DataReference<string> _url = new("SCADA_GetInfos");
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 是否固定控制的Entity,如果固定,只会刷新一次,如果不固定,每帧都会刷新
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Export]
|
|
|
|
|
private bool fixedEntities;
|
|
|
|
|
/// <summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
/// 是否启用
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// </summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
[Export]
|
|
|
|
|
public bool Enabled { get; set; } = true;
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
/// 已加载的Entity
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// </summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
private readonly Dictionary<string, IEntity> _entities = new();
|
|
|
|
|
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取Entity并加载依赖
|
|
|
|
|
/// </summary>
|
|
|
|
|
public override async void _Ready()
|
|
|
|
|
{
|
|
|
|
|
if (!fixedEntities) return;
|
|
|
|
|
await UniTask.Yield();
|
|
|
|
|
LoadAllEntities();
|
|
|
|
|
BIT4Log.Log<SCADAService>($"已加载{_entities.Count}个设备");
|
2023-06-15 21:52:13 +08:00
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(_url))
|
|
|
|
|
{
|
|
|
|
|
BIT4Log.Warnning("SCADA Url为空");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
BIT4Log.Log<SCADAService>($"已找到SCADA_GetInfos:\t{_url.Get()}");
|
|
|
|
|
}
|
2023-06-12 15:51:41 +08:00
|
|
|
|
}
|
|
|
|
|
/// <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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-29 01:01:52 +08:00
|
|
|
|
|
2023-06-15 21:52:13 +08:00
|
|
|
|
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 从http请求json
|
|
|
|
|
/// </summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
|
2023-06-15 21:52:13 +08:00
|
|
|
|
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// 解析json
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="json">从SCADA获取的Json</param>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
public void Set(string json)
|
2023-06-12 15:51:41 +08:00
|
|
|
|
{
|
2023-06-29 01:01:52 +08:00
|
|
|
|
if(Enabled is false)return;
|
2023-06-12 15:51:41 +08:00
|
|
|
|
//首先从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
|
2023-06-29 01:01:52 +08:00
|
|
|
|
var _key = element["value"]!.ToString();
|
|
|
|
|
string _json;
|
|
|
|
|
if (_key.Substring(0) is "\"")
|
|
|
|
|
{
|
|
|
|
|
_json = element["value"]!.ToObject<string>();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
_json = element["value"].ToString();
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-12 15:51:41 +08:00
|
|
|
|
//获取被加载为string的json
|
2023-06-15 21:52:13 +08:00
|
|
|
|
var obj = JsonConvert.DeserializeObject(_json);
|
2023-06-12 15:51:41 +08:00
|
|
|
|
//反序列化string为原始json
|
2023-06-15 21:52:13 +08:00
|
|
|
|
var value = JObject.Parse(obj!.ToString()!);
|
2023-06-12 15:51:41 +08:00
|
|
|
|
//提交json和entity
|
|
|
|
|
ProcessEntity(value,entity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 提交jObject数据和Entity进行解析和处理
|
|
|
|
|
/// </summary>
|
2023-06-29 01:01:52 +08:00
|
|
|
|
/// <param name="jObject">json [result] [index] [value] 中的原始json</param>
|
2023-06-12 15:51:41 +08:00
|
|
|
|
/// <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;
|
|
|
|
|
//加载以获取到的角度
|
2023-06-29 01:01:52 +08:00
|
|
|
|
var rawAngle = jObject[path]!.ToObject<float>();
|
|
|
|
|
//补间角度
|
|
|
|
|
var currentAngle = rotationComponent.CurrentAngle = Mathf.Lerp(rotationComponent.CurrentAngle, rawAngle,
|
|
|
|
|
90 * BITAppForGodot.DeltaTime);
|
2023-06-12 15:51:41 +08:00
|
|
|
|
//最终角度 = 当前角度*角度权重 + 角度偏移 + 原始角度
|
|
|
|
|
var euler = currentAngle * rotationComponent.Weight + rotationComponent.Offset + rotationComponent.OriginalEuler;
|
|
|
|
|
//为Node3D.Rotation提交最后的角度计算结果
|
2023-06-29 01:01:52 +08:00
|
|
|
|
|
|
|
|
|
euler.X = Mathf.DegToRad(euler.X);
|
|
|
|
|
euler.Y = Mathf.DegToRad(euler.Y);
|
|
|
|
|
euler.Z = Mathf.DegToRad(euler.Z);
|
2023-07-18 16:42:33 +08:00
|
|
|
|
rotationComponent.node3D.Rotation = euler;
|
2023-06-29 01:01:52 +08:00
|
|
|
|
//rotationComponent.RotationDegrees = euler;
|
|
|
|
|
|
2023-06-15 21:52:13 +08:00
|
|
|
|
|
2023-06-29 01:01:52 +08:00
|
|
|
|
rotationComponent.SetMeta(_CurrentAngle,(int)rawAngle);
|
2023-06-16 17:08:59 +08:00
|
|
|
|
rotationComponent.SetMeta(_CurrentRotation,euler);
|
2023-06-12 15:51:41 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-29 01:01:52 +08:00
|
|
|
|
|
|
|
|
|
public string Get()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetActive(bool active) => Enabled = active;
|
|
|
|
|
|
2023-06-12 15:51:41 +08:00
|
|
|
|
}
|