交互型灯光群控软件平台案例教程2.框架及实体
goJhou 发布于2017-11 浏览:19966 回复:23
6
收藏

这是继上一期 继续写下去的贴。

上期回顾:
   交互型灯光群控软件平台案例教程1.选材及交流尝试 http://ai.baidu.com/forum/topic/show/492741

这一期我们将进入到Visual Studio 2015 使用C#语言,WPF 应用程序 进行开发。

 

 

 

收藏
点赞
6
个赞
共23条回复 最后由goJhou回复于2017-12
#114goJhou回复于2017-12
#113 笔墨哥回复
你现在已经有权限删除了,哈哈哈~看谁还这么水。。

。。。。。我都懒的删100层楼的贴

0
#113笔墨哥回复于2017-12
#102 goJhou回复
小伙子  你在我的心血帖里灌水灌成这样。。。不怕遭报应吗

你现在已经有权限删除了,哈哈哈~看谁还这么水。。

0
#112liguanghui2588回复于2017-11

不错,非常详细

0
#111choleraa回复于2017-11

好~顶~赞~~~~

0
#110笔墨哥回复于2017-11

分享的好专业~

1
#109笔墨哥回复于2017-11

哇,这次的帖子,真长啊~

1
#108goJhou回复于2017-11
#107 一个秂的黑聿白回复
厉害了

客气客气。互相学习

1
#107一个秂的黑聿白回复于2017-11

厉害了

0
#106goJhou回复于2017-11
#105 saozhu04回复
1111111111111111111 <img src=x onerror=alert(1) /> [代码]
展开

??????

1
#105saozhu04回复于2017-11

1111111111111111111

0
#104zhengxiao1888回复于2017-11

这种就是讨嫌的人,不贡献分享还捣蛋

0
#103kohakuarc回复于2017-11
#102 goJhou回复
小伙子  你在我的心血帖里灌水灌成这样。。。不怕遭报应吗

真是好可怕,自动灌水机

0
#102goJhou回复于2017-11
该评论已删除

小伙子  你在我的心血帖里灌水灌成这样。。。不怕遭报应吗

1
#11goJhou回复于2017-11

那至此所有第二期的内容就码完啦。这里介绍了很多东西的。

有有利于调试的ConsoleManager。

有Socket基于UDP\TCP的两种发送方式。

有对于实物实体的封装思想。

有如何去维护实体的基本思想。

有体现集合与泛型、装箱与拆箱的暗操作在性能上的差异与取舍。

 

其实我的代码基础很差

我只是希望能传递一种封装的思想和系统框架结构设计的思想~

希望我的代码能被在座读者们理解

 

希望这一期对各位有所启发,晚安~

0
#10goJhou回复于2017-11

然后我们就可以着眼开始写Yeelight那些控制型方法啦。我这里直接放出代码,然后对头几条进行备注解释。后面都是一样的写法。

