From ce2600d7e6009dba20007f910d6d8cce60d25436 Mon Sep 17 00:00:00 2001 From: wanggang <76527413@qq.com> Date: Tue, 9 Apr 2019 17:01:28 +0800 Subject: [PATCH] =?UTF-8?q?1.=E8=B0=83=E6=95=B4=E5=92=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=8A=9B=E5=88=9B=E8=AE=BE=E5=A4=87=E6=8E=A5=E5=85=A5=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E9=A1=B9=E7=9B=AE=202.=E6=B6=88=E9=99=A4=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E8=AD=A6=E5=91=8A,=E6=9B=B4=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=8F=B7=E5=88=B0beta.100?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../力创/命令文档整洁版.xlsx | Bin 13782 -> 13981 bytes ...列产品寄存器列表V1.4(20170424).xls | Bin 0 -> 125952 bytes .../Extensions/HelperExtensions.cs | 6 +- .../IoT.Shared/Views/Device/Details.cshtml | 2 +- .../IoT/IoT.Shared/Views/Home/Node.cshtml | 54 +++- projects/IoT/IoT.Shared/wwwroot/js/iot.js | 111 ++++--- projects/IoT/IoT.UI.Shard/IoT.UI.Shard.csproj | 2 - projects/IoT/IoTNode/appsettings.json | 2 +- .../IoTServices/APService/appsettings.json | 2 +- .../Controllers/HomeController.cs | 8 +- .../Infrastructure/DeviceService.cs | 49 ++- .../Infrastructure/DeviceService2.cs | 294 ------------------ .../IoTServices/LiChuangService/Program.cs | 4 +- .../LiChuangService/Views/Home/Index.cshtml | 3 - .../LiChuangService/appsettings.json | 4 +- .../src/main/resources/application.properties | 2 +- .../Infrastructure/OnvifService.cs | 25 +- .../IoT/IoTServices/ONVIFService/Program.cs | 2 +- .../ONVIFService/Views/Home/Test.cshtml | 4 - .../IoTServices/ONVIFService/appsettings.json | 2 +- .../SerialPortService/appsettings.json | 2 +- .../IoTServices/WinService/appsettings.json | 2 +- projects/IoTCenter/appsettings.json | 2 +- projects/StudyCenter/appsettings.json | 2 +- projects/UserCenter/appsettings.json | 26 +- publish/build.cmd | 3 +- publish/src/linux-arm64/publish/install.sh | 1 + .../publish/supervisor/lichuang.conf | 8 + 28 files changed, 198 insertions(+), 424 deletions(-) create mode 100644 docs/资料/物联网中心/设备接入/力创/客户用zigbee系列产品寄存器列表V1.4(20170424).xls delete mode 100644 projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService2.cs create mode 100644 publish/src/linux-arm64/publish/supervisor/lichuang.conf diff --git a/docs/资料/物联网中心/设备接入/力创/命令文档整洁版.xlsx b/docs/资料/物联网中心/设备接入/力创/命令文档整洁版.xlsx index 56e023c573ca5b9f1131d19987d7f34954cff21d..4e5fba88435d64b2a37ed10f25976223d4755560 100644 GIT binary patch delta 7898 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 AlmGw# delta 7668 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 YXS&PJ?zDa7Rvh2>^5?|D|DqrN1>jkTDF6Tf literal 0 HcmV?d00001 diff --git a/projects/Infrastructure/Extensions/HelperExtensions.cs b/projects/Infrastructure/Extensions/HelperExtensions.cs index a334622e..c6f2ab4b 100644 --- a/projects/Infrastructure/Extensions/HelperExtensions.cs +++ b/projects/Infrastructure/Extensions/HelperExtensions.cs @@ -14,9 +14,9 @@ namespace Infrastructure.Extensions var physicalAddress = NetworkInterface .GetAllNetworkInterfaces() .Where(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback) - .Select(nic => nic.GetPhysicalAddress()) - .FirstOrDefault(); - return physicalAddress.ToString().ToLower(); + .Select(nic => nic.GetPhysicalAddress().ToString()) + .FirstOrDefault(o => !string.IsNullOrEmpty(o)); + return physicalAddress.ToLower(); } public static List GetLocalIPList(this Helper helper) diff --git a/projects/IoT/IoT.Shared/Views/Device/Details.cshtml b/projects/IoT/IoT.Shared/Views/Device/Details.cshtml index e889384a..b9930840 100644 --- a/projects/IoT/IoT.Shared/Views/Device/Details.cshtml +++ b/projects/IoT/IoT.Shared/Views/Device/Details.cshtml @@ -1,4 +1,4 @@ -@model Device +@model Device @{ Layout = null; HtmlTitle = Model.Name; diff --git a/projects/IoT/IoT.Shared/Views/Home/Node.cshtml b/projects/IoT/IoT.Shared/Views/Home/Node.cshtml index c133ad3a..8c1af0be 100644 --- a/projects/IoT/IoT.Shared/Views/Home/Node.cshtml +++ b/projects/IoT/IoT.Shared/Views/Home/Node.cshtml @@ -1,4 +1,4 @@ -@model Node +@model Node @{ Layout = null; HtmlTitle = Model?.Name; @@ -170,7 +170,7 @@ -

