fyf 2 роки тому
джерело
коміт
996c4cb58e
18 змінених файлів з 2192 додано та 9 видалено
  1. +328
    -0
      BPASmartClient.Helper/HttpRequestHelper.cs
  2. +93
    -0
      BPASmartClient.Helper/Tools.cs
  3. +11
    -0
      BPASmartClient.IoT/BPASmartClient.IoT.csproj
  4. +0
    -8
      BPASmartClient.IoT/Class1.cs
  5. +30
    -0
      BPASmartClient.IoT/DataVClient.cs
  6. +365
    -0
      BPASmartClient.IoT/DataVReport.cs
  7. +35
    -0
      BPASmartClient.IoT/Model/AlarmTable.cs
  8. +43
    -0
      BPASmartClient.IoT/Model/BaseEntity.cs
  9. +27
    -0
      BPASmartClient.IoT/Model/CommandModel.cs
  10. +39
    -0
      BPASmartClient.IoT/Model/DeviceTable.cs
  11. +27
    -0
      BPASmartClient.IoT/Model/IOT/CommandModel.cs
  12. +336
    -0
      BPASmartClient.IoT/Model/IOT/IOTDevModel.cs
  13. +467
    -0
      BPASmartClient.IoT/Model/IOT/IOTDevServer.cs
  14. +275
    -0
      BPASmartClient.IoT/Model/IOT/ScreenMonitorModel.cs
  15. +71
    -0
      BPASmartClient.IoT/Model/JsonMsg.cs
  16. +14
    -0
      BPASmartClient.IoT/Model/LargeScreenTable.cs
  17. +29
    -0
      BPASmartClient.IoT/Model/LogTable.cs
  18. +2
    -1
      BPASmartClient/App.config

+ 328
- 0
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
{
/// <summary>
/// 该类实现客户端http 同步请求
/// 支持环境 -.net4.0/-.net4.5
/// 创建人:奉友福
/// </summary>
public class HttpRequestHelper
{
#region 私有变量
#endregion

#region 公用函数
/// <summary>
/// GET 同步请求
/// 创建人:奉友福
/// 创建时间:2020-11-19
/// </summary>
/// <param name="url">请求地址</param>
/// <returns>超时时间设置,默认5秒</returns>
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;
}
/// <summary>
/// POST 同步请求
/// 创建人:奉友福
/// 创建时间:2020-11-19
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="PostJsonData">请求数据</param>
/// <returns></returns>
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;
}

/// <summary>
/// GET 同步请求
/// </summary>
/// <param name="url">地址</param>
/// <param name="head">头</param>
/// <param name="headInfo">内容</param>
/// <returns></returns>
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;
}



/// <summary>
/// Post请求带Token
/// 2021-2-2 by dulf
/// </summary>
/// <param name="url"></param>
/// <param name="head"></param>
/// <param name="headInfo"></param>
/// <param name="postParam"></param>
/// <returns></returns>
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("请求<HttpPostResponseWithHead>异常:" + ex.Message);
}
return "";
}
#endregion

}
/// <summary>
/// HTTP请求类
/// </summary>
public class HttpRequest
{
#region 私有变量
/// <summary>
/// http请求超时时间设置
/// 默认值:5秒
/// </summary>
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 公用函数
/// <summary>
/// 函数名称:创建http请求
/// 创建人:奉友福
/// 创建时间:2020-11-19
/// 例如GET 请求: 地址 + "GET"
/// 例如POST请求: 地址 + "POST" + JSON
/// </summary>
/// <param name="url">http请求地址</param>
/// <param name="requestType">http请求方式:GET/POST</param>
/// <param name="strjson">http请求附带数据</param>
/// <returns></returns>
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;
}
/// <summary>
/// http获取数据
/// </summary>
/// <param name="response"></param>
/// <param name="requestType"></param>
/// <returns></returns>
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 私有函数
/// <summary>
/// http+GET请求
/// </summary>
/// <param name="url">请求地址</param>
/// <returns>请求结果</returns>
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;
}
/// <summary>
/// http+POST请求
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="postData"></param>
/// <returns>请求结果</returns>
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
}
}

