Compare commits
27 Commits
8e6759f917
...
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 | |||
7f1a85d430 | |||
05a8d7f090 |
@ -1,12 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<SpaRoot>ClientApp\</SpaRoot>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
|
||||
<AssemblyName>Birdmap.API</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
@ -20,9 +21,9 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="10.1.1" />
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.9">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@ -30,7 +31,13 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</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="NSwag.AspNetCore" Version="13.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@ -42,21 +49,19 @@
|
||||
|
||||
<ItemGroup>
|
||||
<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\AuthClient.ts" />
|
||||
<None Remove="ClientApp\src\components\auth\AuthService.ts" />
|
||||
<None Remove="ClientApp\src\components\devices\DeviceService.ts" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TypeScriptCompile Include="ClientApp\src\components\auth\Auth.tsx" />
|
||||
<TypeScriptCompile Include="ClientApp\src\common\components\BirdmapTitle.tsx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="ClientApp\src\common\components\" />
|
||||
<Folder Include="ClientApp\src\components\dashboard\" />
|
||||
<Folder Include="ClientApp\src\components\devices\" />
|
||||
<Folder Include="ClientApp\src\components\heatmap\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
257
Birdmap.API/ClientApp/package-lock.json
generated
257
Birdmap.API/ClientApp/package-lock.json
generated
@ -1199,6 +1199,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
|
||||
"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": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
||||
@ -1424,6 +1429,11 @@
|
||||
"@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": {
|
||||
"version": "4.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.11.0.tgz",
|
||||
@ -1559,6 +1569,33 @@
|
||||
"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": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||
@ -1733,6 +1770,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/googlemaps": {
|
||||
"version": "3.40.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/googlemaps/-/googlemaps-3.40.3.tgz",
|
||||
"integrity": "sha512-ivlG5S0LlnQgpgPnQCUNAs7kjBtO367ZwDmuK+ggsQfW+w4N0RyWbxWZ6vPwegDe50Du3Xbb5+QVwJuB/U1XpA=="
|
||||
},
|
||||
"@types/history": {
|
||||
"version": "4.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.3.tgz",
|
||||
@ -2165,6 +2207,14 @@
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
||||
"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": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
@ -3401,6 +3451,11 @@
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"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": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
|
||||
@ -3445,6 +3500,11 @@
|
||||
"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": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||
@ -4852,6 +4912,24 @@
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"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": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
@ -4967,6 +5045,11 @@
|
||||
"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": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
@ -5493,6 +5576,11 @@
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"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": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
@ -5852,6 +5940,44 @@
|
||||
"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": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
|
||||
@ -6321,6 +6447,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/google-maps/-/google-maps-4.3.3.tgz",
|
||||
"integrity": "sha512-MQbEgBNQbGyV7mfS2tlFgW4EoGKLia24BvAl4a+kgsYWt4283kyPpaay/yKIsScQLr7nSUONaLNfOdMsCuJDEw==",
|
||||
"requires": {
|
||||
"@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": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.6.tgz",
|
||||
"integrity": "sha512-M8Eo9WndfQEfxcmm6yRq03qdJgw1x6rQmJ9DN+a+xPQ3K7yNDGkVDbinrf4/8vcox7nELbeopbm4bpefKewWfQ=="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
|
||||
@ -7189,6 +7344,15 @@
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
"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": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
@ -8303,6 +8467,16 @@
|
||||
"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": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
@ -8716,6 +8890,15 @@
|
||||
"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": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
@ -10791,6 +10974,50 @@
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.7.tgz",
|
||||
"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": {
|
||||
"version": "16.12.0",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
|
||||
@ -11171,6 +11398,26 @@
|
||||
"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": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
||||
@ -11730,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": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz",
|
||||
@ -13244,6 +13496,11 @@
|
||||
"integrity": "sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==",
|
||||
"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": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
||||
|
@ -6,19 +6,25 @@
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||
"@microsoft/signalr": "^5.0.0",
|
||||
"bootstrap": "^4.3.1",
|
||||
"connected-react-router": "6.5.2",
|
||||
"google-map-react": "^2.1.9",
|
||||
"google-maps": "^4.3.3",
|
||||
"google-maps-react": "^2.0.6",
|
||||
"history": "4.10.1",
|
||||
"jquery": "^3.5.1",
|
||||
"merge": "1.2.1",
|
||||
"popper.js": "^1.16.0",
|
||||
"react": "16.11.0",
|
||||
"react": "^16.11.0",
|
||||
"react-dom": "16.11.0",
|
||||
"react-google-maps": "^9.4.5",
|
||||
"react-redux": "7.1.1",
|
||||
"react-router": "5.1.2",
|
||||
"react-router-dom": "5.1.2",
|
||||
"react-scripts": "^3.4.4",
|
||||
"reactstrap": "8.1.1",
|
||||
"recompose": "^0.30.0",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.3.0",
|
||||
"svgo": "1.3.0"
|
||||
|
@ -22,11 +22,11 @@
|
||||
-->
|
||||
<title>Birdmap</title>
|
||||
</head>
|
||||
<body>
|
||||
<body style="height: 100vh;">
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<div id="root" style="height: 100vh;"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
@ -1,26 +1,32 @@
|
||||
import { Box, Container, IconButton, Menu, MenuItem } 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 AppBar from '@material-ui/core/AppBar';
|
||||
import blue from '@material-ui/core/colors/blue';
|
||||
import orange from '@material-ui/core/colors/orange';
|
||||
import { positions } from '@material-ui/system';
|
||||
import { createMuiTheme, createStyles, makeStyles, Theme } from '@material-ui/core/styles';
|
||||
import Toolbar from '@material-ui/core/Toolbar';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import { ThemeProvider } from '@material-ui/styles';
|
||||
import React, { useState } from 'react';
|
||||
import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
|
||||
import BirdmapTitle from './common/components/BirdmapTitle';
|
||||
import React, { useState, } from 'react';
|
||||
import { BrowserRouter, NavLink, Redirect, Route, Switch, Link } from 'react-router-dom';
|
||||
import BirdmapTitle from './components/appBar/BirdmapTitle';
|
||||
import Auth from './components/auth/Auth';
|
||||
import AuthService from './components/auth/AuthService';
|
||||
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({
|
||||
palette: {
|
||||
primary: {
|
||||
main: blue[900],
|
||||
main: blueGrey[900],
|
||||
dark: grey[400],
|
||||
},
|
||||
secondary: {
|
||||
main: orange[200],
|
||||
dark: blueGrey[50],
|
||||
}
|
||||
},
|
||||
});
|
||||
@ -28,9 +34,11 @@ const theme = createMuiTheme({
|
||||
function App() {
|
||||
|
||||
const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
|
||||
const [isAdmin, setIsAdmin] = useState(AuthService.isAdmin());
|
||||
|
||||
const onAuthenticated = () => {
|
||||
setAuthenticated(AuthService.isAuthenticated());
|
||||
setIsAdmin(AuthService.isAdmin());
|
||||
};
|
||||
|
||||
const AuthComponent = () => {
|
||||
@ -40,15 +48,19 @@ function App() {
|
||||
}
|
||||
|
||||
const DashboardComponent = () => {
|
||||
return <Typography>Dashboard</Typography>;
|
||||
return <Link to="/devices/5">This is a link</Link>;
|
||||
};
|
||||
|
||||
const DevicesComponent = () => {
|
||||
return <Typography>Devices</Typography>;
|
||||
return <Devices isAdmin={isAdmin}/>;
|
||||
|
||||
};
|
||||
const HeatmapComponent = () => {
|
||||
return <Typography>Heatmap</Typography>;
|
||||
return (
|
||||
<Paper elevation={0}>
|
||||
<MapContainer />
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -56,9 +68,11 @@ function App() {
|
||||
<BrowserRouter>
|
||||
<Switch>
|
||||
<PublicRoute path="/login" component={AuthComponent} />
|
||||
<DevicesContextProvider>
|
||||
<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} />
|
||||
</DevicesContextProvider>
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
</ThemeProvider>
|
||||
@ -70,7 +84,7 @@ export default App;
|
||||
const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
|
||||
return (
|
||||
<Route {...rest} render={matchProps => (
|
||||
<DefaultLayout component={Component} authenticated={false} {...matchProps} />
|
||||
<DefaultLayout component={Component} authenticated={false} isAdmin={false} {...matchProps} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
@ -87,53 +101,83 @@ const PrivateRoute = ({ component: Component, authenticated: Authenticated, ...r
|
||||
|
||||
const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
|
||||
const classes = useDefaultLayoutStyles();
|
||||
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
||||
const open = Boolean(anchorEl);
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const anchorRef = React.useRef<HTMLButtonElement>(null);
|
||||
|
||||
const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
const handleToggle = () => {
|
||||
setOpen((prevOpen) => !prevOpen);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
const handleClose = (event: React.MouseEvent<EventTarget>) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleLogout = (event: React.MouseEvent<EventTarget>) => {
|
||||
if (anchorRef.current && anchorRef.current.contains(event.target as HTMLElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AuthService.logout();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
function handleListKeyDown(event: React.KeyboardEvent) {
|
||||
if (event.key === 'Tab') {
|
||||
event.preventDefault();
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
|
||||
const prevOpen = React.useRef(open);
|
||||
React.useEffect(() => {
|
||||
if (prevOpen.current === true && open === false) {
|
||||
anchorRef.current!.focus();
|
||||
}
|
||||
|
||||
prevOpen.current = open;
|
||||
}, [open]);
|
||||
|
||||
|
||||
const renderNavLinks = () => {
|
||||
return Authenticated
|
||||
? <Container className={classes.nav_menu}>
|
||||
<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>
|
||||
<IconButton className={classes.nav_menu_icon}
|
||||
ref={anchorRef}
|
||||
aria-haspopup="true"
|
||||
aria-controls="menu-appbar"
|
||||
aria-controls={open ? 'menu-list-grow' : undefined}
|
||||
aria-label="account of current user"
|
||||
onClick={handleMenu}>
|
||||
onClick={handleToggle}>
|
||||
<AccountCircle/>
|
||||
</IconButton>
|
||||
<Menu
|
||||
id="menu-appbar"
|
||||
anchorEl={anchorEl}
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
keepMounted
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
open={open}
|
||||
onClose={handleClose}>
|
||||
<MenuItem onClick={handleClose}>Logout</MenuItem>
|
||||
</Menu>
|
||||
<Popper open={open} anchorEl={anchorRef.current} role={undefined} transition disablePortal>
|
||||
{({ TransitionProps, placement }) => (
|
||||
<Grow
|
||||
{...TransitionProps}
|
||||
style={{ transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom' }}>
|
||||
<Paper>
|
||||
<ClickAwayListener onClickAway={handleClose}>
|
||||
<MenuList autoFocusItem={open} id="menu-list-grow" onKeyDown={handleListKeyDown}>
|
||||
<MenuItem onClick={handleLogout} component={Link} {...{ to: '/login' }}>Logout</MenuItem>
|
||||
</MenuList>
|
||||
</ClickAwayListener>
|
||||
</Paper>
|
||||
</Grow>
|
||||
)}
|
||||
</Popper>
|
||||
</Container>
|
||||
: null;
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<AppBar position="static">
|
||||
<AppBar position="static" className={classes.bar_root}>
|
||||
<Toolbar>
|
||||
<BirdmapTitle />
|
||||
<Typography component={'span'} className={classes.typo}>
|
||||
@ -141,7 +185,7 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box style={{ margin: '32px' }}>
|
||||
<Box zIndex="modal" className={classes.box_root}>
|
||||
<Component {...rest} />
|
||||
</Box>
|
||||
</React.Fragment>
|
||||
@ -150,6 +194,13 @@ const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...
|
||||
|
||||
const useDefaultLayoutStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
bar_root: {
|
||||
height: '7%',
|
||||
},
|
||||
box_root: {
|
||||
backgroundColor: theme.palette.primary.dark,
|
||||
height: '93%',
|
||||
},
|
||||
typo: {
|
||||
marginLeft: 'auto',
|
||||
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',
|
||||
};
|
616
Birdmap.API/ClientApp/src/common/DeviceService.js
Normal file
616
Birdmap.API/ClientApp/src/common/DeviceService.js
Normal file
@ -0,0 +1,616 @@
|
||||
"use strict";
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
//----------------------
|
||||
// <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>
|
||||
//----------------------
|
||||
// ReSharper disable InconsistentNaming
|
||||
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.SensorStatus = exports.Coordinates = exports.DeviceStatus = exports.Sensor = exports.Device = void 0;
|
||||
var DeviceService = /** @class */ (function () {
|
||||
function DeviceService(baseUrl, http) {
|
||||
this.jsonParseReviver = undefined;
|
||||
this.http = http ? http : window;
|
||||
this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : "api/devices";
|
||||
}
|
||||
/**
|
||||
* Get all device info
|
||||
* @return Array of devices
|
||||
*/
|
||||
DeviceService.prototype.getall = function () {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl;
|
||||
var options_ = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processGetall(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processGetall = 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);
|
||||
if (Array.isArray(resultData200)) {
|
||||
result200 = [];
|
||||
for (var _i = 0, resultData200_1 = resultData200; _i < resultData200_1.length; _i++) {
|
||||
var item = resultData200_1[_i];
|
||||
result200.push(Device.fromJS(item));
|
||||
}
|
||||
}
|
||||
return result200;
|
||||
});
|
||||
}
|
||||
else if (status === 404) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("No device found", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Shut down all devices
|
||||
* @return Message sent
|
||||
*/
|
||||
DeviceService.prototype.offlineall = function () {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/offline";
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processOfflineall(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processOfflineall = 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 === 200) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
else if (status === 500) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Bring all devices online
|
||||
* @return Message sent
|
||||
*/
|
||||
DeviceService.prototype.onlineall = function () {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/online";
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processOnlineall(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processOnlineall = 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 === 200) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
else if (status === 500) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Get all device info
|
||||
* @param deviceID ID of device to query
|
||||
* @return Information about a particular device
|
||||
*/
|
||||
DeviceService.prototype.getdevice = function (deviceID) {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/{deviceID}";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processGetdevice(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processGetdevice = 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 = Device.fromJS(resultData200);
|
||||
return result200;
|
||||
});
|
||||
}
|
||||
else if (status === 404) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Device not found", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Shut down device
|
||||
* @param deviceID ID of device to shut down
|
||||
* @return Message sent
|
||||
*/
|
||||
DeviceService.prototype.offlinedevice = function (deviceID) {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/{deviceID}/offline";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processOfflinedevice(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processOfflinedevice = 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 === 200) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
else if (status === 500) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Bring device online
|
||||
* @param deviceID ID of device to bring online
|
||||
* @return Message sent
|
||||
*/
|
||||
DeviceService.prototype.onlinedevice = function (deviceID) {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/{deviceID}/online";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processOnlinedevice(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processOnlinedevice = 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 === 200) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
else if (status === 500) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Get info about a particular device's sensor
|
||||
* @param deviceID ID of device to query
|
||||
* @param sensorID ID of sensor to query
|
||||
* @return Information about a sensor
|
||||
*/
|
||||
DeviceService.prototype.getsensor = function (deviceID, sensorID) {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/{deviceID}/{sensorID}";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
if (sensorID === undefined || sensorID === null)
|
||||
throw new Error("The parameter 'sensorID' must be defined.");
|
||||
url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processGetsensor(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processGetsensor = 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 = Sensor.fromJS(resultData200);
|
||||
return result200;
|
||||
});
|
||||
}
|
||||
else if (status === 404) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Device or sensor not found", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Shut down sensor
|
||||
* @param deviceID ID of device to query
|
||||
* @param sensorID ID of sensor to query
|
||||
* @return Message sent
|
||||
*/
|
||||
DeviceService.prototype.offlinesensor = function (deviceID, sensorID) {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/{deviceID}/{sensorID}/offline";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
if (sensorID === undefined || sensorID === null)
|
||||
throw new Error("The parameter 'sensorID' must be defined.");
|
||||
url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processOfflinesensor(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processOfflinesensor = 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 === 200) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
else if (status === 500) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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);
|
||||
};
|
||||
/**
|
||||
* Bring sensor online
|
||||
* @param deviceID ID of device to query
|
||||
* @param sensorID ID of sensor to query
|
||||
* @return Message sent
|
||||
*/
|
||||
DeviceService.prototype.onlinesensor = function (deviceID, sensorID) {
|
||||
var _this = this;
|
||||
var url_ = this.baseUrl + "/{deviceID}/{sensorID}/online";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
if (sensorID === undefined || sensorID === null)
|
||||
throw new Error("The parameter 'sensorID' must be defined.");
|
||||
url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
var options_ = {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return this.http.fetch(url_, options_).then(function (_response) {
|
||||
return _this.processOnlinesensor(_response);
|
||||
});
|
||||
};
|
||||
DeviceService.prototype.processOnlinesensor = 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 === 200) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return;
|
||||
});
|
||||
}
|
||||
else if (status === 500) {
|
||||
return response.text().then(function (_responseText) {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
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 DeviceService;
|
||||
}());
|
||||
exports.default = DeviceService;
|
||||
var Device = /** @class */ (function () {
|
||||
function Device(data) {
|
||||
if (data) {
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property))
|
||||
this[property] = data[property];
|
||||
}
|
||||
}
|
||||
if (!data) {
|
||||
this.coordinates = new Coordinates();
|
||||
this.sensors = [];
|
||||
}
|
||||
}
|
||||
Device.prototype.init = function (_data) {
|
||||
if (_data) {
|
||||
this.id = _data["id"];
|
||||
this.status = _data["status"];
|
||||
this.url = _data["url"];
|
||||
this.coordinates = _data["coordinates"] ? Coordinates.fromJS(_data["coordinates"]) : new Coordinates();
|
||||
if (Array.isArray(_data["sensors"])) {
|
||||
this.sensors = [];
|
||||
for (var _i = 0, _a = _data["sensors"]; _i < _a.length; _i++) {
|
||||
var item = _a[_i];
|
||||
this.sensors.push(Sensor.fromJS(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Device.fromJS = function (data) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
var result = new Device();
|
||||
result.init(data);
|
||||
return result;
|
||||
};
|
||||
Device.prototype.toJSON = function (data) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
data["id"] = this.id;
|
||||
data["status"] = this.status;
|
||||
data["url"] = this.url;
|
||||
data["coordinates"] = this.coordinates ? this.coordinates.toJSON() : undefined;
|
||||
if (Array.isArray(this.sensors)) {
|
||||
data["sensors"] = [];
|
||||
for (var _i = 0, _a = this.sensors; _i < _a.length; _i++) {
|
||||
var item = _a[_i];
|
||||
data["sensors"].push(item.toJSON());
|
||||
}
|
||||
}
|
||||
return data;
|
||||
};
|
||||
return Device;
|
||||
}());
|
||||
exports.Device = Device;
|
||||
var Sensor = /** @class */ (function () {
|
||||
function Sensor(data) {
|
||||
if (data) {
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property))
|
||||
this[property] = data[property];
|
||||
}
|
||||
}
|
||||
}
|
||||
Sensor.prototype.init = function (_data) {
|
||||
if (_data) {
|
||||
this.id = _data["id"];
|
||||
this.status = _data["status"];
|
||||
}
|
||||
};
|
||||
Sensor.fromJS = function (data) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
var result = new Sensor();
|
||||
result.init(data);
|
||||
return result;
|
||||
};
|
||||
Sensor.prototype.toJSON = function (data) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
data["id"] = this.id;
|
||||
data["status"] = this.status;
|
||||
return data;
|
||||
};
|
||||
return Sensor;
|
||||
}());
|
||||
exports.Sensor = Sensor;
|
||||
var DeviceStatus;
|
||||
(function (DeviceStatus) {
|
||||
DeviceStatus["Online"] = "online";
|
||||
DeviceStatus["Error"] = "error";
|
||||
DeviceStatus["Offline"] = "offline";
|
||||
})(DeviceStatus = exports.DeviceStatus || (exports.DeviceStatus = {}));
|
||||
var Coordinates = /** @class */ (function () {
|
||||
function Coordinates(data) {
|
||||
if (data) {
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property))
|
||||
this[property] = data[property];
|
||||
}
|
||||
}
|
||||
}
|
||||
Coordinates.prototype.init = function (_data) {
|
||||
if (_data) {
|
||||
this.latitude = _data["latitude"];
|
||||
this.longitude = _data["longitude"];
|
||||
}
|
||||
};
|
||||
Coordinates.fromJS = function (data) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
var result = new Coordinates();
|
||||
result.init(data);
|
||||
return result;
|
||||
};
|
||||
Coordinates.prototype.toJSON = function (data) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
data["latitude"] = this.latitude;
|
||||
data["longitude"] = this.longitude;
|
||||
return data;
|
||||
};
|
||||
return Coordinates;
|
||||
}());
|
||||
exports.Coordinates = Coordinates;
|
||||
var SensorStatus;
|
||||
(function (SensorStatus) {
|
||||
SensorStatus["Online"] = "online";
|
||||
SensorStatus["Unknown"] = "unknown";
|
||||
SensorStatus["Offline"] = "offline";
|
||||
})(SensorStatus = exports.SensorStatus || (exports.SensorStatus = {}));
|
||||
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=DeviceService.js.map
|
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
608
Birdmap.API/ClientApp/src/common/DeviceService.ts
Normal file
608
Birdmap.API/ClientApp/src/common/DeviceService.ts
Normal file
@ -0,0 +1,608 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
//----------------------
|
||||
// <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>
|
||||
//----------------------
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
export default class DeviceService {
|
||||
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 : "api/devices";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all device info
|
||||
* @return Array of devices
|
||||
*/
|
||||
getall(): Promise<Device[]> {
|
||||
let url_ = this.baseUrl;
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processGetall(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processGetall(response: Response): Promise<Device[]> {
|
||||
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);
|
||||
if (Array.isArray(resultData200)) {
|
||||
result200 = [] as any;
|
||||
for (let item of resultData200)
|
||||
result200!.push(Device.fromJS(item));
|
||||
}
|
||||
return result200;
|
||||
});
|
||||
} else if (status === 404) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("No device found", status, _responseText, _headers);
|
||||
});
|
||||
} else if (status !== 200 && status !== 204) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
return Promise.resolve<Device[]>(<any>null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down all devices
|
||||
* @return Message sent
|
||||
*/
|
||||
offlineall(): Promise<void> {
|
||||
let url_ = this.baseUrl + "/offline";
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processOfflineall(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processOfflineall(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 === 200) {
|
||||
return response.text().then((_responseText) => {
|
||||
return;
|
||||
});
|
||||
} else if (status === 500) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring all devices online
|
||||
* @return Message sent
|
||||
*/
|
||||
onlineall(): Promise<void> {
|
||||
let url_ = this.baseUrl + "/online";
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processOnlineall(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processOnlineall(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 === 200) {
|
||||
return response.text().then((_responseText) => {
|
||||
return;
|
||||
});
|
||||
} else if (status === 500) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all device info
|
||||
* @param deviceID ID of device to query
|
||||
* @return Information about a particular device
|
||||
*/
|
||||
getdevice(deviceID: string): Promise<Device> {
|
||||
let url_ = this.baseUrl + "/{deviceID}";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processGetdevice(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processGetdevice(response: Response): Promise<Device> {
|
||||
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 = Device.fromJS(resultData200);
|
||||
return result200;
|
||||
});
|
||||
} else if (status === 404) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Device not found", status, _responseText, _headers);
|
||||
});
|
||||
} else if (status !== 200 && status !== 204) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
return Promise.resolve<Device>(<any>null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down device
|
||||
* @param deviceID ID of device to shut down
|
||||
* @return Message sent
|
||||
*/
|
||||
offlinedevice(deviceID: string): Promise<void> {
|
||||
let url_ = this.baseUrl + "/{deviceID}/offline";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processOfflinedevice(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processOfflinedevice(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 === 200) {
|
||||
return response.text().then((_responseText) => {
|
||||
return;
|
||||
});
|
||||
} else if (status === 500) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring device online
|
||||
* @param deviceID ID of device to bring online
|
||||
* @return Message sent
|
||||
*/
|
||||
onlinedevice(deviceID: string): Promise<void> {
|
||||
let url_ = this.baseUrl + "/{deviceID}/online";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processOnlinedevice(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processOnlinedevice(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 === 200) {
|
||||
return response.text().then((_responseText) => {
|
||||
return;
|
||||
});
|
||||
} else if (status === 500) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get info about a particular device's sensor
|
||||
* @param deviceID ID of device to query
|
||||
* @param sensorID ID of sensor to query
|
||||
* @return Information about a sensor
|
||||
*/
|
||||
getsensor(deviceID: string, sensorID: string): Promise<Sensor> {
|
||||
let url_ = this.baseUrl + "/{deviceID}/{sensorID}";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
if (sensorID === undefined || sensorID === null)
|
||||
throw new Error("The parameter 'sensorID' must be defined.");
|
||||
url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processGetsensor(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processGetsensor(response: Response): Promise<Sensor> {
|
||||
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 = Sensor.fromJS(resultData200);
|
||||
return result200;
|
||||
});
|
||||
} else if (status === 404) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Device or sensor not found", status, _responseText, _headers);
|
||||
});
|
||||
} else if (status !== 200 && status !== 204) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||
});
|
||||
}
|
||||
return Promise.resolve<Sensor>(<any>null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down sensor
|
||||
* @param deviceID ID of device to query
|
||||
* @param sensorID ID of sensor to query
|
||||
* @return Message sent
|
||||
*/
|
||||
offlinesensor(deviceID: string, sensorID: string): Promise<void> {
|
||||
let url_ = this.baseUrl + "/{deviceID}/{sensorID}/offline";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
if (sensorID === undefined || sensorID === null)
|
||||
throw new Error("The parameter 'sensorID' must be defined.");
|
||||
url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processOfflinesensor(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processOfflinesensor(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 === 200) {
|
||||
return response.text().then((_responseText) => {
|
||||
return;
|
||||
});
|
||||
} else if (status === 500) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bring sensor online
|
||||
* @param deviceID ID of device to query
|
||||
* @param sensorID ID of sensor to query
|
||||
* @return Message sent
|
||||
*/
|
||||
onlinesensor(deviceID: string, sensorID: string): Promise<void> {
|
||||
let url_ = this.baseUrl + "/{deviceID}/{sensorID}/online";
|
||||
if (deviceID === undefined || deviceID === null)
|
||||
throw new Error("The parameter 'deviceID' must be defined.");
|
||||
url_ = url_.replace("{deviceID}", encodeURIComponent("" + deviceID));
|
||||
if (sensorID === undefined || sensorID === null)
|
||||
throw new Error("The parameter 'sensorID' must be defined.");
|
||||
url_ = url_.replace("{sensorID}", encodeURIComponent("" + sensorID));
|
||||
url_ = url_.replace(/[?&]$/, "");
|
||||
|
||||
let options_ = <RequestInit>{
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||
return this.processOnlinesensor(_response);
|
||||
});
|
||||
}
|
||||
|
||||
protected processOnlinesensor(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 === 200) {
|
||||
return response.text().then((_responseText) => {
|
||||
return;
|
||||
});
|
||||
} else if (status === 500) {
|
||||
return response.text().then((_responseText) => {
|
||||
return throwException("Message sending unsuccessful", status, _responseText, _headers);
|
||||
});
|
||||
} 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 class Device implements IDevice {
|
||||
id!: string;
|
||||
status!: DeviceStatus;
|
||||
url!: string;
|
||||
coordinates!: Coordinates;
|
||||
sensors!: Sensor[];
|
||||
|
||||
constructor(data?: IDevice) {
|
||||
if (data) {
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property))
|
||||
(<any>this)[property] = (<any>data)[property];
|
||||
}
|
||||
}
|
||||
if (!data) {
|
||||
this.coordinates = new Coordinates();
|
||||
this.sensors = [];
|
||||
}
|
||||
}
|
||||
|
||||
init(_data?: any) {
|
||||
if (_data) {
|
||||
this.id = _data["id"];
|
||||
this.status = _data["status"];
|
||||
this.url = _data["url"];
|
||||
this.coordinates = _data["coordinates"] ? Coordinates.fromJS(_data["coordinates"]) : new Coordinates();
|
||||
if (Array.isArray(_data["sensors"])) {
|
||||
this.sensors = [] as any;
|
||||
for (let item of _data["sensors"])
|
||||
this.sensors!.push(Sensor.fromJS(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static fromJS(data: any): Device {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
let result = new Device();
|
||||
result.init(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
toJSON(data?: any) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
data["id"] = this.id;
|
||||
data["status"] = this.status;
|
||||
data["url"] = this.url;
|
||||
data["coordinates"] = this.coordinates ? this.coordinates.toJSON() : <any>undefined;
|
||||
if (Array.isArray(this.sensors)) {
|
||||
data["sensors"] = [];
|
||||
for (let item of this.sensors)
|
||||
data["sensors"].push(item.toJSON());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IDevice {
|
||||
id: string;
|
||||
status: DeviceStatus;
|
||||
url: string;
|
||||
coordinates: Coordinates;
|
||||
sensors: Sensor[];
|
||||
}
|
||||
|
||||
export class Sensor implements ISensor {
|
||||
id!: string;
|
||||
status!: SensorStatus;
|
||||
|
||||
constructor(data?: ISensor) {
|
||||
if (data) {
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property))
|
||||
(<any>this)[property] = (<any>data)[property];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(_data?: any) {
|
||||
if (_data) {
|
||||
this.id = _data["id"];
|
||||
this.status = _data["status"];
|
||||
}
|
||||
}
|
||||
|
||||
static fromJS(data: any): Sensor {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
let result = new Sensor();
|
||||
result.init(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
toJSON(data?: any) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
data["id"] = this.id;
|
||||
data["status"] = this.status;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ISensor {
|
||||
id: string;
|
||||
status: SensorStatus;
|
||||
}
|
||||
|
||||
export enum DeviceStatus {
|
||||
Online = "online",
|
||||
Error = "error",
|
||||
Offline = "offline",
|
||||
}
|
||||
|
||||
export class Coordinates implements ICoordinates {
|
||||
latitude!: number;
|
||||
longitude!: number;
|
||||
|
||||
constructor(data?: ICoordinates) {
|
||||
if (data) {
|
||||
for (var property in data) {
|
||||
if (data.hasOwnProperty(property))
|
||||
(<any>this)[property] = (<any>data)[property];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init(_data?: any) {
|
||||
if (_data) {
|
||||
this.latitude = _data["latitude"];
|
||||
this.longitude = _data["longitude"];
|
||||
}
|
||||
}
|
||||
|
||||
static fromJS(data: any): Coordinates {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
let result = new Coordinates();
|
||||
result.init(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
toJSON(data?: any) {
|
||||
data = typeof data === 'object' ? data : {};
|
||||
data["latitude"] = this.latitude;
|
||||
data["longitude"] = this.longitude;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export interface ICoordinates {
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
|
||||
export enum SensorStatus {
|
||||
Online = "online",
|
||||
Unknown = "unknown",
|
||||
Offline = "offline",
|
||||
}
|
||||
|
||||
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,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
|
||||
};
|
@ -5,6 +5,7 @@ import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
|
||||
import AuthService from './AuthService';
|
||||
|
||||
export default function Auth(props: any) {
|
||||
props.onAuthenticated();
|
||||
const history = useHistory();
|
||||
const classes = useStyles();
|
||||
|
||||
@ -36,7 +37,6 @@ export default function Auth(props: any) {
|
||||
};
|
||||
|
||||
const onLoginClicked = () => {
|
||||
setIsLoggingIn(true);
|
||||
|
||||
if (!username) {
|
||||
setShowError(true);
|
||||
@ -52,15 +52,16 @@ export default function Auth(props: any) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoggingIn(true);
|
||||
AuthService.login(username, password)
|
||||
.then(() => {
|
||||
setIsLoggingIn(false);
|
||||
props.onAuthenticated();
|
||||
history.push('/');
|
||||
}).catch(() => {
|
||||
setShowError(true);
|
||||
setErrorMessage('Invalid credentials');
|
||||
}).finally(() => {
|
||||
setIsLoggingIn(false);
|
||||
setErrorMessage('Invalid credentials');
|
||||
});
|
||||
};
|
||||
|
||||
@ -86,7 +87,7 @@ export default function Auth(props: any) {
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<TextField label="Username" type="text" onChange={onUsernameChanged} />
|
||||
<TextField autoFocus label="Username" type="text" onChange={onUsernameChanged} />
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<TextField label="Password" type="password" onChange={onPasswordChanged} onKeyPress={onPasswordKeyPress} />
|
||||
|
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,30 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ServiceBase_1 = require("../../common/ServiceBase");
|
||||
var login_url = 'api/auth/authenticate';
|
||||
var AuthClient_1 = require("./AuthClient");
|
||||
exports.default = {
|
||||
isAuthenticated: function () {
|
||||
return sessionStorage.getItem('user') !== null;
|
||||
return sessionStorage.getItem('user') !== null && sessionStorage.getItem('user') !== undefined;
|
||||
},
|
||||
isAdmin: function () {
|
||||
return sessionStorage.getItem('role') === 'Admin';
|
||||
},
|
||||
logout: function () {
|
||||
sessionStorage.removeItem('user');
|
||||
sessionStorage.removeItem('role');
|
||||
},
|
||||
login: function (username, password) {
|
||||
var body = {
|
||||
var service = new AuthClient_1.default();
|
||||
var request = new AuthClient_1.AuthenticateRequest({
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
var options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
return ServiceBase_1.default.makeRequest(login_url, options)
|
||||
});
|
||||
return service.authenticate(request)
|
||||
.then(function (response) {
|
||||
sessionStorage.setItem('user', response.token_type + " " + response.access_token);
|
||||
sessionStorage.setItem('role', response.role);
|
||||
//console.log(response);
|
||||
sessionStorage.setItem('user', response.tokenType + " " + response.accessToken);
|
||||
sessionStorage.setItem('role', response.userRole);
|
||||
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,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,33 +1,32 @@
|
||||
import ServiceBase from '../../common/ServiceBase';
|
||||
|
||||
const login_url = 'api/auth/authenticate';
|
||||
import AuthClient, { AuthenticateRequest } from './AuthClient';
|
||||
|
||||
export default {
|
||||
isAuthenticated() {
|
||||
return sessionStorage.getItem('user') !== null;
|
||||
return sessionStorage.getItem('user') !== null && sessionStorage.getItem('user') !== undefined;
|
||||
},
|
||||
|
||||
isAdmin() {
|
||||
return sessionStorage.getItem('role') === 'Admin';
|
||||
},
|
||||
|
||||
logout() {
|
||||
sessionStorage.removeItem('user');
|
||||
sessionStorage.removeItem('role');
|
||||
},
|
||||
|
||||
login(username: string, password: string) {
|
||||
let body = {
|
||||
const service = new AuthClient();
|
||||
|
||||
let request = new AuthenticateRequest({
|
||||
username: username,
|
||||
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 => {
|
||||
sessionStorage.setItem('user', `${response.token_type} ${response.access_token}`);
|
||||
sessionStorage.setItem('role', response.role);
|
||||
//console.log(response);
|
||||
sessionStorage.setItem('user', `${response.tokenType} ${response.accessToken}`);
|
||||
sessionStorage.setItem('role', response.userRole);
|
||||
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));
|
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>
|
||||
);
|
||||
}
|
||||
}
|
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>
|
||||
);
|
||||
};
|
||||
}
|
@ -35,8 +35,7 @@ namespace Birdmap.Controllers
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("authenticate")]
|
||||
[ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
|
||||
[HttpPost("authenticate"), ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
|
||||
public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest model)
|
||||
{
|
||||
_logger.LogInformation($"Authenticating user [{model.Username}] with password [*******]...");
|
||||
@ -70,8 +69,7 @@ namespace Birdmap.Controllers
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("register")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[HttpPost("register"), ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> RegisterAsync([FromBody] RegisterRequest model)
|
||||
{
|
||||
_logger.LogInformation($"Registering user [{model.Username}]...");
|
||||
|
161
Birdmap.API/Controllers/DevicesController.cs
Normal file
161
Birdmap.API/Controllers/DevicesController.cs
Normal file
@ -0,0 +1,161 @@
|
||||
using Birdmap.BLL.Interfaces;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Birdmap.API.Services.Hubs;
|
||||
using Birdmap.API.Services;
|
||||
|
||||
namespace Birdmap.API.Controllers
|
||||
{
|
||||
[Authorize(Roles = "User, Admin")]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class DevicesController : ControllerBase
|
||||
{
|
||||
private readonly IDeviceService _service;
|
||||
private readonly IHubContext<DevicesHub, IDevicesHubClient> _hubContext;
|
||||
private readonly ILogger<ServicesController> _logger;
|
||||
|
||||
public DevicesController(IDeviceService service, IHubContext<DevicesHub, IDevicesHubClient> hubContext, ILogger<ServicesController> logger)
|
||||
{
|
||||
_service = service;
|
||||
_hubContext = hubContext;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>Get all device info</summary>
|
||||
/// <returns>Array of devices</returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<Device>>> Getall()
|
||||
{
|
||||
_logger.LogInformation("Getting all devices...");
|
||||
|
||||
return (await _service.GetallAsync()).ToList();
|
||||
}
|
||||
|
||||
/// <summary>Shut down all devices</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, Route("offline")]
|
||||
public async Task<IActionResult> Offlineall()
|
||||
{
|
||||
_logger.LogInformation("Turning off all devices and sensors...");
|
||||
|
||||
await _service.OfflineallAsync();
|
||||
await _hubContext.Clients.All.NotifyAllUpdatedAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>Bring all devices online</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, Route("online")]
|
||||
public async Task<IActionResult> Onlineall()
|
||||
{
|
||||
_logger.LogInformation("Turning on all devices and sensors...");
|
||||
|
||||
await _service.OnlineallAsync();
|
||||
await _hubContext.Clients.All.NotifyAllUpdatedAsync();
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>Get all device info</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <returns>Information about a particular device</returns>
|
||||
[HttpGet, Route("{deviceID}")]
|
||||
public async Task<ActionResult<Device>> Getdevice([BindRequired] Guid deviceID)
|
||||
{
|
||||
_logger.LogInformation($"Getting device [{deviceID}]...");
|
||||
|
||||
return await _service.GetdeviceAsync(deviceID);
|
||||
}
|
||||
|
||||
/// <summary>Shut down device</summary>
|
||||
/// <param name="deviceID">ID of device to shut down</param>
|
||||
/// <returns>Message sent</returns>
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, Route("{deviceID}/offline")]
|
||||
public async Task<IActionResult> Offlinedevice([BindRequired] Guid deviceID)
|
||||
{
|
||||
_logger.LogInformation($"Turning off device [{deviceID}]...");
|
||||
|
||||
await _service.OfflinedeviceAsync(deviceID);
|
||||
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>Bring device online</summary>
|
||||
/// <param name="deviceID">ID of device to bring online</param>
|
||||
/// <returns>Message sent</returns>
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, Route("{deviceID}/online")]
|
||||
public async Task<IActionResult> Onlinedevice([BindRequired] Guid deviceID)
|
||||
{
|
||||
_logger.LogInformation($"Turning on device [{deviceID}]...");
|
||||
|
||||
await _service.OnlinedeviceAsync(deviceID);
|
||||
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>Get info about a particular device's sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Information about a sensor</returns>
|
||||
[HttpGet, Route("{deviceID}/{sensorID}")]
|
||||
public async Task<ActionResult<Sensor>> Getsensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
||||
{
|
||||
_logger.LogInformation($"Getting sensor [{sensorID}] of device [{deviceID}]...");
|
||||
|
||||
return await _service.GetsensorAsync(deviceID, sensorID);
|
||||
}
|
||||
|
||||
/// <summary>Shut down sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, Route("{deviceID}/{sensorID}/offline")]
|
||||
public async Task<IActionResult> Offlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
||||
{
|
||||
_logger.LogInformation($"Turning off sensor [{sensorID}] of device [{deviceID}]...");
|
||||
|
||||
await _service.OfflinesensorAsync(deviceID, sensorID);
|
||||
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
/// <summary>Bring sensor online</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, Route("{deviceID}/{sensorID}/online")]
|
||||
public async Task<IActionResult> Onlinesensor([BindRequired] Guid deviceID, [BindRequired] Guid sensorID)
|
||||
{
|
||||
_logger.LogInformation($"Turning on sensor [{sensorID}] of device [{deviceID}]...");
|
||||
|
||||
await _service.OnlinesensorAsync(deviceID, sensorID);
|
||||
await _hubContext.Clients.All.NotifyDeviceUpdatedAsync(deviceID);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore 1591
|
||||
#pragma warning restore 1573
|
||||
#pragma warning restore 472
|
||||
#pragma warning restore 114
|
||||
#pragma warning restore 108
|
@ -14,7 +14,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Birdmap.API.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
[Authorize(Roles = "User, Admin")]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ServicesController : ControllerBase
|
||||
@ -30,8 +30,7 @@ namespace Birdmap.API.Controllers
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[HttpGet, ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<List<ServiceInfo>>> GetAsync()
|
||||
{
|
||||
_logger.LogInformation($"Getting all services from db...");
|
||||
@ -59,8 +58,8 @@ namespace Birdmap.API.Controllers
|
||||
return serviceInfos.ToList();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPost, ProducesResponseType(StatusCodes.Status201Created)]
|
||||
public async Task<ActionResult<ServiceRequest>> PostAsync(ServiceRequest request)
|
||||
{
|
||||
_logger.LogInformation($"Creating service [{request.Name}]...");
|
||||
@ -74,8 +73,8 @@ namespace Birdmap.API.Controllers
|
||||
_mapper.Map<ServiceRequest>(created));
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpPut, ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> PutAsync(ServiceRequest request)
|
||||
{
|
||||
_logger.LogInformation($"Updating service [{request.Name}]...");
|
||||
@ -87,8 +86,8 @@ namespace Birdmap.API.Controllers
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[Authorize(Roles = "Admin")]
|
||||
[HttpDelete("{id}"), ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
public async Task<IActionResult> DeleteAsync(int id)
|
||||
{
|
||||
_logger.LogInformation($"Deleting service [{id}]...");
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Birdmap.Models
|
||||
{
|
||||
public class AuthenticateRequest
|
||||
public record AuthenticateRequest
|
||||
{
|
||||
[Required(AllowEmptyStrings = false, ErrorMessage = "Username is required.")]
|
||||
public string Username { get; set; }
|
||||
|
@ -3,7 +3,7 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Birdmap.API.DTOs
|
||||
{
|
||||
public class AuthenticateResponse
|
||||
public record AuthenticateResponse
|
||||
{
|
||||
[JsonProperty("user_name")]
|
||||
public string Username { get; set; }
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Birdmap.API.DTOs
|
||||
{
|
||||
public class RegisterRequest
|
||||
public record RegisterRequest
|
||||
{
|
||||
[Required(AllowEmptyStrings = false, ErrorMessage = "Username is required.")]
|
||||
public string Username { get; set; }
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Birdmap.API.DTOs
|
||||
{
|
||||
public class ServiceInfo
|
||||
public record ServiceInfo
|
||||
{
|
||||
public ServiceRequest Service { get; set; }
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Birdmap.API.DTOs
|
||||
{
|
||||
public class ServiceRequest
|
||||
public record ServiceRequest
|
||||
{
|
||||
public int Id { 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 Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -8,7 +7,7 @@ using NLog;
|
||||
using NLog.Web;
|
||||
using System;
|
||||
|
||||
namespace Birdmap
|
||||
namespace Birdmap.API
|
||||
{
|
||||
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 Birdmap.API;
|
||||
using Birdmap.API.Extensions;
|
||||
using Birdmap.API.Middlewares;
|
||||
using Birdmap.API.Services.Hubs;
|
||||
using Birdmap.BLL;
|
||||
using Birdmap.DAL;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
@ -11,9 +12,10 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using NSwag.Generation.Processors.Security;
|
||||
using System.Text;
|
||||
|
||||
namespace Birdmap
|
||||
namespace Birdmap.API
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
@ -40,6 +42,8 @@ namespace Birdmap
|
||||
|
||||
services.AddAutoMapper(typeof(Startup));
|
||||
|
||||
services.AddSignalR();
|
||||
|
||||
var key = Encoding.ASCII.GetBytes(Configuration["Secret"]);
|
||||
services.AddAuthentication(opt =>
|
||||
{
|
||||
@ -48,7 +52,7 @@ namespace Birdmap
|
||||
})
|
||||
.AddJwtBearer(opt =>
|
||||
{
|
||||
// opt.RequireHttpsMetadata = false;
|
||||
//opt.RequireHttpsMetadata = false;
|
||||
opt.SaveToken = true;
|
||||
opt.IncludeErrorDetails = true;
|
||||
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
|
||||
services.AddSpaStaticFiles(configuration =>
|
||||
{
|
||||
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.
|
||||
@ -74,24 +119,26 @@ namespace Birdmap
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
app.UseMiddleware<ExceptionHandlerMiddleware>();
|
||||
}
|
||||
|
||||
app.UseOpenApi();
|
||||
app.UseSwaggerUi3();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseStaticFiles();
|
||||
app.UseSpaStaticFiles();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseAuthorization();
|
||||
app.UseAuthentication();
|
||||
app.UseRouting();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapHealthChecks("/health");
|
||||
endpoints.MapControllers();
|
||||
endpoints.MapHub<DevicesHub>("/hubs/devices");
|
||||
});
|
||||
|
||||
app.UseSpa(spa =>
|
||||
|
@ -8,7 +8,8 @@
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Secret": "7vj.3KW.hYE!}4u6",
|
||||
"LocalDbConnectionString": "Data Source=DESKTOP-A6JQ6B5\\SQLEXPRESS;Initial Catalog=Birdmap;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
||||
// "LocalDbConnectionString": "Data Source=DESKTOP-3600\\SQLEXPRESS;Initial Catalog=birdmap;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
||||
"LocalDbConnectionString": "Data Source=DESKTOP-3600;Initial Catalog=birdmap;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
|
||||
"Defaults": {
|
||||
"Services": {
|
||||
"Local Database": "https://localhost:44331/health",
|
||||
@ -26,5 +27,19 @@
|
||||
"Role": "User"
|
||||
}
|
||||
]
|
||||
},
|
||||
"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 -->
|
||||
<targets async="true">
|
||||
<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"
|
||||
layout="${longdate} [${event-properties:item=EventId_Id}] ${uppercase:${level}} ${logger} - ${message} ${exception:format=tostring}" />
|
||||
<target xsi:type="File" name="allFile" fileName="${basedir}Log/birdmap-all-${shortdate}.log"
|
||||
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 -->
|
||||
<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>
|
||||
|
||||
<!-- rules to map from logger name to target +-->
|
||||
<rules>
|
||||
<!--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" />
|
||||
<!-- BlackHole without writeTo -->
|
||||
|
||||
<logger name="*" minlevel="Trace" writeTo="ownFile" />
|
||||
</rules>
|
||||
</nlog>
|
@ -1,9 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Birdmap.Common\Birdmap.Common.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()));
|
||||
}
|
||||
}
|
||||
}
|
279
Birdmap.BLL/Interfaces/IDeviceService.cs
Normal file
279
Birdmap.BLL/Interfaces/IDeviceService.cs
Normal file
@ -0,0 +1,279 @@
|
||||
namespace Birdmap.BLL.Interfaces
|
||||
{
|
||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||
public partial class ListOfDevices : System.Collections.ObjectModel.Collection<Device>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||
public partial class Device
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)]
|
||||
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||
public System.Guid Id { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Always)]
|
||||
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||
public DeviceStatus Status { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("url", Required = Newtonsoft.Json.Required.Always)]
|
||||
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||
public string Url { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("coordinates", Required = Newtonsoft.Json.Required.AllowNull)]
|
||||
[System.ComponentModel.DataAnnotations.Required]
|
||||
public Coordinates Coordinates { get; set; } = new Coordinates();
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("sensors", Required = Newtonsoft.Json.Required.Always)]
|
||||
[System.ComponentModel.DataAnnotations.Required]
|
||||
public ArrayofSensors Sensors { get; set; } = new ArrayofSensors();
|
||||
|
||||
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 ArrayofSensors : System.Collections.ObjectModel.Collection<Sensor>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||
public partial class Sensor
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.Always)]
|
||||
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||
public System.Guid Id { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Always)]
|
||||
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
|
||||
public SensorStatus Status { 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 Coordinates
|
||||
{
|
||||
[Newtonsoft.Json.JsonProperty("latitude", Required = Newtonsoft.Json.Required.Always)]
|
||||
public double Latitude { get; set; }
|
||||
|
||||
[Newtonsoft.Json.JsonProperty("longitude", Required = Newtonsoft.Json.Required.Always)]
|
||||
public double Longitude { 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 enum DeviceStatus
|
||||
{
|
||||
[System.Runtime.Serialization.EnumMember(Value = @"online")]
|
||||
Online = 0,
|
||||
|
||||
[System.Runtime.Serialization.EnumMember(Value = @"error")]
|
||||
Error = 1,
|
||||
|
||||
[System.Runtime.Serialization.EnumMember(Value = @"offline")]
|
||||
Offline = 2,
|
||||
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.2.1.0 (Newtonsoft.Json v12.0.0.0)")]
|
||||
public enum SensorStatus
|
||||
{
|
||||
[System.Runtime.Serialization.EnumMember(Value = @"online")]
|
||||
Online = 0,
|
||||
|
||||
[System.Runtime.Serialization.EnumMember(Value = @"unknown")]
|
||||
Unknown = 1,
|
||||
|
||||
[System.Runtime.Serialization.EnumMember(Value = @"offline")]
|
||||
Offline = 2,
|
||||
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
|
||||
public partial class ApiException : System.Exception
|
||||
{
|
||||
public int StatusCode { get; private set; }
|
||||
|
||||
public string Response { get; private set; }
|
||||
|
||||
public System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> Headers { get; private set; }
|
||||
|
||||
public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers, System.Exception innerException)
|
||||
: base(message + "\n\nStatus: " + statusCode + "\nResponse: \n" + ((response == null) ? "(null)" : response.Substring(0, response.Length >= 512 ? 512 : response.Length)), innerException)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
Response = response;
|
||||
Headers = headers;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("HTTP Response: \n\n{0}\n\n{1}", Response, base.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
|
||||
public partial class ApiException<TResult> : ApiException
|
||||
{
|
||||
public TResult Result { get; private set; }
|
||||
|
||||
public ApiException(string message, int statusCode, string response, System.Collections.Generic.IReadOnlyDictionary<string, System.Collections.Generic.IEnumerable<string>> headers, TResult result, System.Exception innerException)
|
||||
: base(message, statusCode, response, headers, innerException)
|
||||
{
|
||||
Result = result;
|
||||
}
|
||||
}
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.8.2.0 (NJsonSchema v10.2.1.0 (Newtonsoft.Json v12.0.0.0))")]
|
||||
public partial interface IDeviceService
|
||||
{
|
||||
/// <summary>Get all device info</summary>
|
||||
/// <returns>Array of devices</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<Device>> GetallAsync();
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Get all device info</summary>
|
||||
/// <returns>Array of devices</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task<System.Collections.Generic.ICollection<Device>> GetallAsync(System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Shut down all devices</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OfflineallAsync();
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Shut down all devices</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OfflineallAsync(System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Bring all devices online</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OnlineallAsync();
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Bring all devices online</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OnlineallAsync(System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Get all device info</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <returns>Information about a particular device</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task<Device> GetdeviceAsync(System.Guid deviceID);
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Get all device info</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <returns>Information about a particular device</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task<Device> GetdeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Shut down device</summary>
|
||||
/// <param name="deviceID">ID of device to shut down</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID);
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Shut down device</summary>
|
||||
/// <param name="deviceID">ID of device to shut down</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Bring device online</summary>
|
||||
/// <param name="deviceID">ID of device to bring online</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID);
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Bring device online</summary>
|
||||
/// <param name="deviceID">ID of device to bring online</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Get info about a particular device's sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Information about a sensor</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task<Sensor> GetsensorAsync(System.Guid deviceID, System.Guid sensorID);
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Get info about a particular device's sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Information about a sensor</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task<Sensor> GetsensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Shut down sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID);
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Shut down sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>Bring sensor online</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID);
|
||||
|
||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||
/// <summary>Bring sensor online</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
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; }
|
||||
}
|
||||
|
||||
}
|
43
Birdmap.BLL/Services/DeviceAndInputServiceBase.cs
Normal file
43
Birdmap.BLL/Services/DeviceAndInputServiceBase.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using Birdmap.BLL.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Birdmap.BLL.Services
|
||||
{
|
||||
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()
|
||||
=> GetallAsync(CancellationToken.None);
|
||||
public abstract Task<ICollection<Device>> GetallAsync(CancellationToken cancellationToken);
|
||||
public virtual Task<Device> GetdeviceAsync(Guid deviceID)
|
||||
=> GetdeviceAsync(deviceID, CancellationToken.None);
|
||||
public abstract Task<Device> GetdeviceAsync(Guid deviceID, CancellationToken cancellationToken);
|
||||
public virtual Task<Sensor> GetsensorAsync(Guid deviceID, Guid sensorID)
|
||||
=> GetsensorAsync(deviceID, sensorID, CancellationToken.None);
|
||||
public abstract Task<Sensor> GetsensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken);
|
||||
public virtual Task OfflineallAsync()
|
||||
=> OfflineallAsync(CancellationToken.None);
|
||||
public abstract Task OfflineallAsync(CancellationToken cancellationToken);
|
||||
public virtual Task OfflinedeviceAsync(Guid deviceID)
|
||||
=> OfflinedeviceAsync(deviceID, CancellationToken.None);
|
||||
public abstract Task OfflinedeviceAsync(Guid deviceID, CancellationToken cancellationToken);
|
||||
public virtual Task OfflinesensorAsync(Guid deviceID, Guid sensorID)
|
||||
=> OfflinesensorAsync(deviceID, sensorID, CancellationToken.None);
|
||||
public abstract Task OfflinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken);
|
||||
public virtual Task OnlineallAsync()
|
||||
=> OnlineallAsync(CancellationToken.None);
|
||||
public abstract Task OnlineallAsync(CancellationToken cancellationToken);
|
||||
public virtual Task OnlinedeviceAsync(Guid deviceID)
|
||||
=> OnlinedeviceAsync(deviceID, CancellationToken.None);
|
||||
public abstract Task OnlinedeviceAsync(Guid deviceID, CancellationToken cancellationToken);
|
||||
public virtual Task OnlinesensorAsync(Guid deviceID, Guid sensorID)
|
||||
=> OnlinesensorAsync(deviceID, sensorID, CancellationToken.None);
|
||||
public abstract Task OnlinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
171
Birdmap.BLL/Services/DummyDeviceAndInputService.cs
Normal file
171
Birdmap.BLL/Services/DummyDeviceAndInputService.cs
Normal file
@ -0,0 +1,171 @@
|
||||
using Birdmap.BLL.Helpers;
|
||||
using Birdmap.BLL.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Birdmap.BLL.Services
|
||||
{
|
||||
public class DummyDeviceAndInputService : DeviceAndInputServiceBase
|
||||
{
|
||||
private const int numberOfDevices = 15;
|
||||
|
||||
private const double centerLong = 21.469640;
|
||||
private const double centerLat = 48.275939;
|
||||
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 static ListOfDevices GenerateDevices()
|
||||
{
|
||||
var devices = new ListOfDevices();
|
||||
|
||||
T GetRandomEnum<T>()
|
||||
{
|
||||
var values = Enum.GetValues(typeof(T));
|
||||
return (T)values.GetValue(Rand.Next(values.Length));
|
||||
}
|
||||
|
||||
double GetPlusMinus(double center, double radius)
|
||||
{
|
||||
return center - radius + Rand.NextDouble() * radius * 2;
|
||||
}
|
||||
|
||||
for (int d = 0; d < numberOfDevices; d++)
|
||||
{
|
||||
var sensors = new ArrayofSensors();
|
||||
for (int s = 0; s < Rand.Next(1, 6); s++)
|
||||
{
|
||||
sensors.Add(new Sensor
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Status = GetRandomEnum<SensorStatus>(),
|
||||
});
|
||||
}
|
||||
|
||||
devices.Add(new Device
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Sensors = sensors,
|
||||
Status = GetRandomEnum<DeviceStatus>(),
|
||||
Url = "dummyservice.device.url",
|
||||
Coordinates = new Coordinates
|
||||
{
|
||||
Latitude = GetPlusMinus(centerLat, radius),
|
||||
Longitude = GetPlusMinus(centerLong, radius),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
public override Task<ICollection<Device>> GetallAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(Devices.Value);
|
||||
}
|
||||
|
||||
public override Task<Device> GetdeviceAsync(Guid deviceID, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(Devices.Value.SingleOrDefault(d => d.Id == deviceID));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
public override Task OfflineallAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
SetStatus(DeviceStatus.Offline, SensorStatus.Offline);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OfflinedeviceAsync(Guid deviceID, CancellationToken cancellationToken)
|
||||
{
|
||||
SetDeviceStatus(deviceID, DeviceStatus.Offline);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OfflinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
|
||||
{
|
||||
SetSensorStatus(deviceID, sensorID, SensorStatus.Offline);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OnlineallAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
SetStatus(DeviceStatus.Online, SensorStatus.Online);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OnlinedeviceAsync(Guid deviceID, CancellationToken cancellationToken)
|
||||
{
|
||||
SetDeviceStatus(deviceID, DeviceStatus.Online);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task OnlinesensorAsync(Guid deviceID, Guid sensorID, CancellationToken cancellationToken)
|
||||
{
|
||||
SetSensorStatus(deviceID, sensorID, SensorStatus.Online);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void SetStatus(DeviceStatus deviceStatus, SensorStatus sensorStatus)
|
||||
{
|
||||
foreach (var device in Devices.Value)
|
||||
{
|
||||
device.Status = deviceStatus;
|
||||
foreach (var sensor in device.Sensors)
|
||||
{
|
||||
sensor.Status = sensorStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDeviceStatus(Guid deviceID, DeviceStatus status)
|
||||
{
|
||||
var device = GetdeviceAsync(deviceID).Result;
|
||||
device.Status = status;
|
||||
}
|
||||
|
||||
private void SetSensorStatus(Guid deviceId, Guid sensorID, SensorStatus status)
|
||||
{
|
||||
var sensor = GetsensorAsync(deviceId, sensorID).Result;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
904
Birdmap.BLL/Services/LiveDeviceService.cs
Normal file
904
Birdmap.BLL/Services/LiveDeviceService.cs
Normal file
@ -0,0 +1,904 @@
|
||||
//----------------------
|
||||
// <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 LiveDummyService : IDeviceService
|
||||
{
|
||||
private string _baseUrl = "https://birb.k8s.kmlabz.com";
|
||||
private System.Net.Http.HttpClient _httpClient;
|
||||
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
|
||||
|
||||
public LiveDummyService(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 device info</summary>
|
||||
/// <returns>Array of devices</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task<System.Collections.Generic.ICollection<Device>> 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 device info</summary>
|
||||
/// <returns>Array of devices</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task<System.Collections.Generic.ICollection<Device>> GetallAsync(System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices");
|
||||
|
||||
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<Device>>(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)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("No device found", status_, responseText_, headers_, 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>Shut down all devices</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task OfflineallAsync()
|
||||
{
|
||||
return OfflineallAsync(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>Shut down all devices</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task OfflineallAsync(System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/offline");
|
||||
|
||||
var client_ = _httpClient;
|
||||
var disposeClient_ = false;
|
||||
try
|
||||
{
|
||||
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||
{
|
||||
request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
|
||||
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (status_ == 500)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, 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>Bring all devices online</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task OnlineallAsync()
|
||||
{
|
||||
return OnlineallAsync(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>Bring all devices online</summary>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task OnlineallAsync(System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/online");
|
||||
|
||||
var client_ = _httpClient;
|
||||
var disposeClient_ = false;
|
||||
try
|
||||
{
|
||||
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||
{
|
||||
request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
|
||||
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (status_ == 500)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, 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 all device info</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <returns>Information about a particular device</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task<Device> GetdeviceAsync(System.Guid deviceID)
|
||||
{
|
||||
return GetdeviceAsync(deviceID, 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 device info</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <returns>Information about a particular device</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task<Device> GetdeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
if (deviceID == null)
|
||||
throw new System.ArgumentNullException("deviceID");
|
||||
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}");
|
||||
urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, 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<Device>(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)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Device not found", status_, responseText_, headers_, 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>Shut down device</summary>
|
||||
/// <param name="deviceID">ID of device to shut down</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID)
|
||||
{
|
||||
return OfflinedeviceAsync(deviceID, 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>Shut down device</summary>
|
||||
/// <param name="deviceID">ID of device to shut down</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task OfflinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
if (deviceID == null)
|
||||
throw new System.ArgumentNullException("deviceID");
|
||||
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/offline");
|
||||
urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
|
||||
var client_ = _httpClient;
|
||||
var disposeClient_ = false;
|
||||
try
|
||||
{
|
||||
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||
{
|
||||
request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
|
||||
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (status_ == 500)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, 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>Bring device online</summary>
|
||||
/// <param name="deviceID">ID of device to bring online</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID)
|
||||
{
|
||||
return OnlinedeviceAsync(deviceID, 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>Bring device online</summary>
|
||||
/// <param name="deviceID">ID of device to bring online</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task OnlinedeviceAsync(System.Guid deviceID, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
if (deviceID == null)
|
||||
throw new System.ArgumentNullException("deviceID");
|
||||
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/online");
|
||||
urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
|
||||
var client_ = _httpClient;
|
||||
var disposeClient_ = false;
|
||||
try
|
||||
{
|
||||
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||
{
|
||||
request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
|
||||
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (status_ == 500)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, 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 info about a particular device's sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Information about a sensor</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task<Sensor> GetsensorAsync(System.Guid deviceID, System.Guid sensorID)
|
||||
{
|
||||
return GetsensorAsync(deviceID, sensorID, 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 info about a particular device's sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Information about a sensor</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task<Sensor> GetsensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
if (deviceID == null)
|
||||
throw new System.ArgumentNullException("deviceID");
|
||||
|
||||
if (sensorID == null)
|
||||
throw new System.ArgumentNullException("sensorID");
|
||||
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/{sensorID}");
|
||||
urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
urlBuilder_.Replace("{sensorID}", System.Uri.EscapeDataString(ConvertToString(sensorID, 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<Sensor>(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)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Device or sensor not found", status_, responseText_, headers_, 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>Shut down sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID)
|
||||
{
|
||||
return OfflinesensorAsync(deviceID, sensorID, 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>Shut down sensor</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task OfflinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
if (deviceID == null)
|
||||
throw new System.ArgumentNullException("deviceID");
|
||||
|
||||
if (sensorID == null)
|
||||
throw new System.ArgumentNullException("sensorID");
|
||||
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/{sensorID}/offline");
|
||||
urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
urlBuilder_.Replace("{sensorID}", System.Uri.EscapeDataString(ConvertToString(sensorID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
|
||||
var client_ = _httpClient;
|
||||
var disposeClient_ = false;
|
||||
try
|
||||
{
|
||||
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||
{
|
||||
request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
|
||||
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (status_ == 500)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, 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>Bring sensor online</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID)
|
||||
{
|
||||
return OnlinesensorAsync(deviceID, sensorID, 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>Bring sensor online</summary>
|
||||
/// <param name="deviceID">ID of device to query</param>
|
||||
/// <param name="sensorID">ID of sensor to query</param>
|
||||
/// <returns>Message sent</returns>
|
||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||
public async System.Threading.Tasks.Task OnlinesensorAsync(System.Guid deviceID, System.Guid sensorID, System.Threading.CancellationToken cancellationToken)
|
||||
{
|
||||
if (deviceID == null)
|
||||
throw new System.ArgumentNullException("deviceID");
|
||||
|
||||
if (sensorID == null)
|
||||
throw new System.ArgumentNullException("sensorID");
|
||||
|
||||
var urlBuilder_ = new System.Text.StringBuilder();
|
||||
urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/devices/{deviceID}/{sensorID}/online");
|
||||
urlBuilder_.Replace("{deviceID}", System.Uri.EscapeDataString(ConvertToString(deviceID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
urlBuilder_.Replace("{sensorID}", System.Uri.EscapeDataString(ConvertToString(sensorID, System.Globalization.CultureInfo.InvariantCulture)));
|
||||
|
||||
var client_ = _httpClient;
|
||||
var disposeClient_ = false;
|
||||
try
|
||||
{
|
||||
using (var request_ = new System.Net.Http.HttpRequestMessage())
|
||||
{
|
||||
request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json");
|
||||
request_.Method = new System.Net.Http.HttpMethod("POST");
|
||||
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (status_ == 500)
|
||||
{
|
||||
string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
throw new ApiException("Message sending unsuccessful", status_, responseText_, headers_, 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
|
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
|
@ -13,6 +13,17 @@ namespace Birdmap.BLL
|
||||
services.AddTransient<IUserService, UserService>();
|
||||
services.AddTransient<IServiceService, ServiceService>();
|
||||
|
||||
if (configuration.GetValue<bool>("UseDummyServices"))
|
||||
{
|
||||
services.AddTransient<IInputService, DummyDeviceAndInputService>();
|
||||
services.AddTransient<IDeviceService, DummyDeviceAndInputService>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddTransient<IInputService, LiveInputService>();
|
||||
services.AddTransient<IDeviceService, LiveDummyService>();
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,17 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.9">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</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>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Birdmap.DAL.Entities
|
||||
{
|
||||
public class Service
|
||||
public record Service
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
@ -6,7 +6,7 @@
|
||||
Admin,
|
||||
}
|
||||
|
||||
public class User
|
||||
public record User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
@ -9,7 +9,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Birdmap.BLL", "Birdmap.BLL\
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Birdmap.DAL", "Birdmap.DAL\Birdmap.DAL.csproj", "{543FAB06-B960-41A9-8865-1624A2ED2170}"
|
||||
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
|
||||
Global
|
||||
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}.Release|Any CPU.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
272
cnc.yml
Normal file
272
cnc.yml
Normal file
@ -0,0 +1,272 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Command and Control Service
|
||||
description: This service s responsible for controlling and handling information
|
||||
about IoT devices in 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.0.0
|
||||
servers:
|
||||
- url: https://birb.k8s.kmlabz.com
|
||||
tags:
|
||||
- name: cnc
|
||||
description: Command and Control Service interaction
|
||||
paths:
|
||||
/devices:
|
||||
get:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Get all device info
|
||||
operationId: getall
|
||||
responses:
|
||||
200:
|
||||
description: Array of devices
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ListOfDevices'
|
||||
404:
|
||||
description: No device found
|
||||
content: {}
|
||||
/devices/offline:
|
||||
post:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Shut down all devices
|
||||
operationId: offlineall
|
||||
responses:
|
||||
200:
|
||||
description: Message sent
|
||||
content: {}
|
||||
500:
|
||||
description: Message sending unsuccessful
|
||||
content: {}
|
||||
/devices/online:
|
||||
post:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Bring all devices online
|
||||
operationId: onlineall
|
||||
responses:
|
||||
200:
|
||||
description: Message sent
|
||||
content: {}
|
||||
500:
|
||||
description: Message sending unsuccessful
|
||||
content: {}
|
||||
/devices/{deviceID}:
|
||||
get:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Get all device info
|
||||
operationId: getdevice
|
||||
parameters:
|
||||
- name: deviceID
|
||||
in: path
|
||||
description: ID of device to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Information about a particular device
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Device'
|
||||
404:
|
||||
description: Device not found
|
||||
content: {}
|
||||
/devices/{deviceID}/offline:
|
||||
post:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Shut down device
|
||||
operationId: offlinedevice
|
||||
parameters:
|
||||
- name: deviceID
|
||||
in: path
|
||||
description: ID of device to shut down
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Message sent
|
||||
content: {}
|
||||
500:
|
||||
description: Message sending unsuccessful
|
||||
content: {}
|
||||
/devices/{deviceID}/online:
|
||||
post:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Bring device online
|
||||
operationId: onlinedevice
|
||||
parameters:
|
||||
- name: deviceID
|
||||
in: path
|
||||
description: ID of device to bring online
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Message sent
|
||||
content: {}
|
||||
500:
|
||||
description: Message sending unsuccessful
|
||||
content: {}
|
||||
/devices/{deviceID}/{sensorID}:
|
||||
get:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Get info about a particular device's sensor
|
||||
operationId: getsensor
|
||||
parameters:
|
||||
- name: deviceID
|
||||
in: path
|
||||
description: ID of device to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: sensorID
|
||||
in: path
|
||||
description: ID of sensor to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Information about a sensor
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Sensor'
|
||||
404:
|
||||
description: Device or sensor not found
|
||||
content: {}
|
||||
/devices/{deviceID}/{sensorID}/offline:
|
||||
post:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Shut down sensor
|
||||
operationId: offlinesensor
|
||||
parameters:
|
||||
- name: deviceID
|
||||
in: path
|
||||
description: ID of device to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: sensorID
|
||||
in: path
|
||||
description: ID of sensor to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Message sent
|
||||
content: {}
|
||||
500:
|
||||
description: Message sending unsuccessful
|
||||
content: {}
|
||||
/devices/{deviceID}/{sensorID}/online:
|
||||
post:
|
||||
tags:
|
||||
- cnc
|
||||
summary: Bring sensor online
|
||||
operationId: onlinesensor
|
||||
parameters:
|
||||
- name: deviceID
|
||||
in: path
|
||||
description: ID of device to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- name: sensorID
|
||||
in: path
|
||||
description: ID of sensor to query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Message sent
|
||||
content: {}
|
||||
500:
|
||||
description: Message sending unsuccessful
|
||||
content: {}
|
||||
components:
|
||||
schemas:
|
||||
ListOfDevices:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Device'
|
||||
Device:
|
||||
required:
|
||||
- id
|
||||
- sensors
|
||||
- status
|
||||
- url
|
||||
- coordinates
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
status:
|
||||
type: string
|
||||
enum:
|
||||
- online
|
||||
- error
|
||||
- offline
|
||||
url:
|
||||
type: string
|
||||
format: url
|
||||
coordinates:
|
||||
required:
|
||||
- latitude
|
||||
- longitude
|
||||
type: object
|
||||
properties:
|
||||
latitude:
|
||||
type: number
|
||||
format: double
|
||||
longitude:
|
||||
type: number
|
||||
format: double
|
||||
sensors:
|
||||
$ref: '#/components/schemas/ArrayofSensors'
|
||||
ArrayofSensors:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Sensor'
|
||||
Sensor:
|
||||
required:
|
||||
- id
|
||||
- status
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
status:
|
||||
type: string
|
||||
enum:
|
||||
- online
|
||||
- unknown
|
||||
- offline
|
BIN
docs/Dashboard.jpg
Normal file
BIN
docs/Dashboard.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
BIN
docs/Login.jpg
Normal file
BIN
docs/Login.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
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