diff --git a/projects/Infrastructure/wwwroot/css/site.css b/projects/Infrastructure/wwwroot/css/site.css index ce4a0c0d..8dce51d3 100644 --- a/projects/Infrastructure/wwwroot/css/site.css +++ b/projects/Infrastructure/wwwroot/css/site.css @@ -47,6 +47,15 @@ color: #fff!important; border-radius: 5px; } +/**/ +.fancybox img.thumbnail, td .fancybox img { + max-width: 30px; + max-height: 30px; +} + +.ke-container { + width: 100% !important; +} /*.content-header2 { overflow: hidden; } @@ -86,15 +95,6 @@ select.form-control { -.fancybox img.thumbnail,td .fancybox img { - max-width: 20px; - max-height: 20px; -} -.ke-container { - width: 100% !important; -} - - .checkboxfix { height: 34px; diff --git a/projects/IoT.Shared/Application/Domain/Entities/Product.cs b/projects/IoT.Shared/Application/Domain/Entities/Product.cs index da2c61d6..642eb814 100644 --- a/projects/IoT.Shared/Application/Domain/Entities/Product.cs +++ b/projects/IoT.Shared/Application/Domain/Entities/Product.cs @@ -18,6 +18,9 @@ namespace Application.Domain.Entities [Display(Name = "图标")] public string Image { get; set; } + [Display(Name = "路径")] + public string Path { get; set; } + [Display(Name = "ApiJson")] public string ApiJson { get; set; } diff --git a/projects/IoT.Shared/Application/Models/EditProductModel.cs b/projects/IoT.Shared/Application/Models/EditProductModel.cs index 20b8d5d7..77293ecf 100644 --- a/projects/IoT.Shared/Application/Models/EditProductModel.cs +++ b/projects/IoT.Shared/Application/Models/EditProductModel.cs @@ -21,6 +21,9 @@ namespace Application.Models [DataType(DataType.ImageUrl)] public string Image { get; set; } + [Display(Name = "路径")] + public string Path { get; set; } + [Display(Name = "ApiJson")] [DataType(DataType.MultilineText)] public string ApiJson { get; set; } diff --git a/projects/IoTCenter/Controllers/AppController.cs b/projects/IoTCenter/Controllers/AppController.cs index a4b95041..f281a6be 100644 --- a/projects/IoTCenter/Controllers/AppController.cs +++ b/projects/IoTCenter/Controllers/AppController.cs @@ -131,25 +131,12 @@ namespace IoTCenter.Controllers } [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")] - public IActionResult ExecApi(string token, string connectionId, string number, string method, string query) + public IActionResult ExecApi(string token, string connectionId, string number, string method) { try { var userName = User.Identity.IsAuthenticated ? User.Identity.Name : this._jwtHelper.GetPayload(token)["UserName"].ToString(); - var device = this._deviceRepo.ReadOnlyTable().Include(o => o.Node).FirstOrDefault(o => o.Number == number); - if (device != null) - { - var query2 = string.Empty; - var parameters = Request.Method.ToUpper() == "GET" ? Request.Query.ToArray() : Request.Form.ToArray(); - foreach (var item in parameters.Where(o => o.Key.ToLower() != "connectionid" && o.Key.ToLower() != "method")) - { - query2 = query2.SetParam(item.Key, item.Value); - } - - var message = $"{method}{query2}"; - var group = device.Node.Number; - this._hub.ServerToClient(Methods.ExecApiRequest, message, group, connectionId); - } + CallApi(connectionId, number, method); return Json(ApiResponse.AsyncSuccess()); } catch (Exception ex) @@ -159,6 +146,28 @@ namespace IoTCenter.Controllers } } + private void CallApi(string connectionId, string number, string method) + { + var device = this._deviceRepo.ReadOnlyTable().Include(o => o.Node).FirstOrDefault(o => o.Number == number); + if (device != null) + { + var query2 = string.Empty; + var parameters = Request.Method.ToUpper() == "GET" ? Request.Query.ToArray() : Request.Form.ToArray(); + foreach (var item in parameters.Where(o => o.Key.ToLower() != "connectionid" && o.Key.ToLower() != "method")) + { + query2 = query2.SetParam(item.Key, item.Value); + } + foreach (var item in new string[] { "token", "connectionid", "method", "numbers[]" }) + { + query2 = query2.RemoveParam(item); + } + query2 = query2.SetParam("number", number); + var message = $"{method}{query2}"; + var group = device.Node.Number; + this._hub.ServerToClient(Methods.ExecApiRequest, message, group, connectionId); + } + } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")] public IActionResult ExecScene(string token, string connectionId, Guid id) { @@ -176,8 +185,9 @@ namespace IoTCenter.Controllers } } - public IActionResult GetChartData(string number, string time) + public IActionResult GetChartData(string token, string number, string time) { + var userName = User.Identity.IsAuthenticated ? User.Identity.Name : this._jwtHelper.GetPayload(token)["UserName"].ToString(); var device = this._deviceRepo.ReadOnlyTable().Include(o => o.Data).FirstOrDefault(o => o.Number == number); var url = this._configuration["influxdb:url"]; var usr = this._configuration["influxdb:usr"]; @@ -208,7 +218,7 @@ namespace IoTCenter.Controllers } if (rows != null) { - labels = rows.Select(o => o.Timestamp.Value).Select(o => o.ToString("MM-dd")).Distinct().ToList(); + labels = rows.Select(o => o.Timestamp.Value).Select(o => o.ToString("MM-dd hh:mm")).Distinct().ToList(); } } var model = new @@ -220,6 +230,25 @@ namespace IoTCenter.Controllers } } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")] + public IActionResult ExecApiAll(string token, string connectionId, string method, string query, List numbers) + { + try + { + var userName = User.Identity.IsAuthenticated ? User.Identity.Name : this._jwtHelper.GetPayload(token)["UserName"].ToString(); + foreach (var number in numbers) + { + this.CallApi(connectionId, number, method); + } + return Json(ApiResponse.AsyncSuccess()); + } + catch (Exception ex) + { + ex.PrintStack(); + return Json(ApiResponse.Error(ex)); + } + } + private string GetColor(object key) { var randomGen = new Random(); @@ -240,26 +269,6 @@ namespace IoTCenter.Controllers return Json(model); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")] - public IActionResult ExecApiAll(string connectionId, string node, string cmd, List id) - { - try - { - var query = string.Empty; - foreach (var item in Request.Query.Where(o => o.Key != "node" && o.Key != "cmd" && !o.Key.StartsWith("id["))) - { - query = query.SetParam(item.Key, item.Value); - } - //this._pageHubContext.Clients.Group(node).SendAsync(nameof(INodeService.ExecAll), connectionId, id, cmd, query); - return Json(ApiResponse.AsyncSuccess()); - } - catch (Exception ex) - { - ex.PrintStack(); - return Json(ApiResponse.Error(ex)); - } - } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:不捕获常规异常类型", Justification = "<挂起>")] public IActionResult ExecGlobalScene(string connectionId, Guid id) { diff --git a/projects/IoTCenter/Views/Home/Product.cshtml b/projects/IoTCenter/Views/Home/Product.cshtml index ded105ce..83412829 100644 --- a/projects/IoTCenter/Views/Home/Product.cshtml +++ b/projects/IoTCenter/Views/Home/Product.cshtml @@ -24,9 +24,9 @@
- - - + + +
@@ -34,12 +34,12 @@
-

