Former-commit-id: 62d1aaf757dac6209361ca21539915e68de08d45
TangShanKaiPing
wanggang 6 years ago
parent f861b38146
commit 14fe0d9711

@ -15,22 +15,22 @@
</PackageReference> </PackageReference>
<PackageReference Include="JWT" Version="5.3.1" /> <PackageReference Include="JWT" Version="5.3.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.1" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.1.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.0.0-rc1.final" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="3.1.0" /> <PackageReference Include="Serilog.AspNetCore" Version="3.2.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
<PackageReference Include="DotNetCore.NPOI" Version="1.2.2" /> <PackageReference Include="DotNetCore.NPOI" Version="1.2.2" />
<PackageReference Include="HtmlAgilityPack.NetCore" Version="1.5.0.1" /> <PackageReference Include="HtmlAgilityPack.NetCore" Version="1.5.0.1" />
<PackageReference Include="MailKit" Version="2.4.0.1" /> <PackageReference Include="MailKit" Version="2.4.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" /> <PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" /> <PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.0.0-rc4" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.0.0-rc4" />
<PackageReference Include="System.Drawing.Common" Version="4.6.0" /> <PackageReference Include="System.Drawing.Common" Version="4.6.1" />
<PackageReference Include="System.Management" Version="4.6.0" /> <PackageReference Include="System.Management" Version="4.6.0" />
<PackageReference Include="ValueInjecter" Version="3.2.0" /> <PackageReference Include="ValueInjecter" Version="3.2.0" />
<PackageReference Include="Flurl" Version="2.8.2" /> <PackageReference Include="Flurl" Version="2.8.2" />

@ -12,10 +12,10 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.1" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="3.0.0" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Client.Core" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.1.4" /> <PackageReference Include="Microsoft.OpenApi.Readers" Version="1.1.4" />
<PackageReference Include="SerialPortStream" Version="2.2.0" /> <PackageReference Include="SerialPortStream" Version="2.2.0" />
<PackageReference Include="NetCoreSerial" Version="1.3.2" /> <PackageReference Include="NetCoreSerial" Version="1.3.2" />

