LedUtil.cs 8.0 KB
using System;
using System.Collections.Generic; 
using System.Net;
using System.Net.Sockets; 

namespace TSA_V.Common
{
    public class Light
    { 
        public static Light RedLight(int index)
        {
            return new Light(index, 255, 0, 0);
        }
        public static Light YellowLight(int index)
        {
            return new Light(index, 255, 255, 0);
        }
        public static Light BlueLight(int index)
        {
            return new Light(index, 0, 0, 255);
        }
        public static Light GreenLight(int index)
        {
            return new Light(index, 0, 255, 0);
        }

        public static Light CyanLight(int index)
        {
            return new Light(index, 0, 255, 255);
        }

        public static Light ChocolateLight(int index)
        {
            return new Light(index, 210, 105, 30);
        }


        public Light(int index, byte Red, byte Green, byte Blue)
        {
            this.index = index;
            this.Red = Red;
            this.Green = Green;
            this.Blue = Blue;
        }
        public int index { get; set; }
        public byte Red { get; set; }
        public byte Green { get; set; }
        public byte Blue { get; set; }

    }


    /// <summary>
    /// 
    /// </summary>
    public class LEDModule
    {
        //DMX端口为6454, SPI端口为6858
        IPEndPoint iep;
        public const ushort MAX_RGBDMX_UNI = 8;//定义8个RGB灯的DMX域缓存
        //每个DMX域的灯数量
        public const int LIGHT_COUNT_PER_DMX = 170;
        //byte[][] dmxData = new byte[MAX_RGBDMX_UNI][];
        List<byte[]> dmxDatas = new List<byte[]>(MAX_RGBDMX_UNI);

        public LEDModule(string ip)
        {
            iep = new IPEndPoint(IPAddress.Parse(ip), 6858);
            AllLightOff();
        }

        private void InitDatas()
        {
            dmxDatas = new List<byte[]>(MAX_RGBDMX_UNI);
            for (int i = 0; i < MAX_RGBDMX_UNI; i++)
            {
                dmxDatas.Add(new byte[512]);
            }
        }

        public void AllLightOff()
        {
            InitDatas();
            PushToDevice();
        }

        public void AllLightOn()
        {
            AllLightOn(Light.GreenLight(1));
        }

        public void AllLightOn(Light light)
        {
            for (int i = 0; i < MAX_RGBDMX_UNI; i++)
            {
                byte[] data = dmxDatas[i];
                for (int lightIndex = 0; lightIndex < LIGHT_COUNT_PER_DMX; lightIndex++)
                {
                    data[lightIndex * 3] = light.Red;
                    data[lightIndex * 3 + 1] = light.Blue;
                    data[lightIndex * 3 + 2] = light.Green;
                    //dmxDatas[i] = data;
                }
            }
            PushToDevice();
        }

     

        /// <summary>
        /// 只有某些灯亮,其他灯灭掉
        /// </summary>
        /// <param name="lights"></param>
        public void OnlyLightOn(params Light[] lights)
        {
            AllLightOff();
            LightOn(lights);
        }

        /// <summary>
        /// 在之前的状态之上点亮某些灯
        /// </summary>
        /// <param name="lights"></param>
        public void LightOn(params Light[] lights)
        {
            foreach (Light light in lights)
            {
                int dmxIndex = light.index / LIGHT_COUNT_PER_DMX;
                int lightIndex = light.index % LIGHT_COUNT_PER_DMX;
                byte[] data = dmxDatas[dmxIndex];

                //SPI第二通道为蓝色,DMX第二通道为绿色
                data[lightIndex * 3] = light.Red;
                data[lightIndex * 3 + 1] = light.Blue;
                data[lightIndex * 3 + 2] = light.Green;
            }
            PushToDevice();
        }