+ 93
- 0
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
{
/// <summary>
/// 工具
/// </summary>
public class Tools
{
/// <summary>
/// 对象Json序列
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="obj">对象实例</param>
/// <returns></returns>
public static string JsonConvertTools<T>(T obj)
{
string strvalue = JsonConvert.SerializeObject(obj);
return strvalue;
}

/// <summary>
/// 对象反Json序列
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="jsonstring">对象序列化json字符串</param>
/// <returns>返回对象实例</returns>
public static T JsonToObjectTools<T>(string jsonstring)
{
T obj = JsonConvert.DeserializeObject<T>(jsonstring);
return obj;
}

/// <summary>
/// DateTime --> long
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
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;
}

/// <summary>
/// long --> DateTime
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
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;
}

/// <summary>
/// 获取IP 地址
/// </summary>
/// <returns></returns>
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";
}
}
}

+ 11
- 0
BPASmartClient.IoT/BPASmartClient.IoT.csproj Переглянути файл

@@ -4,4 +4,15 @@
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="M2Mqtt" Version="4.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BPASmartClient.Business\BPASmartClient.Business.csproj" />
<ProjectReference Include="..\BPASmartClient.Helper\BPASmartClient.Helper.csproj" />
</ItemGroup>

</Project>

+ 0
- 8
BPASmartClient.IoT/Class1.cs Переглянути файл

@@ -1,8 +0,0 @@
using System;

namespace BPASmartClient.IoT
{
public class Class1
{
}
}

+ 30
- 0
BPASmartClient.IoT/DataVClient.cs Переглянути файл

@@ -0,0 +1,30 @@
using System;

namespace BPASmartClient.IoT
{
/// <summary>
/// DataV客户端数据中心
/// </summary>
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()
{
}
}
}

+ 365
- 0
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
{
/// <summary>
/// DataV客户端
/// </summary>
public class DataVReport
{
#region 外部调用
/// <summary>
/// 初始化IOT连接
/// </summary>
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;
}

/// <summary>
/// 获取连接状态
/// </summary>
public bool GetIsConnected()
{
try
{
if (DatavDeviceClient == null || !DatavDeviceClient.IsConnected)
return false;
else return true;
}
catch (Exception ex)
{
return false;
throw;
}
}

/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
if (DatavDeviceClient != null)
{
DatavDeviceClient.Disconnect();
}
}

/// <summary>
/// 发布消息
/// </summary>
/// <param name="topic"></param>
/// <param name="message"></param>
public void IOT_Publish(string topic, string message)
{
var id = DatavDeviceClient.Publish(topic, Encoding.UTF8.GetBytes(message));
}

/// <summary>
/// 订阅主题
/// </summary>
/// <param name="topic"></param>
public void IOT_Subscribe(string topic)
{
if (SubTopicList.Contains(topic))
{
SubTopicList.Add(topic);
}
DatavDeviceClient.Subscribe(new string[] { topic }, new byte[] { 0 });
}
#endregion
#region 私有函数
/// <summary>
/// 设置变量
/// </summary>
/// <param name="_ProductKey"></param>
/// <param name="_DeviceName"></param>
/// <param name="_DeviceSecret"></param>
/// <param name="_RegionId"></param>
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";
}

/// <summary>
/// 创建连接
/// </summary>
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<List<DeviceTable>> jsonMsg = Tools.JsonToObjectTools<JsonMsg<List<DeviceTable>>>(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<string, string> dict = new Dictionary<string, string>();
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;
}
}

/// <summary>
/// MQTT创建连接
/// </summary>
/// <param name="targetServer"></param>
/// <param name="mqttClientId"></param>
/// <param name="mqttUserName"></param>
/// <param name="mqttPassword"></param>
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;
}