@ -185,8 +185,7 @@
</div> </div>
</div> </div>
</div> </div>
<template v-if="model.Product.Apis.length>0"> <template v-if="model.Name!=='摄像头'">
<!--接口-->
<div class="row" v-if="GetSimpleApis().length>0"> <div class="row" v-if="GetSimpleApis().length>0">
<div class="col-md-12"> <div class="col-md-12">
<div class="card"> <div class="card">
@ -196,39 +195,90 @@
</div> </div>
</div> </div>
</div> </div>
<template v-if="model.Name!=='调色灯'"> <div class="=row" v-for="api in Enumerable.from(model.Product.Apis).orderBy('o=>o.Name')" v-if="api.Parameters.length>1">
<div class="=row" v-for="api in Enumerable.from(model.Product.Apis).orderBy('o=>o.Name')" v-if="api.Parameters.length>1"> <div class="card">
<div class="card"> <div class="card-header">
<div class="card-header"> <h3 class="card-title">{{api.Name}}</h3>
<h3 class="card-title">{{api.Name}}</h3> </div>
</div> <div class="card-body">
<div class="card-body"> <form class="form-horizontal">
<form class="form-horizontal"> <input type="hidden" name="Number" :value="model.Number" />
<input type="hidden" name="Number" :value="model.Number" /> <input type="hidden" name="Method" :value="api.Method" />
<input type="hidden" name="Method" :value="api.Method" /> <div class="form-group" v-for="parameter in api.Parameters" v-if="parameter.Name!=='number'">
<div class="form-group" v-for="parameter in api.Parameters" v-if="parameter.Name!=='number'"> <label :for="parameter.Name">{{parameter.Description}}:</label>
<label :for="parameter.Name">{{parameter.Description}}:</label> <template v-if="model.Name==='网关'&&api.Name==='删掉制定设备'&&parameter.Name==='设备编号'">
<template v-if="model.Name==='网关'&&api.Name==='删掉制定设备'&&parameter.Name==='设备编号'"> </template>
<template v-else>
<template v-if="parameter.Type==='string'">
<input type="text" class="form-control" :name="parameter.Name" :value="GetDataValueByKey(parameter.Name)" />
</template> </template>
<template v-else> <template v-else>
<template v-if="parameter.Type==='string'"> <input type="text" class="form-control" :name="parameter.Name" :value="GetDataValueByKey(parameter.Name)" />
<input type="text" class="form-control" :name="parameter.Name" :value="GetDataValueByKey(parameter.Name)" />
</template>
<template v-else>
<input type="text" class="form-control" :name="parameter.Name" :value="GetDataValueByKey(parameter.Name)" />
</template>
</template> </template>
</template>
</div>
<div class="row">
<div class="col-sm-12">
<button class="btn btn-success">确定</button>
</div> </div>
<div class="row"> </div>
<div class="col-sm-12"> </form>
<button class="btn btn-success">确定</button> </div>
</div> </div>
</div> </div>
</form> </template>
<template v-else-if="model.Name==='摄像头'">
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">{{model.DisplayName}}</h3>
<input type="hidden" id="camera" :value="model.Number" />
<div class="card-tools">
<button class="btn btn-success" v-on:click="CallApi(model.Number,'/Onvif/StartPush')">开始推流</button>
<button class="btn btn-success" v-on:click="CallApi(model.Number,'/Onvif/StopPush')">停止推流</button>
</div>
</div>
<div style="max-width:100%;max-height:50%;margin:0;padding:0;background:#000;">
<video id="liveVideo" class="video" controls autoplay style="width:100%;max-width:100%;height:100%;"></video>
</div>
</div>
</div>
</div>
<div class="row" id="ptz">
<div class="col-md-12">
<div class="card" style="height:220px;">
<div class="card-header">
<h3 class="card-title"><img src="/images/ptz.png" />云台操作</h3>
</div>
<div class="card-body" style="height:178px;">
<table class="ptz" style="width:100%;">
<tr>
<td></td>
<td></td>
<td><img class="ajax camera" data-cmd="Up" :src="iotCenter+'/images/up.png'" /></td>
<td></td>
<td></td>
</tr>
<tr>
<td><img class="ajax camera" data-cmd="Zoomin" :src="iotCenter+'/images/zoomin.png'" /></td>
<td><img class="ajax camera" data-cmd="Left" :src="iotCenter+'/images/left.png'" /></td>
<td><img class="ajax camera" data-cmd="Stop" :src="iotCenter+'/images/stop.png'" /></td>
<td><img class="ajax camera" data-cmd="Right" :src="iotCenter+'/images/right.png'" /></td>
<td><img class="ajax camera" data-cmd="Zoomout" :src="iotCenter+'/images/zoomout.png'" /></td>
</tr>
<tr>
<td></td>
<td></td>
<td><img class="ajax camera" data-cmd="Down" :src="iotCenter+'/images/down.png'" /></td>
<td></td>
<td></td>
</tr>
</table>
</div> </div>
</div> </div>
</div> </div>
</template> </div>
</template> </template>
</template> </template>
</div> </div>

@ -270,7 +270,7 @@
<div class="col-md-12"> <div class="col-md-12">
<div class="card"> <div class="card">
<select class="form-control" id="camera" v-on:change="CameraSelected" style="height:40px;"> <select class="form-control" id="camera" v-on:change="CameraSelected" style="height:40px;">
<option v-for="c in GetDevices('摄像头')" :value="c.Number">{{c.DisplayName||c.Name}}</option> <option v-for="c in GetDevices('摄像头')" :value="c.Number">{{c.DisplayName}}</option>
</select> </select>
<div style="width:100%;height:180px;margin:0;padding:0;background:#000;"> <div style="width:100%;height:180px;margin:0;padding:0;background:#000;">
<video id="liveVideo" class="video" controls autoplay style="width:100%;max-width:100%;height:100%;"></video> <video id="liveVideo" class="video" controls autoplay style="width:100%;max-width:100%;height:100%;"></video>

@ -7,7 +7,7 @@
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup> </PropertyGroup>
 <ItemGroup>  <ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="wwwroot\**\*" /> <EmbeddedResource Include="wwwroot\**\*" />

@ -69,6 +69,9 @@ function onMessage(method, json, to, from) {
if ($('canvas#' + device.Number).length) { if ($('canvas#' + device.Number).length) {
UpdateChart(device.Number); UpdateChart(device.Number);
} }
if ($('#camera').val() === device.Number && item.Name === '推流') {
UpdateCamera();
}
} }
} }
} }

