You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iot/projects/IoTCenter/wwwroot/node.default.html

342 lines
14 KiB

<div style="text-align:center;" v-if="ViewModel">{{ViewModel.Name}}</div>
<div class="row" v-if="ViewModel">
<div class="col-md-6">
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
</div>
<div class="col-md-6">
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
</div>
</div>
<div class="row" v-if="ViewModel">
<div class="col-md-6">
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
</div>
<div class="col-md-6">
<canvas id="NodeChart" style="width:100%;height:250px;"></canvas>
</div>
</div>
<hr />
<div class="row" v-if="ViewModel">
<div class="col-md-6">
<select class="form-control" id="camera" @change="CameraSelected">
<option v-for="c in GetCameras()" :value="c.Number">{{c.Name}}</option>
</select>
<div style="width:100%;height:265px;margin:0;padding:0;background:#000;">
<video id="flvPlayer" class="video" muted controls autoplay style="width:100%;max-width:100%;height:100%;"></video>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-6">
<div class="box box-solid">
<div class="row">
<div class="col-md-4">
<img src="/images/temperature.png" style="width:48px;height:48px;margin:20px;" />
</div>
<div class="col-md-4" style="height:88px;">
<h3 style="line-height:88px;margin:0;">{{GetData('温度','Description')}}</h3>
</div>
<div class="col-md-4" style="height:88px;">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">温度:{{GetData('温度','Value') }} {{GetData('温度','Unit')}}</span>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="box box-solid">
<div class="row">
<div class="col-md-4">
<img src="/images/humidity.png" style="width:48px;height:48px;margin:20px;" />
</div>
<div class="col-md-4" style="height:88px;">
<h3 style="line-height:88px;margin:0;">{{GetData('湿度','Description')}}</h3>
</div>
<div class="col-md-4" style="height:88px;">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">湿度:{{GetData('湿度','Value') }} {{GetData('湿度','Unit')}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="box box-solid">
<div class="row">
<div class="col-md-4">
<img src="/images/light.png" style="width:48px;height:48px;margin:20px;" />
</div>
<div class="col-md-4" style="height:88px;">
<h3 style="line-height:88px;margin:0;">{{GetDataByTag('前门','光照度','Description')}}</h3>
</div>
<div class="col-md-4" style="height:88px;">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">前门光照:{{GetDataByTag('前门','光照度','Value') }} {{GetDataByTag('前门','光照度','Unit')}}</span>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="box box-solid">
<div class="row">
<div class="col-md-4">
<img src="/images/light.png" style="width:48px;height:48px;margin:20px;" />
</div>
<div class="col-md-4" style="height:88px;">
<h3 style="line-height:88px;margin:0;">{{GetDataByTag('后门','光照度','Description')}}</h3>
</div>
<div class="col-md-4" style="height:88px;">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">后门光照:{{GetDataByTag('后门','光照度','Value') }} {{GetDataByTag('后门','光照度','Unit')}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="box box-solid">
<div class="row">
<div class="col-md-4">
<img src="/images/person.png" style="width:48px;height:48px;margin:20px;" />
</div>
<div class="col-md-4" style="height:88px;">
<img src="/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDataByTag('前门','状态','Value')==='警报'" />
</div>
<div class="col-md-4" style="height:88px;">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">前门人体:{{GetDataByTag('前门','状态','Value') }}</span>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="box box-solid">
<div class="row">
<div class="col-md-4">
<img src="/images/person.png" style="width:48px;height:48px;margin:20px;" />
</div>
<div class="col-md-4" style="height:88px;">
<img src="/images/warn.png" style="width:36px;height:36px;margin:32px 0 0 0;" v-if="GetDataByTag('后门','状态','Value')==='警报'" />
</div>
<div class="col-md-4" style="height:88px;">
<span style="display:inline-block;position:absolute;right:20px;bottom:5px;white-space: nowrap;">后门人体:{{GetDataByTag('后门','状态','Value') }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="ViewModel">
<div class="col-md-6">
<div class="box box-solid">
<table class="ptz" v-if="PTZControlSupport()">
<tr>
<td><img src="/images/zoomin.png" /></td>
<td></td>
<td><img src="/images/up.png" /></td>
<td></td>
<td><img src="/images/zoomout.png" /></td>
</tr>
<tr>
<td></td>
<td><img src="/images/left.png" /></td>
<td><img src="/images/stop.png" /></td>
<td><img src="/images/right.png" /></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td><img src="/images/down.png" /></td>
<td></td>
<td></td>
</tr>
</table>
</div>
</div>
<div class="col-md-6">
<div class="box box-solid btns">
<div class="row">
<div class="col-md-6"><button class="btn btn-block btn-primary">一键开</button></div>
<div class="col-md-6"><button class="btn btn-block btn-primary">一键关</button></div>
</div>
<div class="row">
<div class="col-md-3" v-for="scene in ViewModel.Scenes">
<button class="btn btn-block btn-info">{{scene.Name}}</button>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="ViewModel">
<div class="col-md-6">
开关
</div>
<div class="col-md-6">
插座
</div>
</div>
<script>
var flvPlayer;
var decodedFrames;
function UpdateChart(id, title, data, labels, colors, type) {
var ctx = document.getElementById(id).getContext('2d');
colors = colors || $.map(data, function (item) { return Color16(item); });
var data = {
datasets: [{
label: title,
data: data,
backgroundColor: colors
}],
labels: labels
};
var options = {
responsive: true,
legend: {
position: 'right',
},
title: {
display: true,
text: title
},
animation: {
duration: 0
}
};
var chart = new Chart(ctx, {
type: type,
data: data,
options: options
});
}
function Color16() {//十六进制颜色随机
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
var color = '#' + r.toString(16) + g.toString(16) + b.toString(16);
return color;
}
$('body').on('change', 'input.switch', function (e) {
if ($(this).is(':checked')) {
$(this).parent('label').addClass('on');
$(this).parent('label').removeClass('off');
} else {
$(this).parent('label').addClass('off');
$(this).parent('label').removeClass('on');
}
});
$('body').on('change', '#camera', function (e) {
UpdateCamera()
});
function UpdateCamera() {
var number = $('#camera').val();
var device = Enumerable.from(vm.ViewModel.Devices).where(function (o) { return o.Number === number; }).firstOrDefault();
var url = Enumerable.from(device.Data).where(o => o.Name === '主码流flv').firstOrDefault().Value;
closePlayer(flvPlayer);
playFlv(document.getElementById("flvPlayer"), url);
}
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;
}
}
</script>
<script>
var vm = new Vue({
el: '#template',
data() {
return { ViewModel: null }
},
mounted() {
var url = '/Home/GetNode' + '?number=' + new URI().query(true).number;
$.get(url, function (data) {
vm.ViewModel = data;
Vue.nextTick(function () {
//UpdateChart('NodeChart', '节点', vm.ViewModel.NodeChart.data, vm.ViewModel.NodeChart.labels, null, 'doughnut');
//UpdateChart('DeviceChart', '设备', vm.ViewModel.DeviceChart.data, vm.ViewModel.DeviceChart.labels, null, 'pie');
//UpdateChart('EnergyChart', '用电', vm.ViewModel.EnergyChart.data, vm.ViewModel.EnergyChart.labels, null, 'bar');
UpdateCamera();
});
});
},
methods: {
GetData(name, attr) {
var data = Enumerable
.from(vm.ViewModel.Devices)
.selectMany(function (o) { return o.Data; })
.where(function (o) { return o.Name === name; })
.firstOrDefault();
return data == null ? null : data[attr];
},
GetDataByTag(tag, name, attr) {
var data = Enumerable
.from(vm.ViewModel.Devices)
.where(function (o) { return o.Tag === tag; })
.selectMany(function (o) { return o.Data; })
.where(function (o) { return o.Name === name; })
.firstOrDefault();
return data == null ? null : data[attr];
},
GetCameras() {
return Enumerable
.from(vm.ViewModel.Devices)
.where(function (o) { return o.Name === '摄像头' })
.toArray();
},
CameraSelected() {
UpdateCamera();
},
PTZControlSupport() {
return true;
var number = $('#camera').val();
var device = Enumerable.from(vm.ViewModel.Devices).where(function (o) { return o.Number === number; }).firstOrDefault();
var data = Enumerable.from(device.Data).where(o => o.Name === '缩放支持').firstOrDefault().Value;
return data === '是';
}
},
destroy() {
closePlayer();
}
});
</script>