KukaAvarProxyNet.cs 6.39 KB
using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Core.IMessage;
using HslCommunication.Core.Net;
using System;
using System.Collections.Generic;
using System.Text;

namespace HslCommunication.Robot.KUKA
{
    /// <summary>
    /// Kuka机器人的数据交互对象,通讯支持的条件为KUKA 的 KRC4 控制器中运行KUKAVARPROXY 这个第三方软件,端口通常为7000
    /// </summary>
    /// <remarks>
    /// 非常感谢 昆山-LT 网友的测试和意见反馈。
    /// </remarks>
    public class KukaAvarProxyNet : NetworkDoubleBase<KukaVarProxyMessage, ReverseWordTransform>, IRobotNet
    {
        #region Constructor

        /// <summary>
        /// 实例化一个默认的对象
        /// </summary>
        public KukaAvarProxyNet()
        {
            softIncrementCount = new SoftIncrementCount(ushort.MaxValue);
        }

        /// <summary>
        /// 实例化一个默认的Kuka机器人对象,并指定IP地址和端口号,端口号通常为7000
        /// </summary>
        /// <param name="ipAddress">Ip地址</param>
        /// <param name="port">端口号</param>
        public KukaAvarProxyNet(string ipAddress, int port)
        {
            IpAddress = ipAddress;
            Port = port;

            softIncrementCount = new SoftIncrementCount(ushort.MaxValue);
        }

        #endregion

        #region Read Write Support


        /// <summary>
        /// 读取埃夫特机器人的原始的字节数据信息,该地址参数是没有任何作用的,随便填什么
        /// </summary>
        /// <param name="address">无效参数</param>
        /// <returns>带有成功标识的byte[]数组</returns>
        public OperateResult<byte[]> Read(string address)
        {
            OperateResult<byte[]> read = ReadFromCoreServer(PackCommand(BuildReadValueCommand(address)));
            if (!read.IsSuccess) return read;

            return ExtractActualData(read.Content);
        }

        /// <summary>
        /// 读取机器人的所有的数据信息,返回JSON格式的数据对象,地址参数无效
        /// </summary>
        /// <param name="address">地址信息</param>
        /// <returns>带有成功标识的字符串数据</returns>
        public OperateResult<string> ReadString(string address)
        {
            OperateResult<byte[]> read = Read(address);
            if (!read.IsSuccess) return OperateResult.CreateFailedResult<string>(read);

            return OperateResult.CreateSuccessResult(Encoding.Default.GetString(read.Content));
        }

        /// <summary>
        /// 本机器人不支持该方法操作,将永远返回失败,无效的操作
        /// </summary>
        /// <param name="address">指定的地址信息,有些机器人可能不支持</param>
        /// <param name="value">原始的字节数据信息</param>
        /// <returns>是否成功的写入</returns>
        public OperateResult Write(string address, byte[] value)
        {
            return Write(address, Encoding.Default.GetString(value));
        }

        /// <summary>
        /// 本机器人支持该方法操作,根据实际的值记性返回
        /// </summary>
        /// <param name="address">指定的地址信息,有些机器人可能不支持</param>
        /// <param name="value">字符串的数据信息</param>
        /// <returns>是否成功的写入</returns>
        public OperateResult Write(string address, string value)
        {
            OperateResult<byte[]> read = ReadFromCoreServer(PackCommand(BuildWriteValueCommand(address, value)));
            if (!read.IsSuccess) return read;

            return ExtractActualData(read.Content);
        }

        #endregion

        #region Command Build

        /// <summary>
        /// 将核心的指令打包成一个可用于发送的消息对象
        /// </summary>
        /// <param name="commandCore">核心命令</param>
        /// <returns>最终实现的可以发送的机器人的字节数据</returns>
        private byte[] PackCommand(byte[] commandCore)
        {
            byte[] buffer = new byte[commandCore.Length + 4];
            ByteTransform.TransByte((ushort)softIncrementCount.GetCurrentValue()).CopyTo(buffer, 0);
            ByteTransform.TransByte((ushort)commandCore.Length).CopyTo(buffer, 2);
            commandCore.CopyTo(buffer, 4);

            return buffer;
        }

        private OperateResult<byte[]> ExtractActualData(byte[] response)
        {
            try
            {
                if (response[response.Length - 1] != 0x01) return new OperateResult<byte[]>(response[response.Length - 1], "Wrong: " + SoftBasic.ByteToHexString(response, ' '));

                int length = response[5] * 256 + response[6];
                byte[] buffer = new byte[length];
                Array.Copy(response, 7, buffer, 0, length);
                return OperateResult.CreateSuccessResult(buffer);
            }
            catch (Exception ex)
            {
                return new OperateResult<byte[]>("Wrong:" + ex.Message + " Code:" + SoftBasic.ByteToHexString(response, ' '));
            }
        }

        private byte[] BuildCommands(byte function, string[] commands)
        {
            List<byte> buffer = new List<byte>();
            buffer.Add(function);
            for (int i = 0; i < commands.Length; i++)
            {
                byte[] buffer_command = Encoding.Default.GetBytes(commands[i]);
                buffer.AddRange(ByteTransform.TransByte((ushort)buffer_command.Length));
                buffer.AddRange(buffer_command);
            }
            return buffer.ToArray();
        }

        private byte[] BuildReadValueCommand(string address)
        {
            return BuildCommands(0x00, new string[] { address });
        }

        private byte[] BuildWriteValueCommand(string address, string value)
        {
            return BuildCommands(0x01, new string[] { address, value });
        }

        #endregion

        #region Private Member

        private SoftIncrementCount softIncrementCount;              // 自增消息的对象

        #endregion

        #region Object Override

        /// <summary>
        /// 返回表示当前对象的字符串
        /// </summary>
        /// <returns>字符串</returns>
        public override string ToString()
        {
            return $"KukaAvarProxyNet Robot[{IpAddress}:{Port}]";
        }

        #endregion
    }
}