{{item.Name}}

-
-
- -
-
+

+ +

+
diff --git a/projects/IoTCenter/iotcenter.db b/projects/IoTCenter/iotcenter.db index ceee1fcc..3796ca87 100644 Binary files a/projects/IoTCenter/iotcenter.db and b/projects/IoTCenter/iotcenter.db differ diff --git a/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/node.js b/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/node.js index 612cbd16..78bd196c 100644 --- a/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/node.js +++ b/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/node.js @@ -338,12 +338,15 @@ function onMessage(method, json,to, from) { var device = Enumerable.from(vm.model.Devices).firstOrDefault(function (o) { return o.Id === item.DeviceId; }) if (device) { updateItem(device.Data, item); - toastr.info(device.DisplayName+'更新'); + toastr.info(device.DisplayName + '更新'); + if ($('canvas#' + device.Number).length) { + UpdateChart(device.Number); + } } } else if (method == 'SceneEntityInserted' || method == 'SceneEntityUpdated') { updateItem(vm.model.Scenes, item); - toastr.info(item.Name+'更新'); + toastr.info(item.Name + '更新'); } else if (method == 'SceneEntityDeleted') { deleteItem(vm.model.Scenes, item); diff --git a/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/product.js b/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/product.js index cae1b894..39fafcc2 100644 --- a/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/product.js +++ b/projects/IoTClient/Assets/StreamingAssets/wwwroot/js/product.js @@ -67,105 +67,8 @@ function loadTemplate() { alert(error) }); } -function UpdateCamera() { - var number = $('#camera').val(); - var video = document.getElementById("liveVideo"); - if (number) { - if (flvjs.isSupported) { - console.log('flv support'); - playFlv(video); - } - else { - playHls(video); - } - } -} -function playHls(videoElement) { - var number = $('#camera').val(); - var device = Enumerable.from(vm.model.Devices).where(function (o) { return o.Number === number; }).firstOrDefault(); - var url = Enumerable.from(device.Data).where(o => o.Name === '子码流hls').firstOrDefault().Value; - var hasPtz = Enumerable.from(device.Data).where(o => o.Name === '缩放支持').firstOrDefault(); - if (hasPtz && hasPtz.Value === '是') { - $('#ptz').show(); - } - else { - $('#ptz').hide(); - } - video.src = url; -} -function playFlv(videoElement) { - var number = $('#camera').val(); - if (number) { - var device = Enumerable.from(vm.model.Devices).where(function (o) { return o.Number === number; }).firstOrDefault(); - var url = Enumerable.from(device.Data).where(o => o.Name === '子码流flv').firstOrDefault().Value; - var hasPtz = Enumerable.from(device.Data).where(o => o.Name === '缩放支持').firstOrDefault(); - if (hasPtz && hasPtz.Value === '是') { - $('#ptz').show(); - } - else { - $('#ptz').hide(); - } - closePlayer(livePlayer); - try { - livePlayer = flvjs.createPlayer({ - type: 'flv', - url: url, - isLive: true, - cors: true - }, { - enableWorker: true, - enableStashBuffer: false, - stashInitialSize: 1, - fixAudioTimestampGap: false - }); - livePlayer.attachMediaElement(videoElement); - livePlayer.load(); - livePlayer.volume = volume; - livePlayer.muted = muted; - timer = setInterval(function () { - console.log('.'); - if (livePlayer.statisticsInfo.speed == 0) { - console.log('reload1'); - clearInterval(timer); - playFlv(videoElement); - } - else if (decodedFrames && livePlayer.statisticsInfo.decodedFrames <= decodedFrames) { - console.log('reload2'); - clearInterval(timer); - playFlv(videoElement); - } - else if (livePlayer.buffered.end(0) - livePlayer.currentTime > 1) { - console.log('reset currentTime'); - livePlayer.currentTime = livePlayer.buffered.end(0) - 0.001; - } - decodedFrames = livePlayer.statisticsInfo.decodedFrames; - }, 10 * 1000); - } catch (e) { - console.log(e); - } - } -} -function closePlayer(livePlayer) { - if (timer) { - clearInterval(timer); - } - if (livePlayer != null) { - try { - livePlayer.pause(); - } catch (e) { - console.error(e); - } - livePlayer.unload(); - livePlayer.detachMediaElement(); - try { - livePlayer.destroy(); - } catch (e) { - console.error(e); - } - livePlayer = null; - } -} + function ajax(url, data, type) { url = iotCenter + url console.log(url); @@ -222,26 +125,6 @@ function deleteItem(list, item) { } } } -/*event*/ -$(document).on('change', '#camera', function (e) { - UpdateCamera() -}); -$(document).on('mousedown touchstart', 'img.camera.ajax', function (e) { - var number = $('#camera').val(); - var cmd = $(this).attr('data-cmd'); - ajax('/App/ExecApi', { token:token,connectionId: connectionId, number: number, method: '/Onvif/' + cmd }, 'post'); - return false; -}); -$(document).on('mouseup touchend', 'img.camera.ajax', function (e) { - var number = $('#camera').val(); - var cmd = $(this).attr('data-cmd'); - if (cmd !== 'Stop') { - setTimeout(function () { - ajax('/App/ExecApi', { number: number, method: '/Onvif/Stop' }, 'post'); - }, 500); - } - return false; -}); /*ws*/ function connect() { if (debug) { @@ -314,9 +197,6 @@ function init() { }); } connect(); - this.$nextTick(function () { - UpdateCamera(); - }); }, methods: { HasBatchCommand() { @@ -353,15 +233,12 @@ function init() { parent.prop("indeterminate", true); } }, - HasDevices(name) { - return Enumerable - .from(this.model.Devices) - .any(function (o) { return o.Name === name }); - }, - GetDevices(name) { - return Enumerable.from(this.model.Devices) - .where(function (o) { return o.Name == name; }) - .toArray(); + CallApiAll(method) { + var numbers = []; + $('.item:checked').each(function () { + numbers.push($(this).val()); + }); + ajax('/App/ExecApiAll', { token: token, connectionId: connectionId, method: vm.model.Path + method, numbers: numbers }, 'post'); }, GetDataValue(number, name) { var device = Enumerable.from(this.model.Devices) @@ -385,189 +262,6 @@ function init() { } return null; }, - CameraSelected() { - console.log('camera selected:' + new Date()); - UpdateCamera(); - }, - VolumeChange(e) { - muted = e.target.muted; - volume = e.target.volume; - }, - CallApi(number, method, query) { - ajax('/App/ExecApi', { number: number, method: method, query: query }, 'post'); - }, - AjaxSubmit(event, deviceNumber, dataName) { - var device = Enumerable.from(vm.model.Devices) - .where(function (o) { return o.Number === deviceNumber; }) - .firstOrDefault(); - if (device != null) { - var data = Enumerable.from(device.Data) - .where(function (o) { return o.Name == dataName }) - .firstOrDefault(); - if (data != null) { - data.Value = $(event.target).val(); - } - } - var form = $(event.target).parents('form'); - var url = form.attr('action') + '?' + form.serialize(); - Vue.nextTick(function () { - ajax(url, null, 'get'); - }); - }, - getCode1(code) { - var pattern = 0; - var direction = 0; - var wind = 0; - var power = 2; - var temperature = 1; - if (code > 480 + 2) { - pattern = 480; - } - else if (code > 360 + 2) { - pattern = 360; - } - else if (code > 240 + 2) { - pattern = 240; - } - else if (code > 120 + 2) { - pattern = 120; - } - else { - pattern = 0; - } - code -= pattern; - if (code > 75 + 2) { - direction = 75; - } - else if (code > 60 + 2) { - direction = 60; - } - else { - direction = 0; - } - code -= direction; - if (code > 45 + 2) { - wind = 45; - } - else if (code > 30 + 2) { - wind = 30; - } - else if (code > 15 + 2) { - wind = 15; - } - else { - wind = 0; - } - code -= wind; - if (code === 1) { - power = 1; - } - else { - power = 2; - temperature = code - power; - } - return { - pattern: pattern, - direction: direction, - wind: wind, - power: power, - temperature: temperature - }; - }, - SendCode1(event) { - console.log(event.target); - if (event.type !== 'change' && !event.target.checked) { - return; - } - var form = $(event.target).parents('form'); - var url = form.attr('action') + '?' + form.serialize(); - if (form.hasClass('type1')) { - if (event.target.name == "power" && event.target.value == "1") { - url = new URI(url).setQuery('Code', '1').toString(); - } - else { - var list = {}; - list['power'] = form.find("[name = 'power']:checked").val(); - list['pattern'] = form.find("[name = 'pattern']:checked").val(); - list['direction'] = form.find("[name = 'direction']:checked").val(); - list['wind'] = form.find("[name = 'wind']:checked").val(); - list['temperature'] = form.find("[name = 'temperature']").val(); - list[event.target.name] = event.target.value; - var code = 0; - for (var name in list) { - code += parseInt(list[name]); - } - url = new URI(url).setQuery('Code', code).toString(); - } - } - Vue.nextTick(function () { - ajax(url, null, 'get'); - }); - }, - getLightColor(h, s, v) { - return hsvToRgb(parseInt(h * 360 / 255), parseInt(s * 100 / 255), parseInt(v * 100 / 255)); - } } }); -} -function hsvToRgb(h, s, v) { - if (h == "") h = 0; - if (s == "") s = 0; - if (v == "") v = 0; - h = parseFloat(h); - s = parseFloat(s); - v = parseFloat(v); - if (h < 0) h = 0; - if (s < 0) s = 0; - if (v < 0) v = 0; - if (h >= 360) h = 359; - if (s > 100) s = 100; - if (v > 100) v = 100; - s /= 100.0; - v /= 100.0; - C = v * s; - hh = h / 60.0; - X = C * (1.0 - Math.abs((hh % 2) - 1.0)); - r = g = b = 0; - if (hh >= 0 && hh < 1) { - r = C; - g = X; - } - else if (hh >= 1 && hh < 2) { - r = X; - g = C; - } - else if (hh >= 2 && hh < 3) { - g = C; - b = X; - } - else if (hh >= 3 && hh < 4) { - g = X; - b = C; - } - else if (hh >= 4 && hh < 5) { - r = X; - b = C; - } - else { - r = C; - b = X; - } - m = v - C; - r += m; - g += m; - b += m; - r *= 255.0; - g *= 255.0; - b *= 255.0; - r = Math.round(r); - g = Math.round(g); - b = Math.round(b); - hex = r * 65536 + g * 256 + b; - hex = hex.toString(16, 6); - len = hex.length; - if (len < 6) - for (i = 0; i < 6 - len; i++) - hex = '0' + hex; - return '#' + hex; } \ No newline at end of file diff --git a/projects/IoTNode/DeviceServices/BaseDeviceService.cs b/projects/IoTNode/DeviceServices/BaseDeviceService.cs index 53b44e6d..b258debc 100644 --- a/projects/IoTNode/DeviceServices/BaseDeviceService.cs +++ b/projects/IoTNode/DeviceServices/BaseDeviceService.cs @@ -82,6 +82,7 @@ namespace IoTNode.DeviceServices { Number = productNumber, Name = productName, + Path = path, Image = $"/images/{productIcon}.png", CategoryId = categoryRepo.ReadOnlyTable().FirstOrDefault(o => o.Number == categoryNumber).Id }; diff --git a/projects/IoTNode/iotnode.db b/projects/IoTNode/iotnode.db index b17b0c6b..685521bc 100644 Binary files a/projects/IoTNode/iotnode.db and b/projects/IoTNode/iotnode.db differ