/// <summary>
/// MQTT 断开事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Client_ConnectionClosed(object sender, EventArgs e)
{
// 尝试重连
_TryContinueConnect();
}

/// <summary>
/// 订阅数据接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}

/// <summary>
/// 自动重连主体
/// </summary>
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 公有变量
/// <summary>
/// 设备消息数据回调
/// </summary>
public static Action<string, string> DataVMessageAction { get; set; }
/// <summary>
/// 重连事件
/// </summary>
public static Action<string> UnConnectMqtt { get; set; }
/// <summary>
/// 客户端
/// </summary>
public static MqttClient DatavDeviceClient { get; set; }
/// <summary>
/// 当前设备
/// </summary>
public DeviceTable deviceTable { get; set; }
#endregion

#region 发布或订阅主题或URL地址
/// <summary>
/// 属性发布消息主题
/// </summary>
public static string PubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
/// <summary>
/// 属性接收消息主题
/// </summary>
public static string SubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
/// <summary>
/// 自定义发布消息主题
/// </summary>
public static string UserPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
/// <summary>
/// 自定义接收消息主题
/// </summary>
public static string UserSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
/// <summary>
/// 告警订阅主题
/// </summary>
public static string AlarmSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/AlarmMessage";
/// <summary>
/// 日志订阅主题
/// </summary>
public static string LogsSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ExceptionLogs";
/// <summary>
/// 上下线订阅主题
/// </summary>
public static string HeartbeatSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/HeartbeatAndState";
/// <summary>
/// 属性状态主题
/// </summary>
public static string TargetStatusSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/TargetStatus";
/// <summary>
/// 大屏展示发布主题
/// </summary>
public static string ScreenShowPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ScreenShow";
/// <summary>
/// 广播主题
/// </summary>
public static string BroadcastTopic = "/broadcast/" + "grgpECHSL7q" + "/" + DeviceName + "_SetDevice";
/// <summary>
/// 订阅主题集合
/// </summary>
public static List<string> SubTopicList = new List<string>();
#endregion
}

/// <summary>
/// Iot 设备上报
/// </summary>
public class IotSignUtils
{
public static string sign(Dictionary<string, string> 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();
}
}
}

+ 35
- 0
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
{
/// <summary>
/// 告警消息表
/// </summary>
public class AlarmTable : BaseEntity
{
/// <summary>
/// 告警时间
/// </summary>
public string AlarmTime { get; set; }
/// <summary>
/// 告警类型:1 轻微 2:一般 3 严重
/// </summary>
public string AlarmType { get; set; }
/// <summary>
/// 告警消息
/// </summary>
public string AlarmMessage { get; set; }
/// <summary>
/// 告警值
/// </summary>
public string AlarmVla { get; set; }
/// <summary>
/// IP 地址
/// </summary>
public string IP { get; set; }
}
}