@ -106,7 +106,7 @@ methods = {
GetChartDevices() { GetChartDevices() {
return Enumerable.from(this.model.Devices) return Enumerable.from(this.model.Devices)
.where(function (o) { return o.Name === '温湿度传感器' || o.Name === 'PM2.5感应器' || o.Name === '光强检测器' || o.Name === '智能插座'; }) .where(function (o) { return o.Name === '温湿度传感器' || o.Name === 'PM2.5感应器' || o.Name === '光强检测器' || o.Name === '智能插座'; })
.orderBy('o=>o.ProductId') .orderBy(function (o) { return o.Name;})
.toArray(); .toArray();
} }
}; };
@ -130,6 +130,10 @@ function onMessage(method, json, to, from) {
if ($('canvas#' + device.Number).length) { if ($('canvas#' + device.Number).length) {
UpdateChart(device.Number); UpdateChart(device.Number);
} }
if ($('#camera').val() === device.Number && item.Name === '推流') {
console.log('start update camera');
UpdateCamera();
}
} }
} }
} }

@ -515,42 +515,45 @@ function playFlv(videoElement) {
$('#ptz').hide(); $('#ptz').hide();
} }
closePlayer(livePlayer); closePlayer(livePlayer);
try { var push = Enumerable.from(device.Data).where(o => o.Name === '推流').firstOrDefault();
livePlayer = flvjs.createPlayer({ if (push && push.Value === '是') {
type: 'flv', try {
url: url, livePlayer = flvjs.createPlayer({
isLive: true, type: 'flv',
cors: true url: url,
}, { isLive: true,
enableWorker: true, cors: true
enableStashBuffer: false, }, {
stashInitialSize: 1, enableWorker: true,
fixAudioTimestampGap: false enableStashBuffer: false,
}); stashInitialSize: 1,
livePlayer.attachMediaElement(videoElement); fixAudioTimestampGap: false
livePlayer.load(); });
livePlayer.volume = volume; livePlayer.attachMediaElement(videoElement);
livePlayer.muted = muted; livePlayer.load();
timer = setInterval(function () { livePlayer.volume = volume;
console.log('.'); livePlayer.muted = muted;
if (livePlayer.statisticsInfo.speed == 0) { timer = setInterval(function () {
console.log('reload1'); console.log('.');
clearInterval(timer); if (livePlayer.statisticsInfo.speed == 0) {
playFlv(videoElement); console.log('reload1');
} clearInterval(timer);
else if (decodedFrames && livePlayer.statisticsInfo.decodedFrames <= decodedFrames) { playFlv(videoElement);
console.log('reload2'); }
clearInterval(timer); else if (decodedFrames && livePlayer.statisticsInfo.decodedFrames <= decodedFrames) {
playFlv(videoElement); console.log('reload2');
} clearInterval(timer);
else if (livePlayer.buffered.end(0) - livePlayer.currentTime > 1) { playFlv(videoElement);
console.log('reset currentTime'); }
livePlayer.currentTime = livePlayer.buffered.end(0) - 0.001; else if (livePlayer.buffered.end(0) - livePlayer.currentTime > 1) {
} console.log('reset currentTime');
decodedFrames = livePlayer.statisticsInfo.decodedFrames; livePlayer.currentTime = livePlayer.buffered.end(0) - 0.001;
}, 10 * 1000); }
} catch (e) { decodedFrames = livePlayer.statisticsInfo.decodedFrames;
console.log(e); }, 10 * 1000);
} catch (e) {
console.log(e);
}
} }
} }
} }