+
开关 @@ -212,9 +212,9 @@
- - - + + +
@@ -261,6 +261,50 @@
+
+
+
+ 插座 +
+
+ + +
+
+
+
+
+
+
{{d.DisplayName}} {{getDeviceDataValue(d,"状态")}}
+
+ + +
+
+
+
+
+
+
+ 插座 +
+
+ + +
+
+
+
+
+
+
{{d.DisplayName}} {{getDeviceDataValue(d,"状态")}}
+
+ + +
+
+
+
diff --git a/projects/IoT/IoT.Shared/wwwroot/js/iot.js b/projects/IoT/IoT.Shared/wwwroot/js/iot.js index 6febb4b3..b64e697f 100644 --- a/projects/IoT/IoT.Shared/wwwroot/js/iot.js +++ b/projects/IoT/IoT.Shared/wwwroot/js/iot.js @@ -2,6 +2,8 @@ var rtmpPlayer; var flvPlayer; var hlsPlayer; var app; +var timer; +var decodedFrames; var vm = new Vue({ el: '#app', data: { @@ -28,7 +30,9 @@ var vm = new Vue({ this.play2(); } $('#callback').on('popup:closed', function (e, popover) { - closePlayer(); + if ($(this).has('video').length) { + closePlayer(); + } }); }, updated: function () { @@ -167,56 +171,58 @@ var vm = new Vue({ var url = '/Command/Sence/?node=' + this.model.Number + '&id=' + id; getJsonExt(url); }, + playFlv: function (url) { + $('#video-container').html(''); + var videoElement = document.getElementById('player'); + try { + if (flvPlayer != null) { + closePlayer(); + } + flvPlayer = flvjs.createPlayer({ + type: 'flv', + url: url, + isLive: true, + cors: true + }, { + enableWorker: true, + enableStashBuffer: false, + stashInitialSize: 1, + fixAudioTimestampGap: false, + //lazyLoad: false + }); + flvPlayer.attachMediaElement(videoElement); + flvPlayer.load(); + timer = setInterval(function () { + console.log('.'); + if (flvPlayer.statisticsInfo.speed == 0) { + console.log('reload1'); + closePlayer(); + vm.playFlv(url); + } + else if (decodedFrames && flvPlayer.statisticsInfo.decodedFrames <= decodedFrames) { + console.log('reload2'); + closePlayer(); + vm.playFlv(url); + } + else if (flvPlayer.buffered.end(0) - flvPlayer.currentTime > 1) { + console.log('reset currentTime'); + flvPlayer.currentTime = flvPlayer.buffered.end(0) - 0.001; + } + decodedFrames = flvPlayer.statisticsInfo.decodedFrames; + }, 10 * 1000); + } catch (e) { + console.log(e); + } + }, play: function (id) { var hasFlash = navigator.plugins['Shockwave Flash']; var device = _.chain(this.model.Devices).filter(function (o) { return o.Id == id; }).first().value(); var key = (hasFlash ? "rtmp" : (flvjs.isSupported() ? 'flv' : 'hls')) + (isNode ? '1' : '2'); var url = _.chain(device.Data).filter(function (o) { return o.Key === key; }).first().value().Value; console.log(url); - if (hasFlash) { - try { - if (rtmpPlayer != null) { - closePlayer(); - } - $('#video-container').html('
'); - app.popup.open('#callback'); - rtmpPlayer = new Clappr.Player({ - source: url, - parentId: "#player", - autoPlay: true, - plugins: { 'playback': [RTMP] }, - rtmpConfig: { - swfPath: '/lib/clappr/clappr-rtmp-plugin/assets/RTMP.swf', - scaling: 'stretch', - playbackType: 'live', - bufferTime: 1, - startLevel: 0 - }, - }); - } catch (e) { - console.log(e); - } - } - else if (flvjs.isSupported()) { - $('#video-container').html(''); + if (flvjs.isSupported()) { app.popup.open('#callback'); - var videoElement = document.getElementById('player'); - try { - if (flvPlayer != null) { - closePlayer(); - } - flvPlayer = flvjs.createPlayer({ - type: 'flv', - url: url, - isLive: true, - cors: true, - enableStashBuffer: true - }); - flvPlayer.attachMediaElement(videoElement); - flvPlayer.load(); - } catch (e) { - console.log(e); - } + this.playFlv(url); } else if (Hls.isSupported()) { $('#video-container').html(''); @@ -248,18 +254,7 @@ var vm = new Vue({ var url = _.chain(device.Data).filter(function (o) { return o.Key === key; }).first().value().Value; if (flvjs.isSupported()) { - $('#video-container').html(''); - var videoElement = document.getElementById('player'); - var player = flvjs.createPlayer({ - type: 'flv', - url: url, - isLive: true, - cors: true, - enableStashBuffer: true - }); - player.attachMediaElement(videoElement); - player.load(); - + this.playFlv(url); } else if (Hls.isSupported()) { $('#video-container').html(''); @@ -282,6 +277,10 @@ var vm = new Vue({ }); function closePlayer() { console.log('close player'); + if (timer) { + clearInterval(timer); + timer = null; + } if (rtmpPlayer != null) { rtmpPlayer.destroy() } diff --git a/projects/IoT/IoT.UI.Shard/IoT.UI.Shard.csproj b/projects/IoT/IoT.UI.Shard/IoT.UI.Shard.csproj index 6828f54e..47dcb1b6 100644 --- a/projects/IoT/IoT.UI.Shard/IoT.UI.Shard.csproj +++ b/projects/IoT/IoT.UI.Shard/IoT.UI.Shard.csproj @@ -1,9 +1,7 @@  - netcoreapp2.2 true - true diff --git a/projects/IoT/IoTNode/appsettings.json b/projects/IoT/IoTNode/appsettings.json index d3a1c293..6d6ea20e 100644 --- a/projects/IoT/IoTNode/appsettings.json +++ b/projects/IoT/IoTNode/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.21", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Warning" diff --git a/projects/IoT/IoTServices/APService/appsettings.json b/projects/IoT/IoTServices/APService/appsettings.json index 39ea51ab..bb4a50c0 100644 --- a/projects/IoT/IoTServices/APService/appsettings.json +++ b/projects/IoT/IoTServices/APService/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.20", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Warning" diff --git a/projects/IoT/IoTServices/LiChuangService/Controllers/HomeController.cs b/projects/IoT/IoTServices/LiChuangService/Controllers/HomeController.cs index 33720b93..fdda474c 100644 --- a/projects/IoT/IoTServices/LiChuangService/Controllers/HomeController.cs +++ b/projects/IoT/IoTServices/LiChuangService/Controllers/HomeController.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Net.Http; +using System.Threading.Tasks; using Application.Domain.Entities; using Application.Models; using Infrastructure.Data; @@ -29,8 +30,11 @@ namespace LiChuangService.Controllers public IActionResult Index() { - Policy.Timeout(3).Execute(() => this._deviceService.Notify()); - return View(new EditButtonModel { Name = "test" }); + Task.Run(() => + { + this._deviceService.Notify(); + }); + return View(); } #region api diff --git a/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService.cs b/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService.cs index 47257aff..986e7425 100644 --- a/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService.cs +++ b/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService.cs @@ -50,8 +50,8 @@ namespace LiChuangService { try { - //Console.WriteLine("timer ..."); - //Policy.Timeout(3).Execute(() => Notify()); + Console.WriteLine("timer ..."); + Notify(); } catch (Exception ex) { @@ -65,54 +65,69 @@ namespace LiChuangService public void Notify() { Console.WriteLine("notify start ..."); - this.CheckConnection(); - this.SearchAddress(); + try + { + this.CheckConnection(); + this.SearchAddress(); + } + catch (Exception ex) + { + ex.PrintStack(); + } Console.WriteLine("notify end ..."); } public void Switch2AllOn(string id) { - this.Command16(new byte[] { this.GetNumber(id), 0x0f, 0x00, 0x0f, 0x00, 0x03, 0x01, 0x07 }); + this.Command16(new byte[] { this.GetNumber(id), 0x0f, 0x00, 0x00, 0x00, 0x03, 0x01, 0x07 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x02); } public void Switch2AllOff(string id) { - this.Command16(new byte[] { this.GetNumber(id), 0x0f, 0x00, 0x0f, 0x00, 0x03, 0x01, 0x00 }); + this.Command16(new byte[] { this.GetNumber(id), 0x0f, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x02); } public void Switch2L1On(string id) { this.Command16(new byte[] { this.GetNumber(id), 0x05, 0x00, 0x00, 0xff, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x02); } public void Switch2L1Off(string id) { this.Command16(new byte[] { this.GetNumber(id), 0x05, 0x00, 0x00, 0x00, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x02); } public void Switch2L2On(string id) { - this.Command16(new byte[] { this.GetNumber(id), 0x01, 0x05, 0x00, 0x01, 0xff, 0x00 }); + this.Command16(new byte[] { this.GetNumber(id), 0x05, 0x00, 0x01, 0xff, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x02); } public void Switch2L2Off(string id) { - this.Command16(new byte[] { this.GetNumber(id), 0x01, 0x05, 0x00, 0x01, 0x00, 0x00 }); + this.Command16(new byte[] { this.GetNumber(id), 0x05, 0x00, 0x01, 0x00, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x02); } public void SocketOn(string id) { this.Command16(new byte[] { this.GetNumber(id), 0x05, 0x00, 0x00, 0xff, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x10); } public void SocketOff(string id) { this.Command16(new byte[] { this.GetNumber(id), 0x05, 0x00, 0x00, 0x00, 0x00 }); + this.SearchSwitchStatus(this.GetNumber(id), 0x10); } private byte GetNumber(string id) { - return Convert.ToByte(id.Replace(this._addressValue, "")); + return Convert.ToByte(id.Split("-")[1]); } private void CheckConnection() @@ -179,7 +194,7 @@ namespace LiChuangService if (command == 0x0c)//16位地址 { this._address = data.ToList().Skip(5).Take(8).ToArray(); - this._addressValue = BitConverter.ToString(this._address).Replace("-", " "); + this._addressValue = BitConverter.ToString(this._address).Replace("-", ""); this.SearchNodeStatus(); } else if (command == 0x15)//节点状态 @@ -201,7 +216,7 @@ namespace LiChuangService else if (command == 0x17)//读取 { var nodeNumber = data[14]; - if (data.Length > 18 && data[18] == 0xff) + if (data.Length == 22 && data[18] == 0xff)//读类型命令返回值 { var nodeType = data[17]; this._types[nodeNumber] = nodeType; @@ -225,7 +240,7 @@ namespace LiChuangService Console.WriteLine($"unknown type:{nodeType}"); } } - else + if (data[15] == 0x01) { var nodeType = this._types[nodeNumber]; var statusData = data[17]; @@ -235,20 +250,20 @@ namespace LiChuangService 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[6] == '1' ? "开" : "关", DisplayOrder = 1 }); - model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status2", Name = "L2状态", Value = switchStatus[7] == '1' ? "开" : "关", DisplayOrder = 2 }); + 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) { Console.WriteLine($"~~~node {nodeNumber},socket 1 status:{statusData}"); - model = CreateModel("一路插座", this._addressValue + nodeNumber, "socket1", "socket"); + 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) { Console.WriteLine($"~~~node {nodeNumber},socket 2 status:{statusData}"); - model = CreateModel("二路插座", this._addressValue + nodeNumber, "socket2", "switch"); + model = CreateModel("二路插座", this._addressValue + "-" + nodeNumber, "socket2", "switch"); model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = statusData == 0x01 ? "开" : "关", DisplayOrder = 1 }); } else diff --git a/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService2.cs b/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService2.cs deleted file mode 100644 index 628c55e5..00000000 --- a/projects/IoT/IoTServices/LiChuangService/Infrastructure/DeviceService2.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Net.Sockets; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Application.Domain.Entities; -using Infrastructure.Data; -using Infrastructure.Extensions; -using Infrastructure.Models; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Polly; -using RJCP.IO.Ports; - -namespace LiChuangService -{ - public class DeviceService2 : IDisposable - { - private readonly IHostingEnvironment _env; - private readonly IConfiguration _configuration; - private readonly IHttpClientFactory _httpClientFactory; - private readonly IServiceProvider _applicationServices; - private CancellationTokenSource _tokenSource; - private static readonly object lockObject = new Object(); - - public DeviceService2(IHostingEnvironment env, IServiceProvider applicationServices, IConfiguration configuration, IHttpClientFactory httpClientFactory) - { - this._env = env; - this._applicationServices = applicationServices; - this._configuration = configuration; - this._httpClientFactory = httpClientFactory; - this._tokenSource = new CancellationTokenSource(); - } - - public void Start() - { - Task.Run(async () => - { - while (!_tokenSource.IsCancellationRequested) - { - try - { - Console.WriteLine("timer ..."); - Policy.Timeout(3).Execute(() => Notify()); - } - catch (Exception ex) - { - ex.PrintStack(); - } - await Task.Delay(this._configuration.GetValue("timer.seconds") * 1000); - } - }); - } - - public void Exec(string code) - { - using (var scope = _applicationServices.CreateScope()) - { - var repo = scope.ServiceProvider.GetService>(); - var button = repo.ReadOnlyTable().FirstOrDefault(o => o.Name == code); - if (button != null) - { - this.Exec(button); - } - } - } - - public void Exec(Button button) - { - using (var src = new SerialPortStream(button.SerialPort, button.Baud, button.Data, (RJCP.IO.Ports.Parity)button.Partity, (RJCP.IO.Ports.StopBits)button.StopBits)) - { - src.Open(); - var data = button.Message.HexToBytes(); - src.Write(data, 0, data.Length); - src.Flush(); - src.Close(); - } - } - - public void Notify() - { - Console.WriteLine("notify start ..."); - lock (lockObject) - { - try - { - using (var client = new TcpClient()) - { - var tcpIp = this._configuration["tcp.ip"]; - var tcpPort = this._configuration.GetValue("tcp.port"); - client.Connect(tcpIp, tcpPort); - using (var stream = client.GetStream()) - { - var addressData = this.GetAddress(stream); - var address = BitConverter.ToString(addressData).Replace("-", ""); - Console.WriteLine($"address:{address}"); - var nodesStatus = GetNodeStatus(stream, addressData); - Console.WriteLine($"nodes:{BitConverter.ToString(nodesStatus)}"); - - for (int i = 0; i < nodesStatus.Length; i++) - { - if (nodesStatus[i] == 0x01) - { - Console.WriteLine($"node online:{i + 1}"); - NotifyModel model = null; - var type = GetNodeType(stream, addressData, i + 1); - if (type == 2) - { - var switchStatusData = GetSwitchStatus(stream, addressData, i + 1); - var switchStatus = switchStatusData.ToBitString(); - model = CreateModel("二路灯开关", address + i, "switch2", "switch"); - model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "L1状态", Value = switchStatus[7] == '1' ? "开" : "关", DisplayOrder = 1 }); - model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "L2状态", Value = switchStatus[6] == '1' ? "开" : "关", DisplayOrder = 2 }); - } - else if (type == 3) - { - var switchStatusData = GetSwitchStatus(stream, addressData, i + 1); - model = CreateModel("一路插座", address + i, "socket1", "socket"); - model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = switchStatusData == 0x01 ? "开" : "关", DisplayOrder = 1 }); - } - else if (type == 4) - { - var switchStatusData = GetSwitchStatus(stream, addressData, i + 1); - model = CreateModel("二路插座", address + i, "socket2", "switch"); - model.Data.Add(new DataModel { Type = DataValueType.Text.ToString(), Key = "status", Name = "状态", Value = switchStatusData == 0x01 ? "开" : "关", DisplayOrder = 1 }); - } - var url = $"http://{this._configuration["node.url"]}/Notify"; - Console.WriteLine(url); - var hc = this._httpClientFactory.CreateClient(); - var task = this._httpClientFactory.CreateClient().PostAsync(url, new FormUrlEncodedContent(model.ToList())); - task.Wait(); - using (var response = task.Result) - { - using (var content = response.Content) - { - var value = content.ReadAsStringAsync().Result; - Console.WriteLine($"end:{url}:{value}"); - } - } - } - else if (nodesStatus[i] == 0x02) - { - Console.WriteLine($"node offline:{i + 1}"); - } - } - } - } - } - catch (Exception ex) - { - ex.PrintStack(); - } - } - Console.WriteLine("notify end ..."); - } - - public void SwitchAllOn(string id) - { - //throw new NotImplementedException(); - } - - public void SwitchAllOff(string id) - { - //throw new NotImplementedException(); - } - - private NotifyModel CreateModel(string name, string number, string path, string icon) - { - var host = string.IsNullOrEmpty(this._configuration["server.ip"]) ? Helper.Instance.GetLocalIP().ToString() : this._configuration["server.ip"]; - var port = Convert.ToInt32(Regex.Match(this._configuration["server.urls"], @"(?<=:)\d+").Value); - - return new NotifyModel - { - CategoryName = "电器", - CategoryNumber = "20", - Name = name, - Number = number, - Icon = icon, - IsOnline = true, - BaseUrl = $"http://{host}:{port}/{path}", - ApiPath = "/api" - }; - } - - private byte[] Command(byte[] data) - { - var command = new List { 0xfe, 0xa5, 0x00 }; - command.Add((byte)data.Length); - command.AddRange(data); - command.Add((byte)command.Skip(2).Select(o => Convert.ToInt32(o)).Sum()); - return command.ToArray(); - } - - private byte[] Data(byte[] data, bool crc16 = false) - { - var command = new List { 0xfe, 0xa5, 0x01 }; - command.Add((byte)data.Length); - command.AddRange(data); - if (crc16) - { - var crc = Crc16.ComputeChecksum(data); - command.Add(crc[1]); - command.Add(crc[0]); - } - else - { - command.Add((byte)command.Skip(2).Select(o => Convert.ToInt32(o)).Sum()); - } - return command.ToArray(); - } - - private byte[] GetAddress(NetworkStream stream) - { - var list = new List() { 0x0c }; - this.Write(stream, Command(list.ToArray())); - var buffer = new byte[256]; - var length = stream.Read(buffer); - Console.WriteLine($">address:{BitConverter.ToString(buffer, 0, length)}"); - var address = buffer.Skip(5).Take(8).ToArray(); - return address; - } - - private byte[] GetNodeStatus(NetworkStream stream, byte[] address) - { - var list = new List() { 0x15 }; - list.AddRange(address); - list.Add(0x00); - this.Write(stream, Command(list.ToArray())); - var buffer = new byte[256]; - var length = stream.Read(buffer); - Console.WriteLine($">node status:{BitConverter.ToString(buffer, 0, length)}"); - var status = buffer.Skip(14).Take(100).ToArray(); - return status; - } - - private byte GetNodeType(NetworkStream stream, byte[] address, int i) - { - var list = new List() { 0x16 }; - list.AddRange(address); - list.Add(0x00); - var modbusdata = new List { - (byte)i,0x03,0x00,0x0f,0x00,0x01 - }.ToArray(); - var modbus = new List(); - modbus.AddRange(modbusdata); - var crc = Crc16.ComputeChecksum(modbusdata); - modbus.Add(crc[1]); - modbus.Add(crc[0]); - list.AddRange(modbus); - this.Write(stream, Data(list.ToArray())); - var buffer = new byte[256]; - var length = stream.Read(buffer); - Console.WriteLine($">type:{BitConverter.ToString(buffer, 0, length)}"); - return buffer.Skip(14 + 3).Take(1).ToArray()[0]; - } - - private byte GetSwitchStatus(NetworkStream stream, byte[] address, int i) - { - var list = new List() { 0x16 }; - list.AddRange(address); - list.Add(0x00); - var modbusdata = new List { - (byte)i, 0x01,0x00,0x00,0x00,0x04 - }.ToArray(); - var modbus = new List(); - modbus.AddRange(modbusdata); - var crc = Crc16.ComputeChecksum(modbusdata); - modbus.Add(crc[1]); - modbus.Add(crc[0]); - list.AddRange(modbus); - this.Write(stream, Data(list.ToArray())); - var buffer = new byte[256]; - var length = stream.Read(buffer); - Console.WriteLine($">device status:{BitConverter.ToString(buffer, 0, length)}"); - return buffer.Skip(17).Take(1).ToArray()[0]; - } - - private void Write(NetworkStream stream, byte[] data) - { - Thread.Sleep(200); - stream.Write(data); - } - - public void Dispose() - { - Console.WriteLine("LiChuangService dispose..."); - this._tokenSource.Cancel(); - } - } -} \ No newline at end of file diff --git a/projects/IoT/IoTServices/LiChuangService/Program.cs b/projects/IoT/IoTServices/LiChuangService/Program.cs index 782e5773..52d659fa 100644 --- a/projects/IoT/IoTServices/LiChuangService/Program.cs +++ b/projects/IoT/IoTServices/LiChuangService/Program.cs @@ -22,10 +22,10 @@ namespace LiChuangService new EFConfigurationValue { Id = "email:port", Value= "25"}, new EFConfigurationValue { Id = "email:user", Value= "admin@nbaxp.com"}, new EFConfigurationValue { Id = "email:password", Value= "aA123456"}, - new EFConfigurationValue { Id = "server.ip", Value= "192.168.3.84" }, + new EFConfigurationValue { Id = "server.ip", Value= "" }, new EFConfigurationValue { Id = "server.urls", Value= "http://*:8008" }, new EFConfigurationValue { Id = "node.url", Value= "127.0.0.1:8002"}, - new EFConfigurationValue { Id = "timer.seconds", Value="5"}, + new EFConfigurationValue { Id = "timer.seconds", Value="600"}, new EFConfigurationValue { Id = "tcp.ip", Value="192.168.3.233"}, new EFConfigurationValue { Id = "tcp.port", Value="4001"}, // diff --git a/projects/IoT/IoTServices/LiChuangService/Views/Home/Index.cshtml b/projects/IoT/IoTServices/LiChuangService/Views/Home/Index.cshtml index 6eb4cc85..e69de29b 100644 --- a/projects/IoT/IoTServices/LiChuangService/Views/Home/Index.cshtml +++ b/projects/IoT/IoTServices/LiChuangService/Views/Home/Index.cshtml @@ -1,3 +0,0 @@ -@model SPService.Applicaiton.Models.EditButtonModel -

@ViewBag.Result

-@Html.EditorForModel() \ No newline at end of file diff --git a/projects/IoT/IoTServices/LiChuangService/appsettings.json b/projects/IoT/IoTServices/LiChuangService/appsettings.json index 58b53bb6..d7dce16e 100644 --- a/projects/IoT/IoTServices/LiChuangService/appsettings.json +++ b/projects/IoT/IoTServices/LiChuangService/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.20", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Information" @@ -7,7 +7,7 @@ }, "AllowedHosts": "*", "ConnectionStrings": { - "database.mysql.connection": "Server=127.0.0.1;Port=3306;Database=iotnode;Uid=root;Pwd=root;", + "database.mysql.connection": "Server=127.0.0.1;Port=3306;Database=data;Uid=root;Pwd=root;", "database.sqlite.connection": "Data Source=data.db" }, "AppSettings": { diff --git a/projects/IoT/IoTServices/NJWLService/src/main/resources/application.properties b/projects/IoT/IoTServices/NJWLService/src/main/resources/application.properties index 9907d5ba..bc6d7077 100644 --- a/projects/IoT/IoTServices/NJWLService/src/main/resources/application.properties +++ b/projects/IoT/IoTServices/NJWLService/src/main/resources/application.properties @@ -1,4 +1,4 @@ -version=1.0.0-beta.21 +version=1.0.0-beta.100 server.host=127.0.0.1 server.port=8003 spring.thymeleaf.cache=false diff --git a/projects/IoT/IoTServices/ONVIFService/Infrastructure/OnvifService.cs b/projects/IoT/IoTServices/ONVIFService/Infrastructure/OnvifService.cs index 4232e8e1..5b3e1876 100644 --- a/projects/IoT/IoTServices/ONVIFService/Infrastructure/OnvifService.cs +++ b/projects/IoT/IoTServices/ONVIFService/Infrastructure/OnvifService.cs @@ -24,13 +24,6 @@ namespace ONVIFService { private readonly IHostingEnvironment _env; private readonly IConfiguration _configuration; - private readonly string _local_rtmp; - private readonly string _local_flv; - private readonly string _local_hls; - private readonly string _remote_rtmp; - private readonly string _remote_flv; - private readonly string _remote_hls; - private readonly IHttpClientFactory _httpClientFactory; private readonly IServiceProvider _applicationServices; private CancellationTokenSource _tokenSource; @@ -42,12 +35,6 @@ namespace ONVIFService this._env = env; this._applicationServices = applicationServices; this._configuration = configuration; - this._local_rtmp = this._configuration["stream.local.rtmp"]; - this._local_flv = this._configuration["stream.local.flv"]; - this._local_hls = this._configuration["stream.local.hls"]; - this._remote_rtmp = this._configuration["stream.remote.rtmp"]; - this._remote_flv = this._configuration["stream.remote.flv"]; - this._remote_hls = this._configuration["stream.remote.hls"]; this._httpClientFactory = httpClientFactory; this._tokenSource = new CancellationTokenSource(); this._onvifDeviceManagement = new OnvifDeviceManagement(httpClientFactory); @@ -95,12 +82,12 @@ namespace ONVIFService { Name = "摄像头", Number = ipCamera.Id, - Rtmp1 = $"rtmp://{_local_rtmp}/live/{ipCamera.Id}", - Flv1 = $"http://{_local_flv}/live/{ipCamera.Id}.flv", - Hls1 = $"http://{_local_hls}/live/{ipCamera.Id}.m3u8", - Rtmp2 = $"rtmp://{_remote_rtmp}/live/{ipCamera.Id}", - Flv2 = $"http://{_remote_flv}/live/{ipCamera.Id}.flv", - Hls2 = $"http://{_remote_hls}/live/{ipCamera.Id}.m3u8", + Rtmp1 = $"rtmp://{this._configuration["stream.local.rtmp"]}/live/{ipCamera.Id}", + Flv1 = $"http://{this._configuration["stream.local.flv"]}/live/{ipCamera.Id}.flv", + Hls1 = $"http://{this._configuration["stream.local.hls"]}/live/{ipCamera.Id}.m3u8", + Rtmp2 = $"rtmp://{this._configuration["stream.remote.rtmp"]}/live/{ipCamera.Id}", + Flv2 = $"http://{this._configuration["stream.remote.flv"]}/live/{ipCamera.Id}.flv", + Hls2 = $"http://{this._configuration["stream.remote.hls"]}/live/{ipCamera.Id}.m3u8", Arguments = this._configuration["ffmpeg.args"], File = this._configuration["ffmpeg.file"] }; diff --git a/projects/IoT/IoTServices/ONVIFService/Program.cs b/projects/IoT/IoTServices/ONVIFService/Program.cs index d69eae84..d745c983 100644 --- a/projects/IoT/IoTServices/ONVIFService/Program.cs +++ b/projects/IoT/IoTServices/ONVIFService/Program.cs @@ -24,7 +24,7 @@ namespace ONVIFService new EFConfigurationValue { Id = "email:password", Value= "aA123456"}, new EFConfigurationValue { Id = "server.urls", Value= "http://*:8004" }, new EFConfigurationValue { Id = "node.url", Value= "127.0.0.1:8002"}, - new EFConfigurationValue { Id = "timer.seconds", Value="300"}, + new EFConfigurationValue { Id = "timer.seconds", Value="600"}, new EFConfigurationValue { Id = "onvif.timer", Value="1"}, new EFConfigurationValue { Id = "onvif.speed", Value="0.2"}, new EFConfigurationValue { Id = "camera.usr", Value="admin"}, diff --git a/projects/IoT/IoTServices/ONVIFService/Views/Home/Test.cshtml b/projects/IoT/IoTServices/ONVIFService/Views/Home/Test.cshtml index b8b04cc4..b0d35252 100644 --- a/projects/IoT/IoTServices/ONVIFService/Views/Home/Test.cshtml +++ b/projects/IoT/IoTServices/ONVIFService/Views/Home/Test.cshtml @@ -1,8 +1,4 @@ @model List -@{ - int i = 0; - var player = "ucload"; -} @if (Model.Count > 0) {
diff --git a/projects/IoT/IoTServices/ONVIFService/appsettings.json b/projects/IoT/IoTServices/ONVIFService/appsettings.json index 2af830af..4da849fa 100644 --- a/projects/IoT/IoTServices/ONVIFService/appsettings.json +++ b/projects/IoT/IoTServices/ONVIFService/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.22", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Information" diff --git a/projects/IoT/IoTServices/SerialPortService/appsettings.json b/projects/IoT/IoTServices/SerialPortService/appsettings.json index 58b53bb6..4da849fa 100644 --- a/projects/IoT/IoTServices/SerialPortService/appsettings.json +++ b/projects/IoT/IoTServices/SerialPortService/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.20", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Information" diff --git a/projects/IoT/IoTServices/WinService/appsettings.json b/projects/IoT/IoTServices/WinService/appsettings.json index 39ea51ab..bb4a50c0 100644 --- a/projects/IoT/IoTServices/WinService/appsettings.json +++ b/projects/IoT/IoTServices/WinService/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.20", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Warning" diff --git a/projects/IoTCenter/appsettings.json b/projects/IoTCenter/appsettings.json index 809014e7..2e69ecf4 100644 --- a/projects/IoTCenter/appsettings.json +++ b/projects/IoTCenter/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.21", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Warning" diff --git a/projects/StudyCenter/appsettings.json b/projects/StudyCenter/appsettings.json index d58dd8da..872b852e 100644 --- a/projects/StudyCenter/appsettings.json +++ b/projects/StudyCenter/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.1", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Warning" diff --git a/projects/UserCenter/appsettings.json b/projects/UserCenter/appsettings.json index 589260ee..abe8420b 100644 --- a/projects/UserCenter/appsettings.json +++ b/projects/UserCenter/appsettings.json @@ -1,5 +1,5 @@ { - "version": "1.0.0-beta.20", + "version": "1.0.0-beta.100", "Logging": { "LogLevel": { "Default": "Warning" @@ -7,11 +7,29 @@ }, "UseMiniProfiler": false, "ConnectionStrings": { - "database.mysql.connection": "Server=127.0.0.1;Port=3306;Database=data;Uid=root;Pwd=root;", - "database.sqlite.connection": "Data Source=data.db" + "database.mysql.connection": "Server=127.0.0.1;Port=3306;Database=usercenter;Uid=root;Pwd=root;", + "database.sqlite.connection": "Data Source=usercenter.db" }, "AppSettings": { "database": "sqlite", "UseCookieSessionStore": false - } + }, + //Ocelot config + "GlobalConfiguration": { + "BaseUrl": "http://192.168.3.124:8000/" + }, + "ReRoutes": [ + { + "DownstreamPathTemplate": "/api/{version}/{everything}", + "DownstreamScheme": "http", + "DownstreamHostAndPorts": [ + { + "Host": "192.168.3.124", + "Port": 8001 + } + ], + "UpstreamPathTemplate": "/api/{version}/iot/{everything}", + "UpstreamHttpMethod": [ "Get" ] + } + ] } \ No newline at end of file diff --git a/publish/build.cmd b/publish/build.cmd index c6efc945..9fa55922 100644 --- a/publish/build.cmd +++ b/publish/build.cmd @@ -9,7 +9,7 @@ echo d|xcopy "./src/linux-arm64/publish" "./dist/linux-arm64/publish" /s /e /y / dotnet publish ../projects/UserCenter/UserCenter.csproj -c Release -r linux-x64 -o ../../publish/dist/linux-x64/publish/apps/UserCenter dotnet publish ../projects/IoTCenter/IoTCenter.csproj -c Release -r linux-x64 -o ../../publish/dist/linux-x64/publish/apps/IoTCenter -dotnet publish ../projects/UserCenter/UserCenter.csproj -c Release -r linux-arm64 -o .../../publish/dist/linux-arm64/publish/apps/UserCenter +dotnet publish ../projects/UserCenter/UserCenter.csproj -c Release -r linux-arm64 -o ../../publish/dist/linux-arm64/publish/apps/UserCenter dotnet publish ../projects/IoTCenter/IoTCenter.csproj -c Release -r linux-arm64 -o ../../publish/dist/linux-arm64/publish/apps/IoTCenter dotnet publish ../projects/IoT/IoTNode/IoTNode.csproj -c Release -r linux-arm64 -o ../../../publish/dist/linux-arm64/publish/apps/IoTNode dotnet publish ../projects/IoT/IoTServices/WinService/WinService.csproj -c Release -r win-x86 -o "../../../../publish/dist/win-x86/Program Files (x86)/WinService" @@ -17,6 +17,7 @@ dotnet publish ../projects/IoT/IoTServices/APService/APService.csproj -c Release dotnet publish ../projects/IoT/IoTServices/ONVIFService/ONVIFService.csproj -c Release -r linux-x64 -o ../../../../publish/dist/linux-x64/publish/apps/ONVIFService dotnet publish ../projects/IoT/IoTServices/ONVIFService/ONVIFService.csproj -c Release -r linux-arm64 -o ../../../../publish/dist/linux-arm64/publish/apps/ONVIFService dotnet publish ../projects/IoT/IoTServices/SerialPortService/SerialPortService.csproj -c Release -r linux-arm64 -o ../../../../publish/dist/linux-arm64/publish/apps/SerialPortService +dotnet publish ../projects/IoT/IoTServices/LiChuangService/LiChuangService.csproj -c Release -r linux-arm64 -o ../../../../publish/dist/linux-arm64/publish/apps/LiChuangService gradle build -p ../projects/IoT/IoTServices/NJWLService set endtime=%time% diff --git a/publish/src/linux-arm64/publish/install.sh b/publish/src/linux-arm64/publish/install.sh index 51f6bbc8..77ae1a33 100644 --- a/publish/src/linux-arm64/publish/install.sh +++ b/publish/src/linux-arm64/publish/install.sh @@ -11,5 +11,6 @@ chmod 777 /root/publish/apps/APService/APService chmod 777 /root/publish/apps/ONVIFService/ONVIFService chmod 777 /root/publish/apps/ONVIFService/wwwroot/ffmpeg-linux-arm64 chmod 777 /root/publish/apps/SerialPortService/SerialPortService +chmod 777 /root/publish/apps/LiChuangService/LiChuangService chmod 777 /root/publish/apps/srs/objs/srs service supervisor restart \ No newline at end of file diff --git a/publish/src/linux-arm64/publish/supervisor/lichuang.conf b/publish/src/linux-arm64/publish/supervisor/lichuang.conf new file mode 100644 index 00000000..7a13a52a --- /dev/null +++ b/publish/src/linux-arm64/publish/supervisor/lichuang.conf @@ -0,0 +1,8 @@ +[program:lichangservice] +command=/root/publish/apps/LiChuangService/LiChuangService +directory=/root/publish/apps/LiChuangService/ +autostart=true +autorestart=true +user=root +stdout_logfile=/root/publish/logs/lichangservice.log +stderr_logfile=/root/publish/logs/lichangservice.err \ No newline at end of file