Compare commits
25 Commits
7f1a85d430
...
feature/Co
Author | SHA1 | Date | |
---|---|---|---|
779e21909c | |||
f84ea8f0c5 | |||
181985859e | |||
39a38fe8eb | |||
490f0f3265 | |||
41bf14a4e5 | |||
3f267cb009 | |||
0e3eb8720f | |||
3f2467f6c6 | |||
2a83856622 | |||
d726273431 | |||
412647617b | |||
53ff60ae5a | |||
f273823c93 | |||
c92808ac7d | |||
f13133829a | |||
4c1258dc33 | |||
a52f6acd71 | |||
4281c2d524 | |||
639e6edac6 | |||
3632e56dc4 | |||
b87d90e5a4 | |||
f1c1ad69cc | |||
f102b89a21 | |||
e1a596dae9 |
@ -1,12 +1,13 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||||
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
|
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<SpaRoot>ClientApp\</SpaRoot>
|
<SpaRoot>ClientApp\</SpaRoot>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
|
||||||
|
<AssemblyName>Birdmap.API</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
@ -20,9 +21,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoMapper" Version="10.1.1" />
|
<PackageReference Include="AutoMapper" Version="10.1.1" />
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.9" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.9" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.9">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@ -30,7 +31,13 @@
|
|||||||
<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="MQTTnet" Version="3.0.13" />
|
||||||
|
<PackageReference Include="MQTTnet.AspNetCore" Version="3.0.13" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
<PackageReference Include="NLog" Version="4.7.5" />
|
||||||
|
<PackageReference Include="NLog.Web" Version="4.9.3" />
|
||||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
|
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" />
|
||||||
|
<PackageReference Include="NSwag.AspNetCore" Version="13.9.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -42,21 +49,19 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="ClientApp\src\common\components\BirdmapTitle.tsx" />
|
<None Remove="ClientApp\src\common\components\BirdmapTitle.tsx" />
|
||||||
<None Remove="ClientApp\src\common\ErrorDispatcher.ts" />
|
|
||||||
<None Remove="ClientApp\src\common\ServiceBase.ts" />
|
|
||||||
<None Remove="ClientApp\src\components\auth\Auth.tsx" />
|
<None Remove="ClientApp\src\components\auth\Auth.tsx" />
|
||||||
|
<None Remove="ClientApp\src\components\auth\AuthClient.ts" />
|
||||||
<None Remove="ClientApp\src\components\auth\AuthService.ts" />
|
<None Remove="ClientApp\src\components\auth\AuthService.ts" />
|
||||||
|
<None Remove="ClientApp\src\components\devices\DeviceService.ts" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<TypeScriptCompile Include="ClientApp\src\components\auth\Auth.tsx" />
|
<TypeScriptCompile Include="ClientApp\src\components\auth\Auth.tsx" />
|
||||||
<TypeScriptCompile Include="ClientApp\src\common\components\BirdmapTitle.tsx" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Folder Include="ClientApp\src\common\components\" />
|
||||||
<Folder Include="ClientApp\src\components\dashboard\" />
|
<Folder Include="ClientApp\src\components\dashboard\" />
|
||||||
<Folder Include="ClientApp\src\components\devices\" />
|
|
||||||
<Folder Include="ClientApp\src\components\heatmap\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
239
Birdmap.API/ClientApp/package-lock.json
generated
239
Birdmap.API/ClientApp/package-lock.json
generated
@ -1199,6 +1199,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||||
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
"integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="
|
||||||
},
|
},
|
||||||
|
"@googlemaps/js-api-loader": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-aFxlJVFOC00KELhlaqU6tpnxj9szVdG7OSHxQzc9uhp4Ky8/zvYNnzZg2S+pPvhe+WkJPugQL8fowP5nYTBXUg=="
|
||||||
|
},
|
||||||
"@hapi/address": {
|
"@hapi/address": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
||||||
@ -1424,6 +1429,11 @@
|
|||||||
"@types/yargs": "^13.0.0"
|
"@types/yargs": "^13.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@mapbox/point-geometry": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
|
||||||
|
"integrity": "sha1-ioP5M1x4YO/6Lu7KJUMyqgru2PI="
|
||||||
|
},
|
||||||
"@material-ui/core": {
|
"@material-ui/core": {
|
||||||
"version": "4.11.0",
|
"version": "4.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.0.tgz",
|
||||||
@ -1559,6 +1569,33 @@
|
|||||||
"react-is": "^16.8.0"
|
"react-is": "^16.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@microsoft/signalr": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-AsbU1ZB4Q9JsZ77W13VGT8gi/cVrFn3XbvVfULSwrC9DVCXF2JpkBDh0cCmRaYs9M3kqKohiVM1WPqNeAGil/g==",
|
||||||
|
"requires": {
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"eventsource": "^1.0.7",
|
||||||
|
"fetch-cookie": "^0.7.3",
|
||||||
|
"node-fetch": "^2.6.0",
|
||||||
|
"ws": "^6.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||||
|
},
|
||||||
|
"ws": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
|
||||||
|
"requires": {
|
||||||
|
"async-limiter": "~1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@mrmlnc/readdir-enhanced": {
|
"@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||||
@ -2170,6 +2207,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
||||||
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="
|
"integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q=="
|
||||||
},
|
},
|
||||||
|
"abort-controller": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||||
|
"requires": {
|
||||||
|
"event-target-shim": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.7",
|
"version": "1.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||||
@ -3406,6 +3451,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
||||||
},
|
},
|
||||||
|
"can-use-dom": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/can-use-dom/-/can-use-dom-0.1.0.tgz",
|
||||||
|
"integrity": "sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo="
|
||||||
|
},
|
||||||
"caniuse-api": {
|
"caniuse-api": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
|
||||||
@ -3450,6 +3500,11 @@
|
|||||||
"supports-color": "^5.3.0"
|
"supports-color": "^5.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"change-emitter": {
|
||||||
|
"version": "0.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz",
|
||||||
|
"integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU="
|
||||||
|
},
|
||||||
"chardet": {
|
"chardet": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||||
@ -4857,6 +4912,24 @@
|
|||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||||
},
|
},
|
||||||
|
"encoding": {
|
||||||
|
"version": "0.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||||
|
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||||
|
"requires": {
|
||||||
|
"iconv-lite": "^0.6.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"iconv-lite": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"end-of-stream": {
|
"end-of-stream": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
@ -4972,6 +5045,11 @@
|
|||||||
"next-tick": "~1.0.0"
|
"next-tick": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"es6-denodeify": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/es6-denodeify/-/es6-denodeify-0.1.5.tgz",
|
||||||
|
"integrity": "sha1-MdTV/pxVA+ElRgQ5MQ4WoqPznB8="
|
||||||
|
},
|
||||||
"es6-iterator": {
|
"es6-iterator": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||||
@ -5498,6 +5576,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||||
},
|
},
|
||||||
|
"event-target-shim": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="
|
||||||
|
},
|
||||||
"eventemitter3": {
|
"eventemitter3": {
|
||||||
"version": "4.0.7",
|
"version": "4.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||||
@ -5857,6 +5940,44 @@
|
|||||||
"bser": "2.1.1"
|
"bser": "2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fbjs": {
|
||||||
|
"version": "0.8.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
|
||||||
|
"integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^1.0.0",
|
||||||
|
"isomorphic-fetch": "^2.1.1",
|
||||||
|
"loose-envify": "^1.0.0",
|
||||||
|
"object-assign": "^4.1.0",
|
||||||
|
"promise": "^7.1.1",
|
||||||
|
"setimmediate": "^1.0.5",
|
||||||
|
"ua-parser-js": "^0.7.18"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": {
|
||||||
|
"version": "1.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
|
||||||
|
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
|
||||||
|
},
|
||||||
|
"promise": {
|
||||||
|
"version": "7.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
|
||||||
|
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
|
||||||
|
"requires": {
|
||||||
|
"asap": "~2.0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fetch-cookie": {
|
||||||
|
"version": "0.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.7.3.tgz",
|
||||||
|
"integrity": "sha512-rZPkLnI8x5V+zYAiz8QonAHsTb4BY+iFowFBI1RFn0zrO343AVp9X7/yUj/9wL6Ef/8fLls8b/vGtzUvmyAUGA==",
|
||||||
|
"requires": {
|
||||||
|
"es6-denodeify": "^0.1.1",
|
||||||
|
"tough-cookie": "^2.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"figgy-pudding": {
|
"figgy-pudding": {
|
||||||
"version": "3.5.2",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
|
||||||
@ -6326,6 +6447,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"google-map-react": {
|
||||||
|
"version": "2.1.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/google-map-react/-/google-map-react-2.1.9.tgz",
|
||||||
|
"integrity": "sha512-//Pa0o6sdspU2H0ehVztSDQSnYYeV6TY4Z6ftty34yiCJYLliOzeq17dA9uFkyUFdL+XwbTU6e9mfs+bjBMIzw==",
|
||||||
|
"requires": {
|
||||||
|
"@googlemaps/js-api-loader": "^1.7.0",
|
||||||
|
"@mapbox/point-geometry": "^0.1.0",
|
||||||
|
"eventemitter3": "^4.0.4",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"google-maps": {
|
"google-maps": {
|
||||||
"version": "4.3.3",
|
"version": "4.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/google-maps/-/google-maps-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/google-maps/-/google-maps-4.3.3.tgz",
|
||||||
@ -6334,6 +6466,11 @@
|
|||||||
"@types/googlemaps": "^3.39.1"
|
"@types/googlemaps": "^3.39.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"google-maps-infobox": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/google-maps-infobox/-/google-maps-infobox-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-hTuWmWZZSOxf5D/z7l3/hTF1grgRvLG53BEKMdjiKOG+FcK/kH7vqseUeyIU9Zj2ZIqKTOaro0nknxpAuRq4Vw=="
|
||||||
|
},
|
||||||
"google-maps-react": {
|
"google-maps-react": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.6.tgz",
|
||||||
@ -7207,6 +7344,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
|
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
|
||||||
},
|
},
|
||||||
|
"isomorphic-fetch": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
|
||||||
|
"integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
|
||||||
|
"requires": {
|
||||||
|
"node-fetch": "^1.0.1",
|
||||||
|
"whatwg-fetch": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"isstream": {
|
"isstream": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||||
@ -8321,6 +8467,16 @@
|
|||||||
"object-visit": "^1.0.0"
|
"object-visit": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"marker-clusterer-plus": {
|
||||||
|
"version": "2.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/marker-clusterer-plus/-/marker-clusterer-plus-2.1.4.tgz",
|
||||||
|
"integrity": "sha1-+O/3TVmdqzt9Dj/tUmTqDnBPXWc="
|
||||||
|
},
|
||||||
|
"markerwithlabel": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/markerwithlabel/-/markerwithlabel-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-C/cbm1A0h/u54gwHk5ZJNdUU3V3+1BbCpRPMsMyFA7vF4yL+aB4rWpxACz29TpQ+cTg6/iQroExh0PMSRGtQFg=="
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
@ -8734,6 +8890,15 @@
|
|||||||
"tslib": "^1.10.0"
|
"tslib": "^1.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node-fetch": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
|
||||||
|
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
|
||||||
|
"requires": {
|
||||||
|
"encoding": "^0.1.11",
|
||||||
|
"is-stream": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "0.10.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||||
@ -10809,6 +10974,50 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.7.tgz",
|
||||||
"integrity": "sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA=="
|
"integrity": "sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA=="
|
||||||
},
|
},
|
||||||
|
"react-google-maps": {
|
||||||
|
"version": "9.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-google-maps/-/react-google-maps-9.4.5.tgz",
|
||||||
|
"integrity": "sha512-8z5nX9DxIcBCXuEiurmRT1VXVwnzx0C6+3Es6lxB2/OyY2SLax2/LcDu6Aldxnl3HegefTL7NJzGeaKAJ61pOA==",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.11.6",
|
||||||
|
"can-use-dom": "^0.1.0",
|
||||||
|
"google-maps-infobox": "^2.0.0",
|
||||||
|
"invariant": "^2.2.1",
|
||||||
|
"lodash": "^4.16.2",
|
||||||
|
"marker-clusterer-plus": "^2.1.4",
|
||||||
|
"markerwithlabel": "^2.0.1",
|
||||||
|
"prop-types": "^15.5.8",
|
||||||
|
"recompose": "^0.26.0",
|
||||||
|
"scriptjs": "^2.5.8",
|
||||||
|
"warning": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"hoist-non-react-statics": {
|
||||||
|
"version": "2.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||||
|
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
|
||||||
|
},
|
||||||
|
"recompose": {
|
||||||
|
"version": "0.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/recompose/-/recompose-0.26.0.tgz",
|
||||||
|
"integrity": "sha512-KwOu6ztO0mN5vy3+zDcc45lgnaUoaQse/a5yLVqtzTK13czSWnFGmXbQVmnoMgDkI5POd1EwIKSbjU1V7xdZog==",
|
||||||
|
"requires": {
|
||||||
|
"change-emitter": "^0.1.2",
|
||||||
|
"fbjs": "^0.8.1",
|
||||||
|
"hoist-non-react-statics": "^2.3.1",
|
||||||
|
"symbol-observable": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"warning": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz",
|
||||||
|
"integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=",
|
||||||
|
"requires": {
|
||||||
|
"loose-envify": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.12.0",
|
"version": "16.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
||||||
@ -11189,6 +11398,26 @@
|
|||||||
"util.promisify": "^1.0.0"
|
"util.promisify": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"recompose": {
|
||||||
|
"version": "0.30.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz",
|
||||||
|
"integrity": "sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.0.0",
|
||||||
|
"change-emitter": "^0.1.2",
|
||||||
|
"fbjs": "^0.8.1",
|
||||||
|
"hoist-non-react-statics": "^2.3.1",
|
||||||
|
"react-lifecycles-compat": "^3.0.2",
|
||||||
|
"symbol-observable": "^1.0.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"hoist-non-react-statics": {
|
||||||
|
"version": "2.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
|
||||||
|
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"recursive-readdir": {
|
"recursive-readdir": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
||||||
@ -11748,6 +11977,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"scriptjs": {
|
||||||
|
"version": "2.5.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz",
|
||||||
|
"integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg=="
|
||||||
|
},
|
||||||
"seamless-immutable": {
|
"seamless-immutable": {
|
||||||
"version": "7.1.4",
|
"version": "7.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz",
|
||||||
@ -13262,6 +13496,11 @@
|
|||||||
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
|
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"ua-parser-js": {
|
||||||
|
"version": "0.7.22",
|
||||||
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz",
|
||||||
|
"integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q=="
|
||||||
|
},
|
||||||
"unicode-canonical-property-names-ecmascript": {
|
"unicode-canonical-property-names-ecmascript": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@material-ui/icons": "^4.9.1",
|
"@material-ui/icons": "^4.9.1",
|
||||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||||
|
"@microsoft/signalr": "^5.0.0",
|
||||||
"bootstrap": "^4.3.1",
|
"bootstrap": "^4.3.1",
|
||||||
"connected-react-router": "6.5.2",
|
"connected-react-router": "6.5.2",
|
||||||
|
"google-map-react": "^2.1.9",
|
||||||
"google-maps": "^4.3.3",
|
"google-maps": "^4.3.3",
|
||||||
"google-maps-react": "^2.0.6",
|
"google-maps-react": "^2.0.6",
|
||||||
"history": "4.10.1",
|
"history": "4.10.1",
|
||||||
@ -16,11 +18,13 @@
|
|||||||
"popper.js": "^1.16.0",
|
"popper.js": "^1.16.0",
|
||||||
"react": "^16.11.0",
|
"react": "^16.11.0",
|
||||||
"react-dom": "16.11.0",
|
"react-dom": "16.11.0",
|
||||||
|
"react-google-maps": "^9.4.5",
|
||||||
"react-redux": "7.1.1",
|
"react-redux": "7.1.1",
|
||||||
"react-router": "5.1.2",
|
"react-router": "5.1.2",
|
||||||
"react-router-dom": "5.1.2",
|
"react-router-dom": "5.1.2",
|
||||||
"react-scripts": "^3.4.4",
|
"react-scripts": "^3.4.4",
|
||||||
"reactstrap": "8.1.1",
|
"reactstrap": "8.1.1",
|
||||||
|
"recompose": "^0.30.0",
|
||||||
"redux": "4.0.4",
|
"redux": "4.0.4",
|
||||||
"redux-thunk": "2.3.0",
|
"redux-thunk": "2.3.0",
|
||||||
"svgo": "1.3.0"
|
"svgo": "1.3.0"
|
||||||
|
@ -22,11 +22,11 @@
|
|||||||
-->
|
-->
|
||||||
<title>Birdmap</title>
|
<title>Birdmap</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body style="height: 100vh;">
|
||||||
<noscript>
|
<noscript>
|
||||||
You need to enable JavaScript to run this app.
|
You need to enable JavaScript to run this app.
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="root"></div>
|
<div id="root" style="height: 100vh;"></div>
|
||||||
<!--
|
<!--
|
||||||
This HTML file is a template.
|
This HTML file is a template.
|
||||||
If you open it directly in the browser, you will see an empty page.
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
@ -1,27 +1,32 @@
|
|||||||
import { Box, Container, IconButton, Menu, MenuItem, MenuList, Paper, Grow, Popper } from '@material-ui/core';
|
import { Box, Container, IconButton, Menu, MenuItem, MenuList, Paper, Grow, Popper } from '@material-ui/core';
|
||||||
import AccountCircle from '@material-ui/icons/AccountCircle';
|
import AccountCircle from '@material-ui/icons/AccountCircle';
|
||||||
import AppBar from '@material-ui/core/AppBar';
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
import blue from '@material-ui/core/colors/blue';
|
import { positions } from '@material-ui/system';
|
||||||
import orange from '@material-ui/core/colors/orange';
|
|
||||||
import { createMuiTheme, createStyles, makeStyles, Theme } from '@material-ui/core/styles';
|
import { createMuiTheme, createStyles, makeStyles, Theme } from '@material-ui/core/styles';
|
||||||
import Toolbar from '@material-ui/core/Toolbar';
|
import Toolbar from '@material-ui/core/Toolbar';
|
||||||
import Typography from '@material-ui/core/Typography';
|
import Typography from '@material-ui/core/Typography';
|
||||||
import { ThemeProvider } from '@material-ui/styles';
|
import { ThemeProvider } from '@material-ui/styles';
|
||||||
import React, { useState, } from 'react';
|
import React, { useState, } from 'react';
|
||||||
import { BrowserRouter, NavLink, Redirect, Route, Switch, Link } from 'react-router-dom';
|
import { BrowserRouter, NavLink, Redirect, Route, Switch, Link } from 'react-router-dom';
|
||||||
import BirdmapTitle from './common/components/BirdmapTitle';
|
import BirdmapTitle from './components/appBar/BirdmapTitle';
|
||||||
import Auth from './components/auth/Auth';
|
import Auth from './components/auth/Auth';
|
||||||
import AuthService from './components/auth/AuthService';
|
import AuthService from './components/auth/AuthService';
|
||||||
import { ClickAwayListener } from '@material-ui/core';
|
import { ClickAwayListener } from '@material-ui/core';
|
||||||
|
import MapContainer from './components/heatmap/Heatmap';
|
||||||
|
import Devices from './components/devices/Devices';
|
||||||
|
import { blueGrey, blue, orange, grey } from '@material-ui/core/colors';
|
||||||
|
import DevicesContextProvider from './contexts/DevicesContextProvider'
|
||||||
|
|
||||||
|
|
||||||
const theme = createMuiTheme({
|
const theme = createMuiTheme({
|
||||||
palette: {
|
palette: {
|
||||||
primary: {
|
primary: {
|
||||||
main: blue[900],
|
main: blueGrey[900],
|
||||||
|
dark: grey[400],
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: orange[200],
|
main: orange[200],
|
||||||
|
dark: blueGrey[50],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -29,9 +34,11 @@ const theme = createMuiTheme({
|
|||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
|
const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
|
||||||
|
const [isAdmin, setIsAdmin] = useState(AuthService.isAdmin());
|
||||||
|
|
||||||
const onAuthenticated = () => {
|
const onAuthenticated = () => {
|
||||||
setAuthenticated(AuthService.isAuthenticated());
|
setAuthenticated(AuthService.isAuthenticated());
|
||||||
|
setIsAdmin(AuthService.isAdmin());
|
||||||
};
|
};
|
||||||
|
|
||||||
const AuthComponent = () => {
|
const AuthComponent = () => {
|
||||||
@ -41,27 +48,33 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const DashboardComponent = () => {
|
const DashboardComponent = () => {
|
||||||
return <Typography>Dashboard</Typography>;
|
return <Link to="/devices/5">This is a link</Link>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DevicesComponent = () => {
|
const DevicesComponent = () => {
|
||||||
return <Typography>Devices</Typography>;
|
return <Devices isAdmin={isAdmin}/>;
|
||||||
|
|
||||||
};
|
};
|
||||||
const HeatmapComponent = () => {
|
const HeatmapComponent = () => {
|
||||||
return <Typography>Heatmap</Typography>;
|
return (
|
||||||
|
<Paper elevation={0}>
|
||||||
|
<MapContainer />
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Switch>
|
<Switch>
|
||||||
<PublicRoute path="/login" component={AuthComponent} />
|
<PublicRoute path="/login" component={AuthComponent} />
|
||||||
|
<DevicesContextProvider>
|
||||||
<PrivateRoute path="/" exact authenticated={authenticated} component={DashboardComponent} />
|
<PrivateRoute path="/" exact authenticated={authenticated} component={DashboardComponent} />
|
||||||
<PrivateRoute path="/devices" exact authenticated={authenticated} component={DevicesComponent} />
|
<PrivateRoute path="/devices/:id?" exact authenticated={authenticated} component={DevicesComponent} />
|
||||||
<PrivateRoute path="/heatmap" exact authenticated={authenticated} component={HeatmapComponent} />
|
<PrivateRoute path="/heatmap" exact authenticated={authenticated} component={HeatmapComponent} />
|
||||||
</Switch>
|
</DevicesContextProvider>
|
||||||
</BrowserRouter>
|
</Switch>
|
||||||
|
</BrowserRouter>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -71,7 +84,7 @@ export default App;
|
|||||||
const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
|
const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
|
||||||
return (
|
return (
|
||||||
<Route {...rest} render={matchProps => (
|
<Route {...rest} render={matchProps => (
|
||||||
<DefaultLayout component={Component} authenticated={false} {...matchProps} />
|
<DefaultLayout component={Component} authenticated={false} isAdmin={false} {...matchProps} />
|
||||||
)} />
|
)} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -133,7 +146,7 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
|||||||
return Authenticated
|
return Authenticated
|
||||||
? <Container className={classes.nav_menu}>
|
? <Container className={classes.nav_menu}>
|
||||||
<NavLink exact to="/" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Dashboard</NavLink>
|
<NavLink exact to="/" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Dashboard</NavLink>
|
||||||
<NavLink exact to="/devices" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Devices</NavLink>
|
<NavLink to="/devices" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Devices</NavLink>
|
||||||
<NavLink exact to="/heatmap" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Heatmap</NavLink>
|
<NavLink exact to="/heatmap" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Heatmap</NavLink>
|
||||||
<IconButton className={classes.nav_menu_icon}
|
<IconButton className={classes.nav_menu_icon}
|
||||||
ref={anchorRef}
|
ref={anchorRef}
|
||||||
@ -164,7 +177,7 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<AppBar position="static">
|
<AppBar position="static" className={classes.bar_root}>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<BirdmapTitle />
|
<BirdmapTitle />
|
||||||
<Typography component={'span'} className={classes.typo}>
|
<Typography component={'span'} className={classes.typo}>
|
||||||
@ -172,7 +185,7 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
<Box style={{ margin: '32px' }}>
|
<Box zIndex="modal" className={classes.box_root}>
|
||||||
<Component {...rest} />
|
<Component {...rest} />
|
||||||
</Box>
|
</Box>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
@ -181,6 +194,13 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
|||||||
|
|
||||||
const useDefaultLayoutStyles = makeStyles((theme: Theme) =>
|
const useDefaultLayoutStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
|
bar_root: {
|
||||||
|
height: '7%',
|
||||||
|
},
|
||||||
|
box_root: {
|
||||||
|
backgroundColor: theme.palette.primary.dark,
|
||||||
|
height: '93%',
|
||||||
|
},
|
||||||
typo: {
|
typo: {
|
||||||
marginLeft: 'auto',
|
marginLeft: 'auto',
|
||||||
color: 'white',
|
color: 'white',
|
||||||
|
5
Birdmap.API/ClientApp/src/common/Constants.js
Normal file
5
Birdmap.API/ClientApp/src/common/Constants.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default {
|
||||||
|
probability_method_name: 'NotifyDeviceAsync',
|
||||||
|
update_method_name: 'NotifyDeviceUpdatedAsync',
|
||||||
|
update_all_method_name: 'NotifyAllUpdatedAsync',
|
||||||
|
};
|
@ -21,7 +21,7 @@ var __extends = (this && this.__extends) || (function () {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.ApiException = exports.SensorStatus = exports.Coordinates = exports.DeviceStatus = exports.Sensor = exports.Device = exports.DeviceService = void 0;
|
exports.ApiException = exports.SensorStatus = exports.Coordinates = exports.DeviceStatus = exports.Sensor = exports.Device = void 0;
|
||||||
var DeviceService = /** @class */ (function () {
|
var DeviceService = /** @class */ (function () {
|
||||||
function DeviceService(baseUrl, http) {
|
function DeviceService(baseUrl, http) {
|
||||||
this.jsonParseReviver = undefined;
|
this.jsonParseReviver = undefined;
|
||||||
@ -38,7 +38,8 @@ var DeviceService = /** @class */ (function () {
|
|||||||
var options_ = {
|
var options_ = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
@ -89,7 +90,9 @@ var DeviceService = /** @class */ (function () {
|
|||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
var options_ = {
|
var options_ = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {}
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
return _this.processOfflineall(_response);
|
return _this.processOfflineall(_response);
|
||||||
@ -129,7 +132,9 @@ var DeviceService = /** @class */ (function () {
|
|||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
var options_ = {
|
var options_ = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {}
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
return _this.processOnlineall(_response);
|
return _this.processOnlineall(_response);
|
||||||
@ -174,7 +179,8 @@ var DeviceService = /** @class */ (function () {
|
|||||||
var options_ = {
|
var options_ = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
@ -223,7 +229,9 @@ var DeviceService = /** @class */ (function () {
|
|||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
var options_ = {
|
var options_ = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {}
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
return _this.processOfflinedevice(_response);
|
return _this.processOfflinedevice(_response);
|
||||||
@ -267,7 +275,9 @@ var DeviceService = /** @class */ (function () {
|
|||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
var options_ = {
|
var options_ = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {}
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
return _this.processOnlinedevice(_response);
|
return _this.processOnlinedevice(_response);
|
||||||
@ -316,7 +326,8 @@ var DeviceService = /** @class */ (function () {
|
|||||||
var options_ = {
|
var options_ = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
@ -369,7 +380,9 @@ var DeviceService = /** @class */ (function () {
|
|||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
var options_ = {
|
var options_ = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {}
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
return _this.processOfflinesensor(_response);
|
return _this.processOfflinesensor(_response);
|
||||||
@ -417,7 +430,9 @@ var DeviceService = /** @class */ (function () {
|
|||||||
url_ = url_.replace(/[?&]$/, "");
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
var options_ = {
|
var options_ = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {}
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return this.http.fetch(url_, options_).then(function (_response) {
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
return _this.processOnlinesensor(_response);
|
return _this.processOnlinesensor(_response);
|
||||||
@ -449,7 +464,7 @@ var DeviceService = /** @class */ (function () {
|
|||||||
};
|
};
|
||||||
return DeviceService;
|
return DeviceService;
|
||||||
}());
|
}());
|
||||||
exports.DeviceService = DeviceService;
|
exports.default = DeviceService;
|
||||||
var Device = /** @class */ (function () {
|
var Device = /** @class */ (function () {
|
||||||
function Device(data) {
|
function Device(data) {
|
||||||
if (data) {
|
if (data) {
|
1
Birdmap.API/ClientApp/src/common/DeviceService.js.map
Normal file
1
Birdmap.API/ClientApp/src/common/DeviceService.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -7,7 +7,7 @@
|
|||||||
//----------------------
|
//----------------------
|
||||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
export class DeviceService {
|
export default class DeviceService {
|
||||||
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
|
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
|
||||||
private baseUrl: string;
|
private baseUrl: string;
|
||||||
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
|
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
|
||||||
@ -27,7 +27,8 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -73,6 +74,7 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,6 +113,7 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,7 +156,8 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -199,6 +203,7 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -241,6 +246,7 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -287,7 +293,8 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/json"
|
"Accept": "application/json",
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -337,6 +344,7 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -383,6 +391,7 @@ export class DeviceService {
|
|||||||
let options_ = <RequestInit>{
|
let options_ = <RequestInit>{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
'Authorization': sessionStorage.getItem('user')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
var ErrorDispatcher = {
|
|
||||||
errorHandlers: [],
|
|
||||||
registerErrorHandler: function (errorHandlerFn) {
|
|
||||||
this.errorHandlers.push(errorHandlerFn);
|
|
||||||
},
|
|
||||||
raiseError: function (errorMessage) {
|
|
||||||
for (var i = 0; i < this.errorHandlers.length; i++)
|
|
||||||
this.errorHandlers[i](errorMessage);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.default = ErrorDispatcher;
|
|
||||||
//# sourceMappingURL=ErrorDispatcher.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"ErrorDispatcher.js","sourceRoot":"","sources":["ErrorDispatcher.ts"],"names":[],"mappings":";;AAAA,IAAM,eAAe,GAAG;IACtB,aAAa,EAAE,EAAE;IAEjB,oBAAoB,YAAC,cAAc;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU,YAAC,YAAY;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE;YAChD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;CACF,CAAC;AAEF,kBAAe,eAAe,CAAC"}
|
|
@ -1,14 +0,0 @@
|
|||||||
const ErrorDispatcher = {
|
|
||||||
errorHandlers: [],
|
|
||||||
|
|
||||||
registerErrorHandler(errorHandlerFn) {
|
|
||||||
this.errorHandlers.push(errorHandlerFn);
|
|
||||||
},
|
|
||||||
|
|
||||||
raiseError(errorMessage) {
|
|
||||||
for (let i = 0; i < this.errorHandlers.length; i++)
|
|
||||||
this.errorHandlers[i](errorMessage);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ErrorDispatcher;
|
|
@ -1,50 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
var ErrorDispatcher_1 = require("./ErrorDispatcher");
|
|
||||||
function get(url) {
|
|
||||||
var options = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': sessionStorage.getItem('user')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return makeRequest(url, options);
|
|
||||||
}
|
|
||||||
function post(url, request) {
|
|
||||||
var options = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': sessionStorage.getItem('user')
|
|
||||||
},
|
|
||||||
body: "",
|
|
||||||
};
|
|
||||||
if (request)
|
|
||||||
options.body = JSON.stringify(request);
|
|
||||||
return makeRequest(url, options);
|
|
||||||
}
|
|
||||||
function makeRequest(url, options) {
|
|
||||||
return fetch(url, options)
|
|
||||||
.then(ensureResponseSuccess)
|
|
||||||
.catch(errorHandler);
|
|
||||||
}
|
|
||||||
function ensureResponseSuccess(response) {
|
|
||||||
if (!response.ok)
|
|
||||||
return response.json()
|
|
||||||
.then(function (data) { return errorHandler(data); });
|
|
||||||
return response.text()
|
|
||||||
.then(function (text) { return text.length ? JSON.parse(text) : {}; });
|
|
||||||
}
|
|
||||||
function errorHandler(response) {
|
|
||||||
console.log(response);
|
|
||||||
if (response && response.Error)
|
|
||||||
ErrorDispatcher_1.default.raiseError(response.Error);
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
exports.default = {
|
|
||||||
get: get,
|
|
||||||
post: post,
|
|
||||||
makeRequest: makeRequest
|
|
||||||
};
|
|
||||||
//# sourceMappingURL=ServiceBase.js.map
|
|
@ -1 +0,0 @@
|
|||||||
{"version":3,"file":"ServiceBase.js","sourceRoot":"","sources":["ServiceBase.ts"],"names":[],"mappings":";;AAAA,qDAAgD;AAEhD,SAAS,GAAG,CAAC,GAAW;IACpB,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;KACJ,CAAC;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,OAAY;IACnC,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;QACD,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,OAAY;IAC1C,OAAO,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC;SACrB,IAAI,CAAC,qBAAqB,CAAC;SAC3B,KAAK,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAa;IACxC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACZ,OAAO,QAAQ,CAAC,IAAI,EAAE;aACjB,IAAI,CAAC,UAAC,IAAS,IAAK,OAAA,YAAY,CAAC,IAAI,CAAC,EAAlB,CAAkB,CAAC,CAAC;IAEjD,OAAO,QAAQ,CAAC,IAAI,EAAE;SACjB,IAAI,CAAC,UAAC,IAAS,IAAK,OAAA,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAnC,CAAmC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,YAAY,CAAC,QAAa;IAC/B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK;QAC1B,yBAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,kBAAe;IACX,GAAG,KAAA;IACH,IAAI,MAAA;IACJ,WAAW,aAAA;CACd,CAAC"}
|
|
@ -1,59 +0,0 @@
|
|||||||
import ErrorDispatcher from './ErrorDispatcher';
|
|
||||||
|
|
||||||
function get(url: string) {
|
|
||||||
let options = {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': sessionStorage.getItem('user')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return makeRequest(url, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function post(url: string, request: any) {
|
|
||||||
let options = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': sessionStorage.getItem('user')
|
|
||||||
},
|
|
||||||
body: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
if (request)
|
|
||||||
options.body = JSON.stringify(request);
|
|
||||||
|
|
||||||
return makeRequest(url, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeRequest(url: string, options: any) {
|
|
||||||
return fetch(url, options)
|
|
||||||
.then(ensureResponseSuccess)
|
|
||||||
.catch(errorHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureResponseSuccess(response: any) {
|
|
||||||
if (!response.ok)
|
|
||||||
return response.json()
|
|
||||||
.then((data: any) => errorHandler(data));
|
|
||||||
|
|
||||||
return response.text()
|
|
||||||
.then((text: any) => text.length ? JSON.parse(text) : {});
|
|
||||||
}
|
|
||||||
|
|
||||||
function errorHandler(response: any) {
|
|
||||||
console.log(response);
|
|
||||||
|
|
||||||
if (response && response.Error)
|
|
||||||
ErrorDispatcher.raiseError(response.Error);
|
|
||||||
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
get,
|
|
||||||
post,
|
|
||||||
makeRequest
|
|
||||||
};
|
|
@ -54,15 +54,15 @@ export default function Auth(props: any) {
|
|||||||
|
|
||||||
setIsLoggingIn(true);
|
setIsLoggingIn(true);
|
||||||
AuthService.login(username, password)
|
AuthService.login(username, password)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
props.onAuthenticated();
|
setIsLoggingIn(false);
|
||||||
history.push('/');
|
props.onAuthenticated();
|
||||||
}).catch(() => {
|
history.push('/');
|
||||||
setShowError(true);
|
}).catch(() => {
|
||||||
setErrorMessage('Invalid credentials');
|
setShowError(true);
|
||||||
}).finally(() => {
|
setIsLoggingIn(false);
|
||||||
setIsLoggingIn(false);
|
setErrorMessage('Invalid credentials');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderErrorLabel = () => {
|
const renderErrorLabel = () => {
|
||||||
|
256
Birdmap.API/ClientApp/src/components/auth/AuthClient.js
Normal file
256
Birdmap.API/ClientApp/src/components/auth/AuthClient.js
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
"use strict";
|
||||||
|
var __extends = (this && this.__extends) || (function () {
|
||||||
|
var extendStatics = function (d, b) {
|
||||||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||||
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||||
|
return extendStatics(d, b);
|
||||||
|
};
|
||||||
|
return function (d, b) {
|
||||||
|
extendStatics(d, b);
|
||||||
|
function __() { this.constructor = d; }
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.ApiException = exports.RegisterRequest = exports.AuthenticateRequest = exports.HttpStatusCode = void 0;
|
||||||
|
var AuthClient = /** @class */ (function () {
|
||||||
|
function AuthClient(baseUrl, http) {
|
||||||
|
this.jsonParseReviver = undefined;
|
||||||
|
this.http = http ? http : window;
|
||||||
|
this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "";
|
||||||
|
}
|
||||||
|
AuthClient.prototype.authenticate = function (model) {
|
||||||
|
var _this = this;
|
||||||
|
var url_ = this.baseUrl + "/api/Auth/authenticate";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
var content_ = JSON.stringify(model);
|
||||||
|
var options_ = {
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
|
return _this.processAuthenticate(_response);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
AuthClient.prototype.processAuthenticate = function (response) {
|
||||||
|
var _this = this;
|
||||||
|
var status = response.status;
|
||||||
|
var _headers = {};
|
||||||
|
if (response.headers && response.headers.forEach) {
|
||||||
|
response.headers.forEach(function (v, k) { return _headers[k] = v; });
|
||||||
|
}
|
||||||
|
;
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then(function (_responseText) {
|
||||||
|
var result200 = null;
|
||||||
|
var resultData200 = _responseText === "" ? null : JSON.parse(_responseText, _this.jsonParseReviver);
|
||||||
|
result200 = resultData200 !== undefined ? resultData200 : null;
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then(function (_responseText) {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve(null);
|
||||||
|
};
|
||||||
|
AuthClient.prototype.register = function (model) {
|
||||||
|
var _this = this;
|
||||||
|
var url_ = this.baseUrl + "/api/Auth/register";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
var content_ = JSON.stringify(model);
|
||||||
|
var options_ = {
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return this.http.fetch(url_, options_).then(function (_response) {
|
||||||
|
return _this.processRegister(_response);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
AuthClient.prototype.processRegister = function (response) {
|
||||||
|
var status = response.status;
|
||||||
|
var _headers = {};
|
||||||
|
if (response.headers && response.headers.forEach) {
|
||||||
|
response.headers.forEach(function (v, k) { return _headers[k] = v; });
|
||||||
|
}
|
||||||
|
;
|
||||||
|
if (status === 204) {
|
||||||
|
return response.text().then(function (_responseText) {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then(function (_responseText) {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve(null);
|
||||||
|
};
|
||||||
|
return AuthClient;
|
||||||
|
}());
|
||||||
|
exports.default = AuthClient;
|
||||||
|
var HttpStatusCode;
|
||||||
|
(function (HttpStatusCode) {
|
||||||
|
HttpStatusCode["Continue"] = "Continue";
|
||||||
|
HttpStatusCode["SwitchingProtocols"] = "SwitchingProtocols";
|
||||||
|
HttpStatusCode["Processing"] = "Processing";
|
||||||
|
HttpStatusCode["EarlyHints"] = "EarlyHints";
|
||||||
|
HttpStatusCode["OK"] = "OK";
|
||||||
|
HttpStatusCode["Created"] = "Created";
|
||||||
|
HttpStatusCode["Accepted"] = "Accepted";
|
||||||
|
HttpStatusCode["NonAuthoritativeInformation"] = "NonAuthoritativeInformation";
|
||||||
|
HttpStatusCode["NoContent"] = "NoContent";
|
||||||
|
HttpStatusCode["ResetContent"] = "ResetContent";
|
||||||
|
HttpStatusCode["PartialContent"] = "PartialContent";
|
||||||
|
HttpStatusCode["MultiStatus"] = "MultiStatus";
|
||||||
|
HttpStatusCode["AlreadyReported"] = "AlreadyReported";
|
||||||
|
HttpStatusCode["IMUsed"] = "IMUsed";
|
||||||
|
HttpStatusCode["MultipleChoices"] = "Ambiguous";
|
||||||
|
HttpStatusCode["Ambiguous"] = "Ambiguous";
|
||||||
|
HttpStatusCode["MovedPermanently"] = "Moved";
|
||||||
|
HttpStatusCode["Moved"] = "Moved";
|
||||||
|
HttpStatusCode["Found"] = "Redirect";
|
||||||
|
HttpStatusCode["Redirect"] = "Redirect";
|
||||||
|
HttpStatusCode["SeeOther"] = "RedirectMethod";
|
||||||
|
HttpStatusCode["RedirectMethod"] = "RedirectMethod";
|
||||||
|
HttpStatusCode["NotModified"] = "NotModified";
|
||||||
|
HttpStatusCode["UseProxy"] = "UseProxy";
|
||||||
|
HttpStatusCode["Unused"] = "Unused";
|
||||||
|
HttpStatusCode["TemporaryRedirect"] = "TemporaryRedirect";
|
||||||
|
HttpStatusCode["RedirectKeepVerb"] = "TemporaryRedirect";
|
||||||
|
HttpStatusCode["PermanentRedirect"] = "PermanentRedirect";
|
||||||
|
HttpStatusCode["BadRequest"] = "BadRequest";
|
||||||
|
HttpStatusCode["Unauthorized"] = "Unauthorized";
|
||||||
|
HttpStatusCode["PaymentRequired"] = "PaymentRequired";
|
||||||
|
HttpStatusCode["Forbidden"] = "Forbidden";
|
||||||
|
HttpStatusCode["NotFound"] = "NotFound";
|
||||||
|
HttpStatusCode["MethodNotAllowed"] = "MethodNotAllowed";
|
||||||
|
HttpStatusCode["NotAcceptable"] = "NotAcceptable";
|
||||||
|
HttpStatusCode["ProxyAuthenticationRequired"] = "ProxyAuthenticationRequired";
|
||||||
|
HttpStatusCode["RequestTimeout"] = "RequestTimeout";
|
||||||
|
HttpStatusCode["Conflict"] = "Conflict";
|
||||||
|
HttpStatusCode["Gone"] = "Gone";
|
||||||
|
HttpStatusCode["LengthRequired"] = "LengthRequired";
|
||||||
|
HttpStatusCode["PreconditionFailed"] = "PreconditionFailed";
|
||||||
|
HttpStatusCode["RequestEntityTooLarge"] = "RequestEntityTooLarge";
|
||||||
|
HttpStatusCode["RequestUriTooLong"] = "RequestUriTooLong";
|
||||||
|
HttpStatusCode["UnsupportedMediaType"] = "UnsupportedMediaType";
|
||||||
|
HttpStatusCode["RequestedRangeNotSatisfiable"] = "RequestedRangeNotSatisfiable";
|
||||||
|
HttpStatusCode["ExpectationFailed"] = "ExpectationFailed";
|
||||||
|
HttpStatusCode["MisdirectedRequest"] = "MisdirectedRequest";
|
||||||
|
HttpStatusCode["UnprocessableEntity"] = "UnprocessableEntity";
|
||||||
|
HttpStatusCode["Locked"] = "Locked";
|
||||||
|
HttpStatusCode["FailedDependency"] = "FailedDependency";
|
||||||
|
HttpStatusCode["UpgradeRequired"] = "UpgradeRequired";
|
||||||
|
HttpStatusCode["PreconditionRequired"] = "PreconditionRequired";
|
||||||
|
HttpStatusCode["TooManyRequests"] = "TooManyRequests";
|
||||||
|
HttpStatusCode["RequestHeaderFieldsTooLarge"] = "RequestHeaderFieldsTooLarge";
|
||||||
|
HttpStatusCode["UnavailableForLegalReasons"] = "UnavailableForLegalReasons";
|
||||||
|
HttpStatusCode["InternalServerError"] = "InternalServerError";
|
||||||
|
HttpStatusCode["NotImplemented"] = "NotImplemented";
|
||||||
|
HttpStatusCode["BadGateway"] = "BadGateway";
|
||||||
|
HttpStatusCode["ServiceUnavailable"] = "ServiceUnavailable";
|
||||||
|
HttpStatusCode["GatewayTimeout"] = "GatewayTimeout";
|
||||||
|
HttpStatusCode["HttpVersionNotSupported"] = "HttpVersionNotSupported";
|
||||||
|
HttpStatusCode["VariantAlsoNegotiates"] = "VariantAlsoNegotiates";
|
||||||
|
HttpStatusCode["InsufficientStorage"] = "InsufficientStorage";
|
||||||
|
HttpStatusCode["LoopDetected"] = "LoopDetected";
|
||||||
|
HttpStatusCode["NotExtended"] = "NotExtended";
|
||||||
|
HttpStatusCode["NetworkAuthenticationRequired"] = "NetworkAuthenticationRequired";
|
||||||
|
})(HttpStatusCode = exports.HttpStatusCode || (exports.HttpStatusCode = {}));
|
||||||
|
var AuthenticateRequest = /** @class */ (function () {
|
||||||
|
function AuthenticateRequest(data) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
this[property] = data[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AuthenticateRequest.prototype.init = function (_data) {
|
||||||
|
if (_data) {
|
||||||
|
this.username = _data["username"];
|
||||||
|
this.password = _data["password"];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
AuthenticateRequest.fromJS = function (data) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
var result = new AuthenticateRequest();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
AuthenticateRequest.prototype.toJSON = function (data) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
data["username"] = this.username;
|
||||||
|
data["password"] = this.password;
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return AuthenticateRequest;
|
||||||
|
}());
|
||||||
|
exports.AuthenticateRequest = AuthenticateRequest;
|
||||||
|
var RegisterRequest = /** @class */ (function () {
|
||||||
|
function RegisterRequest(data) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
this[property] = data[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegisterRequest.prototype.init = function (_data) {
|
||||||
|
if (_data) {
|
||||||
|
this.username = _data["username"];
|
||||||
|
this.password = _data["password"];
|
||||||
|
this.confirmPassword = _data["confirmPassword"];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RegisterRequest.fromJS = function (data) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
var result = new RegisterRequest();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
RegisterRequest.prototype.toJSON = function (data) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
data["username"] = this.username;
|
||||||
|
data["password"] = this.password;
|
||||||
|
data["confirmPassword"] = this.confirmPassword;
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
return RegisterRequest;
|
||||||
|
}());
|
||||||
|
exports.RegisterRequest = RegisterRequest;
|
||||||
|
var ApiException = /** @class */ (function (_super) {
|
||||||
|
__extends(ApiException, _super);
|
||||||
|
function ApiException(message, status, response, headers, result) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.isApiException = true;
|
||||||
|
_this.message = message;
|
||||||
|
_this.status = status;
|
||||||
|
_this.response = response;
|
||||||
|
_this.headers = headers;
|
||||||
|
_this.result = result;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
ApiException.isApiException = function (obj) {
|
||||||
|
return obj.isApiException === true;
|
||||||
|
};
|
||||||
|
return ApiException;
|
||||||
|
}(Error));
|
||||||
|
exports.ApiException = ApiException;
|
||||||
|
function throwException(message, status, response, headers, result) {
|
||||||
|
if (result !== null && result !== undefined)
|
||||||
|
throw result;
|
||||||
|
else
|
||||||
|
throw new ApiException(message, status, response, headers, null);
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=AuthClient.js.map
|
File diff suppressed because one or more lines are too long
274
Birdmap.API/ClientApp/src/components/auth/AuthClient.ts
Normal file
274
Birdmap.API/ClientApp/src/components/auth/AuthClient.ts
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
export default class AuthClient {
|
||||||
|
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
|
||||||
|
private baseUrl: string;
|
||||||
|
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
|
||||||
|
this.http = http ? http : <any>window;
|
||||||
|
this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate(model: AuthenticateRequest): Promise<any> {
|
||||||
|
let url_ = this.baseUrl + "/api/Auth/authenticate";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
const content_ = JSON.stringify(model);
|
||||||
|
|
||||||
|
let options_ = <RequestInit>{
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processAuthenticate(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processAuthenticate(response: Response): Promise<any> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
|
||||||
|
result200 = resultData200 !== undefined ? resultData200 : <any>null;
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<any>(<any>null);
|
||||||
|
}
|
||||||
|
|
||||||
|
register(model: RegisterRequest): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/Auth/register";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
const content_ = JSON.stringify(model);
|
||||||
|
|
||||||
|
let options_ = <RequestInit>{
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processRegister(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processRegister(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(<any>null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export enum HttpStatusCode {
|
||||||
|
Continue = "Continue",
|
||||||
|
SwitchingProtocols = "SwitchingProtocols",
|
||||||
|
Processing = "Processing",
|
||||||
|
EarlyHints = "EarlyHints",
|
||||||
|
OK = "OK",
|
||||||
|
Created = "Created",
|
||||||
|
Accepted = "Accepted",
|
||||||
|
NonAuthoritativeInformation = "NonAuthoritativeInformation",
|
||||||
|
NoContent = "NoContent",
|
||||||
|
ResetContent = "ResetContent",
|
||||||
|
PartialContent = "PartialContent",
|
||||||
|
MultiStatus = "MultiStatus",
|
||||||
|
AlreadyReported = "AlreadyReported",
|
||||||
|
IMUsed = "IMUsed",
|
||||||
|
MultipleChoices = "Ambiguous",
|
||||||
|
Ambiguous = "Ambiguous",
|
||||||
|
MovedPermanently = "Moved",
|
||||||
|
Moved = "Moved",
|
||||||
|
Found = "Redirect",
|
||||||
|
Redirect = "Redirect",
|
||||||
|
SeeOther = "RedirectMethod",
|
||||||
|
RedirectMethod = "RedirectMethod",
|
||||||
|
NotModified = "NotModified",
|
||||||
|
UseProxy = "UseProxy",
|
||||||
|
Unused = "Unused",
|
||||||
|
TemporaryRedirect = "TemporaryRedirect",
|
||||||
|
RedirectKeepVerb = "TemporaryRedirect",
|
||||||
|
PermanentRedirect = "PermanentRedirect",
|
||||||
|
BadRequest = "BadRequest",
|
||||||
|
Unauthorized = "Unauthorized",
|
||||||
|
PaymentRequired = "PaymentRequired",
|
||||||
|
Forbidden = "Forbidden",
|
||||||
|
NotFound = "NotFound",
|
||||||
|
MethodNotAllowed = "MethodNotAllowed",
|
||||||
|
NotAcceptable = "NotAcceptable",
|
||||||
|
ProxyAuthenticationRequired = "ProxyAuthenticationRequired",
|
||||||
|
RequestTimeout = "RequestTimeout",
|
||||||
|
Conflict = "Conflict",
|
||||||
|
Gone = "Gone",
|
||||||
|
LengthRequired = "LengthRequired",
|
||||||
|
PreconditionFailed = "PreconditionFailed",
|
||||||
|
RequestEntityTooLarge = "RequestEntityTooLarge",
|
||||||
|
RequestUriTooLong = "RequestUriTooLong",
|
||||||
|
UnsupportedMediaType = "UnsupportedMediaType",
|
||||||
|
RequestedRangeNotSatisfiable = "RequestedRangeNotSatisfiable",
|
||||||
|
ExpectationFailed = "ExpectationFailed",
|
||||||
|
MisdirectedRequest = "MisdirectedRequest",
|
||||||
|
UnprocessableEntity = "UnprocessableEntity",
|
||||||
|
Locked = "Locked",
|
||||||
|
FailedDependency = "FailedDependency",
|
||||||
|
UpgradeRequired = "UpgradeRequired",
|
||||||
|
PreconditionRequired = "PreconditionRequired",
|
||||||
|
TooManyRequests = "TooManyRequests",
|
||||||
|
RequestHeaderFieldsTooLarge = "RequestHeaderFieldsTooLarge",
|
||||||
|
UnavailableForLegalReasons = "UnavailableForLegalReasons",
|
||||||
|
InternalServerError = "InternalServerError",
|
||||||
|
NotImplemented = "NotImplemented",
|
||||||
|
BadGateway = "BadGateway",
|
||||||
|
ServiceUnavailable = "ServiceUnavailable",
|
||||||
|
GatewayTimeout = "GatewayTimeout",
|
||||||
|
HttpVersionNotSupported = "HttpVersionNotSupported",
|
||||||
|
VariantAlsoNegotiates = "VariantAlsoNegotiates",
|
||||||
|
InsufficientStorage = "InsufficientStorage",
|
||||||
|
LoopDetected = "LoopDetected",
|
||||||
|
NotExtended = "NotExtended",
|
||||||
|
NetworkAuthenticationRequired = "NetworkAuthenticationRequired",
|
||||||
|
}
|
||||||
|
|
||||||
|
export class AuthenticateRequest implements IAuthenticateRequest {
|
||||||
|
username!: string;
|
||||||
|
password!: string;
|
||||||
|
|
||||||
|
constructor(data?: IAuthenticateRequest) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
(<any>this)[property] = (<any>data)[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_data?: any) {
|
||||||
|
if (_data) {
|
||||||
|
this.username = _data["username"];
|
||||||
|
this.password = _data["password"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJS(data: any): AuthenticateRequest {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
let result = new AuthenticateRequest();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(data?: any) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
data["username"] = this.username;
|
||||||
|
data["password"] = this.password;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IAuthenticateRequest {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RegisterRequest implements IRegisterRequest {
|
||||||
|
username!: string;
|
||||||
|
password!: string;
|
||||||
|
confirmPassword!: string;
|
||||||
|
|
||||||
|
constructor(data?: IRegisterRequest) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
(<any>this)[property] = (<any>data)[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_data?: any) {
|
||||||
|
if (_data) {
|
||||||
|
this.username = _data["username"];
|
||||||
|
this.password = _data["password"];
|
||||||
|
this.confirmPassword = _data["confirmPassword"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJS(data: any): RegisterRequest {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
let result = new RegisterRequest();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(data?: any) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
data["username"] = this.username;
|
||||||
|
data["password"] = this.password;
|
||||||
|
data["confirmPassword"] = this.confirmPassword;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRegisterRequest {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
confirmPassword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileResponse {
|
||||||
|
data: Blob;
|
||||||
|
status: number;
|
||||||
|
fileName?: string;
|
||||||
|
headers?: { [name: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApiException extends Error {
|
||||||
|
message: string;
|
||||||
|
status: number;
|
||||||
|
response: string;
|
||||||
|
headers: { [key: string]: any; };
|
||||||
|
result: any;
|
||||||
|
|
||||||
|
constructor(message: string, status: number, response: string, headers: { [key: string]: any; }, result: any) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.message = message;
|
||||||
|
this.status = status;
|
||||||
|
this.response = response;
|
||||||
|
this.headers = headers;
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected isApiException = true;
|
||||||
|
|
||||||
|
static isApiException(obj: any): obj is ApiException {
|
||||||
|
return obj.isApiException === true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function throwException(message: string, status: number, response: string, headers: { [key: string]: any; }, result?: any): any {
|
||||||
|
if (result !== null && result !== undefined)
|
||||||
|
throw result;
|
||||||
|
else
|
||||||
|
throw new ApiException(message, status, response, headers, null);
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
var ServiceBase_1 = require("../../common/ServiceBase");
|
var AuthClient_1 = require("./AuthClient");
|
||||||
var login_url = 'api/auth/authenticate';
|
|
||||||
exports.default = {
|
exports.default = {
|
||||||
isAuthenticated: function () {
|
isAuthenticated: function () {
|
||||||
return sessionStorage.getItem('user') !== null;
|
return sessionStorage.getItem('user') !== null && sessionStorage.getItem('user') !== undefined;
|
||||||
},
|
},
|
||||||
isAdmin: function () {
|
isAdmin: function () {
|
||||||
return sessionStorage.getItem('role') === 'Admin';
|
return sessionStorage.getItem('role') === 'Admin';
|
||||||
@ -14,21 +13,16 @@ exports.default = {
|
|||||||
sessionStorage.removeItem('role');
|
sessionStorage.removeItem('role');
|
||||||
},
|
},
|
||||||
login: function (username, password) {
|
login: function (username, password) {
|
||||||
var body = {
|
var service = new AuthClient_1.default();
|
||||||
|
var request = new AuthClient_1.AuthenticateRequest({
|
||||||
username: username,
|
username: username,
|
||||||
password: password
|
password: password
|
||||||
};
|
});
|
||||||
var options = {
|
return service.authenticate(request)
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
};
|
|
||||||
return ServiceBase_1.default.makeRequest(login_url, options)
|
|
||||||
.then(function (response) {
|
.then(function (response) {
|
||||||
sessionStorage.setItem('user', response.token_type + " " + response.access_token);
|
//console.log(response);
|
||||||
sessionStorage.setItem('role', response.role);
|
sessionStorage.setItem('user', response.tokenType + " " + response.accessToken);
|
||||||
|
sessionStorage.setItem('role', response.userRole);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,OAAO;QACH,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC;IACtD,CAAC;IAED,MAAM;QACF,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,EAAL,UAAM,QAAgB,EAAE,QAAgB;QACpC,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC9C,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
|
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,2CAA+D;AAE/D,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,SAAS,CAAC;IACnG,CAAC;IAED,OAAO;QACH,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC;IACtD,CAAC;IAED,MAAM;QACF,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAClC,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,EAAL,UAAM,QAAgB,EAAE,QAAgB;QACpC,IAAM,OAAO,GAAG,IAAI,oBAAU,EAAE,CAAC;QAEjC,IAAI,OAAO,GAAG,IAAI,gCAAmB,CAAC;YAClC,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC;aAC/B,IAAI,CAAC,UAAA,QAAQ;YACV,wBAAwB;YACxB,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,SAAS,SAAI,QAAQ,CAAC,WAAa,CAAC,CAAC;YAChF,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAClD,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
|
@ -1,10 +1,8 @@
|
|||||||
import ServiceBase from '../../common/ServiceBase';
|
import AuthClient, { AuthenticateRequest } from './AuthClient';
|
||||||
|
|
||||||
const login_url = 'api/auth/authenticate';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
isAuthenticated() {
|
isAuthenticated() {
|
||||||
return sessionStorage.getItem('user') !== null;
|
return sessionStorage.getItem('user') !== null && sessionStorage.getItem('user') !== undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
isAdmin() {
|
isAdmin() {
|
||||||
@ -17,22 +15,18 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
login(username: string, password: string) {
|
login(username: string, password: string) {
|
||||||
let body = {
|
const service = new AuthClient();
|
||||||
|
|
||||||
|
let request = new AuthenticateRequest({
|
||||||
username: username,
|
username: username,
|
||||||
password: password
|
password: password
|
||||||
};
|
});
|
||||||
let options = {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body),
|
|
||||||
};
|
|
||||||
|
|
||||||
return ServiceBase.makeRequest(login_url, options)
|
return service.authenticate(request)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
sessionStorage.setItem('user', `${response.token_type} ${response.access_token}`);
|
//console.log(response);
|
||||||
sessionStorage.setItem('role', response.role);
|
sessionStorage.setItem('user', `${response.tokenType} ${response.accessToken}`);
|
||||||
|
sessionStorage.setItem('role', response.userRole);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
191
Birdmap.API/ClientApp/src/components/devices/DeviceComponent.jsx
Normal file
191
Birdmap.API/ClientApp/src/components/devices/DeviceComponent.jsx
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import Accordion from '@material-ui/core/Accordion';
|
||||||
|
import { blue, blueGrey, green, orange, red, yellow } from '@material-ui/core/colors';
|
||||||
|
import AccordionSummary from '@material-ui/core/AccordionSummary';
|
||||||
|
import AccordionDetails from '@material-ui/core/AccordionDetails';
|
||||||
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||||
|
import { Grid, Typography, Paper, IconButton, Box, FormControlLabel } from '@material-ui/core';
|
||||||
|
import { withStyles } from '@material-ui/styles';
|
||||||
|
import { withRouter } from "react-router";
|
||||||
|
import { Power, PowerOff, Refresh } from '@material-ui/icons/';
|
||||||
|
import DeviceService from '../../common/DeviceService'
|
||||||
|
import DevicesContext from '../../contexts/DevicesContext';
|
||||||
|
|
||||||
|
const styles = theme => ({
|
||||||
|
acc_summary: {
|
||||||
|
backgroundColor: blueGrey[50],
|
||||||
|
},
|
||||||
|
acc_details: {
|
||||||
|
backgroundColor: blueGrey[100],
|
||||||
|
},
|
||||||
|
grid_typo: {
|
||||||
|
fontSize: theme.typography.pxToRem(20),
|
||||||
|
fontWeight: theme.typography.fontWeightRegular,
|
||||||
|
},
|
||||||
|
grid_typo_2: {
|
||||||
|
marginLeft: '5px',
|
||||||
|
fontSize: theme.typography.pxToRem(15),
|
||||||
|
fontWeight: theme.typography.fontWeightRegular,
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
},
|
||||||
|
grid_item: {
|
||||||
|
width: '100%',
|
||||||
|
marginLeft: '5px',
|
||||||
|
},
|
||||||
|
grid_item_typo: {
|
||||||
|
fontSize: theme.typography.pxToRem(15),
|
||||||
|
fontWeight: theme.typography.fontWeightRegular,
|
||||||
|
},
|
||||||
|
grid_item_typo_2: {
|
||||||
|
marginLeft: '5px',
|
||||||
|
fontSize: theme.typography.pxToRem(15),
|
||||||
|
fontWeight: theme.typography.fontWeightRegular,
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
},
|
||||||
|
icon_box: {
|
||||||
|
marginRight: '15px',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
class DeviceComponent extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
expanded: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static contextType = DevicesContext;
|
||||||
|
|
||||||
|
getColor(status) {
|
||||||
|
if (status == "Online") {
|
||||||
|
return { color: green[600] };
|
||||||
|
} else if (status == "Offline") {
|
||||||
|
return { color: orange[900] };
|
||||||
|
} else /* if (device.status == "unknown") */ {
|
||||||
|
return { color: red[800] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const id = this.props.match.params.id;
|
||||||
|
this.setState({ expanded: id });
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSensorButtons(device, sensor) {
|
||||||
|
var service = new DeviceService();
|
||||||
|
return this.renderButtons(
|
||||||
|
() => service.onlinesensor(device.id, sensor.id),
|
||||||
|
() => service.offlinesensor(device.id, sensor.id),
|
||||||
|
() => this.context.updateDevice(device.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDeviceButtons(device) {
|
||||||
|
var service = new DeviceService();
|
||||||
|
return this.renderButtons(
|
||||||
|
() => service.onlinedevice(device.id),
|
||||||
|
() => service.offlinedevice(device.id),
|
||||||
|
() => this.context.updateDevice(device.id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderButtons(onPower, onPowerOff, onRefresh) {
|
||||||
|
const renderOnOff = () => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<IconButton color="primary" onClick={onPower}>
|
||||||
|
<Power />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton color="primary" onClick={onPowerOff}>
|
||||||
|
<PowerOff />
|
||||||
|
</IconButton>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { classes } = this.props;
|
||||||
|
return (
|
||||||
|
<Box className={classes.icon_box}>
|
||||||
|
{this.props.isAdmin ? renderOnOff() : null}
|
||||||
|
<IconButton color="primary" onClick={onRefresh}>
|
||||||
|
<Refresh />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { classes } = this.props;
|
||||||
|
const Sensors = this.props.device.sensors.map((sensor, index) => (
|
||||||
|
<Grid item className={classes.grid_item} key={sensor.id}>
|
||||||
|
<Grid container
|
||||||
|
spacing={3}
|
||||||
|
direction="row"
|
||||||
|
justify="space-between"
|
||||||
|
alignItems="center">
|
||||||
|
<Grid item>
|
||||||
|
<Typography className={classes.grid_item_typo}>Sensor {index}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography className={classes.grid_item_typo_2}>{sensor.id}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography style={this.getColor(sensor.status)}>Status: <b>{sensor.status}</b></Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
{this.renderSensorButtons(this.props.device, sensor)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
));
|
||||||
|
|
||||||
|
const handleChange = (panel) => (event, isExpanded) => {
|
||||||
|
this.setState({ expanded: isExpanded ? panel : "" });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion expanded={this.state.expanded === this.props.device.id} onChange={handleChange(this.props.device.id)}>
|
||||||
|
<AccordionSummary className={classes.acc_summary}
|
||||||
|
expandIcon={<ExpandMoreIcon />}
|
||||||
|
aria-controls={"device-panel-/" + this.props.device.id}
|
||||||
|
id={"device-panel-/" + this.props.device.id}>
|
||||||
|
<Grid container
|
||||||
|
spacing={3}
|
||||||
|
direction="row"
|
||||||
|
justify="space-between"
|
||||||
|
alignItems="center">
|
||||||
|
<Grid item>
|
||||||
|
<Typography className={classes.grid_typo}>Device {this.props.index}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography className={classes.grid_typo_2}>{this.props.device.id}</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<Typography style={this.getColor(this.props.device.status)}>Status: <b>{this.props.device.status}</b></Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item>
|
||||||
|
<FormControlLabel
|
||||||
|
onClick={(event) => event.stopPropagation()}
|
||||||
|
onFocus={(event) => event.stopPropagation()}
|
||||||
|
control={this.renderDeviceButtons(this.props.device)}/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails className={classes.acc_details}>
|
||||||
|
<Grid className={classes.grid_item}
|
||||||
|
container
|
||||||
|
spacing={3}
|
||||||
|
direction="column"
|
||||||
|
justify="center"
|
||||||
|
alignItems="flex-start">
|
||||||
|
{Sensors}
|
||||||
|
</Grid>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(withStyles(styles)(DeviceComponent));
|
File diff suppressed because one or more lines are too long
90
Birdmap.API/ClientApp/src/components/devices/Devices.jsx
Normal file
90
Birdmap.API/ClientApp/src/components/devices/Devices.jsx
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import { Box, Paper, Typography, IconButton, Grid } from '@material-ui/core';
|
||||||
|
import { blue, blueGrey, green, orange, red, yellow } from '@material-ui/core/colors';
|
||||||
|
import { withStyles } from '@material-ui/styles';
|
||||||
|
import React from 'react';
|
||||||
|
import DeviceService from '../../common/DeviceService';
|
||||||
|
import DevicesContext from '../../contexts/DevicesContext';
|
||||||
|
import DeviceComponent from './DeviceComponent';
|
||||||
|
import { Power, PowerOff, Refresh } from '@material-ui/icons/';
|
||||||
|
|
||||||
|
const styles = theme => ({
|
||||||
|
root: {
|
||||||
|
padding: '64px',
|
||||||
|
backgroundColor: theme.palette.primary.dark,
|
||||||
|
},
|
||||||
|
paper: {
|
||||||
|
backgroundColor: blueGrey[50],
|
||||||
|
height: '60px',
|
||||||
|
margin: 'auto',
|
||||||
|
},
|
||||||
|
typo: {
|
||||||
|
fontSize: theme.typography.pxToRem(20),
|
||||||
|
fontWeight: theme.typography.fontWeightRegular,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
class Devices extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
static contextType = DevicesContext;
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
}
|
||||||
|
|
||||||
|
renderButtons() {
|
||||||
|
var service = new DeviceService();
|
||||||
|
|
||||||
|
const renderOnOff = () => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<IconButton color="primary" onClick={() => service.onlineall()}>
|
||||||
|
<Power />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton color="primary" onClick={() => service.offlineall()}>
|
||||||
|
<PowerOff />
|
||||||
|
</IconButton>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
{this.props.isAdmin ? renderOnOff() : null}
|
||||||
|
<IconButton color="primary" onClick={() => this.context.updateAllDevices()}>
|
||||||
|
<Refresh />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { classes } = this.props;
|
||||||
|
const Devices = this.context.devices.map((device, index) => (
|
||||||
|
<DeviceComponent isAdmin={this.props.isAdmin} device={device} index={index} key={device.id}/>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box className={classes.root}>
|
||||||
|
<Paper className={classes.paper} square>
|
||||||
|
<Grid container
|
||||||
|
spacing={3}
|
||||||
|
direction="row"
|
||||||
|
justify="center"
|
||||||
|
alignItems="center">
|
||||||
|
<Grid item>
|
||||||
|
<Typography className={classes.typo}>All Devices</Typography>
|
||||||
|
</Grid>
|
||||||
|
{this.renderButtons()}
|
||||||
|
<Grid item>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
|
{Devices}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withStyles(styles)(Devices);
|
@ -0,0 +1,63 @@
|
|||||||
|
import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked';
|
||||||
|
import PlayCircleFilledIcon from '@material-ui/icons/PlayCircleFilled';
|
||||||
|
import { shadows } from '@material-ui/system';
|
||||||
|
import { Box, Popover, Typography, Tooltip, Grid } from '@material-ui/core';
|
||||||
|
import { blue, red, yellow } from '@material-ui/core/colors';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { useHistory, withRouter } from 'react-router-dom';
|
||||||
|
import { makeStyles } from '@material-ui/styles';
|
||||||
|
|
||||||
|
class DeviceMarker extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
AnchorEl: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getColor() {
|
||||||
|
const { device } = this.props;
|
||||||
|
if (device.status == "Online") {
|
||||||
|
return { color: blue[800] };
|
||||||
|
} else if (device.status == "Offline") {
|
||||||
|
return { color: yellow[800] };
|
||||||
|
} else /* if (device.status == "unknown") */ {
|
||||||
|
return { color: red[800] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useStyles() {
|
||||||
|
return makeStyles(theme => ({
|
||||||
|
root: {
|
||||||
|
display: 'grid'
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const classes = this.useStyles(this.props);
|
||||||
|
const { device } = this.props;
|
||||||
|
|
||||||
|
const onClick = () => {
|
||||||
|
this.props.history.push('/devices/' + device.id)
|
||||||
|
};
|
||||||
|
|
||||||
|
const open = Boolean(this.state.AnchorEl);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box className={classes.root} boxShadow={5}>
|
||||||
|
<Tooltip title={<div>ID: {device.id}<br />Status: {device.status}</div>} placement="top" leaveDelay={200} arrow>
|
||||||
|
<RadioButtonCheckedIcon fontSize="small" style={this.getColor()}
|
||||||
|
onClick={onClick}>
|
||||||
|
</RadioButtonCheckedIcon>
|
||||||
|
</Tooltip>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(DeviceMarker);
|
105
Birdmap.API/ClientApp/src/components/heatmap/Heatmap.jsx
Normal file
105
Birdmap.API/ClientApp/src/components/heatmap/Heatmap.jsx
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*global google*/
|
||||||
|
import GoogleMapReact from 'google-map-react';
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import DeviceMarker from './DeviceMarker'
|
||||||
|
import C from '../../common/Constants'
|
||||||
|
import DevicesContext from '../../contexts/DevicesContext';
|
||||||
|
|
||||||
|
const lat_offset = 0.000038;
|
||||||
|
const lng_offset = -0.000058;
|
||||||
|
|
||||||
|
export default class MapContainer extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
center: {
|
||||||
|
lat: 48.275939, lng: 21.469640
|
||||||
|
},
|
||||||
|
heatmapPoints: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
this.probabilityHandler = this.probabilityHandler.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static contextType = DevicesContext;
|
||||||
|
|
||||||
|
probabilityHandler(point) {
|
||||||
|
if (point.prob > 0.5) {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
heatmapPoints: [...this.state.heatmapPoints, point]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this._googleMap !== undefined) {
|
||||||
|
const newPoint = { location: new google.maps.LatLng(point.lat, point.lng), weight: point.prob };
|
||||||
|
if (this._googleMap.heatmap !== null) {
|
||||||
|
this._googleMap.heatmap.data.push(newPoint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.context.addHandler(C.probability_method_name, this.probabilityHandler);
|
||||||
|
const newPoints = [];
|
||||||
|
for (var p of this.context.heatmapPoints) {
|
||||||
|
if (p.prob > 0.5) {
|
||||||
|
newPoints.push(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ heatmapPoints: newPoints });
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.context.removeHandler(C.probability_method_name, this.probabilityHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const heatMapData = {
|
||||||
|
positions: this.state.heatmapPoints,
|
||||||
|
options: {
|
||||||
|
radius: 50,
|
||||||
|
opacity: 0.6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapOptions = {
|
||||||
|
disableDefaultUI: true,
|
||||||
|
zoomControl: true,
|
||||||
|
mapTypeControl: true,
|
||||||
|
overviewMapControl: true,
|
||||||
|
streetViewControl: false,
|
||||||
|
scaleControl: true,
|
||||||
|
mapTypeId: 'satellite'
|
||||||
|
}
|
||||||
|
|
||||||
|
const Markers = this.context.devices.map((device, index) => (
|
||||||
|
<DeviceMarker
|
||||||
|
key={device.id}
|
||||||
|
lat={device.coordinates.latitude + lat_offset}
|
||||||
|
lng={device.coordinates.longitude + lng_offset}
|
||||||
|
device={device}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ height: '93vh', width: '100%' }}>
|
||||||
|
<GoogleMapReact
|
||||||
|
bootstrapURLKeys={{
|
||||||
|
key: ["AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY"],
|
||||||
|
libraries: ['visualization']
|
||||||
|
}}
|
||||||
|
ref={(el) => this._googleMap = el}
|
||||||
|
options={mapOptions}
|
||||||
|
defaultZoom={18}
|
||||||
|
heatmapLibrary={true}
|
||||||
|
heatmap={heatMapData}
|
||||||
|
defaultCenter={this.state.center}>
|
||||||
|
{Markers}
|
||||||
|
</GoogleMapReact>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,555 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
|
||||||
exports.initMap = void 0;
|
|
||||||
var google_maps_1 = require("google-maps");
|
|
||||||
var map, heatmap;
|
|
||||||
function initMap() {
|
|
||||||
var options = { /* todo */};
|
|
||||||
var loader = new google_maps_1.Loader('AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY', options);
|
|
||||||
loader.load().then(function (google) {
|
|
||||||
map = new google.maps.Map(document.getElementById("map"), {
|
|
||||||
zoom: 13,
|
|
||||||
center: { lat: 37.775, lng: -122.434 },
|
|
||||||
mapTypeId: "satellite",
|
|
||||||
});
|
|
||||||
heatmap = new google.maps.visualization.HeatmapLayer({
|
|
||||||
data: getPoints(),
|
|
||||||
map: map,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
exports.initMap = initMap;
|
|
||||||
function toggleHeatmap() {
|
|
||||||
heatmap.setMap(heatmap.getMap() ? null : map);
|
|
||||||
}
|
|
||||||
function changeGradient() {
|
|
||||||
var gradient = [
|
|
||||||
"rgba(0, 255, 255, 0)",
|
|
||||||
"rgba(0, 255, 255, 1)",
|
|
||||||
"rgba(0, 191, 255, 1)",
|
|
||||||
"rgba(0, 127, 255, 1)",
|
|
||||||
"rgba(0, 63, 255, 1)",
|
|
||||||
"rgba(0, 0, 255, 1)",
|
|
||||||
"rgba(0, 0, 223, 1)",
|
|
||||||
"rgba(0, 0, 191, 1)",
|
|
||||||
"rgba(0, 0, 159, 1)",
|
|
||||||
"rgba(0, 0, 127, 1)",
|
|
||||||
"rgba(63, 0, 91, 1)",
|
|
||||||
"rgba(127, 0, 63, 1)",
|
|
||||||
"rgba(191, 0, 31, 1)",
|
|
||||||
"rgba(255, 0, 0, 1)",
|
|
||||||
];
|
|
||||||
heatmap.set("gradient", heatmap.get("gradient") ? null : gradient);
|
|
||||||
}
|
|
||||||
function changeRadius() {
|
|
||||||
heatmap.set("radius", heatmap.get("radius") ? null : 20);
|
|
||||||
}
|
|
||||||
function changeOpacity() {
|
|
||||||
heatmap.set("opacity", heatmap.get("opacity") ? null : 0.2);
|
|
||||||
}
|
|
||||||
// Heatmap data: 500 Points
|
|
||||||
function getPoints() {
|
|
||||||
return [
|
|
||||||
new google.maps.LatLng(37.782551, -122.445368),
|
|
||||||
new google.maps.LatLng(37.782745, -122.444586),
|
|
||||||
new google.maps.LatLng(37.782842, -122.443688),
|
|
||||||
new google.maps.LatLng(37.782919, -122.442815),
|
|
||||||
new google.maps.LatLng(37.782992, -122.442112),
|
|
||||||
new google.maps.LatLng(37.7831, -122.441461),
|
|
||||||
new google.maps.LatLng(37.783206, -122.440829),
|
|
||||||
new google.maps.LatLng(37.783273, -122.440324),
|
|
||||||
new google.maps.LatLng(37.783316, -122.440023),
|
|
||||||
new google.maps.LatLng(37.783357, -122.439794),
|
|
||||||
new google.maps.LatLng(37.783371, -122.439687),
|
|
||||||
new google.maps.LatLng(37.783368, -122.439666),
|
|
||||||
new google.maps.LatLng(37.783383, -122.439594),
|
|
||||||
new google.maps.LatLng(37.783508, -122.439525),
|
|
||||||
new google.maps.LatLng(37.783842, -122.439591),
|
|
||||||
new google.maps.LatLng(37.784147, -122.439668),
|
|
||||||
new google.maps.LatLng(37.784206, -122.439686),
|
|
||||||
new google.maps.LatLng(37.784386, -122.43979),
|
|
||||||
new google.maps.LatLng(37.784701, -122.439902),
|
|
||||||
new google.maps.LatLng(37.784965, -122.439938),
|
|
||||||
new google.maps.LatLng(37.78501, -122.439947),
|
|
||||||
new google.maps.LatLng(37.78536, -122.439952),
|
|
||||||
new google.maps.LatLng(37.785715, -122.44003),
|
|
||||||
new google.maps.LatLng(37.786117, -122.440119),
|
|
||||||
new google.maps.LatLng(37.786564, -122.440209),
|
|
||||||
new google.maps.LatLng(37.786905, -122.44027),
|
|
||||||
new google.maps.LatLng(37.786956, -122.440279),
|
|
||||||
new google.maps.LatLng(37.800224, -122.43352),
|
|
||||||
new google.maps.LatLng(37.800155, -122.434101),
|
|
||||||
new google.maps.LatLng(37.80016, -122.43443),
|
|
||||||
new google.maps.LatLng(37.800378, -122.434527),
|
|
||||||
new google.maps.LatLng(37.800738, -122.434598),
|
|
||||||
new google.maps.LatLng(37.800938, -122.43465),
|
|
||||||
new google.maps.LatLng(37.801024, -122.434889),
|
|
||||||
new google.maps.LatLng(37.800955, -122.435392),
|
|
||||||
new google.maps.LatLng(37.800886, -122.435959),
|
|
||||||
new google.maps.LatLng(37.800811, -122.436275),
|
|
||||||
new google.maps.LatLng(37.800788, -122.436299),
|
|
||||||
new google.maps.LatLng(37.800719, -122.436302),
|
|
||||||
new google.maps.LatLng(37.800702, -122.436298),
|
|
||||||
new google.maps.LatLng(37.800661, -122.436273),
|
|
||||||
new google.maps.LatLng(37.800395, -122.436172),
|
|
||||||
new google.maps.LatLng(37.800228, -122.436116),
|
|
||||||
new google.maps.LatLng(37.800169, -122.43613),
|
|
||||||
new google.maps.LatLng(37.800066, -122.436167),
|
|
||||||
new google.maps.LatLng(37.784345, -122.422922),
|
|
||||||
new google.maps.LatLng(37.784389, -122.422926),
|
|
||||||
new google.maps.LatLng(37.784437, -122.422924),
|
|
||||||
new google.maps.LatLng(37.784746, -122.422818),
|
|
||||||
new google.maps.LatLng(37.785436, -122.422959),
|
|
||||||
new google.maps.LatLng(37.78612, -122.423112),
|
|
||||||
new google.maps.LatLng(37.786433, -122.423029),
|
|
||||||
new google.maps.LatLng(37.786631, -122.421213),
|
|
||||||
new google.maps.LatLng(37.78666, -122.421033),
|
|
||||||
new google.maps.LatLng(37.786801, -122.420141),
|
|
||||||
new google.maps.LatLng(37.786823, -122.420034),
|
|
||||||
new google.maps.LatLng(37.786831, -122.419916),
|
|
||||||
new google.maps.LatLng(37.787034, -122.418208),
|
|
||||||
new google.maps.LatLng(37.787056, -122.418034),
|
|
||||||
new google.maps.LatLng(37.787169, -122.417145),
|
|
||||||
new google.maps.LatLng(37.787217, -122.416715),
|
|
||||||
new google.maps.LatLng(37.786144, -122.416403),
|
|
||||||
new google.maps.LatLng(37.785292, -122.416257),
|
|
||||||
new google.maps.LatLng(37.780666, -122.390374),
|
|
||||||
new google.maps.LatLng(37.780501, -122.391281),
|
|
||||||
new google.maps.LatLng(37.780148, -122.392052),
|
|
||||||
new google.maps.LatLng(37.780173, -122.391148),
|
|
||||||
new google.maps.LatLng(37.780693, -122.390592),
|
|
||||||
new google.maps.LatLng(37.781261, -122.391142),
|
|
||||||
new google.maps.LatLng(37.781808, -122.39173),
|
|
||||||
new google.maps.LatLng(37.78234, -122.392341),
|
|
||||||
new google.maps.LatLng(37.782812, -122.393022),
|
|
||||||
new google.maps.LatLng(37.7833, -122.393672),
|
|
||||||
new google.maps.LatLng(37.783809, -122.394275),
|
|
||||||
new google.maps.LatLng(37.784246, -122.394979),
|
|
||||||
new google.maps.LatLng(37.784791, -122.395958),
|
|
||||||
new google.maps.LatLng(37.785675, -122.396746),
|
|
||||||
new google.maps.LatLng(37.786262, -122.39578),
|
|
||||||
new google.maps.LatLng(37.786776, -122.395093),
|
|
||||||
new google.maps.LatLng(37.787282, -122.394426),
|
|
||||||
new google.maps.LatLng(37.787783, -122.393767),
|
|
||||||
new google.maps.LatLng(37.788343, -122.393184),
|
|
||||||
new google.maps.LatLng(37.788895, -122.392506),
|
|
||||||
new google.maps.LatLng(37.789371, -122.391701),
|
|
||||||
new google.maps.LatLng(37.789722, -122.390952),
|
|
||||||
new google.maps.LatLng(37.790315, -122.390305),
|
|
||||||
new google.maps.LatLng(37.790738, -122.389616),
|
|
||||||
new google.maps.LatLng(37.779448, -122.438702),
|
|
||||||
new google.maps.LatLng(37.779023, -122.438585),
|
|
||||||
new google.maps.LatLng(37.778542, -122.438492),
|
|
||||||
new google.maps.LatLng(37.7781, -122.438411),
|
|
||||||
new google.maps.LatLng(37.777986, -122.438376),
|
|
||||||
new google.maps.LatLng(37.77768, -122.438313),
|
|
||||||
new google.maps.LatLng(37.777316, -122.438273),
|
|
||||||
new google.maps.LatLng(37.777135, -122.438254),
|
|
||||||
new google.maps.LatLng(37.776987, -122.438303),
|
|
||||||
new google.maps.LatLng(37.776946, -122.438404),
|
|
||||||
new google.maps.LatLng(37.776944, -122.438467),
|
|
||||||
new google.maps.LatLng(37.776892, -122.438459),
|
|
||||||
new google.maps.LatLng(37.776842, -122.438442),
|
|
||||||
new google.maps.LatLng(37.776822, -122.438391),
|
|
||||||
new google.maps.LatLng(37.776814, -122.438412),
|
|
||||||
new google.maps.LatLng(37.776787, -122.438628),
|
|
||||||
new google.maps.LatLng(37.776729, -122.43865),
|
|
||||||
new google.maps.LatLng(37.776759, -122.438677),
|
|
||||||
new google.maps.LatLng(37.776772, -122.438498),
|
|
||||||
new google.maps.LatLng(37.776787, -122.438389),
|
|
||||||
new google.maps.LatLng(37.776848, -122.438283),
|
|
||||||
new google.maps.LatLng(37.77687, -122.438239),
|
|
||||||
new google.maps.LatLng(37.777015, -122.438198),
|
|
||||||
new google.maps.LatLng(37.777333, -122.438256),
|
|
||||||
new google.maps.LatLng(37.777595, -122.438308),
|
|
||||||
new google.maps.LatLng(37.777797, -122.438344),
|
|
||||||
new google.maps.LatLng(37.77816, -122.438442),
|
|
||||||
new google.maps.LatLng(37.778414, -122.438508),
|
|
||||||
new google.maps.LatLng(37.778445, -122.438516),
|
|
||||||
new google.maps.LatLng(37.778503, -122.438529),
|
|
||||||
new google.maps.LatLng(37.778607, -122.438549),
|
|
||||||
new google.maps.LatLng(37.77867, -122.438644),
|
|
||||||
new google.maps.LatLng(37.778847, -122.438706),
|
|
||||||
new google.maps.LatLng(37.77924, -122.438744),
|
|
||||||
new google.maps.LatLng(37.779738, -122.438822),
|
|
||||||
new google.maps.LatLng(37.780201, -122.438882),
|
|
||||||
new google.maps.LatLng(37.7804, -122.438905),
|
|
||||||
new google.maps.LatLng(37.780501, -122.438921),
|
|
||||||
new google.maps.LatLng(37.780892, -122.438986),
|
|
||||||
new google.maps.LatLng(37.781446, -122.439087),
|
|
||||||
new google.maps.LatLng(37.781985, -122.439199),
|
|
||||||
new google.maps.LatLng(37.782239, -122.439249),
|
|
||||||
new google.maps.LatLng(37.782286, -122.439266),
|
|
||||||
new google.maps.LatLng(37.797847, -122.429388),
|
|
||||||
new google.maps.LatLng(37.797874, -122.42918),
|
|
||||||
new google.maps.LatLng(37.797885, -122.429069),
|
|
||||||
new google.maps.LatLng(37.797887, -122.42905),
|
|
||||||
new google.maps.LatLng(37.797933, -122.428954),
|
|
||||||
new google.maps.LatLng(37.798242, -122.42899),
|
|
||||||
new google.maps.LatLng(37.798617, -122.429075),
|
|
||||||
new google.maps.LatLng(37.798719, -122.429092),
|
|
||||||
new google.maps.LatLng(37.798944, -122.429145),
|
|
||||||
new google.maps.LatLng(37.79932, -122.429251),
|
|
||||||
new google.maps.LatLng(37.79959, -122.429309),
|
|
||||||
new google.maps.LatLng(37.799677, -122.429324),
|
|
||||||
new google.maps.LatLng(37.799966, -122.42936),
|
|
||||||
new google.maps.LatLng(37.800288, -122.42943),
|
|
||||||
new google.maps.LatLng(37.800443, -122.429461),
|
|
||||||
new google.maps.LatLng(37.800465, -122.429474),
|
|
||||||
new google.maps.LatLng(37.800644, -122.42954),
|
|
||||||
new google.maps.LatLng(37.800948, -122.42962),
|
|
||||||
new google.maps.LatLng(37.801242, -122.429685),
|
|
||||||
new google.maps.LatLng(37.801375, -122.429702),
|
|
||||||
new google.maps.LatLng(37.8014, -122.429703),
|
|
||||||
new google.maps.LatLng(37.801453, -122.429707),
|
|
||||||
new google.maps.LatLng(37.801473, -122.429709),
|
|
||||||
new google.maps.LatLng(37.801532, -122.429707),
|
|
||||||
new google.maps.LatLng(37.801852, -122.429729),
|
|
||||||
new google.maps.LatLng(37.802173, -122.429789),
|
|
||||||
new google.maps.LatLng(37.802459, -122.429847),
|
|
||||||
new google.maps.LatLng(37.802554, -122.429825),
|
|
||||||
new google.maps.LatLng(37.802647, -122.429549),
|
|
||||||
new google.maps.LatLng(37.802693, -122.429179),
|
|
||||||
new google.maps.LatLng(37.802729, -122.428751),
|
|
||||||
new google.maps.LatLng(37.766104, -122.409291),
|
|
||||||
new google.maps.LatLng(37.766103, -122.409268),
|
|
||||||
new google.maps.LatLng(37.766138, -122.409229),
|
|
||||||
new google.maps.LatLng(37.766183, -122.409231),
|
|
||||||
new google.maps.LatLng(37.766153, -122.409276),
|
|
||||||
new google.maps.LatLng(37.766005, -122.409365),
|
|
||||||
new google.maps.LatLng(37.765897, -122.40957),
|
|
||||||
new google.maps.LatLng(37.765767, -122.409739),
|
|
||||||
new google.maps.LatLng(37.765693, -122.410389),
|
|
||||||
new google.maps.LatLng(37.765615, -122.411201),
|
|
||||||
new google.maps.LatLng(37.765533, -122.412121),
|
|
||||||
new google.maps.LatLng(37.765467, -122.412939),
|
|
||||||
new google.maps.LatLng(37.765444, -122.414821),
|
|
||||||
new google.maps.LatLng(37.765444, -122.414964),
|
|
||||||
new google.maps.LatLng(37.765318, -122.415424),
|
|
||||||
new google.maps.LatLng(37.763961, -122.415296),
|
|
||||||
new google.maps.LatLng(37.763115, -122.415196),
|
|
||||||
new google.maps.LatLng(37.762967, -122.415183),
|
|
||||||
new google.maps.LatLng(37.762278, -122.415127),
|
|
||||||
new google.maps.LatLng(37.761675, -122.415055),
|
|
||||||
new google.maps.LatLng(37.760932, -122.414988),
|
|
||||||
new google.maps.LatLng(37.759337, -122.414862),
|
|
||||||
new google.maps.LatLng(37.773187, -122.421922),
|
|
||||||
new google.maps.LatLng(37.773043, -122.422118),
|
|
||||||
new google.maps.LatLng(37.773007, -122.422165),
|
|
||||||
new google.maps.LatLng(37.772979, -122.422219),
|
|
||||||
new google.maps.LatLng(37.772865, -122.422394),
|
|
||||||
new google.maps.LatLng(37.772779, -122.422503),
|
|
||||||
new google.maps.LatLng(37.772676, -122.422701),
|
|
||||||
new google.maps.LatLng(37.772606, -122.422806),
|
|
||||||
new google.maps.LatLng(37.772566, -122.42284),
|
|
||||||
new google.maps.LatLng(37.772508, -122.422852),
|
|
||||||
new google.maps.LatLng(37.772387, -122.423011),
|
|
||||||
new google.maps.LatLng(37.772099, -122.423328),
|
|
||||||
new google.maps.LatLng(37.771704, -122.423783),
|
|
||||||
new google.maps.LatLng(37.771481, -122.424081),
|
|
||||||
new google.maps.LatLng(37.7714, -122.424179),
|
|
||||||
new google.maps.LatLng(37.771352, -122.42422),
|
|
||||||
new google.maps.LatLng(37.771248, -122.424327),
|
|
||||||
new google.maps.LatLng(37.770904, -122.424781),
|
|
||||||
new google.maps.LatLng(37.77052, -122.425283),
|
|
||||||
new google.maps.LatLng(37.770337, -122.425553),
|
|
||||||
new google.maps.LatLng(37.770128, -122.425832),
|
|
||||||
new google.maps.LatLng(37.769756, -122.426331),
|
|
||||||
new google.maps.LatLng(37.7693, -122.426902),
|
|
||||||
new google.maps.LatLng(37.769132, -122.427065),
|
|
||||||
new google.maps.LatLng(37.769092, -122.427103),
|
|
||||||
new google.maps.LatLng(37.768979, -122.427172),
|
|
||||||
new google.maps.LatLng(37.768595, -122.427634),
|
|
||||||
new google.maps.LatLng(37.768372, -122.427913),
|
|
||||||
new google.maps.LatLng(37.768337, -122.427961),
|
|
||||||
new google.maps.LatLng(37.768244, -122.428138),
|
|
||||||
new google.maps.LatLng(37.767942, -122.428581),
|
|
||||||
new google.maps.LatLng(37.767482, -122.429094),
|
|
||||||
new google.maps.LatLng(37.767031, -122.429606),
|
|
||||||
new google.maps.LatLng(37.766732, -122.429986),
|
|
||||||
new google.maps.LatLng(37.76668, -122.430058),
|
|
||||||
new google.maps.LatLng(37.766633, -122.430109),
|
|
||||||
new google.maps.LatLng(37.76658, -122.430211),
|
|
||||||
new google.maps.LatLng(37.766367, -122.430594),
|
|
||||||
new google.maps.LatLng(37.76591, -122.431137),
|
|
||||||
new google.maps.LatLng(37.765353, -122.431806),
|
|
||||||
new google.maps.LatLng(37.764962, -122.432298),
|
|
||||||
new google.maps.LatLng(37.764868, -122.432486),
|
|
||||||
new google.maps.LatLng(37.764518, -122.432913),
|
|
||||||
new google.maps.LatLng(37.763435, -122.434173),
|
|
||||||
new google.maps.LatLng(37.762847, -122.434953),
|
|
||||||
new google.maps.LatLng(37.762291, -122.435935),
|
|
||||||
new google.maps.LatLng(37.762224, -122.436074),
|
|
||||||
new google.maps.LatLng(37.761957, -122.436892),
|
|
||||||
new google.maps.LatLng(37.761652, -122.438886),
|
|
||||||
new google.maps.LatLng(37.761284, -122.439955),
|
|
||||||
new google.maps.LatLng(37.76121, -122.440068),
|
|
||||||
new google.maps.LatLng(37.761064, -122.44072),
|
|
||||||
new google.maps.LatLng(37.76104, -122.441411),
|
|
||||||
new google.maps.LatLng(37.761048, -122.442324),
|
|
||||||
new google.maps.LatLng(37.760851, -122.443118),
|
|
||||||
new google.maps.LatLng(37.759977, -122.444591),
|
|
||||||
new google.maps.LatLng(37.759913, -122.444698),
|
|
||||||
new google.maps.LatLng(37.759623, -122.445065),
|
|
||||||
new google.maps.LatLng(37.758902, -122.445158),
|
|
||||||
new google.maps.LatLng(37.758428, -122.44457),
|
|
||||||
new google.maps.LatLng(37.757687, -122.44334),
|
|
||||||
new google.maps.LatLng(37.757583, -122.44324),
|
|
||||||
new google.maps.LatLng(37.757019, -122.442787),
|
|
||||||
new google.maps.LatLng(37.756603, -122.442322),
|
|
||||||
new google.maps.LatLng(37.75638, -122.441602),
|
|
||||||
new google.maps.LatLng(37.75579, -122.441382),
|
|
||||||
new google.maps.LatLng(37.754493, -122.442133),
|
|
||||||
new google.maps.LatLng(37.754361, -122.442206),
|
|
||||||
new google.maps.LatLng(37.753719, -122.44265),
|
|
||||||
new google.maps.LatLng(37.753096, -122.442915),
|
|
||||||
new google.maps.LatLng(37.751617, -122.443211),
|
|
||||||
new google.maps.LatLng(37.751496, -122.443246),
|
|
||||||
new google.maps.LatLng(37.750733, -122.443428),
|
|
||||||
new google.maps.LatLng(37.750126, -122.443536),
|
|
||||||
new google.maps.LatLng(37.750103, -122.443784),
|
|
||||||
new google.maps.LatLng(37.75039, -122.44401),
|
|
||||||
new google.maps.LatLng(37.750448, -122.444013),
|
|
||||||
new google.maps.LatLng(37.750536, -122.44404),
|
|
||||||
new google.maps.LatLng(37.750493, -122.444141),
|
|
||||||
new google.maps.LatLng(37.790859, -122.402808),
|
|
||||||
new google.maps.LatLng(37.790864, -122.402768),
|
|
||||||
new google.maps.LatLng(37.790995, -122.402539),
|
|
||||||
new google.maps.LatLng(37.791148, -122.402172),
|
|
||||||
new google.maps.LatLng(37.791385, -122.401312),
|
|
||||||
new google.maps.LatLng(37.791405, -122.400776),
|
|
||||||
new google.maps.LatLng(37.791288, -122.400528),
|
|
||||||
new google.maps.LatLng(37.791113, -122.400441),
|
|
||||||
new google.maps.LatLng(37.791027, -122.400395),
|
|
||||||
new google.maps.LatLng(37.791094, -122.400311),
|
|
||||||
new google.maps.LatLng(37.791211, -122.400183),
|
|
||||||
new google.maps.LatLng(37.79106, -122.399334),
|
|
||||||
new google.maps.LatLng(37.790538, -122.398718),
|
|
||||||
new google.maps.LatLng(37.790095, -122.398086),
|
|
||||||
new google.maps.LatLng(37.789644, -122.39736),
|
|
||||||
new google.maps.LatLng(37.789254, -122.396844),
|
|
||||||
new google.maps.LatLng(37.788855, -122.396397),
|
|
||||||
new google.maps.LatLng(37.788483, -122.395963),
|
|
||||||
new google.maps.LatLng(37.788015, -122.395365),
|
|
||||||
new google.maps.LatLng(37.787558, -122.394735),
|
|
||||||
new google.maps.LatLng(37.787472, -122.394323),
|
|
||||||
new google.maps.LatLng(37.78763, -122.394025),
|
|
||||||
new google.maps.LatLng(37.787767, -122.393987),
|
|
||||||
new google.maps.LatLng(37.787486, -122.394452),
|
|
||||||
new google.maps.LatLng(37.786977, -122.395043),
|
|
||||||
new google.maps.LatLng(37.786583, -122.395552),
|
|
||||||
new google.maps.LatLng(37.78654, -122.39561),
|
|
||||||
new google.maps.LatLng(37.786516, -122.395659),
|
|
||||||
new google.maps.LatLng(37.786378, -122.395707),
|
|
||||||
new google.maps.LatLng(37.786044, -122.395362),
|
|
||||||
new google.maps.LatLng(37.785598, -122.394715),
|
|
||||||
new google.maps.LatLng(37.785321, -122.394361),
|
|
||||||
new google.maps.LatLng(37.785207, -122.394236),
|
|
||||||
new google.maps.LatLng(37.785751, -122.394062),
|
|
||||||
new google.maps.LatLng(37.785996, -122.393881),
|
|
||||||
new google.maps.LatLng(37.786092, -122.39383),
|
|
||||||
new google.maps.LatLng(37.785998, -122.393899),
|
|
||||||
new google.maps.LatLng(37.785114, -122.394365),
|
|
||||||
new google.maps.LatLng(37.785022, -122.394441),
|
|
||||||
new google.maps.LatLng(37.784823, -122.394635),
|
|
||||||
new google.maps.LatLng(37.784719, -122.394629),
|
|
||||||
new google.maps.LatLng(37.785069, -122.394176),
|
|
||||||
new google.maps.LatLng(37.7855, -122.39365),
|
|
||||||
new google.maps.LatLng(37.78577, -122.393291),
|
|
||||||
new google.maps.LatLng(37.785839, -122.393159),
|
|
||||||
new google.maps.LatLng(37.782651, -122.400628),
|
|
||||||
new google.maps.LatLng(37.782616, -122.400599),
|
|
||||||
new google.maps.LatLng(37.782702, -122.40047),
|
|
||||||
new google.maps.LatLng(37.782915, -122.400192),
|
|
||||||
new google.maps.LatLng(37.783137, -122.399887),
|
|
||||||
new google.maps.LatLng(37.783414, -122.399519),
|
|
||||||
new google.maps.LatLng(37.783629, -122.399237),
|
|
||||||
new google.maps.LatLng(37.783688, -122.399157),
|
|
||||||
new google.maps.LatLng(37.783716, -122.399106),
|
|
||||||
new google.maps.LatLng(37.783798, -122.399072),
|
|
||||||
new google.maps.LatLng(37.783997, -122.399186),
|
|
||||||
new google.maps.LatLng(37.784271, -122.399538),
|
|
||||||
new google.maps.LatLng(37.784577, -122.399948),
|
|
||||||
new google.maps.LatLng(37.784828, -122.40026),
|
|
||||||
new google.maps.LatLng(37.784999, -122.400477),
|
|
||||||
new google.maps.LatLng(37.785113, -122.400651),
|
|
||||||
new google.maps.LatLng(37.785155, -122.400703),
|
|
||||||
new google.maps.LatLng(37.785192, -122.400749),
|
|
||||||
new google.maps.LatLng(37.785278, -122.400839),
|
|
||||||
new google.maps.LatLng(37.785387, -122.400857),
|
|
||||||
new google.maps.LatLng(37.785478, -122.40089),
|
|
||||||
new google.maps.LatLng(37.785526, -122.401022),
|
|
||||||
new google.maps.LatLng(37.785598, -122.401148),
|
|
||||||
new google.maps.LatLng(37.785631, -122.401202),
|
|
||||||
new google.maps.LatLng(37.78566, -122.401267),
|
|
||||||
new google.maps.LatLng(37.803986, -122.426035),
|
|
||||||
new google.maps.LatLng(37.804102, -122.425089),
|
|
||||||
new google.maps.LatLng(37.804211, -122.424156),
|
|
||||||
new google.maps.LatLng(37.803861, -122.423385),
|
|
||||||
new google.maps.LatLng(37.803151, -122.423214),
|
|
||||||
new google.maps.LatLng(37.802439, -122.423077),
|
|
||||||
new google.maps.LatLng(37.80174, -122.422905),
|
|
||||||
new google.maps.LatLng(37.801069, -122.422785),
|
|
||||||
new google.maps.LatLng(37.800345, -122.422649),
|
|
||||||
new google.maps.LatLng(37.799633, -122.422603),
|
|
||||||
new google.maps.LatLng(37.79975, -122.4217),
|
|
||||||
new google.maps.LatLng(37.799885, -122.420854),
|
|
||||||
new google.maps.LatLng(37.799209, -122.420607),
|
|
||||||
new google.maps.LatLng(37.795656, -122.400395),
|
|
||||||
new google.maps.LatLng(37.795203, -122.400304),
|
|
||||||
new google.maps.LatLng(37.778738, -122.415584),
|
|
||||||
new google.maps.LatLng(37.778812, -122.415189),
|
|
||||||
new google.maps.LatLng(37.778824, -122.415092),
|
|
||||||
new google.maps.LatLng(37.778833, -122.414932),
|
|
||||||
new google.maps.LatLng(37.778834, -122.414898),
|
|
||||||
new google.maps.LatLng(37.77874, -122.414757),
|
|
||||||
new google.maps.LatLng(37.778501, -122.414433),
|
|
||||||
new google.maps.LatLng(37.778182, -122.414026),
|
|
||||||
new google.maps.LatLng(37.777851, -122.413623),
|
|
||||||
new google.maps.LatLng(37.777486, -122.413166),
|
|
||||||
new google.maps.LatLng(37.777109, -122.412674),
|
|
||||||
new google.maps.LatLng(37.776743, -122.412186),
|
|
||||||
new google.maps.LatLng(37.77644, -122.4118),
|
|
||||||
new google.maps.LatLng(37.776295, -122.411614),
|
|
||||||
new google.maps.LatLng(37.776158, -122.41144),
|
|
||||||
new google.maps.LatLng(37.775806, -122.410997),
|
|
||||||
new google.maps.LatLng(37.775422, -122.410484),
|
|
||||||
new google.maps.LatLng(37.775126, -122.410087),
|
|
||||||
new google.maps.LatLng(37.775012, -122.409854),
|
|
||||||
new google.maps.LatLng(37.775164, -122.409573),
|
|
||||||
new google.maps.LatLng(37.775498, -122.40918),
|
|
||||||
new google.maps.LatLng(37.775868, -122.40873),
|
|
||||||
new google.maps.LatLng(37.776256, -122.40824),
|
|
||||||
new google.maps.LatLng(37.776519, -122.407928),
|
|
||||||
new google.maps.LatLng(37.776539, -122.407904),
|
|
||||||
new google.maps.LatLng(37.776595, -122.407854),
|
|
||||||
new google.maps.LatLng(37.776853, -122.407547),
|
|
||||||
new google.maps.LatLng(37.777234, -122.407087),
|
|
||||||
new google.maps.LatLng(37.777644, -122.406558),
|
|
||||||
new google.maps.LatLng(37.778066, -122.406017),
|
|
||||||
new google.maps.LatLng(37.778468, -122.405499),
|
|
||||||
new google.maps.LatLng(37.778866, -122.404995),
|
|
||||||
new google.maps.LatLng(37.779295, -122.404455),
|
|
||||||
new google.maps.LatLng(37.779695, -122.40395),
|
|
||||||
new google.maps.LatLng(37.779982, -122.403584),
|
|
||||||
new google.maps.LatLng(37.780295, -122.403223),
|
|
||||||
new google.maps.LatLng(37.780664, -122.402766),
|
|
||||||
new google.maps.LatLng(37.781043, -122.402288),
|
|
||||||
new google.maps.LatLng(37.781399, -122.401823),
|
|
||||||
new google.maps.LatLng(37.781727, -122.401407),
|
|
||||||
new google.maps.LatLng(37.781853, -122.401247),
|
|
||||||
new google.maps.LatLng(37.781894, -122.401195),
|
|
||||||
new google.maps.LatLng(37.782076, -122.400977),
|
|
||||||
new google.maps.LatLng(37.782338, -122.400603),
|
|
||||||
new google.maps.LatLng(37.782666, -122.400133),
|
|
||||||
new google.maps.LatLng(37.783048, -122.399634),
|
|
||||||
new google.maps.LatLng(37.78345, -122.399198),
|
|
||||||
new google.maps.LatLng(37.783791, -122.398998),
|
|
||||||
new google.maps.LatLng(37.784177, -122.398959),
|
|
||||||
new google.maps.LatLng(37.784388, -122.398971),
|
|
||||||
new google.maps.LatLng(37.784404, -122.399128),
|
|
||||||
new google.maps.LatLng(37.784586, -122.399524),
|
|
||||||
new google.maps.LatLng(37.784835, -122.399927),
|
|
||||||
new google.maps.LatLng(37.785116, -122.400307),
|
|
||||||
new google.maps.LatLng(37.785282, -122.400539),
|
|
||||||
new google.maps.LatLng(37.785346, -122.400692),
|
|
||||||
new google.maps.LatLng(37.765769, -122.407201),
|
|
||||||
new google.maps.LatLng(37.76579, -122.407414),
|
|
||||||
new google.maps.LatLng(37.765802, -122.407755),
|
|
||||||
new google.maps.LatLng(37.765791, -122.408219),
|
|
||||||
new google.maps.LatLng(37.765763, -122.408759),
|
|
||||||
new google.maps.LatLng(37.765726, -122.409348),
|
|
||||||
new google.maps.LatLng(37.765716, -122.409882),
|
|
||||||
new google.maps.LatLng(37.765708, -122.410202),
|
|
||||||
new google.maps.LatLng(37.765705, -122.410253),
|
|
||||||
new google.maps.LatLng(37.765707, -122.410369),
|
|
||||||
new google.maps.LatLng(37.765692, -122.41072),
|
|
||||||
new google.maps.LatLng(37.765699, -122.411215),
|
|
||||||
new google.maps.LatLng(37.765687, -122.411789),
|
|
||||||
new google.maps.LatLng(37.765666, -122.412373),
|
|
||||||
new google.maps.LatLng(37.765598, -122.412883),
|
|
||||||
new google.maps.LatLng(37.765543, -122.413039),
|
|
||||||
new google.maps.LatLng(37.765532, -122.413125),
|
|
||||||
new google.maps.LatLng(37.7655, -122.413553),
|
|
||||||
new google.maps.LatLng(37.765448, -122.414053),
|
|
||||||
new google.maps.LatLng(37.765388, -122.414645),
|
|
||||||
new google.maps.LatLng(37.765323, -122.41525),
|
|
||||||
new google.maps.LatLng(37.765303, -122.415847),
|
|
||||||
new google.maps.LatLng(37.765251, -122.416439),
|
|
||||||
new google.maps.LatLng(37.765204, -122.41702),
|
|
||||||
new google.maps.LatLng(37.765172, -122.417556),
|
|
||||||
new google.maps.LatLng(37.765164, -122.418075),
|
|
||||||
new google.maps.LatLng(37.765153, -122.418618),
|
|
||||||
new google.maps.LatLng(37.765136, -122.419112),
|
|
||||||
new google.maps.LatLng(37.765129, -122.419378),
|
|
||||||
new google.maps.LatLng(37.765119, -122.419481),
|
|
||||||
new google.maps.LatLng(37.7651, -122.419852),
|
|
||||||
new google.maps.LatLng(37.765083, -122.420349),
|
|
||||||
new google.maps.LatLng(37.765045, -122.42093),
|
|
||||||
new google.maps.LatLng(37.764992, -122.421481),
|
|
||||||
new google.maps.LatLng(37.76498, -122.421695),
|
|
||||||
new google.maps.LatLng(37.764993, -122.421843),
|
|
||||||
new google.maps.LatLng(37.764986, -122.422255),
|
|
||||||
new google.maps.LatLng(37.764975, -122.422823),
|
|
||||||
new google.maps.LatLng(37.764939, -122.423411),
|
|
||||||
new google.maps.LatLng(37.764902, -122.424014),
|
|
||||||
new google.maps.LatLng(37.764853, -122.424576),
|
|
||||||
new google.maps.LatLng(37.764826, -122.424922),
|
|
||||||
new google.maps.LatLng(37.764796, -122.425375),
|
|
||||||
new google.maps.LatLng(37.764782, -122.425869),
|
|
||||||
new google.maps.LatLng(37.764768, -122.426089),
|
|
||||||
new google.maps.LatLng(37.764766, -122.426117),
|
|
||||||
new google.maps.LatLng(37.764723, -122.426276),
|
|
||||||
new google.maps.LatLng(37.764681, -122.426649),
|
|
||||||
new google.maps.LatLng(37.782012, -122.4042),
|
|
||||||
new google.maps.LatLng(37.781574, -122.404911),
|
|
||||||
new google.maps.LatLng(37.781055, -122.405597),
|
|
||||||
new google.maps.LatLng(37.780479, -122.406341),
|
|
||||||
new google.maps.LatLng(37.779996, -122.406939),
|
|
||||||
new google.maps.LatLng(37.779459, -122.407613),
|
|
||||||
new google.maps.LatLng(37.778953, -122.408228),
|
|
||||||
new google.maps.LatLng(37.778409, -122.408839),
|
|
||||||
new google.maps.LatLng(37.777842, -122.409501),
|
|
||||||
new google.maps.LatLng(37.777334, -122.410181),
|
|
||||||
new google.maps.LatLng(37.776809, -122.410836),
|
|
||||||
new google.maps.LatLng(37.77624, -122.411514),
|
|
||||||
new google.maps.LatLng(37.775725, -122.412145),
|
|
||||||
new google.maps.LatLng(37.77519, -122.412805),
|
|
||||||
new google.maps.LatLng(37.774672, -122.413464),
|
|
||||||
new google.maps.LatLng(37.774084, -122.414186),
|
|
||||||
new google.maps.LatLng(37.773533, -122.413636),
|
|
||||||
new google.maps.LatLng(37.773021, -122.413009),
|
|
||||||
new google.maps.LatLng(37.772501, -122.412371),
|
|
||||||
new google.maps.LatLng(37.771964, -122.411681),
|
|
||||||
new google.maps.LatLng(37.771479, -122.411078),
|
|
||||||
new google.maps.LatLng(37.770992, -122.410477),
|
|
||||||
new google.maps.LatLng(37.770467, -122.409801),
|
|
||||||
new google.maps.LatLng(37.77009, -122.408904),
|
|
||||||
new google.maps.LatLng(37.769657, -122.408103),
|
|
||||||
new google.maps.LatLng(37.769132, -122.407276),
|
|
||||||
new google.maps.LatLng(37.768564, -122.406469),
|
|
||||||
new google.maps.LatLng(37.76798, -122.405745),
|
|
||||||
new google.maps.LatLng(37.76738, -122.405299),
|
|
||||||
new google.maps.LatLng(37.766604, -122.405297),
|
|
||||||
new google.maps.LatLng(37.765838, -122.4052),
|
|
||||||
new google.maps.LatLng(37.765139, -122.405139),
|
|
||||||
new google.maps.LatLng(37.764457, -122.405094),
|
|
||||||
new google.maps.LatLng(37.763716, -122.405142),
|
|
||||||
new google.maps.LatLng(37.762932, -122.405398),
|
|
||||||
new google.maps.LatLng(37.762126, -122.405813),
|
|
||||||
new google.maps.LatLng(37.761344, -122.406215),
|
|
||||||
new google.maps.LatLng(37.760556, -122.406495),
|
|
||||||
new google.maps.LatLng(37.759732, -122.406484),
|
|
||||||
new google.maps.LatLng(37.75891, -122.406228),
|
|
||||||
new google.maps.LatLng(37.758182, -122.405695),
|
|
||||||
new google.maps.LatLng(37.757676, -122.405118),
|
|
||||||
new google.maps.LatLng(37.757039, -122.404346),
|
|
||||||
new google.maps.LatLng(37.756335, -122.403719),
|
|
||||||
new google.maps.LatLng(37.755503, -122.403406),
|
|
||||||
new google.maps.LatLng(37.754665, -122.403242),
|
|
||||||
new google.maps.LatLng(37.753837, -122.403172),
|
|
||||||
new google.maps.LatLng(37.752986, -122.403112),
|
|
||||||
new google.maps.LatLng(37.751266, -122.403355),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=heatmap.js.map
|
|
File diff suppressed because one or more lines are too long
@ -1,561 +0,0 @@
|
|||||||
import { Loader, LoaderOptions } from 'google-maps';
|
|
||||||
|
|
||||||
let map: google.maps.Map, heatmap: google.maps.visualization.HeatmapLayer;
|
|
||||||
|
|
||||||
function initMap(): void {
|
|
||||||
const options: LoaderOptions = {/* todo */ };
|
|
||||||
const loader = new Loader('AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY', options);
|
|
||||||
|
|
||||||
loader.load().then(function (google) {
|
|
||||||
map = new google.maps.Map(document.getElementById("map") as HTMLElement, {
|
|
||||||
zoom: 13,
|
|
||||||
center: { lat: 37.775, lng: -122.434 },
|
|
||||||
mapTypeId: "satellite",
|
|
||||||
});
|
|
||||||
|
|
||||||
heatmap = new google.maps.visualization.HeatmapLayer({
|
|
||||||
data: getPoints(),
|
|
||||||
map: map,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleHeatmap() {
|
|
||||||
heatmap.setMap(heatmap.getMap() ? null : map);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeGradient() {
|
|
||||||
const gradient = [
|
|
||||||
"rgba(0, 255, 255, 0)",
|
|
||||||
"rgba(0, 255, 255, 1)",
|
|
||||||
"rgba(0, 191, 255, 1)",
|
|
||||||
"rgba(0, 127, 255, 1)",
|
|
||||||
"rgba(0, 63, 255, 1)",
|
|
||||||
"rgba(0, 0, 255, 1)",
|
|
||||||
"rgba(0, 0, 223, 1)",
|
|
||||||
"rgba(0, 0, 191, 1)",
|
|
||||||
"rgba(0, 0, 159, 1)",
|
|
||||||
"rgba(0, 0, 127, 1)",
|
|
||||||
"rgba(63, 0, 91, 1)",
|
|
||||||
"rgba(127, 0, 63, 1)",
|
|
||||||
"rgba(191, 0, 31, 1)",
|
|
||||||
"rgba(255, 0, 0, 1)",
|
|
||||||
];
|
|
||||||
heatmap.set("gradient", heatmap.get("gradient") ? null : gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeRadius() {
|
|
||||||
heatmap.set("radius", heatmap.get("radius") ? null : 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeOpacity() {
|
|
||||||
heatmap.set("opacity", heatmap.get("opacity") ? null : 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heatmap data: 500 Points
|
|
||||||
function getPoints() {
|
|
||||||
return [
|
|
||||||
new google.maps.LatLng(37.782551, -122.445368),
|
|
||||||
new google.maps.LatLng(37.782745, -122.444586),
|
|
||||||
new google.maps.LatLng(37.782842, -122.443688),
|
|
||||||
new google.maps.LatLng(37.782919, -122.442815),
|
|
||||||
new google.maps.LatLng(37.782992, -122.442112),
|
|
||||||
new google.maps.LatLng(37.7831, -122.441461),
|
|
||||||
new google.maps.LatLng(37.783206, -122.440829),
|
|
||||||
new google.maps.LatLng(37.783273, -122.440324),
|
|
||||||
new google.maps.LatLng(37.783316, -122.440023),
|
|
||||||
new google.maps.LatLng(37.783357, -122.439794),
|
|
||||||
new google.maps.LatLng(37.783371, -122.439687),
|
|
||||||
new google.maps.LatLng(37.783368, -122.439666),
|
|
||||||
new google.maps.LatLng(37.783383, -122.439594),
|
|
||||||
new google.maps.LatLng(37.783508, -122.439525),
|
|
||||||
new google.maps.LatLng(37.783842, -122.439591),
|
|
||||||
new google.maps.LatLng(37.784147, -122.439668),
|
|
||||||
new google.maps.LatLng(37.784206, -122.439686),
|
|
||||||
new google.maps.LatLng(37.784386, -122.43979),
|
|
||||||
new google.maps.LatLng(37.784701, -122.439902),
|
|
||||||
new google.maps.LatLng(37.784965, -122.439938),
|
|
||||||
new google.maps.LatLng(37.78501, -122.439947),
|
|
||||||
new google.maps.LatLng(37.78536, -122.439952),
|
|
||||||
new google.maps.LatLng(37.785715, -122.44003),
|
|
||||||
new google.maps.LatLng(37.786117, -122.440119),
|
|
||||||
new google.maps.LatLng(37.786564, -122.440209),
|
|
||||||
new google.maps.LatLng(37.786905, -122.44027),
|
|
||||||
new google.maps.LatLng(37.786956, -122.440279),
|
|
||||||
new google.maps.LatLng(37.800224, -122.43352),
|
|
||||||
new google.maps.LatLng(37.800155, -122.434101),
|
|
||||||
new google.maps.LatLng(37.80016, -122.43443),
|
|
||||||
new google.maps.LatLng(37.800378, -122.434527),
|
|
||||||
new google.maps.LatLng(37.800738, -122.434598),
|
|
||||||
new google.maps.LatLng(37.800938, -122.43465),
|
|
||||||
new google.maps.LatLng(37.801024, -122.434889),
|
|
||||||
new google.maps.LatLng(37.800955, -122.435392),
|
|
||||||
new google.maps.LatLng(37.800886, -122.435959),
|
|
||||||
new google.maps.LatLng(37.800811, -122.436275),
|
|
||||||
new google.maps.LatLng(37.800788, -122.436299),
|
|
||||||
new google.maps.LatLng(37.800719, -122.436302),
|
|
||||||
new google.maps.LatLng(37.800702, -122.436298),
|
|
||||||
new google.maps.LatLng(37.800661, -122.436273),
|
|
||||||
new google.maps.LatLng(37.800395, -122.436172),
|
|
||||||
new google.maps.LatLng(37.800228, -122.436116),
|
|
||||||
new google.maps.LatLng(37.800169, -122.43613),
|
|
||||||
new google.maps.LatLng(37.800066, -122.436167),
|
|
||||||
new google.maps.LatLng(37.784345, -122.422922),
|
|
||||||
new google.maps.LatLng(37.784389, -122.422926),
|
|
||||||
new google.maps.LatLng(37.784437, -122.422924),
|
|
||||||
new google.maps.LatLng(37.784746, -122.422818),
|
|
||||||
new google.maps.LatLng(37.785436, -122.422959),
|
|
||||||
new google.maps.LatLng(37.78612, -122.423112),
|
|
||||||
new google.maps.LatLng(37.786433, -122.423029),
|
|
||||||
new google.maps.LatLng(37.786631, -122.421213),
|
|
||||||
new google.maps.LatLng(37.78666, -122.421033),
|
|
||||||
new google.maps.LatLng(37.786801, -122.420141),
|
|
||||||
new google.maps.LatLng(37.786823, -122.420034),
|
|
||||||
new google.maps.LatLng(37.786831, -122.419916),
|
|
||||||
new google.maps.LatLng(37.787034, -122.418208),
|
|
||||||
new google.maps.LatLng(37.787056, -122.418034),
|
|
||||||
new google.maps.LatLng(37.787169, -122.417145),
|
|
||||||
new google.maps.LatLng(37.787217, -122.416715),
|
|
||||||
new google.maps.LatLng(37.786144, -122.416403),
|
|
||||||
new google.maps.LatLng(37.785292, -122.416257),
|
|
||||||
new google.maps.LatLng(37.780666, -122.390374),
|
|
||||||
new google.maps.LatLng(37.780501, -122.391281),
|
|
||||||
new google.maps.LatLng(37.780148, -122.392052),
|
|
||||||
new google.maps.LatLng(37.780173, -122.391148),
|
|
||||||
new google.maps.LatLng(37.780693, -122.390592),
|
|
||||||
new google.maps.LatLng(37.781261, -122.391142),
|
|
||||||
new google.maps.LatLng(37.781808, -122.39173),
|
|
||||||
new google.maps.LatLng(37.78234, -122.392341),
|
|
||||||
new google.maps.LatLng(37.782812, -122.393022),
|
|
||||||
new google.maps.LatLng(37.7833, -122.393672),
|
|
||||||
new google.maps.LatLng(37.783809, -122.394275),
|
|
||||||
new google.maps.LatLng(37.784246, -122.394979),
|
|
||||||
new google.maps.LatLng(37.784791, -122.395958),
|
|
||||||
new google.maps.LatLng(37.785675, -122.396746),
|
|
||||||
new google.maps.LatLng(37.786262, -122.39578),
|
|
||||||
new google.maps.LatLng(37.786776, -122.395093),
|
|
||||||
new google.maps.LatLng(37.787282, -122.394426),
|
|
||||||
new google.maps.LatLng(37.787783, -122.393767),
|
|
||||||
new google.maps.LatLng(37.788343, -122.393184),
|
|
||||||
new google.maps.LatLng(37.788895, -122.392506),
|
|
||||||
new google.maps.LatLng(37.789371, -122.391701),
|
|
||||||
new google.maps.LatLng(37.789722, -122.390952),
|
|
||||||
new google.maps.LatLng(37.790315, -122.390305),
|
|
||||||
new google.maps.LatLng(37.790738, -122.389616),
|
|
||||||
new google.maps.LatLng(37.779448, -122.438702),
|
|
||||||
new google.maps.LatLng(37.779023, -122.438585),
|
|
||||||
new google.maps.LatLng(37.778542, -122.438492),
|
|
||||||
new google.maps.LatLng(37.7781, -122.438411),
|
|
||||||
new google.maps.LatLng(37.777986, -122.438376),
|
|
||||||
new google.maps.LatLng(37.77768, -122.438313),
|
|
||||||
new google.maps.LatLng(37.777316, -122.438273),
|
|
||||||
new google.maps.LatLng(37.777135, -122.438254),
|
|
||||||
new google.maps.LatLng(37.776987, -122.438303),
|
|
||||||
new google.maps.LatLng(37.776946, -122.438404),
|
|
||||||
new google.maps.LatLng(37.776944, -122.438467),
|
|
||||||
new google.maps.LatLng(37.776892, -122.438459),
|
|
||||||
new google.maps.LatLng(37.776842, -122.438442),
|
|
||||||
new google.maps.LatLng(37.776822, -122.438391),
|
|
||||||
new google.maps.LatLng(37.776814, -122.438412),
|
|
||||||
new google.maps.LatLng(37.776787, -122.438628),
|
|
||||||
new google.maps.LatLng(37.776729, -122.43865),
|
|
||||||
new google.maps.LatLng(37.776759, -122.438677),
|
|
||||||
new google.maps.LatLng(37.776772, -122.438498),
|
|
||||||
new google.maps.LatLng(37.776787, -122.438389),
|
|
||||||
new google.maps.LatLng(37.776848, -122.438283),
|
|
||||||
new google.maps.LatLng(37.77687, -122.438239),
|
|
||||||
new google.maps.LatLng(37.777015, -122.438198),
|
|
||||||
new google.maps.LatLng(37.777333, -122.438256),
|
|
||||||
new google.maps.LatLng(37.777595, -122.438308),
|
|
||||||
new google.maps.LatLng(37.777797, -122.438344),
|
|
||||||
new google.maps.LatLng(37.77816, -122.438442),
|
|
||||||
new google.maps.LatLng(37.778414, -122.438508),
|
|
||||||
new google.maps.LatLng(37.778445, -122.438516),
|
|
||||||
new google.maps.LatLng(37.778503, -122.438529),
|
|
||||||
new google.maps.LatLng(37.778607, -122.438549),
|
|
||||||
new google.maps.LatLng(37.77867, -122.438644),
|
|
||||||
new google.maps.LatLng(37.778847, -122.438706),
|
|
||||||
new google.maps.LatLng(37.77924, -122.438744),
|
|
||||||
new google.maps.LatLng(37.779738, -122.438822),
|
|
||||||
new google.maps.LatLng(37.780201, -122.438882),
|
|
||||||
new google.maps.LatLng(37.7804, -122.438905),
|
|
||||||
new google.maps.LatLng(37.780501, -122.438921),
|
|
||||||
new google.maps.LatLng(37.780892, -122.438986),
|
|
||||||
new google.maps.LatLng(37.781446, -122.439087),
|
|
||||||
new google.maps.LatLng(37.781985, -122.439199),
|
|
||||||
new google.maps.LatLng(37.782239, -122.439249),
|
|
||||||
new google.maps.LatLng(37.782286, -122.439266),
|
|
||||||
new google.maps.LatLng(37.797847, -122.429388),
|
|
||||||
new google.maps.LatLng(37.797874, -122.42918),
|
|
||||||
new google.maps.LatLng(37.797885, -122.429069),
|
|
||||||
new google.maps.LatLng(37.797887, -122.42905),
|
|
||||||
new google.maps.LatLng(37.797933, -122.428954),
|
|
||||||
new google.maps.LatLng(37.798242, -122.42899),
|
|
||||||
new google.maps.LatLng(37.798617, -122.429075),
|
|
||||||
new google.maps.LatLng(37.798719, -122.429092),
|
|
||||||
new google.maps.LatLng(37.798944, -122.429145),
|
|
||||||
new google.maps.LatLng(37.79932, -122.429251),
|
|
||||||
new google.maps.LatLng(37.79959, -122.429309),
|
|
||||||
new google.maps.LatLng(37.799677, -122.429324),
|
|
||||||
new google.maps.LatLng(37.799966, -122.42936),
|
|
||||||
new google.maps.LatLng(37.800288, -122.42943),
|
|
||||||
new google.maps.LatLng(37.800443, -122.429461),
|
|
||||||
new google.maps.LatLng(37.800465, -122.429474),
|
|
||||||
new google.maps.LatLng(37.800644, -122.42954),
|
|
||||||
new google.maps.LatLng(37.800948, -122.42962),
|
|
||||||
new google.maps.LatLng(37.801242, -122.429685),
|
|
||||||
new google.maps.LatLng(37.801375, -122.429702),
|
|
||||||
new google.maps.LatLng(37.8014, -122.429703),
|
|
||||||
new google.maps.LatLng(37.801453, -122.429707),
|
|
||||||
new google.maps.LatLng(37.801473, -122.429709),
|
|
||||||
new google.maps.LatLng(37.801532, -122.429707),
|
|
||||||
new google.maps.LatLng(37.801852, -122.429729),
|
|
||||||
new google.maps.LatLng(37.802173, -122.429789),
|
|
||||||
new google.maps.LatLng(37.802459, -122.429847),
|
|
||||||
new google.maps.LatLng(37.802554, -122.429825),
|
|
||||||
new google.maps.LatLng(37.802647, -122.429549),
|
|
||||||
new google.maps.LatLng(37.802693, -122.429179),
|
|
||||||
new google.maps.LatLng(37.802729, -122.428751),
|
|
||||||
new google.maps.LatLng(37.766104, -122.409291),
|
|
||||||
new google.maps.LatLng(37.766103, -122.409268),
|
|
||||||
new google.maps.LatLng(37.766138, -122.409229),
|
|
||||||
new google.maps.LatLng(37.766183, -122.409231),
|
|
||||||
new google.maps.LatLng(37.766153, -122.409276),
|
|
||||||
new google.maps.LatLng(37.766005, -122.409365),
|
|
||||||
new google.maps.LatLng(37.765897, -122.40957),
|
|
||||||
new google.maps.LatLng(37.765767, -122.409739),
|
|
||||||
new google.maps.LatLng(37.765693, -122.410389),
|
|
||||||
new google.maps.LatLng(37.765615, -122.411201),
|
|
||||||
new google.maps.LatLng(37.765533, -122.412121),
|
|
||||||
new google.maps.LatLng(37.765467, -122.412939),
|
|
||||||
new google.maps.LatLng(37.765444, -122.414821),
|
|
||||||
new google.maps.LatLng(37.765444, -122.414964),
|
|
||||||
new google.maps.LatLng(37.765318, -122.415424),
|
|
||||||
new google.maps.LatLng(37.763961, -122.415296),
|
|
||||||
new google.maps.LatLng(37.763115, -122.415196),
|
|
||||||
new google.maps.LatLng(37.762967, -122.415183),
|
|
||||||
new google.maps.LatLng(37.762278, -122.415127),
|
|
||||||
new google.maps.LatLng(37.761675, -122.415055),
|
|
||||||
new google.maps.LatLng(37.760932, -122.414988),
|
|
||||||
new google.maps.LatLng(37.759337, -122.414862),
|
|
||||||
new google.maps.LatLng(37.773187, -122.421922),
|
|
||||||
new google.maps.LatLng(37.773043, -122.422118),
|
|
||||||
new google.maps.LatLng(37.773007, -122.422165),
|
|
||||||
new google.maps.LatLng(37.772979, -122.422219),
|
|
||||||
new google.maps.LatLng(37.772865, -122.422394),
|
|
||||||
new google.maps.LatLng(37.772779, -122.422503),
|
|
||||||
new google.maps.LatLng(37.772676, -122.422701),
|
|
||||||
new google.maps.LatLng(37.772606, -122.422806),
|
|
||||||
new google.maps.LatLng(37.772566, -122.42284),
|
|
||||||
new google.maps.LatLng(37.772508, -122.422852),
|
|
||||||
new google.maps.LatLng(37.772387, -122.423011),
|
|
||||||
new google.maps.LatLng(37.772099, -122.423328),
|
|
||||||
new google.maps.LatLng(37.771704, -122.423783),
|
|
||||||
new google.maps.LatLng(37.771481, -122.424081),
|
|
||||||
new google.maps.LatLng(37.7714, -122.424179),
|
|
||||||
new google.maps.LatLng(37.771352, -122.42422),
|
|
||||||
new google.maps.LatLng(37.771248, -122.424327),
|
|
||||||
new google.maps.LatLng(37.770904, -122.424781),
|
|
||||||
new google.maps.LatLng(37.77052, -122.425283),
|
|
||||||
new google.maps.LatLng(37.770337, -122.425553),
|
|
||||||
new google.maps.LatLng(37.770128, -122.425832),
|
|
||||||
new google.maps.LatLng(37.769756, -122.426331),
|
|
||||||
new google.maps.LatLng(37.7693, -122.426902),
|
|
||||||
new google.maps.LatLng(37.769132, -122.427065),
|
|
||||||
new google.maps.LatLng(37.769092, -122.427103),
|
|
||||||
new google.maps.LatLng(37.768979, -122.427172),
|
|
||||||
new google.maps.LatLng(37.768595, -122.427634),
|
|
||||||
new google.maps.LatLng(37.768372, -122.427913),
|
|
||||||
new google.maps.LatLng(37.768337, -122.427961),
|
|
||||||
new google.maps.LatLng(37.768244, -122.428138),
|
|
||||||
new google.maps.LatLng(37.767942, -122.428581),
|
|
||||||
new google.maps.LatLng(37.767482, -122.429094),
|
|
||||||
new google.maps.LatLng(37.767031, -122.429606),
|
|
||||||
new google.maps.LatLng(37.766732, -122.429986),
|
|
||||||
new google.maps.LatLng(37.76668, -122.430058),
|
|
||||||
new google.maps.LatLng(37.766633, -122.430109),
|
|
||||||
new google.maps.LatLng(37.76658, -122.430211),
|
|
||||||
new google.maps.LatLng(37.766367, -122.430594),
|
|
||||||
new google.maps.LatLng(37.76591, -122.431137),
|
|
||||||
new google.maps.LatLng(37.765353, -122.431806),
|
|
||||||
new google.maps.LatLng(37.764962, -122.432298),
|
|
||||||
new google.maps.LatLng(37.764868, -122.432486),
|
|
||||||
new google.maps.LatLng(37.764518, -122.432913),
|
|
||||||
new google.maps.LatLng(37.763435, -122.434173),
|
|
||||||
new google.maps.LatLng(37.762847, -122.434953),
|
|
||||||
new google.maps.LatLng(37.762291, -122.435935),
|
|
||||||
new google.maps.LatLng(37.762224, -122.436074),
|
|
||||||
new google.maps.LatLng(37.761957, -122.436892),
|
|
||||||
new google.maps.LatLng(37.761652, -122.438886),
|
|
||||||
new google.maps.LatLng(37.761284, -122.439955),
|
|
||||||
new google.maps.LatLng(37.76121, -122.440068),
|
|
||||||
new google.maps.LatLng(37.761064, -122.44072),
|
|
||||||
new google.maps.LatLng(37.76104, -122.441411),
|
|
||||||
new google.maps.LatLng(37.761048, -122.442324),
|
|
||||||
new google.maps.LatLng(37.760851, -122.443118),
|
|
||||||
new google.maps.LatLng(37.759977, -122.444591),
|
|
||||||
new google.maps.LatLng(37.759913, -122.444698),
|
|
||||||
new google.maps.LatLng(37.759623, -122.445065),
|
|
||||||
new google.maps.LatLng(37.758902, -122.445158),
|
|
||||||
new google.maps.LatLng(37.758428, -122.44457),
|
|
||||||
new google.maps.LatLng(37.757687, -122.44334),
|
|
||||||
new google.maps.LatLng(37.757583, -122.44324),
|
|
||||||
new google.maps.LatLng(37.757019, -122.442787),
|
|
||||||
new google.maps.LatLng(37.756603, -122.442322),
|
|
||||||
new google.maps.LatLng(37.75638, -122.441602),
|
|
||||||
new google.maps.LatLng(37.75579, -122.441382),
|
|
||||||
new google.maps.LatLng(37.754493, -122.442133),
|
|
||||||
new google.maps.LatLng(37.754361, -122.442206),
|
|
||||||
new google.maps.LatLng(37.753719, -122.44265),
|
|
||||||
new google.maps.LatLng(37.753096, -122.442915),
|
|
||||||
new google.maps.LatLng(37.751617, -122.443211),
|
|
||||||
new google.maps.LatLng(37.751496, -122.443246),
|
|
||||||
new google.maps.LatLng(37.750733, -122.443428),
|
|
||||||
new google.maps.LatLng(37.750126, -122.443536),
|
|
||||||
new google.maps.LatLng(37.750103, -122.443784),
|
|
||||||
new google.maps.LatLng(37.75039, -122.44401),
|
|
||||||
new google.maps.LatLng(37.750448, -122.444013),
|
|
||||||
new google.maps.LatLng(37.750536, -122.44404),
|
|
||||||
new google.maps.LatLng(37.750493, -122.444141),
|
|
||||||
new google.maps.LatLng(37.790859, -122.402808),
|
|
||||||
new google.maps.LatLng(37.790864, -122.402768),
|
|
||||||
new google.maps.LatLng(37.790995, -122.402539),
|
|
||||||
new google.maps.LatLng(37.791148, -122.402172),
|
|
||||||
new google.maps.LatLng(37.791385, -122.401312),
|
|
||||||
new google.maps.LatLng(37.791405, -122.400776),
|
|
||||||
new google.maps.LatLng(37.791288, -122.400528),
|
|
||||||
new google.maps.LatLng(37.791113, -122.400441),
|
|
||||||
new google.maps.LatLng(37.791027, -122.400395),
|
|
||||||
new google.maps.LatLng(37.791094, -122.400311),
|
|
||||||
new google.maps.LatLng(37.791211, -122.400183),
|
|
||||||
new google.maps.LatLng(37.79106, -122.399334),
|
|
||||||
new google.maps.LatLng(37.790538, -122.398718),
|
|
||||||
new google.maps.LatLng(37.790095, -122.398086),
|
|
||||||
new google.maps.LatLng(37.789644, -122.39736),
|
|
||||||
new google.maps.LatLng(37.789254, -122.396844),
|
|
||||||
new google.maps.LatLng(37.788855, -122.396397),
|
|
||||||
new google.maps.LatLng(37.788483, -122.395963),
|
|
||||||
new google.maps.LatLng(37.788015, -122.395365),
|
|
||||||
new google.maps.LatLng(37.787558, -122.394735),
|
|
||||||
new google.maps.LatLng(37.787472, -122.394323),
|
|
||||||
new google.maps.LatLng(37.78763, -122.394025),
|
|
||||||
new google.maps.LatLng(37.787767, -122.393987),
|
|
||||||
new google.maps.LatLng(37.787486, -122.394452),
|
|
||||||
new google.maps.LatLng(37.786977, -122.395043),
|
|
||||||
new google.maps.LatLng(37.786583, -122.395552),
|
|
||||||
new google.maps.LatLng(37.78654, -122.39561),
|
|
||||||
new google.maps.LatLng(37.786516, -122.395659),
|
|
||||||
new google.maps.LatLng(37.786378, -122.395707),
|
|
||||||
new google.maps.LatLng(37.786044, -122.395362),
|
|
||||||
new google.maps.LatLng(37.785598, -122.394715),
|
|
||||||
new google.maps.LatLng(37.785321, -122.394361),
|
|
||||||
new google.maps.LatLng(37.785207, -122.394236),
|
|
||||||
new google.maps.LatLng(37.785751, -122.394062),
|
|
||||||
new google.maps.LatLng(37.785996, -122.393881),
|
|
||||||
new google.maps.LatLng(37.786092, -122.39383),
|
|
||||||
new google.maps.LatLng(37.785998, -122.393899),
|
|
||||||
new google.maps.LatLng(37.785114, -122.394365),
|
|
||||||
new google.maps.LatLng(37.785022, -122.394441),
|
|
||||||
new google.maps.LatLng(37.784823, -122.394635),
|
|
||||||
new google.maps.LatLng(37.784719, -122.394629),
|
|
||||||
new google.maps.LatLng(37.785069, -122.394176),
|
|
||||||
new google.maps.LatLng(37.7855, -122.39365),
|
|
||||||
new google.maps.LatLng(37.78577, -122.393291),
|
|
||||||
new google.maps.LatLng(37.785839, -122.393159),
|
|
||||||
new google.maps.LatLng(37.782651, -122.400628),
|
|
||||||
new google.maps.LatLng(37.782616, -122.400599),
|
|
||||||
new google.maps.LatLng(37.782702, -122.40047),
|
|
||||||
new google.maps.LatLng(37.782915, -122.400192),
|
|
||||||
new google.maps.LatLng(37.783137, -122.399887),
|
|
||||||
new google.maps.LatLng(37.783414, -122.399519),
|
|
||||||
new google.maps.LatLng(37.783629, -122.399237),
|
|
||||||
new google.maps.LatLng(37.783688, -122.399157),
|
|
||||||
new google.maps.LatLng(37.783716, -122.399106),
|
|
||||||
new google.maps.LatLng(37.783798, -122.399072),
|
|
||||||
new google.maps.LatLng(37.783997, -122.399186),
|
|
||||||
new google.maps.LatLng(37.784271, -122.399538),
|
|
||||||
new google.maps.LatLng(37.784577, -122.399948),
|
|
||||||
new google.maps.LatLng(37.784828, -122.40026),
|
|
||||||
new google.maps.LatLng(37.784999, -122.400477),
|
|
||||||
new google.maps.LatLng(37.785113, -122.400651),
|
|
||||||
new google.maps.LatLng(37.785155, -122.400703),
|
|
||||||
new google.maps.LatLng(37.785192, -122.400749),
|
|
||||||
new google.maps.LatLng(37.785278, -122.400839),
|
|
||||||
new google.maps.LatLng(37.785387, -122.400857),
|
|
||||||
new google.maps.LatLng(37.785478, -122.40089),
|
|
||||||
new google.maps.LatLng(37.785526, -122.401022),
|
|
||||||
new google.maps.LatLng(37.785598, -122.401148),
|
|
||||||
new google.maps.LatLng(37.785631, -122.401202),
|
|
||||||
new google.maps.LatLng(37.78566, -122.401267),
|
|
||||||
new google.maps.LatLng(37.803986, -122.426035),
|
|
||||||
new google.maps.LatLng(37.804102, -122.425089),
|
|
||||||
new google.maps.LatLng(37.804211, -122.424156),
|
|
||||||
new google.maps.LatLng(37.803861, -122.423385),
|
|
||||||
new google.maps.LatLng(37.803151, -122.423214),
|
|
||||||
new google.maps.LatLng(37.802439, -122.423077),
|
|
||||||
new google.maps.LatLng(37.80174, -122.422905),
|
|
||||||
new google.maps.LatLng(37.801069, -122.422785),
|
|
||||||
new google.maps.LatLng(37.800345, -122.422649),
|
|
||||||
new google.maps.LatLng(37.799633, -122.422603),
|
|
||||||
new google.maps.LatLng(37.79975, -122.4217),
|
|
||||||
new google.maps.LatLng(37.799885, -122.420854),
|
|
||||||
new google.maps.LatLng(37.799209, -122.420607),
|
|
||||||
new google.maps.LatLng(37.795656, -122.400395),
|
|
||||||
new google.maps.LatLng(37.795203, -122.400304),
|
|
||||||
new google.maps.LatLng(37.778738, -122.415584),
|
|
||||||
new google.maps.LatLng(37.778812, -122.415189),
|
|
||||||
new google.maps.LatLng(37.778824, -122.415092),
|
|
||||||
new google.maps.LatLng(37.778833, -122.414932),
|
|
||||||
new google.maps.LatLng(37.778834, -122.414898),
|
|
||||||
new google.maps.LatLng(37.77874, -122.414757),
|
|
||||||
new google.maps.LatLng(37.778501, -122.414433),
|
|
||||||
new google.maps.LatLng(37.778182, -122.414026),
|
|
||||||
new google.maps.LatLng(37.777851, -122.413623),
|
|
||||||
new google.maps.LatLng(37.777486, -122.413166),
|
|
||||||
new google.maps.LatLng(37.777109, -122.412674),
|
|
||||||
new google.maps.LatLng(37.776743, -122.412186),
|
|
||||||
new google.maps.LatLng(37.77644, -122.4118),
|
|
||||||
new google.maps.LatLng(37.776295, -122.411614),
|
|
||||||
new google.maps.LatLng(37.776158, -122.41144),
|
|
||||||
new google.maps.LatLng(37.775806, -122.410997),
|
|
||||||
new google.maps.LatLng(37.775422, -122.410484),
|
|
||||||
new google.maps.LatLng(37.775126, -122.410087),
|
|
||||||
new google.maps.LatLng(37.775012, -122.409854),
|
|
||||||
new google.maps.LatLng(37.775164, -122.409573),
|
|
||||||
new google.maps.LatLng(37.775498, -122.40918),
|
|
||||||
new google.maps.LatLng(37.775868, -122.40873),
|
|
||||||
new google.maps.LatLng(37.776256, -122.40824),
|
|
||||||
new google.maps.LatLng(37.776519, -122.407928),
|
|
||||||
new google.maps.LatLng(37.776539, -122.407904),
|
|
||||||
new google.maps.LatLng(37.776595, -122.407854),
|
|
||||||
new google.maps.LatLng(37.776853, -122.407547),
|
|
||||||
new google.maps.LatLng(37.777234, -122.407087),
|
|
||||||
new google.maps.LatLng(37.777644, -122.406558),
|
|
||||||
new google.maps.LatLng(37.778066, -122.406017),
|
|
||||||
new google.maps.LatLng(37.778468, -122.405499),
|
|
||||||
new google.maps.LatLng(37.778866, -122.404995),
|
|
||||||
new google.maps.LatLng(37.779295, -122.404455),
|
|
||||||
new google.maps.LatLng(37.779695, -122.40395),
|
|
||||||
new google.maps.LatLng(37.779982, -122.403584),
|
|
||||||
new google.maps.LatLng(37.780295, -122.403223),
|
|
||||||
new google.maps.LatLng(37.780664, -122.402766),
|
|
||||||
new google.maps.LatLng(37.781043, -122.402288),
|
|
||||||
new google.maps.LatLng(37.781399, -122.401823),
|
|
||||||
new google.maps.LatLng(37.781727, -122.401407),
|
|
||||||
new google.maps.LatLng(37.781853, -122.401247),
|
|
||||||
new google.maps.LatLng(37.781894, -122.401195),
|
|
||||||
new google.maps.LatLng(37.782076, -122.400977),
|
|
||||||
new google.maps.LatLng(37.782338, -122.400603),
|
|
||||||
new google.maps.LatLng(37.782666, -122.400133),
|
|
||||||
new google.maps.LatLng(37.783048, -122.399634),
|
|
||||||
new google.maps.LatLng(37.78345, -122.399198),
|
|
||||||
new google.maps.LatLng(37.783791, -122.398998),
|
|
||||||
new google.maps.LatLng(37.784177, -122.398959),
|
|
||||||
new google.maps.LatLng(37.784388, -122.398971),
|
|
||||||
new google.maps.LatLng(37.784404, -122.399128),
|
|
||||||
new google.maps.LatLng(37.784586, -122.399524),
|
|
||||||
new google.maps.LatLng(37.784835, -122.399927),
|
|
||||||
new google.maps.LatLng(37.785116, -122.400307),
|
|
||||||
new google.maps.LatLng(37.785282, -122.400539),
|
|
||||||
new google.maps.LatLng(37.785346, -122.400692),
|
|
||||||
new google.maps.LatLng(37.765769, -122.407201),
|
|
||||||
new google.maps.LatLng(37.76579, -122.407414),
|
|
||||||
new google.maps.LatLng(37.765802, -122.407755),
|
|
||||||
new google.maps.LatLng(37.765791, -122.408219),
|
|
||||||
new google.maps.LatLng(37.765763, -122.408759),
|
|
||||||
new google.maps.LatLng(37.765726, -122.409348),
|
|
||||||
new google.maps.LatLng(37.765716, -122.409882),
|
|
||||||
new google.maps.LatLng(37.765708, -122.410202),
|
|
||||||
new google.maps.LatLng(37.765705, -122.410253),
|
|
||||||
new google.maps.LatLng(37.765707, -122.410369),
|
|
||||||
new google.maps.LatLng(37.765692, -122.41072),
|
|
||||||
new google.maps.LatLng(37.765699, -122.411215),
|
|
||||||
new google.maps.LatLng(37.765687, -122.411789),
|
|
||||||
new google.maps.LatLng(37.765666, -122.412373),
|
|
||||||
new google.maps.LatLng(37.765598, -122.412883),
|
|
||||||
new google.maps.LatLng(37.765543, -122.413039),
|
|
||||||
new google.maps.LatLng(37.765532, -122.413125),
|
|
||||||
new google.maps.LatLng(37.7655, -122.413553),
|
|
||||||
new google.maps.LatLng(37.765448, -122.414053),
|
|
||||||
new google.maps.LatLng(37.765388, -122.414645),
|
|
||||||
new google.maps.LatLng(37.765323, -122.41525),
|
|
||||||
new google.maps.LatLng(37.765303, -122.415847),
|
|
||||||
new google.maps.LatLng(37.765251, -122.416439),
|
|
||||||
new google.maps.LatLng(37.765204, -122.41702),
|
|
||||||
new google.maps.LatLng(37.765172, -122.417556),
|
|
||||||
new google.maps.LatLng(37.765164, -122.418075),
|
|
||||||
new google.maps.LatLng(37.765153, -122.418618),
|
|
||||||
new google.maps.LatLng(37.765136, -122.419112),
|
|
||||||
new google.maps.LatLng(37.765129, -122.419378),
|
|
||||||
new google.maps.LatLng(37.765119, -122.419481),
|
|
||||||
new google.maps.LatLng(37.7651, -122.419852),
|
|
||||||
new google.maps.LatLng(37.765083, -122.420349),
|
|
||||||
new google.maps.LatLng(37.765045, -122.42093),
|
|
||||||
new google.maps.LatLng(37.764992, -122.421481),
|
|
||||||
new google.maps.LatLng(37.76498, -122.421695),
|
|
||||||
new google.maps.LatLng(37.764993, -122.421843),
|
|
||||||
new google.maps.LatLng(37.764986, -122.422255),
|
|
||||||
new google.maps.LatLng(37.764975, -122.422823),
|
|
||||||
new google.maps.LatLng(37.764939, -122.423411),
|
|
||||||
new google.maps.LatLng(37.764902, -122.424014),
|
|
||||||
new google.maps.LatLng(37.764853, -122.424576),
|
|
||||||
new google.maps.LatLng(37.764826, -122.424922),
|
|
||||||
new google.maps.LatLng(37.764796, -122.425375),
|
|
||||||
new google.maps.LatLng(37.764782, -122.425869),
|
|
||||||
new google.maps.LatLng(37.764768, -122.426089),
|
|
||||||
new google.maps.LatLng(37.764766, -122.426117),
|
|
||||||
new google.maps.LatLng(37.764723, -122.426276),
|
|
||||||
new google.maps.LatLng(37.764681, -122.426649),
|
|
||||||
new google.maps.LatLng(37.782012, -122.4042),
|
|
||||||
new google.maps.LatLng(37.781574, -122.404911),
|
|
||||||
new google.maps.LatLng(37.781055, -122.405597),
|
|
||||||
new google.maps.LatLng(37.780479, -122.406341),
|
|
||||||
new google.maps.LatLng(37.779996, -122.406939),
|
|
||||||
new google.maps.LatLng(37.779459, -122.407613),
|
|
||||||
new google.maps.LatLng(37.778953, -122.408228),
|
|
||||||
new google.maps.LatLng(37.778409, -122.408839),
|
|
||||||
new google.maps.LatLng(37.777842, -122.409501),
|
|
||||||
new google.maps.LatLng(37.777334, -122.410181),
|
|
||||||
new google.maps.LatLng(37.776809, -122.410836),
|
|
||||||
new google.maps.LatLng(37.77624, -122.411514),
|
|
||||||
new google.maps.LatLng(37.775725, -122.412145),
|
|
||||||
new google.maps.LatLng(37.77519, -122.412805),
|
|
||||||
new google.maps.LatLng(37.774672, -122.413464),
|
|
||||||
new google.maps.LatLng(37.774084, -122.414186),
|
|
||||||
new google.maps.LatLng(37.773533, -122.413636),
|
|
||||||
new google.maps.LatLng(37.773021, -122.413009),
|
|
||||||
new google.maps.LatLng(37.772501, -122.412371),
|
|
||||||
new google.maps.LatLng(37.771964, -122.411681),
|
|
||||||
new google.maps.LatLng(37.771479, -122.411078),
|
|
||||||
new google.maps.LatLng(37.770992, -122.410477),
|
|
||||||
new google.maps.LatLng(37.770467, -122.409801),
|
|
||||||
new google.maps.LatLng(37.77009, -122.408904),
|
|
||||||
new google.maps.LatLng(37.769657, -122.408103),
|
|
||||||
new google.maps.LatLng(37.769132, -122.407276),
|
|
||||||
new google.maps.LatLng(37.768564, -122.406469),
|
|
||||||
new google.maps.LatLng(37.76798, -122.405745),
|
|
||||||
new google.maps.LatLng(37.76738, -122.405299),
|
|
||||||
new google.maps.LatLng(37.766604, -122.405297),
|
|
||||||
new google.maps.LatLng(37.765838, -122.4052),
|
|
||||||
new google.maps.LatLng(37.765139, -122.405139),
|
|
||||||
new google.maps.LatLng(37.764457, -122.405094),
|
|
||||||
new google.maps.LatLng(37.763716, -122.405142),
|
|
||||||
new google.maps.LatLng(37.762932, -122.405398),
|
|
||||||
new google.maps.LatLng(37.762126, -122.405813),
|
|
||||||
new google.maps.LatLng(37.761344, -122.406215),
|
|
||||||
new google.maps.LatLng(37.760556, -122.406495),
|
|
||||||
new google.maps.LatLng(37.759732, -122.406484),
|
|
||||||
new google.maps.LatLng(37.75891, -122.406228),
|
|
||||||
new google.maps.LatLng(37.758182, -122.405695),
|
|
||||||
new google.maps.LatLng(37.757676, -122.405118),
|
|
||||||
new google.maps.LatLng(37.757039, -122.404346),
|
|
||||||
new google.maps.LatLng(37.756335, -122.403719),
|
|
||||||
new google.maps.LatLng(37.755503, -122.403406),
|
|
||||||
new google.maps.LatLng(37.754665, -122.403242),
|
|
||||||
new google.maps.LatLng(37.753837, -122.403172),
|
|
||||||
new google.maps.LatLng(37.752986, -122.403112),
|
|
||||||
new google.maps.LatLng(37.751266, -122.403355),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
// [END maps_layer_heatmap]
|
|
||||||
export { initMap };
|
|
@ -1,21 +0,0 @@
|
|||||||
import { Map, GoogleApiWrapper } from 'google-maps-react';
|
|
||||||
|
|
||||||
export function Heatmap() {
|
|
||||||
const mapStyles = {
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Map
|
|
||||||
google={this.props.google}
|
|
||||||
zoom={8}
|
|
||||||
style={mapStyles}
|
|
||||||
initialCenter={{ lat: 47.444, lng: -122.176 }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GoogleApiWrapper({
|
|
||||||
apiKey: 'AIzaSyCZ51VFfxqZ2GkCmVrcNZdUKsM0fuBQUCY'
|
|
||||||
});
|
|
12
Birdmap.API/ClientApp/src/contexts/DevicesContext.js
Normal file
12
Birdmap.API/ClientApp/src/contexts/DevicesContext.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default React.createContext({
|
||||||
|
devices: [],
|
||||||
|
heatmapPoints: [],
|
||||||
|
|
||||||
|
addHandler: (_, __) => { },
|
||||||
|
removeHandler: (_, __) => { },
|
||||||
|
|
||||||
|
updateDevice: () => { },
|
||||||
|
updateAllDevices: () => { },
|
||||||
|
});
|
148
Birdmap.API/ClientApp/src/contexts/DevicesContextProvider.js
Normal file
148
Birdmap.API/ClientApp/src/contexts/DevicesContextProvider.js
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
import Context from './DevicesContext'
|
||||||
|
import { HubConnectionBuilder } from '@microsoft/signalr';
|
||||||
|
import DeviceService from '../common/DeviceService';
|
||||||
|
import C from '../common/Constants'
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
|
||||||
|
const hub_url = '/hubs/devices';
|
||||||
|
|
||||||
|
export default class DevicesContextProvider extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
const handlers = {};
|
||||||
|
for (var property in C) {
|
||||||
|
handlers[C[property]] = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
hubConnection: null,
|
||||||
|
devices: [],
|
||||||
|
heatmapPoints: [],
|
||||||
|
handlers: handlers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addHandler = (methodName, handler) => {
|
||||||
|
const updatedHandlers = this.state.handlers;
|
||||||
|
updatedHandlers[methodName].push(handler);
|
||||||
|
//console.log("Added '" + methodName + "' handler.");
|
||||||
|
this.setState({ handlers: updatedHandlers });
|
||||||
|
}
|
||||||
|
|
||||||
|
removeHandler = (methodName, handler) => {
|
||||||
|
const updatedHandlers = this.state.handlers;
|
||||||
|
var index = updatedHandlers[methodName].findIndex((h => h === handler));
|
||||||
|
if (index > -1) {
|
||||||
|
updatedHandlers[methodName].splice(index, 1);
|
||||||
|
//console.log("Removed '" + methodName + "' handler.");
|
||||||
|
}
|
||||||
|
this.setState({ handlers: updatedHandlers });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDevice = (id) => {
|
||||||
|
this.updateDeviceInternal(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAllDevices = () => {
|
||||||
|
this.updateAllDevicesInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeHandlers(methodName, context) {
|
||||||
|
this.state.handlers[methodName].forEach(function (handler) {
|
||||||
|
handler(context);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAllDevicesInternal(service = null) {
|
||||||
|
if (service === null) {
|
||||||
|
service = new DeviceService();
|
||||||
|
}
|
||||||
|
service.getall().then(result => {
|
||||||
|
this.setState({ devices: result });
|
||||||
|
}).catch(ex => {
|
||||||
|
console.log(ex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDeviceInternal(id, service = null) {
|
||||||
|
if (service === null) {
|
||||||
|
service = new DeviceService();
|
||||||
|
}
|
||||||
|
service.getdevice(id).then(result => {
|
||||||
|
const updatedDevices = [...this.state.devices];
|
||||||
|
var index = updatedDevices.findIndex((d => d.id == id));
|
||||||
|
if (index > -1) {
|
||||||
|
updatedDevices[index] = result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updatedDevices.push(result);
|
||||||
|
}
|
||||||
|
this.setState({ devices: updatedDevices });
|
||||||
|
this.invokeHandlers(C.update_method_name, result);
|
||||||
|
}).catch(ex => console.log("Device update failed.", ex));
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const service = new DeviceService();
|
||||||
|
this.updateAllDevicesInternal(service);
|
||||||
|
|
||||||
|
const newConnection = new HubConnectionBuilder()
|
||||||
|
.withUrl(hub_url)
|
||||||
|
.withAutomaticReconnect()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
this.setState({ hubConnection: newConnection });
|
||||||
|
|
||||||
|
newConnection.start()
|
||||||
|
.then(_ => {
|
||||||
|
console.log('Hub Connected!');
|
||||||
|
|
||||||
|
newConnection.on(C.probability_method_name, (id, date, prob) => {
|
||||||
|
//console.log(method_name + " recieved: [id: " + id + ", date: " + date + ", prob: " + prob + "]");
|
||||||
|
var device = this.state.devices.filter(function (x) { return x.id === id })[0]
|
||||||
|
var newPoint = { lat: device.coordinates.latitude, lng: device.coordinates.longitude, prob: prob, date: date };
|
||||||
|
this.setState({
|
||||||
|
heatmapPoints: [...this.state.heatmapPoints, newPoint]
|
||||||
|
});
|
||||||
|
|
||||||
|
this.invokeHandlers(C.probability_method_name, newPoint);
|
||||||
|
});
|
||||||
|
|
||||||
|
newConnection.on(C.update_all_method_name, () => {
|
||||||
|
this.updateAllDevicesInternal(service);
|
||||||
|
this.invokeHandlers(C.update_all_method_name, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
newConnection.on(C.update_method_name, (id) => this.updateDeviceInternal(id, service));
|
||||||
|
}).catch(e => console.log('Hub Connection failed: ', e));
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.state.hubConnection != null) {
|
||||||
|
this.state.hubConnection.off(C.probability_method_name);
|
||||||
|
this.state.hubConnection.off(C.update_all_method_name);
|
||||||
|
this.state.hubConnection.off(C.update_method_name);
|
||||||
|
console.log('Hub Disconnected!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Context.Provider
|
||||||
|
value={{
|
||||||
|
devices: this.state.devices,
|
||||||
|
heatmapPoints: this.state.heatmapPoints,
|
||||||
|
|
||||||
|
addHandler: this.addHandler,
|
||||||
|
removeHandler: this.removeHandler,
|
||||||
|
|
||||||
|
updateDevice: this.updateDevice,
|
||||||
|
updateAllDevices: this.updateAllDevices,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{this.props.children}
|
||||||
|
</Context.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
@ -7,20 +7,25 @@ using System.Collections.Generic;
|
|||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Birdmap.API.Services.Hubs;
|
||||||
|
using Birdmap.API.Services;
|
||||||
|
|
||||||
namespace Birdmap.API.Controllers
|
namespace Birdmap.API.Controllers
|
||||||
{
|
{
|
||||||
[Authorize]
|
[Authorize(Roles = "User, Admin")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class DevicesController : ControllerBase
|
public class DevicesController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly IDeviceService _service;
|
private readonly IDeviceService _service;
|
||||||
|
private readonly IHubContext<DevicesHub, IDevicesHubClient> _hubContext;
|
||||||
private readonly ILogger<ServicesController> _logger;
|
private readonly ILogger<ServicesController> _logger;
|
||||||
|
|
||||||
public DevicesController(IDeviceService service, ILogger<ServicesController> logger)
|
public DevicesController(IDeviceService service, IHubContext<DevicesHub, IDevicesHubClient> hubContext, ILogger<ServicesController> logger)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
|
_hubContext = hubContext;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,24 +41,28 @@ namespace Birdmap.API.Controllers
|
|||||||
|
|
||||||
/// <summary>Shut down all devices</summary>
|
/// <summary>Shut down all devices</summary>
|
||||||
/// <returns>Message sent</returns>
|
/// <returns>Message sent</returns>
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, Route("offline")]
|
[HttpPost, Route("offline")]
|
||||||
public async Task<IActionResult> Offlineall()
|
public async Task<IActionResult> Offlineall()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Turning off all devices and sensors...");
|
_logger.LogInformation("Turning off all devices and sensors...");
|
||||||
|
|
||||||
await _service.OfflineallAsync();
|
await _service.OfflineallAsync();
|
||||||
|
await _hubContext.Clients.All.NotifyAllUpdatedAsync();
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Bring all devices online</summary>
|
/// <summary>Bring all devices online</summary>
|
||||||
/// <returns>Message sent</returns>
|
/// <returns>Message sent</returns>
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, Route("online")]
|
[HttpPost, Route("online")]
|
||||||
public async Task<IActionResult> Onlineall()
|
public async Task<IActionResult> Onlineall()
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Turning on all devices and sensors...");
|
_logger.LogInformation("Turning on all devices and sensors...");
|
||||||
|
|
||||||
await _service.OnlineallAsync();
|
await _service.OnlineallAsync();
|
||||||
|
await _hubContext.Clients.All.NotifyAllUpdatedAsync();
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -72,12 +81,14 @@ namespace Birdmap.API.Controllers
|
|||||||
/// <summary>Shut down device</summary>
|
/// <summary>Shut down device</summary>
|
||||||
/// <param name="deviceID">ID of device to shut down</param>
|
/// <param name="deviceID">ID of device to shut down</param>
|
||||||
/// <returns>Message sent</returns>
|
/// <returns>Message sent</returns>
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, Route("{deviceID}/offline")]
|
[HttpPost, Route("{deviceID}/offline")]
|
||||||
public async Task<IActionResult> Offlinedevice([BindRequired] Guid deviceID)
|
public async Task<IActionResult> Offlinedevice([BindRequired] Guid deviceID)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Turning off device [{deviceID}]...");
|
_logger.LogInformation($"Turning off device [{deviceID}]...");
|
||||||
|
|
||||||
await _service.OfflinedeviceAsync(deviceID);
|
await _service.OfflinedeviceAsync(deviceID);
|
||||||
|
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -85,12 +96,14 @@ namespace Birdmap.API.Controllers
|
|||||||
/// <summary>Bring device online</summary>
|
/// <summary>Bring device online</summary>
|
||||||
/// <param name="deviceID">ID of device to bring online</param>
|
/// <param name="deviceID">ID of device to bring online</param>
|
||||||
/// <returns>Message sent</returns>
|
/// <returns>Message sent</returns>
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, Route("{deviceID}/online")]
|
[HttpPost, Route("{deviceID}/online")]
|
||||||
public async Task<IActionResult> Onlinedevice([BindRequired] Guid deviceID)
|
public async Task<IActionResult> Onlinedevice([BindRequired] Guid deviceID)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Turning on device [{deviceID}]...");
|
_logger.LogInformation($"Turning on device [{deviceID}]...");
|
||||||
|
|
||||||
await _service.OnlinedeviceAsync(deviceID);
|
await _service.OnlinedeviceAsync(deviceID);
|
||||||
|
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -111,12 +124,14 @@ namespace Birdmap.API.Controllers
|
|||||||
/// <param name="deviceID">ID of device to query</param>
|
/// <param name="deviceID">ID of device to query</param>
|
||||||
/// <param name="sensorID">ID of sensor to query</param>
|
/// <param name="sensorID">ID of sensor to query</param>
|
||||||
/// <returns>Message sent</returns>
|
/// <returns>Message sent</returns>
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, Route("{deviceID}/{sensorID}/offline")]
|
[HttpPost, Route("{deviceID}/{sensorID}/offline")]
|
||||||
public async Task<IActionResult> Offlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
public async Task<IActionResult> Offlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Turning off sensor [{sensorID}] of device [{deviceID}]...");
|
_logger.LogInformation($"Turning off sensor [{sensorID}] of device [{deviceID}]...");
|
||||||
|
|
||||||
await _service.OfflinesensorAsync(deviceID, sensorID);
|
await _service.OfflinesensorAsync(deviceID, sensorID);
|
||||||
|
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
@ -125,12 +140,14 @@ namespace Birdmap.API.Controllers
|
|||||||
/// <param name="deviceID">ID of device to query</param>
|
/// <param name="deviceID">ID of device to query</param>
|
||||||
/// <param name="sensorID">ID of sensor to query</param>
|
/// <param name="sensorID">ID of sensor to query</param>
|
||||||
/// <returns>Message sent</returns>
|
/// <returns>Message sent</returns>
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, Route("{deviceID}/{sensorID}/online")]
|
[HttpPost, Route("{deviceID}/{sensorID}/online")]
|
||||||
public async Task<IActionResult> Onlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
public async Task<IActionResult> Onlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"Turning on sensor [{sensorID}] of device [{deviceID}]...");
|
_logger.LogInformation($"Turning on sensor [{sensorID}] of device [{deviceID}]...");
|
||||||
|
|
||||||
await _service.OnlinesensorAsync(deviceID, sensorID);
|
await _service.OnlinesensorAsync(deviceID, sensorID);
|
||||||
|
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Birdmap.API.Controllers
|
namespace Birdmap.API.Controllers
|
||||||
{
|
{
|
||||||
[Authorize]
|
[Authorize(Roles = "User, Admin")]
|
||||||
[ApiController]
|
[ApiController]
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class ServicesController : ControllerBase
|
public class ServicesController : ControllerBase
|
||||||
@ -58,6 +58,7 @@ namespace Birdmap.API.Controllers
|
|||||||
return serviceInfos.ToList();
|
return serviceInfos.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPost, ProducesResponseType(StatusCodes.Status201Created)]
|
[HttpPost, ProducesResponseType(StatusCodes.Status201Created)]
|
||||||
public async Task<ActionResult<ServiceRequest>> PostAsync(ServiceRequest request)
|
public async Task<ActionResult<ServiceRequest>> PostAsync(ServiceRequest request)
|
||||||
{
|
{
|
||||||
@ -72,6 +73,7 @@ namespace Birdmap.API.Controllers
|
|||||||
_mapper.Map<ServiceRequest>(created));
|
_mapper.Map<ServiceRequest>(created));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpPut, ProducesResponseType(StatusCodes.Status204NoContent)]
|
[HttpPut, ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public async Task<IActionResult> PutAsync(ServiceRequest request)
|
public async Task<IActionResult> PutAsync(ServiceRequest request)
|
||||||
{
|
{
|
||||||
@ -84,6 +86,7 @@ namespace Birdmap.API.Controllers
|
|||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Authorize(Roles = "Admin")]
|
||||||
[HttpDelete("{id}"), ProducesResponseType(StatusCodes.Status204NoContent)]
|
[HttpDelete("{id}"), ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||||
public async Task<IActionResult> DeleteAsync(int id)
|
public async Task<IActionResult> DeleteAsync(int id)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Birdmap.Models
|
namespace Birdmap.Models
|
||||||
{
|
{
|
||||||
public class AuthenticateRequest
|
public record AuthenticateRequest
|
||||||
{
|
{
|
||||||
[Required(AllowEmptyStrings = false, ErrorMessage = "Username is required.")]
|
[Required(AllowEmptyStrings = false, ErrorMessage = "Username is required.")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
@ -3,7 +3,7 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace Birdmap.API.DTOs
|
namespace Birdmap.API.DTOs
|
||||||
{
|
{
|
||||||
public class AuthenticateResponse
|
public record AuthenticateResponse
|
||||||
{
|
{
|
||||||
[JsonProperty("user_name")]
|
[JsonProperty("user_name")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Birdmap.API.DTOs
|
namespace Birdmap.API.DTOs
|
||||||
{
|
{
|
||||||
public class RegisterRequest
|
public record RegisterRequest
|
||||||
{
|
{
|
||||||
[Required(AllowEmptyStrings = false, ErrorMessage = "Username is required.")]
|
[Required(AllowEmptyStrings = false, ErrorMessage = "Username is required.")]
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Birdmap.API.DTOs
|
namespace Birdmap.API.DTOs
|
||||||
{
|
{
|
||||||
public class ServiceInfo
|
public record ServiceInfo
|
||||||
{
|
{
|
||||||
public ServiceRequest Service { get; set; }
|
public ServiceRequest Service { get; set; }
|
||||||
public HttpStatusCode StatusCode { get; set; }
|
public HttpStatusCode StatusCode { get; set; }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
namespace Birdmap.API.DTOs
|
namespace Birdmap.API.DTOs
|
||||||
{
|
{
|
||||||
public class ServiceRequest
|
public record ServiceRequest
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
33
Birdmap.API/Extensions/ServiceCollectionExtensions.cs
Normal file
33
Birdmap.API/Extensions/ServiceCollectionExtensions.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using Birdmap.API.Options;
|
||||||
|
using Birdmap.API.Services.Mqtt;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Birdmap.API.Extensions
|
||||||
|
{
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddMqttClientServiceWithConfig(this IServiceCollection services, Action<AspCoreMqttClientOptions> configureOptions)
|
||||||
|
{
|
||||||
|
services.AddSingleton(serviceProvider =>
|
||||||
|
{
|
||||||
|
var optionBuilder = new AspCoreMqttClientOptions(serviceProvider);
|
||||||
|
configureOptions(optionBuilder);
|
||||||
|
return optionBuilder.Build();
|
||||||
|
});
|
||||||
|
services.AddSingleton<MqttClientService>();
|
||||||
|
services.AddSingleton<IHostedService>(serviceProvider =>
|
||||||
|
{
|
||||||
|
return serviceProvider.GetService<MqttClientService>();
|
||||||
|
});
|
||||||
|
services.AddSingleton(serviceProvider =>
|
||||||
|
{
|
||||||
|
var mqttClientService = serviceProvider.GetService<MqttClientService>();
|
||||||
|
var mqttClientServiceProvider = new MqttClientServiceProvider(mqttClientService);
|
||||||
|
return mqttClientServiceProvider;
|
||||||
|
});
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
Birdmap.API/Options/AspCoreMqttClientOptions.cs
Normal file
22
Birdmap.API/Options/AspCoreMqttClientOptions.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using MQTTnet.Client.Options;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Birdmap.API.Options
|
||||||
|
{
|
||||||
|
public class AspCoreMqttClientOptions : MqttClientOptionsBuilder
|
||||||
|
{
|
||||||
|
public IServiceProvider ServiceProvider { get; }
|
||||||
|
|
||||||
|
public AspCoreMqttClientOptions(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
ServiceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AspCoreMqttClientOptions WithTopic(string topic)
|
||||||
|
{
|
||||||
|
WithUserProperty("Topic", topic);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
using Birdmap.API;
|
|
||||||
using Birdmap.DAL;
|
using Birdmap.DAL;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@ -8,7 +7,7 @@ using NLog;
|
|||||||
using NLog.Web;
|
using NLog.Web;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Birdmap
|
namespace Birdmap.API
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
|
46
Birdmap.API/Services/Hubs/DevicesHub.cs
Normal file
46
Birdmap.API/Services/Hubs/DevicesHub.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Birdmap.API.Services.Hubs
|
||||||
|
{
|
||||||
|
public class DevicesHub : Hub<IDevicesHubClient>
|
||||||
|
{
|
||||||
|
private readonly ILogger<DevicesHub> _logger;
|
||||||
|
|
||||||
|
public DevicesHub(ILogger<DevicesHub> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnConnectedAsync()
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Hub Client connected.");
|
||||||
|
|
||||||
|
return base.OnConnectedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task OnDisconnectedAsync(Exception exception)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Hub Client disconnected.");
|
||||||
|
|
||||||
|
return base.OnDisconnectedAsync(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SendProbabilityAsync(Guid deviceId, DateTime date, double probability)
|
||||||
|
{
|
||||||
|
return Clients.All.NotifyDeviceAsync(deviceId, date, probability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SendDeviceUpdateAsync(Guid deviceId)
|
||||||
|
{
|
||||||
|
return Clients.All.NotifyDeviceUpdatedAsync(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SendAllUpdatedAsync()
|
||||||
|
{
|
||||||
|
return Clients.All.NotifyAllUpdatedAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Birdmap.API/Services/Hubs/IDevicesHubClient.cs
Normal file
12
Birdmap.API/Services/Hubs/IDevicesHubClient.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Birdmap.API.Services
|
||||||
|
{
|
||||||
|
public interface IDevicesHubClient
|
||||||
|
{
|
||||||
|
Task NotifyDeviceAsync(Guid deviceId, DateTime date, double probability);
|
||||||
|
Task NotifyDeviceUpdatedAsync(Guid deviceId);
|
||||||
|
Task NotifyAllUpdatedAsync();
|
||||||
|
}
|
||||||
|
}
|
15
Birdmap.API/Services/IMqttClientService.cs
Normal file
15
Birdmap.API/Services/IMqttClientService.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using MQTTnet.Client.Connecting;
|
||||||
|
using MQTTnet.Client.Disconnecting;
|
||||||
|
using MQTTnet.Client.Receiving;
|
||||||
|
|
||||||
|
namespace Birdmap.API.Services
|
||||||
|
{
|
||||||
|
public interface IMqttClientService : IHostedService,
|
||||||
|
IMqttClientConnectedHandler,
|
||||||
|
IMqttClientDisconnectedHandler,
|
||||||
|
IMqttApplicationMessageReceivedHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
141
Birdmap.API/Services/Mqtt/MqttClientService.cs
Normal file
141
Birdmap.API/Services/Mqtt/MqttClientService.cs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
using Birdmap.API.Services.Hubs;
|
||||||
|
using Birdmap.BLL.Interfaces;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MQTTnet;
|
||||||
|
using MQTTnet.Client;
|
||||||
|
using MQTTnet.Client.Connecting;
|
||||||
|
using MQTTnet.Client.Disconnecting;
|
||||||
|
using MQTTnet.Client.Options;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Birdmap.API.Services.Mqtt
|
||||||
|
{
|
||||||
|
public class MqttClientService : IMqttClientService
|
||||||
|
{
|
||||||
|
private readonly IMqttClient _mqttClient;
|
||||||
|
private readonly IMqttClientOptions _options;
|
||||||
|
private readonly ILogger<MqttClientService> _logger;
|
||||||
|
private readonly IInputService _inputService;
|
||||||
|
private readonly IHubContext<DevicesHub, IDevicesHubClient> _hubContext;
|
||||||
|
|
||||||
|
public MqttClientService(IMqttClientOptions options, ILogger<MqttClientService> logger, IInputService inputService, IHubContext<DevicesHub, IDevicesHubClient> hubContext)
|
||||||
|
{
|
||||||
|
_options = options;
|
||||||
|
_logger = logger;
|
||||||
|
_inputService = inputService;
|
||||||
|
_hubContext = hubContext;
|
||||||
|
_mqttClient = new MqttFactory().CreateMqttClient();
|
||||||
|
ConfigureMqttClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureMqttClient()
|
||||||
|
{
|
||||||
|
_mqttClient.ConnectedHandler = this;
|
||||||
|
_mqttClient.DisconnectedHandler = this;
|
||||||
|
_mqttClient.ApplicationMessageReceivedHandler = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Payload
|
||||||
|
{
|
||||||
|
[JsonProperty("tag")]
|
||||||
|
public Guid TagID { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("probability")]
|
||||||
|
public double Probability { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
var message = eventArgs.ApplicationMessage.ConvertPayloadToString();
|
||||||
|
|
||||||
|
_logger.LogInformation($"Recieved [{eventArgs.ClientId}] " +
|
||||||
|
$"Topic: {eventArgs.ApplicationMessage.Topic} | Payload: {message} | QoS: {eventArgs.ApplicationMessage.QualityOfServiceLevel} | Retain: {eventArgs.ApplicationMessage.Retain}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var payload = JsonConvert.DeserializeObject<Payload>(message);
|
||||||
|
var inputResponse = await _inputService.GetInputAsync(payload.TagID);
|
||||||
|
|
||||||
|
await _hubContext.Clients.All.NotifyDeviceAsync(inputResponse.Message.Device_id, inputResponse.Message.Date.UtcDateTime, payload.Probability);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Could not handle application message.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleConnectedAsync(MqttClientConnectedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var topic = _options.UserProperties.SingleOrDefault(up => up.Name == "Topic")?.Value;
|
||||||
|
_logger.LogInformation($"Connected. Auth result: {eventArgs.AuthenticateResult}. Subscribing to topic: {topic}");
|
||||||
|
|
||||||
|
await _mqttClient.SubscribeAsync(topic);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Cannot subscribe...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleDisconnectedAsync(MqttClientDisconnectedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(eventArgs.Exception, $"Disconnected. Reason {eventArgs.ReasonCode}. Auth result: {eventArgs.AuthenticateResult}. Reconnecting...");
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _mqttClient.ConnectAsync(_options, CancellationToken.None);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Reconnect failed...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _mqttClient.ConnectAsync(_options);
|
||||||
|
if (!_mqttClient.IsConnected)
|
||||||
|
{
|
||||||
|
await _mqttClient.ReconnectAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Cannot connect...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
var disconnectOption = new MqttClientDisconnectOptions
|
||||||
|
{
|
||||||
|
ReasonCode = MqttClientDisconnectReason.NormalDisconnection,
|
||||||
|
ReasonString = "NormalDiconnection"
|
||||||
|
};
|
||||||
|
await _mqttClient.DisconnectAsync(disconnectOption, cancellationToken);
|
||||||
|
}
|
||||||
|
await _mqttClient.DisconnectAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, $"Cannot disconnect...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
Birdmap.API/Services/Mqtt/MqttClientServiceProvider.cs
Normal file
12
Birdmap.API/Services/Mqtt/MqttClientServiceProvider.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Birdmap.API.Services.Mqtt
|
||||||
|
{
|
||||||
|
public class MqttClientServiceProvider
|
||||||
|
{
|
||||||
|
public IMqttClientService MqttClientService { get; }
|
||||||
|
|
||||||
|
public MqttClientServiceProvider(IMqttClientService mqttClientService)
|
||||||
|
{
|
||||||
|
MqttClientService = mqttClientService;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Birdmap.API;
|
using Birdmap.API.Extensions;
|
||||||
using Birdmap.API.Middlewares;
|
using Birdmap.API.Middlewares;
|
||||||
|
using Birdmap.API.Services.Hubs;
|
||||||
using Birdmap.BLL;
|
using Birdmap.BLL;
|
||||||
using Birdmap.DAL;
|
using Birdmap.DAL;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
@ -11,9 +12,10 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using NSwag.Generation.Processors.Security;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Birdmap
|
namespace Birdmap.API
|
||||||
{
|
{
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
@ -40,6 +42,8 @@ namespace Birdmap
|
|||||||
|
|
||||||
services.AddAutoMapper(typeof(Startup));
|
services.AddAutoMapper(typeof(Startup));
|
||||||
|
|
||||||
|
services.AddSignalR();
|
||||||
|
|
||||||
var key = Encoding.ASCII.GetBytes(Configuration["Secret"]);
|
var key = Encoding.ASCII.GetBytes(Configuration["Secret"]);
|
||||||
services.AddAuthentication(opt =>
|
services.AddAuthentication(opt =>
|
||||||
{
|
{
|
||||||
@ -48,7 +52,7 @@ namespace Birdmap
|
|||||||
})
|
})
|
||||||
.AddJwtBearer(opt =>
|
.AddJwtBearer(opt =>
|
||||||
{
|
{
|
||||||
// opt.RequireHttpsMetadata = false;
|
//opt.RequireHttpsMetadata = false;
|
||||||
opt.SaveToken = true;
|
opt.SaveToken = true;
|
||||||
opt.IncludeErrorDetails = true;
|
opt.IncludeErrorDetails = true;
|
||||||
opt.TokenValidationParameters = new TokenValidationParameters
|
opt.TokenValidationParameters = new TokenValidationParameters
|
||||||
@ -60,11 +64,52 @@ namespace Birdmap
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddMqttClientServiceWithConfig(opt =>
|
||||||
|
{
|
||||||
|
var mqtt = Configuration.GetSection("Mqtt");
|
||||||
|
|
||||||
|
var mqttClient = mqtt.GetSection("ClientSettings");
|
||||||
|
var clientSettings = new
|
||||||
|
{
|
||||||
|
Id = mqttClient.GetValue<string>("Id"),
|
||||||
|
Username = mqttClient.GetValue<string>("Username"),
|
||||||
|
Password = mqttClient.GetValue<string>("Password"),
|
||||||
|
Topic = mqttClient.GetValue<string>("Topic"),
|
||||||
|
};
|
||||||
|
|
||||||
|
var mqttBrokerHost = mqtt.GetSection("BrokerHostSettings");
|
||||||
|
var brokerHostSettings = new
|
||||||
|
{
|
||||||
|
Host = mqttBrokerHost.GetValue<string>("Host"),
|
||||||
|
Port = mqttBrokerHost.GetValue<int>("Port"),
|
||||||
|
};
|
||||||
|
|
||||||
|
opt
|
||||||
|
.WithTopic(clientSettings.Topic)
|
||||||
|
.WithCredentials(clientSettings.Username, clientSettings.Password)
|
||||||
|
.WithClientId(clientSettings.Id)
|
||||||
|
.WithTcpServer(brokerHostSettings.Host, brokerHostSettings.Port);
|
||||||
|
});
|
||||||
|
|
||||||
// In production, the React files will be served from this directory
|
// In production, the React files will be served from this directory
|
||||||
services.AddSpaStaticFiles(configuration =>
|
services.AddSpaStaticFiles(configuration =>
|
||||||
{
|
{
|
||||||
configuration.RootPath = "ClientApp/build";
|
configuration.RootPath = "ClientApp/build";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddSwaggerDocument(opt =>
|
||||||
|
{
|
||||||
|
opt.Title = "Birdmap";
|
||||||
|
opt.OperationProcessors.Add(new OperationSecurityScopeProcessor("Jwt Token"));
|
||||||
|
opt.AddSecurity("Jwt Token", new string[] { },
|
||||||
|
new NSwag.OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Type = NSwag.OpenApiSecuritySchemeType.ApiKey,
|
||||||
|
Name = "Authorization",
|
||||||
|
In = NSwag.OpenApiSecurityApiKeyLocation.Header,
|
||||||
|
Description = "Bearer {token}",
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -74,24 +119,26 @@ namespace Birdmap
|
|||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
app.UseMiddleware<ExceptionHandlerMiddleware>();
|
||||||
app.UseMiddleware<ExceptionHandlerMiddleware>();
|
|
||||||
}
|
app.UseOpenApi();
|
||||||
|
app.UseSwaggerUi3();
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
app.UseSpaStaticFiles();
|
app.UseSpaStaticFiles();
|
||||||
|
|
||||||
app.UseRouting();
|
|
||||||
|
|
||||||
app.UseAuthorization();
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
app.UseRouting();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapHealthChecks("/health");
|
endpoints.MapHealthChecks("/health");
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
|
endpoints.MapHub<DevicesHub>("/hubs/devices");
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseSpa(spa =>
|
app.UseSpa(spa =>
|
||||||
|
@ -28,5 +28,18 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"UseDummyServices": true
|
"UseDummyServices": true,
|
||||||
|
"Mqtt": {
|
||||||
|
"BrokerHostSettings": {
|
||||||
|
"Host": "localhost",
|
||||||
|
"Port": 1883
|
||||||
|
},
|
||||||
|
|
||||||
|
"ClientSettings": {
|
||||||
|
"Id": "ASP.NET Core client",
|
||||||
|
"Username": "username",
|
||||||
|
"Password": "password",
|
||||||
|
"Topic": "devices/output"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,22 +14,34 @@
|
|||||||
<!-- the targets to write to -->
|
<!-- the targets to write to -->
|
||||||
<targets async="true">
|
<targets async="true">
|
||||||
<default-target-parameters xsi:type="File" keepFileOpen="false" maxArchiveFiles="10" archiveAboveSize="1048576"/>
|
<default-target-parameters xsi:type="File" keepFileOpen="false" maxArchiveFiles="10" archiveAboveSize="1048576"/>
|
||||||
<target xsi:type="File" name="allfile" fileName="${basedir}Log/birdmap-all-${shortdate}.log"
|
<target xsi:type="File" name="allFile" fileName="${basedir}Log/birdmap-all-${shortdate}.log"
|
||||||
layout="${longdate} [${event-properties:item=EventId_Id}] ${uppercase:${level}} ${logger} - ${message} ${exception:format=tostring}" />
|
layout="${longdate} [${threadname:whenEmpty=${threadid}}] ${uppercase:${level}} ${logger} - ${message} ${exception:format=tostring}" />
|
||||||
|
|
||||||
|
<target xsi:type="File" name="mqttFile" fileName="${basedir}Log/birdmap-mqtt-${shortdate}.log"
|
||||||
|
layout="${longdate} [${threadname:whenEmpty=${threadid}}] ${uppercase:${level}} ${logger} - ${message} ${exception:format=tostring}" />
|
||||||
|
|
||||||
|
<target xsi:type="File" name="hubsFile" fileName="${basedir}Log/birdmap-hubs-${shortdate}.log"
|
||||||
|
layout="${longdate} [${threadname:whenEmpty=${threadid}}] ${uppercase:${level}} ${logger} - ${message} ${exception:format=tostring}" />
|
||||||
|
|
||||||
<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
|
<!-- another file log, only own logs. Uses some ASP.NET core renderers -->
|
||||||
<target xsi:type="File" name="ownFile" fileName="${basedir}Log/birdmap-own-${shortdate}.log"
|
<target xsi:type="File" name="ownFile" fileName="${basedir}Log/birdmap-own-${shortdate}.log"
|
||||||
layout="${longdate} [${event-properties:item=EventId_Id}] ${uppercase:${level}} ${callsite} - ${message} ${exception:format=tostring} (url: ${aspnet-request-url})(action: ${aspnet-mvc-action})" />
|
layout="${longdate} [${threadname:whenEmpty=${threadid}}] ${uppercase:${level}} ${callsite} - ${message} ${exception:format=tostring} (url: ${aspnet-request-url})(action: ${aspnet-mvc-action})" />
|
||||||
</targets>
|
</targets>
|
||||||
|
|
||||||
<!-- rules to map from logger name to target +-->
|
<!-- rules to map from logger name to target +-->
|
||||||
<rules>
|
<rules>
|
||||||
<!--All logs, including from Microsoft-->
|
<!--All logs, including from Microsoft-->
|
||||||
<logger name="*" minlevel="Trace" writeTo="allfile" />
|
<logger name="*" minlevel="Trace" writeTo="allFile" />
|
||||||
|
|
||||||
<!--Skip non-critical Microsoft logs and so log only own logs-->
|
<!--Skip non-critical Mqtt logs-->
|
||||||
|
<logger name="*.*Mqtt*.*" minlevel="Trace" maxlevel="Warning" writeTo="mqttFile" final="true"/>
|
||||||
|
|
||||||
|
<!--Skip non-critical Hub logs-->
|
||||||
|
<logger name="*.*Hubs*.*" minlevel="Trace" maxlevel="Warning" writeTo="hubsFile" final="true"/>
|
||||||
|
|
||||||
|
<!--Skip non-critical Microsoft logs-->
|
||||||
<logger name="Microsoft.*" maxlevel="Info" final="true" />
|
<logger name="Microsoft.*" maxlevel="Info" final="true" />
|
||||||
<!-- BlackHole without writeTo -->
|
|
||||||
<logger name="*" minlevel="Trace" writeTo="ownFile" />
|
<logger name="*" minlevel="Trace" writeTo="ownFile" />
|
||||||
</rules>
|
</rules>
|
||||||
</nlog>
|
</nlog>
|
@ -1,9 +1,13 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Birdmap.Common\Birdmap.Common.csproj" />
|
<ProjectReference Include="..\Birdmap.Common\Birdmap.Common.csproj" />
|
||||||
<ProjectReference Include="..\Birdmap.DAL\Birdmap.DAL.csproj" />
|
<ProjectReference Include="..\Birdmap.DAL\Birdmap.DAL.csproj" />
|
||||||
|
16
Birdmap.BLL/Helpers/IEnumerableExtensions.cs
Normal file
16
Birdmap.BLL/Helpers/IEnumerableExtensions.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Birdmap.BLL.Helpers
|
||||||
|
{
|
||||||
|
public static class IEnumerableExtensions
|
||||||
|
{
|
||||||
|
public static TSource RandomElementAt<TSource>(this IEnumerable<TSource> source, Random random = null)
|
||||||
|
{
|
||||||
|
random ??= new Random();
|
||||||
|
|
||||||
|
return source.ElementAt(random.Next(source.Count()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
163
Birdmap.BLL/Interfaces/IInputService.cs
Normal file
163
Birdmap.BLL/Interfaces/IInputService.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Birdmap.BLL.Interfaces
|
||||||
|
{
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
|
||||||
|
public partial interface IInputService
|
||||||
|
{
|
||||||
|
/// <summary>Get input object by ID</summary>
|
||||||
|
/// <param name="tagID">ID of input object file</param>
|
||||||
|
/// <returns>input object</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
System.Threading.Tasks.Task<InputSingeResponse> GetInputAsync(System.Guid tagID);
|
||||||
|
|
||||||
|
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||||
|
/// <summary>Get input object by ID</summary>
|
||||||
|
/// <param name="tagID">ID of input object file</param>
|
||||||
|
/// <returns>input object</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
System.Threading.Tasks.Task<InputSingeResponse> GetInputAsync(System.Guid tagID, System.Threading.CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||||
|
public partial class InputSingeResponse
|
||||||
|
{
|
||||||
|
[Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required]
|
||||||
|
public InputObject Message { get; set; } = new InputObject();
|
||||||
|
|
||||||
|
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonExtensionData]
|
||||||
|
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
|
||||||
|
{
|
||||||
|
get { return _additionalProperties; }
|
||||||
|
set { _additionalProperties = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||||
|
public partial class InputResponse : System.Collections.ObjectModel.Collection<InputObject>
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||||
|
public partial class InputObject
|
||||||
|
{
|
||||||
|
[Newtonsoft.Json.JsonProperty("tag", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||||
|
public System.Guid Tag { get; set; }
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("date", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||||
|
[Newtonsoft.Json.JsonConverter(typeof(DateFormatConverter))]
|
||||||
|
public System.DateTimeOffset Date { get; set; }
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("device_id", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
public Guid Device_id { get; set; }
|
||||||
|
|
||||||
|
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonExtensionData]
|
||||||
|
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
|
||||||
|
{
|
||||||
|
get { return _additionalProperties; }
|
||||||
|
set { _additionalProperties = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||||
|
public partial class ApiResponse
|
||||||
|
{
|
||||||
|
[Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("message", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonExtensionData]
|
||||||
|
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
|
||||||
|
{
|
||||||
|
get { return _additionalProperties; }
|
||||||
|
set { _additionalProperties = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||||
|
public partial class Description
|
||||||
|
{
|
||||||
|
[Newtonsoft.Json.JsonProperty("deviceid", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
|
||||||
|
public string Deviceid { get; set; }
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("date", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
|
||||||
|
[Newtonsoft.Json.JsonConverter(typeof(DateFormatConverter))]
|
||||||
|
public System.DateTimeOffset Date { get; set; }
|
||||||
|
|
||||||
|
private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonExtensionData]
|
||||||
|
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
|
||||||
|
{
|
||||||
|
get { return _additionalProperties; }
|
||||||
|
set { _additionalProperties = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||||
|
internal class DateFormatConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter
|
||||||
|
{
|
||||||
|
public DateFormatConverter()
|
||||||
|
{
|
||||||
|
DateTimeFormat = "yyyy-MM-dd";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
|
||||||
|
public partial class FileParameter
|
||||||
|
{
|
||||||
|
public FileParameter(System.IO.Stream data)
|
||||||
|
: this(data, null, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileParameter(System.IO.Stream data, string fileName)
|
||||||
|
: this(data, fileName, null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileParameter(System.IO.Stream data, string fileName, string contentType)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
FileName = fileName;
|
||||||
|
ContentType = contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public System.IO.Stream Data { get; private set; }
|
||||||
|
|
||||||
|
public string FileName { get; private set; }
|
||||||
|
|
||||||
|
public string ContentType { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,8 +6,12 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Birdmap.BLL.Services
|
namespace Birdmap.BLL.Services
|
||||||
{
|
{
|
||||||
public abstract class DeviceServiceBase : IDeviceService
|
public abstract class DeviceAndInputServiceBase : IDeviceService, IInputService
|
||||||
{
|
{
|
||||||
|
public virtual Task<InputSingeResponse> GetInputAsync(Guid tagID)
|
||||||
|
=> GetInputAsync(tagID, CancellationToken.None);
|
||||||
|
public abstract Task<InputSingeResponse> GetInputAsync(Guid tagID, CancellationToken cancellationToken);
|
||||||
|
|
||||||
public virtual Task<ICollection<Device>> GetallAsync()
|
public virtual Task<ICollection<Device>> GetallAsync()
|
||||||
=> GetallAsync(CancellationToken.None);
|
=> GetallAsync(CancellationToken.None);
|
||||||
public abstract Task<ICollection<Device>> GetallAsync(CancellationToken cancellationToken);
|
public abstract Task<ICollection<Device>> GetallAsync(CancellationToken cancellationToken);
|
@ -1,4 +1,5 @@
|
|||||||
using Birdmap.BLL.Interfaces;
|
using Birdmap.BLL.Helpers;
|
||||||
|
using Birdmap.BLL.Interfaces;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -7,33 +8,40 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Birdmap.BLL.Services
|
namespace Birdmap.BLL.Services
|
||||||
{
|
{
|
||||||
public class DummyDeviceService : DeviceServiceBase
|
public class DummyDeviceAndInputService : DeviceAndInputServiceBase
|
||||||
{
|
{
|
||||||
|
private const int numberOfDevices = 15;
|
||||||
|
|
||||||
private const double centerLong = 21.469640;
|
private const double centerLong = 21.469640;
|
||||||
private const double centerLat = 48.275939;
|
private const double centerLat = 48.275939;
|
||||||
private const double radius = 0.000200;
|
private const double radius = 0.001;
|
||||||
|
|
||||||
|
private static readonly Random Rand = new Random();
|
||||||
|
|
||||||
|
private static readonly Lazy<ICollection<Device>> Devices = new Lazy<ICollection<Device>>(GenerateDevices);
|
||||||
|
|
||||||
|
private static readonly Dictionary<Guid, InputSingeResponse> TagToInput = new Dictionary<Guid, InputSingeResponse>();
|
||||||
|
private static readonly object InputLock = new object();
|
||||||
|
|
||||||
private readonly Lazy<ICollection<Device>> _devices = new Lazy<ICollection<Device>>(GenerateDevices);
|
|
||||||
private static ListOfDevices GenerateDevices()
|
private static ListOfDevices GenerateDevices()
|
||||||
{
|
{
|
||||||
var devices = new ListOfDevices();
|
var devices = new ListOfDevices();
|
||||||
var rand = new Random();
|
|
||||||
|
|
||||||
T GetRandomEnum<T>()
|
T GetRandomEnum<T>()
|
||||||
{
|
{
|
||||||
var values = Enum.GetValues(typeof(T));
|
var values = Enum.GetValues(typeof(T));
|
||||||
return (T)values.GetValue(rand.Next(values.Length));
|
return (T)values.GetValue(Rand.Next(values.Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetPlusMinus(double center, double radius)
|
double GetPlusMinus(double center, double radius)
|
||||||
{
|
{
|
||||||
return center - radius + rand.NextDouble() * radius * 2;
|
return center - radius + Rand.NextDouble() * radius * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int d = 0; d < 15; d++)
|
for (int d = 0; d < numberOfDevices; d++)
|
||||||
{
|
{
|
||||||
var sensors = new ArrayofSensors();
|
var sensors = new ArrayofSensors();
|
||||||
for (int s = 0; s < rand.Next(1, 5); s++)
|
for (int s = 0; s < Rand.Next(1, 6); s++)
|
||||||
{
|
{
|
||||||
sensors.Add(new Sensor
|
sensors.Add(new Sensor
|
||||||
{
|
{
|
||||||
@ -61,17 +69,17 @@ namespace Birdmap.BLL.Services
|
|||||||
|
|
||||||
public override Task<ICollection<Device>> GetallAsync(CancellationToken cancellationToken)
|
public override Task<ICollection<Device>> GetallAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_devices.Value);
|
return Task.FromResult(Devices.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<Device> GetdeviceAsync(Guid deviceID, CancellationToken cancellationToken)
|
public override Task<Device> GetdeviceAsync(Guid deviceID, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_devices.Value.SingleOrDefault(d => d.Id == deviceID));
|
return Task.FromResult(Devices.Value.SingleOrDefault(d => d.Id == deviceID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<Sensor> GetsensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
|
public override Task<Sensor> GetsensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_devices.Value.SingleOrDefault(d => d.Id == deviceID)?.Sensors.SingleOrDefault(s => s.Id == sensorID));
|
return Task.FromResult(Devices.Value.SingleOrDefault(d => d.Id == deviceID)?.Sensors.SingleOrDefault(s => s.Id == sensorID));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task OfflineallAsync(CancellationToken cancellationToken)
|
public override Task OfflineallAsync(CancellationToken cancellationToken)
|
||||||
@ -114,7 +122,7 @@ namespace Birdmap.BLL.Services
|
|||||||
|
|
||||||
private void SetStatus(DeviceStatus deviceStatus, SensorStatus sensorStatus)
|
private void SetStatus(DeviceStatus deviceStatus, SensorStatus sensorStatus)
|
||||||
{
|
{
|
||||||
foreach (var device in _devices.Value)
|
foreach (var device in Devices.Value)
|
||||||
{
|
{
|
||||||
device.Status = deviceStatus;
|
device.Status = deviceStatus;
|
||||||
foreach (var sensor in device.Sensors)
|
foreach (var sensor in device.Sensors)
|
||||||
@ -135,5 +143,29 @@ namespace Birdmap.BLL.Services
|
|||||||
var sensor = GetsensorAsync(deviceId, sensorID).Result;
|
var sensor = GetsensorAsync(deviceId, sensorID).Result;
|
||||||
sensor.Status = status;
|
sensor.Status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Task<InputSingeResponse> GetInputAsync(Guid tagID, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
lock (InputLock)
|
||||||
|
{
|
||||||
|
if (!TagToInput.TryGetValue(tagID, out var value))
|
||||||
|
{
|
||||||
|
value = new InputSingeResponse
|
||||||
|
{
|
||||||
|
Status = "Dummy_OK",
|
||||||
|
Message = new InputObject
|
||||||
|
{
|
||||||
|
Tag = tagID,
|
||||||
|
Date = DateTime.Now,
|
||||||
|
Device_id = Devices.Value.Where(d => d.Status == DeviceStatus.Online).RandomElementAt(Rand).Id,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TagToInput.TryAdd(tagID, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
|
#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
|
||||||
#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
|
#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
|
||||||
#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
|
#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
|
||||||
|
#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type '...' is never equal to 'null' of type '...?'"
|
||||||
|
|
||||||
namespace Birdmap.BLL.Services
|
namespace Birdmap.BLL.Services
|
||||||
{
|
{
|
||||||
@ -895,6 +896,7 @@ namespace Birdmap.BLL.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma warning restore 8703
|
||||||
#pragma warning restore 1591
|
#pragma warning restore 1591
|
||||||
#pragma warning restore 1573
|
#pragma warning restore 1573
|
||||||
#pragma warning restore 472
|
#pragma warning restore 472
|
||||||
|
479
Birdmap.BLL/Services/LiveInputService.cs
Normal file
479
Birdmap.BLL/Services/LiveInputService.cs
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
//----------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// Generated using the NSwag toolchain v13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0)) (http://NSwag.org)
|
||||||
|
// </auto-generated>
|
||||||
|
//----------------------
|
||||||
|
|
||||||
|
#pragma warning disable 108 // Disable "CS0108 '{derivedDto}.ToJson()' hides inherited member '{dtoBase}.ToJson()'. Use the new keyword if hiding was intended."
|
||||||
|
#pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword."
|
||||||
|
#pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?'
|
||||||
|
#pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ...
|
||||||
|
#pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..."
|
||||||
|
#pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type '...' is never equal to 'null' of type '...?'"
|
||||||
|
|
||||||
|
namespace Birdmap.BLL.Services
|
||||||
|
{
|
||||||
|
using Birdmap.BLL.Interfaces;
|
||||||
|
using System = global::System;
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
|
||||||
|
public partial class LiveInputService : IInputService
|
||||||
|
{
|
||||||
|
private string _baseUrl = "https://birb.k8s.kmlabz.com";
|
||||||
|
private System.Net.Http.HttpClient _httpClient;
|
||||||
|
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
|
||||||
|
|
||||||
|
public LiveInputService(System.Net.Http.HttpClient httpClient)
|
||||||
|
{
|
||||||
|
_httpClient = httpClient;
|
||||||
|
_settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
|
||||||
|
{
|
||||||
|
var settings = new Newtonsoft.Json.JsonSerializerSettings();
|
||||||
|
UpdateJsonSerializerSettings(settings);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BaseUrl
|
||||||
|
{
|
||||||
|
get { return _baseUrl; }
|
||||||
|
set { _baseUrl = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } }
|
||||||
|
|
||||||
|
partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
|
||||||
|
partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url);
|
||||||
|
partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder);
|
||||||
|
partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response);
|
||||||
|
|
||||||
|
/// <summary>Get all stored input queries</summary>
|
||||||
|
/// <returns>Array of input objects</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public System.Threading.Tasks.Task<System.Collections.Generic.ICollection<InputObject>> GetallAsync()
|
||||||
|
{
|
||||||
|
return GetallAsync(System.Threading.CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||||
|
/// <summary>Get all stored input queries</summary>
|
||||||
|
/// <returns>Array of input objects</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public async System.Threading.Tasks.Task<System.Collections.Generic.ICollection<InputObject>> GetallAsync(System.Threading.CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var urlBuilder_ = new System.Text.StringBuilder();
|
||||||
|
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/sample");
|
||||||
|
|
||||||
|
var client_ = _httpClient;
|
||||||
|
var disposeClient_ = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||||
|
{
|
||||||
|
request_.Method = new System.Net.Http.HttpMethod("GET");
|
||||||
|
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
|
||||||
|
|
||||||
|
PrepareRequest(client_, request_, urlBuilder_);
|
||||||
|
var url_ = urlBuilder_.ToString();
|
||||||
|
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
|
||||||
|
PrepareRequest(client_, request_, url_);
|
||||||
|
|
||||||
|
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
|
var disposeResponse_ = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
|
||||||
|
if (response_.Content != null && response_.Content.Headers != null)
|
||||||
|
{
|
||||||
|
foreach (var item_ in response_.Content.Headers)
|
||||||
|
headers_[item_.Key] = item_.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessResponse(client_, response_);
|
||||||
|
|
||||||
|
var status_ = (int)response_.StatusCode;
|
||||||
|
if (status_ == 200)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<System.Collections.Generic.ICollection<InputObject>>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
return objectResponse_.Object;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 404)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("No object matching filter", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeResponse_)
|
||||||
|
response_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeClient_)
|
||||||
|
client_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>uploads a sample into the system</summary>
|
||||||
|
/// <returns>successful operation</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public System.Threading.Tasks.Task<ApiResponse> UploadFileAsync(Description description, FileParameter file)
|
||||||
|
{
|
||||||
|
return UploadFileAsync(description, file, System.Threading.CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||||
|
/// <summary>uploads a sample into the system</summary>
|
||||||
|
/// <returns>successful operation</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public async System.Threading.Tasks.Task<ApiResponse> UploadFileAsync(Description description, FileParameter file, System.Threading.CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var urlBuilder_ = new System.Text.StringBuilder();
|
||||||
|
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/sample");
|
||||||
|
|
||||||
|
var client_ = _httpClient;
|
||||||
|
var disposeClient_ = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||||
|
{
|
||||||
|
var boundary_ = System.Guid.NewGuid().ToString();
|
||||||
|
var content_ = new System.Net.Http.MultipartFormDataContent(boundary_);
|
||||||
|
content_.Headers.Remove("Content-Type");
|
||||||
|
content_.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary_);
|
||||||
|
if (description == null)
|
||||||
|
throw new System.ArgumentNullException("description");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content_.Add(new System.Net.Http.StringContent(ConvertToString(description, System.Globalization.CultureInfo.InvariantCulture)), "description");
|
||||||
|
}
|
||||||
|
if (file == null)
|
||||||
|
throw new System.ArgumentNullException("file");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var content_file_ = new System.Net.Http.StreamContent(file.Data);
|
||||||
|
if (!string.IsNullOrEmpty(file.ContentType))
|
||||||
|
content_file_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse(file.ContentType);
|
||||||
|
content_.Add(content_file_, "file", file.FileName ?? "file");
|
||||||
|
}
|
||||||
|
request_.Content = content_;
|
||||||
|
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||||
|
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
|
||||||
|
|
||||||
|
PrepareRequest(client_, request_, urlBuilder_);
|
||||||
|
var url_ = urlBuilder_.ToString();
|
||||||
|
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
|
||||||
|
PrepareRequest(client_, request_, url_);
|
||||||
|
|
||||||
|
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
|
var disposeResponse_ = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
|
||||||
|
if (response_.Content != null && response_.Content.Headers != null)
|
||||||
|
{
|
||||||
|
foreach (var item_ in response_.Content.Headers)
|
||||||
|
headers_[item_.Key] = item_.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessResponse(client_, response_);
|
||||||
|
|
||||||
|
var status_ = (int)response_.StatusCode;
|
||||||
|
if (status_ == 200)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
return objectResponse_.Object;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 400)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("JSON parse error", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 415)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("Media type error", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 417)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("JSON invalid schema", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 469)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("No file found", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 470)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("Description missing", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeResponse_)
|
||||||
|
response_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeClient_)
|
||||||
|
client_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Get input object by ID</summary>
|
||||||
|
/// <param name="tagID">ID of input object file</param>
|
||||||
|
/// <returns>input object</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public System.Threading.Tasks.Task<InputSingeResponse> GetInputAsync(System.Guid tagID)
|
||||||
|
{
|
||||||
|
return GetInputAsync(tagID, System.Threading.CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||||
|
/// <summary>Get input object by ID</summary>
|
||||||
|
/// <param name="tagID">ID of input object file</param>
|
||||||
|
/// <returns>input object</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public async System.Threading.Tasks.Task<InputSingeResponse> GetInputAsync(System.Guid tagID, System.Threading.CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (tagID == null)
|
||||||
|
throw new System.ArgumentNullException("tagID");
|
||||||
|
|
||||||
|
var urlBuilder_ = new System.Text.StringBuilder();
|
||||||
|
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/sample/{tagID}");
|
||||||
|
urlBuilder_.Replace("{tagID}", System.Uri.EscapeDataString(ConvertToString(tagID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||||
|
|
||||||
|
var client_ = _httpClient;
|
||||||
|
var disposeClient_ = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||||
|
{
|
||||||
|
request_.Method = new System.Net.Http.HttpMethod("GET");
|
||||||
|
request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json"));
|
||||||
|
|
||||||
|
PrepareRequest(client_, request_, urlBuilder_);
|
||||||
|
var url_ = urlBuilder_.ToString();
|
||||||
|
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
|
||||||
|
PrepareRequest(client_, request_, url_);
|
||||||
|
|
||||||
|
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
|
var disposeResponse_ = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
|
||||||
|
if (response_.Content != null && response_.Content.Headers != null)
|
||||||
|
{
|
||||||
|
foreach (var item_ in response_.Content.Headers)
|
||||||
|
headers_[item_.Key] = item_.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessResponse(client_, response_);
|
||||||
|
|
||||||
|
var status_ = (int)response_.StatusCode;
|
||||||
|
if (status_ == 200)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<InputSingeResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
return objectResponse_.Object;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 404)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ApiResponse>(response_, headers_).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ApiResponse>("Tag not found", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeResponse_)
|
||||||
|
response_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeClient_)
|
||||||
|
client_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected struct ObjectResponseResult<T>
|
||||||
|
{
|
||||||
|
public ObjectResponseResult(T responseObject, string responseText)
|
||||||
|
{
|
||||||
|
this.Object = responseObject;
|
||||||
|
this.Text = responseText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Object { get; }
|
||||||
|
|
||||||
|
public string Text { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ReadResponseAsString { get; set; }
|
||||||
|
|
||||||
|
protected virtual async System.Threading.Tasks.Task<ObjectResponseResult<T>> ReadObjectResponseAsync<T>(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers)
|
||||||
|
{
|
||||||
|
if (response == null || response.Content == null)
|
||||||
|
{
|
||||||
|
return new ObjectResponseResult<T>(default(T), string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReadResponseAsString)
|
||||||
|
{
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(responseText, JsonSerializerSettings);
|
||||||
|
return new ObjectResponseResult<T>(typedBody, responseText);
|
||||||
|
}
|
||||||
|
catch (Newtonsoft.Json.JsonException exception)
|
||||||
|
{
|
||||||
|
var message = "Could not deserialize the response body string as " + typeof(T).FullName + ".";
|
||||||
|
throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||||
|
using (var streamReader = new System.IO.StreamReader(responseStream))
|
||||||
|
using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader))
|
||||||
|
{
|
||||||
|
var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings);
|
||||||
|
var typedBody = serializer.Deserialize<T>(jsonTextReader);
|
||||||
|
return new ObjectResponseResult<T>(typedBody, string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Newtonsoft.Json.JsonException exception)
|
||||||
|
{
|
||||||
|
var message = "Could not deserialize the response body stream as " + typeof(T).FullName + ".";
|
||||||
|
throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value is System.Enum)
|
||||||
|
{
|
||||||
|
var name = System.Enum.GetName(value.GetType(), value);
|
||||||
|
if (name != null)
|
||||||
|
{
|
||||||
|
var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name);
|
||||||
|
if (field != null)
|
||||||
|
{
|
||||||
|
var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute))
|
||||||
|
as System.Runtime.Serialization.EnumMemberAttribute;
|
||||||
|
if (attribute != null)
|
||||||
|
{
|
||||||
|
return attribute.Value != null ? attribute.Value : name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value is bool)
|
||||||
|
{
|
||||||
|
return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant();
|
||||||
|
}
|
||||||
|
else if (value is byte[])
|
||||||
|
{
|
||||||
|
return System.Convert.ToBase64String((byte[])value);
|
||||||
|
}
|
||||||
|
else if (value.GetType().IsArray)
|
||||||
|
{
|
||||||
|
var array = System.Linq.Enumerable.OfType<object>((System.Array)value);
|
||||||
|
return string.Join(",", System.Linq.Enumerable.Select(array, o => ConvertToString(o, cultureInfo)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = System.Convert.ToString(value, cultureInfo);
|
||||||
|
return (result is null) ? string.Empty : result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning restore 8703
|
||||||
|
#pragma warning restore 1591
|
||||||
|
#pragma warning restore 1573
|
||||||
|
#pragma warning restore 472
|
||||||
|
#pragma warning restore 114
|
||||||
|
#pragma warning restore 108
|
@ -14,9 +14,15 @@ namespace Birdmap.BLL
|
|||||||
services.AddTransient<IServiceService, ServiceService>();
|
services.AddTransient<IServiceService, ServiceService>();
|
||||||
|
|
||||||
if (configuration.GetValue<bool>("UseDummyServices"))
|
if (configuration.GetValue<bool>("UseDummyServices"))
|
||||||
services.AddTransient<IDeviceService, DummyDeviceService>();
|
{
|
||||||
|
services.AddTransient<IInputService, DummyDeviceAndInputService>();
|
||||||
|
services.AddTransient<IDeviceService, DummyDeviceAndInputService>();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
services.AddTransient<IInputService, LiveInputService>();
|
||||||
services.AddTransient<IDeviceService, LiveDummyService>();
|
services.AddTransient<IDeviceService, LiveDummyService>();
|
||||||
|
}
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.9" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.9">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0">
|
||||||
<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.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.9" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Birdmap.DAL.Entities
|
namespace Birdmap.DAL.Entities
|
||||||
{
|
{
|
||||||
public class Service
|
public record Service
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
Admin,
|
Admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class User
|
public record User
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Birdmap.BLL", "Birdmap.BLL\
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Birdmap.DAL", "Birdmap.DAL\Birdmap.DAL.csproj", "{543FAB06-B960-41A9-8865-1624A2ED2170}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Birdmap.DAL", "Birdmap.DAL\Birdmap.DAL.csproj", "{543FAB06-B960-41A9-8865-1624A2ED2170}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Birdmap.Common", "Birdmap.Common\Birdmap.Common.csproj", "{CE96BAFA-A0FD-4010-8EF2-700451091F71}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Birdmap.Common", "Birdmap.Common\Birdmap.Common.csproj", "{CE96BAFA-A0FD-4010-8EF2-700451091F71}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MQTTnet.TestApp.WinForm", "MQTTnet.TestApp.WinForm\MQTTnet.TestApp.WinForm.csproj", "{E1707FE7-4A65-42AC-B71C-6CC1A55FC42A}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -33,6 +35,10 @@ Global
|
|||||||
{CE96BAFA-A0FD-4010-8EF2-700451091F71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{CE96BAFA-A0FD-4010-8EF2-700451091F71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{CE96BAFA-A0FD-4010-8EF2-700451091F71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{CE96BAFA-A0FD-4010-8EF2-700451091F71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{CE96BAFA-A0FD-4010-8EF2-700451091F71}.Release|Any CPU.Build.0 = Release|Any CPU
|
{CE96BAFA-A0FD-4010-8EF2-700451091F71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E1707FE7-4A65-42AC-B71C-6CC1A55FC42A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E1707FE7-4A65-42AC-B71C-6CC1A55FC42A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E1707FE7-4A65-42AC-B71C-6CC1A55FC42A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E1707FE7-4A65-42AC-B71C-6CC1A55FC42A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
394
MQTTnet.TestApp.WinForm/Form1.Designer.cs
generated
Normal file
394
MQTTnet.TestApp.WinForm/Form1.Designer.cs
generated
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
namespace MQTTnet.TestApp.WinForm
|
||||||
|
{
|
||||||
|
partial class Form1
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.TextBoxPort = new System.Windows.Forms.TextBox();
|
||||||
|
this.ButtonServerStart = new System.Windows.Forms.Button();
|
||||||
|
this.ButtonServerStop = new System.Windows.Forms.Button();
|
||||||
|
this.label2 = new System.Windows.Forms.Label();
|
||||||
|
this.maskedTextBox1 = new System.Windows.Forms.MaskedTextBox();
|
||||||
|
this.label3 = new System.Windows.Forms.Label();
|
||||||
|
this.TextBoxTopicPublished = new System.Windows.Forms.TextBox();
|
||||||
|
this.label4 = new System.Windows.Forms.Label();
|
||||||
|
this.label5 = new System.Windows.Forms.Label();
|
||||||
|
this.ButtonPublisherStop = new System.Windows.Forms.Button();
|
||||||
|
this.ButtonPublisherStart = new System.Windows.Forms.Button();
|
||||||
|
this.TextBoxPublish = new System.Windows.Forms.TextBox();
|
||||||
|
this.ButtonPublish = new System.Windows.Forms.Button();
|
||||||
|
this.ButtonSubscriberStop = new System.Windows.Forms.Button();
|
||||||
|
this.ButtonSubscriberStart = new System.Windows.Forms.Button();
|
||||||
|
this.TextBoxSubscriber = new System.Windows.Forms.TextBox();
|
||||||
|
this.ButtonGeneratePublishedMessage = new System.Windows.Forms.Button();
|
||||||
|
this.label6 = new System.Windows.Forms.Label();
|
||||||
|
this.TextBoxTopicSubscribed = new System.Windows.Forms.TextBox();
|
||||||
|
this.ButtonSubscribe = new System.Windows.Forms.Button();
|
||||||
|
this.label7 = new System.Windows.Forms.Label();
|
||||||
|
this.trackBar1 = new System.Windows.Forms.TrackBar();
|
||||||
|
this.ButtonAutoPublisherStop = new System.Windows.Forms.Button();
|
||||||
|
this.ButtonAutoPublisherStart = new System.Windows.Forms.Button();
|
||||||
|
this.label8 = new System.Windows.Forms.Label();
|
||||||
|
this.checkBox1 = new System.Windows.Forms.CheckBox();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.AutoSize = true;
|
||||||
|
this.label1.Location = new System.Drawing.Point(119, 24);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(32, 15);
|
||||||
|
this.label1.TabIndex = 0;
|
||||||
|
this.label1.Text = "Port:";
|
||||||
|
//
|
||||||
|
// TextBoxPort
|
||||||
|
//
|
||||||
|
this.TextBoxPort.Location = new System.Drawing.Point(172, 21);
|
||||||
|
this.TextBoxPort.Name = "TextBoxPort";
|
||||||
|
this.TextBoxPort.Size = new System.Drawing.Size(100, 23);
|
||||||
|
this.TextBoxPort.TabIndex = 1;
|
||||||
|
this.TextBoxPort.Text = "1883";
|
||||||
|
this.TextBoxPort.TextChanged += new System.EventHandler(this.TextBoxPortTextChanged);
|
||||||
|
//
|
||||||
|
// ButtonServerStart
|
||||||
|
//
|
||||||
|
this.ButtonServerStart.Location = new System.Drawing.Point(433, 21);
|
||||||
|
this.ButtonServerStart.Name = "ButtonServerStart";
|
||||||
|
this.ButtonServerStart.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonServerStart.TabIndex = 2;
|
||||||
|
this.ButtonServerStart.Text = "Start";
|
||||||
|
this.ButtonServerStart.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonServerStart.Click += new System.EventHandler(this.ButtonServerStartClick);
|
||||||
|
//
|
||||||
|
// ButtonServerStop
|
||||||
|
//
|
||||||
|
this.ButtonServerStop.Location = new System.Drawing.Point(514, 21);
|
||||||
|
this.ButtonServerStop.Name = "ButtonServerStop";
|
||||||
|
this.ButtonServerStop.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonServerStop.TabIndex = 3;
|
||||||
|
this.ButtonServerStop.Text = "Stop";
|
||||||
|
this.ButtonServerStop.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonServerStop.Click += new System.EventHandler(this.ButtonServerStopClick);
|
||||||
|
//
|
||||||
|
// label2
|
||||||
|
//
|
||||||
|
this.label2.AutoSize = true;
|
||||||
|
this.label2.Location = new System.Drawing.Point(33, 25);
|
||||||
|
this.label2.Name = "label2";
|
||||||
|
this.label2.Size = new System.Drawing.Size(39, 15);
|
||||||
|
this.label2.TabIndex = 4;
|
||||||
|
this.label2.Text = "Server";
|
||||||
|
//
|
||||||
|
// maskedTextBox1
|
||||||
|
//
|
||||||
|
this.maskedTextBox1.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.maskedTextBox1.Name = "maskedTextBox1";
|
||||||
|
this.maskedTextBox1.Size = new System.Drawing.Size(100, 23);
|
||||||
|
this.maskedTextBox1.TabIndex = 5;
|
||||||
|
this.maskedTextBox1.Text = "maskedTextBox1";
|
||||||
|
//
|
||||||
|
// label3
|
||||||
|
//
|
||||||
|
this.label3.AutoSize = true;
|
||||||
|
this.label3.Location = new System.Drawing.Point(33, 79);
|
||||||
|
this.label3.Name = "label3";
|
||||||
|
this.label3.Size = new System.Drawing.Size(90, 15);
|
||||||
|
this.label3.TabIndex = 5;
|
||||||
|
this.label3.Text = "Topic Published";
|
||||||
|
//
|
||||||
|
// TextBoxTopicPublished
|
||||||
|
//
|
||||||
|
this.TextBoxTopicPublished.Location = new System.Drawing.Point(164, 76);
|
||||||
|
this.TextBoxTopicPublished.Name = "TextBoxTopicPublished";
|
||||||
|
this.TextBoxTopicPublished.Size = new System.Drawing.Size(425, 23);
|
||||||
|
this.TextBoxTopicPublished.TabIndex = 1;
|
||||||
|
this.TextBoxTopicPublished.Text = "devices/output";
|
||||||
|
this.TextBoxTopicPublished.TextChanged += new System.EventHandler(this.TextBoxPortTextChanged);
|
||||||
|
//
|
||||||
|
// label4
|
||||||
|
//
|
||||||
|
this.label4.AutoSize = true;
|
||||||
|
this.label4.Location = new System.Drawing.Point(33, 109);
|
||||||
|
this.label4.Name = "label4";
|
||||||
|
this.label4.Size = new System.Drawing.Size(90, 15);
|
||||||
|
this.label4.TabIndex = 5;
|
||||||
|
this.label4.Text = "Client Publisher";
|
||||||
|
//
|
||||||
|
// label5
|
||||||
|
//
|
||||||
|
this.label5.AutoSize = true;
|
||||||
|
this.label5.Location = new System.Drawing.Point(33, 224);
|
||||||
|
this.label5.Name = "label5";
|
||||||
|
this.label5.Size = new System.Drawing.Size(96, 15);
|
||||||
|
this.label5.TabIndex = 5;
|
||||||
|
this.label5.Text = "Client Subscriber";
|
||||||
|
//
|
||||||
|
// ButtonPublisherStop
|
||||||
|
//
|
||||||
|
this.ButtonPublisherStop.Location = new System.Drawing.Point(514, 105);
|
||||||
|
this.ButtonPublisherStop.Name = "ButtonPublisherStop";
|
||||||
|
this.ButtonPublisherStop.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonPublisherStop.TabIndex = 3;
|
||||||
|
this.ButtonPublisherStop.Text = "Stop";
|
||||||
|
this.ButtonPublisherStop.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonPublisherStop.Click += new System.EventHandler(this.ButtonPublisherStopClick);
|
||||||
|
//
|
||||||
|
// ButtonPublisherStart
|
||||||
|
//
|
||||||
|
this.ButtonPublisherStart.Location = new System.Drawing.Point(433, 105);
|
||||||
|
this.ButtonPublisherStart.Name = "ButtonPublisherStart";
|
||||||
|
this.ButtonPublisherStart.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonPublisherStart.TabIndex = 2;
|
||||||
|
this.ButtonPublisherStart.Text = "Start";
|
||||||
|
this.ButtonPublisherStart.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonPublisherStart.Click += new System.EventHandler(this.ButtonPublisherStartClick);
|
||||||
|
//
|
||||||
|
// TextBoxPublish
|
||||||
|
//
|
||||||
|
this.TextBoxPublish.Location = new System.Drawing.Point(33, 134);
|
||||||
|
this.TextBoxPublish.Name = "TextBoxPublish";
|
||||||
|
this.TextBoxPublish.Size = new System.Drawing.Size(394, 23);
|
||||||
|
this.TextBoxPublish.TabIndex = 1;
|
||||||
|
this.TextBoxPublish.TextChanged += new System.EventHandler(this.TextBoxPortTextChanged);
|
||||||
|
//
|
||||||
|
// ButtonPublish
|
||||||
|
//
|
||||||
|
this.ButtonPublish.Location = new System.Drawing.Point(514, 134);
|
||||||
|
this.ButtonPublish.Name = "ButtonPublish";
|
||||||
|
this.ButtonPublish.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonPublish.TabIndex = 3;
|
||||||
|
this.ButtonPublish.Text = "Publish";
|
||||||
|
this.ButtonPublish.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonPublish.Click += new System.EventHandler(this.ButtonPublishClick);
|
||||||
|
//
|
||||||
|
// ButtonSubscriberStop
|
||||||
|
//
|
||||||
|
this.ButtonSubscriberStop.Location = new System.Drawing.Point(514, 220);
|
||||||
|
this.ButtonSubscriberStop.Name = "ButtonSubscriberStop";
|
||||||
|
this.ButtonSubscriberStop.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonSubscriberStop.TabIndex = 3;
|
||||||
|
this.ButtonSubscriberStop.Text = "Stop";
|
||||||
|
this.ButtonSubscriberStop.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonSubscriberStop.Click += new System.EventHandler(this.ButtonSubscriberStopClick);
|
||||||
|
//
|
||||||
|
// ButtonSubscriberStart
|
||||||
|
//
|
||||||
|
this.ButtonSubscriberStart.Location = new System.Drawing.Point(433, 220);
|
||||||
|
this.ButtonSubscriberStart.Name = "ButtonSubscriberStart";
|
||||||
|
this.ButtonSubscriberStart.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonSubscriberStart.TabIndex = 2;
|
||||||
|
this.ButtonSubscriberStart.Text = "Start";
|
||||||
|
this.ButtonSubscriberStart.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonSubscriberStart.Click += new System.EventHandler(this.ButtonSubscriberStartClick);
|
||||||
|
//
|
||||||
|
// TextBoxSubscriber
|
||||||
|
//
|
||||||
|
this.TextBoxSubscriber.Location = new System.Drawing.Point(33, 309);
|
||||||
|
this.TextBoxSubscriber.Multiline = true;
|
||||||
|
this.TextBoxSubscriber.Name = "TextBoxSubscriber";
|
||||||
|
this.TextBoxSubscriber.Size = new System.Drawing.Size(556, 182);
|
||||||
|
this.TextBoxSubscriber.TabIndex = 6;
|
||||||
|
//
|
||||||
|
// ButtonGeneratePublishedMessage
|
||||||
|
//
|
||||||
|
this.ButtonGeneratePublishedMessage.Location = new System.Drawing.Point(433, 133);
|
||||||
|
this.ButtonGeneratePublishedMessage.Name = "ButtonGeneratePublishedMessage";
|
||||||
|
this.ButtonGeneratePublishedMessage.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonGeneratePublishedMessage.TabIndex = 2;
|
||||||
|
this.ButtonGeneratePublishedMessage.Text = "Random";
|
||||||
|
this.ButtonGeneratePublishedMessage.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonGeneratePublishedMessage.Click += new System.EventHandler(this.ButtonGeneratePublishedMessageClick);
|
||||||
|
//
|
||||||
|
// label6
|
||||||
|
//
|
||||||
|
this.label6.AutoSize = true;
|
||||||
|
this.label6.Location = new System.Drawing.Point(33, 252);
|
||||||
|
this.label6.Name = "label6";
|
||||||
|
this.label6.Size = new System.Drawing.Size(96, 15);
|
||||||
|
this.label6.TabIndex = 5;
|
||||||
|
this.label6.Text = "Topic Subscribed";
|
||||||
|
//
|
||||||
|
// TextBoxTopicSubscribed
|
||||||
|
//
|
||||||
|
this.TextBoxTopicSubscribed.Location = new System.Drawing.Point(164, 249);
|
||||||
|
this.TextBoxTopicSubscribed.Name = "TextBoxTopicSubscribed";
|
||||||
|
this.TextBoxTopicSubscribed.Size = new System.Drawing.Size(344, 23);
|
||||||
|
this.TextBoxTopicSubscribed.TabIndex = 1;
|
||||||
|
this.TextBoxTopicSubscribed.Text = "devices/output";
|
||||||
|
this.TextBoxTopicSubscribed.TextChanged += new System.EventHandler(this.TextBoxPortTextChanged);
|
||||||
|
//
|
||||||
|
// ButtonSubscribe
|
||||||
|
//
|
||||||
|
this.ButtonSubscribe.Location = new System.Drawing.Point(514, 248);
|
||||||
|
this.ButtonSubscribe.Name = "ButtonSubscribe";
|
||||||
|
this.ButtonSubscribe.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonSubscribe.TabIndex = 3;
|
||||||
|
this.ButtonSubscribe.Text = "Subscribe";
|
||||||
|
this.ButtonSubscribe.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonSubscribe.Click += new System.EventHandler(this.ButtonSubscribeClick);
|
||||||
|
//
|
||||||
|
// label7
|
||||||
|
//
|
||||||
|
this.label7.AutoSize = true;
|
||||||
|
this.label7.Location = new System.Drawing.Point(33, 167);
|
||||||
|
this.label7.Name = "label7";
|
||||||
|
this.label7.Size = new System.Drawing.Size(141, 15);
|
||||||
|
this.label7.TabIndex = 5;
|
||||||
|
this.label7.Text = "Auto (Random) Publisher";
|
||||||
|
//
|
||||||
|
// trackBar1
|
||||||
|
//
|
||||||
|
this.trackBar1.LargeChange = 500;
|
||||||
|
this.trackBar1.Location = new System.Drawing.Point(180, 162);
|
||||||
|
this.trackBar1.Maximum = 5050;
|
||||||
|
this.trackBar1.Minimum = 50;
|
||||||
|
this.trackBar1.Name = "trackBar1";
|
||||||
|
this.trackBar1.Size = new System.Drawing.Size(247, 45);
|
||||||
|
this.trackBar1.SmallChange = 100;
|
||||||
|
this.trackBar1.TabIndex = 7;
|
||||||
|
this.trackBar1.TickFrequency = 500;
|
||||||
|
this.trackBar1.Value = 550;
|
||||||
|
this.trackBar1.Scroll += new System.EventHandler(this.trackBar1_Scroll);
|
||||||
|
//
|
||||||
|
// ButtonAutoPublisherStop
|
||||||
|
//
|
||||||
|
this.ButtonAutoPublisherStop.Location = new System.Drawing.Point(513, 162);
|
||||||
|
this.ButtonAutoPublisherStop.Name = "ButtonAutoPublisherStop";
|
||||||
|
this.ButtonAutoPublisherStop.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonAutoPublisherStop.TabIndex = 8;
|
||||||
|
this.ButtonAutoPublisherStop.Text = "Stop";
|
||||||
|
this.ButtonAutoPublisherStop.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonAutoPublisherStop.Click += new System.EventHandler(this.ButtonAutoPublisherStopClick);
|
||||||
|
//
|
||||||
|
// ButtonAutoPublisherStart
|
||||||
|
//
|
||||||
|
this.ButtonAutoPublisherStart.Location = new System.Drawing.Point(433, 162);
|
||||||
|
this.ButtonAutoPublisherStart.Name = "ButtonAutoPublisherStart";
|
||||||
|
this.ButtonAutoPublisherStart.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.ButtonAutoPublisherStart.TabIndex = 8;
|
||||||
|
this.ButtonAutoPublisherStart.Text = "Start";
|
||||||
|
this.ButtonAutoPublisherStart.UseVisualStyleBackColor = true;
|
||||||
|
this.ButtonAutoPublisherStart.Click += new System.EventHandler(this.ButtonAutoPublisherStartClick);
|
||||||
|
//
|
||||||
|
// label8
|
||||||
|
//
|
||||||
|
this.label8.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||||
|
this.label8.AutoSize = true;
|
||||||
|
this.label8.Location = new System.Drawing.Point(180, 191);
|
||||||
|
this.label8.Name = "label8";
|
||||||
|
this.label8.RightToLeft = System.Windows.Forms.RightToLeft.No;
|
||||||
|
this.label8.Size = new System.Drawing.Size(44, 15);
|
||||||
|
this.label8.TabIndex = 9;
|
||||||
|
this.label8.Text = "550 ms";
|
||||||
|
this.label8.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||||
|
//
|
||||||
|
// checkBox1
|
||||||
|
//
|
||||||
|
this.checkBox1.AutoSize = true;
|
||||||
|
this.checkBox1.Checked = true;
|
||||||
|
this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||||
|
this.checkBox1.Location = new System.Drawing.Point(433, 191);
|
||||||
|
this.checkBox1.Name = "checkBox1";
|
||||||
|
this.checkBox1.Size = new System.Drawing.Size(82, 19);
|
||||||
|
this.checkBox1.TabIndex = 10;
|
||||||
|
this.checkBox1.Text = "randomize";
|
||||||
|
this.checkBox1.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// Form1
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(627, 530);
|
||||||
|
this.Controls.Add(this.checkBox1);
|
||||||
|
this.Controls.Add(this.label8);
|
||||||
|
this.Controls.Add(this.ButtonAutoPublisherStart);
|
||||||
|
this.Controls.Add(this.ButtonAutoPublisherStop);
|
||||||
|
this.Controls.Add(this.trackBar1);
|
||||||
|
this.Controls.Add(this.label7);
|
||||||
|
this.Controls.Add(this.TextBoxSubscriber);
|
||||||
|
this.Controls.Add(this.label5);
|
||||||
|
this.Controls.Add(this.label4);
|
||||||
|
this.Controls.Add(this.label3);
|
||||||
|
this.Controls.Add(this.label2);
|
||||||
|
this.Controls.Add(this.ButtonServerStop);
|
||||||
|
this.Controls.Add(this.ButtonServerStart);
|
||||||
|
this.Controls.Add(this.TextBoxPort);
|
||||||
|
this.Controls.Add(this.label1);
|
||||||
|
this.Controls.Add(this.TextBoxTopicPublished);
|
||||||
|
this.Controls.Add(this.ButtonPublisherStop);
|
||||||
|
this.Controls.Add(this.ButtonPublisherStart);
|
||||||
|
this.Controls.Add(this.TextBoxPublish);
|
||||||
|
this.Controls.Add(this.ButtonPublish);
|
||||||
|
this.Controls.Add(this.ButtonSubscriberStop);
|
||||||
|
this.Controls.Add(this.ButtonSubscriberStart);
|
||||||
|
this.Controls.Add(this.ButtonGeneratePublishedMessage);
|
||||||
|
this.Controls.Add(this.label6);
|
||||||
|
this.Controls.Add(this.TextBoxTopicSubscribed);
|
||||||
|
this.Controls.Add(this.ButtonSubscribe);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
|
this.Name = "Form1";
|
||||||
|
this.Text = "MQTT Testing";
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.Label label1;
|
||||||
|
private System.Windows.Forms.TextBox TextBoxPort;
|
||||||
|
private System.Windows.Forms.Button ButtonServerStart;
|
||||||
|
private System.Windows.Forms.Button ButtonServerStop;
|
||||||
|
private System.Windows.Forms.Label label2;
|
||||||
|
private System.Windows.Forms.MaskedTextBox maskedTextBox1;
|
||||||
|
private System.Windows.Forms.Label label3;
|
||||||
|
private System.Windows.Forms.Label label4;
|
||||||
|
private System.Windows.Forms.Label label5;
|
||||||
|
private System.Windows.Forms.Button ButtonPublisherStop;
|
||||||
|
private System.Windows.Forms.Button ButtonPublisherStart;
|
||||||
|
private System.Windows.Forms.TextBox TextBoxPublish;
|
||||||
|
private System.Windows.Forms.Button ButtonPublish;
|
||||||
|
private System.Windows.Forms.Button ButtonSubscriberStop;
|
||||||
|
private System.Windows.Forms.Button ButtonSubscriberStart;
|
||||||
|
private System.Windows.Forms.TextBox TextBoxSubscriber;
|
||||||
|
private System.Windows.Forms.Button ButtonGeneratePublishedMessage;
|
||||||
|
private System.Windows.Forms.Label label6;
|
||||||
|
private System.Windows.Forms.TextBox TextBoxTopicPublished;
|
||||||
|
private System.Windows.Forms.Button ButtonSubscribe;
|
||||||
|
private System.Windows.Forms.TextBox TextBoxTopicSubscribed;
|
||||||
|
private System.Windows.Forms.Label label7;
|
||||||
|
private System.Windows.Forms.TrackBar trackBar1;
|
||||||
|
private System.Windows.Forms.Button ButtonAutoPublisherStop;
|
||||||
|
private System.Windows.Forms.Button ButtonAutoPublisherStart;
|
||||||
|
private System.Windows.Forms.Label label8;
|
||||||
|
private System.Windows.Forms.CheckBox checkBox1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
476
MQTTnet.TestApp.WinForm/Form1.cs
Normal file
476
MQTTnet.TestApp.WinForm/Form1.cs
Normal file
@ -0,0 +1,476 @@
|
|||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
// <copyright file="Form1.cs" company="Haemmer Electronics">
|
||||||
|
// Copyright (c) 2020 All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
// <summary>
|
||||||
|
// The main form.
|
||||||
|
// </summary>
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace MQTTnet.TestApp.WinForm
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Timers;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
using MQTTnet.Client.Connecting;
|
||||||
|
using MQTTnet.Client.Disconnecting;
|
||||||
|
using MQTTnet.Client.Options;
|
||||||
|
using MQTTnet.Client.Receiving;
|
||||||
|
using MQTTnet.Extensions.ManagedClient;
|
||||||
|
using MQTTnet.Formatter;
|
||||||
|
using MQTTnet.Protocol;
|
||||||
|
using MQTTnet.Server;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Timer = System.Timers.Timer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main form.
|
||||||
|
/// </summary>
|
||||||
|
public partial class Form1 : Form
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The managed publisher client.
|
||||||
|
/// </summary>
|
||||||
|
private IManagedMqttClient managedMqttClientPublisher;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The managed subscriber client.
|
||||||
|
/// </summary>
|
||||||
|
private IManagedMqttClient managedMqttClientSubscriber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The MQTT server.
|
||||||
|
/// </summary>
|
||||||
|
private IMqttServer mqttServer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The port.
|
||||||
|
/// </summary>
|
||||||
|
private string port = "1883";
|
||||||
|
|
||||||
|
private readonly Random random;
|
||||||
|
private readonly Timer randomPublisherTimer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Form1"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public Form1()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
|
||||||
|
var timer = new Timer
|
||||||
|
{
|
||||||
|
AutoReset = true, Enabled = true, Interval = 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
timer.Elapsed += this.TimerElapsed;
|
||||||
|
|
||||||
|
random = new Random();
|
||||||
|
randomPublisherTimer = new Timer
|
||||||
|
{
|
||||||
|
AutoReset = true,
|
||||||
|
Enabled = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
randomPublisherTimer.Elapsed += (_, __) => this.BeginInvoke((MethodInvoker)delegate
|
||||||
|
{
|
||||||
|
if (checkBox1.Checked)
|
||||||
|
ButtonGeneratePublishedMessageClick(ButtonGeneratePublishedMessage, EventArgs.Empty);
|
||||||
|
|
||||||
|
ButtonPublishClick(ButtonPublish, EventArgs.Empty);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the publisher connected event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The MQTT client connected event args.</param>
|
||||||
|
private void OnPublisherConnected(MqttClientConnectedEventArgs x)
|
||||||
|
{
|
||||||
|
var item = "Publisher Connected";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the publisher disconnected event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The MQTT client disconnected event args.</param>
|
||||||
|
private void OnPublisherDisconnected(MqttClientDisconnectedEventArgs x)
|
||||||
|
{
|
||||||
|
var item = "Publisher Disconnected";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the subscriber connected event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The MQTT client connected event args.</param>
|
||||||
|
private void OnSubscriberConnected(MqttClientConnectedEventArgs x)
|
||||||
|
{
|
||||||
|
var item = "Subscriber Connected";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the subscriber disconnected event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The MQTT client disconnected event args.</param>
|
||||||
|
private void OnSubscriberDisconnected(MqttClientDisconnectedEventArgs x)
|
||||||
|
{
|
||||||
|
var item = "Subscriber Disconnected";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to generate a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private void ButtonGeneratePublishedMessageClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var message = new
|
||||||
|
{
|
||||||
|
tag = Guid.NewGuid(),
|
||||||
|
probability = random.NextDouble(),
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(message);
|
||||||
|
this.TextBoxPublish.Text = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to publish a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonPublishClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
((Button)sender).Enabled = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var payload = Encoding.UTF8.GetBytes(this.TextBoxPublish.Text);
|
||||||
|
var message = new MqttApplicationMessageBuilder().WithTopic(this.TextBoxTopicPublished.Text.Trim()).WithPayload(payload).WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce).WithRetainFlag().Build();
|
||||||
|
|
||||||
|
if (this.managedMqttClientPublisher != null)
|
||||||
|
{
|
||||||
|
await this.managedMqttClientPublisher.PublishAsync(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var item = ex.Message;
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
((Button)sender).Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to start the publisher.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonPublisherStartClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
var tlsOptions = new MqttClientTlsOptions
|
||||||
|
{
|
||||||
|
UseTls = false, IgnoreCertificateChainErrors = true, IgnoreCertificateRevocationErrors = true, AllowUntrustedCertificates = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = new MqttClientOptions
|
||||||
|
{
|
||||||
|
ClientId = "ClientPublisher",
|
||||||
|
ProtocolVersion = MqttProtocolVersion.V311,
|
||||||
|
ChannelOptions = new MqttClientTcpOptions
|
||||||
|
{
|
||||||
|
Server = "localhost", Port = int.Parse(this.TextBoxPort.Text.Trim()), TlsOptions = tlsOptions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.ChannelOptions == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
options.Credentials = new MqttClientCredentials
|
||||||
|
{
|
||||||
|
Username = "username", Password = Encoding.UTF8.GetBytes("password")
|
||||||
|
};
|
||||||
|
|
||||||
|
options.CleanSession = true;
|
||||||
|
options.KeepAlivePeriod = TimeSpan.FromSeconds(5);
|
||||||
|
this.managedMqttClientPublisher = mqttFactory.CreateManagedMqttClient();
|
||||||
|
this.managedMqttClientPublisher.UseApplicationMessageReceivedHandler(this.HandleReceivedApplicationMessage);
|
||||||
|
this.managedMqttClientPublisher.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnPublisherConnected);
|
||||||
|
this.managedMqttClientPublisher.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnPublisherDisconnected);
|
||||||
|
|
||||||
|
await this.managedMqttClientPublisher.StartAsync(
|
||||||
|
new ManagedMqttClientOptions
|
||||||
|
{
|
||||||
|
ClientOptions = options
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to stop the publisher.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonPublisherStopClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (this.managedMqttClientPublisher == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.managedMqttClientPublisher.StopAsync();
|
||||||
|
this.managedMqttClientPublisher = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to start the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonServerStartClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (this.mqttServer != null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var storage = new JsonServerStorage();
|
||||||
|
storage.Clear();
|
||||||
|
this.mqttServer = new MqttFactory().CreateMqttServer();
|
||||||
|
var options = new MqttServerOptions();
|
||||||
|
options.DefaultEndpointOptions.Port = int.Parse(this.TextBoxPort.Text);
|
||||||
|
options.Storage = storage;
|
||||||
|
options.EnablePersistentSessions = true;
|
||||||
|
options.ConnectionValidator = new MqttServerConnectionValidatorDelegate(
|
||||||
|
c =>
|
||||||
|
{
|
||||||
|
if (c.ClientId.Length < 10)
|
||||||
|
{
|
||||||
|
c.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.Username != "username")
|
||||||
|
{
|
||||||
|
c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.Password != "password")
|
||||||
|
{
|
||||||
|
c.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ReasonCode = MqttConnectReasonCode.Success;
|
||||||
|
});
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await this.mqttServer.StartAsync(options);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var item = ex.Message;
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
|
||||||
|
await this.mqttServer.StopAsync();
|
||||||
|
this.mqttServer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to stop the server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonServerStopClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (this.mqttServer == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.mqttServer.StopAsync();
|
||||||
|
this.mqttServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to subscribe to a certain topic.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonSubscribeClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var topicFilter = new MqttTopicFilter { Topic = this.TextBoxTopicSubscribed.Text.Trim() };
|
||||||
|
await this.managedMqttClientSubscriber.SubscribeAsync(topicFilter);
|
||||||
|
var item = "Topic " + this.TextBoxTopicSubscribed.Text.Trim() + " is subscribed";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to start the subscriber.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonSubscriberStartClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var mqttFactory = new MqttFactory();
|
||||||
|
|
||||||
|
var tlsOptions = new MqttClientTlsOptions
|
||||||
|
{
|
||||||
|
UseTls = false, IgnoreCertificateChainErrors = true, IgnoreCertificateRevocationErrors = true, AllowUntrustedCertificates = true
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = new MqttClientOptions
|
||||||
|
{
|
||||||
|
ClientId = "ClientSubscriber",
|
||||||
|
ProtocolVersion = MqttProtocolVersion.V311,
|
||||||
|
ChannelOptions = new MqttClientTcpOptions
|
||||||
|
{
|
||||||
|
Server = "localhost", Port = int.Parse(this.TextBoxPort.Text.Trim()), TlsOptions = tlsOptions
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.ChannelOptions == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
options.Credentials = new MqttClientCredentials
|
||||||
|
{
|
||||||
|
Username = "username",
|
||||||
|
Password = Encoding.UTF8.GetBytes("password")
|
||||||
|
};
|
||||||
|
|
||||||
|
options.CleanSession = true;
|
||||||
|
options.KeepAlivePeriod = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
|
this.managedMqttClientSubscriber = mqttFactory.CreateManagedMqttClient();
|
||||||
|
this.managedMqttClientSubscriber.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnSubscriberConnected);
|
||||||
|
this.managedMqttClientSubscriber.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnSubscriberDisconnected);
|
||||||
|
this.managedMqttClientSubscriber.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(this.OnSubscriberMessageReceived);
|
||||||
|
|
||||||
|
await this.managedMqttClientSubscriber.StartAsync(
|
||||||
|
new ManagedMqttClientOptions
|
||||||
|
{
|
||||||
|
ClientOptions = options
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the button click to stop the subscriber.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private async void ButtonSubscriberStopClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (this.managedMqttClientSubscriber == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.managedMqttClientSubscriber.StopAsync();
|
||||||
|
this.managedMqttClientSubscriber = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the received application message event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The MQTT application message received event args.</param>
|
||||||
|
private void HandleReceivedApplicationMessage(MqttApplicationMessageReceivedEventArgs x)
|
||||||
|
{
|
||||||
|
var item = $"Timestamp: {DateTime.Now:O} | Topic: {x.ApplicationMessage.Topic} | Payload: {x.ApplicationMessage.ConvertPayloadToString()} | QoS: {x.ApplicationMessage.QualityOfServiceLevel}";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the received subscriber message event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The MQTT application message received event args.</param>
|
||||||
|
private void OnSubscriberMessageReceived(MqttApplicationMessageReceivedEventArgs x)
|
||||||
|
{
|
||||||
|
var item = $"Timestamp: {DateTime.Now:O} | Topic: {x.ApplicationMessage.Topic} | Payload: {x.ApplicationMessage.ConvertPayloadToString()} | QoS: {x.ApplicationMessage.QualityOfServiceLevel}";
|
||||||
|
this.BeginInvoke((MethodInvoker)delegate { this.TextBoxSubscriber.Text = item + Environment.NewLine + this.TextBoxSubscriber.Text; });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the text changes in the text box.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private void TextBoxPortTextChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// ReSharper disable once StyleCop.SA1126
|
||||||
|
if (int.TryParse(this.TextBoxPort.Text, out _))
|
||||||
|
{
|
||||||
|
this.port = this.TextBoxPort.Text.Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.TextBoxPort.Text = this.port;
|
||||||
|
this.TextBoxPort.SelectionStart = this.TextBoxPort.Text.Length;
|
||||||
|
this.TextBoxPort.SelectionLength = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method that handles the timer events.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The sender.</param>
|
||||||
|
/// <param name="e">The event args.</param>
|
||||||
|
private void TimerElapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
this.BeginInvoke(
|
||||||
|
(MethodInvoker)delegate
|
||||||
|
{
|
||||||
|
// Server
|
||||||
|
this.TextBoxPort.Enabled = this.mqttServer == null;
|
||||||
|
this.ButtonServerStart.Enabled = this.mqttServer == null;
|
||||||
|
this.ButtonServerStop.Enabled = this.mqttServer != null;
|
||||||
|
|
||||||
|
// Publisher
|
||||||
|
this.ButtonPublisherStart.Enabled = this.managedMqttClientPublisher == null;
|
||||||
|
this.ButtonPublisherStop.Enabled = this.managedMqttClientPublisher != null;
|
||||||
|
|
||||||
|
// Auto Publisher
|
||||||
|
this.ButtonAutoPublisherStart.Enabled = !this.randomPublisherTimer.Enabled;
|
||||||
|
this.ButtonAutoPublisherStop.Enabled = this.randomPublisherTimer.Enabled;
|
||||||
|
|
||||||
|
// Subscriber
|
||||||
|
this.ButtonSubscriberStart.Enabled = this.managedMqttClientSubscriber == null;
|
||||||
|
this.ButtonSubscriberStop.Enabled = this.managedMqttClientSubscriber != null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trackBar1_Scroll(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
this.label8.Text = $"{this.trackBar1.Value:N0} ms";
|
||||||
|
this.randomPublisherTimer.Interval = this.trackBar1.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ButtonAutoPublisherStartClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
((Button)sender).Enabled = false;
|
||||||
|
this.randomPublisherTimer.Start();
|
||||||
|
((Button)sender).Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ButtonAutoPublisherStopClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
((Button)sender).Enabled = false;
|
||||||
|
this.randomPublisherTimer.Stop();
|
||||||
|
((Button)sender).Enabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
MQTTnet.TestApp.WinForm/Form1.resx
Normal file
60
MQTTnet.TestApp.WinForm/Form1.resx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<root>
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
83
MQTTnet.TestApp.WinForm/JsonServerStorage.cs
Normal file
83
MQTTnet.TestApp.WinForm/JsonServerStorage.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
// <copyright file="JsonServerStorage.cs" company="Haemmer Electronics">
|
||||||
|
// Copyright (c) 2020 All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
// <summary>
|
||||||
|
// The JSON server storage.
|
||||||
|
// </summary>
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace MQTTnet.TestApp.WinForm
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using MQTTnet.Server;
|
||||||
|
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IMqttServerStorage"/>
|
||||||
|
/// <summary>
|
||||||
|
/// The JSON server storage.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IMqttServerStorage"/>
|
||||||
|
public class JsonServerStorage : IMqttServerStorage
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The file name.
|
||||||
|
/// </summary>
|
||||||
|
private readonly string filename = Path.Combine(Directory.GetCurrentDirectory(), "Retained.json");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears the file.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (File.Exists(this.filename))
|
||||||
|
{
|
||||||
|
File.Delete(this.filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IMqttServerStorage"/>
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the retained messages.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="IList{T}"/> of <see cref="MqttApplicationMessage"/>.</returns>
|
||||||
|
/// <seealso cref="IMqttServerStorage"/>
|
||||||
|
public async Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
|
||||||
|
{
|
||||||
|
await Task.CompletedTask;
|
||||||
|
|
||||||
|
if (!File.Exists(this.filename))
|
||||||
|
{
|
||||||
|
return new List<MqttApplicationMessage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var json = await File.ReadAllTextAsync(this.filename);
|
||||||
|
return JsonConvert.DeserializeObject<List<MqttApplicationMessage>>(json);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new List<MqttApplicationMessage>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IMqttServerStorage"/>
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the retained messages to a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messages">The messages.</param>
|
||||||
|
/// <returns>A <see cref="Task"/> representing any asynchronous operation.</returns>
|
||||||
|
/// <seealso cref="IMqttServerStorage"/>
|
||||||
|
public async Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
|
||||||
|
{
|
||||||
|
await Task.CompletedTask;
|
||||||
|
var json = JsonConvert.SerializeObject(messages);
|
||||||
|
await File.WriteAllTextAsync(this.filename, json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
MQTTnet.TestApp.WinForm/MQTTnet.TestApp.WinForm.csproj
Normal file
23
MQTTnet.TestApp.WinForm/MQTTnet.TestApp.WinForm.csproj
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net5.0-windows</TargetFramework>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
|
||||||
|
<RootNamespace>MQTTnet.TestApp.WinForm</RootNamespace>
|
||||||
|
<AssemblyName>MQTTnet.TestApp.WinForm</AssemblyName>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GitVersionTask" Version="5.5.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="MQTTnet" Version="3.0.13" />
|
||||||
|
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="3.0.13" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
45
MQTTnet.TestApp.WinForm/Program.cs
Normal file
45
MQTTnet.TestApp.WinForm/Program.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
// <copyright file="Program.cs" company="Haemmer Electronics">
|
||||||
|
// Copyright (c) 2020 All rights reserved.
|
||||||
|
// </copyright>
|
||||||
|
// <summary>
|
||||||
|
// The main program.
|
||||||
|
// </summary>
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace MQTTnet.TestApp.WinForm
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main program.
|
||||||
|
/// </summary>
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
static readonly Mutex mutex = new Mutex(true, "{B9D725A5-48F1-4907-974F-B6C3B9C8C4BB}");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
private static void Main()
|
||||||
|
{
|
||||||
|
if (!mutex.WaitOne(TimeSpan.Zero, true))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Application.SetHighDpiMode(HighDpiMode.SystemAware);
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new Form1());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
mutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
docs/Trello_Birdmap.png
Normal file
BIN
docs/Trello_Birdmap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 76 KiB |
98
input.nswag
Normal file
98
input.nswag
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{
|
||||||
|
"runtime": "NetCore31",
|
||||||
|
"defaultVariables": null,
|
||||||
|
"documentGenerator": {
|
||||||
|
"fromDocument": {
|
||||||
|
"json": "openapi: 3.0.3\ninfo:\n title: Input Service\n description: This is the input interface of the Birbnetes system.\n contact:\n email: tormakristof@tormakristof.eu\n license:\n name: Apache 2.0\n url: http://www.apache.org/licenses/LICENSE-2.0.html\n version: 1.1.3\nservers:\n- url: https://birb.k8s.kmlabz.com\ntags:\n- name: input\n description: Input Service interaction\npaths:\n /sample:\n get:\n tags:\n - input\n summary: Get all stored input queries\n operationId: getall\n responses:\n 200:\n description: Array of input objects\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/InputResponse'\n 404:\n description: No object matching filter\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n post:\n tags:\n - input\n summary: uploads a sample into the system\n operationId: uploadFile\n requestBody:\n content:\n multipart/form-data:\n schema:\n required:\n - description\n - file\n properties:\n description:\n type: object\n description: Metadata json\n properties:\n deviceid:\n type: string\n date:\n type: string\n format: date\n file:\n type: string\n description: Wave file to upload\n format: binary\n required: true\n responses:\n 200:\n description: successful operation\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n 400:\n description: JSON parse error\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n 415:\n description: Media type error\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n 417:\n description: JSON invalid schema\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n 469:\n description: No file found\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n 470:\n description: Description missing\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\n /sample/{tagID}:\n get:\n tags:\n - input\n summary: Get input object by ID\n operationId: getInput\n parameters:\n - name: tagID\n in: path\n description: ID of input object file\n required: true\n schema:\n type: string\n format: uuid\n responses:\n 200:\n description: input object\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/InputSingeResponse'\n 404:\n description: Tag not found\n content:\n application/json:\n schema:\n $ref: '#/components/schemas/ApiResponse'\ncomponents:\n schemas:\n InputSingeResponse:\n required:\n - message\n - status\n type: object\n properties:\n status:\n type: string\n message:\n $ref: '#/components/schemas/InputObject'\n InputResponse:\n type: array\n items:\n $ref: '#/components/schemas/InputObject'\n InputObject:\n required:\n - date\n - device_id\n - tag\n type: object\n properties:\n tag:\n type: string\n format: uuid\n date:\n type: string\n format: date\n device_id:\n type: integer\n ApiResponse:\n required:\n - message\n - status\n type: object\n properties:\n status:\n type: string\n message:\n type: string\n",
|
||||||
|
"url": "https://git.kmlabz.com/birbnetes/swagger-docs/raw/branch/master/input.yml",
|
||||||
|
"output": null,
|
||||||
|
"newLineBehavior": "Auto"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"codeGenerators": {
|
||||||
|
"openApiToCSharpClient": {
|
||||||
|
"clientBaseClass": null,
|
||||||
|
"configurationClass": null,
|
||||||
|
"generateClientClasses": true,
|
||||||
|
"generateClientInterfaces": true,
|
||||||
|
"clientBaseInterface": null,
|
||||||
|
"injectHttpClient": true,
|
||||||
|
"disposeHttpClient": true,
|
||||||
|
"protectedMethods": [],
|
||||||
|
"generateExceptionClasses": true,
|
||||||
|
"exceptionClass": "ApiException",
|
||||||
|
"wrapDtoExceptions": true,
|
||||||
|
"useHttpClientCreationMethod": false,
|
||||||
|
"httpClientType": "System.Net.Http.HttpClient",
|
||||||
|
"useHttpRequestMessageCreationMethod": false,
|
||||||
|
"useBaseUrl": true,
|
||||||
|
"generateBaseUrlProperty": true,
|
||||||
|
"generateSyncMethods": false,
|
||||||
|
"exposeJsonSerializerSettings": false,
|
||||||
|
"clientClassAccessModifier": "public",
|
||||||
|
"typeAccessModifier": "public",
|
||||||
|
"generateContractsOutput": false,
|
||||||
|
"contractsNamespace": null,
|
||||||
|
"contractsOutputFilePath": null,
|
||||||
|
"parameterDateTimeFormat": "s",
|
||||||
|
"parameterDateFormat": "yyyy-MM-dd",
|
||||||
|
"generateUpdateJsonSerializerSettingsMethod": true,
|
||||||
|
"useRequestAndResponseSerializationSettings": false,
|
||||||
|
"serializeTypeInformation": false,
|
||||||
|
"queryNullValue": "",
|
||||||
|
"className": "InputService",
|
||||||
|
"operationGenerationMode": "MultipleClientsFromOperationId",
|
||||||
|
"additionalNamespaceUsages": [],
|
||||||
|
"additionalContractNamespaceUsages": [],
|
||||||
|
"generateOptionalParameters": false,
|
||||||
|
"generateJsonMethods": false,
|
||||||
|
"enforceFlagEnums": false,
|
||||||
|
"parameterArrayType": "System.Collections.Generic.IEnumerable",
|
||||||
|
"parameterDictionaryType": "System.Collections.Generic.IDictionary",
|
||||||
|
"responseArrayType": "System.Collections.Generic.ICollection",
|
||||||
|
"responseDictionaryType": "System.Collections.Generic.IDictionary",
|
||||||
|
"wrapResponses": false,
|
||||||
|
"wrapResponseMethods": [],
|
||||||
|
"generateResponseClasses": true,
|
||||||
|
"responseClass": "SwaggerResponse",
|
||||||
|
"namespace": "Birdmap.BLL.Services",
|
||||||
|
"requiredPropertiesMustBeDefined": true,
|
||||||
|
"dateType": "System.DateTimeOffset",
|
||||||
|
"jsonConverters": null,
|
||||||
|
"anyType": "object",
|
||||||
|
"dateTimeType": "System.DateTimeOffset",
|
||||||
|
"timeType": "System.TimeSpan",
|
||||||
|
"timeSpanType": "System.TimeSpan",
|
||||||
|
"arrayType": "System.Collections.Generic.ICollection",
|
||||||
|
"arrayInstanceType": "System.Collections.ObjectModel.Collection",
|
||||||
|
"dictionaryType": "System.Collections.Generic.IDictionary",
|
||||||
|
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
|
||||||
|
"arrayBaseType": "System.Collections.ObjectModel.Collection",
|
||||||
|
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
|
||||||
|
"classStyle": "Poco",
|
||||||
|
"generateDefaultValues": true,
|
||||||
|
"generateDataAnnotations": true,
|
||||||
|
"excludedTypeNames": [],
|
||||||
|
"excludedParameterNames": [],
|
||||||
|
"handleReferences": false,
|
||||||
|
"generateImmutableArrayProperties": false,
|
||||||
|
"generateImmutableDictionaryProperties": false,
|
||||||
|
"jsonSerializerSettingsTransformationMethod": null,
|
||||||
|
"inlineNamedArrays": false,
|
||||||
|
"inlineNamedDictionaries": false,
|
||||||
|
"inlineNamedTuples": true,
|
||||||
|
"inlineNamedAny": false,
|
||||||
|
"generateDtoTypes": true,
|
||||||
|
"generateOptionalPropertiesAsNullable": false,
|
||||||
|
"generateNullableReferenceTypes": false,
|
||||||
|
"templateDirectory": null,
|
||||||
|
"typeNameGeneratorType": null,
|
||||||
|
"propertyNameGeneratorType": null,
|
||||||
|
"enumNameGeneratorType": null,
|
||||||
|
"serviceHost": null,
|
||||||
|
"serviceSchemes": null,
|
||||||
|
"output": null,
|
||||||
|
"newLineBehavior": "Auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
167
input.yml
Normal file
167
input.yml
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
openapi: 3.0.3
|
||||||
|
info:
|
||||||
|
title: Input Service
|
||||||
|
description: This is the input interface of the Birbnetes system.
|
||||||
|
contact:
|
||||||
|
email: tormakristof@tormakristof.eu
|
||||||
|
license:
|
||||||
|
name: Apache 2.0
|
||||||
|
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
version: 1.1.3
|
||||||
|
servers:
|
||||||
|
- url: https://birb.k8s.kmlabz.com
|
||||||
|
tags:
|
||||||
|
- name: input
|
||||||
|
description: Input Service interaction
|
||||||
|
paths:
|
||||||
|
/sample:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- input
|
||||||
|
summary: Get all stored input queries
|
||||||
|
operationId: getall
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Array of input objects
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/InputResponse'
|
||||||
|
404:
|
||||||
|
description: No object matching filter
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- input
|
||||||
|
summary: uploads a sample into the system
|
||||||
|
operationId: uploadFile
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
multipart/form-data:
|
||||||
|
schema:
|
||||||
|
required:
|
||||||
|
- description
|
||||||
|
- file
|
||||||
|
properties:
|
||||||
|
description:
|
||||||
|
type: object
|
||||||
|
description: Metadata json
|
||||||
|
properties:
|
||||||
|
deviceid:
|
||||||
|
type: string
|
||||||
|
date:
|
||||||
|
type: string
|
||||||
|
format: date
|
||||||
|
file:
|
||||||
|
type: string
|
||||||
|
description: Wave file to upload
|
||||||
|
format: binary
|
||||||
|
required: true
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: successful operation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
400:
|
||||||
|
description: JSON parse error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
415:
|
||||||
|
description: Media type error
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
417:
|
||||||
|
description: JSON invalid schema
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
469:
|
||||||
|
description: No file found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
470:
|
||||||
|
description: Description missing
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
/sample/{tagID}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- input
|
||||||
|
summary: Get input object by ID
|
||||||
|
operationId: getInput
|
||||||
|
parameters:
|
||||||
|
- name: tagID
|
||||||
|
in: path
|
||||||
|
description: ID of input object file
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: input object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/InputSingeResponse'
|
||||||
|
404:
|
||||||
|
description: Tag not found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ApiResponse'
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
InputSingeResponse:
|
||||||
|
required:
|
||||||
|
- message
|
||||||
|
- status
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
$ref: '#/components/schemas/InputObject'
|
||||||
|
InputResponse:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/InputObject'
|
||||||
|
InputObject:
|
||||||
|
required:
|
||||||
|
- date
|
||||||
|
- device_id
|
||||||
|
- tag
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
tag:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
date:
|
||||||
|
type: string
|
||||||
|
format: date
|
||||||
|
device_id:
|
||||||
|
type: integer
|
||||||
|
ApiResponse:
|
||||||
|
required:
|
||||||
|
- message
|
||||||
|
- status
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
message:
|
||||||
|
type: string
|
Reference in New Issue
Block a user