@ -17,7 +17,7 @@ methods = {
|| this.model.Name.indexOf('插座') >= 0; || this.model.Name.indexOf('插座') >= 0;
}, },
GetDevices() { GetDevices() {
return Enumerable.from(this.model.Devices).orderBy('o=>o.DisplayOrder').orderBy('o=>o.Name').toArray(); return Enumerable.from(this.model.Devices).orderBy(function (o) { return o.DisplayOrder; }).orderBy(function (o) {return o.Name }).toArray();
}, },
GetDataValue(number, name) { GetDataValue(number, name) {
var device = Enumerable.from(this.model.Devices) var device = Enumerable.from(this.model.Devices)

@ -66,7 +66,7 @@ namespace IoTNode.DeviceServices.Onvif
{ {
try try
{ {
this.Remove(item); this.StopPushToServer(item);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -139,7 +139,8 @@ namespace IoTNode.DeviceServices.Onvif
this.UpdateDevice(deviceRepo, device); this.UpdateDevice(deviceRepo, device);
var fileName = $"ffmpeg-{Helper.Instance.GetRunTime()}{(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "")}"; var fileName = $"ffmpeg-{Helper.Instance.GetRunTime()}{(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : "")}";
var file = Path.Combine(this._env.WebRootPath, fileName); var file = Path.Combine(this._env.WebRootPath, fileName);
this.UpdateData(deviceRepo, device, device.CreateData("Push", "是", DeviceDataType.String, "推流")); var pushValue = device.Data.FirstOrDefault(o => o.Name == "推流")?.Value ?? "是";
this.UpdateData(deviceRepo, device, device.CreateData("Push", pushValue, DeviceDataType.String, "推流"));
this.UpdateData(deviceRepo, device, device.CreateData("Record", "否", DeviceDataType.String, "录像")); this.UpdateData(deviceRepo, device, device.CreateData("Record", "否", DeviceDataType.String, "录像"));
this.UpdateData(deviceRepo, device, device.CreateData("ffmpeg.file", file, DeviceDataType.String, "ffmpeg路径", hidden: true)); this.UpdateData(deviceRepo, device, device.CreateData("ffmpeg.file", file, DeviceDataType.String, "ffmpeg路径", hidden: true));
this.UpdateData(deviceRepo, device, device.CreateData("ffmpeg.args", this._cfg["ffmpeg.args"], DeviceDataType.String, "ffmpeg.args", hidden: true)); this.UpdateData(deviceRepo, device, device.CreateData("ffmpeg.args", this._cfg["ffmpeg.args"], DeviceDataType.String, "ffmpeg.args", hidden: true));
@ -253,7 +254,7 @@ namespace IoTNode.DeviceServices.Onvif
} }
if (remove) if (remove)
{ {
this.Remove(key); this.StopPushToServer(key);
} }
} }
foreach (var camera in cameras) foreach (var camera in cameras)
@ -264,7 +265,7 @@ namespace IoTNode.DeviceServices.Onvif
{ {
if (camera.Data.Any(o => o.Key == "NeedAuth" && o.Value == "否") || camera.Data.Any(o => o.Key == "HasAuth" && o.Value == "是")) if (camera.Data.Any(o => o.Key == "NeedAuth" && o.Value == "否") || camera.Data.Any(o => o.Key == "HasAuth" && o.Value == "是"))
{ {
this.Publish(camera); this.StartPushToServer(camera);
} }
} }
} }
@ -276,7 +277,7 @@ namespace IoTNode.DeviceServices.Onvif
} }
} }
private void Publish(Device camera) private void StartPushToServer(Device camera)
{ {
try try
{ {
@ -351,7 +352,7 @@ namespace IoTNode.DeviceServices.Onvif
} }
} }
public void Remove(string key) public void StopPushToServer(string key)
{ {
(Device camera, Process local, Process remote) item; (Device camera, Process local, Process remote) item;
if (this._list.TryRemove(key, out item)) if (this._list.TryRemove(key, out item))
@ -573,8 +574,16 @@ namespace IoTNode.DeviceServices.Onvif
{ {
var repo = scope.ServiceProvider.GetService<IRepository<Device>>(); var repo = scope.ServiceProvider.GetService<IRepository<Device>>();
var device = repo.Table().Include(o => o.Data).FirstOrDefault(o => o.Number == number); var device = repo.Table().Include(o => o.Data).FirstOrDefault(o => o.Number == number);
var data = device.Data.FirstOrDefault(o => o.Key == "Push"); if (device != null)
data.Value = "是"; {
var data = device.Data.FirstOrDefault(o => o.Key == "Push");
if (data != null)
{
data.Value = "是";
this.UpdateData(repo, device, data);
this.StartPushToServer(device);
}
}
} }
} }
@ -584,8 +593,16 @@ namespace IoTNode.DeviceServices.Onvif
{ {
var repo = scope.ServiceProvider.GetService<IRepository<Device>>(); var repo = scope.ServiceProvider.GetService<IRepository<Device>>();
var device = repo.Table().Include(o => o.Data).FirstOrDefault(o => o.Number == number); var device = repo.Table().Include(o => o.Data).FirstOrDefault(o => o.Number == number);
var data = device.Data.FirstOrDefault(o => o.Key == "Push"); if (device != null)
data.Value = "否"; {
var data = device.Data.FirstOrDefault(o => o.Key == "Push");
if (data != null)
{
data.Value = "否";
this.UpdateData(repo, device, data);
this.StopPushToServer(device.Number);
}
}
} }
} }

Loading…
Cancel
Save