Former-commit-id: 299ce789cb272ab624b66b87718cf0e9da56915c
TangShanKaiPing
wanggang 6 years ago
parent a4626b8825
commit bbdb4dc259

@ -1,4 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Infrastructure.Extensions namespace Infrastructure.Extensions
{ {
@ -8,5 +11,38 @@ namespace Infrastructure.Extensions
{ {
return Convert.ToString(@byte, 2).PadLeft(8, '0'); return Convert.ToString(@byte, 2).PadLeft(8, '0');
} }
public static int ToInt(this IEnumerable<byte> bytes)
{
return BitConverter.ToInt16(bytes.ToArray());
}
public static int ReadInt(this Stream bytes)
{
var buffer = new byte[2];
bytes.Read(buffer);
return BitConverter.ToInt16(buffer);
}
public static string ReadASIIString(this Stream bytes, int length)
{
var buffer = new byte[length];
bytes.Read(buffer);
return new string(buffer.Select(o => (char)o).ToArray());
}
public static string ReadHexString(this Stream bytes, int length)
{
var buffer = new byte[length];
bytes.Read(buffer);
return BitConverter.ToString(buffer).Replace("-", "").ToLower();
}
public static byte[] Read(this Stream bytes, int length)
{
var buffer = new byte[length];
bytes.Read(buffer);
return buffer;
}
} }
} }

@ -0,0 +1,43 @@
namespace Application.Domain.Entities
{
public enum DataType
{
uint1 = 0x20,
uint2,
uint3,
uint4,
uint5,
uint6,
uint7,
uint8,
int1,
int2,
int3,
int4,
int5,
int6,
int7,
int8,
enum1,
enum2,
float2 = 0x38,
float4,
float8,
bitstring = 0x41,
characterstring,
longbitstring,
longcharacterstring,
sequence = 0x4c,
set = 0x50,
bag,
time4 = 0xe0,
date4,
utctime4,
cluster2 = 0xe8,
attribute2,
bacnet4,
ieee1 = 0xf0,
m16,
unknown = 0xff
}
}

@ -0,0 +1,20 @@
using Infrastructure.Domain;
using System.Collections.Generic;
namespace Application.Domain.Entities
{
public class DeviceId : BaseEntity
{
public static List<DeviceId> List { get; set; } = new List<DeviceId>();
static DeviceId()
{
List.Add(new DeviceId { Name = "外挂式插座", Category = "电器", Icon = "socket", RawCategory = "Generic", RawName = "Smart plug", RawDeviceId = 0x0051 });
}
public string Name { get; set; }
public string Icon { get; set; }
public string Category { get; set; }
public int RawDeviceId { get; set; }
public string RawCategory { get; set; }
public string RawName { get; set; }
}
}

@ -0,0 +1,63 @@
using Infrastructure.Domain;
using Infrastructure.Extensions;
using System;
using System.IO;
namespace Application.Domain.Entities
{
public class FBeeDevice : BaseEntity
{
public int DataType { get; set; }
public int DataLength { get; set; }
public int Address { get; set; }
public int Endpoint { get; set; }
public int ProfileId { get; set; }
public int DeviceId { get; set; }
public int Status { get; set; }
public int NameLength { get; set; }
public string RawName { get; set; }
public int Online { get; set; }
public string IEEE { get; set; }
public int SNLength { get; set; }
public string RawSN { get; set; }
public int ZoneType { get; set; }
public int Power { get; set; }
public string Data { get; set; }
public string Safe { get; set; }
public string RawValue { get; set; }
//
public string Sn { get; set; }
public string Name { get; set; }
public int Number { get; set; }
public string Icon { get; set; }
public int CategoryNumber { get; set; }
public string CategoryName { get; set; }
public void Update(byte[] data)
{
using (var ms = new MemoryStream(data))
{
this.DataType = ms.ReadByte();
this.DataLength = ms.ReadByte();
this.Address = ms.ReadInt();
this.Endpoint = ms.ReadByte();
this.ProfileId = ms.ReadInt();
this.DeviceId = ms.ReadInt();
this.Status = ms.ReadByte();
this.NameLength = ms.ReadByte();
this.RawName = ms.ReadASIIString(this.NameLength);
this.Online = ms.ReadByte();
this.IEEE = ms.ReadHexString(8);
this.SNLength = ms.ReadByte();
this.RawSN = ms.ReadHexString(this.SNLength);
this.ZoneType = ms.ReadByte();
this.Power = ms.ReadByte();
this.Data = ms.ReadHexString(4);
this.Safe = ms.ReadHexString(2);
this.RawValue = BitConverter.ToString(data);
}
}
}
}