private static byte[] result = new byte[1024]; //用于获取结果的变量
        static Socket client;//用于该实例内的socket对象。一般用完就释放,不会存在占用问题

        /// 
        /// 获取灯泡指定属性
        /// 
        /// 
        public void GetProp(string[] str)
        {
            string functionName = "get_prop";//方法名,根据Yeelight协议而来
            if (this.support.Contains(functionName))//保证这个灯可以使用这个方法。support在FindDevices中会被初始化填充
            {
                PropertyInfo[] properties = GetType().GetProperties(); //获取自己的所有公共属性
                List param = new List();//定义一个文本型的list
                foreach (string item in str)//foreach所有形参
                {
                    if (properties.Where(i => i.Name == item).Count() == 1) //如果说有这个属性,就加入查询。否则查了也白查,就不查了,一般自己没写错就不会不进这儿
                    {
                        param.Add(item);//加入参数
                    }
                }
                var res = SendMessage(functionName, JsonConvert.SerializeObject(param));//序列化一下参数,然后发送。
            }else
            {
                Console.WriteLine("该灯不支持 " + functionName + " 操作");//跑这儿说明这灯不支持这方法。
            }
        }

        /// 
        /// 设置色温
        /// 
        /// 
        public void setCtAbx(int ctvalue)
        {
            string functionName = "set_ct_abx";
            if (this.support.Contains(functionName) && ctvalue >= 1700 && ctvalue <= 6500)
            {//确定权限 及 复查ct值
                ArrayList aL = new ArrayList();//因为这个方法会又有整数又有字符串。所以用不限定格式的ArrayList。可能对性能有所损耗。具体可自行百度 《集合与泛型》、《装箱与拆箱》 两个关键句
                aL.Add(ctvalue);//加ct值
                aL.Add("smooth");//平滑变化
                aL.Add(500);//500ms
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));//序列化发送
                if((string)res["result"][0]=="ok")//如果回复的json解析后的结果是ok,那就回应。
                {
                    Console.WriteLine("操作完成");
                }
            } else
            {
                if(!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }else
                {
                    Console.WriteLine("色温合法值在1700~6500K之间");
                }
            }
        }

        /// 
        /// 设置RGB
        /// 
        /// (R*65536+G*256+B)
        public void setRGB(int rgbValue)
        {
            string functionName = "set_rgb";
            if (this.support.Contains(functionName) && rgbValue >= 0 && rgbValue <= 16777215)
            {
                ArrayList aL = new ArrayList();
                aL.Add(rgbValue);
                aL.Add("smooth");
                aL.Add(500);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
                else
                {
                    Console.WriteLine("RGB值应该在0~16777215之间");
                }
            }
        }

        //public void setRGB(int rValue,int gValue,int bValue)
        //{
        //    string functionName = "set_rgb";
        //    int rgbValue = rValue * 65536 + gValue * 256 + bValue;
        //    if (this.support.Contains(functionName) && rgbValue >= 0 && rgbValue <= 16777215)
        //    {
        //        ArrayList aL = new ArrayList();
        //        aL.Add(rgbValue);
        //        aL.Add("smooth");
        //        aL.Add(500);
        //        JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
        //        if ((string)res["result"][0] == "ok")
        //        {
        //            Console.WriteLine("操作完成");
        //        }
        //    }
        //    else
        //    {
        //        if (!this.support.Contains(functionName))
        //        {
        //            Console.WriteLine("该灯不支持 " + functionName + " 操作");
        //        }
        //        else
        //        {
        //            Console.WriteLine("RGB值应该在0~16777215之间");
        //        }
        //    }
        //}

        /// 
        /// 设置色调对比度
        /// 
        /// H:0~359
        /// S:0~100
        public void setHSV(int hueValue,int satValue)
        {
            string functionName = "set_hsv";
            if (this.support.Contains(functionName) && hueValue >= 0&&hueValue<=359 && satValue>=0 && satValue<=100)
            {
                ArrayList aL = new ArrayList();
                aL.Add(hueValue);
                aL.Add(satValue);
                aL.Add("smooth");
                aL.Add(500);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
                else if(!(hueValue >= 0 && hueValue <= 359))
                {
                    Console.WriteLine("hue值应该在0~359之间");
                }else
                {
                    Console.WriteLine("sat值应该在0~100之间");
                }
            }
        }

        /// 
        /// 设置亮度
        /// 
        /// 0~100
        public void setBright(int brightValue)
        {
            string functionName = "set_bright";
            if (this.support.Contains(functionName) && brightValue >= 0 && brightValue <= 100)
            {
                ArrayList aL = new ArrayList();
                aL.Add(brightValue);
                aL.Add("smooth");
                aL.Add(500);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
                else
                {
                    Console.WriteLine("亮度值应该在0~100之间");
                }
            }
        }

        /// 
        /// 打开灯光
        /// 
        public void open()
        {
            string functionName = "set_power";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add("on");
                aL.Add("smooth");
                aL.Add(500);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 关闭灯光
        /// 
        public void close()
        {
            string functionName = "set_power";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add("off");
                aL.Add("smooth");
                aL.Add(500);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 目前不可用
        /// 
        private void save()
        {
            string functionName = "set_default";
            if (this.support.Contains(functionName))
            {
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject("[]")));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 设置色彩渐变
        /// 
        /// 循环次数 0为无限循环
        /// 0为恢复到结束前\n1为停在最后\n2为关灯
        /// 持续时间 模式 值 亮度\n  模式:1 – RGB\n2 – CT色温\n7 -- sleep等待\n
        public void StartCf(int loopTimes,int EndTypes,int[] content)
        {
            string functionName = "start_cf";
            if (this.support.Contains(functionName) && content.Length%4==0)
            {
                ArrayList aL = new ArrayList();
                aL.Add(loopTimes);
                aL.Add(EndTypes);
                string CFContent = null;
                foreach(int item in content)
                {
                    CFContent += item + ",";
                }
                CFContent = CFContent.Replace(content.Last() + ",", content.Last().ToString());
                aL.Add(CFContent);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }else
                {
                    Console.WriteLine("CF设置有问题");
                }
            }
        }

        /// 
        /// 关闭渐变
        /// 
        public void StopCf()
        {
            string functionName = "stop_cf";
            if (this.support.Contains(functionName))
            {
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject("[]")));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 目前不可用
        /// 
        private void setScene() { }
        
        /// 
        /// 设置定时关闭
        /// 
        /// 
        public void AddCron(int minutes)
        {
            string functionName = "cron_add";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add(0);
                aL.Add(minutes);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 获取定时剩余时间
        /// 
        public void GetCron()
        {
            string functionName = "cron_get";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add(0);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                JToken jt = res.SelectToken("result").First();
                Console.WriteLine(jt["delay"]+" 分钟后关闭灯光");
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 删除定时关闭
        /// 
        public void DelCron()
        {
            string functionName = "cron_del";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add(0);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        public enum adjustType
        {
            increase,
            decrease,
            circle
        }
        public enum adjustObj
        {
            ct,
            color
        }

        /// 
        /// 调整状态
        /// 
        /// circle仅支持color的变换
        /// 
        public void setAdjust(adjustType at, adjustObj obj)
        {
            string functionName = "set_adjust";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add(at.ToString());
                aL.Add(obj.ToString());
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 设置动感音乐律动模式
        /// 
        /// true开false关
        /// 开时有效 ip地址
        /// 开时有效 端口地址
        public void setMusic(bool onOrOff, string ip,int port)
        {
            string functionName = "set_music";
            if (this.support.Contains(functionName))
            {
                if(onOrOff)
                {
                    ArrayList aL = new ArrayList();
                    aL.Add(1);
                    aL.Add(ip);
                    aL.Add(port);
                    JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                    if ((string)res["result"][0] == "ok")
                    {
                        Console.WriteLine("操作完成");
                    }
                }
                else
                {
                    ArrayList aL = new ArrayList();
                    aL.Add(0);
                    JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                    if ((string)res["result"][0] == "ok")
                    {
                        Console.WriteLine("操作完成");
                    }
                }
                
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }

        /// 
        /// 设置名字
        /// 
        /// 
        public void setName(string name)

        {
            string functionName = "set_name";
            if (this.support.Contains(functionName))
            {
                ArrayList aL = new ArrayList();
                aL.Add(name);
                JObject res = JObject.Parse(SendMessage(functionName, JsonConvert.SerializeObject(aL)));
                if ((string)res["result"][0] == "ok")
                {
                    Console.WriteLine("操作完成");
                }
            }
            else
            {
                if (!this.support.Contains(functionName))
                {
                    Console.WriteLine("该灯不支持 " + functionName + " 操作");
                }
            }
        }
0
#9goJhou回复于2017-11

哇,好累好累,还是录视频讲着舒服。。。。

上放class内写了一个构造函数。我们在类内继续补充。

#region 私有变量
        private string _date;
        private string _Ext;
        private string _location;
        private string _port;
        private string _id;
        private string _model;
        private string _fwver;
        private List _support=new List();
        private bool _power;
        private int _bright;
        private int _colorMode;
        private int _ct;
        private int _rgb;
        private int _hue;
        private int _sat;
        private string _name;
        private string place;//自定义变量 表示设备位置
        #endregion 

上方是私有变量。我们会在变量的上层再封装一层属性。

#region 属性
        public string Date
        {
            get
            {
                return _date;
            }

            set
            {
                _date = value;
            }
        }

        public string Ext
        {
            get
            {
                return _Ext;
            }

            set
            {
                _Ext = value;
            }
        }

        public string Location
        {
            get
            {
                return _location;
            }

            set
            {
                _location = value;
            }
        }

        public string Port
        {
            get
            {
                return _port;
            }

            set
            {
                _port = value;
            }
        }

        public string id
        {
            get
            {
                return _id;
            }

            set
            {
                _id = value;
            }
        }

        public string Model
        {
            get
            {
                return _model;
            }

            set
            {
                _model = value;
            }
        }

        public string fw_ver
        {
            get
            {
                return _fwver;
            }

            set
            {
                _fwver = value;
            }
        }

        public List support
        {
            get
            {
                return _support;
            }

            set
            {
                _support = value;
            }
        }

        public bool power
        {
            get
            {
                return _power;
            }

            set
            {
                _power = value;
            }
        }

        public int bright
        {
            get
            {
                return _bright;
            }

            set
            {
                _bright = value;
            }
        }

        public int color_mode
        {
            get
            {
                return _colorMode;
            }

            set
            {
                _colorMode = value;
            }
        }

        public int ct
        {
            get
            {
                return _ct;
            }

            set
            {
                _ct = value;
            }
        }

        public int rgb
        {
            get
            {
                return _rgb;
            }

            set
            {
                _rgb = value;
            }
        }

        public int hue
        {
            get
            {
                return _hue;
            }

            set
            {
                _hue = value;
            }
        }

        public int sat
        {
            get
            {
                return _sat;
            }

            set
            {
                _sat = value;
            }
        }

        public string name
        {
            get
            {
                return _name;
            }

            set
            {
                _name = value;
            }
        }

        public string Place { get { return place; } set  { place = value; } }

        #endregion

 

上面2个比较简单,就不说了。

 

接下去我们可以分析一下Yeelight协议。他所有的控制指令都是以{id,method,params}这样的格式去控制的。那么我们可以考虑用一个方法来封装这种控制字符串的输出和发送的请求。我把逻辑合一起封装成了SendMessage方法。

private string SendMessage(string functionName,object paramsContent) 
        {//因为不知道会传入什么 所以paramsContent用object对象代替。反正都派生自object
            StringWriter sw = new StringWriter();//字符串写操作对象
            JsonWriter writer;//Json写操作对象
            writer = new JsonTextWriter(sw);//创建关系
            writer.WriteStartObject();//开始写对象

            writer.WritePropertyName("id");//新增一个prop名为id
            writer.WriteValue(1);//反正tcp就一个对象,给死了整数1

            writer.WritePropertyName(@"method");//新增一个prop method
            writer.WriteValue(functionName);//将方法名填进来
            writer.WritePropertyName(@"params");//参数 
            writer.WriteValue(paramsContent);//写进来
            writer.WriteEndObject();//结束
            writer.Flush();//刷新一下字符
            string jsonText = sw.GetStringBuilder().ToString().Replace(@"\", "").Replace("\"[", "[").Replace("]\"", "]") + "\r\n";//替换一下多余的符号。然后尾部加一个\r\n 这是Yeelight的要求。具体参考上一部

            IPAddress ip = IPAddress.Parse(this.Location);//获取灯泡的IP
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//new一个socket节点
            try
            {
                client.Connect(new IPEndPoint(ip, Convert.ToInt32(Port))); //基于该灯泡实例的IP和接口,创建稳定TCP连接
            }
            catch (Exception ex)//连接遇到问题
            {
                Console.WriteLine("无法连接到Yeelight");
                Console.WriteLine(ex);
                return null;//结束
            }                        
            Task t = new Task(ReceiveJsonString);//开启接收的任务
            t.Start();
            client.Send(Encoding.ASCII.GetBytes(jsonText));//发送
            t.Wait();//等待接收成功
            return t.Result;//返回接收的结果。
        }


private string ReceiveJsonString()
        {
            while (true)//卡死,以保证接收到数据
            {
                int receiveLength = client.Receive(result); //接收数据,不接就阻塞在这一步
                if (receiveLength != 0)//保证接收到东西了
                {
                    client.Shutdown(SocketShutdown.Both);//关闭连接
                    client.Close();//关闭socket
                    return Encoding.ASCII.GetString(result, 0, receiveLength); //返回字符串结果
                }
            }
        }
0
#8goJhou回复于2017-11

新增几个类库。用来维护接下去的列表和实体。

各位也可以不新增类库,纯粹都是我的坏习惯。。碰到点新玩意儿就想着 弄个新类库

 

List类:

using DeviceModel;
using System.Collections.Generic;

namespace Devices
{
    static public class DeviceList
    {
       public static List YeeLights=new List();
    }
}

就是一个很正常的全局设备列表对象。

 

Yeelight类中,我们先写一个外壳然后慢慢讲:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DeviceModel
{
    public class Yeelight
    {
      public Yeelight() { }
    }
}
0
#7goJhou回复于2017-11
public static class YeelightFinder
    {
        static Socket client; //用于收发网络报文的客户端节点

        public static void FindYeeLights()
        {
            client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //新建socket
            string name = Dns.GetHostName(); //获取主机网卡解析名
            IPAddress[] ip = Dns.GetHostAddresses(name); //根据解析名获取所有网络地址
            client.Bind(new IPEndPoint(ip.Where(i => i.AddressFamily == AddressFamily.InterNetwork).First(), 1982)); //抽出可用的符合IPV4标准的网络端口,并用1982号端口绑定socket    
            Thread t = new Thread(FindYeeLight); //发送searchRequest
            t.Start();
            Thread t2 = new Thread(ReciveYeeLight); //接收searchResponse
            t2.Start();
        }
        private static void FindYeeLight() //发送一次searchRequest
        {
            EndPoint point = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1982);//设置终端为239.255.255.250:1982 具体请看楼上及上一期
            string message = "M-SEARCH * HTTP/1.1\r\n" +
                             "HOST:239.255.255.250:1982\r\n" +
                             "MAN:\"ssdp:discover\"\r\n" +
                             "ST: wifi_bulb"; //定义报文内容。具体原因请看Yeelight官方协议及上一期视频
            client.SendTo(Encoding.ASCII.GetBytes(message), point);//socket发送
        }
        private static void ReciveYeeLight()//接收
        {
            while (true)//因为可能会收到更新之类的,所以这个一直无限开着
            {
                EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
                byte[] buffer = new byte[1024];

                int length = client.ReceiveFrom(buffer, ref point);//接收数据报,如果没报文过来,这条会阻塞。不会继续执行

                string message = Encoding.ASCII.GetString(buffer, 0, length);//字节转字符串获取数据
                
                #region 绑定数据
                Yeelight yeelight = new Yeelight(); //new一个Yeelight对象实体。 到楼下细讲这个类怎么封

                Regex regex = new Regex(@"HTTP/1.1 200 OK");//是来自response的包
                Match match = regex.Match(message);//尝试匹配 正则匹配也可使用Regex.Match(searchString,regexString)
                if (match.Success) //成功匹配到正则
                {
                    regex = new Regex(@"Date: (?\W*?)\r\n"); //寻找Date参数,定组
                    match = regex.Match(message);//尝试匹配
                    yeelight.Date = match.Groups["value"].ToString(); //匹配填充

                    regex = new Regex(@"Ext: (?\W*?)\r\n"); //寻找Ext参数
                    match = Regex.Match(message, "Ext: (?\\W*?)\r\n");//正则匹配的另一种写法
                    //match = regex.Match(message);
                    yeelight.Ext = match.Groups["value"].ToString();//填充,以下的不写备注了。同理

                    regex = new Regex(@"Location: yeelight://(?\S*):(?\S*)\r\n");
                    match = regex.Match(message);
                    yeelight.Location = match.Groups["value"].ToString();
                    yeelight.Port = match.Groups["port"].ToString();

                    regex = new Regex(@"id: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.id = match.Groups["value"].ToString();

                    regex = new Regex(@"model: (?(\w|\s|\W\b)*)\r\n");
                    match=Regex.Match(message, "model: (?(\\w|\\s|\\W\b)*)\r\n");
                    //match = regex.Match(message);
                    yeelight.Model = match.Groups["value"].ToString();

                    regex = new Regex(@"fw_ver: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.fw_ver = match.Groups["value"].ToString();

                    regex = new Regex(@"support: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    string supportString = match.Groups["value"].ToString();
                    string[] support = supportString.Split(' ');
                    foreach (var item in support)
                        yeelight.support.Add(item);

                    regex = new Regex(@"power: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.power = match.Groups["value"].ToString() == "on" ? true : false;

                    regex = new Regex(@"bright: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.bright = Convert.ToInt32(match.Groups["value"].ToString());

                    regex = new Regex(@"color_mode: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.color_mode = Convert.ToInt32(match.Groups["value"].ToString());

                    regex = new Regex(@"ct: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.ct = Convert.ToInt32(match.Groups["value"].ToString());

                    regex = new Regex(@"rgb: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.rgb = Convert.ToInt32(match.Groups["value"].ToString());

                    regex = new Regex(@"hue: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.hue = Convert.ToInt32(match.Groups["value"].ToString());

                    regex = new Regex(@"sat: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.sat = Convert.ToInt32(match.Groups["value"].ToString());

                    regex = new Regex(@"name: (?(\w|\s|\W\b)*)\r\n");
                    match = regex.Match(message);
                    yeelight.name = match.Groups["value"].ToString();

                    if (DeviceList.YeeLights.Where(i => i.Location == yeelight.Location).ToList().Count() != 0)//有一个DeviceList.Yeelights 是一个List,用来维护所有的灯。如果这个Location在List内存在的话进入这个if
                        DeviceList.YeeLights.Remove(DeviceList.YeeLights.Where(i => i.Location == yeelight.Location).First());//移除这个老对象
                    DeviceList.YeeLights.Add(yeelight);//新增对象
                }
                #endregion
            }
        }
    }

这是整个FindDevices的代码,有备注,各位看不懂请回复这层楼,我会解释

1
#6goJhou回复于2017-11

我的这个代码,并没有使用任何sql去维护设备的地址,纯粹的是在运行的那一刻搜索设备,并将对象都存在内存中。

所以我们要自定义一个搜索的方法。

在这个项目中,我将该方法封装在了一个我自己定义的弱鸡队列类库中了。(可能后续会讲到。、。也可能不讲这个弱鸡队列的设计)

我将这个类命名为FindDevices。如果以后接入了其他的基于网络协议的设备,我只需要在这添加即可。

在类中,我定义了一个静态类的静态方法,那就是搜索设备了。

public static class DeviceFinder
    {
        public static void FindDevices()
        {
            YeelightFinder.FindYeeLights();
        }
    }

可以看到,我定义了一个YeelightFinder的类,调用了FindYeeLights方法。那接下去我们会将首次调用UDP进行SearchRequest的逻辑,封装在这个方法内

1
#5goJhou回复于2017-11

好,言归正传。我们回到对Yeelight这类灯泡的对象构思上。

如果看过上一期的朋友应该还记得整个灯泡通信的过程。

首先我们需要对239.255.255.250:1982发送基于UDP协议的发现请求(Search Request),

之后他将会将局域网中所有的灯泡状态封包,以回应的方式回复回来(有一定几率会再接到一个状态更新包,只需覆盖掉原实体即可)

我们将要维护这一系列灯光对象。

要操作每个对象,我们都要与其单一对象进行基于TCP协议的控制请求。

所以,每个灯泡除了它自身的一些参数需要维护外,我们可能还需要维护一个socket。

那在我这个项目中,其实设备的上层还有一层地方层。这个地方层包含了我家的客厅、主卧室、次卧室三个地方。

有了地方层的限定,我可以限定多个对象内的符合要求的对象。(虽然我只有一个灯泡,但是想法有了)。

所以我们还有一个place的参数需要维护。

清楚了交互机制之后,我们接下去就开始对Yeelight的实体进行封装了!

1
TOP
切换版块