| | |
| | | 558=Someone is sitting |
| | | 559=Bind a third-party account |
| | | 560=Bound |
| | | 561=Original password |
| | | |
| | | |
| | | |
| | |
| | | 558=有人坐着 |
| | | 559=绑定第三方账号 |
| | | 560=已绑定 |
| | | 561=原密码 |
| | | |
| | | |
| | | |
| | |
| | | 558=Someone is sitting |
| | | 559=Bind a third-party account |
| | | 560=Bound |
| | | 561=Original password |
| | | |
| | | |
| | | 2532=Visitor Invitation Record |
| | |
| | | 558=Someone is sitting |
| | | 559=Bind a third-party account |
| | | 560=Bound |
| | | 561=Original password |
| | | |
| | | |
| | | 2532=Visitor Invitation Record |
| | |
| | | <AndroidAsset Include="Assets\Phone\FunctionIcon\Icon\HomeIcon\sensormegahealth.png" /> |
| | | <AndroidAsset Include="Assets\Phone\Public\Iot_agreement_icon.png" /> |
| | | <AndroidAsset Include="Assets\Phone\Public\LinkIotIcon.png" /> |
| | | <AndroidAsset Include="Assets\Phone\Public\IotCheckIcon.png" /> |
| | | <AndroidAsset Include="Assets\Phone\Public\IotCheckOnIcon.png" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <AndroidResource Include="Resources\values\colors.xml" /> |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.6.0" package="com.hdl.onpro" xmlns:tools="http://schemas.android.com/tools" android:versionCode="202208031"> |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.6.0" package="com.hdl.onpro" xmlns:tools="http://schemas.android.com/tools" android:versionCode="202208151"> |
| | | <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="29" /> |
| | | <!--友盟--> |
| | | <!--<uses-sdk android:minSdkVersion="8"></uses-sdk>--> |
| | |
| | | <Reference Include="Shared.IOS.HDLFVSDK"> |
| | | <HintPath>..\DLL\IOS\Shared.IOS.HDLFVSDK.dll</HintPath> |
| | | </Reference> |
| | | <Reference Include="HDL.Shared.IOS.ScanQRCode"> |
| | | <HintPath>..\DLL\IOS\HDL.Shared.IOS.ScanQRCode.dll</HintPath> |
| | | </Reference> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <PackageReference Include="Newtonsoft.Json"> |
| | |
| | | <key>UIStatusBarStyle</key> |
| | | <string>UIStatusBarStyleLightContent</string> |
| | | <key>CFBundleShortVersionString</key> |
| | | <string>1.5.902207251</string> |
| | | <string>1.6.002208151</string> |
| | | <key>CFBundleVersion</key> |
| | | <string>1.5.907251</string> |
| | | <string>1.6.008151</string> |
| | | <key>NSLocationWhenInUseUsageDescription</key> |
| | | <string>Use geographic location to provide services such as weather</string> |
| | | <key>NSAppleMusicUsageDescription</key> |
| | |
| | | 556=Someone is running |
| | | 557=Someone is standing |
| | | 558=Someone is sitting |
| | | 559=Bind a third-party account |
| | | 560=Bound |
| | | 561=Original password |
| | | |
| | | |
| | | |
| | |
| | | 556=有人在跑 |
| | | 557=有人站着 |
| | | 558=有人坐着 |
| | | 559=绑定第三方账号 |
| | | 560=已绑定 |
| | | 561=原密码 |
| | | |
| | | |
| | | |
| | |
| | | 556=Someone is running |
| | | 557=Someone is standing |
| | | 558=Someone is sitting |
| | | 559=Bind a third-party account |
| | | 560=Bound |
| | | 561=Original password |
| | | |
| | | |
| | | 2532=Visitor Invitation Record |
| | |
| | | 556=Someone is running |
| | | 557=Someone is standing |
| | | 558=Someone is sitting |
| | | 559=Bind a third-party account |
| | | 560=Bound |
| | | 561=Original password |
| | | |
| | | |
| | | 2532=Visitor Invitation Record |
| | | 2533=Visitor management |
| | |
| | | using HDL_ON_iOS; |
| | | using Shared; |
| | | using ZXing.Mobile; |
| | | |
| | | using HDL.Shared.IOS.ScanQRCode; |
| | | namespace HDL_ON |
| | | { |
| | | public class Scan |
| | |
| | | |
| | | } |
| | | |
| | | static MobileBarcodeScanner scanner; |
| | | public async void OpenScan(Action<string> action) |
| | | void ScanResult(string result) |
| | | { |
| | | string cancel = "取消"; |
| | | string flashText = ""; |
| | | string titleText = "二维码扫描"; |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | cancel = "Cancel"; |
| | | flashText = ""; |
| | | titleText = "Scan"; |
| | | } |
| | | |
| | | if (scanner == null) |
| | | { |
| | | var mZXingOverlayView = new ZXingOverlayView(cancel, flashText, titleText); |
| | | scanner = new MobileBarcodeScanner(AppDelegate.rootViewController) { FlashButtonText = flashText, TopText = titleText, BottomText = "", CancelButtonText = cancel }; |
| | | scanner.UseCustomOverlay = true; |
| | | |
| | | scanner.CustomOverlay = mZXingOverlayView; |
| | | var bOn = false; |
| | | mZXingOverlayView.OnCancel += () => |
| | | { |
| | | scanner?.Cancel(); |
| | | }; |
| | | |
| | | mZXingOverlayView.OnTorch += () => |
| | | { |
| | | bOn = !bOn; |
| | | scanner?.Torch(bOn); |
| | | }; |
| | | |
| | | } |
| | | |
| | | var result = await scanner.Scan(); |
| | | |
| | | if (result != null) |
| | | { |
| | | action?.Invoke(result.Text); |
| | | action?.Invoke(result); |
| | | } |
| | | else |
| | | { |
| | | action?.Invoke(null); |
| | | Console.WriteLine("二维码返回值为null"); |
| | | } |
| | | |
| | | } |
| | | |
| | | static MobileBarcodeScanner scanner; |
| | | |
| | | |
| | | Action<string> action; |
| | | |
| | | public void OpenScan(Action<string> action) |
| | | { |
| | | this.action = action; |
| | | |
| | | string cancel = "取消"; |
| | | //string flashText = ""; |
| | | string titleText = "二维码扫描"; |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | cancel = "Cancel"; |
| | | //flashText = ""; |
| | | titleText = "Scan"; |
| | | } |
| | | var d1 = new HDLQRCodeScanFinish(ScanResult); |
| | | HDL.Shared.IOS.ScanQRCode.HDLScanQRCodeSDK.SharedInstance().ScanQRCodeWith(cancel, titleText, d1); |
| | | |
| | | |
| | | |
| | | //if (scanner == null) |
| | | //{ |
| | | // var mZXingOverlayView = new ZXingOverlayView(cancel, flashText, titleText); |
| | | // scanner = new MobileBarcodeScanner(AppDelegate.rootViewController) { FlashButtonText = flashText, TopText = titleText, BottomText = "", CancelButtonText = cancel }; |
| | | // scanner.UseCustomOverlay = true; |
| | | |
| | | // scanner.CustomOverlay = mZXingOverlayView; |
| | | // var bOn = false; |
| | | // mZXingOverlayView.OnCancel += () => |
| | | // { |
| | | // scanner?.Cancel(); |
| | | // }; |
| | | |
| | | // mZXingOverlayView.OnTorch += () => |
| | | // { |
| | | // bOn = !bOn; |
| | | // scanner?.Torch(bOn); |
| | | // }; |
| | | |
| | | //} |
| | | |
| | | //var result = await scanner.Scan(); |
| | | |
| | | //if (result != null) |
| | | //{ |
| | | // action?.Invoke(result.Text); |
| | | //} |
| | | //else |
| | | //{ |
| | | // action?.Invoke(null); |
| | | // Console.WriteLine("二维码返回值为null"); |
| | | //} |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | | public static byte[] BytesFromText(string text, int width = 300, int height = 300) |
| | |
| | | using System.IO; |
| | | using HDL_ON.Common; |
| | | using System.Collections.Generic; |
| | | using System.Text; |
| | | using System.Security.Cryptography; |
| | | |
| | | namespace HDL_ON |
| | | { |
| | |
| | | /// </summary> |
| | | public byte[] GetImageDownloadUrl(string imageKey) |
| | | { |
| | | var requestJson = HttpUtil.GetSignRequestJson(new GetImageUrlObj() |
| | | if (imageKey.StartsWith("https:")) |
| | | { |
| | | imageKey = imageKey, |
| | | }); |
| | | var revertObj = HttpUtil.RequestHttpsPostFroHome(NewAPI.API_POST_GetImageUrl, requestJson); |
| | | if (revertObj.Code == StateCode.SUCCESS) |
| | | return HttpUtil.HttpsDownload(imageKey); |
| | | } |
| | | else |
| | | { |
| | | if (revertObj.Data != null) |
| | | var requestJson = HttpUtil.GetSignRequestJson(new GetImageUrlObj() |
| | | { |
| | | if (!string.IsNullOrEmpty(revertObj.Data.ToString())) |
| | | imageKey = imageKey, |
| | | }); |
| | | var revertObj = HttpUtil.RequestHttpsPostFroHome(NewAPI.API_POST_GetImageUrl, requestJson); |
| | | if (revertObj.Code == StateCode.SUCCESS) |
| | | { |
| | | if (revertObj.Data != null) |
| | | { |
| | | var url = revertObj.Data.ToString(); |
| | | return HttpUtil.HttpsDownload(url); |
| | | if (!string.IsNullOrEmpty(revertObj.Data.ToString())) |
| | | { |
| | | var url = revertObj.Data.ToString(); |
| | | return HttpUtil.HttpsDownload(url); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | string strKey = "abcdefgh";//注意:这里的密钥sKey必须能转为8个byte,即输入密钥为8半角个字符或者4个全角字符或者4个汉字的字符串 |
| | | string strIV = "ijklmnop"; |
| | | |
| | | // 加密 |
| | | private string Encrypt(string _strQ) |
| | | { |
| | | byte[] buffer = Encoding.UTF8.GetBytes(_strQ); |
| | | MemoryStream ms = new MemoryStream(); |
| | | DESCryptoServiceProvider des = new DESCryptoServiceProvider(); |
| | | CryptoStream encStream = new CryptoStream(ms, des.CreateEncryptor(Encoding.UTF8.GetBytes(strKey), Encoding.UTF8.GetBytes(strIV)), CryptoStreamMode.Write); |
| | | encStream.Write(buffer, 0, buffer.Length); |
| | | encStream.FlushFinalBlock(); |
| | | return Convert.ToBase64String(ms.ToArray()); |
| | | } |
| | | |
| | | // 解密 |
| | | private string Decrypt(string _strQ) |
| | | { |
| | | byte[] buffer = Convert.FromBase64String(_strQ); |
| | | MemoryStream ms = new MemoryStream(); |
| | | DESCryptoServiceProvider des = new DESCryptoServiceProvider(); |
| | | CryptoStream encStream = new CryptoStream(ms, des.CreateDecryptor(Encoding.UTF8.GetBytes(strKey), Encoding.UTF8.GetBytes(strIV)), CryptoStreamMode.Write); |
| | | encStream.Write(buffer, 0, buffer.Length); |
| | | encStream.FlushFinalBlock(); |
| | | return Encoding.UTF8.GetString(ms.ToArray()); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 2020-12-03 |
| | | /// 检测加载图片 |
| | |
| | | { |
| | | try |
| | | { |
| | | var imageUrl = imageKey; |
| | | |
| | | if (imageUrl.StartsWith("http")) |
| | | { |
| | | imageKey = Encrypt(imageKey); |
| | | } |
| | | |
| | | //1.本地默认图库图片,直接加载本地 |
| | | if (imageKey.Contains("Classification/Room/Roombg") || imageKey.Contains("Intelligence/Gallery/scenebg")) |
| | | { |
| | |
| | | //2.2 本地没缓存,开启线程云端下载然后缓存 |
| | | System.Threading.Tasks.Task.Run(() => |
| | | { |
| | | byte[] imageBytes = GetImageDownloadUrl(imageKey); |
| | | byte[] imageBytes = GetImageDownloadUrl(imageUrl); |
| | | if (imageBytes != null) |
| | | { |
| | | WriteFileByBytes(imageKey, imageBytes); |
| | |
| | | if (frameLayout != null) |
| | | { |
| | | frameLayout.BackgroundImagePath = imageKey; |
| | | //Utlis.WriteLine("imageKey 加载云端下载图片成功"); |
| | | Utlis.WriteLine("imageKey 加载云端下载图片成功"); |
| | | } |
| | | }); |
| | | } |
| | | else |
| | | { |
| | | //2.4 下载是否,是否使用默认图片 |
| | | //Utlis.WriteLine("imageKey 加载云端图片失败"); |
| | | Utlis.WriteLine("imageKey 加载云端图片失败"); |
| | | } |
| | | }); |
| | | } |
| | |
| | | public static class StringId |
| | | { |
| | | /// <summary> |
| | | /// 原密码 |
| | | /// </summary> |
| | | public const int OriginalPassword = 561; |
| | | /// <summary> |
| | | /// 已绑定 |
| | | /// </summary> |
| | | public const int Bound = 560; |
| | |
| | | return $"/user/{Control.Ins.GatewayId}/custom/security/list/get"; |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 心跳包 |
| | | /// </summary> |
| | | public string HeartBeat |
| | | { |
| | | get |
| | | { |
| | | return $"/user/{Control.Ins.GatewayId}/custom/gateway/heartbeat"; |
| | | } |
| | | } |
| | | |
| | | #region 门锁 |
| | | public string OneKeyUnlock |
| | |
| | | using HDL_ON.DAL.Server; |
| | | using HDL_ON.Entity; |
| | | using HDL_ON.UI; |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Linq; |
| | | using Shared; |
| | | |
| | | namespace HDL_ON.DriverLayer |
| | | { |
| | | /// <summary> |
| | | /// 通讯方式 |
| | | /// </summary> |
| | | public enum CommunicationMode |
| | | { |
| | | none, |
| | | /// <summary> |
| | | /// 本地udp |
| | | /// </summary> |
| | | local_BusUdp, |
| | | /// <summary> |
| | | /// 本地tcp客户端 |
| | | /// </summary> |
| | | tcp_local_client, |
| | | } |
| | | |
| | | public class Control |
| | | { |
| | | |
| | |
| | | /// 记录接收到的消息,方便zb的工程师调试他们的设备 |
| | | /// </summary> |
| | | public List<string> MsgInfoList = new List<string>(); |
| | | /// <summary> |
| | | /// 本地tcp客户端连接是否成功 |
| | | /// 是否登录网关成功 |
| | | /// </summary> |
| | | public bool LocalTcpClientLogin = false; |
| | | |
| | | int _msg_id = 1; |
| | | /// <summary> |
| | |
| | | public Control_Udp myUdp1 = null; |
| | | |
| | | /// <summary> |
| | | /// 通讯方式 |
| | | /// </summary> |
| | | public CommunicationMode communicationMode; |
| | | |
| | | /// <summary> |
| | | /// 打开tcp服务端 |
| | | /// </summary> |
| | | public void OpenTcpServer() |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | private System.Threading.Thread loginGatewayThread; |
| | | |
| | | /// <summary> |
| | | /// 登录网关 |
| | | /// </summary> |
| | | public void LoginGateway() |
| | | { |
| | | if(loginGatewayThread== null) |
| | | { |
| | | loginGatewayThread = new System.Threading.Thread(() => { |
| | | while (true) |
| | | { |
| | | if (Ins.GatewayOnline_Local && myTcpClient.isConnected && LocalTcpClientLogin) |
| | | { |
| | | var sendData = new { clientType = "app", version = "1.0" }; |
| | | var sendJob = new { id = Control.Ins.msg_id.ToString(), time_stamp = Utlis.GetTimestamp(), objects = sendData }; |
| | | |
| | | var bodyString = JsonConvert.SerializeObject(sendJob); |
| | | |
| | | var sendBytes = ConvertSendBodyData($"/user/{GatewayId}/custom/gateway/login", bodyString); |
| | | |
| | | Ins.myTcpClient.SendMessage(sendBytes); |
| | | } |
| | | System.Threading.Thread.Sleep(2000); |
| | | } |
| | | |
| | | }); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 场景控制入口 |
| | | /// </summary> |
| | |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 安防控制 |
| | | /// </summary> |
| | | public void ControlArm() |
| | | { |
| | | DAL.Server.HttpServerRequest httpServer = new DAL.Server.HttpServerRequest(); |
| | | //var pack = httpServer.GetSecurityAlarmLogList |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 发送命令 |
| | |
| | | //} |
| | | receiveObj.BodyDataString = res[1]; |
| | | |
| | | if(receiveObj.Topic == CommunicationTopic.ct.HeartBeat) |
| | | { |
| | | |
| | | return null; |
| | | } |
| | | |
| | | //2021-09-23 过滤不需要解密的主题 目前搜索网关主题不加密 |
| | | if (receiveObj.Topic != CommunicationTopic.SearchLoaclGatewayReply) |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | try |
| | | { |
| | | var idMsg = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponsePack>(res[1]); |
| | | var hasProcess = hasItBeenProcessed(idMsg.id); |
| | | if (hasProcess) |
| | | { |
| | | return null; |
| | | } |
| | | MainPage.Log($"处理局域网数据id:{idMsg.id}"); |
| | | |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log($"解析局域网数据异常{ex.Message}"); |
| | | } |
| | | |
| | | if (receiveObj.Topic == CommunicationTopic.SearchLoaclGatewayReply || receiveObj.Topic == CommunicationTopic.GatewayBroadcast) |
| | | { |
| | |
| | | //2021-09-23 新增获取当前网关是否本地加密 |
| | | Ins.IsLocalEncrypt = device.isLocalEncrypt; |
| | | //MainPage.Log("网关本地加密状态:" + device.local_encrypt.ToString()); |
| | | |
| | | OpenTcpClent(); |
| | | |
| | | LoginGateway(); |
| | | |
| | | } |
| | | } |
| | | else if (receiveObj.Topic == CommunicationTopic.ct.ReadStatus + "_reply" || |
| | | receiveObj.Topic == CommunicationTopic.ct.ControlFunctionTopic + "_reply" || |
| | | receiveObj.Topic == CommunicationTopic.ct.GatewayUpStatus || |
| | | receiveObj.Topic.Contains( CommunicationTopic.ct.GatewayUpSortTopic)) |
| | | receiveObj.Topic.Contains(CommunicationTopic.ct.GatewayUpSortTopic)) |
| | | { |
| | | //TODO 暂时不传正确的数据上去,如果后面要优化前面这些代码 |
| | | UpdataFunctionStatus(receiveObj.BodyDataString, null); |
| | | } |
| | | else if (receiveObj.Topic == CommunicationTopic.ct.ControlSeurity +"_reply" |
| | | else if (receiveObj.Topic == CommunicationTopic.ct.ControlSeurity + "_reply" |
| | | || receiveObj.Topic == CommunicationTopic.ct.ReadSecurityStatus + "_reply" |
| | | || receiveObj.Topic == CommunicationTopic.ct.SecurityStatusUp) |
| | | { |
| | |
| | | { |
| | | MainPage.Log($"局域网安防信息: {receiveObj.Topic} : 内容: {res[1]}"); |
| | | var tt = ""; |
| | | lock (tt) { |
| | | lock (tt) |
| | | { |
| | | var temp = Newtonsoft.Json.JsonConvert.DeserializeObject<SecurityStatusObj>(receiveObj.BodyDataString); |
| | | if (temp != null) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex){ |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log($"安防局域网异常:{ex.Message}"); |
| | | } |
| | | } |
| | | else if (receiveObj.Topic == $"/user/{GatewayId}/custom/gateway/login_reply") { |
| | | var temp = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(receiveObj.BodyDataString); |
| | | if (temp.GetValue("objects").ToString().Contains("success")) |
| | | { |
| | | LocalTcpClientLogin = true; |
| | | } |
| | | } |
| | | else |
| | |
| | | return receiveObj; |
| | | } |
| | | |
| | | |
| | | private List<string> processedDataList = new List<string>(); |
| | | /// <summary> |
| | | /// 是否已经处理过数据 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | private bool hasItBeenProcessed(string msgId) |
| | | { |
| | | if (processedDataList.Contains(msgId)) |
| | | { |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | if(processedDataList.Count> 50) |
| | | { |
| | | processedDataList.RemoveAt(0); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新设备状态 |
| | | /// A协议数据 |
New file |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Net.Sockets; |
| | | using System.Text; |
| | | using System.Threading; |
| | | using System.Timers; |
| | | using HDL_ON; |
| | | using HDL_ON.Entity; |
| | | using HDL_ON.UI; |
| | | |
| | | namespace HDL_ON.DriverLayer |
| | | { |
| | | /// <summary> |
| | | /// link网关本地链接逻辑 |
| | | /// </summary> |
| | | public class Control_Tcp |
| | | { |
| | | #region ■ 变量声明___________________________ |
| | | |
| | | /// <summary> |
| | | /// link网关链接逻辑 |
| | | /// </summary> |
| | | private static Control_Tcp m_Current = null; |
| | | /// <summary> |
| | | /// link网关链接逻辑 |
| | | /// </summary> |
| | | public static Control_Tcp Current |
| | | { |
| | | get |
| | | { |
| | | if (m_Current == null) |
| | | { |
| | | m_Current = new Control_Tcp(); |
| | | } |
| | | return m_Current; |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// Link网关tcp接收回调,理论上它不会处理zigbee的上报(第一个参数是网关的mac,第二个参数是接收的数据) |
| | | /// </summary> |
| | | private Action<string, string, string> tcpReceiveEvent = null; |
| | | /// <summary> |
| | | /// Tcp客户端连接池 |
| | | /// </summary> |
| | | private List<TcpConnectData> listTcpClient = new List<TcpConnectData>(); |
| | | /// <summary> |
| | | /// 是否搜索网关 |
| | | /// </summary> |
| | | private bool isSearchGateway = false; |
| | | |
| | | #endregion |
| | | |
| | | #region ■ 搜索Link网关_______________________ |
| | | |
| | | // /// <summary> |
| | | // /// 搜索Link网关 |
| | | // /// </summary> |
| | | // /// <param name="resultEvent">搜索到网关的回调函数,-1:异常了 1:收到一个A网关</param> |
| | | // /// <param name="searchTime">搜索时间(秒)</param> |
| | | // /// <param name="connectLocalOnly">当搜索到网关时,是否只连接本地的(不能瞎连其他的网关,但是网关搜索界面特殊)</param> |
| | | // public void SearchLinkGateway(Action<int, AGatewayInfo> resultEvent, int searchTime, bool connectLocalOnly) |
| | | // { |
| | | // this.isSearchGateway = true; |
| | | // //算了,在这里启动远程连接吧,反正也就执行一次 |
| | | // HdlLinkCloudConnectLogic.Current.StartCloudMqttConnection(); |
| | | |
| | | // var listGateway = HdlLinkGatewayLogic.Current.GetAllLocalGateway(); |
| | | // var dicGateway = new Dictionary<string, ZigBee.Device.LinkGateway>(); |
| | | // foreach (var gw in listGateway) |
| | | // { |
| | | // //获取本地全部的A网关的mac |
| | | // dicGateway[gw.GwMac] = gw; |
| | | // } |
| | | // //重复检测 |
| | | // var listCheck = new HashSet<string>(); |
| | | |
| | | // var sendData = "Topic:/user/all/custom/gateway/search\r\n"; |
| | | |
| | | // var dic = new Dictionary<string, string>(); |
| | | // dic["id"] = HdlGatewayResourse.AGatewayLinkFlage; |
| | | // dic["time_stamp"] = HdlHttpLogic.Current.GetTimestamp().PadRight(13, '0'); |
| | | // var bodyData = Newtonsoft.Json.JsonConvert.SerializeObject(dic); |
| | | // sendData += "Length:" + bodyData.Length + "\r\n\r\n"; |
| | | // sendData += bodyData; |
| | | |
| | | // //初始化udp |
| | | // var udpLogic = new HdlUdpLogic(); |
| | | // if (udpLogic.InitUdp("239.0.168.188", 8585) == false) |
| | | // { |
| | | // //关闭udp |
| | | // udpLogic.CloseUdp(); |
| | | |
| | | // resultEvent?.Invoke(-1, null); |
| | | // return; |
| | | // } |
| | | |
| | | // HDL_ON.DriverLayer.Control.Ins.OpenUdp(8585); |
| | | |
| | | // //接收事件 |
| | | // Action<System.Net.IPEndPoint, string> actionEvent = (ipPoint, result) => |
| | | // { |
| | | // //处理搜索A网关时,网关回复的数据 |
| | | // try |
| | | // { |
| | | // ///// |
| | | // System.Net.IPAddress s = ipPoint.Address; |
| | | // MainPage.Log("TcpClient->SearchLinkGateway", $"{s}==网关搜索本地回复,数据内容{result}"); |
| | | |
| | | // //检验A协议网关主题(如果检验是指定主题,则返回负载数据,否则返回null) |
| | | // var resultData = HdlLinkGatewaySendLogic.Current.CheckLinkGatewayTopic("/user/all/custom/gateway/search_reply", result); |
| | | // if (resultData == null) { return; } |
| | | // //调用回调函数 |
| | | // var info = Newtonsoft.Json.JsonConvert.DeserializeObject<AGatewayInfo>(resultData); |
| | | // if (info == null) |
| | | // { |
| | | // //数据异常,退出 |
| | | // return; |
| | | // } |
| | | // if (!(string.IsNullOrEmpty(info.HomeId) == true || info.HomeId == Common.Config.Instance.HomeId)) |
| | | // { |
| | | // //网关已经绑定其他住宅,退出 |
| | | // return; |
| | | // } |
| | | // ///tcp连接目标设备的ip |
| | | // info.Ip_address = ipPoint.Address.ToString(); |
| | | // //搜索到的这个网关,是否是存在在本地了的 |
| | | // if (dicGateway.ContainsKey(info.Device_mac) == true) |
| | | // { |
| | | // var gateWay = dicGateway[info.Device_mac]; |
| | | // //如果搜索得到本地存在的网关,则使用本地通信 |
| | | // gateWay.OnlineStatu = 1; |
| | | // gateWay.isLocalEncrypt = info.isLocalEncrypt; |
| | | // gateWay.Master = info.Master; |
| | | // //gateWay.Slaver_list1 = info.Slaver_list1; |
| | | // gateWay.Oid = info.Oid; |
| | | // gateWay.InGatewayHomeId = info.HomeId; |
| | | // info.IsBindGateway = true; |
| | | |
| | | // Common.Config.Instance.Home.NowHomeOnlineStatu = "1"; |
| | | // } |
| | | // //搜索到的网关,建立链接 |
| | | // if (connectLocalOnly == false || info.IsBindGateway == true) |
| | | // { |
| | | // this.ConnectLocalLinkGateway(info.Device_mac, info.Ip_address, info.GatewayId, info.isLocalEncrypt); |
| | | // } |
| | | // else |
| | | // { |
| | | // //获取连接对象 |
| | | // var connectObj = this.GetConnectObject(info.Device_mac, false); |
| | | // if (connectObj != null) |
| | | // { |
| | | // //如果有这个对象, 则替换一下它的网关id |
| | | // connectObj.GatewayId = info.GatewayId; |
| | | // connectObj.localEncrypt = info.isLocalEncrypt; |
| | | // return; |
| | | // } |
| | | // } |
| | | // if (listCheck.Contains(info.Device_mac) == true) |
| | | // { |
| | | // //已经处理过了 |
| | | // return; |
| | | // } |
| | | // listCheck.Add(info.Device_mac); |
| | | |
| | | |
| | | //#if DEBUG |
| | | // Console.WriteLine($"搜索网关捕抓到网关:{info.Device_mac}"); |
| | | //#endif |
| | | // //info |
| | | |
| | | // //回调函数 |
| | | // resultEvent?.Invoke(1, info); |
| | | // } |
| | | // catch (Exception e) |
| | | // { |
| | | // string str = e.Message; |
| | | // } |
| | | // }; |
| | | // udpLogic.ReceviceEvent += actionEvent; |
| | | // var dateTime = System.DateTime.Now.AddSeconds(searchTime); |
| | | // while (this.isSearchGateway && System.DateTime.Now < dateTime) |
| | | // { |
| | | // udpLogic.SendData(sendData, "239.0.168.188", 8585); |
| | | // udpLogic.SendData(sendData, "255.255.255.255", 8585); |
| | | // System.Threading.Thread.Sleep(1000); |
| | | // } |
| | | // udpLogic.ReceviceEvent -= actionEvent; |
| | | // //别关那么快 |
| | | // System.Threading.Thread.Sleep(300); |
| | | // this.isSearchGateway = false; |
| | | // //关闭udp |
| | | // udpLogic.CloseUdp(); |
| | | |
| | | // } |
| | | |
| | | // /// <summary> |
| | | // /// 停止搜索Link网关 |
| | | // /// </summary> |
| | | // public void StopSearchLinkGateway() |
| | | // { |
| | | // this.isSearchGateway = false; |
| | | // } |
| | | |
| | | #endregion |
| | | |
| | | #region ■ 链接本地Link网关___________________ |
| | | |
| | | /// <summary> |
| | | /// 链接Link网关 |
| | | /// </summary> |
| | | /// <param name="i_mac">网关mac</param> |
| | | /// <param name="i_ipAdrr">网关ip</param> |
| | | /// <param name="i_gwId">网关Id</param> |
| | | /// <param name="isBinded">该tcp所指向的网关,是否是当前住宅所绑定的</param> |
| | | /// <returns></returns> |
| | | public void ConnectLocalLinkGateway(string i_mac, string i_ipAdrr, string i_gwId, bool localEncrypt) |
| | | { |
| | | if (i_mac == string.Empty || i_ipAdrr == string.Empty) |
| | | { |
| | | return; |
| | | } |
| | | var connectData = new TcpConnectData(); |
| | | connectData.GatewayId = i_gwId; |
| | | connectData.GatewayIp = i_ipAdrr; |
| | | connectData.GatewayMac = i_mac; |
| | | connectData.localEncrypt = localEncrypt; |
| | | lock (this.listTcpClient) |
| | | { |
| | | //找到当前网关的连接 |
| | | if (this.listTcpClient.Find((v) => v.GatewayMac == i_mac) != null) |
| | | { |
| | | return; |
| | | } |
| | | this.listTcpClient.Add(connectData); |
| | | } |
| | | |
| | | try |
| | | { |
| | | //TCP连接 |
| | | connectData.tcpClient = new Communication.TcpClient(i_ipAdrr, 8586); |
| | | connectData.tcpClient.Connect(); |
| | | connectData.tcpClient.ReadFormSocket(); |
| | | connectData.tcpClient.ExitEvent += (s, e) => |
| | | { |
| | | StopConnectLinkGateway(connectData); |
| | | }; |
| | | connectData.tcpClient.ReceiveBytesAction += (topic, bytes, socket) => |
| | | { |
| | | managerLinkGatewayData(topic, bytes, socket); |
| | | }; |
| | | |
| | | |
| | | } |
| | | catch |
| | | { |
| | | #if DEBUG |
| | | //HdlMessageLogic.Current.ShowMassage(ShowMsgType.Tip, i_ipAdrr + "Tcp链接不了"); |
| | | #endif |
| | | StopConnectLinkGateway(connectData); |
| | | } |
| | | } |
| | | |
| | | public TcpConnectData GetConnectObjectBySocket(Socket socket) |
| | | { |
| | | lock (listTcpClient) |
| | | { |
| | | var tcpConnectData = listTcpClient.Find(tcd => tcd.tcpClient._socket == socket); |
| | | return tcpConnectData; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 断开全部的Link网关连接 |
| | | /// </summary> |
| | | public void StopAllConnectLinkGateway() |
| | | { |
| | | var listTemp = new List<TcpConnectData>(); |
| | | for (int i = 0; i < this.listTcpClient.Count; i++) |
| | | { |
| | | //创另外一个对象出来,是有作用的 |
| | | listTemp.Add(this.listTcpClient[i]); |
| | | } |
| | | foreach (var data in listTemp) |
| | | { |
| | | //断开指定的link网关连接 |
| | | this.StopConnectLinkGateway(data); |
| | | } |
| | | //清空缓存 |
| | | this.listTcpClient.Clear(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 断开指定的link网关连接 |
| | | /// </summary> |
| | | /// <param name="mac">需要断开连接的网关mac</param> |
| | | public void StopConnectLinkGateway(string mac) |
| | | { |
| | | var tempGateway = listTcpClient.Find((v) => v.GatewayMac == mac); |
| | | if (tempGateway != null) |
| | | { |
| | | //断开指定的link网关连接 |
| | | this.StopConnectLinkGateway(tempGateway); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 断开指定的link网关连接 |
| | | /// </summary> |
| | | /// <param name="connectData">连接数据</param> |
| | | private void StopConnectLinkGateway(TcpConnectData connectData) |
| | | { |
| | | lock (listTcpClient) |
| | | { |
| | | this.listTcpClient.Remove(connectData); |
| | | connectData.tcpClient.Dispose(); |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region ■ 发送数据到Link网关_________________ |
| | | /// <summary> |
| | | /// 发送数据到本地Link网关 |
| | | /// </summary> |
| | | /// <param name="connectData">链接信息</param> |
| | | /// <param name="sendData">发送的数据</param> |
| | | /// <returns></returns> |
| | | private void DoSendDataToLinkGateway(TcpConnectData connectData, string sendData) |
| | | { |
| | | #if DEBUG |
| | | MainPage.Log(DateTime.Now + ":TcpClient->DoSendDataToLinkGateway", $"本地发送数据,Data:{sendData}"); |
| | | #endif |
| | | byte[] byteData; |
| | | //44bytes 加密数据 AES加密 base64密文 |
| | | ////目前默认都是加密载荷 |
| | | //byteData = this.AesEncryptPayload(byteData, Config.Instance.Home.localSecret); |
| | | //解密负载数据(因为写密钥给网关一定明文,因为那时网关还没有密钥) |
| | | if (connectData.localEncrypt) |
| | | { |
| | | var headerAndBody = sendData.Split("\r\n\r\n"); |
| | | string topic = headerAndBody[0].Split("\r\n")[0]; |
| | | //加密载荷 |
| | | var byteBody = this.AesEncryptPayload(System.Text.Encoding.UTF8.GetBytes(headerAndBody[1]), DB_ResidenceData.Instance.CurrentRegion.localSecret); |
| | | var header = System.Text.Encoding.UTF8.GetBytes($"{topic}\r\nLength:{byteBody.Length}\r\n" + "\r\n"); |
| | | |
| | | byteData = new byte[header.Length + byteBody.Length]; |
| | | System.Array.Copy(header, 0, byteData, 0, header.Length); |
| | | ///参数(源文件,取源文件索引值,存储器,存放位置,源文件长度) |
| | | System.Array.Copy(byteBody, 0, byteData, header.Length, byteBody.Length); |
| | | |
| | | } |
| | | else |
| | | { |
| | | byteData = Encoding.UTF8.GetBytes(sendData); |
| | | } |
| | | |
| | | //byteData = Encoding.UTF8.GetBytes(sendData); |
| | | //将数据写入网络流 |
| | | connectData.tcpClient?.CommSend(byteData, byteData.Length); |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region ■ 处理Link网关的数据_________________ |
| | | |
| | | /// <summary> |
| | | /// 处理接收本地Link网关的数据(返回值 0:还不存在完成的数据 1:已经存在完成的数据) |
| | | /// </summary> |
| | | /// <param name="listByte">数据</param> |
| | | private void managerLinkGatewayData(string topic, byte[] bytes, Socket socket) |
| | | { |
| | | try |
| | | { |
| | | var arryTopic = topic.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); |
| | | if (arryTopic.Length < 2) |
| | | { |
| | | //非正规主题 |
| | | return; |
| | | } |
| | | |
| | | |
| | | var connectData = this.GetConnectObjectBySocket(socket); |
| | | if (connectData == null) |
| | | { |
| | | return; |
| | | } |
| | | string gatewayMac = connectData.GatewayMac; |
| | | string gatewayId = connectData.GatewayId; |
| | | ///解密负载数据 |
| | | if (connectData.localEncrypt == true) |
| | | { |
| | | var tempBytes = bytes; |
| | | bytes = this.AesDecryptPayload(bytes, DB_ResidenceData.Instance.CurrentRegion.localSecret); |
| | | if (bytes == null) |
| | | { |
| | | bytes = tempBytes; |
| | | } |
| | | } |
| | | /////目前网关默认都是加密的 |
| | | //bytes = this.AesDecryptPayload(bytes, Config.Instance.Home.localSecret); |
| | | var bodyData = System.Text.Encoding.UTF8.GetString(bytes); |
| | | |
| | | MainPage.Log(DateTime.Now + ":Control_Tcp->本地接收数据", $"Topic:{topic}\r\nData:{bodyData}"); |
| | | |
| | | if (topic.Contains("thing/property/up") == true) |
| | | { |
| | | //这个是Link设备的状态上报,别整,只要zigbee的 |
| | | var temp = Newtonsoft.Json.JsonConvert.DeserializeObject<AlinkFunctionStatusObj>(bodyData); |
| | | |
| | | return; |
| | | } |
| | | |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | } |
| | | } |
| | | |
| | | |
| | | #endregion |
| | | |
| | | #region ■ 结构体_____________________________ |
| | | |
| | | |
| | | /// <summary> |
| | | /// Tcp连接信息 |
| | | /// </summary> |
| | | public class TcpConnectData |
| | | { |
| | | /// <summary> |
| | | /// 网关的mac(主键使用) |
| | | /// </summary> |
| | | public string GatewayMac = string.Empty; |
| | | /// <summary> |
| | | /// 网关ip |
| | | /// </summary> |
| | | public string GatewayIp = string.Empty; |
| | | /// <summary> |
| | | /// 网关Id(不是云端的那个) |
| | | /// </summary> |
| | | public string GatewayId = string.Empty; |
| | | |
| | | // |
| | | public Communication.TcpClient tcpClient; |
| | | |
| | | /// <summary> |
| | | /// 本地是否加密 |
| | | /// </summary> |
| | | public bool localEncrypt; |
| | | } |
| | | #endregion |
| | | |
| | | #region ■ 加密以及解密_______________________ |
| | | |
| | | /// <summary> |
| | | /// 加密负载为二进制流(Link专用) |
| | | /// </summary> |
| | | /// <param name="toEncryptArray"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | private byte[] AesEncryptPayload(byte[] toEncryptArray, string key) |
| | | { |
| | | //加密密钥为空 |
| | | if (key == string.Empty) |
| | | { |
| | | return toEncryptArray; |
| | | } |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(key)) return toEncryptArray; |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | var rm = new System.Security.Cryptography.RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = System.Security.Cryptography.CipherMode.CBC, |
| | | Padding = System.Security.Cryptography.PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES加密器对象 |
| | | var cTransform = rm.CreateEncryptor(); |
| | | //使用AES将明文流转成密文字节数组 |
| | | return cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | } |
| | | catch |
| | | { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 采用Aes解密负载数据(Link专用) |
| | | /// </summary> |
| | | /// <param name="toEncryptArray"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | private byte[] AesDecryptPayload(byte[] toEncryptArray, string key) |
| | | { |
| | | //解密密钥为空 |
| | | if (key == string.Empty) |
| | | { |
| | | return toEncryptArray; |
| | | } |
| | | |
| | | try |
| | | { |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | var rm = new System.Security.Cryptography.RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = System.Security.Cryptography.CipherMode.CBC, |
| | | Padding = System.Security.Cryptography.PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES解密器对象 |
| | | var cTransform = rm.CreateDecryptor(); |
| | | |
| | | //使用AES将密文流转成明文的字节数组 |
| | | return cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | } |
| | | catch |
| | | { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | } |
| | | } |
| | | namespace Communication |
| | | { |
| | | //TCP客户端实现 |
| | | public class TcpClient |
| | | { |
| | | private const int MAX_RECONNECT_TIMES = 3; //断线重连尝试次数 |
| | | |
| | | //soket对象及参数 |
| | | public Socket _socket; |
| | | private string host; |
| | | private int port; |
| | | private bool reconnect; |
| | | private bool run = true; |
| | | private int ConnecteFailedCount { get; set; } |
| | | public int ReconnectStatistics { get; private set; } |
| | | |
| | | private static uint _keepAliveTime = 5000; //无数据交互持续时间(ms) |
| | | private static uint _keepAliveInterval = 500; //发送探测包间隔(ms) |
| | | |
| | | //重连失败事件 |
| | | public event EventHandler ExitEvent; |
| | | public Action<string, byte[], Socket> ReceiveBytesAction; |
| | | |
| | | //构造函数 |
| | | public TcpClient(string host, int port) |
| | | { |
| | | this.host = host; |
| | | this.port = port; |
| | | reconnect = false; |
| | | ConnecteFailedCount = 0; |
| | | } |
| | | |
| | | //连接 |
| | | public void Connect() |
| | | { |
| | | byteList = new List<byte>(1024 * 5); |
| | | _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, |
| | | ProtocolType.Tcp); |
| | | _socket.Connect(host, port); |
| | | MainPage.Log("TcpClient->Reconnect", $"连接成功,IP:{host}"); |
| | | ConnecteFailedCount = MAX_RECONNECT_TIMES; |
| | | |
| | | //设置KeepAlive |
| | | _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); |
| | | byte[] optionValue = new byte[12]; |
| | | BitConverter.GetBytes(1).CopyTo(optionValue, 0); |
| | | BitConverter.GetBytes(_keepAliveTime).CopyTo(optionValue, 4); |
| | | BitConverter.GetBytes(_keepAliveInterval).CopyTo(optionValue, 8); |
| | | _socket.IOControl(IOControlCode.KeepAliveValues, optionValue, null); |
| | | } |
| | | |
| | | //重连 |
| | | public bool Reconnect() |
| | | { |
| | | ReconnectStatistics++; |
| | | reconnect = false; |
| | | close(); |
| | | try |
| | | { |
| | | MainPage.Log("TcpClient->Reconnect", $"重新开始连接,IP:{host}"); |
| | | Connect(); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | ConnecteFailedCount--; |
| | | if (ConnecteFailedCount > 0) |
| | | { |
| | | //Console.WriteLine("重试次数剩余{0}",ConnecteFailedCount); |
| | | reconnect = true; |
| | | return true; |
| | | } |
| | | else |
| | | { |
| | | //重连失败事件 |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 关闭 |
| | | /// </summary> |
| | | private void close() |
| | | { |
| | | try |
| | | { |
| | | MainPage.Log("TcpClient->Close", $"Socket 关闭,IP:{host}"); |
| | | _socket.Close(); |
| | | } |
| | | catch { } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 释放资源 |
| | | /// </summary> |
| | | public void Dispose() |
| | | { |
| | | run = false; |
| | | close(); |
| | | } |
| | | |
| | | |
| | | //发送数据接收实现,断线重连 |
| | | public int CommSend(byte[] buffer, int size) |
| | | { |
| | | int sendSize = 0; |
| | | try |
| | | { |
| | | if (_socket.Connected) |
| | | { |
| | | sendSize = _socket.Send(buffer, size, SocketFlags.None); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | MainPage.Log("TcpClient->CommSend", $"发送失败,Data:{System.Text.Encoding.UTF8.GetString(buffer)} Exception:{e.Message}"); |
| | | ReconnectStatistics++; |
| | | reconnect = true; |
| | | } |
| | | return sendSize; |
| | | } |
| | | |
| | | List<byte> byteList = new List<byte>(); |
| | | //接收数据线程,使用阻塞方式接收数据 |
| | | public void ReadFormSocket() |
| | | { |
| | | new System.Threading.Thread(() => |
| | | { |
| | | int count; |
| | | byte[] byteBuffer = new byte[2048]; |
| | | |
| | | while (run) |
| | | { |
| | | try |
| | | { |
| | | try |
| | | { |
| | | count = _socket.Receive(byteBuffer, SocketFlags.None); |
| | | for (int i = 0; i < count; i++) |
| | | { |
| | | byteList.Add(byteBuffer[i]); |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | count = 0; |
| | | } |
| | | |
| | | //网络断开Receive返回0 |
| | | if (count == 0 || reconnect == true) |
| | | { |
| | | if (run) |
| | | { |
| | | //重连次数用尽,退出 |
| | | if (Reconnect() == false) |
| | | { |
| | | //通知其它功能释放及删除当前对象 |
| | | ExitEvent?.Invoke(null, new EventArgs()); |
| | | break; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | ExitEvent?.Invoke(null, new EventArgs()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | |
| | | while (true) |
| | | { |
| | | var bytes = byteList.ToArray(); |
| | | var topMsgs = System.Text.Encoding.UTF8.GetString(bytes).Split("\r\n"); |
| | | |
| | | var lenght = getLenght(topMsgs); |
| | | |
| | | if (lenght <= 0) |
| | | { |
| | | //头部数据还没有接收完成 |
| | | break; |
| | | } |
| | | //是否已经获取完整所有的数据 |
| | | var data = new byte[lenght]; |
| | | int index = getDataIndex(byteList); |
| | | if (byteList.Count < index + lenght) |
| | | { |
| | | //当前数据还没有接收完成 |
| | | break; |
| | | } |
| | | //复制出body数据 |
| | | System.Array.Copy(bytes, index, data, 0, data.Length); |
| | | |
| | | //保留剩余的数据,以次用 |
| | | byteList.Clear(); |
| | | for (int i = index + lenght; i < bytes.Length; i++) |
| | | { |
| | | byteList.Add(bytes[i]); |
| | | } |
| | | var topic = getTopic(topMsgs); |
| | | |
| | | ReceiveBytesAction?.Invoke(topic, data, _socket); |
| | | } |
| | | } |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | MainPage.Log("TcpClient->ReadFormSocket", $"Exception:{e.Message}"); |
| | | } |
| | | } |
| | | }) |
| | | { |
| | | IsBackground = true |
| | | }.Start(); |
| | | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取内容长度 |
| | | /// </summary> |
| | | /// <param name="topMsgs"></param> |
| | | /// <returns></returns> |
| | | int getLenght(string[] topMsgs) |
| | | { |
| | | for (int i = 0; i < topMsgs.Length; i++) |
| | | { |
| | | string topMsg = topMsgs[i].Trim(); |
| | | if (topMsg.StartsWith("Length:")) |
| | | { |
| | | return int.Parse(topMsg.Replace("Length:", "")); |
| | | } |
| | | } |
| | | //找不到长度 |
| | | return -1; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取主题 |
| | | /// </summary> |
| | | /// <param name="topMsgs"></param> |
| | | /// <returns></returns> |
| | | private string getTopic(string[] topMsgs) |
| | | { |
| | | for (int i = 0; i < topMsgs.Length; i++) |
| | | { |
| | | var topMsg = topMsgs[i].Trim(); |
| | | if (topMsg.StartsWith("Topic:")) |
| | | { |
| | | return topMsg.Replace("Topic:", ""); |
| | | } |
| | | } |
| | | //找不到主题 |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 获取数据的开始位置 |
| | | * @param arrayList 接收到的所有数据 |
| | | * @return 数据位的开始索引 |
| | | */ |
| | | int getDataIndex(List<byte> arrayList) |
| | | { |
| | | var r = (byte)'\r'; |
| | | var n = (byte)'\n'; |
| | | for (int i = 0; i < arrayList.Count; i++) |
| | | { |
| | | //找出数据内容前面的两个换行 |
| | | if (3 <= i && arrayList[i - 3] == r && arrayList[i - 2] == n && arrayList[i - 1] == r && arrayList[i] == n) |
| | | { |
| | | //剩余的数据 |
| | | return i + 1; |
| | | } |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Net; |
| | | using System.Net.Sockets; |
| | | using System.Threading; |
| | | using System.Threading.Tasks; |
| | | using HDL_ON.Entity; |
| | | using Newtonsoft.Json; |
| | | |
| | | namespace HDL_ON.DriverLayer |
| | | { |
| | |
| | | public Action<string> ReceiveEvent; |
| | | |
| | | /// <summary> |
| | | /// 连接次数 |
| | | /// </summary> |
| | | private int reconnectIndex = 0; |
| | | /// <summary> |
| | | /// 是否连接成功 |
| | | /// </summary> |
| | | public bool isConnected = false; |
| | | |
| | | |
| | | /// <summary> |
| | | /// 构造函数 |
| | | /// </summary> |
| | | public Control_TcpClient(string serverIp) |
| | |
| | | } |
| | | |
| | | //TCP连接 |
| | | public bool Connect(int _port = 8586) |
| | | private bool ConnectToTcp( ) |
| | | { |
| | | if (string.IsNullOrEmpty(_ip) || _port == 0) |
| | | if (string.IsNullOrEmpty(_ip) ) |
| | | { |
| | | return false; |
| | | } |
| | | _tcpClient = new TcpClient(); |
| | | if (_tcpClient == null) |
| | | { |
| | | _tcpClient = new TcpClient(); |
| | | } |
| | | try |
| | | { |
| | | _tcpClient.Connect(IPAddress.Parse(_ip), _port); |
| | | _tcpClient.Connect(IPAddress.Parse(_ip), 8586); |
| | | Task.Run(new Action(ReceiveMessage));//开启线程,不停接收消息 |
| | | MainPage.Log($"打开tcp client{_ip}:{_port}"); |
| | | MainPage.Log($"打开tcp client{_ip}:8586"); |
| | | isConnected = true; |
| | | } |
| | | catch (Exception e) |
| | | { |
| | |
| | | } |
| | | return true;//返回连接状态 |
| | | } |
| | | /// <summary> |
| | | /// 连接tcp线程 |
| | | /// </summary> |
| | | private Thread connectThread; |
| | | |
| | | /// <summary> |
| | | /// 连接线程 |
| | | /// </summary> |
| | | public void Connect() |
| | | { |
| | | if(connectThread == null) |
| | | { |
| | | connectThread = new Thread(() => { |
| | | while (Control.Ins.GatewayOnline_Local) |
| | | { |
| | | if (_tcpClient == null) |
| | | { |
| | | ConnectToTcp(); |
| | | } |
| | | else |
| | | { |
| | | if (!_tcpClient.Connected) |
| | | { |
| | | try |
| | | { |
| | | //_tcpClient.ReceiveTimeout = |
| | | _tcpClient.Connect(IPAddress.Parse(_ip), 8586); |
| | | Task.Run(new Action(ReceiveMessage));//开启线程,不停接收消息 |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log($"tcp重连异常:{ex.Message}"); |
| | | _tcpClient.Close(); |
| | | _tcpClient = null; |
| | | } |
| | | } |
| | | } |
| | | Thread.Sleep(1000); |
| | | |
| | | |
| | | } |
| | | }); |
| | | connectThread.Start(); |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 关闭连接 |
| | | /// </summary> |
| | |
| | | /// <param name="bytes">需要发送的字节</param> |
| | | public void SendMessage(byte[] bytes) |
| | | { |
| | | NetworkStream networkStream = _tcpClient.GetStream(); |
| | | if (networkStream.CanWrite) |
| | | if (_tcpClient.GetStream().CanWrite) |
| | | { |
| | | networkStream.Write(bytes, 0, bytes.Length); |
| | | _tcpClient.GetStream().Write(bytes, 0, bytes.Length); |
| | | } |
| | | //networkStream.Close(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取列表数据回调方法 |
| | | /// 心跳包线程 |
| | | /// </summary> |
| | | public Action<string> GetListResponseAction; |
| | | private Thread heartBeatThread; |
| | | private DateTime heartBeatTime; |
| | | public void HeartBeat() |
| | | { |
| | | if(heartBeatThread == null) |
| | | { |
| | | heartBeatThread = new Thread(() => { |
| | | if(_tcpClient.Connected&&10 *1000 <(System.DateTime.Now - heartBeatTime).TotalMilliseconds) |
| | | { |
| | | var sendBytes = Control.Ins.ConvertSendBodyData(CommunicationTopic.ct.HeartBeat, ""); |
| | | SendMessage(sendBytes); |
| | | } |
| | | Thread.Sleep(100); |
| | | }); |
| | | heartBeatThread.Start(); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 接收数据线程 |
| | | /// </summary> |
| | | private Thread receiveThread; |
| | | |
| | | //接收消息 |
| | | public void ReceiveMessage() |
| | | { |
| | | NetworkStream networkStream = _tcpClient.GetStream(); |
| | | while (true) |
| | | if(receiveThread == null) |
| | | { |
| | | // 定义一个2M的缓存区; |
| | | byte[] arrMsgRec = new byte[1024 * 1024 * 2]; |
| | | int size = networkStream.Read(arrMsgRec, 0, arrMsgRec.Length); |
| | | var tcpDataString = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, arrMsgRec.Length); |
| | | if (!string.IsNullOrEmpty(tcpDataString)) |
| | | { |
| | | ReceiveEvent?.Invoke(tcpDataString); |
| | | } |
| | | receiveThread = new Thread(() => { |
| | | while (true) |
| | | { |
| | | if(_tcpClient == null) |
| | | { |
| | | receiveThread.Abort(); |
| | | receiveThread = null; |
| | | return; |
| | | } |
| | | if (!_tcpClient.Connected) |
| | | { |
| | | MainPage.Log("tcp客户端断开了连接..."); |
| | | receiveThread.Abort(); |
| | | receiveThread = null; |
| | | isConnected = false; |
| | | return; |
| | | } |
| | | |
| | | //// 将接受到的数据存入到输入 arrMsgRec中; |
| | | //int length = -1; |
| | | //try |
| | | //{ |
| | | // length = socketClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度; |
| | | //} |
| | | //catch (Exception ex) |
| | | //{ |
| | | // MainPage.Log($"tcpListener error 1 : {ex.Message}"); |
| | | // 定义一个2M的缓存区; |
| | | byte[] arrMsgRec = new byte[1024 * 1024 * 2]; |
| | | int size = _tcpClient.GetStream().Read(arrMsgRec, 0, arrMsgRec.Length); |
| | | var tcpDataString = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, arrMsgRec.Length); |
| | | |
| | | // Flag_Receive = false; |
| | | // // 从通信线程集合中删除被中断连接的通信线程对象; |
| | | // string keystr = socketClient.RemoteEndPoint.ToString(); |
| | | // dic_ClientSocket.Remove(keystr);//删除客户端字典中该socket |
| | | // dic_ClientThread[keystr].Abort();//关闭线程 |
| | | // dic_ClientThread.Remove(keystr);//删除字典中该线程 |
| | | |
| | | // tcpClient = null; |
| | | // socketClient = null; |
| | | // break; |
| | | //} |
| | | //byte[] buf = new byte[length]; |
| | | //Array.Copy(arrMsgRec, buf, length); |
| | | //lock (tcpClient.m_Buffer) |
| | | //{ |
| | | // var tcpDataString = System.Text.Encoding.UTF8.GetString(arrMsgRec, 0, length); |
| | | // if (!string.IsNullOrEmpty(tcpDataString)) |
| | | // { |
| | | // ReceiveEvent?.Invoke(tcpDataString); |
| | | // } |
| | | if (!string.IsNullOrEmpty(tcpDataString)) |
| | | { |
| | | MainPage.Log($"局域网tcp数据接收"); |
| | | Control.Ins.ConvertReceiveData(arrMsgRec, null); |
| | | |
| | | // MainPage.Log($"接收服务端数据:{tcpDataString}"); |
| | | //} |
| | | } |
| | | } |
| | | |
| | | }); |
| | | //receiveThread.IsBackground = true; |
| | | receiveThread.Start(); |
| | | } |
| | | } |
| | | |
| | |
| | | { |
| | | MainPage.Log($"0001 tcpDataString:\r\n {tcpBodyDataString}"); |
| | | var tcpDataObj = Control.Ins.AnalysisReceiveData(tcpBodyDataString, null); |
| | | if (tcpDataObj.BodyDataString == null) |
| | | if (tcpDataObj==null || tcpDataObj.BodyDataString == null) |
| | | { |
| | | return; |
| | | } |
| | |
| | | //mqtt连接数据读取 A协议网络设备信息读取回复 处理 |
| | | if (((IPEndPoint)packet.RemoteEndPoint).Port == 8585) |
| | | { |
| | | MainPage.Log($"局域网udp信息"); |
| | | Control.Ins.ConvertReceiveData(bytes, ((IPEndPoint)packet.RemoteEndPoint).Address.ToString()); |
| | | } |
| | | else if (((IPEndPoint)packet.RemoteEndPoint).Port == 6000)//处理bus 6000端口的数据 |
| | |
| | | var requestJson = HttpUtil.GetSignRequestJson(requestObj); |
| | | return HttpUtil.RequestHttpsPost(NewAPI.API_POST_Member_ForgetPwd, requestJson); |
| | | } |
| | | /// <summary> |
| | | /// 修改密码 |
| | | /// </summary> |
| | | /// <param name="loginPwd"></param> |
| | | /// <param name="loginNewPwd"></param> |
| | | /// <returns></returns> |
| | | public ResponsePackNew UpdataPassword(string loginPwd,string loginNewPwd) |
| | | { |
| | | Dictionary<string, object> d = new Dictionary<string, object>(); |
| | | d.Add("loginPwd", loginPwd); |
| | | d.Add("loginNewPwd", loginNewPwd); |
| | | var requestJson = HttpUtil.GetSignRequestJson(d); |
| | | return HttpUtil.RequestHttpsPost(NewAPI.API_POST_Update_Pwd, requestJson); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 验证验证码 |
| | |
| | | /// 设置第三方设备绑定的住宅 |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | public ResponsePackNew Set3tyIotFunctionToHouse(string deviceId,string homeId, string companyId) |
| | | public ResponsePackNew Set3tyIotFunctionToHouse(List<string> deviceIds,string homeId, string companyId) |
| | | { |
| | | Dictionary<string, object> d = new Dictionary<string, object>(); |
| | | d.Add("deviceId", deviceId); |
| | | d.Add("deviceIds", deviceIds); |
| | | d.Add("homeId", homeId); |
| | | d.Add("companyId", companyId); |
| | | var requestJson = HttpUtil.GetSignRequestJson(d); |
| | |
| | | { |
| | | return sceneImageInfo.defaultIconName; |
| | | } |
| | | else |
| | | { |
| | | return "Intelligence/Gallery/scenebg1.png"; |
| | | } |
| | | return image; |
| | | } |
| | | } |
| | | set |
| | |
| | | /// <summary> |
| | | /// 图片url |
| | | /// </summary> |
| | | public string authrBandIconUrl; |
| | | public string authBrandIconUrl; |
| | | /// <summary> |
| | | /// 认证授权地址 |
| | | /// </summary> |
| | |
| | | <Compile Include="$(MSBuildThisFileDirectory)UI\UI2\4-PersonalCenter\AddFunction\Iot_BrandFunctionListPage.cs" />
|
| | | <Compile Include="$(MSBuildThisFileDirectory)UI\UI2\4-PersonalCenter\AddFunction\Iot_AuthorizedPage.cs" />
|
| | | <Compile Include="$(MSBuildThisFileDirectory)UI\UI2\4-PersonalCenter\AddFunction\Iot_SupportSpkListPage.cs" />
|
| | | <Compile Include="$(MSBuildThisFileDirectory)DAL\DriverLayer\Control_Tcp.cs" />
|
| | | </ItemGroup>
|
| | | <ItemGroup>
|
| | | <Folder Include="$(MSBuildThisFileDirectory)Entity\Device\" />
|
| | |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 自定义日志输出 |
| | | /// </summary> |
| | | public static void Log(string tag,string msg) |
| | | { |
| | | #if DEBUG |
| | | Console.WriteLine($"{tag}-->{msg}"); |
| | | #endif |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | /// <param name="updataFunction"></param> |
| | | public void UpdataStates(Function updataFunction, FrameLayout view, VerticalScrolViewLayout scrolView, Room room = null) |
| | | { |
| | | if (view == null || scrolView == null || updataFunction == null) |
| | | { |
| | | return; |
| | | } |
| | | Application.RunOnMainThread((() => |
| | | { |
| | | try |
| | | { |
| | | if (view == null || scrolView == null || updataFunction == null) |
| | | { |
| | | return; |
| | | } |
| | | if (!scrolView.ScrollEnabled) |
| | | { |
| | | return; |
| | |
| | | { |
| | | var btnHumidityIcon = new Button() |
| | | { |
| | | X = Application.GetRealWidth(51), |
| | | X = Application.GetRealWidth(110), |
| | | Y = Application.GetRealHeight(66), |
| | | Width = Application.GetMinRealAverage(16), |
| | | Height = Application.GetMinRealAverage(16), |
| | |
| | | bodyDiv.AddChidren(btnHumidityIcon); |
| | | var btnHumidityValues = new TextButton() |
| | | { |
| | | X = Application.GetRealWidth(70), |
| | | X = Application.GetRealWidth(130), |
| | | Y = Application.GetRealHeight(64), |
| | | Height = Application.GetRealHeight(18), |
| | | TextColor = 0xFF161616, |
| | |
| | | |
| | | Button btnTempIcon = new Button() |
| | | { |
| | | X = Application.GetRealWidth(110), |
| | | X = Application.GetRealWidth(51), |
| | | Y = Application.GetRealHeight(66), |
| | | Width = Application.GetMinRealAverage(17), |
| | | Height = Application.GetMinRealAverage(17), |
| | |
| | | |
| | | var btnTempValues = new TextButton() |
| | | { |
| | | X = Application.GetRealWidth(130), |
| | | X = Application.GetRealWidth(70), |
| | | Y = Application.GetRealHeight(64), |
| | | Height = Application.GetRealHeight(18), |
| | | TextColor = 0xFF161616, |
| | |
| | | using Shared; |
| | | using HDL_ON.Entity; |
| | | using HDL_ON.DAL.Server; |
| | | using HDL_ON.UI.CSS; |
| | | |
| | | namespace HDL_ON.UI |
| | | { |
| | |
| | | UnsubscribeAsync3tyIotbind(); |
| | | Application.RunOnMainThread(() => |
| | | { |
| | | http.Search3tyIotDevice(brand_Iot.companyId); |
| | | //http.Search3tyIotDevice(brand_Iot.companyId); |
| | | boudedAction?.Invoke(); |
| | | dd.Close(); |
| | | |
| | | |
| | | |
| | | { |
| | | Dialog dialog = new Dialog() |
| | | { |
| | | BackgroundColor = CSS_Color.DialogTransparentColor1, |
| | | }; |
| | | |
| | | FrameLayout contentView = new FrameLayout() |
| | | { |
| | | Gravity = Gravity.Center, |
| | | Width = Application.GetRealWidth(305), |
| | | Height = Application.GetRealHeight(180), |
| | | BackgroundColor = CSS.CSS_Color.MainBackgroundColor, |
| | | BorderColor = 0x00000000, |
| | | BorderWidth = 0, |
| | | Radius = (uint)Application.GetMinRealAverage(10), |
| | | }; |
| | | dialog.AddChidren(contentView); |
| | | |
| | | Button btnTitle = new Button() |
| | | { |
| | | Gravity = Gravity.CenterHorizontal, |
| | | Y = Application.GetRealHeight(10), |
| | | Height = Application.GetRealHeight(38), |
| | | TextAlignment = TextAlignment.Center, |
| | | IsBold = true, |
| | | TextColor = 0xFF222222, |
| | | TextSize = CSS_FontSize.SubheadingFontSize, |
| | | TextID = StringId.Tip |
| | | }; |
| | | contentView.AddChidren(btnTitle); |
| | | |
| | | Button btnMsg = new Button() |
| | | { |
| | | Gravity = Gravity.CenterHorizontal, |
| | | Height = Application.GetRealHeight(70), |
| | | Y = Application.GetRealHeight(55), |
| | | TextAlignment = TextAlignment.TopCenter, |
| | | TextColor = CSS_Color.FirstLevelTitleColor, |
| | | TextSize = CSS_FontSize.SubheadingFontSize, |
| | | Padding = new Padding(0, Application.GetRealWidth(16), 0, Application.GetRealWidth(16)), |
| | | Text = "账户绑定成功,您可以继续完成设备关联操作", |
| | | IsMoreLines = true, |
| | | }; |
| | | contentView.AddChidren(btnMsg); |
| | | if(Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnMsg.Text = "Account binding is successful.You can continue to complete the device association operation"; |
| | | } |
| | | |
| | | Button btnLine = new Button() |
| | | { |
| | | Y = Application.GetRealHeight(125), |
| | | Height = Application.GetRealHeight(1), |
| | | BackgroundColor = CSS.CSS_Color.DividingLineColor, |
| | | }; |
| | | contentView.AddChidren(btnLine); |
| | | |
| | | Button btnConfirm = new Button() |
| | | { |
| | | Y = btnLine.Bottom, |
| | | Height = Application.GetRealHeight(55), |
| | | TextAlignment = TextAlignment.Center, |
| | | TextColor = CSS_Color.MainColor, |
| | | TextSize = CSS_FontSize.SubheadingFontSize, |
| | | SelectedTextColor = CSS_Color.MainBackgroundColor, |
| | | SelectedBackgroundColor = CSS_Color.MainColor, |
| | | TextID = StringId.Confirm, |
| | | }; |
| | | btnConfirm.SetCornerWithSameRadius(Application.GetMinRealAverage(10), HDLUtils.RectCornerBottomLeft); |
| | | btnConfirm.SetCornerWithSameRadius(Application.GetMinRealAverage(10), HDLUtils.RectCornerBottomRight); |
| | | contentView.AddChidren(btnConfirm); |
| | | |
| | | dialog.Show(); |
| | | |
| | | btnConfirm.MouseDownEventHandler += (sender, e) => |
| | | { |
| | | btnConfirm.IsSelected = true; |
| | | }; |
| | | btnConfirm.MouseUpEventHandler += (sender, e) => |
| | | { |
| | | dialog.Close(); |
| | | }; |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | }); |
| | | }; |
| | | SubscribeAsync3tyIotbind(); |
| | |
| | | }) |
| | | { IsBackground = true }.Start(); |
| | | } |
| | | /// <summary> |
| | | /// 搜索第三方设备 |
| | | /// </summary> |
| | | private void SearchDevice() |
| | | { |
| | | var pack = http.Search3tyIotDevice(brand_Iot.companyId); |
| | | if(pack!= null) |
| | | { |
| | | |
| | | } |
| | | } |
| | | ///// <summary> |
| | | ///// 搜索第三方设备 |
| | | ///// </summary> |
| | | //private void SearchDevice() |
| | | //{ |
| | | // var pack = http.Search3tyIotDevice(brand_Iot.companyId); |
| | | // if(pack!= null) |
| | | // { |
| | | // } |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// 获取第三方功能列表 |
| | |
| | | |
| | | FrameLayout contentView; |
| | | |
| | | FrameLayout optionView; |
| | | |
| | | |
| | | IntegratedBrand_Iot brand_Iot; |
| | |
| | | TextColor = CSS_Color.FirstLevelTitleColor, |
| | | Padding = new Padding(12, Application.GetRealWidth(16), 12, Application.GetRealWidth(16)), |
| | | TextSize = CSS_FontSize.TextFontSize, |
| | | Text = "默认将第三方品牌的设备全部关联到On Pro上,您也可以通过下方的开关按键,进行选择性关联。", |
| | | Text = "*您可以将第三方品牌的设备关联到On Pro您当前的住宅上。", |
| | | IsMoreLines = true, |
| | | TextAlignment = TextAlignment.CenterLeft, |
| | | }; |
| | | bodyView.AddChidren(btnTipText); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnTipText.Text = "*You can associate third-party branded devices with on Pro's current home."; |
| | | } |
| | | |
| | | contentView = new FrameLayout() |
| | | { |
| | |
| | | { |
| | | try |
| | | { |
| | | var pack0 = http.Search3tyIotDevice(brand_Iot.companyId); |
| | | if(pack0 != null) |
| | | { |
| | | |
| | | } |
| | | var pack = http.Get3tyIotDeviceFunctionList(brand_Iot.companyId); |
| | | if (pack != null) |
| | | { |
| | |
| | | }); |
| | | } |
| | | }) { IsBackground = true }.Start(); |
| | | |
| | | |
| | | optionView = new FrameLayout() |
| | | { |
| | | Y = Application.GetRealHeight(667 - 80), |
| | | Height = Application.GetRealHeight(90), |
| | | Radius = (uint)Application.GetRealWidth(22), |
| | | Visible = false, |
| | | }; |
| | | bodyView.AddChidren(optionView); |
| | | |
| | | |
| | | var btnComfirm = new Button() |
| | | { |
| | | Gravity = Gravity.CenterHorizontal, |
| | | Y = Application.GetRealHeight(14), |
| | | Width = Application.GetRealWidth(164), |
| | | Height = Application.GetRealHeight(44), |
| | | TextAlignment = TextAlignment.Center, |
| | | BackgroundColor = CSS_Color.MainColor, |
| | | TextColor = CSS_Color.MainBackgroundColor, |
| | | TextSize = CSS_FontSize.SubheadingFontSize, |
| | | TextID = StringId.Confirm, |
| | | Radius = (uint)Application.GetRealHeight(22) |
| | | }; |
| | | optionView.AddChidren(btnComfirm); |
| | | btnComfirm.MouseUpEventHandler = (sender, e) => { |
| | | |
| | | var pack = http.Set3tyIotFunctionToHouse(optionList, DB_ResidenceData.Instance.CurrentRegion.id, brand_Iot.companyId); |
| | | if (pack != null) |
| | | { |
| | | if (pack.Code == StateCode.SUCCESS) |
| | | { |
| | | btnComfirm.Visible = false; |
| | | } |
| | | } |
| | | //var pack = http.Set3tyIotFunctionToHouse(function.deviceId, "0", brand_Iot.companyId); |
| | | //if (pack != null) |
| | | //{ |
| | | // if (pack.Code == StateCode.SUCCESS) |
| | | // { |
| | | // btnName.IsSelected = btnIcon.IsSelected = btnCheckIcon.IsSelected = false; |
| | | // } |
| | | //} |
| | | |
| | | }; |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | var btnbg = new Button() |
| | | { |
| | | UnSelectedImagePath = "Collection/Functionbg.png", |
| | | SelectedImagePath = "Collection/FunctionOnbg.png", |
| | | SelectedImagePath = "Collection/Functionbg.png", |
| | | Tag = function.sid |
| | | }; |
| | | functionView.AddChidren(btnbg); |
| | | LoadDeviceFunctionDiv(functionView, function,btnbg); |
| | | LoadDeviceFunctionDiv(functionView, function); |
| | | index++; |
| | | |
| | | |
| | |
| | | Text = "没有任何设备" |
| | | }; |
| | | view.AddChidren(btnNoCollectionTip); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnNoCollectionTip.Text = "No equipment"; |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | |
| | | deviceFunctionView.AddChidren(new Button { Height = Application.GetRealHeight(30) }); |
| | | #endregion |
| | | |
| | | |
| | | deviceFunctionView.AddChidren(new Button { |
| | | Height = Application.GetRealHeight(90), |
| | | }); |
| | | |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 加载功能控制卡片 |
| | | /// </summary> |
| | | void LoadDeviceFunctionDiv(FrameLayout view, Function function,Button btnBg) |
| | | void LoadDeviceFunctionDiv(FrameLayout view, Function function) |
| | | { |
| | | try |
| | | { |
| | | |
| | | |
| | | var btnCheckIcon = new Button() |
| | | { |
| | | X = Application.GetRealWidth(22), |
| | | Y = Application.GetRealHeight(16), |
| | | Width = Application.GetRealWidth(21), |
| | | Height = Application.GetRealWidth(21), |
| | | UnSelectedImagePath = "Public/IotCheckIcon.png", |
| | | SelectedImagePath = "Public/IotCheckOnIcon.png", |
| | | }; |
| | | view.AddChidren(btnCheckIcon); |
| | | |
| | | Button btnIcon; |
| | | btnIcon = new Button() |
| | | { |
| | |
| | | Button btnClick = new Button(); |
| | | view.AddChidren(btnClick); |
| | | btnClick.MouseUpEventHandler = (sender, e) => { |
| | | function.collect = !function.collect; |
| | | if (function.collect) |
| | | btnCheckIcon.IsSelected = function.collect = !function.collect; |
| | | if (optionList.Contains(function.deviceId)) |
| | | { |
| | | var pack = http.Set3tyIotFunctionToHouse(function.deviceId, DB_ResidenceData.Instance.CurrentRegion.id,brand_Iot.companyId); |
| | | if (pack != null) |
| | | { |
| | | if(pack.Code == StateCode.SUCCESS) |
| | | { |
| | | btnName.IsSelected = btnIcon.IsSelected = btnBg.IsSelected = true; |
| | | } |
| | | } |
| | | optionList.Remove(function.deviceId); |
| | | } |
| | | else |
| | | { |
| | | btnName.IsSelected = btnIcon.IsSelected = btnBg.IsSelected = false; |
| | | var pack = http.Set3tyIotFunctionToHouse(function.deviceId, "0", brand_Iot.companyId); |
| | | if (pack != null) |
| | | { |
| | | if (pack.Code == StateCode.SUCCESS) |
| | | { |
| | | btnName.IsSelected = btnIcon.IsSelected = btnBg.IsSelected = false; |
| | | } |
| | | } |
| | | optionList.Add(function.deviceId); |
| | | } |
| | | |
| | | optionView.Visible = true; |
| | | }; |
| | | |
| | | if (function.homeId == DB_ResidenceData.Instance.CurrentRegion.id ) |
| | | { |
| | | btnCheckIcon.IsSelected = true; |
| | | optionList.Add(function.deviceId); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log("homepage LoadControlView error : " + ex.Message); |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// 记录需要操作的列表 |
| | | /// </summary> |
| | | private List<string> optionList = new List<string>(); |
| | | |
| | | |
| | | void NotListTipView() |
| | |
| | | BorderWidth = 0, |
| | | Text = "查看设备支持范围" |
| | | }; |
| | | contentView.AddChidren(btnAdd); |
| | | //contentView.AddChidren(btnAdd); |
| | | btnAdd.MouseUpEventHandler = (sender, e) => |
| | | { |
| | | //var page = new AddThirdPartyBrandListpage(brandList); |
| | |
| | | TextAlignment = TextAlignment.CenterLeft, |
| | | }; |
| | | bodyView.AddChidren(btnTipText); |
| | | |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnTipText.Text = "Synchronize your devices on the third-party platform to on Pro for control by binding the third-party platform account to the cloud connection"; |
| | | } |
| | | |
| | | |
| | | contentView = new VerticalScrolViewLayout() |
| | | { |
| | | Y = Application.GetRealHeight(150), |
| | |
| | | |
| | | } |
| | | /// <summary> |
| | | /// 获取绑定列表 |
| | | /// 获取列表 |
| | | /// </summary> |
| | | void GetBindList() |
| | | { |
| | |
| | | }; |
| | | row.AddChidren(btnName); |
| | | //下载第三方品牌icon |
| | | ImageUtlis.Current.Load3tyBrandIconImages(brand.brandName, brand.authrBandIconUrl, btnIcon); |
| | | |
| | | btnName.MouseUpEventHandler = (sender, e) => { |
| | | ImageUtlis.Current.Load3tyBrandIconImages(brand.brandName, brand.authBrandIconUrl, btnIcon); |
| | | EventHandler<MouseEventArgs> eventHandler = (sender, e) => { |
| | | if (brand.hasAuthorization) |
| | | { |
| | | Action unboundAction = () => |
| | |
| | | MainPage.BasePageView.PageIndex = MainPage.BasePageView.ChildrenCount - 1; |
| | | } |
| | | }; |
| | | |
| | | btnRight.MouseUpEventHandler = eventHandler; |
| | | row.MouseUpEventHandler = eventHandler; |
| | | btnName.MouseUpEventHandler = eventHandler; |
| | | btnBindTip.MouseUpEventHandler = eventHandler; |
| | | } |
| | | |
| | | } |
| | |
| | | public void LoadPage(IntegratedBrand_Iot brand_Iot) |
| | | { |
| | | |
| | | |
| | | new TopViewDiv(bodyView, Language.StringByID(StringId.Bind3thIotAccount)).LoadTopView(CSS_Color.MainBackgroundColor); |
| | | new TopViewDiv(bodyView, brand_Iot.brandName).LoadTopView(CSS_Color.MainBackgroundColor); |
| | | |
| | | bodyView.BackgroundColor = CSS_Color.MainBackgroundColor; |
| | | |
| | |
| | | Text = "关于账号绑定的声明" |
| | | }; |
| | | contentView.AddChidren(btnTipTitle); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnTipTitle.Text = "Statement on account binding"; |
| | | } |
| | | |
| | | var btnTipText = new Button() |
| | | { |
| | |
| | | "如需终止以上信息的收集与处理,您可以在“我的”> “绑定第三方账户”>“解除”" |
| | | }; |
| | | contentView.AddChidren(btnTipText); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnTipText.Text = $"account binding brand: {brand_Iot.brandName} (hereinafter referred to as the third party brand)" + "\r\n" + "\r\n" + |
| | | "After you bind the account of the third-party brand, you will authorize 'on Pro' to use your account of the third-party to jointly manage the device. On Pro will also automatically synchronize the device you added in the third-party brand." + "\r\n" + "\r\n" + |
| | | "To realize the device control function, this application will obtain the following data from a third party:" + "\r\n" + "\r\n" + |
| | | "1. List of some devices added on the third-party brand for intelligent control in on Pro;" + "\r\n" + "\r\n" + |
| | | "2. Equipment and network information, including equipment identifier, MAC address and equipment serial number, is used to identify the currently working equipment and perform equipment control functions." + "\r\n" + "\r\n" + |
| | | "If you do not agree with our collection of the above information, you will not be able to manage third-party branded devices." + "\r\n" + "\r\n" + |
| | | "To terminate the collection and processing of the above information, you can click my > bind third party account > cancel"; |
| | | } |
| | | |
| | | |
| | | var optionView = new FrameLayout() |
| | |
| | | TextAlignment = TextAlignment.Center, |
| | | TextColor = CSS_Color.MainColor, |
| | | TextSize = CSS_FontSize.SubheadingFontSize, |
| | | Text = "返回", |
| | | TextID= StringId.fanhui, |
| | | Radius = (uint)Application.GetRealHeight(22) |
| | | }; |
| | | optionView.AddChidren(btnCannel); |
| | |
| | | Radius = (uint)Application.GetRealHeight(22) |
| | | }; |
| | | optionView.AddChidren(btnComfirm); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnComfirm.Text = "Consent authorization"; |
| | | } |
| | | |
| | | |
| | | if (!brand_Iot.hasAuthorization) |
| | |
| | | MainPage.BasePageView.PageIndex = MainPage.BasePageView.ChildrenCount - 1; |
| | | }; |
| | | |
| | | var page = new Iot_AuthorizedPage(brand_Iot,action); |
| | | page.LoadView(); |
| | | var page2 = new Iot_AuthorizedPage(brand_Iot,action); |
| | | page2.LoadView(); |
| | | |
| | | |
| | | |
| | |
| | | else |
| | | { |
| | | btnComfirm.Text = "解除授权"; |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnComfirm.Text = "Cancel authorization"; |
| | | } |
| | | btnComfirm.MouseUpEventHandler = (sender, e) => |
| | | { |
| | | Dialog dialog = new Dialog() |
| | |
| | | BackgroundColor = CSS_Color.DialogTransparentColor1, |
| | | }; |
| | | |
| | | FrameLayout contentView = new FrameLayout() |
| | | FrameLayout contentView2 = new FrameLayout() |
| | | { |
| | | Gravity = Gravity.Center, |
| | | Width = Application.GetRealWidth(305), |
| | |
| | | BorderWidth = 0, |
| | | Radius = (uint)Application.GetMinRealAverage(10), |
| | | }; |
| | | dialog.AddChidren(contentView); |
| | | dialog.AddChidren(contentView2); |
| | | |
| | | Button btnMsg = new Button() |
| | | { |
| | |
| | | Text = "撤销授权后,该品牌关联在On Pro中的设备将全部被解绑,相关使用信息合设备值也将失效", |
| | | IsMoreLines = true, |
| | | }; |
| | | contentView.AddChidren(btnMsg); |
| | | contentView2.AddChidren(btnMsg); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnMsg.Text = "After the authorization is revoked, all the devices associated with the brand in on Pro will be unbound, and the relevant use information and device value will also become invalid"; |
| | | } |
| | | |
| | | Button btnLine = new Button() |
| | | { |
| | |
| | | Height = Application.GetRealHeight(1), |
| | | BackgroundColor = CSS.CSS_Color.DividingLineColor, |
| | | }; |
| | | contentView.AddChidren(btnLine); |
| | | contentView2.AddChidren(btnLine); |
| | | |
| | | Button btnConfirm = new Button() |
| | | { |
| | |
| | | SelectedBackgroundColor = CSS_Color.MainColor, |
| | | Text = "确定撤回授权", |
| | | }; |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | btnConfirm.Text = "Confirm to withdraw authorization"; |
| | | } |
| | | btnConfirm.SetCornerWithSameRadius(Application.GetMinRealAverage(10), HDLUtils.RectCornerBottomLeft); |
| | | btnConfirm.SetCornerWithSameRadius(Application.GetMinRealAverage(10), HDLUtils.RectCornerBottomRight); |
| | | contentView.AddChidren(btnConfirm); |
| | | contentView2.AddChidren(btnConfirm); |
| | | |
| | | dialog.Show(); |
| | | |
| | | btnConfirm.MouseDownEventHandler += (sender, e) => |
| | | btnConfirm.MouseDownEventHandler += (sender2, e2) => |
| | | { |
| | | btnConfirm.IsSelected = true; |
| | | }; |
| | | btnConfirm.MouseUpEventHandler += (sender, e) => |
| | | btnConfirm.MouseUpEventHandler += (sender2, e2) => |
| | | { |
| | | var http = new HttpServerRequest(); |
| | | var waitPage = new Loading(); |
| | |
| | | else |
| | | { |
| | | dialog.Close(); |
| | | new Alert("", "操作失败", "").Show(); |
| | | if (Language.CurrentLanguage != "Chinese") |
| | | { |
| | | new Alert("", "Operation failed", "").Show(); |
| | | } |
| | | else |
| | | { |
| | | new Alert("", "操作失败", "").Show(); |
| | | } |
| | | } |
| | | } |
| | | catch { } |
| | |
| | | { |
| | | EventHandler<MouseEventArgs> eventHandler = (sender, e) => |
| | | { |
| | | var page = new ResetPasswordOptionPage(); |
| | | MainPage.BasePageView.AddChidren(page); |
| | | page.LoadPage(); |
| | | //var page = new ResetPasswordOptionPage(); |
| | | //MainPage.BasePageView.AddChidren(page); |
| | | //page.LoadPage(); |
| | | //MainPage.BasePageView.PageIndex = MainPage.BasePageView.ChildrenCount - 1; |
| | | |
| | | var vcp = new ResetPasswordPage(); |
| | | MainPage.BasePageView.AddChidren(vcp); |
| | | vcp.LoadPage(); |
| | | MainPage.BasePageView.PageIndex = MainPage.BasePageView.ChildrenCount - 1; |
| | | |
| | | }; |
| | | btnResetPasswordRight.MouseUpEventHandler = eventHandler; |
| | | btnResetPasswordText.MouseUpEventHandler = eventHandler; |
| | |
| | | |
| | | #region 控件View |
| | | /// <summary> |
| | | /// 原密码文本框 |
| | | /// </summary> |
| | | EditText etOldPwd; |
| | | |
| | | /// <summary> |
| | | /// 密码文本框 |
| | | /// </summary> |
| | | EditText etPassword; |
| | |
| | | |
| | | new TopViewDiv(bodyView, Language.StringByID(StringId.ModifyPassword)).LoadTopView(backAction); |
| | | |
| | | |
| | | #region 原密码 |
| | | FrameLayout oldPwdView = new FrameLayout() |
| | | { |
| | | Y = Application.GetRealHeight(64), |
| | | Height = Application.GetRealHeight(50), |
| | | BackgroundColor = CSS_Color.MainBackgroundColor, |
| | | }; |
| | | bodyView.AddChidren(oldPwdView); |
| | | |
| | | Button btnOldPwdTitle = new Button() |
| | | { |
| | | X = Application.GetRealWidth(16), |
| | | Width = Application.GetRealWidth(180), |
| | | TextColor = CSS_Color.FirstLevelTitleColor, |
| | | TextSize = CSS_FontSize.SubheadingFontSize, |
| | | TextAlignment = TextAlignment.CenterLeft, |
| | | Text = Language.StringByID(StringId.OriginalPassword) + ":" |
| | | }; |
| | | oldPwdView.AddChidren(btnOldPwdTitle); |
| | | |
| | | etOldPwd = new EditText() |
| | | { |
| | | Width = Application.GetRealWidth(359), |
| | | TextColor = CSS_Color.PromptingColor1, |
| | | TextSize = CSS_FontSize.TextFontSize, |
| | | SecureTextEntry = true, |
| | | TextAlignment = TextAlignment.CenterRight, |
| | | Foucs = true |
| | | }; |
| | | oldPwdView.AddChidren(etOldPwd); |
| | | oldPwdView.AddChidren(new LineView(oldPwdView.Height)); |
| | | #endregion |
| | | |
| | | |
| | | #region 新密码 |
| | | FrameLayout rowView = new FrameLayout() |
| | | { |
| | | Y = Application.GetRealHeight(64), |
| | | Y = oldPwdView.Bottom , |
| | | Height = Application.GetRealHeight(50), |
| | | BackgroundColor = CSS_Color.MainBackgroundColor, |
| | | }; |
| | |
| | | public partial class ResetPasswordPage |
| | | { |
| | | |
| | | /// <summary> |
| | | /// 指定关闭页面个数 |
| | | /// </summary> |
| | | /// <param name="countPage"></param> |
| | | void ClosePageWithCount(int countPage) |
| | | { |
| | | //关闭多少个页面 |
| | | for (int i = 0; i < countPage; i++) |
| | | { |
| | | MainPage.BasePageView.GetChildren(MainPage.BasePageView.ChildrenCount - 1).RemoveFromParent(); |
| | | } |
| | | } |
| | | ///// <summary> |
| | | ///// 指定关闭页面个数 |
| | | ///// </summary> |
| | | ///// <param name="countPage"></param> |
| | | //void ClosePageWithCount(int countPage) |
| | | //{ |
| | | // //关闭多少个页面 |
| | | // for (int i = 0; i < countPage; i++) |
| | | // { |
| | | // MainPage.BasePageView.GetChildren(MainPage.BasePageView.ChildrenCount - 1).RemoveFromParent(); |
| | | // } |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="password"></param> |
| | | void ResetPassword(string password) |
| | | void ResetPassword(string oldPwd, string password) |
| | | { |
| | | |
| | | //校验密码是否符合要求 |
| | |
| | | try |
| | | { |
| | | // 忘记密码 |
| | | var resultObj = new HttpServerRequest().ForgetPassword(account, password, verCode, isPhone); |
| | | var resultObj = new HttpServerRequest().UpdataPassword(oldPwd, password); |
| | | if (resultObj.Code == StateCode.SUCCESS) |
| | | { |
| | | Application.RunOnMainThread(() => |
| | | { |
| | | Utlis.ShowTip(Language.StringByID(StringId.PasswordChangeSuccessfully)); |
| | | ClosePageWithCount(2); |
| | | this.RemoveFromParent(); |
| | | }); |
| | | } |
| | | else |
| | |
| | | { |
| | | if (btnReset.IsSelected) |
| | | { |
| | | ResetPassword(etPassword.Text.ToString()); |
| | | ResetPassword(etOldPwd.Text.Trim().ToString(), etPassword.Text.ToString()); |
| | | } |
| | | }; |
| | | } |
| | |
| | | this.RefreshNowDeviceStatuMemory(this.device); |
| | | //刷新界面状态 |
| | | this.RefreshFormStatu(); |
| | | controlTime = DateTime.Now; |
| | | //读取状态 |
| | | new System.Threading.Thread(() => |
| | | { |
| | |
| | | { |
| | | if (controlTime == DateTime.MinValue) |
| | | { |
| | | |
| | | |
| | | } |
| | | else if (controlTime.AddSeconds(2) < DateTime.Now) |
| | | { |
| | |
| | | temp = (int)Convert.ToDouble(device.GetAttrState(FunctionAttributeKey.SetTemp).Replace(",", ".")); |
| | | if (temp <= 0) |
| | | { |
| | | //默认值改成16,2022年06月10日10:03:19 成甫要求的 |
| | | temp = 16; |
| | | device.SetAttrState(FunctionAttributeKey.SetTemp, temp.ToString()); |
| | | } |
| | |
| | | { |
| | | //btnIndoorTemp.Text = Language.StringByID(StringId.IndoorTemp) + Convert.ToInt32(Convert.ToDouble(device.GetAttrState(FunctionAttributeKey.RoomTemp).Replace(",", "."))) + "°C" |
| | | // + Language.StringByID(StringId.Humidity) + Convert.ToInt32(Convert.ToDouble(device.GetAttrState("room_humidity").Replace(", ", "."))) + "%"; |
| | | btnTempValues.Text = Convert.ToInt32(Convert.ToDouble(device.GetAttrState(FunctionAttributeKey.RoomTemp).Replace(",", "."))) + "°C"; |
| | | btnHumidityValues.Text = Convert.ToInt32(Convert.ToDouble(device.GetAttrState("room_humidity").Replace(", ", "."))) + "%"; |
| | | btnTempValues.Text = Convert.ToDouble(device.GetAttrState(FunctionAttributeKey.RoomTemp).Replace(",", ".")) + "°C"; |
| | | btnHumidityValues.Text = Convert.ToDouble(device.GetAttrState("room_humidity").Replace(", ", ".")) + "%"; |
| | | |
| | | btnMode.UnSelectedImagePath = acFunction.GetModeIconPath(device.GetAttrState(FunctionAttributeKey.Mode)); |
| | | btnModeText.Text = acFunction.GetModeAttrText(device.GetAttrState(FunctionAttributeKey.Mode)); |
| | | |
| | | temp = Convert.ToInt32(Convert.ToDouble(device.GetAttrState(FunctionAttributeKey.SetTemp).Replace(",", "."))); |
| | | |
| | | |