@ -0,0 +1,10 @@
namespace Application.Domain.Entities
{
public class MessageType
{
public const int DeviceResponse = 0x01;
public const int DevicePowerResponse = 0x07;
public const int DeviceNotify = 0x70;
public const int DeviceNotiryExt = 0x72;
}
}

@ -7,7 +7,7 @@ using Infrastructure.Web.Mvc;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SPService.Applicaiton.Models; using SPService.Applicaiton.Models;
namespace LiChuangService.Areas.Controllers namespace FBeeService.Areas.Controllers
{ {
[Area("Admin")] [Area("Admin")]
public class HomeController : CrudController<Gateway, PagedListModel<EditGatewayModel>, EditGatewayModel, EditGatewayModel> public class HomeController : CrudController<Gateway, PagedListModel<EditGatewayModel>, EditGatewayModel, EditGatewayModel>

@ -13,17 +13,17 @@ using Polly;
using SPService.Applicaiton.Models; using SPService.Applicaiton.Models;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
namespace LiChuangService.Controllers namespace FBeeService.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {
private readonly IRepository<Gateway> _cameraRepo; private readonly IRepository<FBeeDevice> _repo;
private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpClientFactory _httpClientFactory;
private readonly DeviceService _deviceService; private readonly DeviceService _deviceService;
public HomeController(IHttpClientFactory httpClientFactory, DeviceService deviceService, IRepository<Gateway> cameraRepo) public HomeController(IHttpClientFactory httpClientFactory, DeviceService deviceService, IRepository<FBeeDevice> repo)
{ {
this._cameraRepo = cameraRepo; this._repo = repo;
this._httpClientFactory = httpClientFactory; this._httpClientFactory = httpClientFactory;
this._deviceService = deviceService; this._deviceService = deviceService;
} }
@ -34,7 +34,7 @@ namespace LiChuangService.Controllers
{ {
this._deviceService.Notify(); this._deviceService.Notify();
}); });
return View(); return View(this._repo.ReadOnlyTable().ToList());
} }
#region api #region api