        public void LightOff(params int[] lightIndexs)
        {
            foreach (int lightId in lightIndexs)
            {
                int dmxIndex = lightId / LIGHT_COUNT_PER_DMX;
                int lightIndex = lightId % LIGHT_COUNT_PER_DMX;
                byte[] data = dmxDatas[dmxIndex];

                //SPI第二通道为蓝色,DMX第二通道为绿色
                data[lightIndex * 3] = 0;
                data[lightIndex * 3 + 1] = 0;
                data[lightIndex * 3 + 2] = 0;
            }

            PushToDevice();
        }



        private void PushToDevice()
        {
            //闲置的时候会有不起作用的情况,这里多发几遍
            for (int time = 0; time < 2; time++)
            {
                UdpClient myUdpClient = new UdpClient();
                try
                {
                        for (int i = 0; i < dmxDatas.Count; i++)
                        {
                            byte[] toSend = ToSPIData(i, dmxDatas[i]);
                            myUdpClient.Send(toSend, toSend.Length, iep);
                        }
                }
                catch (Exception err)
                {
                    Console.WriteLine("发送失败");
                }
                finally
                {
                    myUdpClient.Close();
                }

            }
        }


        /// <summary>
        /// 46:51:35:31:32:4e:65:74: 	数据包头[16]	 
        //0b:00:	OpCode
        //40:
        //06: 序列号
        //00:
        //01: 更新标准:0=写到缓存,未输出到dmxData;1=无缓存,立即输出到dmxData
        //03:	0=没有广播,只控制指定域;1=对设备的所有端口广播;2=对某个子网内的所有域广播;3,对网络下的所有子网广播;0xff=对所有网络设备的所有口广播
        //34:	字节的高4位为子网,字节的低4位为dmxData域,;子网:0~15,DMX域:0~15;
        //02:	IP灯光网络地址:0~127
        //02:00:  通道数512
        //00:00:00: 第0个灯RBG
        //00:00:00: 第1个灯RBG
        //...: 第n个灯RBG
        /// </summary>
        /// <returns></returns>
        private byte[] ToSPIData(int dmxIndex, byte[] dmxData)
        {
            string head = "46:51:35:31:32:4e:65:74:";// 8字节数据包头: "FQ512Net" 
            string OpCode = "0b:00:";	 //指令2字节
            string beforeSeq = "40";
            string seq = "ca";
            string afterSeq = "aa";
            string UpdateFlag = "01";//更新标准:0=写到缓存,未输出到dmxData;1=无缓存,立即输出到dmxData
            string Broadcast = "0";//0=没有广播,只控制指定域;1=对设备的所有端口广播;2=对某个子网内的所有域广播;3,对网络下的所有子网广播;0xff=对所有网络设备的所有口广播
            string SubUni = "00";// IP灯光子网地址:0~255;子网又可分,字节的高4位为子网,字节的低4位为dmxData域,;子网:0~15,DMX域:0~15;
            string net = "" + dmxIndex +"00"; //IP灯光网络地址:0~127
            string preStr = head + OpCode + beforeSeq + seq + afterSeq + UpdateFlag + Broadcast + SubUni + net;
            //preStr = "46513531324e65740b00400000010003";
            byte[] preBytes = StringToByte(preStr);
            byte[] toSend = new byte[preBytes.Length + dmxData.Length];
            Array.Copy(preBytes, 0, toSend, 0, preBytes.Length);
            Array.Copy(dmxData, 0, toSend, preBytes.Length, dmxData.Length);
            return toSend;
        }

        /// <summary>
        /// 打包方法,可以将十六制字符串转成byte[] ,字符串没有空格
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        private byte[] StringToByte(string s)
        {
            string temps = s.Replace(" ", "").Replace(":", "");
            if (temps.Length % 2 != 0)
            {
                temps = "0" + temps;
            }
            byte[] tempb = new byte[temps.Length / 2];
            int j = 0;
            for (int i = 0; i < temps.Length; i = i + 2, j++)
            {
                tempb[j] = Convert.ToByte(temps.Substring(i, 2), 16);
            }
            byte[] send = new byte[j];
            Array.Copy(tempb, send, j);
            return send;
        }
    }
}