+ 43
- 0
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
{
/// <summary>
/// MongoDB基类
/// </summary>
public abstract class BaseEntity
{
/// <summary>
/// ID
/// </summary>
public string Id { get; set; }
/// <summary>
/// 客户端 ID
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// 设备 ID
/// </summary>
public string DeviceId { get; set; }
/// <summary>
/// 阿里云设备名称
/// </summary>
public string devicename { get; set; }
/// <summary>
/// 状态
/// </summary>
public string State { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public DateTime UpdateTime { get; set; }
}
}

+ 27
- 0
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
{
/// <summary>
/// 命令实体类
/// </summary>
public class CommandModel
{
/// <summary>
/// 设备名称
/// </summary>
public string deviceName { get; set; }
/// <summary>
/// 命令名称:0 控制类 1 设置属性 2 通知信息类
/// </summary>
public int CommandName { get; set; }
/// <summary>
/// 命令变量:执行变量 key为属性或时间 value为值或者消息
/// </summary>
public Dictionary<string, string> CommandValue { get; set; }
}
}

+ 39
- 0
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
{
/// <summary>
/// 设备信息表
/// </summary>
public class DeviceTable : BaseEntity
{
/// <summary>
/// 阿里云设备key
/// </summary>
public string productkey { get; set; }
/// <summary>
/// 阿里云设备secret
/// </summary>
public string devicesecret { get; set; }
/// <summary>
/// 客户端类型
/// </summary>
public string devtype { get; set; }
/// <summary>
/// 经度
/// </summary>
public string jd { get; set; }
/// <summary>
/// 维度
/// </summary>
public string wd { get; set; }
/// <summary>
/// 备注
/// </summary>
public string remark { get; set; }
}
}

+ 27
- 0
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
{
/// <summary>
/// 命令实体类
/// </summary>
public class IOTCommandModel
{
/// <summary>
/// 设备名称
/// </summary>
public string deviceName { get; set; }
/// <summary>
/// 命令名称:0 控制类 1 设置属性 2 通知信息类
/// </summary>
public int CommandName { get; set; }
/// <summary>
/// 命令变量:执行变量 key为属性或时间 value为值或者消息
/// </summary>
public Dictionary<string, string> CommandValue { get; set; }
}
}

+ 336
- 0
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
{
/// <summary>
/// IOT Model
/// </summary>
public class IotModel<T>
{
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";
}
/// <summary>
/// IOT 接收数据Model
/// </summary>
public class ReceiveModel
{
/// <summary>
/// 设备详细信息
/// </summary>
public DevBase deviceContext { get; set; }
/// <summary>
/// 设备属性
/// </summary>
public ReceiveSXModel props { get; set; }
/// <summary>
/// 设备上下线状态
/// </summary>
public Vls status { get; set; }

}
/// <summary>
/// 接收数据Model
/// </summary>
public class ReceiveSXModel
{
/// <summary>
/// 告警消息
/// </summary>
public Vls GJXX { get; set; }
/// <summary>
/// 扩展属性
/// </summary>
public Vls KZSX { get; set; }
/// <summary>
/// 基本属性
/// </summary>
public Vls JBSX { get; set; }
/// <summary>
/// 节点状态
/// </summary>
public Vls NodeStatus { get; set; }
/// <summary>
/// 日志消息
/// </summary>
public Vls SZXX { get; set; }
}
/// <summary>
/// IOT 设备属性 Model
/// </summary>
public class IOTDevSXModel
{
/// <summary>
/// 硬件状态
/// </summary>
public string HardwareStatus { get; set; }
/// <summary>
/// 扩展属性
/// </summary>
public string KZSX { get; set; }
/// <summary>
/// 基本属性
/// </summary>
public string JBSX { get; set; }
/// <summary>
/// 节点状态
/// </summary>
public string NodeStatus { get; set; }
/// <summary>
/// Model
/// </summary>
public IOTDevSXModel()
{

}
/// <summary>
/// 序列化为JSON
/// </summary>
/// <returns></returns>
public string Tojson()
{
try
{
IotModel<IOTDevSXModel> iotModel = new IotModel<IOTDevSXModel> { @params = this };
string json = Tools.JsonConvertTools(iotModel);
return json;
}
catch (Exception ex)
{
return string.Empty;
}
}
/// <summary>
/// 设置基本属性
/// </summary>
/// <param name="devSX"></param>
/// <returns></returns>
public void SetJBSX(DevSX devSX)
{
try
{
JBSX = Tools.JsonConvertTools(devSX);
}
catch (Exception ex)
{
JBSX = string.Empty;
}
}
/// <summary>
/// 设置基本属性状态
/// </summary>
/// <param name="devSX"></param>
/// <returns></returns>
public void SetJBSXStatus(DevSXBase sXBase, bool Status)
{
try
{
if (sXBase == null) return;
DevSX dev = Tools.JsonToObjectTools<DevSX>(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;
}
}
/// <summary>
/// 设置扩展属性
/// </summary>
/// <param name="devSX"></param>
public void SetKZSX(DevSX devSX)
{
try
{
KZSX = Tools.JsonConvertTools(devSX);
}
catch (Exception ex)
{
KZSX = string.Empty;
}
}
/// <summary>
/// 设置扩展属性状态
/// </summary>
/// <param name="devSX"></param>
/// <returns></returns>
public void SetKZSXStatus(DevSXBase sXBase, bool Status)
{
try
{
if (sXBase == null) return;
DevSX dev = Tools.JsonToObjectTools<DevSX>(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;
}
}
}
/// <summary>
/// 告警消息
/// </summary>
public class AlarmMessage
{
public List<AlarmModel> data { get; set; }
}
/// <summary>
/// 告警Model
/// </summary>
public class AlarmModel : DeviceBase
{
/// <summary>
/// 告警程度:提示 一般 严重
/// </summary>
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; }
/// <summary>
/// 颜色
/// </summary>
public ALYColor DeviceColor { get; set; }
}
/// <summary>
/// 设备上报属性
/// </summary>
public class DevSX
{
public List<DevSXBase> data { get; set; }
}
/// <summary>
/// 设备基本属性Model
/// </summary>
public class DevSXBase
{
/// <summary>
/// 属性名称
/// </summary>
public string SXMC { get; set; }
/// <summary>
/// 属性类型
/// </summary>
public string SXLX { get; set; }
/// <summary>
/// 属性状态
/// </summary>
private bool _SXStatus { get; set; }
public bool SXStatus
{
get { return _SXStatus; }
set
{
_SXStatus = value;
if (_SXStatus)
{
SXZT = "正常";
}
else
{
SXZT = "异常";
}
}
}
private string _SXZT { get; set; }
/// <summary>
/// 属性状态:正常 异常
/// </summary>
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 };
}
}
}
/// <summary>
/// 属性异常描述
/// </summary>
public string SXYCMS { get; set; }
public string YCZT { get; set; }
/// <summary>
/// 属性颜色
/// </summary>
public ALYColor SXYC { get; set; }
/// <summary>
/// 按钮文字
/// </summary>
public string ButtonText { get; set; }
/// <summary>
/// 按钮颜色
/// </summary>
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 };
}
}