@ -17,4 +17,6 @@
<ProjectReference Include="..\..\IoT.Shared\IoT.Shared.csproj" /> <ProjectReference Include="..\..\IoT.Shared\IoT.Shared.csproj" />
<ProjectReference Include="..\..\IoT.UI.Shard\IoT.UI.Shard.csproj" /> <ProjectReference Include="..\..\IoT.UI.Shard\IoT.UI.Shard.csproj" />
</ItemGroup> </ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties libman_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
</Project> </Project>

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
namespace LiChuangService namespace FBeeService
{ {
public static class CommandHelper public static class CommandHelper
{ {

@ -1,4 +1,4 @@
namespace LiChuangService namespace FBeeService
{ {
public static class Crc16 public static class Crc16
{ {

@ -1,5 +1,8 @@
using Application.Domain.Entities; using Application.Domain.Entities;
using Application.Models; using Application.Models;
using Application.Domain.Entities;
using Infrastructure.Data; using Infrastructure.Data;
using Infrastructure.Extensions; using Infrastructure.Extensions;
using Infrastructure.Models; using Infrastructure.Models;
@ -9,6 +12,7 @@ using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
@ -19,7 +23,7 @@ using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LiChuangService namespace FBeeService
{ {
public class DeviceService : IDisposable public class DeviceService : IDisposable
{ {
@ -194,7 +198,7 @@ namespace LiChuangService
var gateway = repo.Table().FirstOrDefault(o => o.Sn == sn); var gateway = repo.Table().FirstOrDefault(o => o.Sn == sn);
if (gateway == null) if (gateway == null)
{ {
gateway = new Gateway { Sn = sn, Ip = ip }; gateway = new Gateway { Sn = sn, Ip = ip, Enable = true };
repo.Add(gateway); repo.Add(gateway);
repo.SaveChanges(); repo.SaveChanges();
} }
@ -220,8 +224,8 @@ namespace LiChuangService
if (client.Client.Connected) if (client.Client.Connected)
{ {
client.Client.Close(); client.Client.Close();
this.Connect(gateway.Sn, client);
} }
this.Connect(gateway.Sn, client);
} }
else else
{ {
@ -256,10 +260,6 @@ namespace LiChuangService
private void Connect(string sn, TcpClientWrapper client) private void Connect(string sn, TcpClientWrapper client)
{ {
if (client.Client.Connected)
{
client.Client.Close();
}
try try
{ {
client.Client.Connect(client.Ip, 8001); client.Client.Connect(client.Ip, 8001);
@ -275,6 +275,9 @@ namespace LiChuangService
var buffer = new byte[512]; var buffer = new byte[512];
var length = stream.Read(buffer); var length = stream.Read(buffer);
var data = buffer.ToList().Take(length).ToArray(); var data = buffer.ToList().Take(length).ToArray();
Console.WriteLine($"response:{BitConverter.ToString(data)}");
var test = new byte[] {
0x16,0x00, 0x34, 0xF5, 0x41, 0x11, 0xFE, 0x82, 0x0D, 0x02, 0x42 ,0x20 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x01 ,0x00 ,0x00 ,0x00 };
this.Handle(sn, data); this.Handle(sn, data);
} }
catch (Exception ex) catch (Exception ex)
@ -311,114 +314,116 @@ namespace LiChuangService
private void Handle(string sn, byte[] data) private void Handle(string sn, byte[] data)
{ {
Console.WriteLine($"response:{BitConverter.ToString(data)}"); var length = 2 + data[1];
if (data[0] == 0x01)//获取设备返回值 if (data.Length > length)
{ {
var length = Convert.ToInt32(data[1]); Handle(sn, data.Skip(length).ToArray());
} }
if (data[0] == 0x70)//设备上报 else
{ {
this.HandleInternal(sn, data.Take(length).ToArray());
} }
//var list = new List<byte[]>();
//for (int i = 0; i < data.Length; i++)
//{
// if ((i + 3) < data.Length && data[i] == 0xfe && data[i + 1] == 0xa5)
// {
// var length = data[i + 3];
// this.HandleInternal(data.Skip(i).Take(5 + length).ToArray());
// }
//}
} }
private void HandleInternal(byte[] data) private void HandleInternal(string sn, byte[] data)
{ {
Console.WriteLine($"read:{BitConverter.ToString(data).Replace("-", " ")}"); Console.WriteLine($"read:{BitConverter.ToString(data).Replace("-", " ")}");
var type = data[2]; using (var ms = new MemoryStream(data))
var command = data[4];
if (command == 0x0c)//16位地址
{ {
this._address = this._address ?? data.ToList().Skip(5).Take(8).ToArray(); var responseType = ms.ReadByte();
this._addressValue = BitConverter.ToString(this._address).Replace("-", ""); var dataLength = ms.ReadByte();
this.SearchNodeStatus(); var deviceNumber = ms.ReadInt();
} var endpoint = ms.ReadByte();
else if (command == 0x15)//节点状态 using (var scope = _applicationServices.CreateScope())
{ {
var status = data.ToList().Skip(14).Take(100).ToArray(); var deviceRepo = scope.ServiceProvider.GetService<IRepository<FBeeDevice>>();
for (int i = 0; i < 100; i++) var device = deviceRepo.Table().FirstOrDefault(o => o.Number == deviceNumber);
if (device == null)
{ {
if (status[i] == 0x01) Console.WriteLine($"{deviceNumber} dose not save in database");
}
if (responseType == MessageType.DeviceResponse)//获取设备返回值
{ {
Console.WriteLine($"node {i + 1} online"); var profileId = ms.ReadInt();
this.SearchNodeType(i + 1); var deviceId = ms.ReadInt();
var deviceType = DeviceId.List.FirstOrDefault(o => o.RawDeviceId == deviceId);
if (deviceType == null)
{
Console.WriteLine($"{deviceId} dose not config in database");
} }
else if (status[i] == 0x02) else
{
if (device == null)
{
device = new FBeeDevice
{ {
Console.WriteLine($"node {i + 1} offline"); Sn = sn,
Number = deviceNumber,
Name = deviceType.Name,
Icon = deviceType.Icon,
CategoryNumber = deviceType.RawDeviceId,
CategoryName = deviceType.Category
};
deviceRepo.Add(device);
} }
device.Update(data);
} }
} }
else if (command == 0x17)//读取 else if (responseType == MessageType.DeviceNotify || responseType == MessageType.DeviceNotiryExt)//设备上报
{ {
var nodeNumber = data[14]; var clusterId = ms.ReadInt();
if (data.Length == 22 && data[18] == 0xff)//读类型命令返回值 if (device != null)
{ {
var nodeType = data[17]; var reportCount = ms.ReadByte();
this._types[nodeNumber] = nodeType; var props = new Dictionary<int, byte[]>();
if (nodeType == 0x02) for (int i = 0; i < reportCount; i++)
{ {
Console.WriteLine($"node {nodeNumber} is switch 2"); var propId = ms.ReadInt();
this.SearchSwitchStatus(nodeNumber, 0x02); var propDataTypeValue = ms.ReadByte();
} int propDataLength;
else if (nodeType == 0x03) if (Enum.IsDefined(typeof(DataType), propDataTypeValue))
{ {
Console.WriteLine($"node {nodeNumber} is socket 1"); var propDataType = (DataType)propDataTypeValue;
this.SearchSwitchStatus(nodeNumber, 0x10); if (propDataType == DataType.bitstring || propDataType == DataType.characterstring)
}
else if (nodeType == 0x04)
{ {
Console.WriteLine($"node {nodeNumber} is socket 2"); propDataLength = ms.ReadByte();
this.SearchSwitchStatus(nodeNumber, 0x10);
} }
else else if (propDataType == DataType.longbitstring || propDataType == DataType.longcharacterstring)
{ {
Console.WriteLine($"unknown type:{nodeType}"); propDataLength = ms.ReadInt();
}
} }
if (data[15] == 0x01) else if (propDataType == DataType.sequence || propDataType == DataType.set || propDataType == DataType.bag)
{ {
var nodeType = this._types[nodeNumber]; propDataLength = ms.ReadInt();
var statusData = data[17];
NotifyModel model = null;
if (nodeType == 0x02)
{
Console.WriteLine($"~~~node {nodeNumber},switch 2 status:{statusData}");
var switchStatus = statusData.ToBitString();
model = CreateModel("二路灯开关", this._addressValue + "-" + nodeNumber, "switch2", "switch");
model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status1", Name = "L1状态", Value = switchStatus[7] == '1' ? "开" : "关", DisplayOrder = 1 });
model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status2", Name = "L2状态", Value = switchStatus[6] == '1' ? "开" : "关", DisplayOrder = 2 });
} }
else if (nodeType == 0x03) else if (propDataType == DataType.unknown)
{ {
Console.WriteLine($"~~~node {nodeNumber},socket 1 status:{statusData}"); propDataLength = 0;
model = CreateModel("一路插座", this._addressValue + "-" + nodeNumber, "socket1", "socket");
model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = statusData == 0x01 ? "开" : "关", DisplayOrder = 1 });
} }
else if (nodeType == 0x04) else
{ {
Console.WriteLine($"~~~node {nodeNumber},socket 2 status:{statusData}"); propDataLength = Convert.ToInt32(Regex.Match(propDataType.GetName(), @"\d+").Groups[1].Value);
model = CreateModel("二路插座", this._addressValue + "-" + nodeNumber, "socket2", "socket"); }
model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = statusData == 0x01 ? "开" : "关", DisplayOrder = 1 });
} }
else else
{ {
Console.WriteLine($"unknown type:{nodeType}"); propDataLength = 1;
}
var propData = ms.Read(propDataLength);
props.Add(propId, propData);
} }
if (model != null) }
}
else if (responseType == MessageType.DevicePowerResponse)
{
var powerStatus = ms.ReadByte();
if (device != null)
{ {
this.NotifyServer(model); device.Power = powerStatus;
} }
} }
deviceRepo.SaveChanges();
}
} }
} }
@ -518,10 +523,17 @@ namespace LiChuangService
} }
private void Write(TcpClient client, byte[] command) private void Write(TcpClient client, byte[] command)
{
if (client.Connected)
{ {
Console.WriteLine($"write:{BitConverter.ToString(command).Replace("-", " ")}"); Console.WriteLine($"write:{BitConverter.ToString(command).Replace("-", " ")}");
client.GetStream().Write(command); client.GetStream().Write(command);
} }
else
{
Console.WriteLine($"can not write:{BitConverter.ToString(command).Replace("-", " ")}");
}
}
private NotifyModel CreateModel(string name, string number, string path, string icon) private NotifyModel CreateModel(string name, string number, string path, string icon)
{ {

@ -5,7 +5,7 @@ using Infrastructure.Extensions;
using Infrastructure.Web.Hosting; using Infrastructure.Web.Hosting;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
namespace LiChuangService namespace FBeeService
{ {
public class Program public class Program
{ {

@ -6,8 +6,9 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System;
namespace LiChuangService namespace FBeeService
{ {
public class Startup : ShardStartup public class Startup : ShardStartup
{ {
@ -31,6 +32,11 @@ namespace LiChuangService
{ {
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Gateway>().HasIndex(o => o.Sn).IsUnique(); modelBuilder.Entity<Gateway>().HasIndex(o => o.Sn).IsUnique();
modelBuilder.Entity<FBeeDevice>().HasIndex(o => new { o.Sn, o.Number }).IsUnique();
}
public override void Seed(DbContext dbContext, IServiceProvider serviceProvider, IConfiguration configuration)
{
} }
} }
} }

@ -0,0 +1,25 @@
@model List<FBeeDevice>
<table>
<tr>
<th>Sn</th>
<th>地址</th>
<th>开关</th>
<th>RawValue</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.Sn</td>
<td>@item.Address</td>
<td>@item.Power</td>
<td>@item.RawValue</td>
</tr>
}
</table>
@section styles{
<style>
td {
padding: 5px 1em;
}
</style>
}

@ -7,7 +7,7 @@ using Infrastructure.Web.Mvc;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using SPService.Applicaiton.Models; using SPService.Applicaiton.Models;
namespace LiChuangService.Areas.Controllers namespace FBeeService.Areas.Controllers
{ {
[Area("Admin")] [Area("Admin")]
public class HomeController : CrudController<Button, PagedListModel<EditButtonModel>, EditButtonModel, EditButtonModel> public class HomeController : CrudController<Button, PagedListModel<EditButtonModel>, EditButtonModel, EditButtonModel>

@ -13,7 +13,7 @@ using Polly;
using SPService.Applicaiton.Models; using SPService.Applicaiton.Models;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
namespace LiChuangService.Controllers namespace FBeeService.Controllers
{ {
public class HomeController : Controller public class HomeController : Controller
{ {

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Sockets; using System.Net.Sockets;
namespace LiChuangService namespace FBeeService
{ {
public static class CommandHelper public static class CommandHelper
{ {

@ -1,4 +1,4 @@
namespace LiChuangService namespace FBeeService
{ {
public static class Crc16 public static class Crc16
{ {

@ -11,7 +11,7 @@ using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LiChuangService namespace FBeeService
{ {
public class DeviceService : IDisposable public class DeviceService : IDisposable
{ {

@ -5,7 +5,7 @@ using Infrastructure.Extensions;
using Infrastructure.Web.Hosting; using Infrastructure.Web.Hosting;
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
namespace LiChuangService namespace FBeeService
{ {
public class Program public class Program
{ {

@ -7,7 +7,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace LiChuangService namespace FBeeService
{ {
public class Startup : ShardStartup public class Startup : ShardStartup
{ {

Loading…
Cancel
Save