@@ -1,4 +1,4 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>net6.0</TargetFramework> | |||
@@ -1,30 +1,213 @@ | |||
using System; | |||
using BPASmartClient.Business; | |||
using BPASmartClient.Helper; | |||
using BPASmartClient.Message; | |||
using BPASmartDatavDeviceClient.IoT; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Threading; | |||
namespace BPASmartClient.IoT | |||
{ | |||
/// <summary> | |||
/// DataV客户端数据中心 | |||
/// </summary> | |||
public class DataVClient | |||
public class DataVClient | |||
{ | |||
#region 单例模式 | |||
private volatile static DataVClient _Instance; | |||
public static DataVClient GetInstance => _Instance ?? (_Instance = new DataVClient()); | |||
public static DataVClient GetInstance() => _Instance ?? (_Instance = new DataVClient()); | |||
public DataVClient() | |||
{ | |||
DataVApiAddress = System.Configuration.ConfigurationManager.AppSettings["DataVServiceUri"].ToString(); | |||
ClientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"].ToString(); | |||
Initialize(); | |||
} | |||
#endregion | |||
#region 公有变量 | |||
//DataV 服务地址 | |||
/// <summary> | |||
/// DataV 服务地址 | |||
/// </summary> | |||
public string DataVApiAddress { set; get; } | |||
/// <summary> | |||
/// 客户端ID | |||
/// </summary> | |||
public string ClientId { set; get; } | |||
/// <summary> | |||
/// MQTT上报集合 | |||
/// </summary> | |||
public DataVReport DeviceDataV=new DataVReport(); | |||
#endregion | |||
public DataVClient() | |||
#region API调用 | |||
/// <summary> | |||
/// 增加告警信息 | |||
/// </summary> | |||
/// <param name="alarmTable"></param> | |||
/// <returns>返回ID</returns> | |||
public string HttpAddAlarm(AlarmTable alarmTable) | |||
{ | |||
DataVApiAddress = System.Configuration.ConfigurationManager.AppSettings["DataVServiceUri"].ToString(); | |||
string id = string.Empty; | |||
try | |||
{ | |||
if (DeviceDataV != null && DeviceDataV.GetIsConnected()) | |||
{ | |||
string url = DataVApiAddress + "/api/Alarm/Create"; | |||
alarmTable.ClientId = ClientId; | |||
alarmTable.devicename = DeviceDataV.deviceTable.devicename; | |||
string redata = HttpRequestHelper.HttpPostRequest(url, Tools.JsonConvertTools(alarmTable)); | |||
if (!string.IsNullOrEmpty(redata)) | |||
{ | |||
JsonMsg<AlarmTable> msg = Tools.JsonToObjectTools<JsonMsg<AlarmTable>>(redata); | |||
id = msg?.obj?.data?.Id; | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
MessageLog.GetInstance.Show(ex.Message); | |||
} | |||
return id; | |||
} | |||
/// <summary> | |||
/// 根据ID删除告警信息 | |||
/// </summary> | |||
/// <param name="alarm"></param> | |||
public void HttpDeleteAlarm(string id) | |||
{ | |||
try | |||
{ | |||
if (string.IsNullOrEmpty(id)) { MessageLog.GetInstance.Show("API调用删除告警信息,ID不能为空!"); return; } | |||
string url = DataVApiAddress + "/api/Alarm/Delete?id=" + id; | |||
HttpRequestHelper.HttpGetRequest(url); | |||
} | |||
catch (Exception ex) | |||
{ | |||
MessageLog.GetInstance.Show(ex.Message); | |||
} | |||
} | |||
/// <summary> | |||
/// 增加日志信息 | |||
/// </summary> | |||
/// <param name="alarmTable"></param> | |||
/// <returns>返回ID</returns> | |||
public string HttpAddLog(LogTable logTable) | |||
{ | |||
string id = string.Empty; | |||
try | |||
{ | |||
if (DeviceDataV != null && DeviceDataV.GetIsConnected()) | |||
{ | |||
string url = DataVApiAddress + "/api/Log/Create"; | |||
logTable.ClientId = ClientId; | |||
logTable.devicename = DeviceDataV.deviceTable.devicename; | |||
string redata = HttpRequestHelper.HttpPostRequest(url, Tools.JsonConvertTools(logTable)); | |||
if (!string.IsNullOrEmpty(redata)) | |||
{ | |||
JsonMsg<LogTable> msg = Tools.JsonToObjectTools<JsonMsg<LogTable>>(redata); | |||
id = msg?.obj?.data?.Id; | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
MessageLog.GetInstance.Show(ex.Message); | |||
} | |||
return id; | |||
} | |||
#endregion | |||
#region 公用 | |||
/// <summary> | |||
/// 释放 | |||
/// </summary> | |||
public void Dispose() | |||
{ | |||
ThreadManage.GetInstance().StopTask("DataV数据上报"); | |||
} | |||
/// <summary> | |||
/// 初始化 | |||
/// </summary> | |||
public void Initialize() | |||
{ | |||
string message = string.Empty; | |||
if (DeviceDataV.Initialize(DataVApiAddress, ClientId, "", ref message)) | |||
{ | |||
DeviceDataV.DataVMessageAction += DevIOTActionHandler; | |||
MessageLog.GetInstance.Show($"客户端:【{ClientId}】,设备名称{DeviceDataV.deviceTable.devicename}阿里云连接成功"); | |||
} | |||
else MessageLog.GetInstance.ShowEx(message); | |||
} | |||
/// <summary> | |||
/// 启动DataV数据上报 | |||
/// </summary> | |||
public void Start() | |||
{ | |||
ThreadManage.GetInstance().StartLong(new Action(() => | |||
{ | |||
Plugin.GetInstance()?.GetPlugin<DeviceMgr>()?.GetDevices()?.ForEach(device => | |||
{ | |||
Dictionary<string, object> status = device.Status.GetStatus(); | |||
if (DeviceDataV.GetIsConnected()) | |||
{ | |||
// DeviceDataVs[device.DeviceId.ToString()]. | |||
} | |||
}); | |||
Thread.Sleep(5000); | |||
}), "DataV数据上报", true); | |||
} | |||
#endregion | |||
#region 私有 | |||
/// <summary> | |||
/// 接收云端消息 | |||
/// </summary> | |||
/// <param name="topic"></param> | |||
/// <param name="message"></param> | |||
private void DevIOTActionHandler(string deviceId, string topic, string message) | |||
{ | |||
if (DeviceDataV.BroadcastTopic == topic && !string.IsNullOrEmpty(message))//广播主题消息,将广播消息发送到相应客户端 | |||
{ | |||
IOTCommandModel iOTCommand = Tools.JsonToObjectTools<IOTCommandModel>(message); | |||
if (iOTCommand.deviceName == DeviceDataV.deviceTable.devicename) | |||
ActionManage.GetInstance.Send("IotBroadcast", iOTCommand); | |||
} | |||
} | |||
#endregion | |||
} | |||
//命令实体类 | |||
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; | |||
} | |||
} | |||
} |
@@ -21,18 +21,17 @@ namespace BPASmartDatavDeviceClient.IoT | |||
/// <summary> | |||
/// 初始化IOT连接 | |||
/// </summary> | |||
public bool Initialize(string url,string clientId,string deviceId,ref string message) | |||
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)) | |||
deviceId = _deviceId; | |||
if (!CreateLinks(url, _clientId,out deviceTable, _deviceId)) | |||
{ | |||
message += $"客户端{clientId}设备{deviceId}阿里云上没有该设备。"; | |||
message += $"客户端{_clientId}设备{_deviceId}阿里云上没有该设备。"; | |||
return false; | |||
} | |||
IOT_Subscribe(BroadcastTopic);//订阅广播主题 | |||
if (DatavDeviceClient.IsConnected) message += $"设备{device.devicename} {device.remark}阿里云连接成功."; | |||
else message += $"设备{device.devicename} {device.remark}阿里云连接失败.不能上报业务信息"; | |||
if (!DatavDeviceClient.IsConnected) message += $"客户端:【{_clientId}】,设备名称{deviceTable.devicename}阿里云连接失败.不能上报业务信息"; | |||
return DatavDeviceClient.IsConnected; | |||
} | |||
@@ -118,11 +117,15 @@ namespace BPASmartDatavDeviceClient.IoT | |||
/// <summary> | |||
/// 创建连接 | |||
/// </summary> | |||
private bool CreateLinks(string url, string clientId, string deviceId, out DeviceTable device) | |||
private bool CreateLinks(string url, string clientId, out DeviceTable device ,string deviceId = "") | |||
{ | |||
try | |||
{ | |||
string json = HttpRequestHelper.HttpGetRequest($"{url}/api/Device/Query?clientId={clientId}&deviceId={deviceId}"); | |||
string json = string.Empty; | |||
if (string.IsNullOrEmpty(deviceId)) | |||
json = HttpRequestHelper.HttpGetRequest($"{url}/api/Device/Query?clientId={clientId}"); | |||
else | |||
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) | |||
{ | |||
@@ -130,7 +133,7 @@ namespace BPASmartDatavDeviceClient.IoT | |||
if (device == null) return false; | |||
SetValue(device.productkey, device.devicename, device.devicesecret); | |||
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName()); | |||
string _clientId = host.AddressList.FirstOrDefault( | |||
string _clientIp = host.AddressList.FirstOrDefault( | |||
ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).ToString(); | |||
string t = Convert.ToString(DateTimeOffset.Now.ToUnixTimeMilliseconds()); | |||
string signmethod = "hmacmd5"; | |||
@@ -138,12 +141,12 @@ namespace BPASmartDatavDeviceClient.IoT | |||
Dictionary<string, string> dict = new Dictionary<string, string>(); | |||
dict.Add("productKey", ProductKey); | |||
dict.Add("deviceName", DeviceName); | |||
dict.Add("clientId", _clientId); | |||
dict.Add("clientId", _clientIp); | |||
dict.Add("timestamp", t); | |||
mqttUserName = DeviceName + "&" + ProductKey; | |||
mqttPassword = IotSignUtils.sign(dict, DeviceSecret, signmethod); | |||
mqttClientId = clientId + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|"; | |||
mqttClientId = _clientIp + "|securemode=3,signmethod=" + signmethod + ",timestamp=" + t + "|"; | |||
targetServer = ProductKey + ".iot-as-mqtt." + RegionId + ".aliyuncs.com"; | |||
ConnectMqtt(targetServer, mqttClientId, mqttUserName, mqttPassword); | |||
return true; | |||
@@ -182,7 +185,7 @@ namespace BPASmartDatavDeviceClient.IoT | |||
/// </summary> | |||
/// <param name="sender"></param> | |||
/// <param name="e"></param> | |||
private static void Client_ConnectionClosed(object sender, EventArgs e) | |||
private void Client_ConnectionClosed(object sender, EventArgs e) | |||
{ | |||
// 尝试重连 | |||
_TryContinueConnect(); | |||
@@ -193,20 +196,20 @@ namespace BPASmartDatavDeviceClient.IoT | |||
/// </summary> | |||
/// <param name="sender"></param> | |||
/// <param name="e"></param> | |||
private static void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e) | |||
private 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); | |||
DataVMessageAction.Invoke(deviceId, topic, message); | |||
} | |||
} | |||
/// <summary> | |||
/// 自动重连主体 | |||
/// </summary> | |||
private static void _TryContinueConnect() | |||
private void _TryContinueConnect() | |||
{ | |||
Thread retryThread = new Thread(new ThreadStart(delegate | |||
{ | |||
@@ -263,13 +266,14 @@ namespace BPASmartDatavDeviceClient.IoT | |||
private static string mqttPassword = string.Empty; | |||
private static string mqttClientId = string.Empty; | |||
private static string targetServer = string.Empty; | |||
private static string deviceId = string.Empty; | |||
#endregion | |||
#region 公有变量 | |||
/// <summary> | |||
/// 设备消息数据回调 | |||
/// </summary> | |||
public static Action<string, string> DataVMessageAction { get; set; } | |||
public Action<string,string, string> DataVMessageAction { get; set; } | |||
/// <summary> | |||
/// 重连事件 | |||
/// </summary> | |||
@@ -281,7 +285,7 @@ namespace BPASmartDatavDeviceClient.IoT | |||
/// <summary> | |||
/// 当前设备 | |||
/// </summary> | |||
public DeviceTable deviceTable { get; set; } | |||
public DeviceTable deviceTable =new DeviceTable(); | |||
#endregion | |||
#region 发布或订阅主题或URL地址 | |||
@@ -324,7 +328,7 @@ namespace BPASmartDatavDeviceClient.IoT | |||
/// <summary> | |||
/// 广播主题 | |||
/// </summary> | |||
public static string BroadcastTopic = "/broadcast/" + "grgpECHSL7q" + "/" + DeviceName + "_SetDevice"; | |||
public string BroadcastTopic = "/broadcast/" + "grgpECHSL7q" + "/" + DeviceName + "_SetDevice"; | |||
/// <summary> | |||
/// 订阅主题集合 | |||
/// </summary> |
@@ -4,4 +4,8 @@ | |||
<TargetFramework>net6.0</TargetFramework> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\BPASmartClient.Peripheral\BPASmartClient.Peripheral.csproj" /> | |||
</ItemGroup> | |||
</Project> |
@@ -1,7 +1,9 @@ | |||
using System; | |||
using BPASmartClient.Peripheral; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
@@ -59,7 +61,38 @@ namespace BPASmartClient.Message | |||
} | |||
#endregion | |||
#region 查找设备ID | |||
/// <summary> | |||
/// 查询设备ID | |||
/// </summary> | |||
/// <returns></returns> | |||
public object ReturnDeviceID() | |||
{ | |||
object DeviceId = null; | |||
StackTrace trace = new StackTrace(); | |||
for (int i = 1; i < 10; i++) | |||
{ | |||
Type type = trace.GetFrame(i).GetMethod().ReflectedType; | |||
try | |||
{ | |||
object obj = Activator.CreateInstance(type); | |||
if (obj is IPeripheral) | |||
{ | |||
IPeripheral peripheral = obj as IPeripheral; | |||
DeviceId = type?.GetProperty("DeviceId")?.GetValue(peripheral, null); | |||
} | |||
if (DeviceId != null) break; | |||
} | |||
catch (Exception ex) | |||
{ | |||
} | |||
} | |||
return DeviceId; | |||
} | |||
#endregion | |||
@@ -21,6 +21,7 @@ | |||
<ProjectReference Include="..\BPASmartClient.Business\BPASmartClient.Business.csproj" /> | |||
<ProjectReference Include="..\BPASmartClient.DRCoffee\BPASmartClient.DRCoffee.csproj" /> | |||
<ProjectReference Include="..\BPASmartClient.GSIceCream\BPASmartClient.GSIceCream.csproj" /> | |||
<ProjectReference Include="..\BPASmartClient.IoT\BPASmartClient.IoT.csproj" /> | |||
<ProjectReference Include="..\BPASmartClient.KLMCoffee\BPASmartClient.KLMCoffee.csproj" /> | |||
<ProjectReference Include="..\BPASmartClient.Lebai\BPASmartClient.Lebai.csproj" /> | |||
<ProjectReference Include="..\BPASmartClient.MorkD\BPASmartClient.MorkD.csproj" /> | |||
@@ -42,6 +42,14 @@ | |||
</DataGridTemplateColumn.CellTemplate> | |||
</DataGridTemplateColumn> | |||
<!--<DataGridTemplateColumn Header="设备ID" Width="100"> | |||
<DataGridTemplateColumn.CellTemplate> | |||
<DataTemplate> | |||
<TextBlock HorizontalAlignment="Center" Text="{Binding deviceId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="14" Foreground="{Binding foreground, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> | |||
</DataTemplate> | |||
</DataGridTemplateColumn.CellTemplate> | |||
</DataGridTemplateColumn>--> | |||
<DataGridTemplateColumn Header="日志类型" Width="300"> | |||
<DataGridTemplateColumn.CellTemplate> | |||
<DataTemplate> | |||
@@ -5,6 +5,7 @@ using BPASmartClient.CustomResource.UserControls.MessageShow; | |||
using BPASmartClient.Device; | |||
using BPASmartClient.EventBus; | |||
using BPASmartClient.Helper; | |||
using BPASmartClient.IoT; | |||
using BPASmartClient.Message; | |||
using BPASmartClient.Model; | |||
using BPASmartClient.Model.冰淇淋.Enum; | |||
@@ -60,6 +61,7 @@ namespace BPASmartClient | |||
ThreadManage.GetInstance().Start(new Action(() => | |||
{ | |||
DataVClient.GetInstance().Start(); | |||
new MainConsole().Start(); | |||
}), "启动主控制台"); | |||
} | |||