/// <summary>
/// 设备颜色
/// </summary>
public class ALYColor
{
public int r { get; set; }
public int g { get; set; }
public int b { get; set; }
public double a { get; set; }
}

/// <summary>
/// 变量
/// </summary>
public class Vls
{
public long time { get; set; }
public string value { get; set; }
}
}

+ 467
- 0
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
{
/// <summary>
/// add fengyoufu
/// 黑菠萝科技有限公司
/// IOT设备上报消息类
/// </summary>
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 公有变量
/// <summary>
/// 设备消息数据回调
/// </summary>
public static Action<string, string> DevIOTAction { get; set; }
/// <summary>
/// 重连事件
/// </summary>
public static Action<string> UNConnectMqtt { get; set; }
/// <summary>
/// 客户端
/// </summary>
public static MqttClient client { get; set; }
#endregion

#region 发布或订阅主题或URL地址
/// <summary>
/// API 服务
/// </summary>
private static string APIurl = "http://124.222.238.75:6002";
/// <summary>
/// 属性发布消息主题
/// </summary>
public static string PubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
/// <summary>
/// 属性接收消息主题
/// </summary>
public static string SubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
/// <summary>
/// 自定义发布消息主题
/// </summary>
public static string UserPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/update";
/// <summary>
/// 自定义接收消息主题
/// </summary>
public static string UserSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/get";
/// <summary>
/// 告警订阅主题
/// </summary>
public static string AlarmSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/AlarmMessage";
/// <summary>
/// 日志订阅主题
/// </summary>
public static string LogsSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ExceptionLogs";
/// <summary>
/// 上下线订阅主题
/// </summary>
public static string HeartbeatSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/HeartbeatAndState";
/// <summary>
/// 属性状态主题
/// </summary>
public static string TargetStatusSubTopic = "/" + ProductKey + "/" + DeviceName + "/user/TargetStatus";
/// <summary>
/// 大屏展示发布主题
/// </summary>
public static string ScreenShowPubTopic = "/" + ProductKey + "/" + DeviceName + "/user/ScreenShow";
/// <summary>
/// 广播主题
/// </summary>
public static string BroadcastTopic = "/broadcast/" + "grgpECHSL7q" + "/" + DeviceName + "_SetDevice";
/// <summary>
/// 订阅主题集合
/// </summary>
public static List<string> SubTopicList = new List<string>();
#endregion

#region 单例模式
private static IOTDevServer iot = null;
public static IOTDevServer GetInstance()
{
if (iot == null) { iot = new IOTDevServer(); }
return iot;
}
#endregion

#region 公共调用阿里云连接或检测
/// <summary>
/// 设置URL
/// </summary>
/// <param name="url"></param>
public void SetUrl(string url = "http://124.222.238.75:6002")
{
APIurl = url;
}

/// <summary>
/// 设置变量
/// </summary>
/// <param name="_ProductKey"></param>
/// <param name="_DeviceName"></param>
/// <param name="_DeviceSecret"></param>
/// <param name="_RegionId"></param>
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";
}

