diff --git a/BPASmartClient.Helper/HttpRequestHelper.cs b/BPASmartClient.Helper/HttpRequestHelper.cs
new file mode 100644
index 00000000..dd191933
--- /dev/null
+++ b/BPASmartClient.Helper/HttpRequestHelper.cs
@@ -0,0 +1,328 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+namespace BPASmartClient.Helper
+{
+ ///
+ /// 该类实现客户端http 同步请求
+ /// 支持环境 -.net4.0/-.net4.5
+ /// 创建人:奉友福
+ ///
+ public class HttpRequestHelper
+ {
+ #region 私有变量
+ #endregion
+
+ #region 公用函数
+ ///
+ /// GET 同步请求
+ /// 创建人:奉友福
+ /// 创建时间:2020-11-19
+ ///
+ /// 请求地址
+ /// 超时时间设置,默认5秒
+ public static string HttpGetRequest(string url, int _timeout = 2000)
+ {
+ string resultData = string.Empty;
+
+ try
+ {
+ WebClient wc = new WebClient();
+ byte[] bytes = wc.DownloadData(url);
+ string s = Encoding.UTF8.GetString(bytes);
+ return s;
+ }
+ catch (Exception e)
+ {
+ throw e;
+ }
+ return "";
+
+ try
+ {
+ var getrequest = HttpRequest.GetInstance().CreateHttpRequest(url, "GET", _timeout);
+ var getreponse = getrequest.GetResponse() as HttpWebResponse;
+ resultData = HttpRequest.GetInstance().GetHttpResponse(getreponse, "GET");
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ return resultData;
+ }
+ ///
+ /// POST 同步请求
+ /// 创建人:奉友福
+ /// 创建时间:2020-11-19
+ ///
+ /// 请求地址
+ /// 请求数据
+ ///
+ public static string HttpPostRequest(string url, string PostJsonData, int _timeout = 2000)
+ {
+ string resultData = string.Empty;
+ try
+ {
+ var postrequest = HttpRequest.GetInstance().CreateHttpRequest(url, "POST", _timeout, PostJsonData);
+ var postreponse = postrequest.GetResponse() as HttpWebResponse;
+ resultData = HttpRequest.GetInstance().GetHttpResponse(postreponse, "POST");
+ }
+ catch (Exception ex)
+ {
+ return ex.Message;
+ }
+ return resultData;
+ }
+
+ public static string HttpDeleteRequest(string url, string PostJsonData, int _timeout = 10000)
+ {
+ string resultData = string.Empty;
+ try
+ {
+ var deleteRequest = HttpRequest.CreateDeleteHttpRequest(url, PostJsonData, _timeout);
+ var deleteReponse = deleteRequest.GetResponse() as HttpWebResponse;
+ using (StreamReader reader = new StreamReader(deleteReponse.GetResponseStream(), Encoding.GetEncoding("UTF-8")))
+ {
+ resultData = reader.ReadToEnd();
+ }
+ }
+ catch (Exception ex)
+ {
+ }
+ return resultData;
+ }
+
+ ///
+ /// GET 同步请求
+ ///
+ /// 地址
+ /// 头
+ /// 内容
+ ///
+ public static string GetHttpGetResponseWithHead(string url, HttpRequestHeader head, string headInfo)
+ {
+ HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
+ request.Method = "GET";
+ request.ContentType = "application/json;charset=UTF-8";
+ request.Timeout = 6000;
+ request.Headers.Set(head, headInfo);
+ StreamReader sr = null;
+ HttpWebResponse response = null;
+ Stream stream = null;
+ try
+ {
+ response = (HttpWebResponse)request.GetResponse();
+ stream = response.GetResponseStream();
+ sr = new StreamReader(stream, Encoding.GetEncoding("utf-8"));
+ var resultData = sr.ReadToEnd();
+ return resultData;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(url + " 访问失败:" + ex.Message);
+ //return ex.Message;
+ }
+ finally
+ {
+ if (response != null)
+ {
+ response.Dispose();
+ }
+ if (stream != null)
+ {
+ stream.Dispose();
+ }
+ if (sr != null)
+ {
+ sr.Dispose();
+ }
+ }
+ return null;
+ }
+
+
+
+ ///
+ /// Post请求带Token
+ /// 2021-2-2 by dulf
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string HttpPostResponseWithHead(string url, HttpRequestHeader head, string headInfo, string postParam, int Timeout = 6000)
+ {
+ string resultData = string.Empty;
+ try
+ {
+ var postrequest = WebRequest.Create(url) as HttpWebRequest;
+ postrequest.Timeout = Timeout;
+ postrequest.Method = "POST";
+ postrequest.ContentType = "application/json;charset=UTF-8";
+ postrequest.Headers.Set(head, headInfo);
+ byte[] data = Encoding.UTF8.GetBytes(postParam);
+ using (Stream reqStream = postrequest.GetRequestStream())
+ {
+ reqStream.Write(data, 0, data.Length);
+ var postreponse = postrequest.GetResponse() as HttpWebResponse;
+ resultData = HttpRequest.GetInstance().GetHttpResponse(postreponse, "POST");
+ reqStream.Close();
+ }
+ return resultData;
+ }
+ catch (Exception ex)
+ {
+ Console.Write("请求异常:" + ex.Message);
+ }
+ return "";
+ }
+ #endregion
+
+ }
+ ///
+ /// HTTP请求类
+ ///
+ public class HttpRequest
+ {
+ #region 私有变量
+ ///
+ /// http请求超时时间设置
+ /// 默认值:5秒
+ ///
+ private static int Timeout = 5000;
+ #endregion
+
+ #region 单例模式
+ private static HttpRequest _HttpRequest = null;
+ public static HttpRequest GetInstance()
+ {
+ if (_HttpRequest == null)
+ {
+ _HttpRequest = new HttpRequest();
+ }
+ return _HttpRequest;
+ }
+ private HttpRequest()
+ {
+
+ }
+ #endregion
+
+ #region 公用函数
+ ///
+ /// 函数名称:创建http请求
+ /// 创建人:奉友福
+ /// 创建时间:2020-11-19
+ /// 例如GET 请求: 地址 + "GET"
+ /// 例如POST请求: 地址 + "POST" + JSON
+ ///
+ /// http请求地址
+ /// http请求方式:GET/POST
+ /// http请求附带数据
+ ///
+ public HttpWebRequest CreateHttpRequest(string url, string requestType, int _timeout = 5000, params object[] strjson)
+ {
+ HttpWebRequest request = null;
+ const string get = "GET";
+ const string post = "POST";
+ Timeout = _timeout;
+ if (string.Equals(requestType, get, StringComparison.OrdinalIgnoreCase))
+ {
+ request = CreateGetHttpRequest(url);
+ }
+ if (string.Equals(requestType, post, StringComparison.OrdinalIgnoreCase))
+ {
+ request = CreatePostHttpRequest(url, strjson[0].ToString());
+ }
+ return request;
+ }
+ ///
+ /// http获取数据
+ ///
+ ///
+ ///
+ ///
+ public string GetHttpResponse(HttpWebResponse response, string requestType)
+ {
+ var resultData = string.Empty;
+ const string post = "POST";
+ string encoding = "UTF-8";
+ if (string.Equals(requestType, post, StringComparison.OrdinalIgnoreCase))
+ {
+ encoding = response.ContentEncoding;
+ if (encoding == null || encoding.Length < 1)
+ encoding = "UTF-8";
+ }
+ using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding)))
+ {
+ resultData = reader.ReadToEnd();
+ }
+ return resultData;
+ }
+ #endregion
+
+ #region 私有函数
+ ///
+ /// http+GET请求
+ ///
+ /// 请求地址
+ /// 请求结果
+ private static HttpWebRequest CreateGetHttpRequest(string url)
+ {
+ var getrequest = WebRequest.Create(url) as HttpWebRequest;
+ getrequest.Method = "GET";
+ getrequest.Timeout = Timeout;
+ getrequest.ContentType = "application/json;charset=UTF-8";
+ getrequest.Proxy = null;
+ getrequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+ return getrequest;
+ }
+ ///
+ /// http+POST请求
+ ///
+ /// 请求地址
+ ///
+ /// 请求结果
+ private static HttpWebRequest CreatePostHttpRequest(string url, string postData)
+ {
+ var postrequest = WebRequest.Create(url) as HttpWebRequest;
+ //postrequest.KeepAlive = false;
+ postrequest.Timeout = Timeout;
+ postrequest.Method = "POST";
+ postrequest.ContentType = "application/json;charset=UTF-8";
+ //postrequest.ContentLength = postData.Length;
+ //postrequest.AllowWriteStreamBuffering = false;
+ //StreamWriter writer = new StreamWriter(postrequest.GetRequestStream(), Encoding.UTF8);
+ //writer.Write(postData);
+ //writer.Flush();
+ byte[] data = Encoding.UTF8.GetBytes(postData);
+ using (Stream reqStream = postrequest.GetRequestStream())
+ {
+ reqStream.Write(data, 0, data.Length);
+ reqStream.Close();
+ }
+ return postrequest;
+ }
+
+ public static HttpWebRequest CreateDeleteHttpRequest(string url, string postJson, int _timeout = 5000)
+ {
+ var deleteRequest = WebRequest.Create(url) as HttpWebRequest;
+ deleteRequest.Timeout = _timeout;
+ deleteRequest.Method = "DELETE";
+ deleteRequest.ContentType = "application/json;charset=UTF-8";
+ byte[] data = Encoding.UTF8.GetBytes(postJson);
+ using (Stream reqStream = deleteRequest.GetRequestStream())
+ {
+ reqStream.Write(data, 0, data.Length);
+ reqStream.Close();
+ }
+ return deleteRequest;
+ }
+ #endregion
+ }
+}
diff --git a/BPASmartClient.Helper/Tools.cs b/BPASmartClient.Helper/Tools.cs
new file mode 100644
index 00000000..8d5379b3
--- /dev/null
+++ b/BPASmartClient.Helper/Tools.cs
@@ -0,0 +1,93 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.Helper
+{
+ ///
+ /// 工具
+ ///
+ public class Tools
+ {
+ ///
+ /// 对象Json序列
+ ///
+ /// 对象类型
+ /// 对象实例
+ ///
+ public static string JsonConvertTools(T obj)
+ {
+ string strvalue = JsonConvert.SerializeObject(obj);
+ return strvalue;
+ }
+
+ ///
+ /// 对象反Json序列
+ ///
+ /// 对象类型
+ /// 对象序列化json字符串
+ /// 返回对象实例
+ public static T JsonToObjectTools(string jsonstring)
+ {
+ T obj = JsonConvert.DeserializeObject(jsonstring);
+ return obj;
+ }
+
+ ///
+ /// DateTime --> long
+ ///
+ ///
+ ///
+ public static long ConvertDateTimeToLong(DateTime dt)
+ {
+ DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
+ TimeSpan toNow = dt.Subtract(dtStart);
+ long timeStamp = toNow.Ticks;
+ timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 4));
+ return timeStamp;
+ }
+
+ ///
+ /// long --> DateTime
+ ///
+ ///
+ ///
+ public static DateTime ConvertLongToDateTime(long d)
+ {
+ DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
+ long lTime = long.Parse(d + "0000");
+ TimeSpan toNow = new TimeSpan(lTime);
+ DateTime dtResult = dtStart.Add(toNow);
+ return dtResult;
+ }
+
+ ///
+ /// 获取IP 地址
+ ///
+ ///
+ public static string GetLocalIp()
+ {
+ //得到本机名
+ string hostname = Dns.GetHostName();
+ //解析主机名称或IP地址的system.net.iphostentry实例。
+ IPHostEntry localhost = Dns.GetHostEntry(hostname);
+ if (localhost != null)
+ {
+ foreach (IPAddress item in localhost.AddressList)
+ {
+ //判断是否是内网IPv4地址
+ if (item.AddressFamily == AddressFamily.InterNetwork)
+ {
+ return item.MapToIPv4().ToString();
+ }
+ }
+ }
+ return "192.168.1.124";
+ }
+ }
+}
diff --git a/BPASmartClient.IoT/BPASmartClient.IoT.csproj b/BPASmartClient.IoT/BPASmartClient.IoT.csproj
index dbc15171..a3727742 100644
--- a/BPASmartClient.IoT/BPASmartClient.IoT.csproj
+++ b/BPASmartClient.IoT/BPASmartClient.IoT.csproj
@@ -4,4 +4,15 @@
net6.0
+
+
+
+
+
+
+
+
+
+
+
diff --git a/BPASmartClient.IoT/Class1.cs b/BPASmartClient.IoT/Class1.cs
deleted file mode 100644
index 1aa0de8c..00000000
--- a/BPASmartClient.IoT/Class1.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System;
-
-namespace BPASmartClient.IoT
-{
- public class Class1
- {
- }
-}
diff --git a/BPASmartClient.IoT/DataVClient.cs b/BPASmartClient.IoT/DataVClient.cs
new file mode 100644
index 00000000..a76c28c8
--- /dev/null
+++ b/BPASmartClient.IoT/DataVClient.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace BPASmartClient.IoT
+{
+ ///
+ /// DataV客户端数据中心
+ ///
+ public class DataVClient
+ {
+ #region 单例模式
+ private volatile static DataVClient _Instance;
+ public static DataVClient GetInstance => _Instance ?? (_Instance = new DataVClient());
+ #endregion
+
+ #region 公有变量
+ //DataV 服务地址
+ public string DataVApiAddress { set; get; }
+ #endregion
+
+ public DataVClient()
+ {
+ DataVApiAddress = System.Configuration.ConfigurationManager.AppSettings["DataVServiceUri"].ToString();
+ }
+
+ public void Start()
+ {
+
+ }
+ }
+}
diff --git a/BPASmartClient.IoT/DataVReport.cs b/BPASmartClient.IoT/DataVReport.cs
new file mode 100644
index 00000000..78e1017a
--- /dev/null
+++ b/BPASmartClient.IoT/DataVReport.cs
@@ -0,0 +1,365 @@
+using BPASmartClient.Helper;
+using BPASmartClient.IoT;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using uPLibrary.Networking.M2Mqtt;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace BPASmartDatavDeviceClient.IoT
+{
+ ///
+ /// DataV客户端
+ ///
+ public class DataVReport
+ {
+ #region 外部调用
+ ///
+ /// 初始化IOT连接
+ ///
+ public bool Initialize(string url,string clientId,string deviceId,ref string message)
+ {
+ if(string.IsNullOrEmpty(url))return false;
+ DeviceTable device;
+ if (!CreateLinks(url,clientId,deviceId, out device))
+ {
+ message += $"客户端{clientId}设备{deviceId}阿里云上没有该设备。";
+ return false;
+ }
+ IOT_Subscribe(BroadcastTopic);//订阅广播主题
+ if (DatavDeviceClient.IsConnected) message += $"设备{device.devicename} {device.remark}阿里云连接成功.";
+ else message += $"设备{device.devicename} {device.remark}阿里云连接失败.不能上报业务信息";
+ return DatavDeviceClient.IsConnected;
+ }
+
+ ///
+ /// 获取连接状态
+ ///
+ public bool GetIsConnected()
+ {
+ try
+ {
+ if (DatavDeviceClient == null || !DatavDeviceClient.IsConnected)
+ return false;
+ else return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ throw;
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ public void Disconnect()
+ {
+ if (DatavDeviceClient != null)
+ {
+ DatavDeviceClient.Disconnect();
+ }
+ }
+
+ ///
+ /// 发布消息
+ ///
+ ///
+ ///
+ public void IOT_Publish(string topic, string message)
+ {
+ var id = DatavDeviceClient.Publish(topic, Encoding.UTF8.GetBytes(message));
+ }
+
+ ///
+ /// 订阅主题
+ ///
+ ///
+ public void IOT_Subscribe(string topic)
+ {
+ if (SubTopicList.Contains(topic))
+ {
+ SubTopicList.Add(topic);
+ }
+ DatavDeviceClient.Subscribe(new string[] { topic }, new byte[] { 0 });
+ }
+ #endregion
+
+ #region 私有函数
+ ///
+ /// 设置变量
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void SetValue(string _ProductKey, string _DeviceName, string _DeviceSecret, string _RegionId = "cn-shanghai")
+ {
+ ProductKey = _ProductKey;
+ DeviceName = _DeviceName;
+ DeviceSecret = _DeviceSecret;
+ RegionId = _RegionId;
+ PubTopic = "/sys/" + ProductKey + "/" + DeviceName + "/thing/event/property/post";
+ SubTopic = "/sys/" + ProductKey + "/" + DeviceName + "/thing/event/property/set";
+ UserPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
+ UserSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
+ BroadcastTopic = "/broadcast/" + ProductKey + "/" + DeviceName + "_SetDevice";
+ AlarmSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/AlarmMessage";
+ LogsSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ExceptionLogs";
+ HeartbeatSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/HeartbeatAndState";
+ TargetStatusSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/TargetStatus";
+ ScreenShowPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ScreenShow";
+ }
+
+ ///
+ /// 创建连接
+ ///
+ private bool CreateLinks(string url, string clientId, string deviceId, out DeviceTable device)
+ {
+ try
+ {
+ string json = HttpRequestHelper.HttpGetRequest($"{url}/api/Device/Query?clientId={clientId}&deviceId={deviceId}");
+ JsonMsg> jsonMsg = Tools.JsonToObjectTools>>(json);
+ if (jsonMsg.obj != null && jsonMsg.obj.data != null)
+ {
+ device = jsonMsg.obj.data.FirstOrDefault();
+ if (device == null) return false;
+ SetValue(device.productkey, device.devicename, device.devicesecret);
+ IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
+ string _clientId = host.AddressList.FirstOrDefault(
+ ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString();
+ string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds());
+ string signmethod = "hmacmd5";
+
+ Dictionary dict = new Dictionary();
+ dict.Add("productKey", ProductKey);
+ dict.Add("deviceName", DeviceName);
+ dict.Add("clientId", _clientId);
+ dict.Add("timestamp", t);
+
+ mqttUserName = DeviceName + "&" + ProductKey;
+ mqttPassword = IotSignUtils.sign(dict, DeviceSecret, signmethod);
+ mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|";
+ targetServer = ProductKey + ".iot-as-mqtt." + RegionId + ".aliyuncs.com";
+ ConnectMqtt(targetServer, mqttClientId, mqttUserName, mqttPassword);
+ return true;
+ }
+ else
+ {
+ device = null;
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ device = null;
+ return false;
+ }
+ }
+
+ ///
+ /// MQTT创建连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void ConnectMqtt(string targetServer, string mqttClientId, string mqttUserName, string mqttPassword)
+ {
+ DatavDeviceClient = new MqttClient(targetServer);
+ DatavDeviceClient.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
+ DatavDeviceClient.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
+ DatavDeviceClient.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
+ DatavDeviceClient.ConnectionClosed += Client_ConnectionClosed;
+ }
+
+ ///
+ /// MQTT 断开事件
+ ///
+ ///
+ ///
+ private static void Client_ConnectionClosed(object sender, EventArgs e)
+ {
+ // 尝试重连
+ _TryContinueConnect();
+ }
+
+ ///
+ /// 订阅数据接收
+ ///
+ ///
+ ///
+ private static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
+ {
+ string topic = e.Topic;
+ string message = Encoding.UTF8.GetString(e.Message);
+ if (DataVMessageAction != null)
+ {
+ DataVMessageAction.Invoke(topic, message);
+ }
+ }
+
+ ///
+ /// 自动重连主体
+ ///
+ private static void _TryContinueConnect()
+ {
+ Thread retryThread = new Thread(new ThreadStart(delegate
+ {
+ while (DatavDeviceClient == null || !DatavDeviceClient.IsConnected)
+ {
+ if (DatavDeviceClient.IsConnected) break;
+
+ if (DatavDeviceClient == null)
+ {
+ DatavDeviceClient = new MqttClient(targetServer);
+ DatavDeviceClient.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
+ DatavDeviceClient.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
+ DatavDeviceClient.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
+ DatavDeviceClient.ConnectionClosed += Client_ConnectionClosed;
+ if (DatavDeviceClient.IsConnected)
+ {
+ SubTopicList?.ForEach(par =>{DatavDeviceClient.Subscribe(new string[] { par }, new byte[] { 0 }); });
+ }
+ Thread.Sleep(3000);
+ continue;
+ }
+
+ try
+ {
+ DatavDeviceClient.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
+ if (DatavDeviceClient.IsConnected)
+ {
+ SubTopicList?.ForEach(par => { DatavDeviceClient.Subscribe(new string[] { par }, new byte[] { 0 }); });
+ UnConnectMqtt?.Invoke("重新连接阿里云MQTT成功!");
+ }
+ }
+ catch (Exception ce)
+ {
+ UnConnectMqtt?.Invoke("重新连接阿里云MQTT失败!");
+ }
+ // 如果还没连接不符合结束条件则睡2秒
+ if (!DatavDeviceClient.IsConnected)
+ {
+ Thread.Sleep(2000);
+ }
+ }
+ }));
+
+ retryThread.Start();
+ }
+ #endregion
+
+ #region 私有IOT连接变量
+ private static string ProductKey = "grgpECHSL7q";
+ private static string DeviceName = "hbldev";
+ private static string DeviceSecret = "4ec120de0c866199183b22e2e3135aeb";
+ private static string RegionId = "cn-shanghai";
+ private static string mqttUserName = string.Empty;
+ private static string mqttPassword = string.Empty;
+ private static string mqttClientId = string.Empty;
+ private static string targetServer = string.Empty;
+ #endregion
+
+ #region 公有变量
+ ///
+ /// 设备消息数据回调
+ ///
+ public static Action DataVMessageAction { get; set; }
+ ///
+ /// 重连事件
+ ///
+ public static Action UnConnectMqtt { get; set; }
+ ///
+ /// 客户端
+ ///
+ public static MqttClient DatavDeviceClient { get; set; }
+ ///
+ /// 当前设备
+ ///
+ public DeviceTable deviceTable { get; set; }
+ #endregion
+
+ #region 发布或订阅主题或URL地址
+ ///
+ /// 属性发布消息主题
+ ///
+ public static string PubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
+ ///
+ /// 属性接收消息主题
+ ///
+ public static string SubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
+ ///
+ /// 自定义发布消息主题
+ ///
+ public static string UserPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
+ ///
+ /// 自定义接收消息主题
+ ///
+ public static string UserSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
+ ///
+ /// 告警订阅主题
+ ///
+ public static string AlarmSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/AlarmMessage";
+ ///
+ /// 日志订阅主题
+ ///
+ public static string LogsSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ExceptionLogs";
+ ///
+ /// 上下线订阅主题
+ ///
+ public static string HeartbeatSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/HeartbeatAndState";
+ ///
+ /// 属性状态主题
+ ///
+ public static string TargetStatusSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/TargetStatus";
+ ///
+ /// 大屏展示发布主题
+ ///
+ public static string ScreenShowPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ScreenShow";
+ ///
+ /// 广播主题
+ ///
+ public static string BroadcastTopic = "/broadcast/" + "grgpECHSL7q" + "/" + DeviceName + "_SetDevice";
+ ///
+ /// 订阅主题集合
+ ///
+ public static List SubTopicList = new List();
+ #endregion
+ }
+
+ ///
+ /// Iot 设备上报
+ ///
+ public class IotSignUtils
+ {
+ public static string sign(Dictionary param,
+ string deviceSecret, string signMethod)
+ {
+ string[] sortedKey = param.Keys.ToArray();
+ Array.Sort(sortedKey);
+
+ StringBuilder builder = new StringBuilder();
+ foreach (var i in sortedKey)
+ {
+ builder.Append(i).Append(param[i]);
+ }
+
+ byte[] key = Encoding.UTF8.GetBytes(deviceSecret);
+ byte[] signContent = Encoding.UTF8.GetBytes(builder.ToString());
+ //这里根据signMethod动态调整,本例子硬编码了: 'hmacmd5'
+ var hmac = new HMACMD5(key);
+ byte[] hashBytes = hmac.ComputeHash(signContent);
+
+ StringBuilder signBuilder = new StringBuilder();
+ foreach (byte b in hashBytes)
+ signBuilder.AppendFormat("{0:x2}", b);
+
+ return signBuilder.ToString();
+ }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/AlarmTable.cs b/BPASmartClient.IoT/Model/AlarmTable.cs
new file mode 100644
index 00000000..66c0e205
--- /dev/null
+++ b/BPASmartClient.IoT/Model/AlarmTable.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.IoT
+{
+ ///
+ /// 告警消息表
+ ///
+ public class AlarmTable : BaseEntity
+ {
+ ///
+ /// 告警时间
+ ///
+ public string AlarmTime { get; set; }
+ ///
+ /// 告警类型:1 轻微 2:一般 3 严重
+ ///
+ public string AlarmType { get; set; }
+ ///
+ /// 告警消息
+ ///
+ public string AlarmMessage { get; set; }
+ ///
+ /// 告警值
+ ///
+ public string AlarmVla { get; set; }
+ ///
+ /// IP 地址
+ ///
+ public string IP { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/BaseEntity.cs b/BPASmartClient.IoT/Model/BaseEntity.cs
new file mode 100644
index 00000000..0cbff59d
--- /dev/null
+++ b/BPASmartClient.IoT/Model/BaseEntity.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.IoT
+{
+ ///
+ /// MongoDB基类
+ ///
+ public abstract class BaseEntity
+ {
+ ///
+ /// ID
+ ///
+ public string Id { get; set; }
+ ///
+ /// 客户端 ID
+ ///
+ public string ClientId { get; set; }
+ ///
+ /// 设备 ID
+ ///
+ public string DeviceId { get; set; }
+ ///
+ /// 阿里云设备名称
+ ///
+ public string devicename { get; set; }
+ ///
+ /// 状态
+ ///
+ public string State { get; set; }
+ ///
+ /// 创建时间
+ ///
+ public DateTime CreateTime { get; set; }
+ ///
+ /// 修改时间
+ ///
+ public DateTime UpdateTime { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/CommandModel.cs b/BPASmartClient.IoT/Model/CommandModel.cs
new file mode 100644
index 00000000..964e21bd
--- /dev/null
+++ b/BPASmartClient.IoT/Model/CommandModel.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.IoT
+{
+ ///
+ /// 命令实体类
+ ///
+ public class CommandModel
+ {
+ ///
+ /// 设备名称
+ ///
+ public string deviceName { get; set; }
+ ///
+ /// 命令名称:0 控制类 1 设置属性 2 通知信息类
+ ///
+ public int CommandName { get; set; }
+ ///
+ /// 命令变量:执行变量 key为属性或时间 value为值或者消息
+ ///
+ public Dictionary CommandValue { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/DeviceTable.cs b/BPASmartClient.IoT/Model/DeviceTable.cs
new file mode 100644
index 00000000..e55d7ff5
--- /dev/null
+++ b/BPASmartClient.IoT/Model/DeviceTable.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.IoT
+{
+ ///
+ /// 设备信息表
+ ///
+ public class DeviceTable : BaseEntity
+ {
+ ///
+ /// 阿里云设备key
+ ///
+ public string productkey { get; set; }
+ ///
+ /// 阿里云设备secret
+ ///
+ public string devicesecret { get; set; }
+ ///
+ /// 客户端类型
+ ///
+ public string devtype { get; set; }
+ ///
+ /// 经度
+ ///
+ public string jd { get; set; }
+ ///
+ /// 维度
+ ///
+ public string wd { get; set; }
+ ///
+ /// 备注
+ ///
+ public string remark { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/IOT/CommandModel.cs b/BPASmartClient.IoT/Model/IOT/CommandModel.cs
new file mode 100644
index 00000000..b48fea53
--- /dev/null
+++ b/BPASmartClient.IoT/Model/IOT/CommandModel.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DataVAPI.Tool.IOT
+{
+ ///
+ /// 命令实体类
+ ///
+ public class IOTCommandModel
+ {
+ ///
+ /// 设备名称
+ ///
+ public string deviceName { get; set; }
+ ///
+ /// 命令名称:0 控制类 1 设置属性 2 通知信息类
+ ///
+ public int CommandName { get; set; }
+ ///
+ /// 命令变量:执行变量 key为属性或时间 value为值或者消息
+ ///
+ public Dictionary CommandValue { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/IOT/IOTDevModel.cs b/BPASmartClient.IoT/Model/IOT/IOTDevModel.cs
new file mode 100644
index 00000000..b1186572
--- /dev/null
+++ b/BPASmartClient.IoT/Model/IOT/IOTDevModel.cs
@@ -0,0 +1,336 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DataVAPI.Tool.IOT
+{
+ ///
+ /// IOT Model
+ ///
+ public class IotModel
+ {
+ public string id { get; set; } = Guid.NewGuid().ToString();
+ public string version { get; set; } = "1.0";
+ public T @params { get; set; }
+ public string method { get; set; } = "thing.event.property.post";
+ }
+ ///
+ /// IOT 接收数据Model
+ ///
+ public class ReceiveModel
+ {
+ ///
+ /// 设备详细信息
+ ///
+ public DevBase deviceContext { get; set; }
+ ///
+ /// 设备属性
+ ///
+ public ReceiveSXModel props { get; set; }
+ ///
+ /// 设备上下线状态
+ ///
+ public Vls status { get; set; }
+
+ }
+ ///
+ /// 接收数据Model
+ ///
+ public class ReceiveSXModel
+ {
+ ///
+ /// 告警消息
+ ///
+ public Vls GJXX { get; set; }
+ ///
+ /// 扩展属性
+ ///
+ public Vls KZSX { get; set; }
+ ///
+ /// 基本属性
+ ///
+ public Vls JBSX { get; set; }
+ ///
+ /// 节点状态
+ ///
+ public Vls NodeStatus { get; set; }
+ ///
+ /// 日志消息
+ ///
+ public Vls SZXX { get; set; }
+ }
+ ///
+ /// IOT 设备属性 Model
+ ///
+ public class IOTDevSXModel
+ {
+ ///
+ /// 硬件状态
+ ///
+ public string HardwareStatus { get; set; }
+ ///
+ /// 扩展属性
+ ///
+ public string KZSX { get; set; }
+ ///
+ /// 基本属性
+ ///
+ public string JBSX { get; set; }
+ ///
+ /// 节点状态
+ ///
+ public string NodeStatus { get; set; }
+ ///
+ /// Model
+ ///
+ public IOTDevSXModel()
+ {
+
+ }
+ ///
+ /// 序列化为JSON
+ ///
+ ///
+ public string Tojson()
+ {
+ try
+ {
+ IotModel iotModel = new IotModel { @params = this };
+ string json = Tools.JsonConvertTools(iotModel);
+ return json;
+ }
+ catch (Exception ex)
+ {
+ return string.Empty;
+ }
+ }
+ ///
+ /// 设置基本属性
+ ///
+ ///
+ ///
+ public void SetJBSX(DevSX devSX)
+ {
+ try
+ {
+ JBSX = Tools.JsonConvertTools(devSX);
+ }
+ catch (Exception ex)
+ {
+ JBSX = string.Empty;
+ }
+ }
+ ///
+ /// 设置基本属性状态
+ ///
+ ///
+ ///
+ public void SetJBSXStatus(DevSXBase sXBase, bool Status)
+ {
+ try
+ {
+ if (sXBase == null) return;
+ DevSX dev = Tools.JsonToObjectTools(JBSX);
+ dev.data?.ForEach(x =>
+ {
+ if (x.SXMC == sXBase.SXMC && x.SXLX == sXBase.SXLX)
+ {
+ x.SXStatus = Status;
+ }
+ });
+ JBSX = Tools.JsonConvertTools(dev);
+ }
+ catch (Exception ex)
+ {
+ JBSX = string.Empty;
+ }
+ }
+ ///
+ /// 设置扩展属性
+ ///
+ ///
+ public void SetKZSX(DevSX devSX)
+ {
+ try
+ {
+ KZSX = Tools.JsonConvertTools(devSX);
+ }
+ catch (Exception ex)
+ {
+ KZSX = string.Empty;
+ }
+ }
+ ///
+ /// 设置扩展属性状态
+ ///
+ ///
+ ///
+ public void SetKZSXStatus(DevSXBase sXBase, bool Status)
+ {
+ try
+ {
+ if (sXBase == null) return;
+ DevSX dev = Tools.JsonToObjectTools(KZSX);
+ dev.data?.ForEach(x =>
+ {
+ if (x.SXMC == sXBase.SXMC && x.SXLX == sXBase.SXLX)
+ {
+ x.SXStatus = Status;
+ }
+ });
+ KZSX = Tools.JsonConvertTools(dev);
+ }
+ catch (Exception ex)
+ {
+ KZSX = string.Empty;
+ }
+ }
+ }
+ ///
+ /// 告警消息
+ ///
+ public class AlarmMessage
+ {
+ public List data { get; set; }
+ }
+ ///
+ /// 告警Model
+ ///
+ public class AlarmModel : DeviceBase
+ {
+ ///
+ /// 告警程度:提示 一般 严重
+ ///
+ public string AlarmCD
+ {
+ get { return _AlarmCD; }
+ set
+ {
+ _AlarmCD = value;
+ if (_AlarmCD == "提示") DeviceColor = new ALYColor { r = 13, g = 254, b = 73, a = 1 };
+ else if (_AlarmCD == "一般") DeviceColor = new ALYColor { r = 245, g = 216, b = 13, a = 1 };
+ else if (_AlarmCD == "严重") DeviceColor = new ALYColor { r = 245, g = 13, b = 13, a = 1 };
+ }
+ }
+ private string _AlarmCD { get; set; }
+ ///
+ /// 颜色
+ ///
+ public ALYColor DeviceColor { get; set; }
+ }
+ ///
+ /// 设备上报属性
+ ///
+ public class DevSX
+ {
+ public List data { get; set; }
+ }
+ ///
+ /// 设备基本属性Model
+ ///
+ public class DevSXBase
+ {
+ ///
+ /// 属性名称
+ ///
+ public string SXMC { get; set; }
+ ///
+ /// 属性类型
+ ///
+ public string SXLX { get; set; }
+ ///
+ /// 属性状态
+ ///
+ private bool _SXStatus { get; set; }
+ public bool SXStatus
+ {
+ get { return _SXStatus; }
+ set
+ {
+ _SXStatus = value;
+ if (_SXStatus)
+ {
+ SXZT = "正常";
+ }
+ else
+ {
+ SXZT = "异常";
+ }
+ }
+ }
+ private string _SXZT { get; set; }
+ ///
+ /// 属性状态:正常 异常
+ ///
+ public string SXZT
+ {
+ get { return _SXZT; }
+ set
+ {
+ _SXZT = value;
+ if (_SXZT == "正常")
+ {
+ SXYC = new ALYColor { r = 13, g = 254, b = 73, a = 1 };//绿色
+ SXYCMS = "";
+ YCZT = "";
+ ButtonText = "";
+ ButtonYC = new ALYColor { r = 0, g = 0, b = 0, a = 0 };
+ }
+ else if (_SXZT == "异常")
+ {
+ SXYC = new ALYColor { r = 245, g = 13, b = 13, a = 1 };//红色
+ ButtonText = "详情";
+ ButtonYC = new ALYColor { r = 48, g = 109, b = 201, a = 0.18 };
+ }
+ }
+ }
+ ///
+ /// 属性异常描述
+ ///
+ public string SXYCMS { get; set; }
+ public string YCZT { get; set; }
+ ///
+ /// 属性颜色
+ ///
+ public ALYColor SXYC { get; set; }
+ ///
+ /// 按钮文字
+ ///
+ public string ButtonText { get; set; }
+ ///
+ /// 按钮颜色
+ ///
+ public ALYColor ButtonYC { get; set; }
+ public DevSXBase()
+ {
+ SXZT = "";
+ SXYC = new ALYColor { r = 13, g = 254, b = 73, a = 1 };//绿色
+ SXYCMS = "";
+ YCZT = "";
+ ButtonText = "";
+ ButtonYC = new ALYColor { r = 0, g = 0, b = 0, a = 0 };
+ }
+ }
+
+ ///
+ /// 设备颜色
+ ///
+ public class ALYColor
+ {
+ public int r { get; set; }
+ public int g { get; set; }
+ public int b { get; set; }
+ public double a { get; set; }
+ }
+
+ ///
+ /// 变量
+ ///
+ public class Vls
+ {
+ public long time { get; set; }
+ public string value { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/IOT/IOTDevServer.cs b/BPASmartClient.IoT/Model/IOT/IOTDevServer.cs
new file mode 100644
index 00000000..98de2203
--- /dev/null
+++ b/BPASmartClient.IoT/Model/IOT/IOTDevServer.cs
@@ -0,0 +1,467 @@
+
+
+using BPASmartClient.Helper;
+using BPASmartClient.IoT;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using uPLibrary.Networking.M2Mqtt;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace DataVAPI.Tool.IOT
+{
+ ///
+ /// add fengyoufu
+ /// 黑菠萝科技有限公司
+ /// IOT设备上报消息类
+ ///
+ public class IOTDevServer
+ {
+ #region 私有IOT连接变量
+ private static string ProductKey = "grgpECHSL7q";
+ private static string DeviceName = "hbldev";
+ private static string DeviceSecret = "4ec120de0c866199183b22e2e3135aeb";
+ private static string RegionId = "cn-shanghai";
+ private static string mqttUserName = string.Empty;
+ private static string mqttPassword = string.Empty;
+ private static string mqttClientId = string.Empty;
+ private static string targetServer = string.Empty;
+ #endregion
+
+ #region 公有变量
+ ///
+ /// 设备消息数据回调
+ ///
+ public static Action DevIOTAction { get; set; }
+ ///
+ /// 重连事件
+ ///
+ public static Action UNConnectMqtt { get; set; }
+ ///
+ /// 客户端
+ ///
+ public static MqttClient client { get; set; }
+ #endregion
+
+ #region 发布或订阅主题或URL地址
+ ///
+ /// API 服务
+ ///
+ private static string APIurl = "http://124.222.238.75:6002";
+ ///
+ /// 属性发布消息主题
+ ///
+ public static string PubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
+ ///
+ /// 属性接收消息主题
+ ///
+ public static string SubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
+ ///
+ /// 自定义发布消息主题
+ ///
+ public static string UserPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
+ ///
+ /// 自定义接收消息主题
+ ///
+ public static string UserSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
+ ///
+ /// 告警订阅主题
+ ///
+ public static string AlarmSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/AlarmMessage";
+ ///
+ /// 日志订阅主题
+ ///
+ public static string LogsSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ExceptionLogs";
+ ///
+ /// 上下线订阅主题
+ ///
+ public static string HeartbeatSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/HeartbeatAndState";
+ ///
+ /// 属性状态主题
+ ///
+ public static string TargetStatusSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/TargetStatus";
+ ///
+ /// 大屏展示发布主题
+ ///
+ public static string ScreenShowPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ScreenShow";
+ ///
+ /// 广播主题
+ ///
+ public static string BroadcastTopic = "/broadcast/" + "grgpECHSL7q" + "/" + DeviceName + "_SetDevice";
+ ///
+ /// 订阅主题集合
+ ///
+ public static List SubTopicList = new List();
+ #endregion
+
+ #region 单例模式
+ private static IOTDevServer iot = null;
+ public static IOTDevServer GetInstance()
+ {
+ if (iot == null) { iot = new IOTDevServer(); }
+ return iot;
+ }
+ #endregion
+
+ #region 公共调用阿里云连接或检测
+ ///
+ /// 设置URL
+ ///
+ ///
+ public void SetUrl(string url = "http://124.222.238.75:6002")
+ {
+ APIurl = url;
+ }
+
+ ///
+ /// 设置变量
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void Set(string _ProductKey, string _DeviceName, string _DeviceSecret, string _RegionId = "cn-shanghai")
+ {
+ ProductKey = _ProductKey;
+ DeviceName = _DeviceName;
+ DeviceSecret = _DeviceSecret;
+ RegionId = _RegionId;
+ PubTopic = "/sys/" + ProductKey + "/" + DeviceName + "/thing/event/property/post";
+ SubTopic = "/sys/" + ProductKey + "/" + DeviceName + "/thing/event/property/set";
+ UserPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
+ UserSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
+ BroadcastTopic = "/broadcast/" + ProductKey + "/" + DeviceName + "_SetDevice";
+ AlarmSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/AlarmMessage";
+ LogsSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ExceptionLogs";
+ HeartbeatSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/HeartbeatAndState";
+ TargetStatusSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/TargetStatus";
+ ScreenShowPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ScreenShow";
+ }
+
+ ///
+ /// 创建连接
+ ///
+ ///
+ public bool CreateLinks(int ClientId, out DeviceTable device)
+ {
+ try
+ {
+ //http://localhost:9092/api/Device/Query?chid=2
+ string json = HttpRequestHelper.HttpGetRequest($"{APIurl}/api/Device/Query?clientId={ClientId}");
+ JsonMsg> jsonMsg = Tools.JsonToObjectTools>>(json);
+ if (jsonMsg.obj != null && jsonMsg.obj.data!=null)
+ {
+ device = jsonMsg.obj.data.FirstOrDefault();
+ if (device == null) return false;
+
+ Set(device.productkey, device.devicename, device.devicesecret);
+
+ IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
+ string clientId = host.AddressList.FirstOrDefault(
+ ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
+ string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds());
+ string signmethod = "hmacmd5";
+
+ Dictionary dict = new Dictionary();
+ dict.Add("productKey", ProductKey);
+ dict.Add("deviceName", DeviceName);
+ dict.Add("clientId", clientId);
+ dict.Add("timestamp", t);
+
+ mqttUserName = DeviceName + "&" + ProductKey;
+ mqttPassword = IotSignUtils.sign(dict, DeviceSecret, signmethod);
+ mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|";
+ targetServer = ProductKey + ".iot-as-mqtt." + RegionId + ".aliyuncs.com";
+ ConnectMqtt(targetServer, mqttClientId, mqttUserName, mqttPassword);
+ return true;
+ }
+ else
+ {
+ device = null;
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ device = null;
+ return false;
+ }
+ }
+
+ ///
+ /// 获取连接状态
+ ///
+ public bool GetIsConnected()
+ {
+ try
+ {
+ if (client == null || !client.IsConnected)
+ return false;
+ else return true;
+ }
+ catch (Exception ex)
+ {
+ return false;
+ throw;
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ public void Disconnect()
+ {
+ if (client != null)
+ {
+ client.Disconnect();
+ }
+ }
+ #endregion
+
+ #region 公共发布或订阅函数
+ ///
+ /// 发布消息
+ ///
+ ///
+ ///
+ public void IOT_Publish(string topic, string message)
+ {
+ var id = client.Publish(topic, Encoding.UTF8.GetBytes(message));
+ }
+
+ ///
+ /// 订阅主题
+ ///
+ ///
+ public void IOT_Subscribe(string topic)
+ {
+ if (SubTopicList.Contains(topic))
+ {
+ SubTopicList.Add(topic);
+ }
+ client.Subscribe(new string[] { topic }, new byte[] { 0 });
+ }
+ #endregion
+
+ #region 私有函数
+ ///
+ /// mQTT创建连接
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void ConnectMqtt(string targetServer, string mqttClientId, string mqttUserName, string mqttPassword)
+ {
+ client = new MqttClient(targetServer);
+ client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
+ client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
+ client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
+ client.ConnectionClosed += Client_ConnectionClosed;
+ }
+
+ ///
+ /// MQTT 断开事件
+ ///
+ ///
+ ///
+ private static void Client_ConnectionClosed(object sender, EventArgs e)
+ {
+ // 尝试重连
+ _TryContinueConnect();
+ }
+
+ ///
+ /// 订阅数据接收
+ ///
+ ///
+ ///
+ private static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
+ {
+ string topic = e.Topic;
+ string message = Encoding.UTF8.GetString(e.Message);
+ if (DevIOTAction != null)
+ {
+ DevIOTAction.Invoke(topic, message);
+ }
+ }
+
+ ///
+ /// 自动重连主体
+ ///
+ private static void _TryContinueConnect()
+ {
+ Thread retryThread = new Thread(new ThreadStart(delegate
+ {
+ while (client == null || !client.IsConnected)
+ {
+ if (client.IsConnected) break;
+
+ if (client == null)
+ {
+ client = new MqttClient(targetServer);
+ client.ProtocolVersion = MqttProtocolVersion.Version_3_1_1;
+ client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
+ client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
+ client.ConnectionClosed += Client_ConnectionClosed;
+ if (client.IsConnected)
+ {
+ SubTopicList.ForEach(par =>
+ {
+ client.Subscribe(new string[] { par }, new byte[] { 0 });
+ });
+ }
+ Thread.Sleep(3000);
+ continue;
+ }
+
+ try
+ {
+ client.Connect(mqttClientId, mqttUserName, mqttPassword, false, 60);
+ if (client.IsConnected)
+ {
+ SubTopicList.ForEach(par =>
+ {
+ client.Subscribe(new string[] { par }, new byte[] { 0 });
+ });
+ UNConnectMqtt?.Invoke("重新连接阿里云MQTT成功!");
+ }
+ }
+ catch (Exception ce)
+ {
+ UNConnectMqtt?.Invoke("重新连接阿里云MQTT失败!");
+ }
+ // 如果还没连接不符合结束条件则睡2秒
+ if (!client.IsConnected)
+ {
+ Thread.Sleep(2000);
+ }
+ }
+ }));
+
+ retryThread.Start();
+ }
+ #endregion
+ }
+
+ ///
+ /// Iot 设备上报
+ ///
+ public class IotSignUtils
+ {
+ public static string sign(Dictionary param,
+ string deviceSecret, string signMethod)
+ {
+ string[] sortedKey = param.Keys.ToArray();
+ Array.Sort(sortedKey);
+
+ StringBuilder builder = new StringBuilder();
+ foreach (var i in sortedKey)
+ {
+ builder.Append(i).Append(param[i]);
+ }
+
+ byte[] key = Encoding.UTF8.GetBytes(deviceSecret);
+ byte[] signContent = Encoding.UTF8.GetBytes(builder.ToString());
+ //这里根据signMethod动态调整,本例子硬编码了: 'hmacmd5'
+ var hmac = new HMACMD5(key);
+ byte[] hashBytes = hmac.ComputeHash(signContent);
+
+ StringBuilder signBuilder = new StringBuilder();
+ foreach (byte b in hashBytes)
+ signBuilder.AppendFormat("{0:x2}", b);
+
+ return signBuilder.ToString();
+ }
+ }
+
+ ///
+ /// 工具
+ ///
+ public class Tools
+ {
+ ///
+ /// 对象Json序列
+ ///
+ /// 对象类型
+ /// 对象实例
+ ///
+ public static string JsonConvertTools(T obj)
+ {
+ string strvalue = JsonConvert.SerializeObject(obj);
+ return strvalue;
+ }
+
+ ///
+ /// 对象反Json序列
+ ///
+ /// 对象类型
+ /// 对象序列化json字符串
+ /// 返回对象实例
+ public static T JsonToObjectTools(string jsonstring)
+ {
+ T obj = JsonConvert.DeserializeObject(jsonstring);
+ return obj;
+ }
+
+ ///
+ /// DateTime --> long
+ ///
+ ///
+ ///
+ public static long ConvertDateTimeToLong(DateTime dt)
+ {
+ DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
+ TimeSpan toNow = dt.Subtract(dtStart);
+ long timeStamp = toNow.Ticks;
+ timeStamp = long.Parse(timeStamp.ToString().Substring(0, timeStamp.ToString().Length - 4));
+ return timeStamp;
+ }
+
+ ///
+ /// long --> DateTime
+ ///
+ ///
+ ///
+ public static DateTime ConvertLongToDateTime(long d)
+ {
+ DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
+ long lTime = long.Parse(d + "0000");
+ TimeSpan toNow = new TimeSpan(lTime);
+ DateTime dtResult = dtStart.Add(toNow);
+ return dtResult;
+ }
+
+ ///
+ /// 获取IP 地址
+ ///
+ ///
+ public static string GetLocalIp()
+ {
+ //得到本机名
+ string hostname = Dns.GetHostName();
+ //解析主机名称或IP地址的system.net.iphostentry实例。
+ IPHostEntry localhost = Dns.GetHostEntry(hostname);
+ if (localhost != null)
+ {
+ foreach (IPAddress item in localhost.AddressList)
+ {
+ //判断是否是内网IPv4地址
+ if (item.AddressFamily == AddressFamily.InterNetwork)
+ {
+ return item.MapToIPv4().ToString();
+ }
+ }
+ }
+ return "192.168.1.124";
+ }
+ }
+
+
+}
diff --git a/BPASmartClient.IoT/Model/IOT/ScreenMonitorModel.cs b/BPASmartClient.IoT/Model/IOT/ScreenMonitorModel.cs
new file mode 100644
index 00000000..21933f4e
--- /dev/null
+++ b/BPASmartClient.IoT/Model/IOT/ScreenMonitorModel.cs
@@ -0,0 +1,275 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace DataVAPI.Tool.IOT
+{
+
+ ///
+ /// 大屏监视Model
+ ///
+ public class ScreenMonitorModel
+ {
+ ///
+ /// 服务商家数
+ ///
+ public string TotalSales { get; set; }
+ ///
+ /// 现场运营设备状态
+ ///
+ public OperatingDeviceStatus operatingDeviceStatus { get; set; }
+ ///
+ /// 通知消息
+ ///
+ public InfoMessage infoMessage { get; set; }
+ ///
+ /// 返回JSON
+ ///
+ ///
+ public string ToJSON()
+ {
+ try
+ {
+ return Tools.JsonConvertTools(this);
+ }
+ catch (Exception ex)
+ {
+ return string.Empty;
+ }
+ }
+ ///
+ /// 序列化为对象
+ ///
+ ///
+ ///
+ public ScreenMonitorModel JSONtoDX(string JSON)
+ {
+ try
+ {
+ return Tools.JsonToObjectTools(JSON);
+ }
+ catch (Exception ex)
+ {
+ return new ScreenMonitorModel();
+ }
+ }
+ }
+ ///
+ /// 下订单统计
+ ///
+ public class PlaceOrderCount
+ {
+ ///
+ /// 今日下单量统计
+ ///
+ public string ToDayPlaceCount { get; set; }
+ ///
+ /// 本月下单量统计
+ ///
+ public string MonthPlaceCount { get; set; }
+ ///
+ /// 本年下单量统计
+ ///
+ public string YearPlaceCount { get; set; }
+
+ }
+ ///
+ /// 制作流程
+ ///
+ public class ProcessMessage
+ {
+ public List data { get; set; }
+ }
+ ///
+ /// 制作流程Model
+ ///
+ public class ProcessModel
+ {
+ ///
+ /// 告警程度:提示 一般 严重
+ ///
+ private bool _IsMark { get; set; }
+ public bool IsMark
+ {
+ get { return _IsMark; }
+ set
+ {
+ _IsMark = value;
+ if (_IsMark) ProcessColor = new ALYColor { r = 253, g = 234, b = 1, a = 1 };
+ else ProcessColor = new ALYColor { r = 151, g = 150, b = 140, a = 1 };
+ }
+ }
+ ///
+ /// 流程名称
+ ///
+ public string ProcessName { get; set; }
+ ///
+ /// 流程描述
+ ///
+ public string ProcessMS { get; set; }
+ ///
+ /// 颜色
+ ///
+ public ALYColor ProcessColor { get; set; }
+ public ProcessModel()
+ {
+ IsMark = false;
+ ProcessMS = string.Empty;
+ ProcessName = string.Empty;
+ }
+
+ }
+
+ ///
+ /// 通知消息
+ ///
+ public class InfoMessage
+ {
+ public List data { get; set; }
+
+ }
+ ///
+ /// 运营设备及状态
+ ///
+ public class OperatingDeviceStatus
+ {
+ public List data { get; set; }
+ }
+ ///
+ /// 设备状态
+ ///
+ public class DevStatus : DeviceBase
+ {
+ ///
+ /// 设备状态
+ ///
+ public string DeviceZT
+ {
+ get { return _DeviceZT; }
+ set
+ {
+ _DeviceZT = value;
+ if (_DeviceZT == "在线") DeviceColor = new ALYColor { r = 13, g = 254, b = 73, a = 1 };
+ else DeviceColor = new ALYColor { r = 249, g = 191, b = 0, a = 1 };
+ }
+ }
+ private string _DeviceZT { get; set; }
+ ///
+ /// 是否有告警
+ ///
+ public bool IsAlarm
+ {
+ get { return _IsAlarm; }
+ set
+ {
+ _IsAlarm = value;
+ if (_IsAlarm) AlarmColor = new ALYColor { r = 245, g = 13, b = 13, a = 1 };
+ else AlarmColor = new ALYColor { r = 245, g = 13, b = 13, a = 0 };
+ }
+ }
+ private bool _IsAlarm { get; set; }
+
+ ///
+ /// 颜色
+ ///
+ public ALYColor DeviceColor { get; set; }
+ ///
+ /// 告警颜色
+ ///
+ public ALYColor AlarmColor { get; set; }
+ ///
+ /// 初始化
+ ///
+ public DevStatus()
+ {
+ IsAlarm = false;
+ AlarmColor = new ALYColor { r = 245, g = 13, b = 13, a = 0 };
+ DeviceColor = new ALYColor { r = 249, g = 191, b = 0, a = 1 };
+ }
+ ///
+ /// 设置属性
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SetTarget(string _deviceName, string _gmtCreate, string _DeviceMC, string _DeviceMS, string _DeviceSJ, string _DeviceZT)
+ {
+ deviceName = _deviceName;
+ gmtCreate = _gmtCreate;
+ DeviceMC = _DeviceMC;
+ DeviceMS = _DeviceMS;
+ DeviceSJ = _DeviceSJ;
+ DeviceZT = _DeviceZT;
+ }
+ ///
+ /// 状态
+ ///
+ ///
+ public void SetStatus(string _DeviceZT)
+ {
+ DeviceSJ = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
+ DeviceZT = _DeviceZT;
+ }
+ }
+ ///
+ /// 设备基本属性
+ ///
+ public class DeviceBase : DevBase
+ {
+ ///
+ /// 设备名称
+ ///
+ public string DeviceMC { get; set; }
+ ///
+ /// 设备描述
+ ///
+ public string DeviceMS { get; set; }
+ ///
+ /// 设备时间
+ ///
+ public string DeviceSJ { get; set; }
+ ///
+ /// 设备状态:已处理 未处理
+ ///
+ public string DeviceZT { get; set; }
+ }
+ ///
+ /// 设备基本信息
+ ///
+ public class DevBase
+ {
+ ///
+ /// 唯一id
+ ///
+ public string id { get; set; }
+ ///
+ /// 设备key
+ ///
+ public string productKey { get; set; }
+ ///
+ /// 设备名称
+ ///
+ public string deviceName { get; set; }
+ ///
+ /// gmtCreate
+ ///
+ public string gmtCreate { get; set; }
+ ///
+ /// 客户端ID
+ ///
+ public string clientId { get; set; }
+
+ public DevBase()
+ {
+ id = Guid.NewGuid().ToString();
+ }
+ }
+
+
+
+}
diff --git a/BPASmartClient.IoT/Model/JsonMsg.cs b/BPASmartClient.IoT/Model/JsonMsg.cs
new file mode 100644
index 00000000..8f1ee188
--- /dev/null
+++ b/BPASmartClient.IoT/Model/JsonMsg.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BPASmartClient.IoT
+{
+ ///
+ /// 返回消息
+ ///
+ public class JsonMsg where T : class
+ {
+ ///
+ /// 状态码
+ ///
+ public int code { get; set; }
+
+ ///
+ /// 消息
+ ///
+ public string msg { get; set; }
+
+ ///
+ /// 描述
+ ///
+ public string ms { get; set; }
+
+ ///
+ /// 内容
+ ///
+ public IOTData obj { get; set; }
+
+ /////
+ ///// 返回数据
+ /////
+ //public IOTData oTData { get; set; }
+
+ ///
+ /// 图标
+ ///
+ public int icon { get; set; }
+
+
+ public static JsonMsg OK(T obj, string msg = "接口名称", string mso = "调用接口成功")
+ {
+ string str = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 接口名称为“ {msg + "”调用成功,描述:" + mso + obj}";
+ ConsoleColor currentForeColor = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine(str);
+ Console.ForegroundColor = currentForeColor;
+ ;
+ return new JsonMsg() { code = 1, ms = mso, msg = "成功", obj = new IOTData { data = obj }, icon = 1};
+ }
+
+ public static JsonMsg Error(T obj, string msg = "接口名称", string mso = "调用接口成功失败")
+ {
+ string str = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 接口名称为“ {msg + "”调用失败,描述:" + mso + obj}";
+ ConsoleColor currentForeColor = Console.ForegroundColor;
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(str);
+ Console.ForegroundColor = currentForeColor;
+ return new JsonMsg() { code = 0, ms = mso, msg = "失败",icon = 1, obj = new IOTData { data = obj } };
+ }
+ }
+
+ public class IOTData where T : class
+ {
+ public T data { get; set; }
+ }
+}
diff --git a/BPASmartClient.IoT/Model/LargeScreenTable.cs b/BPASmartClient.IoT/Model/LargeScreenTable.cs
new file mode 100644
index 00000000..10faa77a
--- /dev/null
+++ b/BPASmartClient.IoT/Model/LargeScreenTable.cs
@@ -0,0 +1,14 @@
+namespace BPASmartClient.IoT
+{
+ ///
+ /// 大屏消息表
+ ///
+ public class LargeScreenTable : BaseEntity
+ {
+ ///
+ /// Json值
+ ///
+ public string json { get; set; }
+ }
+
+}
diff --git a/BPASmartClient.IoT/Model/LogTable.cs b/BPASmartClient.IoT/Model/LogTable.cs
new file mode 100644
index 00000000..7aec43c0
--- /dev/null
+++ b/BPASmartClient.IoT/Model/LogTable.cs
@@ -0,0 +1,29 @@
+namespace BPASmartClient.IoT
+{
+ ///
+ /// 日志表
+ ///
+ public class LogTable : BaseEntity
+ {
+ ///
+ /// 日志时间
+ ///
+ public string LogTime { get; set; }
+ ///
+ /// 日志类型:1 轻微 2:一般 3 严重
+ ///
+ public string LogType { get; set; }
+ ///
+ /// 日志消息
+ ///
+ public string LogMessage { get; set; }
+ ///
+ /// 日志值
+ ///
+ public string LogVla { get; set; }
+ ///
+ /// IP 地址
+ ///
+ public string IP { get; set; }
+ }
+}
diff --git a/BPASmartClient/App.config b/BPASmartClient/App.config
index 6f8c7af3..aa86f0ed 100644
--- a/BPASmartClient/App.config
+++ b/BPASmartClient/App.config
@@ -15,9 +15,10 @@
+
-
+