using Shared.Common; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Net; using System.Text; using ZigBee.Device; namespace Shared.Phone { /// /// 分享的逻辑 /// public class HdlShardLogic { #region ■ 变量声明___________________________ /// /// 分享的逻辑 /// private static HdlShardLogic m_Current = null; /// /// 分享的逻辑 /// public static HdlShardLogic Current { get { if (m_Current == null) { m_Current = new HdlShardLogic(); } return m_Current; } set { m_Current = value; } } /// /// 分享压缩文件的名字 /// private const string SHARED_BIN_FILE = "SharedData.bin"; /// /// 分享的设备对象 /// private Dictionary DicDevices = null; /// /// 分享的场景对象 /// private Dictionary DicScenes = new Dictionary(); /// /// 分享的房间信息 /// private Dictionary DicRooms = new Dictionary(); /// /// 分享的楼层信息 /// private Dictionary DicFloor = new Dictionary(); /// /// 分享的文件的主键(key:文件名,value:主键) /// private Dictionary DicShardKeys = new Dictionary(); #endregion #region ■ 同步服务器的分享内容_______________ /// /// 同步服务器的分享内容(里面只负责把东西存入本地) /// public bool SynchronizeDbSharedContent() { if (HdlUserCenterResourse.ResidenceOption.AuthorityNo != 3) { //只有成员才有这个概念 return true; } //获取主人分享给成员的文件列表 var listShardInfo = this.GetShardFileListFromDb(Config.Instance.Guid); if (listShardInfo == null) { return false; } //主键 var dicAddMark = new Dictionary(); //检测取消了共享的操作使用 var dicShardFile = new Dictionary(); //获取前回共享文件的更新日期(keys:文件名字,value:更新日期) var dicUpdateTime = this.GetAllShardFileAgoUpdateTime(); //先看看这分享数据里面有什么鬼 foreach (var info in listShardInfo) { //如果是压缩文件,需要特殊处理 if (info.FileName == SHARED_BIN_FILE) { //判断Bin文件的更新日期 if (dicUpdateTime.ContainsKey(info.FileName) == false || info.CreateTime.CompareTo(dicUpdateTime[info.FileName]) > 0) { dicAddMark[info.Id] = info.FileName; //更新日更新 dicUpdateTime[info.FileName] = info.CreateTime; } continue; } dicShardFile[info.FileName] = info.Id; //如果本地没有,或者更新日期大于前回更新日期的时候 if (Global.IsExistsByHomeId(info.FileName) == false || dicUpdateTime.ContainsKey(info.FileName) == false || info.CreateTime.CompareTo(dicUpdateTime[info.FileName]) > 0) { dicAddMark[info.Id] = info.FileName; //更新日更新 dicUpdateTime[info.FileName] = info.CreateTime; } } //不要忘记初始化这个东西 this.DicDevices = new Dictionary(); //从云端获取下来文件 if (dicAddMark.Count > 0) { //开启进度条 共享数据同步中 ProgressFormBar.Current.Start(); ProgressFormBar.Current.SetMsg(Language.StringByID(R.MyInternationalizationString.uShardDataIsSynchronizing)); //将分享的数据存入本地(获取的是本地没有的) var listDbFile = this.SetShardFileToLocation(dicAddMark); if (listDbFile == null) { //关闭 ProgressFormBar.Current.Close(); return false; } //转移文件 foreach (string fileName in listDbFile) { //不是bin文件,则移动文件到本地 if (fileName != SHARED_BIN_FILE) { var oldPath = Path.Combine(HdlFileNameResourse.DownLoadShardDirectory, fileName); var newPath = Path.Combine(Config.Instance.FullPath, fileName); HdlFileLogic.Current.CopyFile(oldPath, newPath); } else { //读取bin文件的内容 var dataContent = this.GetShardFileContent(fileName); if (dataContent != null) { //解析bin文件 this.AdjustBinFileContent(Encoding.UTF8.GetString(dataContent)); } } } } //同步服务器的取消了的分享内容 return this.SynchronizeSharedCancelContent(dicShardFile, dicUpdateTime); } /// /// 同步服务器的取消了的分享内容 /// /// 云端上面分享的文件,key:文件名 value:主键 /// 分享文件的更新时间,key:文件名 value:时间 /// private bool SynchronizeSharedCancelContent(Dictionary dicShardFile, Dictionary dicUpdateTime) { //开启进度条 共享数据同步中 ProgressFormBar.Current.Start(); ProgressFormBar.Current.SetMsg(Language.StringByID(R.MyInternationalizationString.uShardDataIsSynchronizing)); //重新设置楼层 Config.Instance.Home.FloorDics.Clear(); foreach (var key in this.DicFloor.Keys) { Config.Instance.Home.FloorDics[key] = this.DicFloor[key]; } //获取分享的设备的文件名 var listShardDeviceFile = new HashSet(); foreach (var device in this.DicDevices.Values) { listShardDeviceFile.Add(device.FilePath); } //住宅的根目录 var localPath = Config.Instance.FullPath; //然后检测本地的文件 var listLocalFile = HdlFileLogic.Current.GetRootPathListFile(); foreach (string fileName in listLocalFile) { try { if (dicShardFile.ContainsKey(fileName) == true) { //本地的这个文件还分享着,没有问题,或许应该只有分享图片 continue; } //检测本地设备文件,是否存在已经取消了共享了的 if (fileName.StartsWith("Device_") == true) { //判断是否还在分享的bin文件里面 if (listShardDeviceFile.Contains(fileName) == false) { //删除掉这个设备文件 HdlFileLogic.Current.DeleteFile(Path.Combine(localPath, fileName)); dicUpdateTime.Remove(fileName); } } //检测本地房间文件,是否存在已经取消了共享了的 else if (fileName.StartsWith("Room_") == true) { var fullFile = Path.Combine(localPath, fileName); var roomData = HdlFileLogic.Current.ReadFileTextContent(fullFile); if (roomData != null) { var nowRoom = Newtonsoft.Json.JsonConvert.DeserializeObject(roomData); if (nowRoom.IsSharedRoom == false || this.DicRooms.ContainsKey(nowRoom.Id) == true) { //这个房间是他自己创建的,或者还在分享着 continue; } //删除掉这个房间文件 HdlFileLogic.Current.DeleteFile(fullFile); dicUpdateTime.Remove(fileName); } } //检测本地场景文件,是否存在已经取消了共享了的 else if (fileName.StartsWith("Scene_") == true) { var fullFile = Path.Combine(localPath, fileName); var sceneData = HdlFileLogic.Current.ReadFileTextContent(fullFile); var nowScene = Newtonsoft.Json.JsonConvert.DeserializeObject(sceneData); if (nowScene != null) { if (nowScene.IsSharedScene == false || this.DicScenes.ContainsKey(nowScene.Id) == true) { //这个场景是他自己创建的,或者还在分享着 continue; } //删除掉这个场景文件 HdlFileLogic.Current.DeleteFile(fullFile); dicUpdateTime.Remove(fileName); } } } catch { } } //保存楼层数据 Config.Instance.Home.Save(false); //网关文件非合法性是刷新设备列表的函数里面实现 //保存全部分享文件的更新日期 this.SaveAllShardFileAgoUpdateTime(dicUpdateTime); //关闭 ProgressFormBar.Current.Close(); //释放缓存 this.Dispone(); return true; } #endregion #region ■ 同步内容更新时间___________________ /// /// 获取全部分享文件的前回更新日期 /// /// private Dictionary GetAllShardFileAgoUpdateTime() { var dicTime = new Dictionary(); var data = HdlFileLogic.Current.ReadFileByteContent(HdlFileNameResourse.ShardFileUpdateTimeFile); if (data == null) { //目标文件不存在 return dicTime; } dicTime = Newtonsoft.Json.JsonConvert.DeserializeObject>(System.Text.Encoding.UTF8.GetString(data)); return dicTime; } /// /// 保存全部分享文件的更新日期 /// /// private void SaveAllShardFileAgoUpdateTime(Dictionary dicTime) { HdlFileLogic.Current.SaveFileContent(HdlFileNameResourse.ShardFileUpdateTimeFile, dicTime); } #endregion #region ■ 获取分享数据列表___________________ /// /// 从云端获取分享的文件列表 /// /// 账号的id,成员登陆的话,直接传账号密码登陆之后,云端返回的那个id /// private List GetShardFileListFromDb(string i_childAccountId) { //获取主人分享给成员的文件列表 var pra = new { homeId = Config.Instance.HomeId, childAccountId = i_childAccountId }; var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/home/share/findAll", RestSharp.Method.POST, pra, null, null, CheckMode.A账号权限); //检测状态码 if (HdlCheckLogic.Current.CheckNetCode(result, ShowNetCodeMode.YES) == false) { return null; } var listShardInfo = Newtonsoft.Json.JsonConvert.DeserializeObject>(result.Data.ToString()); return listShardInfo; } /// /// 将分享的数据存入本地,返回的是文件名字(异常时返回null) /// /// key:文件的主键 value:文件名称 /// private List SetShardFileToLocation(Dictionary dicFileKeys) { if (dicFileKeys.Count == 0) { return new List(); } //创建文件夹 string strDir = HdlFileNameResourse.DownLoadShardDirectory; HdlFileLogic.Current.CreateDirectory(strDir, true); int listMarkCount = dicFileKeys.Count; List listFile = new List(); //不允许按系统的返回键 Config.Instance.BackKeyCanClick = false; HdlUserCenterResourse.AccountOption.AppCanSignout = false; //计数 int nowCount = 0; foreach (var fileKey in dicFileKeys.Keys) { nowCount++; var pra = new { homeId = Config.Instance.Home.Id, homeShareId = fileKey }; var result = HdlHttpLogic.Current.RequestByteFromZigbeeHttps("home-wisdom/home/share/downOne", RestSharp.Method.POST, pra, null, null, CheckMode.A账号权限, true, 10); //检测状态码 if (result == null) { //允许按系统的返回键 Config.Instance.BackKeyCanClick = true; HdlUserCenterResourse.AccountOption.AppCanSignout = true; return null; } string shareName = dicFileKeys[fileKey]; //文件名字 listFile.Add(shareName); //保存到指定文件夹下 HdlFileLogic.Current.SaveByteToFile(System.IO.Path.Combine(strDir, shareName), result); //设置进度值 ProgressFormBar.Current.SetValue(nowCount, listMarkCount); } //允许按系统的返回键 Config.Instance.BackKeyCanClick = true; HdlUserCenterResourse.AccountOption.AppCanSignout = true; return listFile; } #endregion #region ■ 初始化成员分享数据_________________ /// /// 初始化成员共享列表然后保存到本地 /// /// 成员ID /// public bool InitMemberShardContentListAndSetToLocation(string i_ChildAccountId) { if (DicDevices != null) { //已经获取了,则不再获取 return true; } //正在获取分享数据 ProgressFormBar.Current.Start(); ProgressFormBar.Current.SetMsg(Language.StringByID(R.MyInternationalizationString.uShardContentGetting)); //从云端获取分享的文件列表 var listData = this.GetShardFileListFromDb(i_ChildAccountId); if (listData == null) { //关闭进度条 ProgressFormBar.Current.Close(); return false; } //分享的压缩文件的主键 string shardBinKey = string.Empty; foreach (var data in listData) { //如果是这个压缩文件 if (data.FileName == SHARED_BIN_FILE) { shardBinKey = data.Id; } //记录起它们的主键 this.DicShardKeys[data.FileName] = data.Id; } //下载压缩的bin文件,然后进行解析,其他文件不用理会 bool result = this.DownloadBinFileAndAdjust(shardBinKey); //关闭进度条 ProgressFormBar.Current.Close(); return result; } /// /// 下载压缩的bin文件,然后进行解析 /// /// 压缩文件的主键 /// private bool DownloadBinFileAndAdjust(string i_binFileId) { if (i_binFileId == string.Empty) { //不要忘记要初始化这个东西 this.DicDevices = new Dictionary(); return true; } var pra = new { homeId = Config.Instance.Home.Id, homeShareId = i_binFileId }; var result = HdlHttpLogic.Current.RequestByteFromZigbeeHttps("home-wisdom/home/share/downOne", RestSharp.Method.POST, pra, null, null, CheckMode.A账号权限, true, 10); //检测状态码 if (result == null) { return false; } //不要忘记要初始化这个东西 this.DicDevices = new Dictionary(); //直接飙到100% ProgressFormBar.Current.SetValue(1); var fileContent = Encoding.UTF8.GetString(result); //解析压缩的bin文件 this.AdjustBinFileContent(fileContent); return true; } /// /// 解析压缩的bin文件 /// /// private void AdjustBinFileContent(string i_content) { var deviceType = string.Empty; //根据换行符切分数据文本 string[] arryData = i_content.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); string strContentData = string.Empty; foreach (string strData in arryData) { if (strData == "#START#") { //无附加数据的【数据标题】 continue; } if (strData.StartsWith("#DeviceInfo START#") == true) { //附加数据:设备对象类型 deviceType = strData.Substring(18); continue; } //执行数据处理 try { //场景对象 if (strData == "#Scene END#") { var scene = Newtonsoft.Json.JsonConvert.DeserializeObject(strContentData); this.DicScenes[scene.Id] = scene; strContentData = string.Empty; continue; } //楼层对象 else if (strData == "#FloorInfo END#") { this.DicFloor = Newtonsoft.Json.JsonConvert.DeserializeObject>(strContentData); strContentData = string.Empty; continue; } //房间对象 else if (strData == "#RoomInfo END#") { var room = Newtonsoft.Json.JsonConvert.DeserializeObject(strContentData); this.DicRooms[room.Id] = room; strContentData = string.Empty; continue; } //设备对象 else if (strData == "#DeviceInfo END#") { //反序列化设备 CommonDevice device = null; if (HdlCheckLogic.Current.CheckIsNumber(deviceType) == true) { //数值型为新数据,直接转换 device = CommonDevice.CommonDeviceByByteString(Convert.ToInt32(deviceType), strContentData); } else { //字符串型为旧数据,需要特殊处理 var myType = (DeviceType)Enum.Parse(typeof(DeviceType), deviceType); device = CommonDevice.CommonDeviceByByteString((int)myType, strContentData); } if (device != null) { this.DicDevices[HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device)] = device; } strContentData = string.Empty; continue; } else { strContentData += strData; } } catch (Exception ex) { HdlLogLogic.Current.WriteLog(ex, "分享bin文件出问题\r\n" + strContentData); strContentData = string.Empty; } } } #endregion #region ■ 上传分享内容_______________________ /// /// 执行上传新的分享(设备和场景仅限同一个房间) /// /// 成员的ID /// 指定的房间 /// 选择上传的设备(仅限一个房间) /// 选择上传的场景(仅限一个房间,不要获取它里面的绑定列表) public bool UploadSharedContent(string i_ChildAccountId, Room i_nowRoom, List i_listDevice, List i_listScene) { if (i_listDevice.Count == 0 && i_listScene.Count == 0) { return true; } //打开进度条 ProgressBar.Show(); var listCheck = new HashSet(); //获取场景里面嵌套的子设备和子场景(这几个东西不加到房间) var listChirdDevice = new List(); var listChirdScene = new List(); foreach (var SceneTemp in i_listScene) { //从缓存获取场景的执行目标 this.GetSceneAdjustTargetListFromLocal(SceneTemp, listCheck, listChirdScene, listChirdDevice); } //克隆一个房间出来 var cloneRoom = HdlRoomLogic.Current.CloneRoomClass(i_nowRoom); if (this.DicRooms.ContainsKey(cloneRoom.Id) == true) { //把原来的的东西也复制过来 cloneRoom.ListDevice.AddRange(this.DicRooms[cloneRoom.Id].ListDevice); cloneRoom.ListDeviceMac.AddRange(this.DicRooms[cloneRoom.Id].ListDeviceMac); cloneRoom.ListSceneId.AddRange(this.DicRooms[cloneRoom.Id].ListSceneId); } else { //这里有点特殊,如果不存在的话,把真实设备的区域丢过去,因为只是主键而已 cloneRoom.ListDeviceMac.AddRange(i_nowRoom.ListDeviceMac); } //然后把场景和设备丢到这个克隆的对象里面去 foreach (var device in i_listDevice) { string mainKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device); if (cloneRoom.ListDevice.Contains(mainKey) == false) { //丢设备过去 cloneRoom.ListDevice.Add(mainKey); } } foreach (var secne in i_listScene) { if (cloneRoom.ListSceneId.Contains(secne.Id) == false) { //丢场景过去 cloneRoom.ListSceneId.Add(secne.Id); } } //获取需要上传的图片 var listUploadPic = this.GetUploadPictrueFile(new List { cloneRoom }, i_listScene, listChirdScene); //生成分享Bin文件内容 var binfFileContent = this.CreatShardBinContentOnAdd(new List { cloneRoom }, i_listDevice, i_listScene, listChirdDevice, listChirdScene); //设置最大值 ProgressBar.SetMaxValue(listUploadPic.Count + 1); //上传bin文件 var fileKey = this.DoUploadShardContent(i_ChildAccountId, SHARED_BIN_FILE, Encoding.UTF8.GetBytes(binfFileContent)); if (fileKey == null) { ProgressBar.Close(); return false; } ProgressBar.SetValue(1); //记录主键 this.DicShardKeys[SHARED_BIN_FILE] = fileKey; binfFileContent = null; //上传图片 foreach (var fileName in listUploadPic) { var byteData = HdlFileLogic.Current.ReadFileByteContent(Path.Combine(Config.Instance.FullPath, fileName)); if (byteData != null) { fileKey = this.DoUploadShardContent(i_ChildAccountId, fileName, byteData); if (fileKey == null) { ProgressBar.Close(); return false; } //记录主键 this.DicShardKeys[SHARED_BIN_FILE] = fileKey; } ProgressBar.SetValue(1); } //如果全部成功了的话,覆盖缓存 this.DicDevices.Clear(); this.DicScenes.Clear(); this.DicRooms.Clear(); this.DicFloor.Clear(); this.AdjustBinFileContent(binfFileContent); //删除已经不再分享的图片 this.DeleteNotShardPictrue(); ProgressBar.Close(); return true; } /// /// 执行上传新的分享房间(整个房间分享) /// /// 成员的ID /// 需要分享的房间 public bool UploadSharedRoom(string i_ChildAccountId, List i_listRoom) { //打开进度条 ProgressBar.Show(); //让设备和场景不重复的东西 var listCheck = new HashSet(); //克隆房间 var listCloneRoom = new List(); //添加的设备 var listDevice = new List(); //添加的场景 var listScene = new List(); foreach (var room in i_listRoom) { //克隆一个房间出来 var cloneRoom = HdlRoomLogic.Current.CloneRoomClass(room); if (this.DicRooms.ContainsKey(cloneRoom.Id) == true) { //把原来的的东西也复制过来 cloneRoom.ListDevice.AddRange(this.DicRooms[cloneRoom.Id].ListDevice); cloneRoom.ListDeviceMac.AddRange(this.DicRooms[cloneRoom.Id].ListDeviceMac); cloneRoom.ListSceneId.AddRange(this.DicRooms[cloneRoom.Id].ListSceneId); } else { //这里有点特殊,如果不存在的话,把真实设备的区域丢过去,因为只是主键而已 cloneRoom.ListDeviceMac.AddRange(room.ListDeviceMac); } listCloneRoom.Add(cloneRoom); //获取设备对象 foreach (var mainkey in cloneRoom.ListDevice) { var device = HdlDeviceCommonLogic.Current.GetDevice(mainkey); if (device != null) { listDevice.Add(device); } listCheck.Add(mainkey); } //获取场景对象 foreach (var sceneId in cloneRoom.ListSceneId) { var scene = HdlSceneLogic.Current.GetSceneUIBySceneId(sceneId); if (scene != null) { listScene.Add(scene); } listCheck.Add(sceneId.ToString()); //从缓存获取场景的执行目标 this.GetSceneAdjustTargetListFromLocal(scene, listCheck, listScene, listDevice); } } //获取需要上传的图片 var listUploadPic = this.GetUploadPictrueFile(listCloneRoom, listScene, new List()); //生成分享Bin文件内容 var binfFileContent = this.CreatShardBinContentOnAdd(listCloneRoom, listDevice, listScene, new List(), new List()); //设置最大值 ProgressBar.SetMaxValue(listUploadPic.Count + 1); //上传bin文件 var fileKey = this.DoUploadShardContent(i_ChildAccountId, SHARED_BIN_FILE, Encoding.UTF8.GetBytes(binfFileContent)); if (fileKey == null) { ProgressBar.Close(); return false; } ProgressBar.SetValue(1); //记录主键 this.DicShardKeys[SHARED_BIN_FILE] = fileKey; binfFileContent = null; //上传图片 foreach (var fileName in listUploadPic) { var byteData = HdlFileLogic.Current.ReadFileByteContent(Path.Combine(Config.Instance.FullPath, fileName)); if (byteData != null) { fileKey = this.DoUploadShardContent(i_ChildAccountId, fileName, byteData); if (fileKey == null) { ProgressBar.Close(); return false; } //记录主键 this.DicShardKeys[SHARED_BIN_FILE] = fileKey; } ProgressBar.SetValue(1); } //如果全部成功了的话,覆盖缓存 this.DicDevices.Clear(); this.DicScenes.Clear(); this.DicRooms.Clear(); this.DicFloor.Clear(); this.AdjustBinFileContent(binfFileContent); //删除已经不再分享的图片 this.DeleteNotShardPictrue(); ProgressBar.Close(); return true; } /// /// 删除已经不再分享的图片(不用管返回值,即使失败也没事) /// private void DeleteNotShardPictrue() { var listPictrue = new List(); foreach (var room in this.DicRooms.Values) { if (room.BackgroundImageType != 0) { //房间图片 listPictrue.Add(room.BackgroundImage); } } foreach (var scene in this.DicScenes.Values) { if (scene.IconPathType != 0) { //场景图片 listPictrue.Add(scene.IconPath); } } var listDeleteFile = new List(); foreach (var fileName in this.DicShardKeys.Keys) { //如果是房间或者场景的图片 if (fileName.StartsWith("RoomIcon_") == true || fileName.StartsWith("SceneIcon_") == true) { if (listPictrue.Contains(fileName) == false) { //这个图片变更了,需要删除掉 listDeleteFile.Add(fileName); } } } //删除图片 this.DoDeleteSharedContent(listDeleteFile, ShowNetCodeMode.No); } /// /// 上传分享内容(返回主键) /// /// 子账号的主键 /// 文件名字 /// 文件内容 /// private string DoUploadShardContent(string i_childAccountId, string i_fileName, byte[] i_content) { var dicQuery = new Dictionary(); dicQuery["homeId"] = Config.Instance.Home.Id; dicQuery["childAccountId"] = i_childAccountId; dicQuery["fileName"] = i_fileName; var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/home/share/add", RestSharp.Method.POST, i_content, dicQuery, null, CheckMode.A账号权限, true, 10); //检测状态码 if (HdlCheckLogic.Current.CheckNetCode(result, ShowNetCodeMode.YES) == false) { return null; } var info = Newtonsoft.Json.JsonConvert.DeserializeObject(result.Data.ToString()); return info.Id; } #endregion #region ■ 上传分享内容辅助方法_______________ /// /// 从本地获取场景里面的执行目标列表 /// /// 场景 /// 重复检测用 /// 添加分享的场景列表 /// 添加分享的设备列表 /// private void GetSceneAdjustTargetListFromLocal(SceneUI scene, HashSet listCheck, List listSceneUI, List listDevice) { foreach (var data in scene.AdjustTargetList) { //设备 if (data.Type == 0) { string mainKeys = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(data.DeviceAddr, data.Epoint); if (listCheck.Contains(mainKeys) == true) { //不重复添加 continue; } listCheck.Add(mainKeys); var device = HdlDeviceCommonLogic.Current.GetDevice(data.DeviceAddr, data.Epoint); if (device != null) { listDevice.Add(device); } } //场景 else if (data.Type == 1) { string mainKeys = data.ElseScenesId.ToString(); if (listCheck.Contains(mainKeys) == true) { //不重复添加 continue; } listCheck.Add(mainKeys); //获取场景对象 var sceneUi = HdlSceneLogic.Current.GetSceneUIBySceneId(data.ElseScenesId); if (sceneUi != null) { listSceneUI.Add(sceneUi); //递归获取执行目标 this.GetSceneAdjustTargetListFromLocal(sceneUi, listCheck, listSceneUI, listDevice); } } } } /// /// 获取需要上传的图片名字 /// /// 房间对象 /// 场景对象 /// 场景对象 /// private List GetUploadPictrueFile(List i_listRoom, List i_listScene, List i_listChirdScene) { var listPic = new List(); foreach (var room in i_listRoom) { if (room.BackgroundImageType != 0 && this.DicShardKeys.ContainsKey(room.BackgroundImage) == false) { //自定义图片 listPic.Add(room.BackgroundImage); } } foreach (var scene in i_listScene) { if (scene.IconPathType != 0 && this.DicShardKeys.ContainsKey(scene.IconPath) == false) { //自定义图片 listPic.Add(scene.IconPath); } } foreach (var scene in i_listChirdScene) { if (scene.IconPathType != 0 && this.DicShardKeys.ContainsKey(scene.IconPath) == false) { //自定义图片 listPic.Add(scene.IconPath); } } return listPic; } #endregion #region ■ 删除分享内容_______________________ /// /// 移除指定分享内容(设备和场景仅限同一个房间) /// /// 成员ID /// 指定的房间 /// 选择上传的设备(仅限一个房间) /// 选择上传的场景(仅限一个房间,不要获取它里面的绑定列表) /// public bool DeleteSharedContent(string i_ChildAccountId, Room i_nowRoom, List i_listDevice, List i_listScene) { //克隆一个房间出来 var cloneRoom = HdlRoomLogic.Current.CloneRoomClass(i_nowRoom); if (this.DicRooms.ContainsKey(cloneRoom.Id) == true) { //把原来的的东西也复制过来 cloneRoom.ListDevice.AddRange(this.DicRooms[cloneRoom.Id].ListDevice); cloneRoom.ListDeviceMac.AddRange(this.DicRooms[cloneRoom.Id].ListDeviceMac); cloneRoom.ListSceneId.AddRange(this.DicRooms[cloneRoom.Id].ListSceneId); } //让设备和场景不重复添加的东西 var listCheck = new HashSet(); //然后把场景和设备从这个克隆的对象里面移除掉(真实物理设备的房间不用理) foreach (var device in i_listDevice) { string mainKey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device); cloneRoom.ListDevice.Remove(mainKey); listCheck.Add(mainKey); } foreach (var secne in i_listScene) { cloneRoom.ListSceneId.Remove(secne.Id); listCheck.Add(secne.Id.ToString()); } //如果都移除完的话,则直接走删除分享房间的方法 if (cloneRoom.ListDevice.Count == 0 && cloneRoom.ListSceneId.Count == 0) { //执行整个房间删除的方法 return this.DeleteSharedRoom(i_ChildAccountId, new List { i_nowRoom }); } //获取场景里面嵌套的子设备和子场景 foreach (var sceneTemp in i_listScene) { //从缓存获取场景的执行目标 this.GetSceneAdjustTargetListFromShard(sceneTemp, listCheck, i_listScene, i_listDevice); } //在删除一个房间中的一些设备的模式下,检测设备和场景是否能够删除(有可能它还在别的房间或者场景当中) var listDelDevice = new List(); var listDelScene = new List(); this.CheckDeviceAndSceneCanDeleteOnDeleteSome(i_listDevice, i_listScene, ref listDelDevice, ref listDelScene, cloneRoom); //生成分享Bin文件内容(这里不用删除房间) var binfFileContent = this.CreatShardBinContentOnDelete(new List(), listDelDevice, listDelScene); //上传bin文件 var fileKey = this.DoUploadShardContent(i_ChildAccountId, SHARED_BIN_FILE, Encoding.UTF8.GetBytes(binfFileContent)); if (fileKey == null) { ProgressBar.Close(); return false; } ProgressBar.SetValue(1); //记录主键 this.DicShardKeys[SHARED_BIN_FILE] = fileKey; binfFileContent = null; //如果全部成功了的话,覆盖缓存 this.DicDevices.Clear(); this.DicScenes.Clear(); this.DicRooms.Clear(); this.DicFloor.Clear(); this.AdjustBinFileContent(binfFileContent); //删除已经不再分享的图片 this.DeleteNotShardPictrue(); ProgressBar.Close(); return true; } /// /// 移除指定分享内容(整个房间删除) /// /// 成员ID /// 需要整个删除的房间 /// public bool DeleteSharedRoom(string i_ChildAccountId, List i_listRoom) { //打开进度条 ProgressBar.Show(); //设置最大值 ProgressBar.SetMaxValue(1); //获取删除房间的全部全部设备和场景 var listDevice = new List(); var listScene = new List(); this.GetDeleteRoomAllDeviceAndScene(i_listRoom, ref listDevice, ref listScene); //删除的房间ID var listDeleteRoom = new List(); foreach (var room in i_listRoom) { //判断场景和设备是否能删除时使用 listDeleteRoom.Add(room.Id); } //在删除整个房间的模式下,检测设备和场景是否能够删除(有可能它还在别的房间或者场景当中) var listDelDevice = new List(); var listDelScene = new List(); this.CheckDeviceAndSceneCanDeleteOnDeleteRoom(listDevice, listScene, ref listDelDevice, ref listDelScene, listDeleteRoom); //生成分享Bin文件内容 var binfFileContent = this.CreatShardBinContentOnDelete(i_listRoom, listDelDevice, listDelScene); //上传bin文件 var fileKey = this.DoUploadShardContent(i_ChildAccountId, SHARED_BIN_FILE, Encoding.UTF8.GetBytes(binfFileContent)); if (fileKey == null) { ProgressBar.Close(); return false; } ProgressBar.SetValue(1); //记录主键 this.DicShardKeys[SHARED_BIN_FILE] = fileKey; binfFileContent = null; //如果全部成功了的话,覆盖缓存 this.DicDevices.Clear(); this.DicScenes.Clear(); this.DicRooms.Clear(); this.DicFloor.Clear(); this.AdjustBinFileContent(binfFileContent); //删除已经不再分享的图片 this.DeleteNotShardPictrue(); ProgressBar.Close(); return true; } /// /// 执行移除分享数据 /// /// 删除的文件 /// 失败时是否显示tip消息 /// private bool DoDeleteSharedContent(List listDelFile, ShowNetCodeMode mode = ShowNetCodeMode.YES) { if (listDelFile.Count == 0) { return true; } foreach (var fileName in listDelFile) { if (this.DicShardKeys.ContainsKey(fileName) == false) { //我也不知道为什么会找不到主键 continue; } var pra = new { homeId = Config.Instance.Home.Id, homeShareId = this.DicShardKeys[fileName] }; //执行删除 var result = HdlHttpLogic.Current.RequestResponseFromZigbeeHttps("home-wisdom/home/share/delete", RestSharp.Method.POST, pra, null, null, CheckMode.A账号权限); //检测状态码 if (HdlCheckLogic.Current.CheckNetCode(result, mode) == false) { return false; } //移除缓存 this.DicShardKeys.Remove(fileName); } return true; } #endregion #region ■ 删除分享内容辅助方法_______________ /// /// 获取删除房间的全部全部设备和场景 /// /// 删除的房间 /// 全部设备(返回值) /// 全部场景(返回值) private void GetDeleteRoomAllDeviceAndScene(List i_listRoom, ref List listDevice, ref List listScene) { var listCheck = new HashSet(); foreach (var room in i_listRoom) { //获取设备 foreach (var mainkey in room.ListDevice) { if (listCheck.Contains(mainkey) == true) { continue; } listCheck.Add(mainkey); //分享数据里面有才添加 if (this.DicDevices.ContainsKey(mainkey) == true) { listDevice.Add(this.DicDevices[mainkey]); } } //然后再获取场景 foreach (var sceneId in room.ListSceneId) { if (listCheck.Contains(sceneId.ToString()) == true) { continue; } listCheck.Add(sceneId.ToString()); //分享数据里面有才添加 if (this.DicScenes.ContainsKey(sceneId) == true) { var sceneTemp = this.DicScenes[sceneId]; listScene.Add(sceneTemp); //获取场景里面嵌套的子设备和子场景 this.GetSceneAdjustTargetListFromShard(sceneTemp, listCheck, listScene, listDevice); } } } } /// /// 在删除整个房间的模式下,检测设备和场景是否能够删除(有可能它还在别的房间或者场景当中) /// /// 理论上要删除的设备 /// 理论上要删除的场景 /// 真实能够删除的设备(返回值) /// 真实能够删除的场景(返回值) /// 删除的房间 private void CheckDeviceAndSceneCanDeleteOnDeleteRoom(List i_listDevice, List i_listScene, ref List listDeleteDevice, ref List listDeleteScene, List i_listNotCheckRoom) { //注意:这个函数和下面的CheckDeviceAndSceneCanDeleteOnDeleteSome有本质区别 //这个只是完全删除一个房间内的设备或者场景,因此只需要去判断删除以外的就可以了 //获取理论上需要删除的场景ID var listSceneId = new List(); foreach (var scene in i_listScene) { listSceneId.Add(scene.Id); } var listShardDevice = new HashSet(); var listShardScene = new HashSet(); //获取除了理论上需要删除的场景之外,目前还分享的场景的执行目标里面的设备 foreach (var scene in this.DicScenes.Values) { //这个是要删除的场景 if (listSceneId.Contains(scene.Id) == true) { continue; } foreach (var data in scene.AdjustTargetList) { //设备 if (data.Type == 0) { var mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(data.DeviceAddr, data.Epoint); if (listShardDevice.Contains(mainkey) == false) { listShardDevice.Add(mainkey); } } //子场景 else if (data.Type == 1) { if (listShardScene.Contains(data.ElseScenesId) == false) { listShardScene.Add(data.ElseScenesId); } } } } //获取除了理论上需要删除的房间之外,目前还分享的设备 foreach (var room in this.DicRooms.Values) { //这个是要删除的房间 if (i_listNotCheckRoom.Contains(room.Id) == true) { continue; } foreach (var mainkey in room.ListDevice) { if (listShardDevice.Contains(mainkey) == false) { listShardDevice.Add(mainkey); } } foreach (var sceneId in room.ListSceneId) { if (listShardScene.Contains(sceneId) == false) { listShardScene.Add(sceneId); } } } //判断实际能够删除的设备 foreach (var device in i_listDevice) { var mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device); if (listShardDevice.Contains(mainkey) == false) { //这个设备已经不在分享 listDeleteDevice.Add(device); } } //判断实际能够删除的场景 foreach (var scene in i_listScene) { if (listShardScene.Contains(scene.Id) == false) { //这个场景已经不在分享 listDeleteScene.Add(scene); } } } /// /// 在删除一个房间中的一些设备的模式下,检测设备和场景是否能够删除(有可能它还在别的房间或者场景当中) /// /// 理论上要删除的设备 /// 理论上要删除的场景 /// 真实能够删除的设备(返回值) /// 真实能够删除的场景(返回值) /// 当前房间(克隆) private void CheckDeviceAndSceneCanDeleteOnDeleteSome(List i_listDevice, List i_listScene, ref List listDeleteDevice, ref List listDeleteScene, Room i_nowCloneRoom) { //注意:这个函数和上面的CheckDeviceAndSceneCanDeleteOnDeleteRoom有本质区别 //这个只是删除一个房间内的部分设备或者场景,因此它有可能自身就嵌套着要删除的设备或者场景 //先获取目前还在分享的设备和场景 var listShardDevice = new HashSet(); var listShardScene = new HashSet(); foreach (var roomId in this.DicRooms.Keys) { //如果是当前克隆的房间,则用克隆的房间来处理,克隆的房间已经把理论上要删除的设备和场景都删除了 var room = i_nowCloneRoom.Id != roomId ? this.DicRooms[roomId] : i_nowCloneRoom; //还在分享的设备 foreach (var mainkey in room.ListDevice) { if (listShardDevice.Contains(mainkey) == false) { listShardDevice.Add(mainkey); } } //还在分享的场景 foreach (var sceneId in room.ListSceneId) { if (listShardScene.Contains(sceneId) == false) { listShardScene.Add(sceneId); } //从场景的执行目标当前获取 if (this.DicScenes.ContainsKey(sceneId) == true) { foreach (var data in this.DicScenes[sceneId].AdjustTargetList) { //子设备 if (data.Type == 0) { var mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(data.DeviceAddr, data.Epoint); if (listShardDevice.Contains(mainkey) == false) { listShardDevice.Add(mainkey); } } //子场景 else if (data.Type == 1) { if (listShardScene.Contains(data.ElseScenesId) == false) { listShardScene.Add(data.ElseScenesId); } } } } } } //判断实际能够删除的设备 foreach (var device in i_listDevice) { var mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device); if (listShardDevice.Contains(mainkey) == false) { //这个设备已经不在分享 listDeleteDevice.Add(device); } } //判断实际能够删除的场景 foreach (var scene in i_listScene) { if (listShardScene.Contains(scene.Id) == false) { //这个场景已经不在分享 listDeleteScene.Add(scene); } } } /// /// 从分享数据里面获取场景里面的执行目标列表 /// /// 场景 /// 重复检测用 /// 添加分享的场景列表 /// 添加分享的设备列表 /// private void GetSceneAdjustTargetListFromShard(SceneUI scene, HashSet listCheck, List listSceneUI, List listDevice) { foreach (var data in scene.AdjustTargetList) { //设备 if (data.Type == 0) { string mainKeys = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(data.DeviceAddr, data.Epoint); if (listCheck.Contains(mainKeys) == true) { //不重复添加 continue; } listCheck.Add(mainKeys); if (this.DicDevices.ContainsKey(mainKeys) == true) { listDevice.Add(this.DicDevices[mainKeys]); } } //场景 else if (data.Type == 1) { string mainKeys = data.ElseScenesId.ToString(); if (listCheck.Contains(mainKeys) == true) { //不重复添加 continue; } listCheck.Add(mainKeys); //获取场景对象 if (this.DicScenes.ContainsKey(data.ElseScenesId) == true) { var sceneUi = this.DicScenes[data.ElseScenesId]; listSceneUI.Add(sceneUi); //递归获取执行目标 this.GetSceneAdjustTargetListFromShard(sceneUi, listCheck, listSceneUI, listDevice); } } } } #endregion #region ■ 生成分享Bin文件内容________________ /// /// 生成分享Bin文件内容(新增模式) /// /// 新的房间对象集合(也就是变更了的房间) /// 这个是需要追加的分享设备 /// 这个是需要追加的分享场景 /// 这个是由场景的执行目标来的 /// 这个是由场景的执行目标来的 /// private string CreatShardBinContentOnAdd(List i_listNewRoom, List i_listDevice, List i_listScene, List i_listChirdDevice, List i_listChirdScene) { string writeText = string.Empty; //生成写入文件的【设备对象数据】 this.CreatWriteCommonDeviceData(i_listDevice, i_listChirdDevice, false, ref writeText); //生成写入文件的【场景数据】 this.CreatWriteSceneData(i_listScene, i_listChirdScene, false, ref writeText); //生成写入文件的【场景数据】 this.CrearWriteRoomData(i_listNewRoom, false, ref writeText); return writeText; } /// /// 生成分享Bin文件内容(删除模式) /// /// 要删除的房间 /// 这个是需要删除的分享设备 /// 这个是需要删除的分享场景 /// private string CreatShardBinContentOnDelete(List i_listDelRoom, List i_listDevice, List i_listScene) { string writeText = string.Empty; //生成写入文件的【设备对象数据】 this.CreatWriteCommonDeviceData(i_listDevice, new List(), true, ref writeText); //生成写入文件的【场景数据】 this.CreatWriteSceneData(i_listScene, new List(), true, ref writeText); //生成写入文件的【场景数据】 this.CrearWriteRoomData(i_listDelRoom, true, ref writeText); return writeText; } /// /// 生成写入文件的【设备对象数据】 /// /// private void CreatWriteCommonDeviceData(List i_listDevice, List i_listChirdDevice, bool i_isDel, ref string writeText) { //合并设备到一个新的对象当中 var dicNewDevice = this.MergeNewShardDevices(i_listDevice, i_listChirdDevice, i_isDel); var listCheck = new HashSet(); foreach (var device in dicNewDevice.Values) { //设备端点 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"; } } } } /// /// 生成写入文件的【场景数据】 /// /// 这个是需要追加的分享场景 /// 这个是由场景的执行目标来的 /// private void CreatWriteSceneData(List i_listScene, List i_listChirdScene, bool i_isDel, ref string writeText) { //合并场景到一个新的对象当中 var dicNewScene = this.MergeNewShardScenes(i_listScene, i_listChirdScene, i_isDel); foreach (var scene in dicNewScene.Values) { writeText += "#START#\r\n"; string dataInfo = Newtonsoft.Json.JsonConvert.SerializeObject(scene); writeText += dataInfo + "\r\n"; writeText += "#SceneTemplate END#\r\n\r\n"; } } /// /// 生成写入文件的【房间模板数据】 /// /// 新的房间对象集合(也就是变更了的房间) /// private void CrearWriteRoomData(List i_listNewRoom, bool i_isDel, ref string writeText) { var dicNewFloor = new Dictionary(); //合并分享的房间到一个新的对象中 var dicNewRoom = this.MergeNewShardRooms(i_listNewRoom, i_isDel); foreach (var room in dicNewRoom.Values) { writeText += "#START#\r\n"; string dataInfo2 = Newtonsoft.Json.JsonConvert.SerializeObject(room); writeText += dataInfo2 + "\r\n"; writeText += "#RoomInfo END#\r\n\r\n"; if (room.FloorId != string.Empty) { dicNewFloor[room.FloorId] = HdlResidenceLogic.Current.GetFloorNameById(room.FloorId); } } //楼层数据 writeText += "#START#\r\n"; string dataInfo1 = Newtonsoft.Json.JsonConvert.SerializeObject(dicNewFloor); writeText += dataInfo1 + "\r\n"; writeText += "#FloorInfo END#\r\n\r\n"; } #endregion #region ■ 生成分享Bin文件内容辅助方法________ /// /// 合并分享的设备到一个新的对象中 /// /// 这个是需要追加的分享设备 /// 这个是由场景的执行目标来的 /// 是否是删除分享模式 /// private Dictionary MergeNewShardDevices(List i_listDevice, List i_listChirdDevice, bool i_isDel) { var dicNewDevice = new Dictionary(); //先合并原来的 foreach (var key in this.DicDevices.Keys) { dicNewDevice[key] = this.DicDevices[key]; } //再合并新添加的 foreach (var device in i_listDevice) { string mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device); if (i_isDel == false) { //直接覆盖,没问题 dicNewDevice[mainkey] = device; } else { //删除模式 dicNewDevice.Remove(mainkey); } } foreach (var device in i_listChirdDevice) { string mainkey = HdlDeviceCommonLogic.Current.GetDeviceMainKeys(device); //直接覆盖,没问题 dicNewDevice[mainkey] = device; } return dicNewDevice; } /// /// 合并分享的场景到一个新的对象中 /// /// 这个是需要追加的分享场景 /// 这个是由场景的执行目标来的 /// 是否是删除分享模式 /// private Dictionary MergeNewShardScenes(List i_listScene, List i_listChirdScene, bool i_isDel) { var dicNewScene = new Dictionary(); //先合并原来的 foreach (var key in this.DicScenes.Keys) { dicNewScene[key] = this.DicScenes[key]; } //再合并新添加的 foreach (var scene in i_listScene) { if (i_isDel == false) { //直接覆盖,没问题 dicNewScene[scene.Id] = scene; } else { //删除模式 dicNewScene.Remove(scene.Id); } } foreach (var scene in i_listChirdScene) { //直接覆盖,没问题 dicNewScene[scene.Id] = scene; } return dicNewScene; } /// /// 合并分享的房间到一个新的对象中 /// /// 新的房间对象集合(也就是变更了的房间) /// 是否是删除分享模式 /// private Dictionary MergeNewShardRooms(List i_listNewRoom, bool i_isDel) { var dicNewRoom = new Dictionary(); //先合并原来的 foreach (var key in this.DicRooms.Keys) { dicNewRoom[key] = this.DicRooms[key]; } //再合并新添加的 foreach (var room in i_listNewRoom) { if (i_isDel == false) { //直接覆盖,没问题 dicNewRoom[room.Id] = room; } else { //删除模式 dicNewRoom.Remove(room.Id); } } return dicNewRoom; } #endregion #region ■ 获取分享缓存方法___________________ /// /// 从缓存当中获取分享的设备 /// /// 设备的主键 /// public CommonDevice GetShardDeviceFromMemory(string i_deviceKey) { if (this.DicDevices.ContainsKey(i_deviceKey) == true) { return this.DicDevices[i_deviceKey]; } return null; } /// /// 从缓存当中获取分享的场景 /// /// 场景ID /// public SceneUI GetShardSceneFromMemory(int i_sceneId) { if (this.DicScenes.ContainsKey(i_sceneId) == true) { return this.DicScenes[i_sceneId]; } return null; } /// /// 从缓存当中获取分享的房间 /// /// public Dictionary GetShardRoomFromMemory() { return this.DicRooms; } /// /// 从缓存当中获取分享的房间 /// /// 房间ID /// public Room GetShardRoomFromMemory(string i_roomId) { if (this.DicRooms.ContainsKey(i_roomId) == true) { return this.DicRooms[i_roomId]; } return null; } /// /// 从缓存当中获取分享的楼层 /// /// public Dictionary GetShardFloorFormMemory() { return this.DicFloor; } #endregion #region ■ 一般方法___________________________ /// /// 获取分享文件的内容 /// /// 文件名称(不是全路径) /// private byte[] GetShardFileContent(string fileName) { string fullName = System.IO.Path.Combine(HdlFileNameResourse.DownLoadShardDirectory, fileName); if (System.IO.File.Exists(fullName) == false) { return null; } var varByte = HdlFileLogic.Current.ReadFileByteContent(fullName); return varByte; } /// /// 清空共享缓存 /// public void Dispone() { this.DicDevices = null; this.DicScenes.Clear(); this.DicRooms.Clear(); this.DicShardKeys.Clear(); this.DicFloor.Clear(); //清空文件夹 string strDir = HdlFileNameResourse.DownLoadShardDirectory; HdlFileLogic.Current.CreateDirectory(strDir, true); m_Current = null; } #endregion #region ■ 结构体类___________________________ /// /// 接收分享数据 /// private class ReceiveShardInfoResult { /// /// 文件名字 /// public string FileName = string.Empty; /// /// 更新时间 /// public string CreateTime = string.Empty; /// /// 主键 /// public string Id = string.Empty; } #endregion } }