/// <summary>
/// 创建连接
/// </summary>
/// <returns></returns>
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<List<DeviceTable>> jsonMsg = Tools.JsonToObjectTools<JsonMsg<List<DeviceTable>>>(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<string, string> dict = new Dictionary<string, string>();
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;
}
}

/// <summary>
/// 获取连接状态
/// </summary>
public bool GetIsConnected()
{
try
{
if (client == null || !client.IsConnected)
return false;
else return true;
}
catch (Exception ex)
{
return false;
throw;
}
}

/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
if (client != null)
{
client.Disconnect();
}
}
#endregion

#region 公共发布或订阅函数
/// <summary>
/// 发布消息
/// </summary>
/// <param name="topic"></param>
/// <param name="message"></param>
public void IOT_Publish(string topic, string message)
{
var id = client.Publish(topic, Encoding.UTF8.GetBytes(message));
}

/// <summary>
/// 订阅主题
/// </summary>
/// <param name="topic"></param>
public void IOT_Subscribe(string topic)
{
if (SubTopicList.Contains(topic))
{
SubTopicList.Add(topic);
}
client.Subscribe(new string[] { topic }, new byte[] { 0 });
}
#endregion

#region 私有函数
/// <summary>
/// mQTT创建连接
/// </summary>
/// <param name="targetServer"></param>
/// <param name="mqttClientId"></param>
/// <param name="mqttUserName"></param>
/// <param name="mqttPassword"></param>
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;
}

/// <summary>
/// MQTT 断开事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Client_ConnectionClosed(object sender, EventArgs e)
{
// 尝试重连
_TryContinueConnect();
}

/// <summary>
/// 订阅数据接收
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}

/// <summary>
/// 自动重连主体
/// </summary>
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
}

/// <summary>
/// Iot 设备上报
/// </summary>
public class IotSignUtils
{
public static string sign(Dictionary<string, string> 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();
}
}

/// <summary>
/// 工具
/// </summary>
public class Tools
{
/// <summary>
/// 对象Json序列
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="obj">对象实例</param>
/// <returns></returns>
public static string JsonConvertTools<T>(T obj)
{
string strvalue = JsonConvert.SerializeObject(obj);
return strvalue;
}

/// <summary>
/// 对象反Json序列
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <param name="jsonstring">对象序列化json字符串</param>
/// <returns>返回对象实例</returns>
public static T JsonToObjectTools<T>(string jsonstring)
{
T obj = JsonConvert.DeserializeObject<T>(jsonstring);
return obj;
}

/// <summary>
/// DateTime --> long
/// </summary>
/// <param name="dt"></param>
/// <returns></returns>
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;
}

