if (!localStorage.getItem('token')) { } var vm; var app; var node; var device; var connection; var isApp = false; var flvPlayer; var timer; var decodedFrames; var isiOS = new MobileDetect(window.navigator.userAgent).os() === 'iOS'; //func $.ajaxSetup({ cache: false, timeout: 5000 }); $('body').on('click', 'img.shot', function () { $(this).toggleClass('zoom'); }); function ajax(url) { console.log(url); app.dialog.progress(); $.get(url, function (response) { var result = response; if (result.code === 0) { if (result.type === 0) { if (result.format === 1) { console.log('format/1/base64 jpeg image'); $('#callback .page-content').html(''); } else { console.log('format/0/json object'); $('#callback .page-content').html(result.data); } app.popup.open('#callback'); } } }).fail(function (result) { console.log('error'); console.log(result); }).always(function () { app.dialog.close(); });; } function connect() { if (connection && connection.connection.connectionState === 1) { console.log('has connected'); } else { console.log('start connect to server:' + Date()); connection.start().then(function () { console.log('signalR>start'); }).catch(function (err) { console.error(err.toString()); setTimeout(connect, 10 * 1000); }); } } function onMessage() { connection.on('Connected', function (id) { vm.ConnectionId = id; }); connection.on('ApiResult', function (result) { result = JSON.parse(result); if (result.code === 0) { if (result.type === 0) { if (result.format === 1) { console.log('format/1/base64 jpeg image'); $('#callback .page-content').html(''); } else { console.log('format/0/json object'); $('#callback .page-content').html(result.data); } app.popup.open('#callback'); } } }); connection.on("UpdateNode", (message) => { var newNode = JSON.parse(message); var oldNode = _.chain(vm.Nodes).filter(o => o.Number === newNode.Number).first().value(); oldNode.Name = newNode.Name; if (node && node.Node.Number === newNode.Number) { node.Node.Name = newNode.Name; } console.log('update:' + newNode.Name); }); connection.on("UpdateDevice", (message) => { var newDevice = JSON.parse(message); while (vm.Messages.length >= 20) { vm.Messages.pop(); } vm.Messages.push(newDevice); if (node && node.Node.Id == newDevice.NodeId) { var update = false; for (var i = 0; i < node.Node.Devices.length; i++) { if (node.Node.Devices[i].Number == newDevice.Number) { update = true; break; } } if (update) { node.Node.Devices.splice(i, 1, newDevice); } else { node.Node.Devices.push(newDevice); } } if (device && device.Device.Number == newDevice.Number) { device.Device.Name = newDevice.Name; device.Device.DisplayName = newDevice.DisplayName; device.Device.Data = newDevice.Data; updateChart(); } }); connection.on("DeleteDevice", (message) => { var newDevice = JSON.parse(message); if (node && node.Node.Id === newDevice.NodeId) { for (var i = 0; i < node.Node.Devices.length; i++) { if (node.Node.Devices[i].Number == newDevice.Number) { node.Node.Devices.splice(i, 1); break; } } console.log('delete:' + newDevice.Number); } }); connection.on("UpdateSence", function (message) { var sence = JSON.parse(message); if (node && node.Node.Id === sence.NodeId) { var update = false; for (var i = 0; i < node.Node.Sences.length; i++) { if (node.Node.Sences[i].Id == sence.Id) { update = true; break; } } if (update) { node.Node.Sences.splice(i, 1, sence); } else { node.Node.Sences.push(sence); } console.log('update:' + sence.DisplayName); } }); connection.on("DeleteSence", function (message) { var sence = JSON.parse(message); if (node && node.Node.Id === sence.NodeId) { for (var i = 0; i < node.Node.Sences.length; i++) { if (node.Node.Sences[i].Id == sence.Id) { node.Node.Sences.splice(i, 1); break; } } console.log('delete:' + sence.Name); } }); connection.onclose(function () { setTimeout(connect, 10 * 1000); }); } function playFlv(videoElement,url) { try { var flvPlayer = flvjs.createPlayer({ type: 'flv', url: url, isLive: true, cors: true }, { enableWorker: true, enableStashBuffer: false, stashInitialSize: 1, fixAudioTimestampGap: false }); flvPlayer.attachMediaElement(videoElement); flvPlayer.load(); var timer = setInterval(function () { console.log('.'); if (flvPlayer.statisticsInfo.speed == 0) { console.log('reload1'); clearInterval(timer); closePlayer(flvPlayer); playFlv(videoElement,url); } else if (decodedFrames && flvPlayer.statisticsInfo.decodedFrames <= decodedFrames) { console.log('reload2'); clearInterval(timer); closePlayer(flvPlayer); playFlv(videoElement,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); } } function closePlayer(flvPlayer) { if (flvPlayer != null) { flvPlayer.pause(); flvPlayer.unload(); flvPlayer.detachMediaElement(); flvPlayer.destroy(); flvPlayer = null; } } function createChart() { $('canvas.chart').each(function () { var id = $(this).attr('id'); var canvas = document.getElementById(id); var label = $(this).attr('data-label'); var ctx = canvas.getContext('2d'); var config = createConfig(label, [], []); new Chart(ctx, config); }); } function createConfig(label, labels, data) { return { type: 'line', data: { labels: labels, datasets: [{ label: label, data: data, borderColor: 'green', fill: false }] }, options: { responsive: true, title: { display: true, text: label, } } }; } function updateChart() { var url = vm.IoTServer + '/App/Data?id=' + device.Device.Id; $.getJSON(url, function (result) { console.log(result); $.each(result, function (i, n) { var id = n.id; Chart.helpers.each(Chart.instances, function (instance) { if (instance.chart.canvas.id == id) { console.log('update chart:' + id); instance.chart.data.labels = n.labels; instance.chart.data.datasets[0].data = n.data; instance.chart.update(); } }) }); }).fail(function () { console.log('error'); }).always(function () { app.dialog.close(); });; } Framework7.use(Framework7Vue); Vue.component('page-home', { template: '#page-home', data() { return { }; }, mounted() { }, methods: { } }); Vue.component('page-login', { template: '#page-login', data() { return { Server: localStorage.getItem('Server') || 'http://localhost:8000', UserName: localStorage.getItem('UserName'), Password: null, RememberMe: localStorage.getItem('RememberMe') }; }, mounted() { localStorage.removeItem('Token'); $('form.login').removeData('validator'); $('form.login').removeData('unobtrusiveValidation'); $.validator.unobtrusive.parse('form.login'); }, methods: { FaceLogin: function (server, rememberMe) { window.location.href = "uniwebview://facelogin?Server=" + encodeURIComponent(server) + "&RememberMe=" + rememberMe; }, OnSubmit: function (e) { if (!$(e.target).valid()) { return; } var url = e.target.action; var data = $(e.target).serialize(); var current = this; $.post(url, data, function (response) { localStorage.setItem("Server", current.Server); if (response.Code === 0) { vm.Token = response.Token; if (current.RememberMe === true) { localStorage.setItem("Token", response.Token); localStorage.setItem("UserName", current.UserName); localStorage.setItem("NickName", response.NickName); localStorage.setItem("Title", response.Title); localStorage.setItem("IoTServer", _.trimEnd(response.IoTServer, ['/'])); } else { localStorage.removeItem("Token"); } vm.Server = current.Server; vm.RememberMe = current.RememberMe; vm.UserName = current.UserName; vm.NickName = response.NickName; vm.Title = response.Title; vm.IoTServer = _.trimEnd(response.IoTServer, ['/']); vm.$f7.view.current.router.back(); } else { app.dialog.alert(response.Message, "消息"); } }).fail(function (e) { var message; if (e.status === 0) { message = "不是有效的服务器地址"; } else { message = e.status + ":" + e.statusText; } vm.$f7.dialog.alert(message, "消息"); }); } } }); Vue.component('page-node', { template: '#page-node', data() { return { Node: { Number: null, Name: null, Sences: [], Devices: [] } } }, mounted() { this.Node.Number = this.$f7route.params.number; this.Node.Name = this.$f7route.params.name; node = this; var ajaxUrl = vm.IoTServer + "/App/GetNode?token=" + vm.Token + '&number=' + this.Node.Number; app.dialog.progress(); $.get(ajaxUrl, function (response) { node.Node = response; Vue.nextTick(function () { $('video.video').each(function () { var videoElement = $(this)[0]; var url = $(this).attr('src'); playFlv(videoElement,url); }); }); }).always(function () { app.dialog.close(); }); }, destroyed() { node = null; }, methods: { getDevices: function () { var args = arguments; return _.chain(this.Node.Devices).filter(function (device) { return _.chain(args).filter(function (name) { return device.Name.indexOf(name) != -1; }).value().length > 0; }).orderBy(['DisplayOrder', 'Name']).value(); }, getValue(device, dataName) { if (device != null) { var data = _.first(_.filter(device.Data, function (o) { return o.Name === dataName })); if (data != null) { if (data.Value) { var value = data.Value; return value; } else { console.log('值为空:' + device.Name + '/' + dataName); } } else { console.log('无法找到:' + device.Name + '/' + dataName); } } else { console.log('无法找到:' + dataName); } return ""; }, getData(device, dataName) { if (device != null) { var data = _.first(_.filter(device.Data, function (o) { return o.Name === dataName })); if (data != null) { if (data.Value) { var value = data.Value; if (data.Unit) { value += " " + data.Unit; } if (data.Description) { value += " " + data.Description; } return value; } else { console.log('值为空:' + device.Name + '/' + dataName); } } else { console.log('无法找到:' + device.Name + '/' + dataName); } } else { console.log('无法找到:' + dataName); } return ""; }, callSence(id) { var url = vm.IoTServer + '/App/Sence/?node=' + this.Node.Number + '&id=' + id; ajax(url); }, call: function (gateway,number, cmd, query) { query = query || ''; var url = vm.IoTServer + '/App/Exec/?connectionId=' + vm.ConnectionId + '&gateway=' + gateway + '&number=' + number + '&method=' + cmd + query; if (query != '') { url += "&" + query; } ajax(url); }, callAll: function (name, cmd, query) { query = query || ''; var url = vm.IoTServer + '/App/ExecAll/?connectionId=' + vm.ConnectionId + '&node=' + this.Node.Number + '&cmd=' + cmd; var list = this.getDevices(name); for (var i = 0; i < list.length; i++) { url += '&id[' + i + ']=' + list[i].Id; } if (query != '') { url += "&" + query; } ajax(url); }, change1(e,device) { var data = _.first(_.filter(device.Data, function (o) { return o.Name === '按键' })); var form = $(e.target).parents('form'); if (form.hasClass('KeyCodeType1')) { if (form.find("[name='power']").val() == '1') { data.Value = "1";//form.find("[name = 'code']").val(1); } else { var code = 2; code += parseInt(form.find("[name = 'pattern']").val()); code += parseInt(form.find("[name = 'direction']").val()); code += parseInt(form.find("[name = 'wind']").val()); code += parseInt(form.find("[name = 'temperature']").val()); data.Value = code;//form.find("[name = 'code']").val(code); } } var url = form.attr('action') + '?' + form.serialize(); ajax(url); }, 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 }; } } }); Vue.component('page-device', { template: '#page-device', data() { return { Device: { Number: null, Name: null, Data: [], Apis: [] } } }, mounted() { this.Device.Number = this.$f7route.params.number; this.Device.Name = this.$f7route.params.name; device = this; var ajaxUrl = vm.IoTServer + "/App/GetDevice?token=" + vm.Token + '&number=' + this.Device.Number; app.dialog.progress(); $.get(ajaxUrl, function (response) { device.Device = response; Vue.nextTick(function () { createChart(); updateChart(); $('form.command').removeData('validator'); $('form.command').removeData('unobtrusiveValidation'); $.validator.unobtrusive.parse('form.command'); }); }).always(function () { app.dialog.close(); }); }, methods: { isSelect: function (device, key) { return _.filter(device.Data, function (o) { return o.Key == key + '[]' }).length > 0; }, getSelect: function (device, key) { var data = _.first(_.filter(device.Data, function (o) { return o.Key == key + '[]' })).Value; var result = JSON.parse(data); return result; }, getParameter: function (name) { console.log(name); var prop = _.chain(this.Device.Data).filter(function (o) { return o.Key == name; }).first().value(); return prop ? prop.Value : ''; }, call: function (e) { if (!$(e.target).valid()) { return; } var url = vm.IoTServer + '/App/Exec/?connectionId=' + vm.ConnectionId + '&node=' + this.getNodeNumber(this.Device.NodeId) + '&' + $(e.target).serialize(); ajax(url); }, getNodeNumber(nodeId) { return _.chain(vm.Nodes).filter(function (o) { return o.Id === nodeId; }).first().value().Number; }, showData(name) { if (name === 'hidden' || name.indexOf('rtsp') != -1 || name.indexOf('rtmp') != -1 || name.indexOf('flv') != -1 || name.indexOf('hls') != -1) { return false; } return true; }, showApi(api) { if (this.Device.Name === '摄像头') { if (this.getParameter('Ptz3DZoomSupport') === '否') { if (api.Name !== '截屏') { return false; } } } return true; }, getUrl(type) { var url = _.chain(this.Device.Data).filter(function (o) { return o.Name === (type + '2'); }).first().value().Value; url += '?id=' + this.Device.Id; url += '&host=' + encodeURIComponent(vm.IoTServer); url += '&node=' + _.chain(vm.Nodes).filter(function (o) { return o.Id === device.Device.NodeId; }).first().value().Number; if (this.getParameter('Ptz3DZoomSupport') !== '否') { url += '&ptz=true'; } return url; }, flv() { this.$f7router.navigate('/camera/', { props: { name: this.Device.DisplayName || this.Device.Name, url: this.getParameter('flv2'), ptz: this.getParameter('Ptz3DZoomSupport') !== '否', node: this.getNodeNumber(this.Device.NodeId), id: this.Device.Id, hls: this.getParameter('hls2') } }); } }, destroyed() { device = null; }, }); Vue.component('page-camera', { template: '#page-camera', props: ['name', 'url', 'ptz', 'node', 'id', 'hls'], data() { return { } }, mounted() { this.play(); }, methods: { play: function () { var url = this.$props.url; if (isiOS) { $('#flvPlayer').attr('src', this.$props.hls); } else { playFlv(url); } }, call: function (cmd) { console.log(cmd); var url = vm.IoTServer + '/App/Exec/?connectionId=' + vm.ConnectionId + '&cmd=' + cmd + '&node=' + this.$props.node + '&id=' + this.$props.id; ajax(url); return false; } }, destroy() { closePlayer(); } }); Vue.component('page-not-found', { template: '#page-not-found' }); vm = new Vue({ el: '#app', data() { return { f7params: { root: '#app', id: 'io.framework7.testapp', name: 'Framework7', theme: 'ios', routes: [ { path: '/', component: 'page-home' }, { path: '/login/', component: 'page-login' }, { path: '/node/:number/name/:name', component: 'page-node' }, { path: '/device/:number/name/:name', component: 'page-device' }, { path: '/camera/', component: 'page-camera' }, { path: '(.*)', component: 'page-not-found', }, ], }, Title: localStorage.getItem('Title'), Server: localStorage.getItem('Server'), Token: localStorage.getItem('Token'), UserName: localStorage.getItem('UserName'), RememberMe: localStorage.getItem('RememberMe'), NickName: localStorage.getItem('NickName'), IoTServer: localStorage.getItem('IoTServer'), User: null, Nodes: [], Messages: [], } }, mounted() { this.$f7ready((f7) => { app = this.$f7; if ((window.navigator.userAgent.indexOf("app") > -1)) { window.location.href = "uniwebview://init"; } else { load(); } }); }, methods: { init() { if (vm.Token) { var baseUrl = this.IoTServer; var wsUrl = baseUrl + "/hub?group=page"; var ajaxUrl = baseUrl + "/App/GetNodes?token=" + vm.Token; $.get(ajaxUrl, function (response) { vm.Nodes = response; }); connection = new signalR.HubConnectionBuilder().withUrl(wsUrl).build(); onMessage(); connect(); } } } }); function load() { if (localStorage.getItem('Token')) { vm.init(); } else { setTimeout(function () { app.view.current.router.navigate('/login/') }, 0); } } function load2(message) { var response = JSON.parse(message); vm.Token = response.Token; if (response.RememberMe === true) { localStorage.setItem("Token", response.Token); localStorage.setItem("Server", response.Server); localStorage.setItem("UserName", response.UserName); localStorage.setItem("NickName", response.NickName); localStorage.setItem("Title", response.Title); localStorage.setItem("IoTServer", _.trimEnd(response.IoTServer, ['/'])); } else { localStorage.removeItem("Token"); } vm.Server = response.Server; vm.RememberMe = response.RememberMe; vm.UserName = response.UserName; vm.NickName = response.NickName; vm.Title = response.Title; vm.IoTServer = _.trimEnd(response.IoTServer, ['/']); vm.$f7.view.current.router.back(); vm.init(); } // $('body').on('change', 'input.ajax', function (e) { var form = $(this).parents('form'); var url = form.attr('action') + '?' + form.serialize(); if (form.hasClass('KeyCodeType1')) { if (e.target.name == "power" && e.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[e.target.name] = e.target.value; var code = 0; for (var name in list) { code += parseInt(list[name]); } url = new URI(url).setQuery('Code', code).toString(); } } ajax(url); return false; });