/*var*/ var isApp = location.href.indexOf('http') !== 0; var server = isApp ? localStorage.getItem('server') : null; var iotCenter = isApp ? server + '/IoTCenter' : ''; var dataUrl = iotCenter + '/App/GetNode'; var token = isApp ? localStorage.getItem('token') : null; var wsUrl = iotCenter + '/hub?group=page'; var connectionId; const connection = new signalR.HubConnectionBuilder() .withUrl(wsUrl) .build(); var app; var vm; // var livePlayer; var timer; var decodedFrames; var muted = true; var volume = 0.5; // if (isApp) { Framework7.use(Framework7Vue); } toastr.options.timeOut = 500; toastr.options.positionClass = "toast-top-center"; /*fun*/ function alert(message,title) { if (isApp) { title = title || '消息'; app.dialog.alert(message, title); } else { alert(message); } } function hideLoading(message) { toastr.success(message||'请求成功'); $('.overlay').hide(); } function loadData() { var formData = new FormData(); formData.append('number', new URI().search(true).number); if (isApp) { formData.append('token', token); } axios.post(dataUrl, formData) .then(function (response) { console.log(response); data = response.data; if (data.Template) { loadTemplate(); } else { init(); } }) .catch(function (error) { toastr.error('数据加载失败!'); }) .then(hideLoading); } function loadTemplate() { var url = iotCenter + '/App/GetTemplate?template=' + data.Template; axios.post(url, { crossDomain: true }) .then(function (response) { var html = response.data; $('#template').html(html); init(); }) .catch(function (error) { 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 UpdateChart(deviceNumber) { $('canvas.chart').each(function () { var canvas = this; var number = canvas.id; if (!deviceNumber || deviceNumber === number) { var device = vm.GetDevice(number); var time = time || '30d'; var url = iotCenter + '/App/GetChartData?time=' + time + '+&number=' + number; axios.post(url, { crossDomain: true }) .then(function (response) { var data = response.data; UpdateChartInternal(canvas, device.DisplayName,data); }) .catch(function (error) { console.log(error); toastr.error(error) }); } }); } function UpdateChartInternal(canvas, title, data) { var chart; Chart.helpers.each(Chart.instances, function (instance) { if (instance.chart.canvas.id === canvas.id) { chart = instance; } }) if (chart) { chart.data = data; chart.update(); } else { var ctx = canvas.getContext('2d'); var options = { responsive: true, legend: { position: 'bottom', }, title: { display: false, text: title }, animation: { duration: 0 } }; var chart = new Chart(ctx, { type: 'line', data: data, options: options }); } } 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); type = type || 'get'; $('.overlay').show(); $.ajax({ type: type, url: url, data: data, success: AjaxCallBack }).fail(function (result) { toastr.error('请求发送失败!'); console.log(result); }).always(function () { $('.overlay').hide(); }); } function AjaxCallBack(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'); } } } function updateItem(list, item) { var update = false; for (var i = 0; i < list.length; i++) { if (list[i].Id == item.Id) { update = true; break; } } if (update) { list.splice(i, 1, item); } else { list.push(item); } } function deleteItem(list, item) { for (var i = 0; i < list.length; i++) { if (list[i].Id == item.Id) { list.splice(i, 1); break; } } } /*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', { token: token, connectionId: connectionId, number: number, method: '/Onvif/Stop' }, 'post'); }, 500); } return false; }); /*ws*/ function connect() { if (debug) { console.log('start connect to server:' + Date()); } if (connection.state === signalR.HubConnectionState.Disconnected) { connection.start().then(function () { toastr.success('客户端与服务器连接成功!'); }).catch(function (err) { toastr.error('客户端与服务器连接失败!'); setTimeout(connect, 15 * 1000); }); } } connection.on('Connected', function (id) { connectionId = id; }); connection.onclose(function (err) { setTimeout(connect, 15 * 1000); }); connection.on("ServerToClient", function (method, json, to,from) { console.log(method + ':' + json); onMessage(method, json,to, from); }); function onMessage(method, json,to, from) { var item = JSON.parse(json); if (method === 'ExecApiRsponse') { console.log(json); toastr.success('操作调用成功'); } else if (method === 'ExecSceneRsponse') { console.log(json); toastr.success('场景调用成功'); } else { if(method == 'DataEntityInserted' || method == 'DataEntityUpdated') { 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 + '更新'); if ($('canvas#' + device.Number).length) { UpdateChart(device.Number); } } } else if (method == 'SceneEntityInserted' || method == 'SceneEntityUpdated') { updateItem(vm.model.Scenes, item); toastr.info(item.Name + '更新'); } else if (method == 'SceneEntityDeleted') { deleteItem(vm.model.Scenes, item); toastr.info(item.Name+'删除'); } } } /*vue*/ function init() { $('#template style').each(function (i, n) { $('head').append(n); }); vm = new Vue({ el: '#app', data() { return { f7params: { routes: [], name: 'My App', id: 'com.myapp.test', theme: 'ios', }, model: data }; }, mounted() { if (isApp) { if (!server) { location.href = "config.html"; } if (!token) { location.href = "login.html"; } this.$f7ready((f7) => { app = this.$f7; }); } connect(); this.$nextTick(function () { UpdateCamera(); UpdateChart(); }); }, methods: { 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(); }, GetDevice(nameOrNumber) { return Enumerable.from(this.model.Devices) .where(function (o) { return o.Name === nameOrNumber || o.Number === nameOrNumber; }) .firstOrDefault(); }, GetChartDevices() { return Enumerable.from(this.model.Devices) .where(function (o) { return o.Name === '温湿度传感器' || o.Name === 'PM2.5感应器' || o.Name === '光强检测器' || o.Name === '智能插座'; }) .orderBy('o=>o.ProductId') .toArray(); }, GetDataValue(number, name) { var device = Enumerable.from(this.model.Devices) .where(function (o) { return o.Number === number; }) .firstOrDefault(); if (device != null) { var data = Enumerable.from(device.Data) .where(function (o) { return o.Name == name }) .firstOrDefault(); if (data != null) { return data.Value; } } return null; }, GetDeviceDataValue(number, name, attr) { var device = Enumerable.from(this.model.Devices).where(function (o) { return o.Number === number; }).firstOrDefault(); var data = Enumerable.from(device.Data).where(o => o.Name === name).firstOrDefault(); if (data != null) { return data[attr]; } 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', { token: token, connectionId: connectionId, number: number, method: method, query: query }, 'post'); }, GetScenes() { return Enumerable.from(this.model.Scenes).orderBy('o=>o.DisplayOrder').toArray(); }, CallScene(id) { ajax('/App/ExecScene', { token: token, connectionId: connectionId, id: id }, '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 + ',' + event.type + ',' + event.target.checked); 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; }