/// <summary>
/// long --> DateTime
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
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;
}

/// <summary>
/// 获取IP 地址
/// </summary>
/// <returns></returns>
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";
}
}


}

+ 275
- 0
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
{

/// <summary>
/// 大屏监视Model
/// </summary>
public class ScreenMonitorModel
{
/// <summary>
/// 服务商家数
/// </summary>
public string TotalSales { get; set; }
/// <summary>
/// 现场运营设备状态
/// </summary>
public OperatingDeviceStatus operatingDeviceStatus { get; set; }
/// <summary>
/// 通知消息
/// </summary>
public InfoMessage infoMessage { get; set; }
/// <summary>
/// 返回JSON
/// </summary>
/// <returns></returns>
public string ToJSON()
{
try
{
return Tools.JsonConvertTools(this);
}
catch (Exception ex)
{
return string.Empty;
}
}
/// <summary>
/// 序列化为对象
/// </summary>
/// <param name="JSON"></param>
/// <returns></returns>
public ScreenMonitorModel JSONtoDX(string JSON)
{
try
{
return Tools.JsonToObjectTools<ScreenMonitorModel>(JSON);
}
catch (Exception ex)
{
return new ScreenMonitorModel();
}
}
}
/// <summary>
/// 下订单统计
/// </summary>
public class PlaceOrderCount
{
/// <summary>
/// 今日下单量统计
/// </summary>
public string ToDayPlaceCount { get; set; }
/// <summary>
/// 本月下单量统计
/// </summary>
public string MonthPlaceCount { get; set; }
/// <summary>
/// 本年下单量统计
/// </summary>
public string YearPlaceCount { get; set; }

}
/// <summary>
/// 制作流程
/// </summary>
public class ProcessMessage
{
public List<ProcessModel> data { get; set; }
}
/// <summary>
/// 制作流程Model
/// </summary>
public class ProcessModel
{
/// <summary>
/// 告警程度:提示 一般 严重
/// </summary>
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 };
}
}
/// <summary>
/// 流程名称
/// </summary>
public string ProcessName { get; set; }
/// <summary>
/// 流程描述
/// </summary>
public string ProcessMS { get; set; }
/// <summary>
/// 颜色
/// </summary>
public ALYColor ProcessColor { get; set; }
public ProcessModel()
{
IsMark = false;
ProcessMS = string.Empty;
ProcessName = string.Empty;
}

}

/// <summary>
/// 通知消息
/// </summary>
public class InfoMessage
{
public List<DeviceBase> data { get; set; }

}
/// <summary>
/// 运营设备及状态
/// </summary>
public class OperatingDeviceStatus
{
public List<DevStatus> data { get; set; }
}
/// <summary>
/// 设备状态
/// </summary>
public class DevStatus : DeviceBase
{
/// <summary>
/// 设备状态
/// </summary>
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; }
/// <summary>
/// 是否有告警
/// </summary>
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; }

