黄学彪
2020-12-16 0d9f64668fd7350d6a21fd157e32009a96d98134
ZigbeeApp/Shared/Phone/Common/Logic/HdlTemplateCommonLogic.cs
old mode 100755 new mode 100644
File was renamed from ZigbeeApp/Shared/Phone/TemplateData/TemplateCommonLogic.cs
@@ -1,2139 +1,2166 @@
using Shared.Phone.UserCenter;
using System;
using System.Collections.Generic;
using System.Text;
using ZigBee.Device;
namespace Shared.Phone.TemplateData
{
    /// <summary>
    /// 模板的共通逻辑类
    /// </summary>
    public class TemplateCommonLogic
    {
        #region ■ 变量声明___________________________
        /// <summary>
        /// 模板的共通逻辑类
        /// </summary>
        private static TemplateCommonLogic m_Current = null;
        /// <summary>
        /// 模板的共通逻辑类
        /// </summary>
        public static TemplateCommonLogic Current
        {
            get
            {
                if (m_Current == null)
                {
                    m_Current = new TemplateCommonLogic();
                }
                return m_Current;
            }
        }
        /// <summary>
        /// 模板数据
        /// </summary>
        public TemplateMemoryData modelData = new TemplateMemoryData();
        /// <summary>
        /// 模板文件中 #start# 到 #end# 的内容(临时变量)
        /// </summary>
        private string strTempContentData = string.Empty;
        /// <summary>
        /// 本地模板文件的名字
        /// </summary>
        private const string TemplateFileName = "ModelData_Release.bin";
        #endregion
        #region ■ 加载本地模板缓存___________________
        /// <summary>
        /// 加载本地模板文件缓存(此方法以本地缓存为准,切换住宅时使用)
        /// </summary>
        public void LoadLocalTemplateMemoryData()
        {
            this.modelData = new TemplateMemoryData();
            //保存的路径
            string saveFile = DirNameResourse.LocalTemplateDirectory;
            //如果当前住宅拥有选择的模板
            if (Common.Config.Instance.Home.SelectTemplate != string.Empty)
            {
                string checkFile = System.IO.Path.Combine(saveFile, TemplateFileName);
                //如果本地没有这个bin文件
                if (System.IO.File.Exists(checkFile) == false)
                {
                    //复制模板bin文件到本地的模板文件夹里
                    this.CopyTemplateFileToLocalDirectory(Common.Config.Instance.Home.SelectTemplate);
                }
            }
            //获取这个路径下面全部的文件
            var listFile = HdlFileLogic.Current.GetFileFromDirectory(saveFile);
            //模板Bin文件
            string templateBinFile = string.Empty;
            //这里是读取他上一次编辑完成之后的模板数据(也就是编辑到一半之后,退出App,下一次再编辑)
            foreach (var fileName in listFile)
            {
                if (fileName == TemplateFileName)
                {
                    //模板Bin文件
                    templateBinFile = fileName;
                    continue;
                }
                if (fileName.StartsWith("Device_") == false)
                {
                    //只要设备
                    continue;
                }
                string fileData = HdlFileLogic.Current.ReadFileTextContent(System.IO.Path.Combine(saveFile, fileName));
                if (fileData == null)
                {
                    continue;
                }
                string deviceData = string.Empty;
                ModelDeviceSaveEnum saveDiv = ModelDeviceSaveEnum.A未定义;
                //根据换行符切分数据文本
                string[] arryData = fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string strData in arryData)
                {
                    //设备数据标志
                    if (strData.StartsWith("===>") == true)
                    {
                        if (deviceData != string.Empty)
                        {
                            //反序列化设备的保存文件内容
                            var tempData = this.DeserializeDeviceDataByDiv(saveDiv, deviceData);
                            //将设备模板数据添加入缓存
                            string mainKey = Common.LocalDevice.Current.GetDeviceMainKeys(tempData.DeviceMac, tempData.DeviceEpoint);
                            this.SetTemplateDeviceDataToMemmory(tempData, deviceData, mainKey, true);
                        }
                        //清空
                        deviceData = string.Empty;
                        saveDiv = (ModelDeviceSaveEnum)Convert.ToInt32(strData.Substring(4));
                        continue;
                    }
                    deviceData += strData;
                }
                if (deviceData != string.Empty)
                {
                    //反序列化设备的保存文件内容
                    var tempData = this.DeserializeDeviceDataByDiv(saveDiv, deviceData);
                    //将设备模板数据添加入缓存
                    string mainKey = Common.LocalDevice.Current.GetDeviceMainKeys(tempData.DeviceMac, tempData.DeviceEpoint);
                    this.SetTemplateDeviceDataToMemmory(tempData, deviceData, mainKey, true);
                }
            }
            //读取模板Bin文件
            if (templateBinFile != string.Empty)
            {
                bool hadRoom = HdlRoomLogic.Current.GetAllListRooms().Count > 1 && Common.Config.Instance.Home.FloorDics.Count == 0;
                //开始读取文件内容
                this.ReadTemplateFileMethord((strData, saveDiv, deviceType) =>
                {
                    //在加载本地缓存的前提下,处理模板文件里面的特殊内容
                    var result = this.AdjustTemplateBinFileContentOnLoadMemory(strData, hadRoom);
                    //false代表它不是特殊内容
                    if (result == false)
                    {
                        //处理模板文件里面的共通内容
                        //因为上面已经加载了指定本地的缓存,所以这里不需要添加入dicDeviceTemplateData中
                        this.AdjustTemplateBinFileCommonContent(strData, saveDiv, deviceType, false);
                    }
                });
            }
            //清空对象缓存
            this.strTempContentData = string.Empty;
            //加载设备和网关模板选择的数据
            this.modelData.dicDeviceTemplateSelect = new Dictionary<string, string>();
            this.modelData.dicGatewayTemplateSelect = new Dictionary<string, string>();
            string fileData2 = HdlFileLogic.Current.ReadFileTextContent(DirNameResourse.DeviceTemplateSelectFile);
            if (fileData2 != null)
            {
                //设备选择的模板对象(keys:本地设备的Mac value:模板中的Mac)
                this.modelData.dicDeviceTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(fileData2);
            }
            fileData2 = HdlFileLogic.Current.ReadFileTextContent(DirNameResourse.GatewayTemplateSelectFile);
            if (fileData2 != null)
            {
                //网关对象选择的模板对象(keys:本地网关ID,  value:模板中的网关ID)
                this.modelData.dicGatewayTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(fileData2);
            }
        }
        /// <summary>
        /// 在加载本地缓存的前提下,处理模板文件里面的特殊内容
        /// </summary>
        /// <param name="strData">模板文件中的行数据</param>
        /// <param name="hadRoom">是否已经有了房间</param>
        private bool AdjustTemplateBinFileContentOnLoadMemory(string strData, bool hadRoom)
        {
            //场景对象
            if (strData == "#SceneTemplate END#")
            {
                if (hadRoom == false)
                {
                    //只初始化一次,有房间时代表已经不是第一次加载了
                    var scene = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.SceneUI>(this.strTempContentData);
                    scene.Save();
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //楼层对象
            else if (strData == "#FloorInfo END#")
            {
                if (hadRoom == false)
                {
                    //只初始化一次,有房间时代表已经不是第一次加载了
                    Common.Config.Instance.Home.FloorDics = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                    Common.Config.Instance.Home.Save(false);
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //房间对象
            else if (strData == "#RoomInfo END#")
            {
                var room = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.Room>(this.strTempContentData);
                //各自端点所处的房间ID,保存起来
                foreach (var deviceKey in room.ListDevice)
                {
                    this.modelData.dicDeviceTemplateRoom[deviceKey] = room.Id;
                }
                if (hadRoom == false)
                {
                    //第一次加载,设备列表需要清空,选择设备模板时,才添加
                    room.ListDevice.Clear();
                    room.Save();
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //设备选择的模板
            else if (strData == "#DeviceSelectTemplate END#")
            {
                //这个东西在这个分支下不从文件中读取,从本地缓存文件当中获取
                this.strTempContentData = string.Empty;
                return true;
            }
            //网关选择的模板
            else if (strData == "#GatewaySelectTemplate END#")
            {
                //这个东西在这个分支下不从文件中读取,从本地缓存文件当中获取
                this.strTempContentData = string.Empty;
                return true;
            }
            return false;
        }
        #endregion
        #region ■ 根据模板Bin文件恢复数据____________
        /// <summary>
        /// 根据模板Bin文件,恢复数据(分两个函数吧,太难控制了)
        /// </summary>
        public void RecoverDataByTemplateBinFile()
        {
            //重新初始化
            this.modelData = new TemplateMemoryData();
            //开始读取文件内容
            this.ReadTemplateFileMethord((strData, saveDiv, deviceType) =>
            {
                //在恢复数据的前提下,处理模板文件里面的特殊内容
                var result = this.AdjustTemplateBinFileContentOnRecover(strData);
                //false代表它不是特殊内容
                if (result == false)
                {
                    //处理模板文件里面的共通内容
                    //因为是以模板来恢复住宅数据,所以这里需要添加入dicDeviceTemplateData中
                    this.AdjustTemplateBinFileCommonContent(strData, saveDiv, deviceType, true);
                }
            });
            //清空对象缓存
            this.strTempContentData = string.Empty;
            //删掉这两个保存选择模板的文件(这两个东西可能还存在)
            HdlFileLogic.Current.DeleteFile(DirNameResourse.DeviceTemplateSelectFile);
            HdlFileLogic.Current.DeleteFile(DirNameResourse.GatewayTemplateSelectFile);
            //再次初始化房间
            HdlRoomLogic.Current.InitAllRoom();
            //无模板模式时,恢复备份的时候,把备份文件删除
            if (Common.Config.Instance.Home.TemplateMode != 2)
            {
                //存放的路径
                string fullFile = System.IO.Path.Combine(DirNameResourse.LocalTemplateDirectory, TemplateFileName);
                HdlFileLogic.Current.DeleteFile(fullFile);
            }
            //覆盖物理设备所在的房间数据
            HdlFileLogic.Current.SaveFileContent(DirNameResourse.DeviceRoomIdFile, this.modelData.dicDeviceTemplateRealRoom);
        }
        /// <summary>
        /// 在恢复数据的前提下,处理模板文件里面的特殊内容
        /// </summary>
        /// <param name="strData">模板文件中的行数据</param>
        private bool AdjustTemplateBinFileContentOnRecover(string strData)
        {
            //场景对象
            if (strData == "#SceneTemplate END#")
            {
                var scene = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.SceneUI>(this.strTempContentData);
                scene.Save();
                this.strTempContentData = string.Empty;
                return true;
            }
            //楼层对象
            else if (strData == "#FloorInfo END#")
            {
                Common.Config.Instance.Home.FloorDics = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                Common.Config.Instance.Home.Save(false);
                this.strTempContentData = string.Empty;
                return true;
            }
            //房间对象
            else if (strData == "#RoomInfo END#")
            {
                var room = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.Room>(this.strTempContentData);
                room.Save();
                //各自端点所处的房间ID,保存起来
                foreach (var deviceKey in room.ListDevice)
                {
                    this.modelData.dicDeviceTemplateRoom[deviceKey] = room.Id;
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //设备选择的模板
            else if (strData == "#DeviceSelectTemplate END#")
            {
                this.modelData.dicDeviceTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                this.strTempContentData = string.Empty;
                return true;
            }
            //网关选择的模板
            else if (strData == "#GatewaySelectTemplate END#")
            {
                this.modelData.dicGatewayTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                this.strTempContentData = string.Empty;
                return true;
            }
            return false;
        }
        #endregion
        #region ■ 处理模板文件里面的共通内容_________
        /// <summary>
        /// 处理模板文件里面的共通内容
        /// </summary>
        /// <param name="strData">模板文件中的行数据</param>
        /// <param name="saveDiv">模板设备保存的区分(设备数据时有效)</param>
        /// <param name="deviceType">模板中设备的deviceType(设备数据时有效,反射用)</param>
        /// <param name="addToTemplate">是否添加到设备模板缓存中</param>
        private void AdjustTemplateBinFileCommonContent(string strData, ModelDeviceSaveEnum saveDiv, string deviceType, bool addToTemplate)
        {
            //模板基本数据
            if (strData == "#TemplateData END#")
            {
                var templateData = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(this.strTempContentData);
                this.modelData.TemplateName = templateData.ModelName;
                this.strTempContentData = string.Empty;
                return;
            }
            //设备模板
            else if (strData == "#DeviceTemplate END#")
            {
                //反序列化设备的保存文件内容
                var tempData = this.DeserializeDeviceDataByDiv(saveDiv, this.strTempContentData);
                //将设备模板数据添加入缓存(此处特殊,不需要加入设备模板缓存中)
                string mainKey = Common.LocalDevice.Current.GetDeviceMainKeys(tempData.DeviceMac, tempData.DeviceEpoint);
                this.SetTemplateDeviceDataToMemmory(tempData, this.strTempContentData, mainKey, addToTemplate);
                this.strTempContentData = string.Empty;
                return;
            }
            //设备对象
            else if (strData == "#DeviceInfo END#")
            {
                //反序列化设备
                CommonDevice device = null;
                if (HdlCheckLogic.Current.CheckIsNumber(deviceType) == true)
                {
                    //数值型为新数据,直接转换
                    device = CommonDevice.CommonDeviceByByteString(Convert.ToInt32(deviceType), this.strTempContentData);
                }
                else
                {
                    //字符串型为旧数据,需要特殊处理
                    var myType = (DeviceType)Enum.Parse(typeof(DeviceType), deviceType);
                    device = CommonDevice.CommonDeviceByByteString((int)myType, this.strTempContentData);
                }
                if (device != null)
                {
                    if (this.modelData.dicDeviceInfo.ContainsKey(device.DeviceAddr) == false)
                    {
                        this.modelData.dicDeviceInfo[device.DeviceAddr] = new List<CommonDevice>();
                    }
                    this.modelData.dicDeviceInfo[device.DeviceAddr].Add(device);
                }
                this.strTempContentData = string.Empty;
                return;
            }
            //网关对象数据
            else if (strData == "#GatewayInfo END#")
            {
                //反序列化设备
                var gateway = Newtonsoft.Json.JsonConvert.DeserializeObject<ZbGateway>(this.strTempContentData);
                this.modelData.dicGatewayInfo[gateway.GwId] = gateway;
                this.strTempContentData = string.Empty;
                return;
            }
            //物理设备的房间
            else if (strData == "#DeviceTemplateRealRoom END#")
            {
                this.modelData.dicDeviceTemplateRealRoom = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                this.strTempContentData = string.Empty;
                return;
            }
            //模板住宅的信息(目前在这里基本没用)
            else if (strData == "#TemplateHomeInfo END#")
            {
                this.strTempContentData = string.Empty;
                return;
            }
            this.strTempContentData += strData;
        }
        #endregion
        #region ■ 读取模板文件内容___________________
        /// <summary>
        /// 读取模板文件内容
        /// </summary>
        /// <param name="AdjustAction">
        /// <para>参数1:模板文件中的行数据</para>
        /// <para>参数2:模板设备保存的区分(设备数据时有效)</para>
        /// <para>参数3:板中设备的deviceType(设备数据时有效,反射用)</para>
        /// </param>
        private void ReadTemplateFileMethord(Action<string, ModelDeviceSaveEnum, string> AdjustAction)
        {
            //保存的路径
            string saveFile = DirNameResourse.LocalTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, TemplateFileName);
            string fileData = HdlFileLogic.Current.ReadFileTextContent(saveFile);
            if (fileData == null)
            {
                AdjustAction = null;
                return;
            }
            var saveDiv = ModelDeviceSaveEnum.A未定义;
            var deviceType = string.Empty;
            //根据换行符切分数据文本
            string[] arryData = fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string strData in arryData)
            {
                if (strData == "#START#")
                {
                    //无附加数据的【数据标题】
                    continue;
                }
                if (strData.StartsWith("#DeviceTemplate START#") == true)
                {
                    //附加数据:设备保存区分
                    saveDiv = (ModelDeviceSaveEnum)Convert.ToInt32(strData.Substring(22));
                    continue;
                }
                if (strData.StartsWith("#DeviceInfo START#") == true)
                {
                    //附加数据:设备对象类型
                    deviceType = strData.Substring(18);
                    continue;
                }
                try
                {
                    //执行数据处理
                    AdjustAction(strData, saveDiv, deviceType);
                }
                catch (Exception ex)
                {
                    HdlLogLogic.Current.WriteLog(ex, "模板bin文件出问题\r\n" + this.strTempContentData);
                    this.strTempContentData = string.Empty;
                }
            }
        }
        #endregion
        #region ■ 反序列化设备的保存文件内容_________
        /// <summary>
        /// 反序列化设备的保存文件内容
        /// </summary>
        /// <param name="saveDiv">保存区分</param>
        /// <param name="fileData"></param>
        /// <returns></returns>
        private TemplateDeviceDataCommon DeserializeDeviceDataByDiv(ModelDeviceSaveEnum saveDiv, string fileData)
        {
            TemplateDeviceDataCommon modelData = null;
            if (saveDiv == ModelDeviceSaveEnum.APir配置)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPirSensorSettion>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A空调摆风功能)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelAcSwingModeSupport>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A空调自定义模式)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelAcModeSupport>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A窗帘手拉控制)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelCurtainHandPullControl>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A窗帘方向及限位)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelCurtainDirectionAndLimite>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A端点名称)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceEpointNameInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A设备名称)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceMacNameInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A设备绑定列表)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceBindData>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板亮度调节)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelBrightnessAdjustInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板节能模式)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelEnergyModeInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板指示灯)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelIndicatorLightInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板震动功能)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelVibrationInfo>(fileData);
            }
            return modelData;
        }
        /// <summary>
        /// 将设备模板数据添加入缓存
        /// </summary>
        /// <param name="modelData">模板数据</param>
        /// <param name="fileData">设备保存在文件中的内容(可为null)</param>
        /// <param name="mainKey">添加的主键</param>
        /// <param name="addToTemplate">是否添加到设备模板缓存中</param>
        private void SetTemplateDeviceDataToMemmory(TemplateDeviceDataCommon modelData, string fileData, string mainKey, bool addToTemplate)
        {
            if (modelData == null)
            {
                return;
            }
            //从模板主文件中获取的设备模板信息,是不需要添加到这个变量中的
            //因为它只能慢慢一个个匹配
            if (addToTemplate == true)
            {
                if (this.modelData.dicDeviceTemplateData.ContainsKey(mainKey) == false)
                {
                    this.modelData.dicDeviceTemplateData[mainKey] = new List<TemplateDeviceDataCommon>();
                }
                this.modelData.dicDeviceTemplateData[mainKey].Add(modelData);
            }
            if (fileData != null)
            {
                //临时缓存:模板中各自端点所保存的内容(keys:设备主键),设备选择模板时,模板数据迁移使用,因为是引用类型,所以需要重新New
                if (this.modelData.dicDeviceFileContent.ContainsKey(mainKey) == false)
                {
                    this.modelData.dicDeviceFileContent[mainKey] = new List<TemplateDeviceContent>();
                }
                var fileCentent = new TemplateDeviceContent();
                fileCentent.saveDiv = modelData.DataSaveDiv;
                fileCentent.FileContent = fileData;
                fileCentent.DeviceMac = modelData.DeviceMac;
                this.modelData.dicDeviceFileContent[mainKey].Add(fileCentent);
            }
        }
        #endregion
        #region ■ 保存模板数据到本地相关_____________
        /// <summary>
        /// 保存模板数据到本地
        /// </summary>
        /// <param name="backupName">备份名称</param>
        public void SaveTemplateDataToLocation(string backupName)
        {
            //获取本地全部的模板列表的基本信息
            var localModel = this.GetLocalAllModelList();
            var fileName = this.GetNewTemplateFileName();
            foreach (var model in localModel)
            {
                //名字一样时
                if (model.ModelName == backupName)
                {
                    fileName = model.FileName;
                    //备份数据已经存在,是否覆盖?
                    this.ShowMassage(ShowMsgType.Confirm, Language.StringByID(R.MyInternationalizationString.BackUpDataIsEsixtAndPickUp), () =>
                    {
                        //将模板数据保存到到指定的文件夹中
                        this.SaveTemplateDataToLocation2(fileName, backupName);
                    });
                    return;
                }
            }
            //将模板数据保存到到指定的文件夹中
            this.SaveTemplateDataToLocation2(fileName, backupName);
        }
        /// <summary>
        /// 保存模板数据到本地
        /// </summary>
        /// <param name="fileName">保存文件的名字</param>
        /// <param name="backName">模板备份的名字</param>
        private void SaveTemplateDataToLocation2(string fileName, string backupName)
        {
            HdlThreadLogic.Current.RunThread(() =>
            {
                ProgressFormBar.Current.Start();
                ProgressFormBar.Current.SetMsg("正在保存模板数据");
                System.Threading.Thread.Sleep(1500);
                //将模板数据保存到到指定的文件夹中
                var fileFullName = this.SaveTemplateDataToFile(fileName, backupName);
                //获取升级固件文件
                var result = HdlFirmwareUpdateLogic.DownLoadTemplateDeviceFirmware(fileFullName, "正在保存升级固件数据");
                if (result == -1)
                {
                    this.ShowMassage(ShowMsgType.Tip, "保存升级固件数据失败");
                }
                else
                {
                    //本地备份保存成功
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.SaveLocalBackDataSuccess));
                }
                ProgressFormBar.Current.Close();
            });
        }
        /// <summary>
        /// 在生成模板数据之前,检测模板数据
        /// </summary>
        private void CheckTempLateDataBeforCreat()
        {
            //为了保证模板里的设备数和本地的一致,所以检测一下
            //如果缺少,则添加修改Mac的数据进去
            //其他的,如果不点击各自的配置界面,则当做是默认设备原来的配置状态
            //获取目前已经设置设备物理名称的设备Mac
            var listMac = new HashSet<string>();
            foreach (var listData in this.modelData.dicDeviceTemplateData.Values)
            {
                if (listData.Count > 0 && listMac.Contains(listData[0].DeviceMac) == true)
                {
                    //已经加了
                    continue;
                }
                foreach (var data in listData)
                {
                    if (data.DataSaveDiv == ModelDeviceSaveEnum.A设备名称)
                    {
                        listMac.Add(data.DeviceMac);
                    }
                }
            }
            var listDevice = Common.LocalDevice.Current.listAllDevice;
            foreach (var device in listDevice)
            {
                if (listMac.Contains(device.DeviceAddr) == false)
                {
                    listMac.Add(device.DeviceAddr);
                    //重新添加Mac名字缓存
                    TemplateDeviceDataLogic.Current.ReDeviceMacName(device, Common.LocalDevice.Current.GetDeviceMacName(device));
                }
                //重新添加端点名字缓存
                TemplateDeviceDataLogic.Current.ReDeviceEpointName(device, Common.LocalDevice.Current.GetDeviceEpointName(device));
            }
        }
        #endregion
        #region ■ 获取模板对象相关___________________
        /// <summary>
        /// 获取本地全部的模板列表的基本信息
        /// </summary>
        /// <returns></returns>
        public List<LocalModelBaseInfo> GetLocalAllModelList()
        {
            var dicData = new Dictionary<string, List<LocalModelBaseInfo>>();
            var listTime = new List<string>();
            var strPath = DirNameResourse.AllResidenceTemplateDirectory;
            //获取全部文件
            var arryFile = System.IO.Directory.GetFiles(strPath, "ModelData_*");
            foreach (string modelFile in arryFile)
            {
                //读取文件内容
                var textValue = HdlFileLogic.Current.ReadFileTextContent(modelFile);
                if (textValue == null)
                {
                    continue;
                }
                //从文件中获取指定的内容
                string modelBaseInfo = this.GetDataFromFileContent(textValue, "#START#", "#TemplateData END#");
                if (modelBaseInfo != string.Empty)
                {
                    var myModel = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(modelBaseInfo);
                    myModel.FileName = modelFile.Substring(strPath.Length + 1);
                    if (dicData.ContainsKey(myModel.EditorTime) == false)
                    {
                        dicData[myModel.EditorTime] = new List<LocalModelBaseInfo>();
                        listTime.Add(myModel.EditorTime);
                    }
                    dicData[myModel.EditorTime].Add(myModel);
                    string homeData = this.GetDataFromFileContent(textValue, "#START#", "#TemplateHomeInfo END#");
                    if (homeData != string.Empty)
                    {
                        var homeInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<TemplateHomeInfo>(homeData);
                        myModel.ListUintContent.AddRange(homeInfo.ListUintContent);
                        myModel.ListUintName.AddRange(homeInfo.ListUintName);
                        myModel.ResidenceAddressName = homeInfo.ResidenceAddressName;
                    }
                }
            }
            //按时间排序
            listTime.Sort();
            var listData = new List<LocalModelBaseInfo>();
            for (int i = listTime.Count - 1; i >= 0; i--)
            {
                listData.AddRange(dicData[listTime[i]]);
            }
            return listData;
        }
        /// <summary>
        /// 获取云端全部的模板列表的基本信息
        /// </summary>
        /// <returns></returns>
        public List<CloundModelBaseInfo> GetCloundAllModelList()
        {
            var pra = new
            {
                RequestVersion = Common.CommonPage.RequestVersion,
                RequestSource = 5,
                LoginAccessToken = Common.Config.Instance.Token
            };
            var result = UserCenterLogic.GetResponseDataByRequestHttps("ProjectTemplate/GetProTemplateList", false, pra);
            if (result == null) { return new List<CloundModelBaseInfo>(); }
            var dicData = new Dictionary<string, List<CloundModelBaseInfo>>();
            var listTime = new List<string>();
            var listCloundData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CloundModelBaseInfo>>(result);
            foreach (var data in listCloundData)
            {
                //变更时间格式
                data.CreatedOnUtc = UserCenterLogic.ConvertUtcTimeToLocalTime(data.CreatedOnUtc).ToString("yyyy.MM.dd HH:mm");
                if (dicData.ContainsKey(data.CreatedOnUtc) == false)
                {
                    dicData[data.CreatedOnUtc] = new List<CloundModelBaseInfo>();
                    listTime.Add(data.CreatedOnUtc);
                }
                dicData[data.CreatedOnUtc].Add(data);
            }
            //按时间排序
            listTime.Sort();
            var listData = new List<CloundModelBaseInfo>();
            for (int i = listTime.Count - 1; i >= 0; i--)
            {
                listData.AddRange(dicData[listTime[i]]);
            }
            return listData;
        }
        /// <summary>
        /// 获取一个新的模板保存文件名
        /// </summary>
        /// <returns></returns>
        public string GetNewTemplateFileName()
        {
            return "ModelData_Local_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".bin";
        }
        /// <summary>
        /// 获取一个新的模板保存文件名
        /// </summary>
        /// <returns></returns>
        public string GetNewTemplateFileName(DateTime dateTime)
        {
            return "ModelData_Local_" + dateTime.ToString("yyyyMMdd_HHmmss") + ".bin";
        }
        #endregion
        #region ■ 上传模板备份_______________________
        /// <summary>
        /// 上传模板备份(内部使用线程来执行,有转圈的界面)
        /// </summary>
        /// <param name="i_localTemplate">本地模板信息</param>
        /// <param name="i_saveName">备份名字</param>
        public void UpLoadTemplateData(LocalModelBaseInfo i_localTemplate, string i_saveName)
        {
            HdlThreadLogic.Current.RunThread(() =>
            {
                ProgressBar.Show();
                //获取云端的模板列表
                var listTemplate = this.GetCloundAllModelList();
                foreach (var data in listTemplate)
                {
                    if (data.TemplateName == i_saveName)
                    {
                        //模板名字已经存在
                        this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.TheTemplateNameIsEsixt));
                        ProgressBar.Close();
                        return;
                    }
                }
                //这里修改掉模板文件里面记载的模板名称
                string templateFile = System.IO.Path.Combine(DirNameResourse.AllResidenceTemplateDirectory, i_localTemplate.FileName);
                string binFileData = HdlFileLogic.Current.ReadFileTextContent(templateFile);
                var arryBinFile = binFileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                //替换目标 这里是模板基本信息的json数据
                string strFileData = arryBinFile[1];
                var templateBaseInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(strFileData);
                templateBaseInfo.ModelName = i_saveName;//更改掉名字
                templateBaseInfo.EditorTime = DateTime.Now.ToString("yyyy.MM.dd HH:mm");//更改掉时间
                //替换对象
                string replaceDta = Newtonsoft.Json.JsonConvert.SerializeObject(templateBaseInfo);
                binFileData = binFileData.Replace(strFileData, replaceDta);
                var pra = new
                {
                    RequestVersion = Common.CommonPage.RequestVersion,
                    RequestSource = 5,
                    LoginAccessToken = Common.Config.Instance.Token,
                    ProTemplateName = i_saveName,
                    ProTemplateDetails = new List<TemplateDetailsInfo>()
                };
                var detailsInfo = new TemplateDetailsInfo();
                detailsInfo.DetailName = "ModelData_Cloud_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".bin";
                detailsInfo.DetailContent = Encoding.UTF8.GetBytes(binFileData);
                pra.ProTemplateDetails.Add(detailsInfo);
                //清掉这个字符串缓存
                binFileData = null;
                var result = UserCenterLogic.GetResultStatuByRequestHttps("ProjectTemplate/AddProTemplate", false, pra);
                if (result == true)
                {
                    //上传模板成功
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.UploadTemplateSuccess));
                }
                else
                {
                    //上传模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.UploadTemplateFail));
                }
                ProgressBar.Close();
            });
        }
        /// <summary>
        /// 上传模板文件的信息
        /// </summary>
        private class TemplateDetailsInfo
        {
            /// <summary>
            /// 文件名字
            /// </summary>
            public string DetailName = string.Empty;
            /// <summary>
            /// 模板内容
            /// </summary>
            public byte[] DetailContent = null;
        }
        #endregion
        #region ■ 下载模板备份_______________________
        /// <summary>
        /// 下载模板备份(内部是使用线程执行,有界面型进度条)
        /// </summary>
        /// <param name="i_templateId">数据库主键</param>
        /// <param name="i_SuccessAction">下载完全成功之后的回调事件,参数为保存模板的全路径(参数null代表失败)</param>
        public void DownLoadTemplate(string i_templateId, Action<string> i_SuccessAction = null)
        {
            HdlThreadLogic.Current.RunThread(() =>
            {
                ProgressFormBar.Current.Start();
                ProgressFormBar.Current.SetMsg("正在下载模板数据");
                System.Threading.Thread.Sleep(1500);
                var pra = new
                {
                    RequestVersion = Common.CommonPage.RequestVersion,
                    RequestSource = 5,
                    LoginAccessToken = Common.Config.Instance.Token,
                    ProTemplateId = i_templateId
                };
                var result = UserCenterLogic.GetResponseDataByRequestHttps("ProjectTemplate/GetProTemplateDetailList", false, pra);
                if (result == null)
                {
                    //下载模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.DownloadTemplateFail));
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                var fileListData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DownloadTemplateData>>(result);
                if (fileListData.Count == 0)
                {
                    //下载模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.DownloadTemplateFail));
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                //解析这个模板的名字
                var strFileData = this.GetDataFromFileContent(Encoding.UTF8.GetString(fileListData[0].DetailContent), "#START#", "#TemplateData END#");
                var templateBaseInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(strFileData);
                //检测本地的模板是否有同名的
                var listLocal = this.GetLocalAllModelList();
                string fileName = fileListData[0].DetailName;
                foreach (var localData in listLocal)
                {
                    if (localData.ModelName == templateBaseInfo.ModelName)
                    {
                        //替换,直接使用本地的模板文件名字
                        fileName = localData.FileName;
                        break;
                    }
                }
                //存成文件
                string fileFullName = System.IO.Path.Combine(DirNameResourse.AllResidenceTemplateDirectory, fileName);
                HdlFileLogic.Current.SaveByteToFile(fileFullName, fileListData[0].DetailContent);
                //获取升级固件文件
                var result2 = HdlFirmwareUpdateLogic.DownLoadTemplateDeviceFirmware(fileFullName, "正在获取升级固件数据");
                if (result2 == -1)
                {
                    this.ShowMassage(ShowMsgType.Tip, "获取升级固件数据失败");
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                ProgressFormBar.Current.Close();
                i_SuccessAction?.Invoke(fileFullName);
            });
        }
        /// <summary>
        /// 下载模板
        /// </summary>
        private class DownloadTemplateData
        {
            /// <summary>
            /// 模板文件名字
            /// </summary>
            public string DetailName = string.Empty;
            /// <summary>
            /// 模板数据
            /// </summary>
            public byte[] DetailContent = null;
        }
        #endregion
        #region ■ 删除模板备份_______________________
        /// <summary>
        /// 删除云端模板备份
        /// </summary>
        /// <param name="i_templateId">模板主键</param>
        /// <returns></returns>
        public bool DeleteTemplateFromDb(string i_templateId)
        {
            var pra = new
            {
                RequestVersion = Common.CommonPage.RequestVersion,
                RequestSource = 5,
                LoginAccessToken = Common.Config.Instance.Token,
                ProTemplateId = i_templateId
            };
            var result = UserCenterLogic.GetResultStatuByRequestHttps("ProjectTemplate/DeleteProTemplate", false, pra);
            return result;
        }
        /// <summary>
        /// 删除本地模板备份
        /// </summary>
        /// <param name="i_baseInfo">本地模板的基本信息</param>
        /// <returns></returns>
        public void DeleteLocalTemplate(LocalModelBaseInfo i_baseInfo)
        {
            var fullFile = System.IO.Path.Combine(DirNameResourse.AllResidenceTemplateDirectory, i_baseInfo.FileName);
            HdlFileLogic.Current.DeleteFile(fullFile);
        }
        #endregion
        #region ■ 生成模板数据相关___________________
        /// <summary>
        /// 保存模板数据到文件(返回保存文件的全路径)
        /// </summary>
        /// <param name="fileName">保存文件的名字(新建时用 GetNewTemplateFileName函数新建)</param>
        /// <param name="backName">模板备份的名字</param>
        public string SaveTemplateDataToFile(string fileName, string backUpName)
        {
            //写入文件的内容
            string writeText = string.Empty;
            //在生成模板数据之前,检测模板数据
            this.CheckTempLateDataBeforCreat();
            //生成写入文件的【模板基本数据】
            this.CreatWriteTemplateBaseData(ref writeText, backUpName);
            //生成写入文件的【模板住宅信息数据】
            this.CreatWriteTemplateHomeData(ref writeText);
            //生成写入文件的【设备模板数据】
            this.CreatWriteDeviceTemplateData(ref writeText);
            //生成写入文件的【设备对象数据】
            this.CreatWriteCommonDeviceData(ref writeText);
            //生成写入文件的【网关对象数据】
            this.CreatWriteGatewayData(ref writeText);
            //生成写入文件的【场景模板数据】
            this.CreatWriteSceneData(ref writeText);
            //生成写入文件的【房间模板数据】
            this.CrearWriteRoomTemplateData(ref writeText);
            //生成写入文件的【设备和网关选择的模板的数据】
            this.CrearWriteDeviceSelectTemplateData(ref writeText);
            //写入内容
            string saveFile = DirNameResourse.AllResidenceTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, fileName);
            HdlFileLogic.Current.SaveTextToFile(saveFile, writeText);
            return saveFile;
        }
        /// <summary>
        /// 生成写入文件的【模板基本数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CreatWriteTemplateBaseData(ref string writeText, string backUpName)
        {
            var modelData = new LocalModelBaseInfo();
            modelData.EditorTime = DateTime.Now.ToString("yyyy.MM.dd HH:mm");
            modelData.ModelName = backUpName;
            modelData.FloorCount = Common.Config.Instance.Home.FloorDics.Count;
            modelData.DeviceCount = this.modelData.dicDeviceTemplateData.Count;
            //功能数
            int funcCount = 0;
            foreach (var listData in this.modelData.dicDeviceTemplateData.Values)
            {
                if (listData.Count > 0)
                {
                    var listDevice = Common.LocalDevice.Current.GetDevicesByMac(listData[0].DeviceMac, false);
                    funcCount += listDevice.Count;
                }
            }
            modelData.FunctionCount = funcCount;
            writeText += "#START#\r\n";
            string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(modelData);
            writeText += dataInfo + "\r\n";
            writeText += "#TemplateData END#\r\n\r\n";
        }
        /// <summary>
        /// 生成写入文件的【模板住宅信息数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CreatWriteTemplateHomeData(ref string writeText)
        {
            var homeData = new TemplateHomeInfo();
            homeData.ResidenceAddressName = Common.Config.Instance.Home.ResidenceAddressName;
            homeData.ListUintName.AddRange(Common.Config.Instance.Home.ListUintName);
            homeData.ListUintContent.AddRange(Common.Config.Instance.Home.ListUintContent);
            writeText += "#START#\r\n";
            string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(homeData);
            writeText += dataInfo + "\r\n";
            writeText += "#TemplateHomeInfo END#\r\n\r\n";
        }
        /// <summary>
        /// 生成写入文件的【设备模板数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CreatWriteDeviceTemplateData(ref string writeText)
        {
            foreach (var list in this.modelData.dicDeviceTemplateData.Values)
            {
                foreach (var data in list)
                {
                    writeText += "#DeviceTemplate START#" + (int)data.DataSaveDiv + "\r\n";
                    string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                    writeText += dataInfo + "\r\n";
                    writeText += "#DeviceTemplate END#\r\n\r\n";
                }
            }
        }
        /// <summary>
        /// 生成写入文件的【设备对象数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CreatWriteCommonDeviceData(ref string writeText)
        {
            var listDevice = Common.LocalDevice.Current.listAllDevice;
            var listCheck = new HashSet<string>();
            foreach (var device in listDevice)
            {
                //设备端点
                writeText += "#DeviceInfo START#" + (int)device.Type + "\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(device);
                writeText += dataInfo + "\r\n";
                writeText += "#DeviceInfo END#\r\n\r\n";
                //添加Ota设备对象的缓存
                if (listCheck.Contains(device.DeviceAddr) == false)
                {
                    listCheck.Add(device.DeviceAddr);
                    var otaDevice = Common.LocalDevice.Current.GetOTADevice(device.DeviceAddr);
                    if (otaDevice != null)
                    {
                        writeText += "#DeviceInfo START#" + (int)otaDevice.Type + "\r\n";
                        string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(otaDevice);
                        writeText += dataInfo2 + "\r\n";
                        writeText += "#DeviceInfo END#\r\n\r\n";
                    }
                }
            }
        }
        /// <summary>
        /// 生成写入文件的【网关对象数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CreatWriteGatewayData(ref string writeText)
        {
            var listGateway = HdlGatewayLogic.Current.GetAllLocalGateway();
            foreach (var gateway in listGateway)
            {
                //设备端点
                writeText += "#START#\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(gateway);
                writeText += dataInfo + "\r\n";
                writeText += "#GatewayInfo END#\r\n\r\n";
            }
        }
        /// <summary>
        /// 生成写入文件的【场景数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CreatWriteSceneData(ref string writeText)
        {
            //全部的场景
            var listScene = HdlSceneLogic.Current.GetAllLocalScene();
            foreach (var scene in listScene)
            {
                writeText += "#START#\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(scene);
                writeText += dataInfo + "\r\n";
                writeText += "#SceneTemplate END#\r\n\r\n";
            }
        }
        /// <summary>
        /// 生成写入文件的【房间模板数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CrearWriteRoomTemplateData(ref string writeText)
        {
            //楼层数据
            writeText += "#START#\r\n";
            string dataInfo1 = Newtonsoft.Json.JsonConvert.SerializeObject(Common.Config.Instance.Home.FloorDics);
            writeText += dataInfo1 + "\r\n";
            writeText += "#FloorInfo END#\r\n\r\n";
            //房间数据
            var listRoom = HdlRoomLogic.Current.GetAllListRooms();
            foreach (var room in listRoom)
            {
                writeText += "#START#\r\n";
                string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(room);
                writeText += dataInfo2 + "\r\n";
                writeText += "#RoomInfo END#\r\n\r\n";
            }
            //物理网关所在的房间
            var dicRealRoom = new Dictionary<string, string>();
            var listGateway = HdlGatewayLogic.Current.GetAllLocalGateway();
            foreach (var gateway in listGateway)
            {
                dicRealRoom[gateway.GwId] = gateway.RoomId;
            }
            //获取全部物理设备所属房间的记录
            var dicDeviceRoom = HdlRoomLogic.Current.GetAllRealDeviceRoomData();
            foreach (var strMac in dicDeviceRoom.Keys)
            {
                dicRealRoom[strMac] = dicDeviceRoom[strMac];
            }
            writeText += "#START#\r\n";
            string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(dicRealRoom);
            writeText += dataInfo + "\r\n";
            writeText += "#DeviceTemplateRealRoom END#\r\n\r\n";
        }
        /// <summary>
        /// 生成写入文件的【设备和网关选择的模板的数据】
        /// </summary>
        /// <param name="writeText"></param>
        private void CrearWriteDeviceSelectTemplateData(ref string writeText)
        {
            //设备选择模板的数据
            writeText += "#START#\r\n";
            string dataInfo1 = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicDeviceTemplateSelect);
            writeText += dataInfo1 + "\r\n";
            writeText += "#DeviceSelectTemplate END#\r\n\r\n";
            //网关选择模板的数据
            writeText += "#START#\r\n";
            string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicGatewayTemplateSelect);
            writeText += dataInfo2 + "\r\n";
            writeText += "#GatewaySelectTemplate END#\r\n\r\n";
        }
        #endregion
        #region ■ 强制执行的特殊函数_________________
        /// <summary>
        /// 强制从缓存当中生成设备和网关文件
        /// </summary>
        public void CreatDeviceAndGatewayFileFromMemoryByForce()
        {
            //原来的状态
            bool oldShowTemplate = Common.Config.Instance.Home.IsShowTemplate;
            //让它可以生成文件
            Common.Config.Instance.Home.IsShowTemplate = false;
            //生成设备文件
            foreach (var listDevice in this.modelData.dicDeviceInfo.Values)
            {
                foreach (var device in listDevice)
                {
                    device.ReSave();
                }
            }
            //生成网关文件
            foreach (var gateway in this.modelData.dicGatewayInfo.Values)
            {
                gateway.ReSave();
            }
            //还原状态
            Common.Config.Instance.Home.IsShowTemplate = oldShowTemplate;
        }
        #endregion
        #region ■ 设备和网关模板选择相关_____________
        /// <summary>
        /// 添加/修改 设备模板选择目标
        /// </summary>
        /// <param name="sourceMac">设备Mac对象</param>
        /// <param name="targetMac">目标Mac对象</param>
        public void AddDeviceTemplateSelect(string sourceMac, string targetMac)
        {
            //获取本地指定的Mac的全部设备
            var listDevice = Common.LocalDevice.Current.GetDevicesByMac(sourceMac, false);
            var otaDevice = Common.LocalDevice.Current.GetOTADevice(sourceMac);
            if (otaDevice != null)
            {
                //这里ota设备也要加进去,重中之重
                listDevice.Add(otaDevice);
            }
            foreach (var device in listDevice)
            {
                //模板选择的时候,他们的端点是一致的
                string localDeviceKey = Common.LocalDevice.Current.GetDeviceMainKeys(device);
                string templateDeviceKey = Common.LocalDevice.Current.GetDeviceMainKeys(targetMac, device.DeviceEpoint);
                if (this.modelData.dicDeviceTemplateRoom.ContainsKey(templateDeviceKey) == true
                    && (device is OTADevice) == false)
                {
                    //如果模板里面,这个端点设置有房间的话
                    HdlRoomLogic.Current.ChangedRoom(device, this.modelData.dicDeviceTemplateRoom[templateDeviceKey], false);
                }
                //如果这个端点有模板数据的话
                if (this.modelData.dicDeviceFileContent.ContainsKey(templateDeviceKey) == true)
                {
                    //如果原来它选择有模板数据的话
                    if (this.modelData.dicDeviceTemplateData.ContainsKey(localDeviceKey) == true)
                    {
                        //删除这个设备的模板保存文件
                        HdlFileLogic.Current.DeleteFile(System.IO.Path.Combine(DirNameResourse.LocalTemplateDirectory, device.FilePath));
                        //移除当前端点保存的模板数据
                        this.modelData.dicDeviceTemplateData.Remove(localDeviceKey);
                    }
                    //反序列化设备数据
                    foreach (var strCentent in this.modelData.dicDeviceFileContent[templateDeviceKey])
                    {
                        var tempData = this.DeserializeDeviceDataByDiv(strCentent.saveDiv, strCentent.FileContent);
                        //这里需要替换掉Mac
                        tempData.DeviceMac = sourceMac;
                        //添加缓存(主键为本地设备的主键)
                        this.SetTemplateDeviceDataToMemmory(tempData, null, localDeviceKey, true);
                        //修改端点缓存名字
                        if (tempData.DataSaveDiv == ModelDeviceSaveEnum.A端点名称)
                        {
                            Common.LocalDevice.Current.SetEpointName(device, ((ModelDeviceEpointNameInfo)tempData).deviceEpointName);
                        }
                        else if (tempData.DataSaveDiv == ModelDeviceSaveEnum.A设备名称)
                        {
                            Common.LocalDevice.Current.SetMacName(device, ((ModelDeviceMacNameInfo)tempData).deviceMacName);
                        }
                    }
                }
                //不管如何,都需要则重新保存成文件
                this.SaveDeviceMemmoryData(device.DeviceAddr, device.DeviceEpoint);
                //还原及变更场景的执行目标
                //this.RecoverAndChangedSceneAdjustTarget(device, targetMac);
            }
            //更改物理设备所在的房间
            if (this.modelData.dicDeviceTemplateRealRoom.ContainsKey(targetMac) == true)
            {
                HdlRoomLogic.Current.SaveRealDeviceRoomId(listDevice, this.modelData.dicDeviceTemplateRealRoom[targetMac], false);
            }
            //记录缓存
            this.modelData.dicDeviceTemplateSelect[sourceMac] = targetMac;
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicDeviceTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(DirNameResourse.DeviceTemplateSelectFile, fileData);
        }
        /// <summary>
        /// 还原及变更场景的执行目标
        /// </summary>
        /// <param name="device">本地设备对象</param>
        /// <param name="targetMac">需要变更的模板设备的Mac</param>
        private void RecoverAndChangedSceneAdjustTarget(CommonDevice device, string targetMac)
        {
            //如果这个设备是替换选择的模板的话
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(device.DeviceAddr) == false)
            {
                return;
            }
            //全部的场景
            var listScene = HdlSceneLogic.Current.GetAllLocalScene();
            //还没有执行变更前,它目前选择的模板的Mac
            string oldTemplateMac = this.modelData.dicDeviceTemplateSelect[device.DeviceAddr];
            //将场景对象中,这个回路的主键,替换回原来模板中的Mac+端口
            foreach (var scene in listScene)
            {
                bool save = false;
                for (int i = 0; i < scene.AdjustTargetList.Count; i++)
                {
                    if (scene.AdjustTargetList[i].Type != 0)
                    {
                        //只处理设备绑定目标
                        continue;
                    }
                    //如果是当前回路
                    if (scene.AdjustTargetList[i].DeviceAddr == device.DeviceAddr &&
                       scene.AdjustTargetList[i].Epoint == device.DeviceEpoint)
                    {
                        //替换掉Mac
                        scene.AdjustTargetList[i].DeviceAddr = oldTemplateMac;
                        save = true;
                        continue;
                    }
                    //如果是模板目标回路
                    if (targetMac != null &&
                        scene.AdjustTargetList[i].DeviceAddr == targetMac &&
                        scene.AdjustTargetList[i].Epoint == device.DeviceEpoint)
                    {
                        //将目标的Mac变更为当前设备的Mac
                        scene.AdjustTargetList[i].DeviceAddr = device.DeviceAddr;
                        save = true;
                        continue;
                    }
                }
                if (save == true)
                {
                    //保存缓存
                    scene.Save();
                }
            }
        }
        /// <summary>
        /// 获取设备已经选择了的模板目标的设备的Mac(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">设备的Mac</param>
        /// <returns></returns>
        public string GetDeviceTemplateSelectMac(string sourceMac)
        {
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(sourceMac) == true)
            {
                return this.modelData.dicDeviceTemplateSelect[sourceMac];
            }
            return null;
        }
        /// <summary>
        /// 获取设备已经选择了的模板目标的设备的Mac名字(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">设备的Mac</param>
        /// <returns></returns>
        public string GetDeviceTemplateSelectName(string sourceMac)
        {
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(sourceMac) == true)
            {
                string tempMac = this.modelData.dicDeviceTemplateSelect[sourceMac];
                foreach (var listData in this.modelData.dicDeviceFileContent.Values)
                {
                    foreach (var data in listData)
                    {
                        if (data.DeviceMac != tempMac || data.saveDiv != ModelDeviceSaveEnum.A设备名称)
                        {
                            continue;
                        }
                        var tempModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceMacNameInfo>(data.FileContent);
                        return tempModel.deviceMacName;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 取消设备模板的选择目标
        /// </summary>
        /// <param name="sourceMac">设备的Mac</param>
        public void RemoveDeviceTemplateSelect(string sourceMac)
        {
            ////获取本地指定的Mac的全部设备
            //var listDevice = Common.LocalDevice.Current.GetDevicesByMac(sourceMac, false);
            //foreach (var device in listDevice)
            //{
            //    //还原场景的执行目标
            //    this.RecoverAndChangedSceneAdjustTarget(device, null);
            //}
            //记录缓存
            this.modelData.dicDeviceTemplateSelect.Remove(sourceMac);
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicDeviceTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(DirNameResourse.DeviceTemplateSelectFile, fileData);
        }
        /// <summary>
        /// 添加/修改 网关模板选择目标
        /// </summary>
        /// <param name="sourceGwid">网关id</param>
        /// <param name="targetGwid">目标网关id(模板)</param>
        public void AddGatewayTemplateSelect(string sourceGwid, string targetGwid)
        {
            //记录缓存
            this.modelData.dicGatewayTemplateSelect[sourceGwid] = targetGwid;
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicGatewayTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(DirNameResourse.GatewayTemplateSelectFile, fileData);
            //变更网关房间
            if (this.modelData.dicDeviceTemplateRealRoom.ContainsKey(targetGwid) == true)
            {
                HdlRoomLogic.Current.ChangedGatewayRoom(sourceGwid, this.modelData.dicDeviceTemplateRealRoom[targetGwid]);
            }
            //变更网关名字
            //if (this.modelData.dicGatewayInfo.ContainsKey(targetGwid) == true)
            //{
            //    var localGateway = HdlGatewayLogic.Current.GetLocalGateway(sourceGwid);
            //    string gwName = HdlGatewayLogic.Current.GetGatewayName(this.modelData.dicGatewayInfo[targetGwid]);
            //    HdlGatewayLogic.Current.ReName(localGateway, gwName);
            //}
        }
        /// <summary>
        /// 取消网关模板选择目标
        /// </summary>
        /// <param name="sourceGwid">网关id</param>
        /// <param name="targetGwid">目标网关id</param>
        public void RemoveGatewayTemplateSelect(string sourceGwid)
        {
            //记录缓存
            this.modelData.dicGatewayTemplateSelect.Remove(sourceGwid);
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicGatewayTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(DirNameResourse.GatewayTemplateSelectFile, fileData);
        }
        /// <summary>
        /// 获取网关已经选择了的模板目标的网关的名字(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">网关id</param>
        /// <returns></returns>
        public string GetGatewayTemplateSelectName(string sourceGwid)
        {
            if (this.modelData.dicGatewayTemplateSelect.ContainsKey(sourceGwid) == true)
            {
                string tempMac = this.modelData.dicGatewayTemplateSelect[sourceGwid];
                if (this.modelData.dicGatewayInfo.ContainsKey(tempMac) == true)
                {
                    string gwName = HdlGatewayLogic.Current.GetGatewayName(this.modelData.dicGatewayInfo[tempMac]);
                    return gwName;
                }
            }
            return null;
        }
        /// <summary>
        /// 获取网关已经选择了的模板目标的网关的名字(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">网关id</param>
        /// <returns></returns>
        public string GetGatewayTemplateSelectId(string sourceGwid)
        {
            if (this.modelData.dicGatewayTemplateSelect.ContainsKey(sourceGwid) == true)
            {
                return this.modelData.dicGatewayTemplateSelect[sourceGwid];
            }
            return null;
        }
        /// <summary>
        /// 获取模板中全部网关的名字
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetAllGatewayTemplateName()
        {
            var dic = new Dictionary<string, string>();
            foreach (string gwId in this.modelData.dicGatewayInfo.Keys)
            {
                string gwName = HdlGatewayLogic.Current.GetGatewayName(this.modelData.dicGatewayInfo[gwId]);
                dic[gwId] = gwName;
            }
            return dic;
        }
        /// <summary>
        /// 获取指定网关能够选择的模板名字
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetGatewayCanSelectTemplateName(ZbGateway zbGateway)
        {
            var dic = new Dictionary<string, string>();
            foreach (var zbway in this.modelData.dicGatewayInfo.Values)
            {
                if (zbGateway.LinuxImageType == zbway.LinuxImageType)
                {
                    string gwName = HdlGatewayLogic.Current.GetGatewayName(zbway);
                    dic[zbway.GwId] = gwName;
                }
            }
            return dic;
        }
        /// <summary>
        /// 清除全部已经已经选择好了模板对象的设备和网关
        /// </summary>
        public void ClearAllSelectDeviceAndGateway()
        {
            //重新初始化
            this.modelData.dicDeviceTemplateSelect = new Dictionary<string, string>();
            this.modelData.dicGatewayTemplateSelect = new Dictionary<string, string>();
            //删掉这两个保存选择模板的文件
            HdlFileLogic.Current.DeleteFile(DirNameResourse.DeviceTemplateSelectFile);
            HdlFileLogic.Current.DeleteFile(DirNameResourse.GatewayTemplateSelectFile);
        }
        #endregion
        #region ■ 获取能够选择的模板_________________
        /// <summary>
        /// 获取能够选择的模板
        /// </summary>
        /// <param name="localDevice">本地设备</param>
        /// <returns></returns>
        public List<TemplateCanSelectContent> GetCanSelectDeviceTemplate(CommonDevice localDevice)
        {
            var listCanSelect = new List<TemplateCanSelectContent>();
            if (this.modelData.dicGatewayTemplateSelect.ContainsKey(localDevice.CurrentGateWayId) == false)
            {
                //该网关没有匹配模板,不提供模板选择
                return listCanSelect;
            }
            var listHadSelect = new HashSet<string>();
            foreach (var localMac in this.modelData.dicDeviceTemplateSelect.Keys)
            {
                //它自己的话,可以显示(因为有个取消绑定的功能)
                if (localMac != localDevice.DeviceAddr)
                {
                    //目前已经被选择了的模板Mac
                    listHadSelect.Add(this.modelData.dicDeviceTemplateSelect[localMac]);
                }
            }
            var listCheck = new HashSet<string>();
            //设备的模块ID
            string modelId = this.GetDeviceModelId(localDevice.DeviceAddr);
            //模板中的网关ID
            string gatewayTemplateId = this.modelData.dicGatewayTemplateSelect[localDevice.CurrentGateWayId];
            foreach (var listData in this.modelData.dicDeviceFileContent.Values)
            {
                foreach (var data in listData)
                {
                    if (data.saveDiv != ModelDeviceSaveEnum.A设备名称)
                    {
                        //只获取设备mac名称的模板数据
                        continue;
                    }
                    if (listHadSelect.Contains(data.DeviceMac) == true
                        || listCheck.Contains(data.DeviceMac) == true)
                    {
                        //如果这个模板已经被其他设备选择了,或者这个Mac已经处理了,则break
                        break;
                    }
                    if (this.modelData.dicDeviceInfo.ContainsKey(data.DeviceMac) == false
                        || this.modelData.dicDeviceInfo[data.DeviceMac][0].CurrentGateWayId != gatewayTemplateId
                        || this.modelData.dicDeviceInfo[data.DeviceMac][0].ModelIdentifier != modelId)
                    {
                        //该模板不是这个网关的,或者模块ID不一样的
                        break;
                    }
                    listCheck.Add(data.DeviceMac);
                    var info = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceMacNameInfo>(data.FileContent);
                    var selectData = new TemplateCanSelectContent();
                    selectData.DeviceMac = data.DeviceMac;
                    selectData.DeviceName = info.deviceMacName;
                    Common.Room room = null;
                    if (this.modelData.dicDeviceTemplateRealRoom.ContainsKey(data.DeviceMac) == true)
                    {
                        room = HdlRoomLogic.Current.GetRoomById(this.modelData.dicDeviceTemplateRealRoom[data.DeviceMac]);
                    }
                    selectData.RoomName = HdlRoomLogic.Current.GetRoomName(room);
                    listCanSelect.Add(selectData);
                }
            }
            return listCanSelect;
        }
        #endregion
        #region ■ 删除设备___________________________
        /// <summary>
        /// 删除设备
        /// </summary>
        /// <param name="device"></param>
        public void DeleteDevice(CommonDevice device)
        {
            //删除保存文件
            string saveFile = DirNameResourse.LocalTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, device.FilePath);
            HdlFileLogic.Current.DeleteFile(saveFile);
            //移除模板缓存
            this.modelData.dicDeviceTemplateData.Remove(Common.LocalDevice.Current.GetDeviceMainKeys(device));
            //移除设备选择缓存
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(device.DeviceAddr) == true)
            {
                this.modelData.dicDeviceTemplateSelect.Remove(device.DeviceAddr);
                HdlFileLogic.Current.SaveFileContent(DirNameResourse.DeviceTemplateSelectFile, this.modelData.dicDeviceTemplateSelect);
            }
        }
        #endregion
        #region ■ 保存设备缓存_______________________
        /// <summary>
        /// 保存设备缓存(考虑有的设备用的是200端点,所以这里最好不用设备对象作为参数)
        /// </summary>
        /// <param name="deviceMac">设备mac</param>
        /// <param name="deviceEpoint">设备Epoint</param>
        public void SaveDeviceMemmoryData(string deviceMac, int deviceEpoint)
        {
            string mainkey = Common.LocalDevice.Current.GetDeviceMainKeys(deviceMac, deviceEpoint);
            if (this.modelData.dicDeviceTemplateData.ContainsKey(mainkey) == false)
            {
                return;
            }
            //保存路径
            string saveFile = DirNameResourse.LocalTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, "Device_" + mainkey);
            var listData = this.modelData.dicDeviceTemplateData[mainkey];
            if (listData.Count == 0)
            {
                //删除掉这个文件
                HdlFileLogic.Current.DeleteFile(saveFile);
                return;
            }
            //写入文件的内容
            string writeText = string.Empty;
            foreach (var data in listData)
            {
                writeText += "===>" + (int)data.DataSaveDiv + "\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                writeText += dataInfo + "\r\n";
            }
            //写入内容
            HdlFileLogic.Current.SaveTextToFile(saveFile, writeText);
        }
        #endregion
        #region ■ 获取需要升级的设备对象_____________
        /// <summary>
        /// 获取需要升级的设备对象,按网关分组(key:网关ID value的key:本地Ota设备的Mac value:升级固件地址)
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, Dictionary<string, string>> GetNeedToUpdateDevice()
        {
            var dicGatewayDevice = new Dictionary<string, Dictionary<string, string>>();
            //循环设备匹配的模板
            foreach (var localMac in this.modelData.dicDeviceTemplateSelect.Keys)
            {
                string tempMac = this.modelData.dicDeviceTemplateSelect[localMac];
                if (this.modelData.dicDeviceInfo.ContainsKey(tempMac) == false)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                //取本地Ota设备对象
                var localOta = Common.LocalDevice.Current.GetOTADevice(localMac);
                if (localOta == null)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                foreach (var tempDevice in this.modelData.dicDeviceInfo[tempMac])
                {
                    //取模板Ota设备对象
                    if (tempDevice is OTADevice)
                    {
                        //只要两者的固件版本不一样,并且本地有这个升级固件,则都需要升级
                        if (localOta.ImgVersion != tempDevice.ImgVersion
                            && HdlFirmwareUpdateLogic.IsEsixtDeviceFirmwareFile((OTADevice)tempDevice) == true)
                        {
                            //按网关分组
                            if (dicGatewayDevice.ContainsKey(localOta.CurrentGateWayId) == false)
                            {
                                dicGatewayDevice[localOta.CurrentGateWayId] = new Dictionary<string, string>();
                            }
                            var dicDevice = dicGatewayDevice[localOta.CurrentGateWayId];
                            dicDevice[localMac] = HdlFirmwareUpdateLogic.GetDeviceFirmwareFile((OTADevice)tempDevice);
                        }
                        break;
                    }
                }
            }
            return dicGatewayDevice;
        }
        /// <summary>
        /// 获取需要升级的网关对象(key:本地网关的id value:升级固件地址,第一位是Linux,第二位是协调器,之后都是虚拟驱动)
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, List<GatewayNeedUpdateInfo>> GetNeedToUpdateGateway()
        {
            var dicGateway = new Dictionary<string, List<GatewayNeedUpdateInfo>>();
            //循环网关匹配的模板
            foreach (var localId in this.modelData.dicGatewayTemplateSelect.Keys)
            {
                string tempId = this.modelData.dicGatewayTemplateSelect[localId];
                if (this.modelData.dicGatewayInfo.ContainsKey(tempId) == false)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                //取本地网关对象
                var localGateway = HdlGatewayLogic.Current.GetLocalGateway(localId);
                if (localGateway == null)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                var tempGateway = this.modelData.dicGatewayInfo[tempId];
                //初始化容器
                var listUpdateInfo = new List<GatewayNeedUpdateInfo>() { null, null };
                bool needUpdate = false;
                //Linux版本比较
                if (tempGateway.LinuxFirmwareVersion != localGateway.LinuxFirmwareVersion)
                {
                    //Linux升级固件文件全路径
                    string updateFile = HdlFirmwareUpdateLogic.GetGatewayLinuxFirmwareFile(tempGateway);
                    if (System.IO.File.Exists(updateFile) == true)
                    {
                        //如果存在的话
                        var info = new GatewayNeedUpdateInfo();
                        info.Div = 1;
                        info.FullFileName = updateFile;
                        listUpdateInfo[0] = info;
                        needUpdate = true;
                    }
                }
                //协调器版本比较
                if (tempGateway.CoordinatorFirmwareVersion != localGateway.CoordinatorFirmwareVersion)
                {
                    //协调器升级固件文件全路径
                    string updateFile = HdlFirmwareUpdateLogic.GetGatewayCoordinatorFirmwareFile(tempGateway);
                    if (System.IO.File.Exists(updateFile) == true)
                    {
                        //如果存在的话
                        var info = new GatewayNeedUpdateInfo();
                        info.Div = 2;
                        info.FullFileName = updateFile;
                        listUpdateInfo[1] = info;
                        needUpdate = true;
                    }
                }
                //虚拟驱动比较
                if (HdlGatewayLogic.Current.CheckGatewayHadDriveCode(localGateway) == true)
                {
                    foreach (var localCode in localGateway.DriveCodeList)
                    {
                        foreach (var tempCode in tempGateway.DriveCodeList)
                        {
                            //防止它放的顺序不样
                            if (localCode.DriveCode == tempCode.DriveCode && localCode.DriveFwVersion != tempCode.DriveFwVersion)
                            {
                                //虚拟驱动升级固件文件全路径
                                string updateFile = HdlFirmwareUpdateLogic.GetGatewayDriveCodeFirmwareFile(tempCode);
                                if (System.IO.File.Exists(updateFile) == true)
                                {
                                    //如果存在的话
                                    var info = new GatewayNeedUpdateInfo();
                                    info.Div = 3;
                                    info.DriveCode = tempCode.DriveCode;
                                    info.FullFileName = updateFile;
                                    listUpdateInfo.Add(info);
                                    needUpdate = true;
                                }
                            }
                        }
                    }
                }
                //添加目标缓存
                if (needUpdate == true)
                {
                    dicGateway[localId] = listUpdateInfo;
                }
            }
            return dicGateway;
        }
        #endregion
        #region ■ 从模板文件中获取对象(外部调用)_____
        /// <summary>
        /// 从模板文件中,获取设备和网关对象
        /// </summary>
        /// <param name="fullFileName">模板文件的全路径</param>
        /// <param name="listDevice">ota设备列表</param>
        /// <param name="listGateway">网关列表</param>
        public void GetDeviceObjectFromTemplate(string fullFileName, ref List<OTADevice> listDevice, ref List<ZbGateway> listGateway)
        {
            var fileData = HdlFileLogic.Current.ReadFileTextContent(fullFileName);
            if (fileData == null)
            {
                return;
            }
            var deviceType = string.Empty;
            var strTempContentData = string.Empty;
            //根据换行符切分数据文本
            string[] arryData = fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string strData in arryData)
            {
                if (strData == "#START#")
                {
                    //无附加数据的【数据标题】
                    strTempContentData = string.Empty;
                    continue;
                }
                if (strData.StartsWith("#DeviceInfo START#") == true)
                {
                    //附加数据:设备对象类型
                    deviceType = strData.Substring(18);
                    strTempContentData = string.Empty;
                    continue;
                }
                try
                {
                    //设备对象
                    if (strData == "#DeviceInfo END#")
                    {
                        //反序列化设备
                        if (deviceType == "OtaDevice" || deviceType == "OtaPanelDevice")
                        {
                            var device = Newtonsoft.Json.JsonConvert.DeserializeObject<OTADevice>(strTempContentData);
                            if (device != null)
                            {
                                listDevice.Add(device);
                            }
                        }
                        strTempContentData = string.Empty;
                        continue;
                    }
                    //网关对象数据
                    else if (strData == "#GatewayInfo END#")
                    {
                        //反序列化设备
                        var gateway = Newtonsoft.Json.JsonConvert.DeserializeObject<ZbGateway>(strTempContentData);
                        if (gateway != null)
                        {
                            listGateway.Add(gateway);
                        }
                        strTempContentData = string.Empty;
                        return;
                    }
                    strTempContentData += strData;
                }
                catch (Exception ex)
                {
                    HdlLogLogic.Current.WriteLog(ex, "模板bin文件出问题\r\n" + strTempContentData);
                    strTempContentData = string.Empty;
                }
            }
        }
        #endregion
        #region ■ 一般方法___________________________
        /// <summary>
        /// 复制模板bin文件到本地的模板文件夹里
        /// </summary>
        /// <param name="templateFileName">模板文件的名字(全住宅存放的模板)</param>
        public void CopyTemplateFileToLocalDirectory(string templateFileName)
        {
            string sourceFile = System.IO.Path.Combine(DirNameResourse.AllResidenceTemplateDirectory, templateFileName);
            this.CopyTemplateFileToLocalDirectory2(sourceFile);
        }
        /// <summary>
        /// 复制模板bin文件到本地的模板文件夹里
        /// </summary>
        /// <param name="fullTemplateName">模板文件的全路径</param>
        public void CopyTemplateFileToLocalDirectory2(string fullTemplateName)
        {
            if (System.IO.File.Exists(fullTemplateName) == false)
            {
                return;
            }
            //保存的路径
            string targetFile = DirNameResourse.LocalTemplateDirectory;
            targetFile = System.IO.Path.Combine(targetFile, TemplateFileName);
            try { System.IO.File.Copy(fullTemplateName, targetFile, true); }
            catch (Exception ex) { HdlLogLogic.Current.WriteLog(ex, "复制模板bin文件失败"); }
        }
        /// <summary>
        /// 删除本地全部的模板缓存文件
        /// </summary>
        public void DeleteAllLocalFile()
        {
            //获取这个路径下面全部的文件
            var listFile = HdlFileLogic.Current.GetFileFromDirectory(DirNameResourse.LocalTemplateDirectory, false); ;
            foreach (var file in listFile)
            {
                HdlFileLogic.Current.DeleteFile(file);
            }
        }
        /// <summary>
        /// 获取模板中的设备数
        /// </summary>
        /// <returns></returns>
        public int GetTemplateDeviceCount()
        {
            return this.modelData.dicDeviceInfo.Count;
        }
        /// <summary>
        /// 检测设备模板数和当前设备选择的模板数是否一致
        /// </summary>
        /// <returns></returns>
        public bool CheckTemplateDeviceCountAndSelectCountIsEqual()
        {
            return this.modelData.dicDeviceInfo.Count == this.modelData.dicDeviceTemplateSelect.Count;
        }
        /// <summary>
        /// 获取文件里指定的内容
        /// </summary>
        /// <param name="fileContrnt">文件文本</param>
        /// <param name="startFlage">开始字符</param>
        /// <param name="endFlage">结束字符</param>
        /// <returns></returns>
        private string GetDataFromFileContent(string fileContrnt, string startFlage, string endFlage)
        {
            string[] arryValue = fileContrnt.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            string modelBaseInfo = string.Empty;
            bool getData = false;
            bool success = false;
            foreach (var strValue in arryValue)
            {
                //开始
                if (strValue == startFlage)
                {
                    getData = true;
                    //同一开始字符的东西很多
                    modelBaseInfo = string.Empty;
                    continue;
                }
                //结束
                if (strValue == endFlage)
                {
                    success = true;
                    break;
                }
                if (getData == true)
                {
                    modelBaseInfo += strValue;
                }
            }
            return success == true ? modelBaseInfo : string.Empty;
        }
        /// <summary>
        /// 获取模块ID
        /// </summary>
        /// <param name="deviceMac"></param>
        /// <returns></returns>
        private string GetDeviceModelId(string deviceMac)
        {
            var listDevice = Common.LocalDevice.Current.GetDevicesByMac(deviceMac);
            foreach (var device in listDevice)
            {
                if (device.ModelIdentifier != string.Empty)
                {
                    return device.ModelIdentifier;
                }
            }
            return string.Empty;
        }
        /// <summary>
        /// 获取设备保存的模板对象(考虑有的设备用的是200端点,所以这里最好不用设备对象作为参数)
        /// </summary>
        /// <param name="device"></param>
        /// <param name="saveEnum"></param>
        /// <returns></returns>
        public TemplateDeviceDataCommon GetDeviceModelDataClass(string deviceMac, int deviceEpoint, ModelDeviceSaveEnum saveEnum, TemplateDeviceDataCommon newClass)
        {
            string mainkey = Common.LocalDevice.Current.GetDeviceMainKeys(deviceMac, deviceEpoint);
            //创建存储空间
            if (this.modelData.dicDeviceTemplateData.ContainsKey(mainkey) == false)
            {
                this.modelData.dicDeviceTemplateData[mainkey] = new List<TemplateDeviceDataCommon>();
            }
            foreach (var data in this.modelData.dicDeviceTemplateData[mainkey])
            {
                //如果是已经存在了的
                if (data.DataSaveDiv == saveEnum)
                {
                    return data;
                }
            }
            //新建一个新的对象
            newClass.DataSaveDiv = saveEnum;
            newClass.DeviceEpoint = deviceEpoint;
            newClass.DeviceMac = deviceMac;
            //默认创建一个索引位
            newClass.ListReceiveResult.Add(string.Empty);
            newClass.ListReceiveTopic.Add(string.Empty);
            newClass.ListSendTopic.Add(string.Empty);
            this.modelData.dicDeviceTemplateData[mainkey].Add(newClass);
            return newClass;
        }
        /// <summary>
        /// 显示信息框
        /// </summary>
        /// <param name="msgType">信息类型</param>
        /// <param name="msg">信息</param>
        /// <param name="action">单击确认后执行的回调函数</param>
        /// <param name="buttonText">按钮的文本</param>
        private void ShowMassage(ShowMsgType msgType, string msg, Action action = null, string buttonText = null)
        {
            HdlMessageLogic.Current.ShowMassage(msgType, msg, action, buttonText);
        }
        #endregion
    }
}
using Shared.Phone.UserCenter;
using System;
using System.Collections.Generic;
using System.Text;
using ZigBee.Device;
namespace Shared.Phone
{
    /// <summary>
    /// 模板的共通逻辑类
    /// </summary>
    public class HdlTemplateCommonLogic
    {
        #region ■ 变量声明___________________________
        /// <summary>
        /// 模板的共通逻辑类
        /// </summary>
        private static HdlTemplateCommonLogic m_Current = null;
        /// <summary>
        /// 模板的共通逻辑类
        /// </summary>
        public static HdlTemplateCommonLogic Current
        {
            get
            {
                if (m_Current == null)
                {
                    m_Current = new HdlTemplateCommonLogic();
                }
                return m_Current;
            }
        }
        /// <summary>
        /// 模板数据
        /// </summary>
        public TemplateMemoryData modelData = new TemplateMemoryData();
        /// <summary>
        /// 模板文件中 #start# 到 #end# 的内容(临时变量)
        /// </summary>
        private string strTempContentData = string.Empty;
        /// <summary>
        /// 本地模板文件的名字
        /// </summary>
        private const string TemplateFileName = "ModelData_Release.bin";
        #endregion
        #region ■ 加载本地模板缓存___________________
        /// <summary>
        /// 加载本地模板文件缓存(此方法以本地缓存为准,切换住宅时使用)
        /// </summary>
        public void LoadLocalTemplateMemoryData()
        {
            this.modelData = new TemplateMemoryData();
            //保存的路径
            string saveFile = HdlFileNameResourse.LocalTemplateDirectory;
            //如果当前住宅拥有选择的模板
            if (Common.Config.Instance.Home.SelectTemplate != string.Empty)
            {
                string checkFile = System.IO.Path.Combine(saveFile, TemplateFileName);
                //如果本地没有这个bin文件
                if (System.IO.File.Exists(checkFile) == false)
                {
                    //复制模板bin文件到本地的模板文件夹里
                    this.CopyTemplateFileToLocalDirectory(Common.Config.Instance.Home.SelectTemplate);
                }
            }
            //获取这个路径下面全部的文件
            var listFile = HdlFileLogic.Current.GetFileFromDirectory(saveFile);
            //模板Bin文件
            string templateBinFile = string.Empty;
            //这里是读取他上一次编辑完成之后的模板数据(也就是编辑到一半之后,退出App,下一次再编辑)
            foreach (var fileName in listFile)
            {
                if (fileName == TemplateFileName)
                {
                    //模板Bin文件
                    templateBinFile = fileName;
                    continue;
                }
                if (fileName.StartsWith("Device_") == false)
                {
                    //只要设备
                    continue;
                }
                string fileData = HdlFileLogic.Current.ReadFileTextContent(System.IO.Path.Combine(saveFile, fileName));
                if (fileData == null)
                {
                    continue;
                }
                string deviceData = string.Empty;
                ModelDeviceSaveEnum saveDiv = ModelDeviceSaveEnum.A未定义;
                //根据换行符切分数据文本
                string[] arryData = fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (string strData in arryData)
                {
                    //设备数据标志
                    if (strData.StartsWith("===>") == true)
                    {
                        if (deviceData != string.Empty)
                        {
                            //反序列化设备的保存文件内容
                            var tempData = this.DeserializeDeviceDataByDiv(saveDiv, deviceData);
                            //将设备模板数据添加入缓存
                            string mainKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(tempData.DeviceMac, tempData.DeviceEpoint);
                            this.SetTemplateDeviceDataToMemmory(tempData, deviceData, mainKey, true);
                        }
                        //清空
                        deviceData = string.Empty;
                        saveDiv = (ModelDeviceSaveEnum)Convert.ToInt32(strData.Substring(4));
                        continue;
                    }
                    deviceData += strData;
                }
                if (deviceData != string.Empty)
                {
                    //反序列化设备的保存文件内容
                    var tempData = this.DeserializeDeviceDataByDiv(saveDiv, deviceData);
                    //将设备模板数据添加入缓存
                    string mainKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(tempData.DeviceMac, tempData.DeviceEpoint);
                    this.SetTemplateDeviceDataToMemmory(tempData, deviceData, mainKey, true);
                }
            }
            //读取模板Bin文件
            if (templateBinFile != string.Empty)
            {
                bool hadRoom = HdlRoomLogic.Current.GetAllListRooms().Count > 1 && Common.Config.Instance.Home.FloorDics.Count == 0;
                //开始读取文件内容
                this.ReadTemplateFileMethord((strData, saveDiv, deviceType) =>
                {
                    //在加载本地缓存的前提下,处理模板文件里面的特殊内容
                    var result = this.AdjustTemplateBinFileContentOnLoadMemory(strData, hadRoom);
                    //false代表它不是特殊内容
                    if (result == false)
                    {
                        //处理模板文件里面的共通内容
                        //因为上面已经加载了指定本地的缓存,所以这里不需要添加入dicDeviceTemplateData中
                        this.AdjustTemplateBinFileCommonContent(strData, saveDiv, deviceType, false);
                    }
                });
            }
            //清空对象缓存
            this.strTempContentData = string.Empty;
            //加载设备和网关模板选择的数据
            this.modelData.dicDeviceTemplateSelect = new Dictionary<string, string>();
            this.modelData.dicGatewayTemplateSelect = new Dictionary<string, string>();
            string fileData2 = HdlFileLogic.Current.ReadFileTextContent(HdlFileNameResourse.DeviceTemplateSelectFile);
            if (fileData2 != null)
            {
                //设备选择的模板对象(keys:本地设备的Mac value:模板中的Mac)
                this.modelData.dicDeviceTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(fileData2);
            }
            fileData2 = HdlFileLogic.Current.ReadFileTextContent(HdlFileNameResourse.GatewayTemplateSelectFile);
            if (fileData2 != null)
            {
                //网关对象选择的模板对象(keys:本地网关ID,  value:模板中的网关ID)
                this.modelData.dicGatewayTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(fileData2);
            }
        }
        /// <summary>
        /// 在加载本地缓存的前提下,处理模板文件里面的特殊内容
        /// </summary>
        /// <param name="strData">模板文件中的行数据</param>
        /// <param name="hadRoom">是否已经有了房间</param>
        private bool AdjustTemplateBinFileContentOnLoadMemory(string strData, bool hadRoom)
        {
            //场景对象
            if (strData == "#SceneTemplate END#")
            {
                if (hadRoom == false)
                {
                    //只初始化一次,有房间时代表已经不是第一次加载了
                    var scene = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.SceneUI>(this.strTempContentData);
                    scene.Save();
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //楼层对象
            else if (strData == "#FloorInfo END#")
            {
                if (hadRoom == false)
                {
                    //只初始化一次,有房间时代表已经不是第一次加载了
                    Common.Config.Instance.Home.FloorDics = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                    Common.Config.Instance.Home.Save(false);
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //房间对象
            else if (strData == "#RoomInfo END#")
            {
                var room = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.Room>(this.strTempContentData);
                //各自端点所处的房间ID,保存起来
                foreach (var deviceKey in room.ListDevice)
                {
                    this.modelData.dicDeviceTemplateRoom[deviceKey] = room.Id;
                }
                foreach (var strMac in room.ListDeviceMac)
                {
                    //物理设备所在的区域,在这个函数外面已经初始化了这个变量
                    this.modelData.dicDeviceTemplateRealRoom[strMac] = room.Id;
                }
                if (hadRoom == false)
                {
                    //第一次加载,设备列表需要清空,选择设备模板时,才添加
                    room.ListDevice.Clear();
                    room.Save();
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //设备选择的模板
            else if (strData == "#DeviceSelectTemplate END#")
            {
                //这个东西在这个分支下不从文件中读取,从本地缓存文件当中获取
                this.strTempContentData = string.Empty;
                return true;
            }
            //网关选择的模板
            else if (strData == "#GatewaySelectTemplate END#")
            {
                //这个东西在这个分支下不从文件中读取,从本地缓存文件当中获取
                this.strTempContentData = string.Empty;
                return true;
            }
            return false;
        }
        #endregion
        #region ■ 根据模板Bin文件恢复数据____________
        /// <summary>
        /// 根据模板Bin文件,恢复数据(分两个函数吧,太难控制了)
        /// </summary>
        public void RecoverDataByTemplateBinFile()
        {
            //重新初始化
            this.modelData = new TemplateMemoryData();
            //开始读取文件内容
            this.ReadTemplateFileMethord((strData, saveDiv, deviceType) =>
            {
                //在恢复数据的前提下,处理模板文件里面的特殊内容
                var result = this.AdjustTemplateBinFileContentOnRecover(strData);
                //false代表它不是特殊内容
                if (result == false)
                {
                    //处理模板文件里面的共通内容
                    //因为是以模板来恢复住宅数据,所以这里需要添加入dicDeviceTemplateData中
                    this.AdjustTemplateBinFileCommonContent(strData, saveDiv, deviceType, true);
                }
            });
            //清空对象缓存
            this.strTempContentData = string.Empty;
            //删掉这两个保存选择模板的文件(这两个东西可能还存在)
            HdlFileLogic.Current.DeleteFile(HdlFileNameResourse.DeviceTemplateSelectFile);
            HdlFileLogic.Current.DeleteFile(HdlFileNameResourse.GatewayTemplateSelectFile);
            //再次初始化房间
            HdlRoomLogic.Current.InitAllRoom();
            //无模板模式时,恢复备份的时候,把备份文件删除
            if (Common.Config.Instance.Home.TemplateMode != 2)
            {
                //存放的路径
                string fullFile = System.IO.Path.Combine(HdlFileNameResourse.LocalTemplateDirectory, TemplateFileName);
                HdlFileLogic.Current.DeleteFile(fullFile);
            }
        }
        /// <summary>
        /// 在恢复数据的前提下,处理模板文件里面的特殊内容
        /// </summary>
        /// <param name="strData">模板文件中的行数据</param>
        private bool AdjustTemplateBinFileContentOnRecover(string strData)
        {
            //场景对象
            if (strData == "#SceneTemplate END#")
            {
                var scene = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.SceneUI>(this.strTempContentData);
                scene.Save();
                this.strTempContentData = string.Empty;
                return true;
            }
            //楼层对象
            else if (strData == "#FloorInfo END#")
            {
                Common.Config.Instance.Home.FloorDics = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                Common.Config.Instance.Home.Save(false);
                this.strTempContentData = string.Empty;
                return true;
            }
            //房间对象
            else if (strData == "#RoomInfo END#")
            {
                var room = Newtonsoft.Json.JsonConvert.DeserializeObject<Common.Room>(this.strTempContentData);
                room.Save();
                //各自端点所处的房间ID,保存起来
                foreach (var deviceKey in room.ListDevice)
                {
                    this.modelData.dicDeviceTemplateRoom[deviceKey] = room.Id;
                }
                foreach (var strMac in room.ListDeviceMac)
                {
                    //物理设备所在的区域,在这个函数外面已经初始化了这个变量
                    this.modelData.dicDeviceTemplateRealRoom[strMac] = room.Id;
                }
                this.strTempContentData = string.Empty;
                return true;
            }
            //设备选择的模板
            else if (strData == "#DeviceSelectTemplate END#")
            {
                this.modelData.dicDeviceTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                this.strTempContentData = string.Empty;
                return true;
            }
            //网关选择的模板
            else if (strData == "#GatewaySelectTemplate END#")
            {
                this.modelData.dicGatewayTemplateSelect = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(this.strTempContentData);
                this.strTempContentData = string.Empty;
                return true;
            }
            return false;
        }
        #endregion
        #region ■ 处理模板文件里面的共通内容_________
        /// <summary>
        /// 处理模板文件里面的共通内容
        /// </summary>
        /// <param name="strData">模板文件中的行数据</param>
        /// <param name="saveDiv">模板设备保存的区分(设备数据时有效)</param>
        /// <param name="deviceType">模板中设备的deviceType(设备数据时有效,反射用)</param>
        /// <param name="addToTemplate">是否添加到设备模板缓存中</param>
        private void AdjustTemplateBinFileCommonContent(string strData, ModelDeviceSaveEnum saveDiv, string deviceType, bool addToTemplate)
        {
            //模板基本数据
            if (strData == "#TemplateData END#")
            {
                var templateData = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(this.strTempContentData);
                this.modelData.TemplateName = templateData.ModelName;
                this.strTempContentData = string.Empty;
                return;
            }
            //设备模板
            else if (strData == "#DeviceTemplate END#")
            {
                //反序列化设备的保存文件内容
                var tempData = this.DeserializeDeviceDataByDiv(saveDiv, this.strTempContentData);
                //将设备模板数据添加入缓存(此处特殊,不需要加入设备模板缓存中)
                string mainKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(tempData.DeviceMac, tempData.DeviceEpoint);
                this.SetTemplateDeviceDataToMemmory(tempData, this.strTempContentData, mainKey, addToTemplate);
                this.strTempContentData = string.Empty;
                return;
            }
            //设备对象
            else if (strData == "#DeviceInfo END#")
            {
                //反序列化设备
                CommonDevice device = null;
                if (HdlCheckLogic.Current.CheckIsNumber(deviceType) == true)
                {
                    //数值型为新数据,直接转换
                    device = CommonDevice.CommonDeviceByByteString(Convert.ToInt32(deviceType), this.strTempContentData);
                }
                else
                {
                    //字符串型为旧数据,需要特殊处理
                    var myType = (DeviceType)Enum.Parse(typeof(DeviceType), deviceType);
                    device = CommonDevice.CommonDeviceByByteString((int)myType, this.strTempContentData);
                }
                if (device != null)
                {
                    if (this.modelData.dicDeviceInfo.ContainsKey(device.DeviceAddr) == false)
                    {
                        this.modelData.dicDeviceInfo[device.DeviceAddr] = new List<CommonDevice>();
                    }
                    this.modelData.dicDeviceInfo[device.DeviceAddr].Add(device);
                }
                this.strTempContentData = string.Empty;
                return;
            }
            //网关对象数据
            else if (strData == "#GatewayInfo END#")
            {
                //反序列化设备
                var gateway = Newtonsoft.Json.JsonConvert.DeserializeObject<ZbGateway>(this.strTempContentData);
                this.modelData.dicGatewayInfo[gateway.GwId] = gateway;
                this.strTempContentData = string.Empty;
                return;
            }
            //模板住宅的信息(目前在这里基本没用)
            else if (strData == "#TemplateHomeInfo END#")
            {
                this.strTempContentData = string.Empty;
                return;
            }
            this.strTempContentData += strData;
        }
        #endregion
        #region ■ 读取模板文件内容___________________
        /// <summary>
        /// 读取模板文件内容
        /// </summary>
        /// <param name="AdjustAction">
        /// <para>参数1:模板文件中的行数据</para>
        /// <para>参数2:模板设备保存的区分(设备数据时有效)</para>
        /// <para>参数3:板中设备的deviceType(设备数据时有效,反射用)</para>
        /// </param>
        private void ReadTemplateFileMethord(Action<string, ModelDeviceSaveEnum, string> AdjustAction)
        {
            //保存的路径
            string saveFile = HdlFileNameResourse.LocalTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, TemplateFileName);
            string fileData = HdlFileLogic.Current.ReadFileTextContent(saveFile);
            if (fileData == null)
            {
                AdjustAction = null;
                return;
            }
            var saveDiv = ModelDeviceSaveEnum.A未定义;
            var deviceType = string.Empty;
            //根据换行符切分数据文本
            string[] arryData = fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string strData in arryData)
            {
                if (strData == "#START#")
                {
                    //无附加数据的【数据标题】
                    continue;
                }
                if (strData.StartsWith("#DeviceTemplate START#") == true)
                {
                    //附加数据:设备保存区分
                    saveDiv = (ModelDeviceSaveEnum)Convert.ToInt32(strData.Substring(22));
                    continue;
                }
                if (strData.StartsWith("#DeviceInfo START#") == true)
                {
                    //附加数据:设备对象类型
                    deviceType = strData.Substring(18);
                    continue;
                }
                try
                {
                    //执行数据处理
                    AdjustAction(strData, saveDiv, deviceType);
                }
                catch (Exception ex)
                {
                    HdlLogLogic.Current.WriteLog(ex, "模板bin文件出问题\r\n" + this.strTempContentData);
                    this.strTempContentData = string.Empty;
                }
            }
        }
        #endregion
        #region ■ 反序列化设备的保存文件内容_________
        /// <summary>
        /// 反序列化设备的保存文件内容
        /// </summary>
        /// <param name="saveDiv">保存区分</param>
        /// <param name="fileData"></param>
        /// <returns></returns>
        private TemplateDeviceDataCommon DeserializeDeviceDataByDiv(ModelDeviceSaveEnum saveDiv, string fileData)
        {
            TemplateDeviceDataCommon modelData = null;
            if (saveDiv == ModelDeviceSaveEnum.APir配置)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPirSensorSettion>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A空调摆风功能)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelAcSwingModeSupport>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A空调自定义模式)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelAcModeSupport>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A窗帘手拉控制)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelCurtainHandPullControl>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A窗帘方向及限位)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelCurtainDirectionAndLimite>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A端点名称)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceEpointNameInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A设备名称)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceMacNameInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A设备绑定列表)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceBindData>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板亮度调节)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelBrightnessAdjustInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板节能模式)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelEnergyModeInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板指示灯)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelIndicatorLightInfo>(fileData);
            }
            else if (saveDiv == ModelDeviceSaveEnum.A面板震动功能)
            {
                modelData = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelPanelVibrationInfo>(fileData);
            }
            return modelData;
        }
        /// <summary>
        /// 将设备模板数据添加入缓存
        /// </summary>
        /// <param name="modelData">模板数据</param>
        /// <param name="fileData">设备保存在文件中的内容(可为null)</param>
        /// <param name="mainKey">添加的主键</param>
        /// <param name="addToTemplate">是否添加到设备模板缓存中</param>
        private void SetTemplateDeviceDataToMemmory(TemplateDeviceDataCommon modelData, string fileData, string mainKey, bool addToTemplate)
        {
            if (modelData == null)
            {
                return;
            }
            //从模板主文件中获取的设备模板信息,是不需要添加到这个变量中的
            //因为它只能慢慢一个个匹配
            if (addToTemplate == true)
            {
                if (this.modelData.dicDeviceTemplateData.ContainsKey(mainKey) == false)
                {
                    this.modelData.dicDeviceTemplateData[mainKey] = new List<TemplateDeviceDataCommon>();
                }
                this.modelData.dicDeviceTemplateData[mainKey].Add(modelData);
            }
            if (fileData != null)
            {
                //临时缓存:模板中各自端点所保存的内容(keys:设备主键),设备选择模板时,模板数据迁移使用,因为是引用类型,所以需要重新New
                if (this.modelData.dicDeviceFileContent.ContainsKey(mainKey) == false)
                {
                    this.modelData.dicDeviceFileContent[mainKey] = new List<TemplateDeviceContent>();
                }
                var fileCentent = new TemplateDeviceContent();
                fileCentent.saveDiv = modelData.DataSaveDiv;
                fileCentent.FileContent = fileData;
                fileCentent.DeviceMac = modelData.DeviceMac;
                this.modelData.dicDeviceFileContent[mainKey].Add(fileCentent);
            }
        }
        #endregion
        #region ■ 保存模板数据到本地相关_____________
        /// <summary>
        /// 保存模板数据到本地
        /// </summary>
        /// <param name="backupName">备份名称</param>
        /// <param name="saveFirmware">是否下载固件</param>
        public void SaveTemplateDataToLocation(string backupName, bool downloadFirmware = true)
        {
            //获取本地全部的模板列表的基本信息
            var localModel = this.GetLocalAllModelList();
            var fileName = this.GetNewTemplateFileName();
            foreach (var model in localModel)
            {
                //名字一样时
                if (model.ModelName == backupName)
                {
                    fileName = model.FileName;
                    //备份数据已经存在,是否覆盖?
                    this.ShowMassage(ShowMsgType.Confirm, Language.StringByID(R.MyInternationalizationString.BackUpDataIsEsixtAndPickUp), () =>
                    {
                        //将模板数据保存到到指定的文件夹中
                        this.SaveTemplateDataToLocation2(fileName, backupName, downloadFirmware);
                    });
                    return;
                }
            }
            //将模板数据保存到到指定的文件夹中
            this.SaveTemplateDataToLocation2(fileName, backupName, downloadFirmware);
        }
        /// <summary>
        /// 保存模板数据到本地
        /// </summary>
        /// <param name="fileName">保存文件的名字</param>
        /// <param name="backName">模板备份的名字</param>
        /// <param name="saveFirmware">是否下载固件</param>
        private void SaveTemplateDataToLocation2(string fileName, string backupName, bool downloadFirmware = true)
        {
            HdlThreadLogic.Current.RunThread(() =>
            {
                ProgressFormBar.Current.Start();
                ProgressFormBar.Current.SetMsg("正在保存模板数据");
                System.Threading.Thread.Sleep(1500);
                //将模板数据保存到到指定的文件夹中
                var fileFullName = this.SaveTemplateDataToFile(fileName, backupName);
                if (downloadFirmware == false)
                {
                    //本地备份保存成功
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.SaveLocalBackDataSuccess));
                    ProgressFormBar.Current.Close();
                    return;
                }
                //获取升级固件文件
                var result = HdlFirmwareUpdateLogic.Current.DownLoadTemplateDeviceFirmware(fileFullName, "正在保存升级固件数据");
                if (result == -1)
                {
                    this.ShowMassage(ShowMsgType.Tip, "保存升级固件数据失败");
                    //删掉这个模板
                    HdlFileLogic.Current.DeleteFile(fileFullName);
                }
                else
                {
                    //本地备份保存成功
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.SaveLocalBackDataSuccess));
                }
                ProgressFormBar.Current.Close();
            });
        }
        /// <summary>
        /// 在生成模板数据之前,检测模板数据
        /// </summary>
        private void CheckTempLateDataBeforCreat()
        {
            //为了保证模板里的设备数和本地的一致,所以检测一下
            //如果缺少,则添加修改Mac的数据进去
            //其他的,如果不点击各自的配置界面,则当做是默认设备原来的配置状态
            //获取目前已经设置设备物理名称的设备Mac
            var listMac = new HashSet<string>();
            foreach (var listData in this.modelData.dicDeviceTemplateData.Values)
            {
                if (listData.Count > 0 && listMac.Contains(listData[0].DeviceMac) == true)
                {
                    //已经加了
                    continue;
                }
                foreach (var data in listData)
                {
                    if (data.DataSaveDiv == ModelDeviceSaveEnum.A设备名称)
                    {
                        listMac.Add(data.DeviceMac);
                    }
                }
            }
            var listDevice = HdlDeviceCommonLogic.Current.listAllDevice;
            foreach (var device in listDevice)
            {
                if (listMac.Contains(device.DeviceAddr) == false)
                {
                    listMac.Add(device.DeviceAddr);
                    //重新添加Mac名字缓存
                    HdlTemplateDeviceDataLogic.Current.ReDeviceMacName(device, HdlDeviceCommonLogic.Current.GetDeviceMacName(device));
                }
                //重新添加端点名字缓存
                HdlTemplateDeviceDataLogic.Current.ReDeviceEpointName(device, HdlDeviceCommonLogic.Current.GetDeviceEpointName(device));
            }
        }
        #endregion
        #region ■ 获取模板对象相关___________________
        /// <summary>
        /// 获取本地全部的模板列表的基本信息
        /// </summary>
        /// <returns></returns>
        public List<LocalModelBaseInfo> GetLocalAllModelList()
        {
            var dicData = new Dictionary<string, List<LocalModelBaseInfo>>();
            var listTime = new List<string>();
            var strPath = HdlFileNameResourse.AllResidenceTemplateDirectory;
            //获取全部文件
            var arryFile = System.IO.Directory.GetFiles(strPath, "ModelData_*");
            foreach (string modelFile in arryFile)
            {
                //读取文件内容
                var textValue = HdlFileLogic.Current.ReadFileTextContent(modelFile);
                if (textValue == null)
                {
                    continue;
                }
                //从文件中获取指定的内容
                string modelBaseInfo = this.GetDataFromFileContent(textValue, "#START#", "#TemplateData END#");
                if (modelBaseInfo != string.Empty)
                {
                    var myModel = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(modelBaseInfo);
                    myModel.FileName = modelFile.Substring(strPath.Length + 1);
                    if (dicData.ContainsKey(myModel.EditorTime) == false)
                    {
                        dicData[myModel.EditorTime] = new List<LocalModelBaseInfo>();
                        listTime.Add(myModel.EditorTime);
                    }
                    dicData[myModel.EditorTime].Add(myModel);
                    string homeData = this.GetDataFromFileContent(textValue, "#START#", "#TemplateHomeInfo END#");
                    if (homeData != string.Empty)
                    {
                        var homeInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<TemplateHomeInfo>(homeData);
                        myModel.ListUintContent.AddRange(homeInfo.ListUintContent);
                        myModel.ListUintName.AddRange(homeInfo.ListUintName);
                        myModel.ResidenceAddressName = homeInfo.ResidenceAddressName;
                    }
                }
            }
            //按时间排序
            listTime.Sort();
            var listData = new List<LocalModelBaseInfo>();
            for (int i = listTime.Count - 1; i >= 0; i--)
            {
                listData.AddRange(dicData[listTime[i]]);
            }
            return listData;
        }
        /// <summary>
        /// 获取云端全部的模板列表的基本信息
        /// </summary>
        /// <param name="mode">失败时是否显示tip消息</param>
        /// <returns></returns>
        public List<CloundModelBaseInfo> GetCloundAllModelList(ShowNetCodeMode mode= ShowNetCodeMode.YES)
        {
            var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/template/metaInfo/findAll", RestSharp.Method.POST, null);
            //检测状态码
            if (HdlCheckLogic.Current.CheckNetCode(result, mode) == false)
            {
                return new List<CloundModelBaseInfo>();
            }
            var dicData = new Dictionary<string, List<CloundModelBaseInfo>>();
            var listTime = new List<string>();
            var listCloundData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<CloundModelBaseInfo>>(result.Data.ToString());
            foreach (var data in listCloundData)
            {
                //变更时间格式
                data.CreateTime = HdlCommonLogic.Current.ConvertUtcTimeToLocalTime2(data.CreateTime).ToString("yyyy.MM.dd HH:mm");
                if (dicData.ContainsKey(data.CreateTime) == false)
                {
                    dicData[data.CreateTime] = new List<CloundModelBaseInfo>();
                    listTime.Add(data.CreateTime);
                }
                dicData[data.CreateTime].Add(data);
            }
            //按时间排序
            listTime.Sort();
            var listData = new List<CloundModelBaseInfo>();
            for (int i = listTime.Count - 1; i >= 0; i--)
            {
                listData.AddRange(dicData[listTime[i]]);
            }
            return listData;
        }
        /// <summary>
        /// 获取一个新的模板保存文件名
        /// </summary>
        /// <returns></returns>
        public string GetNewTemplateFileName()
        {
            return "ModelData_Local_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".bin";
        }
        /// <summary>
        /// 获取一个新的模板保存文件名
        /// </summary>
        /// <returns></returns>
        public string GetNewTemplateFileName(DateTime dateTime)
        {
            return "ModelData_Local_" + dateTime.ToString("yyyyMMdd_HHmmss") + ".bin";
        }
        #endregion
        #region ■ 上传模板备份_______________________
        /// <summary>
        /// 上传模板备份(内部使用线程来执行,有转圈的界面)
        /// </summary>
        /// <param name="i_localTemplate">本地模板信息</param>
        /// <param name="i_saveName">备份名字</param>
        /// <param name="mode">失败时是否显示tip消息</param>
        public void UpLoadTemplateData(LocalModelBaseInfo i_localTemplate, string i_saveName, ShowNetCodeMode mode = ShowNetCodeMode.YES)
        {
            HdlThreadLogic.Current.RunThread(() =>
            {
                ProgressBar.Show();
                //获取云端的模板列表
                var listTemplate = this.GetCloundAllModelList();
                foreach (var data in listTemplate)
                {
                    if (data.TemplateName == i_saveName)
                    {
                        //模板名字已经存在
                        this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.TheTemplateNameIsEsixt));
                        ProgressBar.Close();
                        return;
                    }
                }
                //创建新的模板备份
                var templateId = this.CreatNewTemplateNameToDB(i_saveName, mode);
                if (templateId == null)
                {
                    ProgressBar.Close();
                    return;
                }
                //这里修改掉模板文件里面记载的模板名称
                string templateFile = System.IO.Path.Combine(HdlFileNameResourse.AllResidenceTemplateDirectory, i_localTemplate.FileName);
                string binFileData = HdlFileLogic.Current.ReadFileTextContent(templateFile);
                var arryBinFile = binFileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                //替换目标 这里是模板基本信息的json数据
                string strFileData = arryBinFile[1];
                var templateBaseInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(strFileData);
                templateBaseInfo.ModelName = i_saveName;//更改掉名字
                templateBaseInfo.EditorTime = DateTime.Now.ToString("yyyy.MM.dd HH:mm");//更改掉时间
                //替换对象
                string replaceDta = Newtonsoft.Json.JsonConvert.SerializeObject(templateBaseInfo);
                binFileData = binFileData.Replace(strFileData, replaceDta);
                var dicQuery = new Dictionary<string, object>();
                dicQuery["fileName"] = "ModelData_Cloud_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".bin";
                dicQuery["templateId"] = templateId;
                var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/template/file/add", RestSharp.Method.POST, Encoding.UTF8.GetBytes(binFileData), dicQuery, null, CheckMode.A不检测, true, 10);
                //检测状态码
                if (HdlCheckLogic.Current.CheckNetCode(result, mode) == true)
                {
                    //上传模板成功
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.UploadTemplateSuccess));
                }
                else
                {
                    //上传模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.UploadTemplateFail));
                }
                ProgressBar.Close();
            });
        }
        /// <summary>
        /// 在云端创建新的模板名称
        /// </summary>
        /// <param name="i_saveName">新名字</param>
        /// <param name="mode">失败时是否显示tip消息</param>
        /// <returns></returns>
        private string CreatNewTemplateNameToDB(string i_saveName, ShowNetCodeMode mode = ShowNetCodeMode.YES)
        {
            var pra = new { templateName = i_saveName };
            var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/template/metaInfo/add", RestSharp.Method.POST, pra);
            //检测状态码
            if (HdlCheckLogic.Current.CheckNetCode(result, mode) == false)
            {
                return null;
            }
            var idData = Newtonsoft.Json.JsonConvert.DeserializeObject<IdInfoClass>(result.Data.ToString());
            return idData.Id;
        }
        #endregion
        #region ■ 下载模板备份_______________________
        /// <summary>
        /// 下载模板备份(内部是使用线程执行,有界面型进度条)
        /// </summary>
        /// <param name="i_templateId">数据库主键</param>
        /// <param name="i_SuccessAction">下载完全成功之后的回调事件,参数为保存模板的全路径(参数null代表失败)</param>
        /// <param name="mode">失败时是否显示tip消息</param>
        public void DownLoadTemplate(string i_templateId, Action<string> i_SuccessAction = null,ShowNetCodeMode mode= ShowNetCodeMode.YES)
        {
            HdlThreadLogic.Current.RunThread(() =>
            {
                ProgressFormBar.Current.Start();
                ProgressFormBar.Current.SetMsg("正在下载模板数据");
                System.Threading.Thread.Sleep(1500);
                var pra = new { templateId = i_templateId };
                //获取指定模板的列表文件
                var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/template/file/findAll", RestSharp.Method.POST, pra);
                //检测状态码
                if (HdlCheckLogic.Current.CheckNetCode(result, mode) == false)
                {
                    //下载模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.DownloadTemplateFail));
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                var listFileData = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DownloadTemplateData>>(result.Data.ToString());
                if (listFileData.Count == 0)
                {
                    //下载模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.DownloadTemplateFail));
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                //下载模板的内容
                var pra2 = new { templateFileId = listFileData[0].Id, templateMetaInfoId = i_templateId };
                var byteContent = HdlHttpLogic.Current.RequestByteFromZigbeeHttps("home-wisdom/template/file/downOne", RestSharp.Method.POST, pra2, null, null, CheckMode.A不检测, true, 10);
                if (byteContent == null || byteContent.Length == 0)
                {
                    //下载模板失败
                    this.ShowMassage(ShowMsgType.Tip, Language.StringByID(R.MyInternationalizationString.DownloadTemplateFail));
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                //解析这个模板的名字
                var strFileData = this.GetDataFromFileContent(Encoding.UTF8.GetString(byteContent), "#START#", "#TemplateData END#");
                var templateBaseInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<LocalModelBaseInfo>(strFileData);
                //检测本地的模板是否有同名的
                var listLocal = this.GetLocalAllModelList();
                string fileName = listFileData[0].FileName;
                foreach (var localData in listLocal)
                {
                    if (localData.ModelName == templateBaseInfo.ModelName)
                    {
                        //替换,直接使用本地的模板文件名字
                        fileName = localData.FileName;
                        break;
                    }
                }
                //存成文件
                string fileFullName = System.IO.Path.Combine(HdlFileNameResourse.AllResidenceTemplateDirectory, fileName);
                HdlFileLogic.Current.SaveByteToFile(fileFullName, byteContent);
                byteContent = null;
                //获取升级固件文件
                var result2 = HdlFirmwareUpdateLogic.Current.DownLoadTemplateDeviceFirmware(fileFullName, "正在获取升级固件数据");
                if (result2 == -1)
                {
                    this.ShowMassage(ShowMsgType.Tip, "获取升级固件数据失败");
                    ProgressFormBar.Current.Close();
                    i_SuccessAction?.Invoke(null);
                    return;
                }
                ProgressFormBar.Current.Close();
                i_SuccessAction?.Invoke(fileFullName);
            });
        }
        /// <summary>
        /// 下载模板
        /// </summary>
        private class DownloadTemplateData
        {
            /// <summary>
            /// 模板文件名字
            /// </summary>
            public string FileName = string.Empty;
            /// <summary>
            /// 主键
            /// </summary>
            public string Id = string.Empty;
        }
        #endregion
        #region ■ 删除模板备份_______________________
        /// <summary>
        /// 删除云端模板备份
        /// </summary>
        /// <param name="i_templateId">模板主键</param>
        /// <param name="mode">失败时是否显示tip消息</param>
        /// <returns></returns>
        public bool DeleteTemplateFromDb(string i_templateId, ShowNetCodeMode mode = ShowNetCodeMode.YES)
        {
            var pra = new { templateId = i_templateId };
            var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/template/metaInfo/delete", RestSharp.Method.POST, pra);
            if (result != null && result.Code == HttpMessageEnum.A10605)
            {
                //模板对象不存在,当做成功
                return true;
            }
            //检测状态码
            if (HdlCheckLogic.Current.CheckNetCode(result, mode) == false)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 删除本地模板备份
        /// </summary>
        /// <param name="i_baseInfo">本地模板的基本信息</param>
        /// <returns></returns>
        public void DeleteLocalTemplate(LocalModelBaseInfo i_baseInfo)
        {
            var fullFile = System.IO.Path.Combine(HdlFileNameResourse.AllResidenceTemplateDirectory, i_baseInfo.FileName);
            HdlFileLogic.Current.DeleteFile(fullFile);
        }
        #endregion
        #region ■ 生成模板数据相关___________________
        /// <summary>
        /// 保存模板数据到文件(返回保存文件的全路径)
        /// </summary>
        /// <param name="fileName">保存文件的名字(新建时用 GetNewTemplateFileName函数新建)</param>
        /// <param name="backName">模板备份的名字</param>
        public string SaveTemplateDataToFile(string fileName, string backUpName)
        {
            //写入文件的内容
            string writeText = string.Empty;
            //在生成模板数据之前,检测模板数据
            this.CheckTempLateDataBeforCreat();
            //生成写入文件的【模板基本数据】
            this.CreatWriteTemplateBaseData(ref writeText, backUpName);
            //生成写入文件的【模板住宅信息数据】
            this.CreatWriteTemplateHomeData(ref writeText);
            //生成写入文件的【设备模板数据】
            this.CreatWriteDeviceTemplateData(ref writeText);
            //生成写入文件的【设备对象数据】
            this.CreatWriteCommonDeviceData(ref writeText);
            //生成写入文件的【网关对象数据】
            this.CreatWriteGatewayData(ref writeText);
            //生成写入文件的【场景模板数据】
            this.CreatWriteSceneData(ref writeText);
            //生成写入文件的【房间模板数据】
            this.CrearWriteRoomTemplateData(ref writeText);
            //生成写入文件的【设备和网关选择的模板的数据】
            this.CrearWriteDeviceSelectTemplateData(ref writeText);
            //写入内容
            string saveFile = HdlFileNameResourse.AllResidenceTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, fileName);
            HdlFileLogic.Current.SaveTextToFile(saveFile, writeText);
            return saveFile;
        }
        /// <summary>
        /// 生成写入文件的【模板基本数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CreatWriteTemplateBaseData(ref string writeText, string backUpName)
        {
            var modelData = new LocalModelBaseInfo();
            modelData.EditorTime = DateTime.Now.ToString("yyyy.MM.dd HH:mm");
            modelData.ModelName = backUpName;
            modelData.FloorCount = Common.Config.Instance.Home.FloorDics.Count;
            modelData.DeviceCount = this.modelData.dicDeviceTemplateData.Count;
            //功能数
            int funcCount = 0;
            foreach (var listData in this.modelData.dicDeviceTemplateData.Values)
            {
                if (listData.Count > 0)
                {
                    var listDevice = HdlDeviceCommonLogic.Current.GetDevicesByMac(listData[0].DeviceMac, false);
                    funcCount += listDevice.Count;
                }
            }
            modelData.FunctionCount = funcCount;
            writeText += "#START#\r\n";
            string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(modelData);
            writeText += dataInfo + "\r\n";
            writeText += "#TemplateData END#\r\n\r\n";
        }
        /// <summary>
        /// 生成写入文件的【模板住宅信息数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CreatWriteTemplateHomeData(ref string writeText)
        {
            var homeData = new TemplateHomeInfo();
            homeData.ResidenceAddressName = Common.Config.Instance.Home.ResidenceAddressName;
            homeData.ListUintName.AddRange(Common.Config.Instance.Home.ListUintName);
            homeData.ListUintContent.AddRange(Common.Config.Instance.Home.ListUintContent);
            writeText += "#START#\r\n";
            string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(homeData);
            writeText += dataInfo + "\r\n";
            writeText += "#TemplateHomeInfo END#\r\n\r\n";
        }
        /// <summary>
        /// 生成写入文件的【设备模板数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CreatWriteDeviceTemplateData(ref string writeText)
        {
            foreach (var list in this.modelData.dicDeviceTemplateData.Values)
            {
                foreach (var data in list)
                {
                    writeText += "#DeviceTemplate START#" + (int)data.DataSaveDiv + "\r\n";
                    string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                    writeText += dataInfo + "\r\n";
                    writeText += "#DeviceTemplate END#\r\n\r\n";
                }
            }
        }
        /// <summary>
        /// 生成写入文件的【设备对象数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CreatWriteCommonDeviceData(ref string writeText)
        {
            var listDevice = HdlDeviceCommonLogic.Current.listAllDevice;
            var listCheck = new HashSet<string>();
            foreach (var device in listDevice)
            {
                //设备端点
                writeText += "#DeviceInfo START#" + (int)device.Type + "\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(device);
                writeText += dataInfo + "\r\n";
                writeText += "#DeviceInfo END#\r\n\r\n";
                //添加Ota设备对象的缓存
                if (listCheck.Contains(device.DeviceAddr) == false)
                {
                    listCheck.Add(device.DeviceAddr);
                    var otaDevice = HdlDeviceCommonLogic.Current.GetOTADevice(device.DeviceAddr);
                    if (otaDevice != null)
                    {
                        writeText += "#DeviceInfo START#" + (int)otaDevice.Type + "\r\n";
                        string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(otaDevice);
                        writeText += dataInfo2 + "\r\n";
                        writeText += "#DeviceInfo END#\r\n\r\n";
                    }
                }
            }
        }
        /// <summary>
        /// 生成写入文件的【网关对象数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CreatWriteGatewayData(ref string writeText)
        {
            var listGateway = HdlGatewayLogic.Current.GetAllLocalGateway();
            foreach (var gateway in listGateway)
            {
                //设备端点
                writeText += "#START#\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(gateway);
                writeText += dataInfo + "\r\n";
                writeText += "#GatewayInfo END#\r\n\r\n";
            }
        }
        /// <summary>
        /// 生成写入文件的【场景数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CreatWriteSceneData(ref string writeText)
        {
            //全部的场景
            var listScene = HdlSceneLogic.Current.GetAllLocalScene();
            foreach (var scene in listScene)
            {
                writeText += "#START#\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(scene);
                writeText += dataInfo + "\r\n";
                writeText += "#SceneTemplate END#\r\n\r\n";
            }
        }
        /// <summary>
        /// 生成写入文件的【房间模板数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CrearWriteRoomTemplateData(ref string writeText)
        {
            //楼层数据
            writeText += "#START#\r\n";
            string dataInfo1 = Newtonsoft.Json.JsonConvert.SerializeObject(Common.Config.Instance.Home.FloorDics);
            writeText += dataInfo1 + "\r\n";
            writeText += "#FloorInfo END#\r\n\r\n";
            //房间数据
            var listRoom = HdlRoomLogic.Current.GetAllListRooms();
            foreach (var room in listRoom)
            {
                writeText += "#START#\r\n";
                string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(room);
                writeText += dataInfo2 + "\r\n";
                writeText += "#RoomInfo END#\r\n\r\n";
            }
        }
        /// <summary>
        /// 生成写入文件的【设备和网关选择的模板的数据】
        /// </summary>
        /// <param name="writeText"></param>
        public void CrearWriteDeviceSelectTemplateData(ref string writeText)
        {
            //设备选择模板的数据
            writeText += "#START#\r\n";
            string dataInfo1 = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicDeviceTemplateSelect);
            writeText += dataInfo1 + "\r\n";
            writeText += "#DeviceSelectTemplate END#\r\n\r\n";
            //网关选择模板的数据
            writeText += "#START#\r\n";
            string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicGatewayTemplateSelect);
            writeText += dataInfo2 + "\r\n";
            writeText += "#GatewaySelectTemplate END#\r\n\r\n";
        }
        #endregion
        #region ■ 强制执行的特殊函数_________________
        /// <summary>
        /// 强制从缓存当中生成设备和网关文件
        /// </summary>
        public void CreatDeviceAndGatewayFileFromMemoryByForce()
        {
            //原来的状态
            bool oldShowTemplate = Common.Config.Instance.Home.IsShowTemplate;
            //让它可以生成文件
            Common.Config.Instance.Home.IsShowTemplate = false;
            //生成设备文件
            foreach (var listDevice in this.modelData.dicDeviceInfo.Values)
            {
                foreach (var device in listDevice)
                {
                    device.ReSave();
                }
            }
            //生成网关文件
            foreach (var gateway in this.modelData.dicGatewayInfo.Values)
            {
                gateway.ReSave();
            }
            //还原状态
            Common.Config.Instance.Home.IsShowTemplate = oldShowTemplate;
        }
        #endregion
        #region ■ 设备和网关模板选择相关_____________
        /// <summary>
        /// 添加/修改 设备模板选择目标
        /// </summary>
        /// <param name="sourceMac">设备Mac对象</param>
        /// <param name="targetMac">目标Mac对象</param>
        public void AddDeviceTemplateSelect(string sourceMac, string targetMac)
        {
            //获取本地指定的Mac的全部设备
            var listDevice = HdlDeviceCommonLogic.Current.GetDevicesByMac(sourceMac, false);
            var otaDevice = HdlDeviceCommonLogic.Current.GetOTADevice(sourceMac);
            if (otaDevice != null)
            {
                //这里ota设备也要加进去,重中之重
                listDevice.Add(otaDevice);
            }
            foreach (var device in listDevice)
            {
                //模板选择的时候,他们的端点是一致的
                string localDeviceKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device);
                string templateDeviceKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(targetMac, device.DeviceEpoint);
                if (this.modelData.dicDeviceTemplateRoom.ContainsKey(templateDeviceKey) == true
                    && (device is OTADevice) == false)
                {
                    //如果模板里面,这个端点设置有房间的话
                    HdlRoomLogic.Current.ChangedRoom(device, this.modelData.dicDeviceTemplateRoom[templateDeviceKey], false);
                }
                //如果这个端点有模板数据的话
                if (this.modelData.dicDeviceFileContent.ContainsKey(templateDeviceKey) == true)
                {
                    //如果原来它选择有模板数据的话
                    if (this.modelData.dicDeviceTemplateData.ContainsKey(localDeviceKey) == true)
                    {
                        //删除这个设备的模板保存文件
                        HdlFileLogic.Current.DeleteFile(System.IO.Path.Combine(HdlFileNameResourse.LocalTemplateDirectory, device.FilePath));
                        //移除当前端点保存的模板数据
                        this.modelData.dicDeviceTemplateData.Remove(localDeviceKey);
                    }
                    //反序列化设备数据
                    foreach (var strCentent in this.modelData.dicDeviceFileContent[templateDeviceKey])
                    {
                        var tempData = this.DeserializeDeviceDataByDiv(strCentent.saveDiv, strCentent.FileContent);
                        //这里需要替换掉Mac
                        tempData.DeviceMac = sourceMac;
                        //添加缓存(主键为本地设备的主键)
                        this.SetTemplateDeviceDataToMemmory(tempData, null, localDeviceKey, true);
                        //修改端点缓存名字
                        if (tempData.DataSaveDiv == ModelDeviceSaveEnum.A端点名称)
                        {
                            HdlDeviceCommonLogic.Current.SetEpointName(device, ((ModelDeviceEpointNameInfo)tempData).deviceEpointName);
                        }
                        else if (tempData.DataSaveDiv == ModelDeviceSaveEnum.A设备名称)
                        {
                            HdlDeviceCommonLogic.Current.SetMacName(device, ((ModelDeviceMacNameInfo)tempData).deviceMacName);
                        }
                    }
                }
                //不管如何,都需要则重新保存成文件
                this.SaveDeviceMemmoryData(device.DeviceAddr, device.DeviceEpoint);
                //还原及变更场景的执行目标
                //this.RecoverAndChangedSceneAdjustTarget(device, targetMac);
            }
            //更改物理设备所在的房间
            if (this.modelData.dicDeviceTemplateRealRoom.ContainsKey(targetMac) == true)
            {
                HdlRoomLogic.Current.SaveRealDeviceRoomId(listDevice, this.modelData.dicDeviceTemplateRealRoom[targetMac], false);
            }
            //记录缓存
            this.modelData.dicDeviceTemplateSelect[sourceMac] = targetMac;
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicDeviceTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(HdlFileNameResourse.DeviceTemplateSelectFile, fileData);
        }
        /// <summary>
        /// 还原及变更场景的执行目标
        /// </summary>
        /// <param name="device">本地设备对象</param>
        /// <param name="targetMac">需要变更的模板设备的Mac</param>
        private void RecoverAndChangedSceneAdjustTarget(CommonDevice device, string targetMac)
        {
            //如果这个设备是替换选择的模板的话
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(device.DeviceAddr) == false)
            {
                return;
            }
            //全部的场景
            var listScene = HdlSceneLogic.Current.GetAllLocalScene();
            //还没有执行变更前,它目前选择的模板的Mac
            string oldTemplateMac = this.modelData.dicDeviceTemplateSelect[device.DeviceAddr];
            //将场景对象中,这个回路的主键,替换回原来模板中的Mac+端口
            foreach (var scene in listScene)
            {
                bool save = false;
                for (int i = 0; i < scene.AdjustTargetList.Count; i++)
                {
                    if (scene.AdjustTargetList[i].Type != 0)
                    {
                        //只处理设备绑定目标
                        continue;
                    }
                    //如果是当前回路
                    if (scene.AdjustTargetList[i].DeviceAddr == device.DeviceAddr &&
                       scene.AdjustTargetList[i].Epoint == device.DeviceEpoint)
                    {
                        //替换掉Mac
                        scene.AdjustTargetList[i].DeviceAddr = oldTemplateMac;
                        save = true;
                        continue;
                    }
                    //如果是模板目标回路
                    if (targetMac != null &&
                        scene.AdjustTargetList[i].DeviceAddr == targetMac &&
                        scene.AdjustTargetList[i].Epoint == device.DeviceEpoint)
                    {
                        //将目标的Mac变更为当前设备的Mac
                        scene.AdjustTargetList[i].DeviceAddr = device.DeviceAddr;
                        save = true;
                        continue;
                    }
                }
                if (save == true)
                {
                    //保存缓存
                    scene.Save();
                }
            }
        }
        /// <summary>
        /// 获取设备已经选择了的模板目标的设备的Mac(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">设备的Mac</param>
        /// <returns></returns>
        public string GetDeviceTemplateSelectMac(string sourceMac)
        {
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(sourceMac) == true)
            {
                return this.modelData.dicDeviceTemplateSelect[sourceMac];
            }
            return null;
        }
        /// <summary>
        /// 获取设备已经选择了的模板目标的设备的Mac名字(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">设备的Mac</param>
        /// <returns></returns>
        public string GetDeviceTemplateSelectName(string sourceMac)
        {
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(sourceMac) == true)
            {
                string tempMac = this.modelData.dicDeviceTemplateSelect[sourceMac];
                foreach (var listData in this.modelData.dicDeviceFileContent.Values)
                {
                    foreach (var data in listData)
                    {
                        if (data.DeviceMac != tempMac || data.saveDiv != ModelDeviceSaveEnum.A设备名称)
                        {
                            continue;
                        }
                        var tempModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceMacNameInfo>(data.FileContent);
                        return tempModel.deviceMacName;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// 取消设备模板的选择目标
        /// </summary>
        /// <param name="sourceMac">设备的Mac</param>
        public void RemoveDeviceTemplateSelect(string sourceMac)
        {
            ////获取本地指定的Mac的全部设备
            //var listDevice = HdlDeviceCommonLogic.Current.GetDevicesByMac(sourceMac, false);
            //foreach (var device in listDevice)
            //{
            //    //还原场景的执行目标
            //    this.RecoverAndChangedSceneAdjustTarget(device, null);
            //}
            //记录缓存
            this.modelData.dicDeviceTemplateSelect.Remove(sourceMac);
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicDeviceTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(HdlFileNameResourse.DeviceTemplateSelectFile, fileData);
        }
        /// <summary>
        /// 添加/修改 网关模板选择目标
        /// </summary>
        /// <param name="sourceGwid">网关id</param>
        /// <param name="targetGwid">目标网关id(模板)</param>
        public void AddGatewayTemplateSelect(string sourceGwid, string targetGwid)
        {
            //记录缓存
            this.modelData.dicGatewayTemplateSelect[sourceGwid] = targetGwid;
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicGatewayTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(HdlFileNameResourse.GatewayTemplateSelectFile, fileData);
            //变更网关房间
            if (this.modelData.dicDeviceTemplateRealRoom.ContainsKey(targetGwid) == true)
            {
                HdlRoomLogic.Current.ChangedGatewayRoom(sourceGwid, this.modelData.dicDeviceTemplateRealRoom[targetGwid]);
            }
            //变更网关名字
            //if (this.modelData.dicGatewayInfo.ContainsKey(targetGwid) == true)
            //{
            //    var localGateway = HdlGatewayLogic.Current.GetLocalGateway(sourceGwid);
            //    string gwName = HdlGatewayLogic.Current.GetGatewayName(this.modelData.dicGatewayInfo[targetGwid]);
            //    HdlGatewayLogic.Current.ReName(localGateway, gwName);
            //}
        }
        /// <summary>
        /// 取消网关模板选择目标
        /// </summary>
        /// <param name="sourceGwid">网关id</param>
        /// <param name="targetGwid">目标网关id</param>
        public void RemoveGatewayTemplateSelect(string sourceGwid)
        {
            //记录缓存
            this.modelData.dicGatewayTemplateSelect.Remove(sourceGwid);
            //保存的路径
            string fileData = Newtonsoft.Json.JsonConvert.SerializeObject(this.modelData.dicGatewayTemplateSelect);
            HdlFileLogic.Current.SaveTextToFile(HdlFileNameResourse.GatewayTemplateSelectFile, fileData);
        }
        /// <summary>
        /// 获取网关已经选择了的模板目标的网关的名字(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">网关id</param>
        /// <returns></returns>
        public string GetGatewayTemplateSelectName(string sourceGwid)
        {
            if (this.modelData.dicGatewayTemplateSelect.ContainsKey(sourceGwid) == true)
            {
                string tempMac = this.modelData.dicGatewayTemplateSelect[sourceGwid];
                if (this.modelData.dicGatewayInfo.ContainsKey(tempMac) == true)
                {
                    string gwName = HdlGatewayLogic.Current.GetGatewayName(this.modelData.dicGatewayInfo[tempMac]);
                    return gwName;
                }
            }
            return null;
        }
        /// <summary>
        /// 获取网关已经选择了的模板目标的网关的名字(没有目标时,返回null)
        /// </summary>
        /// <param name="sourceMac">网关id</param>
        /// <returns></returns>
        public string GetGatewayTemplateSelectId(string sourceGwid)
        {
            if (this.modelData.dicGatewayTemplateSelect.ContainsKey(sourceGwid) == true)
            {
                return this.modelData.dicGatewayTemplateSelect[sourceGwid];
            }
            return null;
        }
        /// <summary>
        /// 获取模板中全部网关的名字
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetAllGatewayTemplateName()
        {
            var dic = new Dictionary<string, string>();
            foreach (string gwId in this.modelData.dicGatewayInfo.Keys)
            {
                string gwName = HdlGatewayLogic.Current.GetGatewayName(this.modelData.dicGatewayInfo[gwId]);
                dic[gwId] = gwName;
            }
            return dic;
        }
        /// <summary>
        /// 获取指定网关能够选择的模板名字
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, string> GetGatewayCanSelectTemplateName(ZbGateway zbGateway)
        {
            var dic = new Dictionary<string, string>();
            foreach (var zbway in this.modelData.dicGatewayInfo.Values)
            {
                if (zbGateway.LinuxImageType == zbway.LinuxImageType)
                {
                    string gwName = HdlGatewayLogic.Current.GetGatewayName(zbway);
                    dic[zbway.GwId] = gwName;
                }
            }
            return dic;
        }
        /// <summary>
        /// 清除全部已经已经选择好了模板对象的设备和网关
        /// </summary>
        public void ClearAllSelectDeviceAndGateway()
        {
            //重新初始化
            this.modelData.dicDeviceTemplateSelect = new Dictionary<string, string>();
            this.modelData.dicGatewayTemplateSelect = new Dictionary<string, string>();
            //删掉这两个保存选择模板的文件
            HdlFileLogic.Current.DeleteFile(HdlFileNameResourse.DeviceTemplateSelectFile);
            HdlFileLogic.Current.DeleteFile(HdlFileNameResourse.GatewayTemplateSelectFile);
        }
        #endregion
        #region ■ 获取能够选择的模板_________________
        /// <summary>
        /// 获取能够选择的模板
        /// </summary>
        /// <param name="localDevice">本地设备</param>
        /// <returns></returns>
        public List<TemplateCanSelectContent> GetCanSelectDeviceTemplate(CommonDevice localDevice)
        {
            var listCanSelect = new List<TemplateCanSelectContent>();
            if (this.modelData.dicGatewayTemplateSelect.ContainsKey(localDevice.CurrentGateWayId) == false)
            {
                //该网关没有匹配模板,不提供模板选择
                return listCanSelect;
            }
            var listHadSelect = new HashSet<string>();
            foreach (var localMac in this.modelData.dicDeviceTemplateSelect.Keys)
            {
                //它自己的话,可以显示(因为有个取消绑定的功能)
                if (localMac != localDevice.DeviceAddr)
                {
                    //目前已经被选择了的模板Mac
                    listHadSelect.Add(this.modelData.dicDeviceTemplateSelect[localMac]);
                }
            }
            var listCheck = new HashSet<string>();
            //设备的模块ID
            string modelId = this.GetDeviceModelId(localDevice.DeviceAddr);
            //模板中的网关ID
            string gatewayTemplateId = this.modelData.dicGatewayTemplateSelect[localDevice.CurrentGateWayId];
            foreach (var mainKey in this.modelData.dicDeviceFileContent.Keys)
            {
                var listData = this.modelData.dicDeviceFileContent[mainKey];
                foreach (var data in listData)
                {
                    if (data.saveDiv != ModelDeviceSaveEnum.A设备名称)
                    {
                        //只获取设备mac名称的模板数据
                        continue;
                    }
                    if (listHadSelect.Contains(data.DeviceMac) == true
                        || listCheck.Contains(data.DeviceMac) == true)
                    {
                        //如果这个模板已经被其他设备选择了,或者这个Mac已经处理了,则break
                        break;
                    }
                    if (this.modelData.dicDeviceInfo.ContainsKey(data.DeviceMac) == false
                        || this.modelData.dicDeviceInfo[data.DeviceMac][0].CurrentGateWayId != gatewayTemplateId
                        || this.modelData.dicDeviceInfo[data.DeviceMac][0].ModelIdentifier != modelId)
                    {
                        //该模板不是这个网关的,或者模块ID不一样的
                        break;
                    }
                    if (localDevice.DriveCode != 0)
                    {
                        //如果是虚拟设备,则如果不是同一个端点,则不能作为模板对象
                        string checkKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(data.DeviceMac, localDevice.DeviceEpoint);
                        if (checkKey != mainKey)
                        {
                            break;
                        }
                    }
                    listCheck.Add(data.DeviceMac);
                    var info = Newtonsoft.Json.JsonConvert.DeserializeObject<ModelDeviceMacNameInfo>(data.FileContent);
                    var selectData = new TemplateCanSelectContent();
                    selectData.DeviceMac = data.DeviceMac;
                    selectData.DeviceName = info.deviceMacName;
                    Common.Room room = null;
                    if (this.modelData.dicDeviceTemplateRealRoom.ContainsKey(data.DeviceMac) == true)
                    {
                        room = HdlRoomLogic.Current.GetRoomById(this.modelData.dicDeviceTemplateRealRoom[data.DeviceMac]);
                    }
                    selectData.RoomName = HdlRoomLogic.Current.GetRoomName(room);
                    listCanSelect.Add(selectData);
                }
            }
            return listCanSelect;
        }
        #endregion
        #region ■ 删除设备___________________________
        /// <summary>
        /// 删除设备
        /// </summary>
        /// <param name="device"></param>
        public void DeleteDevice(CommonDevice device)
        {
            //删除保存文件
            string saveFile = HdlFileNameResourse.LocalTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, device.FilePath);
            HdlFileLogic.Current.DeleteFile(saveFile);
            //移除模板缓存
            this.modelData.dicDeviceTemplateData.Remove(HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device));
            //移除设备选择缓存
            if (this.modelData.dicDeviceTemplateSelect.ContainsKey(device.DeviceAddr) == true)
            {
                this.modelData.dicDeviceTemplateSelect.Remove(device.DeviceAddr);
                HdlFileLogic.Current.SaveFileContent(HdlFileNameResourse.DeviceTemplateSelectFile, this.modelData.dicDeviceTemplateSelect);
            }
        }
        #endregion
        #region ■ 保存设备缓存_______________________
        /// <summary>
        /// 保存设备缓存(考虑有的设备用的是200端点,所以这里最好不用设备对象作为参数)
        /// </summary>
        /// <param name="deviceMac">设备mac</param>
        /// <param name="deviceEpoint">设备Epoint</param>
        public void SaveDeviceMemmoryData(string deviceMac, int deviceEpoint)
        {
            string mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(deviceMac, deviceEpoint);
            if (this.modelData.dicDeviceTemplateData.ContainsKey(mainkey) == false)
            {
                return;
            }
            //保存路径
            string saveFile = HdlFileNameResourse.LocalTemplateDirectory;
            saveFile = System.IO.Path.Combine(saveFile, "Device_" + mainkey);
            var listData = this.modelData.dicDeviceTemplateData[mainkey];
            if (listData.Count == 0)
            {
                //删除掉这个文件
                HdlFileLogic.Current.DeleteFile(saveFile);
                return;
            }
            //写入文件的内容
            string writeText = string.Empty;
            foreach (var data in listData)
            {
                writeText += "===>" + (int)data.DataSaveDiv + "\r\n";
                string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                writeText += dataInfo + "\r\n";
            }
            //写入内容
            HdlFileLogic.Current.SaveTextToFile(saveFile, writeText);
        }
        #endregion
        #region ■ 获取需要升级的设备对象_____________
        /// <summary>
        /// 获取需要升级的设备对象,按网关分组(key:网关ID value的key:本地Ota设备的Mac value:升级固件地址)
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, Dictionary<string, string>> GetNeedToUpdateDevice()
        {
            var dicGatewayDevice = new Dictionary<string, Dictionary<string, string>>();
            //循环设备匹配的模板
            foreach (var localMac in this.modelData.dicDeviceTemplateSelect.Keys)
            {
                string tempMac = this.modelData.dicDeviceTemplateSelect[localMac];
                if (this.modelData.dicDeviceInfo.ContainsKey(tempMac) == false)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                //取本地Ota设备对象
                var localOta = HdlDeviceCommonLogic.Current.GetOTADevice(localMac);
                if (localOta == null)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                foreach (var tempDevice in this.modelData.dicDeviceInfo[tempMac])
                {
                    //取模板Ota设备对象
                    if (tempDevice is OTADevice)
                    {
                        //只要两者的固件版本不一样,并且本地有这个升级固件,则都需要升级
                        if (localOta.ImgVersion != tempDevice.ImgVersion
                            && HdlFirmwareUpdateLogic.Current.IsEsixtDeviceFirmwareFile((OTADevice)tempDevice) == true)
                        {
                            //按网关分组
                            if (dicGatewayDevice.ContainsKey(localOta.CurrentGateWayId) == false)
                            {
                                dicGatewayDevice[localOta.CurrentGateWayId] = new Dictionary<string, string>();
                            }
                            var dicDevice = dicGatewayDevice[localOta.CurrentGateWayId];
                            dicDevice[localMac] = HdlFirmwareUpdateLogic.Current.GetDeviceFirmwareFile((OTADevice)tempDevice);
                        }
                        break;
                    }
                }
            }
            return dicGatewayDevice;
        }
        /// <summary>
        /// 获取需要升级的网关对象(key:本地网关的id value:升级固件地址,第一位是Linux,第二位是协调器,之后都是虚拟驱动)
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, List<GatewayNeedUpdateInfo>> GetNeedToUpdateGateway()
        {
            var dicGateway = new Dictionary<string, List<GatewayNeedUpdateInfo>>();
            //循环网关匹配的模板
            foreach (var localId in this.modelData.dicGatewayTemplateSelect.Keys)
            {
                string tempId = this.modelData.dicGatewayTemplateSelect[localId];
                if (this.modelData.dicGatewayInfo.ContainsKey(tempId) == false)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                //取本地网关对象
                var localGateway = HdlGatewayLogic.Current.GetLocalGateway(localId);
                if (localGateway == null)
                {
                    //应该不会进来,即使进来,我也不知道为什么
                    continue;
                }
                var tempGateway = this.modelData.dicGatewayInfo[tempId];
                //初始化容器
                var listUpdateInfo = new List<GatewayNeedUpdateInfo>() { null, null };
                bool needUpdate = false;
                //Linux版本比较
                if (tempGateway.LinuxFirmwareVersion != localGateway.LinuxFirmwareVersion)
                {
                    //Linux升级固件文件全路径
                    string updateFile = HdlFirmwareUpdateLogic.Current.GetGatewayLinuxFirmwareFile(tempGateway);
                    if (System.IO.File.Exists(updateFile) == true)
                    {
                        //如果存在的话
                        var info = new GatewayNeedUpdateInfo();
                        info.Div = 1;
                        info.FullFileName = updateFile;
                        listUpdateInfo[0] = info;
                        needUpdate = true;
                    }
                }
                //协调器版本比较
                if (tempGateway.CoordinatorFirmwareVersion != localGateway.CoordinatorFirmwareVersion)
                {
                    //协调器升级固件文件全路径
                    string updateFile = HdlFirmwareUpdateLogic.Current.GetGatewayCoordinatorFirmwareFile(tempGateway);
                    if (System.IO.File.Exists(updateFile) == true)
                    {
                        //如果存在的话
                        var info = new GatewayNeedUpdateInfo();
                        info.Div = 2;
                        info.FullFileName = updateFile;
                        listUpdateInfo[1] = info;
                        needUpdate = true;
                    }
                }
                //虚拟驱动比较
                if (HdlGatewayLogic.Current.CheckGatewayHadDriveCode(localGateway) == true)
                {
                    foreach (var localCode in localGateway.DriveCodeList)
                    {
                        foreach (var tempCode in tempGateway.DriveCodeList)
                        {
                            //防止它放的顺序不样
                            if (localCode.DriveCode == tempCode.DriveCode && localCode.DriveFwVersion != tempCode.DriveFwVersion)
                            {
                                //虚拟驱动升级固件文件全路径
                                string updateFile = HdlFirmwareUpdateLogic.Current.GetGatewayDriveCodeFirmwareFile(tempCode);
                                if (System.IO.File.Exists(updateFile) == true)
                                {
                                    //如果存在的话
                                    var info = new GatewayNeedUpdateInfo();
                                    info.Div = 3;
                                    info.DriveCode = tempCode.DriveCode;
                                    info.FullFileName = updateFile;
                                    listUpdateInfo.Add(info);
                                    needUpdate = true;
                                }
                            }
                        }
                    }
                }
                if (listUpdateInfo.Count == 2)
                {
                    listUpdateInfo.Add(null);
                }
                //添加目标缓存
                if (needUpdate == true)
                {
                    dicGateway[localId] = listUpdateInfo;
                }
            }
            return dicGateway;
        }
        #endregion
        #region ■ 从模板文件中获取对象(外部调用)_____
        /// <summary>
        /// 从模板文件中,获取设备和网关对象
        /// </summary>
        /// <param name="fullFileName">模板文件的全路径</param>
        /// <param name="listDevice">ota设备列表</param>
        /// <param name="listGateway">网关列表</param>
        public void GetDeviceObjectFromTemplate(string fullFileName, ref List<OTADevice> listDevice, ref List<ZbGateway> listGateway)
        {
            var fileData = HdlFileLogic.Current.ReadFileTextContent(fullFileName);
            if (fileData == null)
            {
                return;
            }
            var deviceType = string.Empty;
            var strTempContentData = string.Empty;
            //根据换行符切分数据文本
            string[] arryData = fileData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string strData in arryData)
            {
                if (strData == "#START#")
                {
                    //无附加数据的【数据标题】
                    strTempContentData = string.Empty;
                    continue;
                }
                if (strData.StartsWith("#DeviceInfo START#") == true)
                {
                    //附加数据:设备对象类型
                    deviceType = strData.Substring(18);
                    strTempContentData = string.Empty;
                    continue;
                }
                try
                {
                    //设备对象
                    if (strData == "#DeviceInfo END#")
                    {
                        //反序列化设备
                        if (deviceType == "OtaDevice" || deviceType == "OtaPanelDevice")
                        {
                            var device = Newtonsoft.Json.JsonConvert.DeserializeObject<OTADevice>(strTempContentData);
                            if (device != null)
                            {
                                listDevice.Add(device);
                            }
                        }
                        strTempContentData = string.Empty;
                        continue;
                    }
                    //网关对象数据
                    else if (strData == "#GatewayInfo END#")
                    {
                        //反序列化设备
                        var gateway = Newtonsoft.Json.JsonConvert.DeserializeObject<ZbGateway>(strTempContentData);
                        if (gateway != null)
                        {
                            listGateway.Add(gateway);
                        }
                        strTempContentData = string.Empty;
                        return;
                    }
                    strTempContentData += strData;
                }
                catch (Exception ex)
                {
                    HdlLogLogic.Current.WriteLog(ex, "模板bin文件出问题\r\n" + strTempContentData);
                    strTempContentData = string.Empty;
                }
            }
        }
        #endregion
        #region ■ 一般方法___________________________
        /// <summary>
        /// 复制模板bin文件到本地的模板文件夹里
        /// </summary>
        /// <param name="templateFileName">模板文件的名字(全住宅存放的模板)</param>
        public void CopyTemplateFileToLocalDirectory(string templateFileName)
        {
            string sourceFile = System.IO.Path.Combine(HdlFileNameResourse.AllResidenceTemplateDirectory, templateFileName);
            this.CopyTemplateFileToLocalDirectory2(sourceFile);
        }
        /// <summary>
        /// 复制模板bin文件到本地的模板文件夹里
        /// </summary>
        /// <param name="fullTemplateName">模板文件的全路径</param>
        public void CopyTemplateFileToLocalDirectory2(string fullTemplateName)
        {
            if (System.IO.File.Exists(fullTemplateName) == false)
            {
                return;
            }
            //保存的路径
            string targetFile = HdlFileNameResourse.LocalTemplateDirectory;
            targetFile = System.IO.Path.Combine(targetFile, TemplateFileName);
            try { System.IO.File.Copy(fullTemplateName, targetFile, true); }
            catch (Exception ex) { HdlLogLogic.Current.WriteLog(ex, "复制模板bin文件失败"); }
        }
        /// <summary>
        /// 删除本地全部的模板缓存文件
        /// </summary>
        public void DeleteAllLocalFile()
        {
            //获取这个路径下面全部的文件
            var listFile = HdlFileLogic.Current.GetFileFromDirectory(HdlFileNameResourse.LocalTemplateDirectory, false); ;
            foreach (var file in listFile)
            {
                HdlFileLogic.Current.DeleteFile(file);
            }
        }
        /// <summary>
        /// 获取模板中的设备数
        /// </summary>
        /// <returns></returns>
        public int GetTemplateDeviceCount()
        {
            return this.modelData.dicDeviceInfo.Count;
        }
        /// <summary>
        /// 检测设备模板数和当前设备选择的模板数是否一致
        /// </summary>
        /// <returns></returns>
        public bool CheckTemplateDeviceCountAndSelectCountIsEqual()
        {
            return this.modelData.dicDeviceInfo.Count == this.modelData.dicDeviceTemplateSelect.Count;
        }
        /// <summary>
        /// 获取文件里指定的内容
        /// </summary>
        /// <param name="fileContrnt">文件文本</param>
        /// <param name="startFlage">开始字符</param>
        /// <param name="endFlage">结束字符</param>
        /// <returns></returns>
        private string GetDataFromFileContent(string fileContrnt, string startFlage, string endFlage)
        {
            string[] arryValue = fileContrnt.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            string modelBaseInfo = string.Empty;
            bool getData = false;
            bool success = false;
            foreach (var strValue in arryValue)
            {
                //开始
                if (strValue == startFlage)
                {
                    getData = true;
                    //同一开始字符的东西很多
                    modelBaseInfo = string.Empty;
                    continue;
                }
                //结束
                if (strValue == endFlage)
                {
                    success = true;
                    break;
                }
                if (getData == true)
                {
                    modelBaseInfo += strValue;
                }
            }
            return success == true ? modelBaseInfo : string.Empty;
        }
        /// <summary>
        /// 获取模块ID
        /// </summary>
        /// <param name="deviceMac"></param>
        /// <returns></returns>
        private string GetDeviceModelId(string deviceMac)
        {
            var listDevice = HdlDeviceCommonLogic.Current.GetDevicesByMac(deviceMac);
            foreach (var device in listDevice)
            {
                if (device.ModelIdentifier != string.Empty)
                {
                    return device.ModelIdentifier;
                }
            }
            return string.Empty;
        }
        /// <summary>
        /// 获取设备保存的模板对象(考虑有的设备用的是200端点,所以这里最好不用设备对象作为参数)
        /// </summary>
        /// <param name="device"></param>
        /// <param name="saveEnum"></param>
        /// <returns></returns>
        public TemplateDeviceDataCommon GetDeviceModelDataClass(string deviceMac, int deviceEpoint, ModelDeviceSaveEnum saveEnum, TemplateDeviceDataCommon newClass)
        {
            string mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(deviceMac, deviceEpoint);
            //创建存储空间
            if (this.modelData.dicDeviceTemplateData.ContainsKey(mainkey) == false)
            {
                this.modelData.dicDeviceTemplateData[mainkey] = new List<TemplateDeviceDataCommon>();
            }
            foreach (var data in this.modelData.dicDeviceTemplateData[mainkey])
            {
                //如果是已经存在了的
                if (data.DataSaveDiv == saveEnum)
                {
                    return data;
                }
            }
            //新建一个新的对象
            newClass.DataSaveDiv = saveEnum;
            newClass.DeviceEpoint = deviceEpoint;
            newClass.DeviceMac = deviceMac;
            //默认创建一个索引位
            newClass.ListReceiveResult.Add(string.Empty);
            newClass.ListReceiveTopic.Add(string.Empty);
            newClass.ListSendTopic.Add(string.Empty);
            this.modelData.dicDeviceTemplateData[mainkey].Add(newClass);
            return newClass;
        }
        /// <summary>
        /// 显示信息框
        /// </summary>
        /// <param name="msgType">信息类型</param>
        /// <param name="msg">信息</param>
        /// <param name="action">单击确认后执行的回调函数</param>
        /// <param name="buttonText">按钮的文本</param>
        private void ShowMassage(ShowMsgType msgType, string msg, Action action = null, string buttonText = null)
        {
            HdlMessageLogic.Current.ShowMassage(msgType, msg, action, buttonText);
        }
        #endregion
    }
}