/// <summary>
/// 颜色
/// </summary>
public ALYColor DeviceColor { get; set; }
/// <summary>
/// 告警颜色
/// </summary>
public ALYColor AlarmColor { get; set; }
/// <summary>
/// 初始化
/// </summary>
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 };
}
/// <summary>
/// 设置属性
/// </summary>
/// <param name="_deviceName"></param>
/// <param name="_gmtCreate"></param>
/// <param name="_DeviceMC"></param>
/// <param name="_DeviceMS"></param>
/// <param name="_DeviceSJ"></param>
/// <param name="_DeviceZT"></param>
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;
}
/// <summary>
/// 状态
/// </summary>
/// <param name="_DeviceZT"></param>
public void SetStatus(string _DeviceZT)
{
DeviceSJ = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
DeviceZT = _DeviceZT;
}
}
/// <summary>
/// 设备基本属性
/// </summary>
public class DeviceBase : DevBase
{
/// <summary>
/// 设备名称
/// </summary>
public string DeviceMC { get; set; }
/// <summary>
/// 设备描述
/// </summary>
public string DeviceMS { get; set; }
/// <summary>
/// 设备时间
/// </summary>
public string DeviceSJ { get; set; }
/// <summary>
/// 设备状态:已处理 未处理
/// </summary>
public string DeviceZT { get; set; }
}
/// <summary>
/// 设备基本信息
/// </summary>
public class DevBase
{
/// <summary>
/// 唯一id
/// </summary>
public string id { get; set; }
/// <summary>
/// 设备key
/// </summary>
public string productKey { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string deviceName { get; set; }
/// <summary>
/// gmtCreate
/// </summary>
public string gmtCreate { get; set; }
/// <summary>
/// 客户端ID
/// </summary>
public string clientId { get; set; }

public DevBase()
{
id = Guid.NewGuid().ToString();
}
}



}

+ 71
- 0
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
{
/// <summary>
/// 返回消息
/// </summary>
public class JsonMsg<T> where T : class
{
/// <summary>
/// 状态码
/// </summary>
public int code { get; set; }

/// <summary>
/// 消息
/// </summary>
public string msg { get; set; }

/// <summary>
/// 描述
/// </summary>
public string ms { get; set; }

/// <summary>
/// 内容
/// </summary>
public IOTData<T> obj { get; set; }

///// <summary>
///// 返回数据
///// </summary>
//public IOTData<T> oTData { get; set; }

/// <summary>
/// 图标
/// </summary>
public int icon { get; set; }


public static JsonMsg<T> 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<T>() { code = 1, ms = mso, msg = "成功", obj = new IOTData<T> { data = obj }, icon = 1};
}

public static JsonMsg<T> 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<T>() { code = 0, ms = mso, msg = "失败",icon = 1, obj = new IOTData<T> { data = obj } };
}
}

public class IOTData<T> where T : class
{
public T data { get; set; }
}
}

+ 14
- 0
BPASmartClient.IoT/Model/LargeScreenTable.cs Переглянути файл

@@ -0,0 +1,14 @@
namespace BPASmartClient.IoT
{
/// <summary>
/// 大屏消息表
/// </summary>
public class LargeScreenTable : BaseEntity
{
/// <summary>
/// Json值
/// </summary>
public string json { get; set; }
}

}

+ 29
- 0
BPASmartClient.IoT/Model/LogTable.cs Переглянути файл

@@ -0,0 +1,29 @@
namespace BPASmartClient.IoT
{
/// <summary>
/// 日志表
/// </summary>
public class LogTable : BaseEntity
{
/// <summary>
/// 日志时间
/// </summary>
public string LogTime { get; set; }
/// <summary>
/// 日志类型:1 轻微 2:一般 3 严重
/// </summary>
public string LogType { get; set; }
/// <summary>
/// 日志消息
/// </summary>
public string LogMessage { get; set; }
/// <summary>
/// 日志值
/// </summary>
public string LogVla { get; set; }
/// <summary>
/// IP 地址
/// </summary>
public string IP { get; set; }
}
}

+ 2
- 1
BPASmartClient/App.config Переглянути файл

@@ -15,9 +15,10 @@
<add key="ApolloUri" value="http://10.2.1.21:28080"/>
<add key="OrderServiceUri" value="http://10.2.1.26:21527/order/"/>
<add key="StockServiceUri" value="http://10.2.1.26:21527/stock/"/>
<add key="DataVServiceUri" value="http://111.9.47.105:21527/datav"/>


<add key="COM_Coffee" value="COM3"/>
<add key="COM_Coffee" value="COM3"/>
<add key="BAUD_Coffee" value="115200"/>
<add key="COM_IceCream" value="COM12"/>
<add key="BAUD_IceCream" value="9600"/>


Завантаження…
Відмінити
Зберегти